UNPKG

@visx/vendor

Version:

vendored packages for visx

169 lines (164 loc) 5.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = _default; var _index = require("../../../vendor-cjs/d3-array/src/index.js"); var _area = require("./area.js"); var _cartesian = require("./cartesian.js"); var _math = require("./math.js"); var _stream = _interopRequireDefault(require("./stream.js")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var lambda0, phi0, lambda1, phi1, // bounds lambda2, // previous lambda-coordinate lambda00, phi00, // first point p0, // previous 3D point deltaSum, ranges, range; var boundsStream = { point: boundsPoint, lineStart: boundsLineStart, lineEnd: boundsLineEnd, polygonStart: function () { boundsStream.point = boundsRingPoint; boundsStream.lineStart = boundsRingStart; boundsStream.lineEnd = boundsRingEnd; deltaSum = new _index.Adder(); _area.areaStream.polygonStart(); }, polygonEnd: function () { _area.areaStream.polygonEnd(); boundsStream.point = boundsPoint; boundsStream.lineStart = boundsLineStart; boundsStream.lineEnd = boundsLineEnd; if (_area.areaRingSum < 0) lambda0 = -(lambda1 = 180), phi0 = -(phi1 = 90);else if (deltaSum > _math.epsilon) phi1 = 90;else if (deltaSum < -_math.epsilon) phi0 = -90; range[0] = lambda0, range[1] = lambda1; }, sphere: function () { lambda0 = -(lambda1 = 180), phi0 = -(phi1 = 90); } }; function boundsPoint(lambda, phi) { ranges.push(range = [lambda0 = lambda, lambda1 = lambda]); if (phi < phi0) phi0 = phi; if (phi > phi1) phi1 = phi; } function linePoint(lambda, phi) { var p = (0, _cartesian.cartesian)([lambda * _math.radians, phi * _math.radians]); if (p0) { var normal = (0, _cartesian.cartesianCross)(p0, p), equatorial = [normal[1], -normal[0], 0], inflection = (0, _cartesian.cartesianCross)(equatorial, normal); (0, _cartesian.cartesianNormalizeInPlace)(inflection); inflection = (0, _cartesian.spherical)(inflection); var delta = lambda - lambda2, sign = delta > 0 ? 1 : -1, lambdai = inflection[0] * _math.degrees * sign, phii, antimeridian = (0, _math.abs)(delta) > 180; if (antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) { phii = inflection[1] * _math.degrees; if (phii > phi1) phi1 = phii; } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign * lambda2 < lambdai && lambdai < sign * lambda)) { phii = -inflection[1] * _math.degrees; if (phii < phi0) phi0 = phii; } else { if (phi < phi0) phi0 = phi; if (phi > phi1) phi1 = phi; } if (antimeridian) { if (lambda < lambda2) { if (angle(lambda0, lambda) > angle(lambda0, lambda1)) lambda1 = lambda; } else { if (angle(lambda, lambda1) > angle(lambda0, lambda1)) lambda0 = lambda; } } else { if (lambda1 >= lambda0) { if (lambda < lambda0) lambda0 = lambda; if (lambda > lambda1) lambda1 = lambda; } else { if (lambda > lambda2) { if (angle(lambda0, lambda) > angle(lambda0, lambda1)) lambda1 = lambda; } else { if (angle(lambda, lambda1) > angle(lambda0, lambda1)) lambda0 = lambda; } } } } else { ranges.push(range = [lambda0 = lambda, lambda1 = lambda]); } if (phi < phi0) phi0 = phi; if (phi > phi1) phi1 = phi; p0 = p, lambda2 = lambda; } function boundsLineStart() { boundsStream.point = linePoint; } function boundsLineEnd() { range[0] = lambda0, range[1] = lambda1; boundsStream.point = boundsPoint; p0 = null; } function boundsRingPoint(lambda, phi) { if (p0) { var delta = lambda - lambda2; deltaSum.add((0, _math.abs)(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta); } else { lambda00 = lambda, phi00 = phi; } _area.areaStream.point(lambda, phi); linePoint(lambda, phi); } function boundsRingStart() { _area.areaStream.lineStart(); } function boundsRingEnd() { boundsRingPoint(lambda00, phi00); _area.areaStream.lineEnd(); if ((0, _math.abs)(deltaSum) > _math.epsilon) lambda0 = -(lambda1 = 180); range[0] = lambda0, range[1] = lambda1; p0 = null; } // Finds the left-right distance between two longitudes. // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want // the distance between ±180° to be 360°. function angle(lambda0, lambda1) { return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1; } function rangeCompare(a, b) { return a[0] - b[0]; } function rangeContains(range, x) { return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x; } function _default(feature) { var i, n, a, b, merged, deltaMax, delta; phi1 = lambda1 = -(lambda0 = phi0 = Infinity); ranges = []; (0, _stream.default)(feature, boundsStream); // First, sort ranges by their minimum longitudes. if (n = ranges.length) { ranges.sort(rangeCompare); // Then, merge any ranges that overlap. for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) { b = ranges[i]; if (rangeContains(a, b[0]) || rangeContains(a, b[1])) { if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1]; if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0]; } else { merged.push(a = b); } } // Finally, find the largest gap between the merged ranges. // The final bounding box will be the inverse of this gap. for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) { b = merged[i]; if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0 = b[0], lambda1 = a[1]; } } ranges = range = null; return lambda0 === Infinity || phi0 === Infinity ? [[NaN, NaN], [NaN, NaN]] : [[lambda0, phi0], [lambda1, phi1]]; }