diff --git a/packages/turf-boolean-valid/index.ts b/packages/turf-boolean-valid/index.ts index b61d79f3f9..4587128db7 100644 --- a/packages/turf-boolean-valid/index.ts +++ b/packages/turf-boolean-valid/index.ts @@ -83,6 +83,31 @@ function booleanValid(feature: Feature | Geometry) { } } return true; + case "GeometryCollection": + if (!geom.geometries) { + return false; + } + + // To avoid situations where Geometry Collections nested within one another + // could lead to a situation where there is an infinite validation loop, + // we enforce the GeoJSON RFC recommendations + // (https://datatracker.ietf.org/doc/html/rfc7946#section-3.1.8) + // which states that we should not have Nested Geometry Collections + return ( + Array.isArray(geom.geometries) && + geom.geometries.length > 0 && + geom.geometries.every( + (geometry: Geometry) => + [ + "Point", + "LineString", + "MultiLineString", + "MultiPoint", + "Polygon", + "MultiPolygon", + ].includes(geometry.type) && booleanValid(geometry) + ) + ); default: return false; } diff --git a/packages/turf-boolean-valid/package.json b/packages/turf-boolean-valid/package.json index f7d4b1612d..4fa9427aca 100644 --- a/packages/turf-boolean-valid/package.json +++ b/packages/turf-boolean-valid/package.json @@ -5,7 +5,8 @@ "author": "Turf Authors", "contributors": [ "Rowan Winsemius <@rowanwins>", - "Denis Carriere <@DenisCarriere>" + "Denis Carriere <@DenisCarriere>", + "Martin Künzi <@ltkum>" ], "license": "MIT", "bugs": { diff --git a/packages/turf-boolean-valid/test/false/GeometryCollection/malformed-geometry-in-collection.geojson b/packages/turf-boolean-valid/test/false/GeometryCollection/malformed-geometry-in-collection.geojson new file mode 100644 index 0000000000..879f4b2eba --- /dev/null +++ b/packages/turf-boolean-valid/test/false/GeometryCollection/malformed-geometry-in-collection.geojson @@ -0,0 +1,26 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "GeometryCollection", + "geometries": [ + { + "type": "Point", + "coordinates": [2.8113711933311403] + }, + { + "type": "LineString", + "coordinates": [ + [1.285400390625, 4.214943141390651], + [0.472412109375, 2.9649843693339677], + [1.900634765625, 2.1857489471296665] + ] + } + ] + } + } + ] +} diff --git a/packages/turf-boolean-valid/test/false/GeometryCollection/nested-collection.geojson b/packages/turf-boolean-valid/test/false/GeometryCollection/nested-collection.geojson new file mode 100644 index 0000000000..5dd36a107b --- /dev/null +++ b/packages/turf-boolean-valid/test/false/GeometryCollection/nested-collection.geojson @@ -0,0 +1,27 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "GeometryCollection", + "geometries": [ + { + "type": "GeometryCollection", + "geometries": [ + { + "type": "Point", + "coordinates": [6.7575683593749996, 2.8113711933311403] + }, + { + "type": "Point", + "coordinates": [2.7575683593749996, 2.8113711933311403] + } + ] + } + ] + } + } + ] +} diff --git a/packages/turf-boolean-valid/test/false/GeometryCollection/no-type-in-nested-geometry.geojson b/packages/turf-boolean-valid/test/false/GeometryCollection/no-type-in-nested-geometry.geojson new file mode 100644 index 0000000000..b133619de8 --- /dev/null +++ b/packages/turf-boolean-valid/test/false/GeometryCollection/no-type-in-nested-geometry.geojson @@ -0,0 +1,25 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "GeometryCollection", + "geometries": [ + { + "coordinates": [6.7575683593749996, 2.8113711933311403] + }, + { + "type": "LineString", + "coordinates": [ + [1.285400390625, 4.214943141390651], + [0.472412109375, 2.9649843693339677], + [1.900634765625, 2.1857489471296665] + ] + } + ] + } + } + ] +} diff --git a/packages/turf-boolean-valid/test/false/GeometryCollection/non-geometry-in-collection.geojson b/packages/turf-boolean-valid/test/false/GeometryCollection/non-geometry-in-collection.geojson new file mode 100644 index 0000000000..c055410626 --- /dev/null +++ b/packages/turf-boolean-valid/test/false/GeometryCollection/non-geometry-in-collection.geojson @@ -0,0 +1,26 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "GeometryCollection", + "geometries": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [2.7575683593749996, 2.8113711933311403] + } + }, + { + "type": "Point", + "coordinates": [2.7575683593749996, 2.8113711933311403] + } + ] + } + } + ] +} diff --git a/packages/turf-boolean-valid/test/true/GeometryCollection/geometry-collection.geojson b/packages/turf-boolean-valid/test/true/GeometryCollection/geometry-collection.geojson new file mode 100644 index 0000000000..942a96f0a0 --- /dev/null +++ b/packages/turf-boolean-valid/test/true/GeometryCollection/geometry-collection.geojson @@ -0,0 +1,26 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "GeometryCollection", + "geometries": [ + { + "type": "Point", + "coordinates": [6.7575683593749996, 2.8113711933311403] + }, + { + "type": "LineString", + "coordinates": [ + [1.285400390625, 4.214943141390651], + [0.472412109375, 2.9649843693339677], + [1.900634765625, 2.1857489471296665] + ] + } + ] + } + } + ] +}