Skip to content

Commit abb5048

Browse files
committed
@turf/boolean-contains: Add MultiPolygon support for non-polygon types
1 parent 1fed227 commit abb5048

23 files changed

Lines changed: 1100 additions & 1 deletion

packages/turf-boolean-contains/index.ts

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
Feature,
44
Geometry,
55
LineString,
6+
MultiLineString,
67
MultiPoint,
78
MultiPolygon,
89
Point,
@@ -87,8 +88,18 @@ function booleanContains(
8788
}
8889
case "MultiPolygon":
8990
switch (type2) {
91+
case "Point":
92+
return isPointInMultiPolygon(geom1, geom2);
93+
case "MultiPoint":
94+
return isMultiPointInMultiPolygon(geom1, geom2);
95+
case "LineString":
96+
return isLineInMultiPolygon(geom1, geom2);
97+
case "MultiLineString":
98+
return isMultiLineStringInMultiPolygon(geom1, geom2);
9099
case "Polygon":
91100
return isPolygonInMultiPolygon(geom1, geom2);
101+
case "MultiPolygon":
102+
return isMultiPolygonInMultiPolygon(geom1, geom2);
92103
default:
93104
throw new Error("feature2 " + type2 + " geometry not supported");
94105
}
@@ -103,6 +114,122 @@ function isPolygonInMultiPolygon(multiPolygon: MultiPolygon, polygon: Polygon) {
103114
);
104115
}
105116

