@visx/vendor
Version:
vendored packages for visx
72 lines (68 loc) • 3.11 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
var _index = require("../../../vendor-cjs/d3-array/src/index.js");
var _cartesian = require("./cartesian.js");
var _math = require("./math.js");
function longitude(point) {
return (0, _math.abs)(point[0]) <= _math.pi ? point[0] : (0, _math.sign)(point[0]) * (((0, _math.abs)(point[0]) + _math.pi) % _math.tau - _math.pi);
}
function _default(polygon, point) {
var lambda = longitude(point),
phi = point[1],
sinPhi = (0, _math.sin)(phi),
normal = [(0, _math.sin)(lambda), -(0, _math.cos)(lambda), 0],
angle = 0,
winding = 0;
var sum = new _index.Adder();
if (sinPhi === 1) phi = _math.halfPi + _math.epsilon;else if (sinPhi === -1) phi = -_math.halfPi - _math.epsilon;
for (var i = 0, n = polygon.length; i < n; ++i) {
if (!(m = (ring = polygon[i]).length)) continue;
var ring,
m,
point0 = ring[m - 1],
lambda0 = longitude(point0),
phi0 = point0[1] / 2 + _math.quarterPi,
sinPhi0 = (0, _math.sin)(phi0),
cosPhi0 = (0, _math.cos)(phi0);
for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
var point1 = ring[j],
lambda1 = longitude(point1),
phi1 = point1[1] / 2 + _math.quarterPi,
sinPhi1 = (0, _math.sin)(phi1),
cosPhi1 = (0, _math.cos)(phi1),
delta = lambda1 - lambda0,
sign = delta >= 0 ? 1 : -1,
absDelta = sign * delta,
antimeridian = absDelta > _math.pi,
k = sinPhi0 * sinPhi1;
sum.add((0, _math.atan2)(k * sign * (0, _math.sin)(absDelta), cosPhi0 * cosPhi1 + k * (0, _math.cos)(absDelta)));
angle += antimeridian ? delta + sign * _math.tau : delta;
// Are the longitudes either side of the point’s meridian (lambda),
// and are the latitudes smaller than the parallel (phi)?
if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
var arc = (0, _cartesian.cartesianCross)((0, _cartesian.cartesian)(point0), (0, _cartesian.cartesian)(point1));
(0, _cartesian.cartesianNormalizeInPlace)(arc);
var intersection = (0, _cartesian.cartesianCross)(normal, arc);
(0, _cartesian.cartesianNormalizeInPlace)(intersection);
var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * (0, _math.asin)(intersection[2]);
if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
winding += antimeridian ^ delta >= 0 ? 1 : -1;
}
}
}
}
// First, determine whether the South pole is inside or outside:
//
// It is inside if:
// * the polygon winds around it in a clockwise direction.
// * the polygon does not (cumulatively) wind around it, but has a negative
// (counter-clockwise) area.
//
// Second, count the (signed) number of times a segment crosses a lambda
// from the point to the South pole. If it is zero, then the point is the
// same side as the South pole.
return (angle < -_math.epsilon || angle < _math.epsilon && sum < -_math.epsilon2) ^ winding & 1;
}
;