Open Portur opened 1 year ago
The check
method takes a string as an argument - passing it an object or any other type is undefined behavior. If there's a bug with check + a string argument, happy to look at it, but the documentation and TypeScript types dictate that it is only to be used with string arguments.
Ok thanks I missed that.
There is however still the issue where these invalid geoms arent being seen as invalid
const { check: geojsonTester } = require("@placemarkio/check-geojson");
// https://github.com/chrieke/geojson-invalid-geometry/blob/main/examples_geojson/invalid/polygon_unclosed_polygon.geojson?short_path=2a32854
const invalidGeojsonGeometryPolygonUnclosed = {
type: "Polygon",
coordinates: [
[
[13.376753, 52.515641],
[13.37696, 52.515011],
[13.378033, 52.514998],
[13.378049, 52.516176],
],
],
};
// https://github.com/chrieke/geojson-invalid-geometry/blob/main/examples_geojson/invalid/polygon_has_duplicate_nodes.geojson?short_path=487c8b7
const invalidGeojsonGeometryPolygonDuplicatesNodes = {
type: "Polygon",
coordinates: [
[
[13.378261, 52.513389],
[13.377365, 52.51446],
[13.377365, 52.51446],
[13.376762, 52.51337],
[13.378261, 52.513389],
],
],
};
// https://github.com/chrieke/geojson-invalid-geometry/blob/main/examples_geojson/invalid/polygon_has_less_than_three_unique_nodes.geojson?short_path=e1e556d
const invalidGeojsonGeometryPolygonTwoNodes = {
type: "Polygon",
coordinates: [
[
[13.377016, 52.512418],
[13.378182, 52.51285],
[13.377016, 52.512418],
],
],
};
// https://github.com/chrieke/geojson-invalid-geometry/blob/main/examples_geojson/invalid/polygon_interior_ring_not_clockwise_winding_order.geojson?short_path=1df04b0
const invalidGeojsonGeometryPolygonWithHolesCounterClockwise = {
type: "Polygon",
coordinates: [
[
[13.379307, 52.512661],
[13.381102, 52.512687],
[13.380973, 52.514197],
[13.379281, 52.514133],
[13.379307, 52.512661],
],
[
[13.380443, 52.513849],
[13.379901, 52.513849],
[13.379669, 52.51372],
[13.379591, 52.513384],
[13.379669, 52.512945],
[13.380185, 52.512855],
[13.380676, 52.51301],
[13.380559, 52.513294],
[13.379979, 52.513603],
[13.380443, 52.513849],
],
],
};
// https://github.com/chrieke/geojson-invalid-geometry/blob/main/examples_geojson/invalid/polygon_exterior_ring_not_counterclockwise_winding_order.geojson?short_path=f7e7cf0
const invalidGeojsonGeometryPolygonWithoutHolesCounterClockwise = {
type: "Polygon",
coordinates: [
[
[13.379263, 52.516012],
[13.380039, 52.516012],
[13.380557, 52.515852],
[13.380756, 52.515275],
[13.380597, 52.514996],
[13.380139, 52.514718],
[13.379601, 52.514757],
[13.379422, 52.514937],
[13.379522, 52.515534],
[13.379701, 52.515833],
[13.379263, 52.516012],
],
],
};
// https://github.com/chrieke/geojson-invalid-geometry/blob/main/examples_geojson/invalid/polygon_inner_and_exterior_ring_cross.geojson?short_path=dae4bfa
const invalidGeojsonGeometryPolygonSelfIntersect = {
type: "Polygon",
coordinates: [
[
[13.382288, 52.515426],
[13.382096, 52.514797],
[13.383424, 52.51464],
[13.383529, 52.515496],
[13.382288, 52.515426],
],
[
[13.382603, 52.514954],
[13.38262, 52.516255],
[13.383144, 52.515321],
[13.383127, 52.514867],
[13.382603, 52.514954],
],
],
};
// https://github.com/chrieke/geojson-invalid-geometry/blob/main/examples_geojson/invalid/linestring_zero_length.geojson?short_path=14d173c
const invalidGeojsonGeometryLineZeroLength = {
type: "LineString",
coordinates: [
[13.39265, 52.515046],
[13.39265, 52.515046],
],
};
// https://github.com/chrieke/geojson-invalid-geometry/blob/main/examples_geojson/invalid/incorrect_geometry_data_type.geojson?short_path=01db740
const invalidGeojsonGeometryType = {
type: "LineString",
coordinates: [
[
[13.383092, 52.510235],
[13.383092, 52.509704],
[13.38458, 52.509704],
[13.38458, 52.510235],
[13.383092, 52.510235],
],
],
};
try {
geojsonTester(JSON.stringify(invalidGeojsonGeometryPolygonUnclosed));
console.log("fail - invalidGeojsonGeometryPolygonUnclosed");
} catch (e) {
console.log("pass - invalidGeojsonGeometryPolygonUnclosed");
}
try {
geojsonTester(JSON.stringify(invalidGeojsonGeometryPolygonDuplicatesNodes));
console.log("fail - invalidGeojsonGeometryPolygonDuplicatesNodes");
} catch (e) {
console.log("pass - invalidGeojsonGeometryPolygonDuplicatesNodes");
}
try {
geojsonTester(JSON.stringify(invalidGeojsonGeometryPolygonTwoNodes));
console.log("fail - invalidGeojsonGeometryPolygonTwoNodes");
} catch (e) {
console.log("pass - invalidGeojsonGeometryPolygonTwoNodes");
}
try {
geojsonTester(JSON.stringify(invalidGeojsonGeometryPolygonWithHolesCounterClockwise));
console.log("fail - invalidGeojsonGeometryPolygonWithHolesCounterClockwise");
} catch (e) {
console.log("pass - invalidGeojsonGeometryPolygonWithHolesCounterClockwise");
}
try {
geojsonTester(JSON.stringify(invalidGeojsonGeometryPolygonWithoutHolesCounterClockwise));
console.log("fail - invalidGeojsonGeometryPolygonWithoutHolesCounterClockwise");
} catch (e) {
console.log("pass - invalidGeojsonGeometryPolygonWithoutHolesCounterClockwise");
}
try {
geojsonTester(JSON.stringify(invalidGeojsonGeometryPolygonSelfIntersect));
console.log("fail - invalidGeojsonGeometryPolygonSelfIntersect");
} catch (e) {
console.log("pass - invalidGeojsonGeometryPolygonSelfIntersect");
}
try {
geojsonTester(JSON.stringify(invalidGeojsonGeometryLineZeroLength));
console.log("fail - invalidGeojsonGeometryLineZeroLength");
} catch (e) {
console.log("pass - invalidGeojsonGeometryLineZeroLength");
}
try {
geojsonTester(JSON.stringify(invalidGeojsonGeometryType));
console.log("fail - invalidGeojsonGeometryType");
} catch (e) {
console.log("pass - invalidGeojsonGeometryType");
}
pass - invalidGeojsonGeometryPolygonUnclosed
fail - invalidGeojsonGeometryPolygonDuplicatesNodes
pass - invalidGeojsonGeometryPolygonTwoNodes
fail - invalidGeojsonGeometryPolygonWithHolesCounterClockwise
fail - invalidGeojsonGeometryPolygonWithoutHolesCounterClockwise
fail - invalidGeojsonGeometryPolygonSelfIntersect
fail - invalidGeojsonGeometryLineZeroLength
pass - invalidGeojsonGeometryType
@tmcw I just want to raise awareness of the above - where even using the values as string will still fail to check the invalid geometries above
Thanks, I think we should look at the invalid LineString & the three-node & unclosed Polygon test cases - whoops, just realized that those ones are passing.
The others are a little iffy for inclusion in this library. For the Right-hand-rule, we're following the current spec guidance:
Note: the [GJ2008] specification did not discuss linear ring winding order. For backwards compatibility, parsers SHOULD NOT reject Polygons that do not follow the right-hand rule.
Detecting & throwing on invalid geometries, like self-intersections, is pretty out-of-scope for this module as-is (though if someone wanted to contribute a robust implementation, I wouldn't be opposed.) Basically, we're checking structural validity and things defined in the GeoJSON spec. The GeoJSON spec doesn't even mention self-intersections - this is deferred to the WFS simple features spec. Checking things like self-intersections requires robust implementations of a bunch of geometry algorithms that can be much more performance-intensive than anything in this module, and also should probably be in a module that's more format-agnostic.
I'll do some investigating and come back. I don't think I have the knowledge or experience to contribute in any way but I'll see what I can find on how others have solved performant checks for self intersection.
Hi, here are tests that I expected to throw but don't. Sorry for the long post. It seems sending the value as
object
does not throw, where sending the same object asstring
does throw. I have added additional invalid types and which ones fail.The objects I have tested that cause the function to not throw are: