d2-ui
Version:
150 lines (133 loc) • 4.69 kB
JavaScript
import "../core/noop";
import "../math/trigonometry";
import "geo";
import "stream";
d3.geo.centroid = function(object) {
d3_geo_centroidW0 = d3_geo_centroidW1 =
d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 =
d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 =
d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
d3.geo.stream(object, d3_geo_centroid);
var x = d3_geo_centroidX2,
y = d3_geo_centroidY2,
z = d3_geo_centroidZ2,
m = x * x + y * y + z * z;
// If the area-weighted centroid is undefined, fall back to length-weighted centroid.
if (m < ε2) {
x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
// If the feature has zero length, fall back to arithmetic mean of point vectors.
if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
m = x * x + y * y + z * z;
// If the feature still has an undefined centroid, then return.
if (m < ε2) return [NaN, NaN];
}
return [Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees];
};
var d3_geo_centroidW0,
d3_geo_centroidW1,
d3_geo_centroidX0,
d3_geo_centroidY0,
d3_geo_centroidZ0,
d3_geo_centroidX1,
d3_geo_centroidY1,
d3_geo_centroidZ1,
d3_geo_centroidX2,
d3_geo_centroidY2,
d3_geo_centroidZ2;
var d3_geo_centroid = {
sphere: d3_noop,
point: d3_geo_centroidPoint,
lineStart: d3_geo_centroidLineStart,
lineEnd: d3_geo_centroidLineEnd,
polygonStart: function() {
d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
},
polygonEnd: function() {
d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
}
};
// Arithmetic mean of Cartesian vectors.
function d3_geo_centroidPoint(λ, φ) {
λ *= d3_radians;
var cosφ = Math.cos(φ *= d3_radians);
d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
}
function d3_geo_centroidPointXYZ(x, y, z) {
++d3_geo_centroidW0;
d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
}
function d3_geo_centroidLineStart() {
var x0, y0, z0; // previous point
d3_geo_centroid.point = function(λ, φ) {
λ *= d3_radians;
var cosφ = Math.cos(φ *= d3_radians);
x0 = cosφ * Math.cos(λ);
y0 = cosφ * Math.sin(λ);
z0 = Math.sin(φ);
d3_geo_centroid.point = nextPoint;
d3_geo_centroidPointXYZ(x0, y0, z0);
};
function nextPoint(λ, φ) {
λ *= d3_radians;
var cosφ = Math.cos(φ *= d3_radians),
x = cosφ * Math.cos(λ),
y = cosφ * Math.sin(λ),
z = Math.sin(φ),
w = Math.atan2(
Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w),
x0 * x + y0 * y + z0 * z);
d3_geo_centroidW1 += w;
d3_geo_centroidX1 += w * (x0 + (x0 = x));
d3_geo_centroidY1 += w * (y0 + (y0 = y));
d3_geo_centroidZ1 += w * (z0 + (z0 = z));
d3_geo_centroidPointXYZ(x0, y0, z0);
}
}
function d3_geo_centroidLineEnd() {
d3_geo_centroid.point = d3_geo_centroidPoint;
}
// See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
// J. Applied Mechanics 42, 239 (1975).
function d3_geo_centroidRingStart() {
var λ00, φ00, // first point
x0, y0, z0; // previous point
d3_geo_centroid.point = function(λ, φ) {
λ00 = λ, φ00 = φ;
d3_geo_centroid.point = nextPoint;
λ *= d3_radians;
var cosφ = Math.cos(φ *= d3_radians);
x0 = cosφ * Math.cos(λ);
y0 = cosφ * Math.sin(λ);
z0 = Math.sin(φ);
d3_geo_centroidPointXYZ(x0, y0, z0);
};
d3_geo_centroid.lineEnd = function() {
nextPoint(λ00, φ00);
d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
d3_geo_centroid.point = d3_geo_centroidPoint;
};
function nextPoint(λ, φ) {
λ *= d3_radians;
var cosφ = Math.cos(φ *= d3_radians),
x = cosφ * Math.cos(λ),
y = cosφ * Math.sin(λ),
z = Math.sin(φ),
cx = y0 * z - z0 * y,
cy = z0 * x - x0 * z,
cz = x0 * y - y0 * x,
m = Math.sqrt(cx * cx + cy * cy + cz * cz),
u = x0 * x + y0 * y + z0 * z,
v = m && -d3_acos(u) / m, // area weight
w = Math.atan2(m, u); // line weight
d3_geo_centroidX2 += v * cx;
d3_geo_centroidY2 += v * cy;
d3_geo_centroidZ2 += v * cz;
d3_geo_centroidW1 += w;
d3_geo_centroidX1 += w * (x0 + (x0 = x));
d3_geo_centroidY1 += w * (y0 + (y0 = y));
d3_geo_centroidZ1 += w * (z0 + (z0 = z));
d3_geo_centroidPointXYZ(x0, y0, z0);
}
}