12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- 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;
- }
|