Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 44 additions & 22 deletions packages/turf-polygonize/lib/Graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,9 @@ function validateGeoJson(geoJson: AllGeoJSON) {
* This graph is directed (both directions are created)
*/
class Graph {
private nodes = new Set<Node>();
private nodeIdx: Map<number, Map<number, Node>> = new Map(); // Map<longitude, Map<latitude, Node>>
private nodes: Map<number, Map<number, Node>> = new Map(); // Map<longitude, Map<latitude, Node>>
private nodeId = 0; // the next node id to use
private edges: Edge[] = [];
private edges = new Map<Node, Map<Node, Edge>>(); // Map<from, Map<to, Edge>>

/**
* Creates a graph from a GeoJSON.
Expand Down Expand Up @@ -88,15 +87,14 @@ class Graph {
* @returns {Node} - The created or stored node
*/
getNode(coordinates: number[]) {
let node = this.nodeIdx.get(coordinates[0])?.get(coordinates[1]);
let node = this.nodes.get(coordinates[0])?.get(coordinates[1]);

if (node == null) {
const node = new Node(this.nodeId++, coordinates);
this.nodes.add(node);
let byLat = this.nodeIdx.get(coordinates[0]);
let byLat = this.nodes.get(coordinates[0]);
if (byLat == null) {
byLat = new Map();
this.nodeIdx.set(coordinates[0], byLat);
this.nodes.set(coordinates[0], byLat);
}
byLat.set(coordinates[1], node);
return node;
Expand All @@ -117,17 +115,28 @@ class Graph {
const edge = new Edge(from, to),
symetricEdge = edge.getSymetric();

this.edges.push(edge);
this.edges.push(symetricEdge);
// add the forward edge
let toMap = this.edges.get(from);
if (toMap == null) {
toMap = new Map();
this.edges.set(from, toMap);
}
toMap.set(to, edge);

// add the symmetric edge
let symToMap = this.edges.get(to);
if (symToMap == null) {
symToMap = new Map();
this.edges.set(to, symToMap);
}
symToMap.set(from, symetricEdge);
Comment on lines +118 to +132

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block actually implicitly deduplicates edges as they're inserted. We'll create a new edge and clobber the previous edge with the same (to, from) Nodes.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After a bit more research, the Edge constructor modifies the passed-in Node objects. That means that merely creating an Edge will still cause the bug that #3045 set out to address.

}

/**
* Removes Dangle Nodes (nodes with grade 1).
*/
deleteDangles() {
for (const node of this.nodes) {
this._removeIfDangle(node);
}
this._forEachNode((node) => this._removeIfDangle(node));
}

/**
Expand Down Expand Up @@ -158,7 +167,7 @@ class Graph {
this._findLabeledEdgeRings();

// Cut-edges (bridges) are edges where both edges have the same label
this.edges.forEach((edge) => {
this._forEachEdge((edge) => {
if (edge.label === edge.symetric!.label) {
this.removeEdge(edge.symetric!);
this.removeEdge(edge);
Expand All @@ -176,9 +185,7 @@ class Graph {
*/
_computeNextCWEdges(node?: Node) {
if (node == null) {
for (const node of this.nodes) {
this._computeNextCWEdges(node);
}
this._forEachNode((node) => this._computeNextCWEdges(node));
} else {
node.getOuterEdges().forEach((edge, i) => {
node.getOuterEdge(
Expand Down Expand Up @@ -242,7 +249,7 @@ class Graph {
_findLabeledEdgeRings() {
const edgeRingStarts: Edge[] = [];
let label = 0;
this.edges.forEach((edge) => {
this._forEachEdge((edge) => {
if (edge.label! >= 0) return;

edgeRingStarts.push(edge);
Expand All @@ -268,7 +275,7 @@ class Graph {
this._computeNextCWEdges();

// Clear labels
this.edges.forEach((edge) => {
this._forEachEdge((edge) => {
edge.label = undefined;
});

Expand All @@ -282,7 +289,7 @@ class Graph {
const edgeRingList: EdgeRing[] = [];

// find all edgerings
this.edges.forEach((edge) => {
this._forEachEdge((edge) => {
if (edge.ring) return;
edgeRingList.push(this._findEdgeRing(edge));
});
Expand Down Expand Up @@ -342,8 +349,7 @@ class Graph {
removeNode(node: Node) {
node.getOuterEdges().forEach((edge) => this.removeEdge(edge));
node.innerEdges.forEach((edge) => this.removeEdge(edge));
this.nodeIdx.get(node.coordinates[0])?.delete(node.coordinates[1]);
this.nodes.delete(node);
this.nodes.get(node.coordinates[0])?.delete(node.coordinates[1]);
}

/**
Expand All @@ -352,9 +358,25 @@ class Graph {
* @param {Edge} edge - Edge to be removed
*/
removeEdge(edge: Edge) {
this.edges = this.edges.filter((e) => !e.isEqual(edge));
this.edges.get(edge.from)?.delete(edge.to);
edge.deleteEdge();
}

_forEachNode(fn: (n: Node) => void) {
for (const latMap of this.nodes.values()) {
for (const node of latMap.values()) {
fn(node);
}
}
}

_forEachEdge(fn: (e: Edge) => void) {
for (const toMap of this.edges.values()) {
for (const edge of toMap.values()) {
fn(edge);
}
}
}
}

export { Graph };
Expand Down
Loading
Loading