+76
@@ -0,0 +1,76 @@
|
||||
import {Adder} from "d3-array";
|
||||
import {atan2, cos, quarterPi, radians, sin, tau} from "./math.js";
|
||||
import noop from "./noop.js";
|
||||
import stream from "./stream.js";
|
||||
|
||||
export var areaRingSum = new Adder();
|
||||
|
||||
// hello?
|
||||
|
||||
var areaSum = new Adder(),
|
||||
lambda00,
|
||||
phi00,
|
||||
lambda0,
|
||||
cosPhi0,
|
||||
sinPhi0;
|
||||
|
||||
export var areaStream = {
|
||||
point: noop,
|
||||
lineStart: noop,
|
||||
lineEnd: noop,
|
||||
polygonStart: function() {
|
||||
areaRingSum = new Adder();
|
||||
areaStream.lineStart = areaRingStart;
|
||||
areaStream.lineEnd = areaRingEnd;
|
||||
},
|
||||
polygonEnd: function() {
|
||||
var areaRing = +areaRingSum;
|
||||
areaSum.add(areaRing < 0 ? tau + areaRing : areaRing);
|
||||
this.lineStart = this.lineEnd = this.point = noop;
|
||||
},
|
||||
sphere: function() {
|
||||
areaSum.add(tau);
|
||||
}
|
||||
};
|
||||
|
||||
function areaRingStart() {
|
||||
areaStream.point = areaPointFirst;
|
||||
}
|
||||
|
||||
function areaRingEnd() {
|
||||
areaPoint(lambda00, phi00);
|
||||
}
|
||||
|
||||
function areaPointFirst(lambda, phi) {
|
||||
areaStream.point = areaPoint;
|
||||
lambda00 = lambda, phi00 = phi;
|
||||
lambda *= radians, phi *= radians;
|
||||
lambda0 = lambda, cosPhi0 = cos(phi = phi / 2 + quarterPi), sinPhi0 = sin(phi);
|
||||
}
|
||||
|
||||
function areaPoint(lambda, phi) {
|
||||
lambda *= radians, phi *= radians;
|
||||
phi = phi / 2 + quarterPi; // half the angular distance from south pole
|
||||
|
||||
// Spherical excess E for a spherical triangle with vertices: south pole,
|
||||
// previous point, current point. Uses a formula derived from Cagnoli’s
|
||||
// theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
|
||||
var dLambda = lambda - lambda0,
|
||||
sdLambda = dLambda >= 0 ? 1 : -1,
|
||||
adLambda = sdLambda * dLambda,
|
||||
cosPhi = cos(phi),
|
||||
sinPhi = sin(phi),
|
||||
k = sinPhi0 * sinPhi,
|
||||
u = cosPhi0 * cosPhi + k * cos(adLambda),
|
||||
v = k * sdLambda * sin(adLambda);
|
||||
areaRingSum.add(atan2(v, u));
|
||||
|
||||
// Advance the previous points.
|
||||
lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi;
|
||||
}
|
||||
|
||||
export default function(object) {
|
||||
areaSum = new Adder();
|
||||
stream(object, areaStream);
|
||||
return areaSum * 2;
|
||||
}
|
||||
Reference in New Issue
Block a user