diff --git a/packages/turf-polygonize/lib/Graph.ts b/packages/turf-polygonize/lib/Graph.ts index bd9f9f3fbc..5b663ce294 100644 --- a/packages/turf-polygonize/lib/Graph.ts +++ b/packages/turf-polygonize/lib/Graph.ts @@ -44,6 +44,7 @@ function validateGeoJson(geoJson: AllGeoJSON) { class Graph { private nodes: { [id: string]: Node }; private edges: Edge[]; + private edgeIds: { [id: string]: true }; /** * Creates a graph from a GeoJSON. @@ -102,15 +103,21 @@ class Graph { * @param {Node} to - Node which ends the Edge */ addEdge(from: Node, to: Node) { - const edge = new Edge(from, to), - symetricEdge = edge.getSymetric(); + const edgeId = `${from.id}->${to.id}`; + if (this.edgeIds[edgeId]) return; + const edge = new Edge(from, to); + const symetricEdge = edge.getSymetric(); + + this.edgeIds[`${edge.from.id}->${edge.to.id}`] = true; + this.edgeIds[`${symetricEdge.from.id}->${symetricEdge.to.id}`] = true; this.edges.push(edge); this.edges.push(symetricEdge); } constructor() { this.edges = []; //< {Edge[]} dirEdges + this.edgeIds = {}; // The key is the `id` of the Node (ie: coordinates.join(',')) this.nodes = {}; @@ -348,6 +355,7 @@ class Graph { removeEdge(edge: Edge) { this.edges = this.edges.filter((e) => !e.isEqual(edge)); edge.deleteEdge(); + delete this.edgeIds[`${edge.from.id}->${edge.to.id}`]; } } diff --git a/packages/turf-polygonize/package.json b/packages/turf-polygonize/package.json index 6fc2eb1f7a..8bad8af1e0 100644 --- a/packages/turf-polygonize/package.json +++ b/packages/turf-polygonize/package.json @@ -5,7 +5,8 @@ "author": "Turf Authors", "contributors": [ "Nicolas Cisco <@nickcis>", - "Denis Carriere <@DenisCarriere>" + "Denis Carriere <@DenisCarriere>", + "Kenny Sabir <@Traksewt>" ], "license": "MIT", "bugs": { diff --git a/packages/turf-polygonize/test.ts b/packages/turf-polygonize/test.ts index c45470a78b..48a15d5108 100644 --- a/packages/turf-polygonize/test.ts +++ b/packages/turf-polygonize/test.ts @@ -81,6 +81,40 @@ test("turf-polygonize -- input mutation", (t) => { t.end(); }); +test("turf-polygonize -- duplicate segment", (t) => { + const lines = featureCollection([ + lineString([ + [0, 0], + [1, 0], + ]), + lineString([ + [1, 0], + [1, 1], + ]), + lineString([ + [1, 1], + [0, 1], + ]), + lineString([ + [0, 1], + [0, 0], + ]), + // Duplicate boundary segment should not prevent polygonization. + lineString([ + [0, 0], + [1, 0], + ]), + ]); + + const polygonized = polygonize(lines); + t.equal( + polygonized.features.length, + 1, + "returns one polygon for closed ring with duplicate edge" + ); + t.end(); +}); + function colorize(feature, color = "#F00", width = 6) { feature.properties["fill"] = color; feature.properties["fill-opacity"] = 0.3;