117+
/**
118+
* Is Point inside MultiPolygon
119+
*
120+
* @private
121+
* @param {MultiPolygon} multiPolygon MultiPolygon geometry
122+
* @param {Point} point Point geometry
123+
* @returns {boolean} true if point is inside the interior of any polygon in the MultiPolygon
124+
*/
125+
function isPointInMultiPolygon(multiPolygon: MultiPolygon, point: Point) {
126+
return multiPolygon.coordinates.some((coords) =>
127+
booleanPointInPolygon(
128+
point,
129+
{ type: "Polygon", coordinates: coords },
130+
{
131+
ignoreBoundary: true,
132+
}
133+
)
134+
);
135+
}
136+
137+
/**
138+
* Is MultiPoint inside MultiPolygon
139+
*
140+
* @private
141+
* @param {MultiPolygon} multiPolygon MultiPolygon geometry
142+
* @param {MultiPoint} multiPoint MultiPoint geometry
143+
* @returns {boolean} true if every point is inside the interior of some polygon in the MultiPolygon
144+
*/
145+
function isMultiPointInMultiPolygon(
146+
multiPolygon: MultiPolygon,
147+
multiPoint: MultiPoint
148+
) {
149+
for (const coord of multiPoint.coordinates) {
150+
const pointInside = multiPolygon.coordinates.some((polyCoords) =>
151+
booleanPointInPolygon(
152+
coord,
153+
{ type: "Polygon", coordinates: polyCoords },
154+
{ ignoreBoundary: true }
155+
)
156+
);
157+
if (!pointInside) {
158+
return false;
159+
}
160+
}
161+
return true;
162+
}
163+
164+
/**
165+
* Is LineString inside MultiPolygon
166+
*
167+
* @private
168+
* @param {MultiPolygon} multiPolygon MultiPolygon geometry
169+
* @param {LineString} lineString LineString geometry
170+
* @returns {boolean} true if the LineString is fully contained within a single polygon of the MultiPolygon
171+
*/
172+
function isLineInMultiPolygon(
173+
multiPolygon: MultiPolygon,
174+
lineString: LineString
175+
) {
176+
return multiPolygon.coordinates.some((coords) =>
177+
isLineInPoly({ type: "Polygon", coordinates: coords }, lineString)
178+
);
179+
}
180+
181+
/**
182+
* Is MultiLineString inside MultiPolygon
183+
*
184+
* @private
185+
* @param {MultiPolygon} multiPolygon MultiPolygon geometry
186+
* @param {MultiLineString} multiLineString MultiLineString geometry
187+
* @returns {boolean} true if every LineString is fully contained within some single polygon of the MultiPolygon
188+
*/
189+
function isMultiLineStringInMultiPolygon(
190+
multiPolygon: MultiPolygon,
191+
multiLineString: MultiLineString
192+
) {
193+
for (const lineCoords of multiLineString.coordinates) {
194+
const lineInside = multiPolygon.coordinates.some((polyCoords) =>
195+
isLineInPoly(
196+
{ type: "Polygon", coordinates: polyCoords },
197+
{ type: "LineString", coordinates: lineCoords }
198+
)
199+
);
200+
if (!lineInside) {
201+
return false;
202+
}
203+
}
204+
return true;
205+
}
206+
207+
/**
208+
* Is MultiPolygon inside MultiPolygon
209+
*
210+
* @private
211+
* @param {MultiPolygon} multiPolygon1 MultiPolygon geometry (container)
212+
* @param {MultiPolygon} multiPolygon2 MultiPolygon geometry (contained)
213+
* @returns {boolean} true if every polygon of multiPolygon2 is fully contained within some single polygon of multiPolygon1
214+
*/
215+
function isMultiPolygonInMultiPolygon(
216+
multiPolygon1: MultiPolygon,
217+
multiPolygon2: MultiPolygon
218+
) {
219+
for (const poly2Coords of multiPolygon2.coordinates) {
220+
const polyInside = multiPolygon1.coordinates.some((poly1Coords) =>
221+
isPolyInPoly(
222+
{ type: "Polygon", coordinates: poly1Coords },
223+
{ type: "Polygon", coordinates: poly2Coords }
224+
)
225+
);
226+
if (!polyInside) {
227+
return false;
228+
}
229+
}
230+
return true;
231+
}
232+
106233
function isMultiPolyInPoly(polygon: Polygon, multiPolygon: MultiPolygon) {
107234
return multiPolygon.coordinates.every((coords) =>
108235
isPolyInPoly(polygon, { type: "Polygon", coordinates: coords })

packages/turf-boolean-contains/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"contributors": [
77
"Rowan Winsemius <@rowanwins>",
88
"Denis Carriere <@DenisCarriere>",
9-
"Samuel Arbibe <@samuelarbibe>"
9+
"Samuel Arbibe <@samuelarbibe>",
10+
"Espen Hovlandsdal <@rexxars>"
1011
],
1112
"license": "MIT",
1213
"bugs": {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"type": "FeatureCollection",
3+
"features": [
4+
{
5+
"type": "Feature",
6+
"properties": {},
7+
"geometry": {
8+
"type": "MultiPolygon",
9+
"coordinates": [
10+
[
11+
[
12+
[0, 0],
13+
[10, 0],
14+
[10, 10],
15+
[0, 10],
16+
[0, 0]
17+
]
18+
],
19+
[
20+
[
21+
[20, 0],
22+
[30, 0],
23+
[30, 10],
24+
[20, 10],
25+
[20, 0]
26+
]
27+
]
28+
]
29+
}
30+
},
31+
{
32+
"type": "Feature",
33+
"properties": {},
34+
"geometry": {
35+
"type": "LineString",
36+
"coordinates": [
37+
[0, 2],
38+
[0, 8]
39+
]
40+
}
41+
}
42+
]
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"type": "FeatureCollection",
3+
"features": [
4+
{
5+
"type": "Feature",
6+
"properties": {},
7+
"geometry": {
8+
"type": "MultiPolygon",
9+
"coordinates": [
10+
[
11+
[
12+
[0, 0],
13+
[10, 0],
14+
[10, 10],
15+
[0, 10],
16+
[0, 0]
17+
]
18+
],
19+
[
20+
[
21+
[20, 0],
22+
[30, 0],
23+
[30, 10],
24+
[20, 10],
25+
[20, 0]
26+
]
27+
]
28+
]
29+
}
30+
},
31+
{
32+
"type": "Feature",
33+
"properties": {},
34+
"geometry": {
35+
"type": "LineString",
36+
"coordinates": [
37+
[12, 5],
38+
[18, 5]
39+
]
40+
}
41+
}
42+
]
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
{
2+
"type": "FeatureCollection",
3+
"features": [
4+
{
5+
"type": "Feature",
6+
"properties": {},
7+
"geometry": {
8+
"type": "MultiPolygon",
9+
"coordinates": [
10+
[
11+
[
12+
[0, 0],
13+
[10, 0],
14+
[10, 10],
15+
[0, 10],
16+
[0, 0]
17+
]
18+
],
19+
[
20+
[
21+
[20, 0],
22+
[30, 0],
23+
[30, 10],
24+
[20, 10],
25+
[20, 0]
26+
]
27+
]
28+
]
29+
}
30+
},
31+
{
32+
"type": "Feature",
33+
"properties": {},
34+
"geometry": {
35+
"type": "LineString",
36+
"coordinates": [
37+
[5, 5],
38+
[25, 5]
39+
]
40+
}
41+
}
42+
]
43+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"type": "FeatureCollection",
3+
"features": [
4+
{
5+
"type": "Feature",
6+
"properties": {},
7+
"geometry": {
8+
"type": "MultiPolygon",
9+
"coordinates": [
10+
[
11+
[
12+
[0, 0],
13+
[10, 0],
14+
[10, 10],
15+
[0, 10],
16+
[0, 0]
17+
]
18+
],
19+
[
20+
[
21+
[20, 0],
22+
[30, 0],
23+
[30, 10],
24+
[20, 10],
25+
[20, 0]
26+
]
27+
]
28+
]
29+
}
30+
},
31+
{
32+
"type": "Feature",
33+
"properties": {},
34+
"geometry": {
35+
"type": "MultiLineString",
36+
"coordinates": [
37+
[
38+
[2, 2],
39+
[8, 8]
40+
],
41+
[
42+
[12, 2],
43+
[18, 8]
44+
]
45+
]
46+
}
47+
}
48+
]
49+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"type": "FeatureCollection",
3+
"features": [
4+
{
5+
"type": "Feature",
6+
"properties": {},
7+
"geometry": {
8+
"type": "MultiPolygon",
9+
"coordinates": [
10+
[
11+
[
12+
[0, 0],
13+
[10, 0],
14+
[10, 10],
15+
[0, 10],
16+
[0, 0]
17+
]
18+
],
19+
[
20+
[
21+
[20, 0],
22+
[30, 0],
23+
[30, 10],
24+
[20, 10],
25+
[20, 0]
26+
]
27+
]
28+
]
29+
}
30+
},
31+
{
32+
"type": "Feature",
33+
"properties": {},
34+
"geometry": {
35+
"type": "MultiLineString",
36+
"coordinates": [
37+
[
38+
[2, 2],
39+
[8, 8]
40+
],
41+
[
42+
[5, 5],
43+
[25, 5]
44+
]
45+
]
46+
}
47+
}
48+
]
49+
}

0 commit comments

Comments
 (0)