source: node_modules/d3-geo/src/polygonContains.js@ e4c61dd

Last change on this file since e4c61dd was e4c61dd, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Prototype 1.1

  • Property mode set to 100644
File size: 2.7 KB
Line 
1import {Adder} from "d3-array";
2import {cartesian, cartesianCross, cartesianNormalizeInPlace} from "./cartesian.js";
3import {abs, asin, atan2, cos, epsilon, epsilon2, halfPi, pi, quarterPi, sign, sin, tau} from "./math.js";
4
5function longitude(point) {
6 return abs(point[0]) <= pi ? point[0] : sign(point[0]) * ((abs(point[0]) + pi) % tau - pi);
7}
8
9export default function(polygon, point) {
10 var lambda = longitude(point),
11 phi = point[1],
12 sinPhi = sin(phi),
13 normal = [sin(lambda), -cos(lambda), 0],
14 angle = 0,
15 winding = 0;
16
17 var sum = new Adder();
18
19 if (sinPhi === 1) phi = halfPi + epsilon;
20 else if (sinPhi === -1) phi = -halfPi - epsilon;
21
22 for (var i = 0, n = polygon.length; i < n; ++i) {
23 if (!(m = (ring = polygon[i]).length)) continue;
24 var ring,
25 m,
26 point0 = ring[m - 1],
27 lambda0 = longitude(point0),
28 phi0 = point0[1] / 2 + quarterPi,
29 sinPhi0 = sin(phi0),
30 cosPhi0 = cos(phi0);
31
32 for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
33 var point1 = ring[j],
34 lambda1 = longitude(point1),
35 phi1 = point1[1] / 2 + quarterPi,
36 sinPhi1 = sin(phi1),
37 cosPhi1 = cos(phi1),
38 delta = lambda1 - lambda0,
39 sign = delta >= 0 ? 1 : -1,
40 absDelta = sign * delta,
41 antimeridian = absDelta > pi,
42 k = sinPhi0 * sinPhi1;
43
44 sum.add(atan2(k * sign * sin(absDelta), cosPhi0 * cosPhi1 + k * cos(absDelta)));
45 angle += antimeridian ? delta + sign * tau : delta;
46
47 // Are the longitudes either side of the point’s meridian (lambda),
48 // and are the latitudes smaller than the parallel (phi)?
49 if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
50 var arc = cartesianCross(cartesian(point0), cartesian(point1));
51 cartesianNormalizeInPlace(arc);
52 var intersection = cartesianCross(normal, arc);
53 cartesianNormalizeInPlace(intersection);
54 var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);
55 if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
56 winding += antimeridian ^ delta >= 0 ? 1 : -1;
57 }
58 }
59 }
60 }
61
62 // First, determine whether the South pole is inside or outside:
63 //
64 // It is inside if:
65 // * the polygon winds around it in a clockwise direction.
66 // * the polygon does not (cumulatively) wind around it, but has a negative
67 // (counter-clockwise) area.
68 //
69 // Second, count the (signed) number of times a segment crosses a lambda
70 // from the point to the South pole. If it is zero, then the point is the
71 // same side as the South pole.
72
73 return (angle < -epsilon || angle < epsilon && sum < -epsilon2) ^ (winding & 1);
74}
Note: See TracBrowser for help on using the repository browser.