• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Open-S2 / gis-tools / #105

14 Dec 2025 04:48AM UTC coverage: 92.048% (-1.0%) from 93.085%
#105

push

Mr Martian
test fixes for actions

97653 of 106089 relevant lines covered (92.05%)

433911.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.63
/src/geometry/tools/polys/pointInPoly.ts
1
import { orient2d, pointOverlap } from '../../../index.js';
118✔
2

3
import type {
4
  MValue,
5
  Properties,
6
  VectorFeatures,
7
  VectorLineString,
8
  VectorMultiPolygon,
9
  VectorMultiPolygonGeometry,
10
  VectorPoint,
11
  VectorPolygon,
12
  VectorPolygonGeometry,
13
} from '../../../index.js';
14

15
/**
16
 * A robust method to see if a point is in a collection of polygons or not.
17
 * Be sure the point and polygon are in the same projection space.
18
 * @param point - the point to check
19
 * @param polygons - the collection of polygons
20
 * @param ignoreBoundary - if true, ignore when the point is on the boundary
21
 * @returns - true if the point is in the polygon
22
 */
23
export function pointInPolygons<
10✔
24
  M = Record<string, unknown>,
25
  D extends MValue = Properties,
26
  P extends Properties = Properties,
27
>(
2✔
28
  point: VectorPoint,
14✔
29
  polygons:
20✔
30
    | VectorMultiPolygon<D>
31
    | VectorMultiPolygonGeometry<D>
32
    | VectorFeatures<M, D, P, VectorMultiPolygonGeometry<D>>,
33
  ignoreBoundary = false,
48✔
34
): boolean | 0 {
6✔
35
  const vectorPolygons: VectorMultiPolygon =
46✔
36
    'geometry' in polygons
48✔
37
      ? polygons.geometry.coordinates
6✔
38
      : 'coordinates' in polygons
56✔
39
        ? polygons.coordinates
4✔
40
        : polygons;
20✔
41
  let res: boolean | 0 = false;
36✔
42
  for (let i = 0; i < vectorPolygons.length; i++) {
102✔
43
    const test = pointInPolygon(point, vectorPolygons[i], ignoreBoundary);
148✔
44
    if (test === true) return true;
54✔
45
    else if (!ignoreBoundary && test === 0) res = 0;
106✔
46
  }
4✔
47
  return res;
22✔
48
}
49

50
/**
51
 * A robust method to see if a point is in a polygon or not.
52
 * Be sure the point and polygon are in the same projection space.
53
 * @param point - the point to check
54
 * @param polygon - the polygon
55
 * @param ignoreBoundary - if true, ignore when the point is on the boundary
56
 * @returns - true if the point is in the polygon
57
 */
58
export function pointInPolygon<
10✔
59
  M = Record<string, unknown>,
60
  D extends MValue = Properties,
61
  P extends Properties = Properties,
62
>(
2✔
63
  point: VectorPoint,
14✔
64
  polygon:
18✔
65
    | VectorPolygon<D>
66
    | VectorPolygonGeometry<D>
67
    | VectorFeatures<M, D, P, VectorPolygonGeometry<D>>,
68
  ignoreBoundary = false,
48✔
69
): boolean | 0 {
6✔
70
  // bbox test case - if it doesn't even fit within the bbox, we know it's not in the polygon
71
  const bbox =
26✔
72
    'geometry' in polygon ? polygon.geometry.bbox : 'bbox' in polygon ? polygon.bbox : undefined;
118✔
73
  if (bbox !== undefined && !pointOverlap(bbox, point)) return false;
116✔
74
  // check poly against the point
75
  const vectorPolygon: VectorPolygon =
44✔
76
    'geometry' in polygon
46✔
77
      ? polygon.geometry.coordinates
6✔
78
      : 'coordinates' in polygon
54✔
79
        ? polygon.coordinates
42✔
80
        : polygon;
18✔
81

82
  const pip = _pointInPolygon(point, vectorPolygon);
104✔
83
  if (ignoreBoundary && pip === 0) return false;
98✔
84
  return pip;
22✔
85
}
86

87
/**
88
 * Check if a hole is inside an outer ring
89
 * @param hole - the hole to test if inside the outer
90
 * @param outer - the outer to test against
91
 * @returns true if the hole is inside the outer
92
 */
93
export function polylineInPolyline(hole: VectorLineString, outer: VectorLineString): boolean {
44✔
94
  const outerPoly = [outer];
56✔
95
  for (const point of hole) {
60✔
96
    const result = pointInPolygon(point, outerPoly, false);
118✔
97
    if (result === true) return true;
80✔
98
    else if (result === false) return false;
90✔
99
  }
×
100
  // If we make it means all points of the hole were on the boundary therefore its inside the outer
101
  return true;
×
102
}
103

104
/**
105
 * A Robust point in polygon test
106
 * @param point - the point
107
 * @param polygon - the polygon
108
 * @returns - true if the point is in the polygon, 0 if on the boundary, false otherwise
109
 */
110
function _pointInPolygon<M extends MValue = Properties>(
2✔
111
  point: VectorPoint<M>,
14✔
112
  polygon: VectorPolygon<M>,
18✔
113
): boolean | 0 {
6✔
114
  let i;
16✔
115
  let ii;
18✔
116
  let k = 0;
24✔
117
  let f;
16✔
118
  let u1;
18✔
119
  let v1;
18✔
120
  let u2;
18✔
121
  let v2;
18✔
122
  let currentP;
30✔
123
  let nextP;
24✔
124

125
  const { x, y } = point;
50✔
126

127
  const numContours = polygon.length;
74✔
128
  for (i = 0; i < numContours; i++) {
74✔
129
    ii = 0;
22✔
130
    const contour = polygon[i];
62✔
131
    const contourLen = contour.length - 1;
84✔
132

133
    currentP = contour[0];
52✔
134
    if (currentP.x !== contour[contourLen].x && currentP.y !== contour[contourLen].y) {
162✔
135
      // since the first and last coordinates in a ring are not the same, assume it's not a polygon and return false
136
      return false;
×
137
    }
8✔
138

139
    u1 = currentP.x - x;
48✔
140
    v1 = currentP.y - y;
48✔
141

142
    for (ii; ii < contourLen; ii++) {
74✔
143
      nextP = contour[ii + 1];
60✔
144

145
      u2 = nextP.x - x;
46✔
146
      v2 = nextP.y - y;
46✔
147

148
      if (v1 === 0 && v2 === 0) {
68✔
149
        if ((u2 <= 0 && u1 >= 0) || (u1 <= 0 && u2 >= 0)) return 0;
136✔
150
      } else if ((v2 >= 0 && v1 <= 0) || (v2 <= 0 && v1 >= 0)) {
120✔
151
        f = orient2d(u1, u2, v1, v2, 0, 0);
86✔
152
        if (f === 0) return 0;
74✔
153
        if ((f > 0 && v2 > 0 && v1 <= 0) || (f < 0 && v2 <= 0 && v1 > 0)) k++;
158✔
154
      }
14✔
155
      // currentP = nextP;
156
      v1 = v2;
28✔
157
      u1 = u2;
24✔
158
    }
4✔
159
  }
4✔
160

161
  if (k % 2 === 0) return false;
66✔
162
  return true;
22✔
163
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc