import “centroid”;

// TODO Unify this code with d3.geom.polygon centroid? // TODO Enforce positive area for exterior, negative area for interior?

var d3_geo_pathCentroid = {

point: d3_geo_pathCentroidPoint,

// For lines, weight by length.
lineStart: d3_geo_pathCentroidLineStart,
lineEnd: d3_geo_pathCentroidLineEnd,

// For polygons, weight by area.
polygonStart: function() {
  d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
},
polygonEnd: function() {
  d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
  d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
  d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
}

};

function d3_geo_pathCentroidPoint(x, y) {

d3_geo_centroidX0 += x;
d3_geo_centroidY0 += y;
++d3_geo_centroidZ0;

}

function d3_geo_pathCentroidLineStart() {

var x0, y0;

d3_geo_pathCentroid.point = function(x, y) {
  d3_geo_pathCentroid.point = nextPoint;
  d3_geo_pathCentroidPoint(x0 = x, y0 = y);
};

function nextPoint(x, y) {
  var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
  d3_geo_centroidX1 += z * (x0 + x) / 2;
  d3_geo_centroidY1 += z * (y0 + y) / 2;
  d3_geo_centroidZ1 += z;
  d3_geo_pathCentroidPoint(x0 = x, y0 = y);
}

}

function d3_geo_pathCentroidLineEnd() {

d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;

}

function d3_geo_pathCentroidRingStart() {

var x00, y00, x0, y0;

// For the first point, …
d3_geo_pathCentroid.point = function(x, y) {
  d3_geo_pathCentroid.point = nextPoint;
  d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
};

// For subsequent points, …
function nextPoint(x, y) {
  var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
  d3_geo_centroidX1 += z * (x0 + x) / 2;
  d3_geo_centroidY1 += z * (y0 + y) / 2;
  d3_geo_centroidZ1 += z;

  z = y0 * x - x0 * y;
  d3_geo_centroidX2 += z * (x0 + x);
  d3_geo_centroidY2 += z * (y0 + y);
  d3_geo_centroidZ2 += z * 3;
  d3_geo_pathCentroidPoint(x0 = x, y0 = y);
}

// For the last point, return to the start.
d3_geo_pathCentroid.lineEnd = function() {
  nextPoint(x00, y00);
};

}