@turf/polygonize
Advanced tools
Comparing version 6.2.0-alpha.2 to 6.2.0-alpha.3
@@ -22,8 +22,8 @@ import booleanPointInPolygon from '@turf/boolean-point-in-polygon'; | ||
function orientationIndex(p1, p2, q) { | ||
var dx1 = p2[0] - p1[0], | ||
dy1 = p2[1] - p1[1], | ||
dx2 = q[0] - p2[0], | ||
dy2 = q[1] - p2[1]; | ||
var dx1 = p2[0] - p1[0], | ||
dy1 = p2[1] - p1[1], | ||
dx2 = q[0] - p2[0], | ||
dy2 = q[1] - p2[1]; | ||
return Math.sign(dx1 * dy2 - dx2 * dy1); | ||
return Math.sign(dx1 * dy2 - dx2 * dy1); | ||
} | ||
@@ -41,11 +41,21 @@ | ||
function envelopeIsEqual(env1, env2) { | ||
var envX1 = env1.geometry.coordinates.map(function (c) { return c[0]; }), | ||
envY1 = env1.geometry.coordinates.map(function (c) { return c[1]; }), | ||
envX2 = env2.geometry.coordinates.map(function (c) { return c[0]; }), | ||
envY2 = env2.geometry.coordinates.map(function (c) { return c[1]; }); | ||
var envX1 = env1.geometry.coordinates.map(function (c) { | ||
return c[0]; | ||
}), | ||
envY1 = env1.geometry.coordinates.map(function (c) { | ||
return c[1]; | ||
}), | ||
envX2 = env2.geometry.coordinates.map(function (c) { | ||
return c[0]; | ||
}), | ||
envY2 = env2.geometry.coordinates.map(function (c) { | ||
return c[1]; | ||
}); | ||
return Math.max(null, envX1) === Math.max(null, envX2) && | ||
return ( | ||
Math.max(null, envX1) === Math.max(null, envX2) && | ||
Math.max(null, envY1) === Math.max(null, envY2) && | ||
Math.min(null, envX1) === Math.min(null, envX2) && | ||
Math.min(null, envY1) === Math.min(null, envY2); | ||
Math.min(null, envY1) === Math.min(null, envY2) | ||
); | ||
} | ||
@@ -65,3 +75,5 @@ | ||
function envelopeContains(self, env) { | ||
return env.geometry.coordinates[0].every(function (c) { return booleanPointInPolygon(point(c), self); }); | ||
return env.geometry.coordinates[0].every(function (c) { | ||
return booleanPointInPolygon(point(c), self); | ||
}); | ||
} | ||
@@ -77,3 +89,3 @@ | ||
function coordinatesEqual(coord1, coord2) { | ||
return coord1[0] === coord2[0] && coord1[1] === coord2[1]; | ||
return coord1[0] === coord2[0] && coord1[1] === coord2[1]; | ||
} | ||
@@ -85,21 +97,25 @@ | ||
var Node = function Node(coordinates) { | ||
this.id = Node.buildId(coordinates); | ||
this.coordinates = coordinates; //< {Number[]} | ||
this.innerEdges = []; //< {Edge[]} | ||
this.id = Node.buildId(coordinates); | ||
this.coordinates = coordinates; //< {Number[]} | ||
this.innerEdges = []; //< {Edge[]} | ||
// We wil store to (out) edges in an CCW order as geos::planargraph::DirectedEdgeStar does | ||
this.outerEdges = []; //< {Edge[]} | ||
this.outerEdgesSorted = false; //< {Boolean} flag that stores if the outer Edges had been sorted | ||
// We wil store to (out) edges in an CCW order as geos::planargraph::DirectedEdgeStar does | ||
this.outerEdges = []; //< {Edge[]} | ||
this.outerEdgesSorted = false; //< {Boolean} flag that stores if the outer Edges had been sorted | ||
}; | ||
Node.buildId = function buildId (coordinates) { | ||
return coordinates.join(','); | ||
Node.buildId = function buildId(coordinates) { | ||
return coordinates.join(","); | ||
}; | ||
Node.prototype.removeInnerEdge = function removeInnerEdge (edge) { | ||
this.innerEdges = this.innerEdges.filter(function (e) { return e.from.id !== edge.from.id; }); | ||
Node.prototype.removeInnerEdge = function removeInnerEdge(edge) { | ||
this.innerEdges = this.innerEdges.filter(function (e) { | ||
return e.from.id !== edge.from.id; | ||
}); | ||
}; | ||
Node.prototype.removeOuterEdge = function removeOuterEdge (edge) { | ||
this.outerEdges = this.outerEdges.filter(function (e) { return e.to.id !== edge.to.id; }); | ||
Node.prototype.removeOuterEdge = function removeOuterEdge(edge) { | ||
this.outerEdges = this.outerEdges.filter(function (e) { | ||
return e.to.id !== edge.to.id; | ||
}); | ||
}; | ||
@@ -113,5 +129,5 @@ | ||
*/ | ||
Node.prototype.addOuterEdge = function addOuterEdge (edge) { | ||
this.outerEdges.push(edge); | ||
this.outerEdgesSorted = false; | ||
Node.prototype.addOuterEdge = function addOuterEdge(edge) { | ||
this.outerEdges.push(edge); | ||
this.outerEdgesSorted = false; | ||
}; | ||
@@ -125,36 +141,61 @@ | ||
*/ | ||
Node.prototype.sortOuterEdges = function sortOuterEdges () { | ||
var this$1 = this; | ||
Node.prototype.sortOuterEdges = function sortOuterEdges() { | ||
var this$1 = this; | ||
if (!this.outerEdgesSorted) { | ||
//this.outerEdges.sort((a, b) => a.compareTo(b)); | ||
// Using this comparator in order to be deterministic | ||
this.outerEdges.sort(function (a, b) { | ||
var aNode = a.to, | ||
bNode = b.to; | ||
if (!this.outerEdgesSorted) { | ||
//this.outerEdges.sort((a, b) => a.compareTo(b)); | ||
// Using this comparator in order to be deterministic | ||
this.outerEdges.sort(function (a, b) { | ||
var aNode = a.to, | ||
bNode = b.to; | ||
if (aNode.coordinates[0] - this$1.coordinates[0] >= 0 && bNode.coordinates[0] - this$1.coordinates[0] < 0) | ||
{ return 1; } | ||
if (aNode.coordinates[0] - this$1.coordinates[0] < 0 && bNode.coordinates[0] - this$1.coordinates[0] >= 0) | ||
{ return -1; } | ||
if ( | ||
aNode.coordinates[0] - this$1.coordinates[0] >= 0 && | ||
bNode.coordinates[0] - this$1.coordinates[0] < 0 | ||
) { | ||
return 1; | ||
} | ||
if ( | ||
aNode.coordinates[0] - this$1.coordinates[0] < 0 && | ||
bNode.coordinates[0] - this$1.coordinates[0] >= 0 | ||
) { | ||
return -1; | ||
} | ||
if (aNode.coordinates[0] - this$1.coordinates[0] === 0 && bNode.coordinates[0] - this$1.coordinates[0] === 0) { | ||
if (aNode.coordinates[1] - this$1.coordinates[1] >= 0 || bNode.coordinates[1] - this$1.coordinates[1] >= 0) | ||
{ return aNode.coordinates[1] - bNode.coordinates[1]; } | ||
return bNode.coordinates[1] - aNode.coordinates[1]; | ||
} | ||
if ( | ||
aNode.coordinates[0] - this$1.coordinates[0] === 0 && | ||
bNode.coordinates[0] - this$1.coordinates[0] === 0 | ||
) { | ||
if ( | ||
aNode.coordinates[1] - this$1.coordinates[1] >= 0 || | ||
bNode.coordinates[1] - this$1.coordinates[1] >= 0 | ||
) { | ||
return aNode.coordinates[1] - bNode.coordinates[1]; | ||
} | ||
return bNode.coordinates[1] - aNode.coordinates[1]; | ||
} | ||
var det = orientationIndex(this$1.coordinates, aNode.coordinates, bNode.coordinates); | ||
if (det < 0) | ||
{ return 1; } | ||
if (det > 0) | ||
{ return -1; } | ||
var det = orientationIndex( | ||
this$1.coordinates, | ||
aNode.coordinates, | ||
bNode.coordinates | ||
); | ||
if (det < 0) { | ||
return 1; | ||
} | ||
if (det > 0) { | ||
return -1; | ||
} | ||
var d1 = Math.pow(aNode.coordinates[0] - this$1.coordinates[0], 2) + Math.pow(aNode.coordinates[1] - this$1.coordinates[1], 2), | ||
d2 = Math.pow(bNode.coordinates[0] - this$1.coordinates[0], 2) + Math.pow(bNode.coordinates[1] - this$1.coordinates[1], 2); | ||
var d1 = | ||
Math.pow(aNode.coordinates[0] - this$1.coordinates[0], 2) + | ||
Math.pow(aNode.coordinates[1] - this$1.coordinates[1], 2), | ||
d2 = | ||
Math.pow(bNode.coordinates[0] - this$1.coordinates[0], 2) + | ||
Math.pow(bNode.coordinates[1] - this$1.coordinates[1], 2); | ||
return d1 - d2; | ||
}); | ||
this.outerEdgesSorted = true; | ||
} | ||
return d1 - d2; | ||
}); | ||
this.outerEdgesSorted = true; | ||
} | ||
}; | ||
@@ -170,14 +211,14 @@ | ||
*/ | ||
Node.prototype.getOuterEdges = function getOuterEdges () { | ||
this.sortOuterEdges(); | ||
return this.outerEdges; | ||
Node.prototype.getOuterEdges = function getOuterEdges() { | ||
this.sortOuterEdges(); | ||
return this.outerEdges; | ||
}; | ||
Node.prototype.getOuterEdge = function getOuterEdge (i) { | ||
this.sortOuterEdges(); | ||
return this.outerEdges[i]; | ||
Node.prototype.getOuterEdge = function getOuterEdge(i) { | ||
this.sortOuterEdges(); | ||
return this.outerEdges[i]; | ||
}; | ||
Node.prototype.addInnerEdge = function addInnerEdge (edge) { | ||
this.innerEdges.push(edge); | ||
Node.prototype.addInnerEdge = function addInnerEdge(edge) { | ||
this.innerEdges.push(edge); | ||
}; | ||
@@ -189,12 +230,12 @@ | ||
var Edge = function Edge(from, to) { | ||
this.from = from; //< start | ||
this.to = to; //< End | ||
this.from = from; //< start | ||
this.to = to; //< End | ||
this.next = undefined; //< The edge to be computed after | ||
this.label = undefined; //< Used in order to detect Cut Edges (Bridges) | ||
this.symetric = undefined; //< The symetric edge of this | ||
this.ring = undefined; //< EdgeRing in which the Edge is | ||
this.next = undefined; //< The edge to be computed after | ||
this.label = undefined; //< Used in order to detect Cut Edges (Bridges) | ||
this.symetric = undefined; //< The symetric edge of this | ||
this.ring = undefined; //< EdgeRing in which the Edge is | ||
this.from.addOuterEdge(this); | ||
this.to.addInnerEdge(this); | ||
this.from.addOuterEdge(this); | ||
this.to.addInnerEdge(this); | ||
}; | ||
@@ -205,14 +246,14 @@ | ||
*/ | ||
Edge.prototype.getSymetric = function getSymetric () { | ||
if (!this.symetric) { | ||
this.symetric = new Edge(this.to, this.from); | ||
this.symetric.symetric = this; | ||
} | ||
Edge.prototype.getSymetric = function getSymetric() { | ||
if (!this.symetric) { | ||
this.symetric = new Edge(this.to, this.from); | ||
this.symetric.symetric = this; | ||
} | ||
return this.symetric; | ||
return this.symetric; | ||
}; | ||
Edge.prototype.deleteEdge = function deleteEdge () { | ||
this.from.removeOuterEdge(this); | ||
this.to.removeInnerEdge(this); | ||
Edge.prototype.deleteEdge = function deleteEdge() { | ||
this.from.removeOuterEdge(this); | ||
this.to.removeInnerEdge(this); | ||
}; | ||
@@ -228,8 +269,8 @@ | ||
*/ | ||
Edge.prototype.isEqual = function isEqual (edge) { | ||
return this.from.id === edge.from.id && this.to.id === edge.to.id; | ||
Edge.prototype.isEqual = function isEqual(edge) { | ||
return this.from.id === edge.from.id && this.to.id === edge.to.id; | ||
}; | ||
Edge.prototype.toString = function toString () { | ||
return ("Edge { " + (this.from.id) + " -> " + (this.to.id) + " }"); | ||
Edge.prototype.toString = function toString() { | ||
return "Edge { " + this.from.id + " -> " + this.to.id + " }"; | ||
}; | ||
@@ -242,4 +283,4 @@ | ||
*/ | ||
Edge.prototype.toLineString = function toLineString () { | ||
return lineString([this.from.coordinates, this.to.coordinates]); | ||
Edge.prototype.toLineString = function toLineString() { | ||
return lineString([this.from.coordinates, this.to.coordinates]); | ||
}; | ||
@@ -257,4 +298,8 @@ | ||
*/ | ||
Edge.prototype.compareTo = function compareTo (edge) { | ||
return orientationIndex(edge.from.coordinates, edge.to.coordinates, this.to.coordinates); | ||
Edge.prototype.compareTo = function compareTo(edge) { | ||
return orientationIndex( | ||
edge.from.coordinates, | ||
edge.to.coordinates, | ||
this.to.coordinates | ||
); | ||
}; | ||
@@ -270,5 +315,5 @@ | ||
var EdgeRing = function EdgeRing() { | ||
this.edges = []; | ||
this.polygon = undefined; //< Caches Polygon representation | ||
this.envelope = undefined; //< Caches Envelope representation | ||
this.edges = []; | ||
this.polygon = undefined; //< Caches Polygon representation | ||
this.envelope = undefined; //< Caches Envelope representation | ||
}; | ||
@@ -284,7 +329,7 @@ | ||
*/ | ||
EdgeRing.prototype.push = function push (edge) { | ||
// Emulate Array getter ([]) behaviour | ||
this[this.edges.length] = edge; | ||
this.edges.push(edge); | ||
this.polygon = this.envelope = undefined; | ||
EdgeRing.prototype.push = function push(edge) { | ||
// Emulate Array getter ([]) behaviour | ||
this[this.edges.length] = edge; | ||
this.edges.push(edge); | ||
this.polygon = this.envelope = undefined; | ||
}; | ||
@@ -299,4 +344,4 @@ | ||
*/ | ||
EdgeRing.prototype.get = function get (i) { | ||
return this.edges[i]; | ||
EdgeRing.prototype.get = function get(i) { | ||
return this.edges[i]; | ||
}; | ||
@@ -311,3 +356,3 @@ | ||
prototypeAccessors.length.get = function () { | ||
return this.edges.length; | ||
return this.edges.length; | ||
}; | ||
@@ -321,4 +366,4 @@ | ||
*/ | ||
EdgeRing.prototype.forEach = function forEach (f) { | ||
this.edges.forEach(f); | ||
EdgeRing.prototype.forEach = function forEach(f) { | ||
this.edges.forEach(f); | ||
}; | ||
@@ -333,4 +378,4 @@ | ||
*/ | ||
EdgeRing.prototype.map = function map (f) { | ||
return this.edges.map(f); | ||
EdgeRing.prototype.map = function map(f) { | ||
return this.edges.map(f); | ||
}; | ||
@@ -345,4 +390,4 @@ | ||
*/ | ||
EdgeRing.prototype.some = function some (f) { | ||
return this.edges.some(f); | ||
EdgeRing.prototype.some = function some(f) { | ||
return this.edges.some(f); | ||
}; | ||
@@ -360,5 +405,5 @@ | ||
*/ | ||
EdgeRing.prototype.isValid = function isValid () { | ||
// TODO: stub | ||
return true; | ||
EdgeRing.prototype.isValid = function isValid() { | ||
// TODO: stub | ||
return true; | ||
}; | ||
@@ -375,19 +420,28 @@ | ||
*/ | ||
EdgeRing.prototype.isHole = function isHole () { | ||
var this$1 = this; | ||
EdgeRing.prototype.isHole = function isHole() { | ||
var this$1 = this; | ||
// XXX: Assuming Ring is valid | ||
// Find highest point | ||
var hiIndex = this.edges.reduce(function (high, edge, i) { | ||
if (edge.from.coordinates[1] > this$1.edges[high].from.coordinates[1]) | ||
{ high = i; } | ||
return high; | ||
}, 0), | ||
iPrev = (hiIndex === 0 ? this.length : hiIndex) - 1, | ||
iNext = (hiIndex + 1) % this.length, | ||
disc = orientationIndex(this.edges[iPrev].from.coordinates, this.edges[hiIndex].from.coordinates, this.edges[iNext].from.coordinates); | ||
// XXX: Assuming Ring is valid | ||
// Find highest point | ||
var hiIndex = this.edges.reduce(function (high, edge, i) { | ||
if (edge.from.coordinates[1] > this$1.edges[high].from.coordinates[1]) { | ||
high = i; | ||
} | ||
return high; | ||
}, 0), | ||
iPrev = (hiIndex === 0 ? this.length : hiIndex) - 1, | ||
iNext = (hiIndex + 1) % this.length, | ||
disc = orientationIndex( | ||
this.edges[iPrev].from.coordinates, | ||
this.edges[hiIndex].from.coordinates, | ||
this.edges[iNext].from.coordinates | ||
); | ||
if (disc === 0) | ||
{ return this.edges[iPrev].from.coordinates[0] > this.edges[iNext].from.coordinates[0]; } | ||
return disc > 0; | ||
if (disc === 0) { | ||
return ( | ||
this.edges[iPrev].from.coordinates[0] > | ||
this.edges[iNext].from.coordinates[0] | ||
); | ||
} | ||
return disc > 0; | ||
}; | ||
@@ -401,4 +455,8 @@ | ||
*/ | ||
EdgeRing.prototype.toMultiPoint = function toMultiPoint () { | ||
return multiPoint(this.edges.map(function (edge) { return edge.from.coordinates; })); | ||
EdgeRing.prototype.toMultiPoint = function toMultiPoint() { | ||
return multiPoint( | ||
this.edges.map(function (edge) { | ||
return edge.from.coordinates; | ||
}) | ||
); | ||
}; | ||
@@ -412,8 +470,11 @@ | ||
*/ | ||
EdgeRing.prototype.toPolygon = function toPolygon () { | ||
if (this.polygon) | ||
{ return this.polygon; } | ||
var coordinates = this.edges.map(function (edge) { return edge.from.coordinates; }); | ||
coordinates.push(this.edges[0].from.coordinates); | ||
return (this.polygon = polygon([coordinates])); | ||
EdgeRing.prototype.toPolygon = function toPolygon() { | ||
if (this.polygon) { | ||
return this.polygon; | ||
} | ||
var coordinates = this.edges.map(function (edge) { | ||
return edge.from.coordinates; | ||
}); | ||
coordinates.push(this.edges[0].from.coordinates); | ||
return (this.polygon = polygon([coordinates])); | ||
}; | ||
@@ -427,6 +488,7 @@ | ||
*/ | ||
EdgeRing.prototype.getEnvelope = function getEnvelope () { | ||
if (this.envelope) | ||
{ return this.envelope; } | ||
return (this.envelope = envelope(this.toPolygon())); | ||
EdgeRing.prototype.getEnvelope = function getEnvelope() { | ||
if (this.envelope) { | ||
return this.envelope; | ||
} | ||
return (this.envelope = envelope(this.toPolygon())); | ||
}; | ||
@@ -442,29 +504,41 @@ | ||
*/ | ||
EdgeRing.findEdgeRingContaining = function findEdgeRingContaining (testEdgeRing, shellList) { | ||
var testEnvelope = testEdgeRing.getEnvelope(); | ||
EdgeRing.findEdgeRingContaining = function findEdgeRingContaining( | ||
testEdgeRing, | ||
shellList | ||
) { | ||
var testEnvelope = testEdgeRing.getEnvelope(); | ||
var minEnvelope, | ||
minShell; | ||
shellList.forEach(function (shell) { | ||
var tryEnvelope = shell.getEnvelope(); | ||
var minEnvelope, minShell; | ||
shellList.forEach(function (shell) { | ||
var tryEnvelope = shell.getEnvelope(); | ||
if (minShell) | ||
{ minEnvelope = minShell.getEnvelope(); } | ||
if (minShell) { | ||
minEnvelope = minShell.getEnvelope(); | ||
} | ||
// the hole envelope cannot equal the shell envelope | ||
if (envelopeIsEqual(tryEnvelope, testEnvelope)) | ||
{ return; } | ||
// the hole envelope cannot equal the shell envelope | ||
if (envelopeIsEqual(tryEnvelope, testEnvelope)) { | ||
return; | ||
} | ||
if (envelopeContains(tryEnvelope, testEnvelope)) { | ||
var testPoint = testEdgeRing.map(function (edge) { return edge.from.coordinates; }) | ||
.find(function (pt) { return !shell.some(function (edge) { return coordinatesEqual(pt, edge.from.coordinates); }); }); | ||
if (envelopeContains(tryEnvelope, testEnvelope)) { | ||
var testPoint = testEdgeRing | ||
.map(function (edge) { | ||
return edge.from.coordinates; | ||
}) | ||
.find(function (pt) { | ||
return !shell.some(function (edge) { | ||
return coordinatesEqual(pt, edge.from.coordinates); | ||
}); | ||
}); | ||
if (testPoint && shell.inside(point(testPoint))) { | ||
if (!minShell || envelopeContains(minEnvelope, tryEnvelope)) | ||
{ minShell = shell; } | ||
} | ||
if (testPoint && shell.inside(point(testPoint))) { | ||
if (!minShell || envelopeContains(minEnvelope, tryEnvelope)) { | ||
minShell = shell; | ||
} | ||
}); | ||
} | ||
} | ||
}); | ||
return minShell; | ||
return minShell; | ||
}; | ||
@@ -478,7 +552,7 @@ | ||
*/ | ||
EdgeRing.prototype.inside = function inside (pt) { | ||
return booleanPointInPolygon(pt, this.toPolygon()); | ||
EdgeRing.prototype.inside = function inside(pt) { | ||
return booleanPointInPolygon(pt, this.toPolygon()); | ||
}; | ||
Object.defineProperties( EdgeRing.prototype, prototypeAccessors ); | ||
Object.defineProperties(EdgeRing.prototype, prototypeAccessors); | ||
@@ -492,12 +566,19 @@ /** | ||
function validateGeoJson(geoJson) { | ||
if (!geoJson) | ||
{ throw new Error('No geojson passed'); } | ||
if (!geoJson) { | ||
throw new Error("No geojson passed"); | ||
} | ||
if (geoJson.type !== 'FeatureCollection' && | ||
geoJson.type !== 'GeometryCollection' && | ||
geoJson.type !== 'MultiLineString' && | ||
geoJson.type !== 'LineString' && | ||
geoJson.type !== 'Feature' | ||
) | ||
{ throw new Error(("Invalid input type '" + (geoJson.type) + "'. Geojson must be FeatureCollection, GeometryCollection, LineString, MultiLineString or Feature")); } | ||
if ( | ||
geoJson.type !== "FeatureCollection" && | ||
geoJson.type !== "GeometryCollection" && | ||
geoJson.type !== "MultiLineString" && | ||
geoJson.type !== "LineString" && | ||
geoJson.type !== "Feature" | ||
) { | ||
throw new Error( | ||
"Invalid input type '" + | ||
geoJson.type + | ||
"'. Geojson must be FeatureCollection, GeometryCollection, LineString, MultiLineString or Feature" | ||
); | ||
} | ||
} | ||
@@ -515,6 +596,6 @@ | ||
var Graph = function Graph() { | ||
this.edges = []; //< {Edge[]} dirEdges | ||
this.edges = []; //< {Edge[]} dirEdges | ||
// The key is the `id` of the Node (ie: coordinates.join(',')) | ||
this.nodes = {}; | ||
// The key is the `id` of the Node (ie: coordinates.join(',')) | ||
this.nodes = {}; | ||
}; | ||
@@ -525,21 +606,21 @@ | ||
*/ | ||
Graph.fromGeoJson = function fromGeoJson (geoJson) { | ||
validateGeoJson(geoJson); | ||
Graph.fromGeoJson = function fromGeoJson(geoJson) { | ||
validateGeoJson(geoJson); | ||
var graph = new Graph(); | ||
flattenEach(geoJson, function (feature) { | ||
featureOf(feature, 'LineString', 'Graph::fromGeoJson'); | ||
// When a LineString if formed by many segments, split them | ||
coordReduce(feature, function (prev, cur) { | ||
if (prev) { | ||
var start = graph.getNode(prev), | ||
end = graph.getNode(cur); | ||
var graph = new Graph(); | ||
flattenEach(geoJson, function (feature) { | ||
featureOf(feature, "LineString", "Graph::fromGeoJson"); | ||
// When a LineString if formed by many segments, split them | ||
coordReduce(feature, function (prev, cur) { | ||
if (prev) { | ||
var start = graph.getNode(prev), | ||
end = graph.getNode(cur); | ||
graph.addEdge(start, end); | ||
} | ||
return cur; | ||
}); | ||
graph.addEdge(start, end); | ||
} | ||
return cur; | ||
}); | ||
}); | ||
return graph; | ||
return graph; | ||
}; | ||
@@ -553,9 +634,10 @@ | ||
*/ | ||
Graph.prototype.getNode = function getNode (coordinates) { | ||
var id = Node.buildId(coordinates); | ||
var node = this.nodes[id]; | ||
if (!node) | ||
{ node = this.nodes[id] = new Node(coordinates); } | ||
Graph.prototype.getNode = function getNode(coordinates) { | ||
var id = Node.buildId(coordinates); | ||
var node = this.nodes[id]; | ||
if (!node) { | ||
node = this.nodes[id] = new Node(coordinates); | ||
} | ||
return node; | ||
return node; | ||
}; | ||
@@ -571,16 +653,20 @@ | ||
*/ | ||
Graph.prototype.addEdge = function addEdge (from, to) { | ||
var edge = new Edge(from, to), | ||
symetricEdge = edge.getSymetric(); | ||
Graph.prototype.addEdge = function addEdge(from, to) { | ||
var edge = new Edge(from, to), | ||
symetricEdge = edge.getSymetric(); | ||
this.edges.push(edge); | ||
this.edges.push(symetricEdge); | ||
this.edges.push(edge); | ||
this.edges.push(symetricEdge); | ||
}; | ||
Graph.prototype.deleteDangles = function deleteDangles () { | ||
var this$1 = this; | ||
Graph.prototype.deleteDangles = function deleteDangles() { | ||
var this$1 = this; | ||
Object.keys(this.nodes) | ||
.map(function (id) { return this$1.nodes[id]; }) | ||
.forEach(function (node) { return this$1._removeIfDangle(node); }); | ||
Object.keys(this.nodes) | ||
.map(function (id) { | ||
return this$1.nodes[id]; | ||
}) | ||
.forEach(function (node) { | ||
return this$1._removeIfDangle(node); | ||
}); | ||
}; | ||
@@ -595,11 +681,15 @@ | ||
*/ | ||
Graph.prototype._removeIfDangle = function _removeIfDangle (node) { | ||
var this$1 = this; | ||
Graph.prototype._removeIfDangle = function _removeIfDangle(node) { | ||
var this$1 = this; | ||
// As edges are directed and symetrical, we count only innerEdges | ||
if (node.innerEdges.length <= 1) { | ||
var outerNodes = node.getOuterEdges().map(function (e) { return e.to; }); | ||
this.removeNode(node); | ||
outerNodes.forEach(function (n) { return this$1._removeIfDangle(n); }); | ||
} | ||
// As edges are directed and symetrical, we count only innerEdges | ||
if (node.innerEdges.length <= 1) { | ||
var outerNodes = node.getOuterEdges().map(function (e) { | ||
return e.to; | ||
}); | ||
this.removeNode(node); | ||
outerNodes.forEach(function (n) { | ||
return this$1._removeIfDangle(n); | ||
}); | ||
} | ||
}; | ||
@@ -614,15 +704,15 @@ | ||
*/ | ||
Graph.prototype.deleteCutEdges = function deleteCutEdges () { | ||
var this$1 = this; | ||
Graph.prototype.deleteCutEdges = function deleteCutEdges() { | ||
var this$1 = this; | ||
this._computeNextCWEdges(); | ||
this._findLabeledEdgeRings(); | ||
this._computeNextCWEdges(); | ||
this._findLabeledEdgeRings(); | ||
// Cut-edges (bridges) are edges where both edges have the same label | ||
this.edges.forEach(function (edge) { | ||
if (edge.label === edge.symetric.label) { | ||
this$1.removeEdge(edge.symetric); | ||
this$1.removeEdge(edge); | ||
} | ||
}); | ||
// Cut-edges (bridges) are edges where both edges have the same label | ||
this.edges.forEach(function (edge) { | ||
if (edge.label === edge.symetric.label) { | ||
this$1.removeEdge(edge.symetric); | ||
this$1.removeEdge(edge); | ||
} | ||
}); | ||
}; | ||
@@ -638,13 +728,16 @@ | ||
*/ | ||
Graph.prototype._computeNextCWEdges = function _computeNextCWEdges (node) { | ||
var this$1 = this; | ||
Graph.prototype._computeNextCWEdges = function _computeNextCWEdges(node) { | ||
var this$1 = this; | ||
if (typeof node === 'undefined') { | ||
Object.keys(this.nodes) | ||
.forEach(function (id) { return this$1._computeNextCWEdges(this$1.nodes[id]); }); | ||
} else { | ||
node.getOuterEdges().forEach(function (edge, i) { | ||
node.getOuterEdge((i === 0 ? node.getOuterEdges().length : i) - 1).symetric.next = edge; | ||
}); | ||
} | ||
if (typeof node === "undefined") { | ||
Object.keys(this.nodes).forEach(function (id) { | ||
return this$1._computeNextCWEdges(this$1.nodes[id]); | ||
}); | ||
} else { | ||
node.getOuterEdges().forEach(function (edge, i) { | ||
node.getOuterEdge( | ||
(i === 0 ? node.getOuterEdges().length : i) - 1 | ||
).symetric.next = edge; | ||
}); | ||
} | ||
}; | ||
@@ -663,41 +756,49 @@ | ||
*/ | ||
Graph.prototype._computeNextCCWEdges = function _computeNextCCWEdges (node, label) { | ||
var edges = node.getOuterEdges(); | ||
var firstOutDE, | ||
prevInDE; | ||
Graph.prototype._computeNextCCWEdges = function _computeNextCCWEdges( | ||
node, | ||
label | ||
) { | ||
var edges = node.getOuterEdges(); | ||
var firstOutDE, prevInDE; | ||
for (var i = edges.length - 1; i >= 0; --i) { | ||
var de = edges[i], | ||
sym = de.symetric, | ||
outDE = (void 0), | ||
inDE = (void 0); | ||
for (var i = edges.length - 1; i >= 0; --i) { | ||
var de = edges[i], | ||
sym = de.symetric, | ||
outDE = void 0, | ||
inDE = void 0; | ||
if (de.label === label) | ||
{ outDE = de; } | ||
if (de.label === label) { | ||
outDE = de; | ||
} | ||
if (sym.label === label) | ||
{ inDE = sym; } | ||
if (sym.label === label) { | ||
inDE = sym; | ||
} | ||
if (!outDE || !inDE) // This edge is not in edgering | ||
{ continue; } | ||
if (!outDE || !inDE) { | ||
// This edge is not in edgering | ||
continue; | ||
} | ||
if (inDE) | ||
{ prevInDE = inDE; } | ||
if (inDE) { | ||
prevInDE = inDE; | ||
} | ||
if (outDE) { | ||
if (prevInDE) { | ||
prevInDE.next = outDE; | ||
prevInDE = undefined; | ||
} | ||
if (outDE) { | ||
if (prevInDE) { | ||
prevInDE.next = outDE; | ||
prevInDE = undefined; | ||
} | ||
if (!firstOutDE) | ||
{ firstOutDE = outDE; } | ||
} | ||
if (!firstOutDE) { | ||
firstOutDE = outDE; | ||
} | ||
} | ||
} | ||
if (prevInDE) | ||
{ prevInDE.next = firstOutDE; } | ||
if (prevInDE) { | ||
prevInDE.next = firstOutDE; | ||
} | ||
}; | ||
/** | ||
@@ -710,21 +811,22 @@ * Finds rings and labels edges according to which rings are. | ||
*/ | ||
Graph.prototype._findLabeledEdgeRings = function _findLabeledEdgeRings () { | ||
var edgeRingStarts = []; | ||
var label = 0; | ||
this.edges.forEach(function (edge) { | ||
if (edge.label >= 0) | ||
{ return; } | ||
Graph.prototype._findLabeledEdgeRings = function _findLabeledEdgeRings() { | ||
var edgeRingStarts = []; | ||
var label = 0; | ||
this.edges.forEach(function (edge) { | ||
if (edge.label >= 0) { | ||
return; | ||
} | ||
edgeRingStarts.push(edge); | ||
edgeRingStarts.push(edge); | ||
var e = edge; | ||
do { | ||
e.label = label; | ||
e = e.next; | ||
} while (!edge.isEqual(e)); | ||
var e = edge; | ||
do { | ||
e.label = label; | ||
e = e.next; | ||
} while (!edge.isEqual(e)); | ||
label++; | ||
}); | ||
label++; | ||
}); | ||
return edgeRingStarts; | ||
return edgeRingStarts; | ||
}; | ||
@@ -737,29 +839,30 @@ | ||
*/ | ||
Graph.prototype.getEdgeRings = function getEdgeRings () { | ||
var this$1 = this; | ||
Graph.prototype.getEdgeRings = function getEdgeRings() { | ||
var this$1 = this; | ||
this._computeNextCWEdges(); | ||
this._computeNextCWEdges(); | ||
// Clear labels | ||
this.edges.forEach(function (edge) { | ||
edge.label = undefined; | ||
}); | ||
// Clear labels | ||
this.edges.forEach(function (edge) { | ||
edge.label = undefined; | ||
}); | ||
this._findLabeledEdgeRings().forEach(function (edge) { | ||
// convertMaximalToMinimalEdgeRings | ||
this$1._findIntersectionNodes(edge).forEach(function (node) { | ||
this$1._computeNextCCWEdges(node, edge.label); | ||
}); | ||
this._findLabeledEdgeRings().forEach(function (edge) { | ||
// convertMaximalToMinimalEdgeRings | ||
this$1._findIntersectionNodes(edge).forEach(function (node) { | ||
this$1._computeNextCCWEdges(node, edge.label); | ||
}); | ||
}); | ||
var edgeRingList = []; | ||
var edgeRingList = []; | ||
// find all edgerings | ||
this.edges.forEach(function (edge) { | ||
if (edge.ring) | ||
{ return; } | ||
edgeRingList.push(this$1._findEdgeRing(edge)); | ||
}); | ||
// find all edgerings | ||
this.edges.forEach(function (edge) { | ||
if (edge.ring) { | ||
return; | ||
} | ||
edgeRingList.push(this$1._findEdgeRing(edge)); | ||
}); | ||
return edgeRingList; | ||
return edgeRingList; | ||
}; | ||
@@ -773,24 +876,28 @@ | ||
*/ | ||
Graph.prototype._findIntersectionNodes = function _findIntersectionNodes (startEdge) { | ||
var intersectionNodes = []; | ||
var edge = startEdge; | ||
var loop = function () { | ||
// getDegree | ||
var degree = 0; | ||
edge.from.getOuterEdges().forEach(function (e) { | ||
if (e.label === startEdge.label) | ||
{ ++degree; } | ||
}); | ||
Graph.prototype._findIntersectionNodes = function _findIntersectionNodes( | ||
startEdge | ||
) { | ||
var intersectionNodes = []; | ||
var edge = startEdge; | ||
var loop = function () { | ||
// getDegree | ||
var degree = 0; | ||
edge.from.getOuterEdges().forEach(function (e) { | ||
if (e.label === startEdge.label) { | ||
++degree; | ||
} | ||
}); | ||
if (degree > 1) | ||
{ intersectionNodes.push(edge.from); } | ||
if (degree > 1) { | ||
intersectionNodes.push(edge.from); | ||
} | ||
edge = edge.next; | ||
}; | ||
edge = edge.next; | ||
}; | ||
do { | ||
loop(); | ||
} while (!startEdge.isEqual(edge)); | ||
do { | ||
loop(); | ||
} while (!startEdge.isEqual(edge)); | ||
return intersectionNodes; | ||
return intersectionNodes; | ||
}; | ||
@@ -804,13 +911,13 @@ | ||
*/ | ||
Graph.prototype._findEdgeRing = function _findEdgeRing (startEdge) { | ||
var edge = startEdge; | ||
var edgeRing = new EdgeRing(); | ||
Graph.prototype._findEdgeRing = function _findEdgeRing(startEdge) { | ||
var edge = startEdge; | ||
var edgeRing = new EdgeRing(); | ||
do { | ||
edgeRing.push(edge); | ||
edge.ring = edgeRing; | ||
edge = edge.next; | ||
} while (!startEdge.isEqual(edge)); | ||
do { | ||
edgeRing.push(edge); | ||
edge.ring = edgeRing; | ||
edge = edge.next; | ||
} while (!startEdge.isEqual(edge)); | ||
return edgeRing; | ||
return edgeRing; | ||
}; | ||
@@ -824,8 +931,12 @@ | ||
*/ | ||
Graph.prototype.removeNode = function removeNode (node) { | ||
var this$1 = this; | ||
Graph.prototype.removeNode = function removeNode(node) { | ||
var this$1 = this; | ||
node.getOuterEdges().forEach(function (edge) { return this$1.removeEdge(edge); }); | ||
node.innerEdges.forEach(function (edge) { return this$1.removeEdge(edge); }); | ||
delete this.nodes[node.id]; | ||
node.getOuterEdges().forEach(function (edge) { | ||
return this$1.removeEdge(edge); | ||
}); | ||
node.innerEdges.forEach(function (edge) { | ||
return this$1.removeEdge(edge); | ||
}); | ||
delete this.nodes[node.id]; | ||
}; | ||
@@ -838,5 +949,7 @@ | ||
*/ | ||
Graph.prototype.removeEdge = function removeEdge (edge) { | ||
this.edges = this.edges.filter(function (e) { return !e.isEqual(edge); }); | ||
edge.deleteEdge(); | ||
Graph.prototype.removeEdge = function removeEdge(edge) { | ||
this.edges = this.edges.filter(function (e) { | ||
return !e.isEqual(edge); | ||
}); | ||
edge.deleteEdge(); | ||
}; | ||
@@ -863,33 +976,42 @@ | ||
function polygonize(geoJson) { | ||
var graph = Graph.fromGeoJson(geoJson); | ||
var graph = Graph.fromGeoJson(geoJson); | ||
// 1. Remove dangle node | ||
graph.deleteDangles(); | ||
// 1. Remove dangle node | ||
graph.deleteDangles(); | ||
// 2. Remove cut-edges (bridge edges) | ||
graph.deleteCutEdges(); | ||
// 2. Remove cut-edges (bridge edges) | ||
graph.deleteCutEdges(); | ||
// 3. Get all holes and shells | ||
var holes = [], | ||
shells = []; | ||
// 3. Get all holes and shells | ||
var holes = [], | ||
shells = []; | ||
graph.getEdgeRings() | ||
.filter(function (edgeRing) { return edgeRing.isValid(); }) | ||
.forEach(function (edgeRing) { | ||
if (edgeRing.isHole()) | ||
{ holes.push(edgeRing); } | ||
else | ||
{ shells.push(edgeRing); } | ||
}); | ||
// 4. Assign Holes to Shells | ||
holes.forEach(function (hole) { | ||
if (EdgeRing.findEdgeRingContaining(hole, shells)) | ||
{ shells.push(hole); } | ||
graph | ||
.getEdgeRings() | ||
.filter(function (edgeRing) { | ||
return edgeRing.isValid(); | ||
}) | ||
.forEach(function (edgeRing) { | ||
if (edgeRing.isHole()) { | ||
holes.push(edgeRing); | ||
} else { | ||
shells.push(edgeRing); | ||
} | ||
}); | ||
// 5. EdgeRings to Polygons | ||
return featureCollection(shells.map(function (shell) { return shell.toPolygon(); })); | ||
// 4. Assign Holes to Shells | ||
holes.forEach(function (hole) { | ||
if (EdgeRing.findEdgeRingContaining(hole, shells)) { | ||
shells.push(hole); | ||
} | ||
}); | ||
// 5. EdgeRings to Polygons | ||
return featureCollection( | ||
shells.map(function (shell) { | ||
return shell.toPolygon(); | ||
}) | ||
); | ||
} | ||
export default polygonize; |
@@ -26,8 +26,8 @@ 'use strict'; | ||
function orientationIndex(p1, p2, q) { | ||
var dx1 = p2[0] - p1[0], | ||
dy1 = p2[1] - p1[1], | ||
dx2 = q[0] - p2[0], | ||
dy2 = q[1] - p2[1]; | ||
var dx1 = p2[0] - p1[0], | ||
dy1 = p2[1] - p1[1], | ||
dx2 = q[0] - p2[0], | ||
dy2 = q[1] - p2[1]; | ||
return Math.sign(dx1 * dy2 - dx2 * dy1); | ||
return Math.sign(dx1 * dy2 - dx2 * dy1); | ||
} | ||
@@ -45,11 +45,21 @@ | ||
function envelopeIsEqual(env1, env2) { | ||
var envX1 = env1.geometry.coordinates.map(function (c) { return c[0]; }), | ||
envY1 = env1.geometry.coordinates.map(function (c) { return c[1]; }), | ||
envX2 = env2.geometry.coordinates.map(function (c) { return c[0]; }), | ||
envY2 = env2.geometry.coordinates.map(function (c) { return c[1]; }); | ||
var envX1 = env1.geometry.coordinates.map(function (c) { | ||
return c[0]; | ||
}), | ||
envY1 = env1.geometry.coordinates.map(function (c) { | ||
return c[1]; | ||
}), | ||
envX2 = env2.geometry.coordinates.map(function (c) { | ||
return c[0]; | ||
}), | ||
envY2 = env2.geometry.coordinates.map(function (c) { | ||
return c[1]; | ||
}); | ||
return Math.max(null, envX1) === Math.max(null, envX2) && | ||
return ( | ||
Math.max(null, envX1) === Math.max(null, envX2) && | ||
Math.max(null, envY1) === Math.max(null, envY2) && | ||
Math.min(null, envX1) === Math.min(null, envX2) && | ||
Math.min(null, envY1) === Math.min(null, envY2); | ||
Math.min(null, envY1) === Math.min(null, envY2) | ||
); | ||
} | ||
@@ -69,3 +79,5 @@ | ||
function envelopeContains(self, env) { | ||
return env.geometry.coordinates[0].every(function (c) { return booleanPointInPolygon(helpers.point(c), self); }); | ||
return env.geometry.coordinates[0].every(function (c) { | ||
return booleanPointInPolygon(helpers.point(c), self); | ||
}); | ||
} | ||
@@ -81,3 +93,3 @@ | ||
function coordinatesEqual(coord1, coord2) { | ||
return coord1[0] === coord2[0] && coord1[1] === coord2[1]; | ||
return coord1[0] === coord2[0] && coord1[1] === coord2[1]; | ||
} | ||
@@ -89,21 +101,25 @@ | ||
var Node = function Node(coordinates) { | ||
this.id = Node.buildId(coordinates); | ||
this.coordinates = coordinates; //< {Number[]} | ||
this.innerEdges = []; //< {Edge[]} | ||
this.id = Node.buildId(coordinates); | ||
this.coordinates = coordinates; //< {Number[]} | ||
this.innerEdges = []; //< {Edge[]} | ||
// We wil store to (out) edges in an CCW order as geos::planargraph::DirectedEdgeStar does | ||
this.outerEdges = []; //< {Edge[]} | ||
this.outerEdgesSorted = false; //< {Boolean} flag that stores if the outer Edges had been sorted | ||
// We wil store to (out) edges in an CCW order as geos::planargraph::DirectedEdgeStar does | ||
this.outerEdges = []; //< {Edge[]} | ||
this.outerEdgesSorted = false; //< {Boolean} flag that stores if the outer Edges had been sorted | ||
}; | ||
Node.buildId = function buildId (coordinates) { | ||
return coordinates.join(','); | ||
Node.buildId = function buildId(coordinates) { | ||
return coordinates.join(","); | ||
}; | ||
Node.prototype.removeInnerEdge = function removeInnerEdge (edge) { | ||
this.innerEdges = this.innerEdges.filter(function (e) { return e.from.id !== edge.from.id; }); | ||
Node.prototype.removeInnerEdge = function removeInnerEdge(edge) { | ||
this.innerEdges = this.innerEdges.filter(function (e) { | ||
return e.from.id !== edge.from.id; | ||
}); | ||
}; | ||
Node.prototype.removeOuterEdge = function removeOuterEdge (edge) { | ||
this.outerEdges = this.outerEdges.filter(function (e) { return e.to.id !== edge.to.id; }); | ||
Node.prototype.removeOuterEdge = function removeOuterEdge(edge) { | ||
this.outerEdges = this.outerEdges.filter(function (e) { | ||
return e.to.id !== edge.to.id; | ||
}); | ||
}; | ||
@@ -117,5 +133,5 @@ | ||
*/ | ||
Node.prototype.addOuterEdge = function addOuterEdge (edge) { | ||
this.outerEdges.push(edge); | ||
this.outerEdgesSorted = false; | ||
Node.prototype.addOuterEdge = function addOuterEdge(edge) { | ||
this.outerEdges.push(edge); | ||
this.outerEdgesSorted = false; | ||
}; | ||
@@ -129,36 +145,61 @@ | ||
*/ | ||
Node.prototype.sortOuterEdges = function sortOuterEdges () { | ||
var this$1 = this; | ||
Node.prototype.sortOuterEdges = function sortOuterEdges() { | ||
var this$1 = this; | ||
if (!this.outerEdgesSorted) { | ||
//this.outerEdges.sort((a, b) => a.compareTo(b)); | ||
// Using this comparator in order to be deterministic | ||
this.outerEdges.sort(function (a, b) { | ||
var aNode = a.to, | ||
bNode = b.to; | ||
if (!this.outerEdgesSorted) { | ||
//this.outerEdges.sort((a, b) => a.compareTo(b)); | ||
// Using this comparator in order to be deterministic | ||
this.outerEdges.sort(function (a, b) { | ||
var aNode = a.to, | ||
bNode = b.to; | ||
if (aNode.coordinates[0] - this$1.coordinates[0] >= 0 && bNode.coordinates[0] - this$1.coordinates[0] < 0) | ||
{ return 1; } | ||
if (aNode.coordinates[0] - this$1.coordinates[0] < 0 && bNode.coordinates[0] - this$1.coordinates[0] >= 0) | ||
{ return -1; } | ||
if ( | ||
aNode.coordinates[0] - this$1.coordinates[0] >= 0 && | ||
bNode.coordinates[0] - this$1.coordinates[0] < 0 | ||
) { | ||
return 1; | ||
} | ||
if ( | ||
aNode.coordinates[0] - this$1.coordinates[0] < 0 && | ||
bNode.coordinates[0] - this$1.coordinates[0] >= 0 | ||
) { | ||
return -1; | ||
} | ||
if (aNode.coordinates[0] - this$1.coordinates[0] === 0 && bNode.coordinates[0] - this$1.coordinates[0] === 0) { | ||
if (aNode.coordinates[1] - this$1.coordinates[1] >= 0 || bNode.coordinates[1] - this$1.coordinates[1] >= 0) | ||
{ return aNode.coordinates[1] - bNode.coordinates[1]; } | ||
return bNode.coordinates[1] - aNode.coordinates[1]; | ||
} | ||
if ( | ||
aNode.coordinates[0] - this$1.coordinates[0] === 0 && | ||
bNode.coordinates[0] - this$1.coordinates[0] === 0 | ||
) { | ||
if ( | ||
aNode.coordinates[1] - this$1.coordinates[1] >= 0 || | ||
bNode.coordinates[1] - this$1.coordinates[1] >= 0 | ||
) { | ||
return aNode.coordinates[1] - bNode.coordinates[1]; | ||
} | ||
return bNode.coordinates[1] - aNode.coordinates[1]; | ||
} | ||
var det = orientationIndex(this$1.coordinates, aNode.coordinates, bNode.coordinates); | ||
if (det < 0) | ||
{ return 1; } | ||
if (det > 0) | ||
{ return -1; } | ||
var det = orientationIndex( | ||
this$1.coordinates, | ||
aNode.coordinates, | ||
bNode.coordinates | ||
); | ||
if (det < 0) { | ||
return 1; | ||
} | ||
if (det > 0) { | ||
return -1; | ||
} | ||
var d1 = Math.pow(aNode.coordinates[0] - this$1.coordinates[0], 2) + Math.pow(aNode.coordinates[1] - this$1.coordinates[1], 2), | ||
d2 = Math.pow(bNode.coordinates[0] - this$1.coordinates[0], 2) + Math.pow(bNode.coordinates[1] - this$1.coordinates[1], 2); | ||
var d1 = | ||
Math.pow(aNode.coordinates[0] - this$1.coordinates[0], 2) + | ||
Math.pow(aNode.coordinates[1] - this$1.coordinates[1], 2), | ||
d2 = | ||
Math.pow(bNode.coordinates[0] - this$1.coordinates[0], 2) + | ||
Math.pow(bNode.coordinates[1] - this$1.coordinates[1], 2); | ||
return d1 - d2; | ||
}); | ||
this.outerEdgesSorted = true; | ||
} | ||
return d1 - d2; | ||
}); | ||
this.outerEdgesSorted = true; | ||
} | ||
}; | ||
@@ -174,14 +215,14 @@ | ||
*/ | ||
Node.prototype.getOuterEdges = function getOuterEdges () { | ||
this.sortOuterEdges(); | ||
return this.outerEdges; | ||
Node.prototype.getOuterEdges = function getOuterEdges() { | ||
this.sortOuterEdges(); | ||
return this.outerEdges; | ||
}; | ||
Node.prototype.getOuterEdge = function getOuterEdge (i) { | ||
this.sortOuterEdges(); | ||
return this.outerEdges[i]; | ||
Node.prototype.getOuterEdge = function getOuterEdge(i) { | ||
this.sortOuterEdges(); | ||
return this.outerEdges[i]; | ||
}; | ||
Node.prototype.addInnerEdge = function addInnerEdge (edge) { | ||
this.innerEdges.push(edge); | ||
Node.prototype.addInnerEdge = function addInnerEdge(edge) { | ||
this.innerEdges.push(edge); | ||
}; | ||
@@ -193,12 +234,12 @@ | ||
var Edge = function Edge(from, to) { | ||
this.from = from; //< start | ||
this.to = to; //< End | ||
this.from = from; //< start | ||
this.to = to; //< End | ||
this.next = undefined; //< The edge to be computed after | ||
this.label = undefined; //< Used in order to detect Cut Edges (Bridges) | ||
this.symetric = undefined; //< The symetric edge of this | ||
this.ring = undefined; //< EdgeRing in which the Edge is | ||
this.next = undefined; //< The edge to be computed after | ||
this.label = undefined; //< Used in order to detect Cut Edges (Bridges) | ||
this.symetric = undefined; //< The symetric edge of this | ||
this.ring = undefined; //< EdgeRing in which the Edge is | ||
this.from.addOuterEdge(this); | ||
this.to.addInnerEdge(this); | ||
this.from.addOuterEdge(this); | ||
this.to.addInnerEdge(this); | ||
}; | ||
@@ -209,14 +250,14 @@ | ||
*/ | ||
Edge.prototype.getSymetric = function getSymetric () { | ||
if (!this.symetric) { | ||
this.symetric = new Edge(this.to, this.from); | ||
this.symetric.symetric = this; | ||
} | ||
Edge.prototype.getSymetric = function getSymetric() { | ||
if (!this.symetric) { | ||
this.symetric = new Edge(this.to, this.from); | ||
this.symetric.symetric = this; | ||
} | ||
return this.symetric; | ||
return this.symetric; | ||
}; | ||
Edge.prototype.deleteEdge = function deleteEdge () { | ||
this.from.removeOuterEdge(this); | ||
this.to.removeInnerEdge(this); | ||
Edge.prototype.deleteEdge = function deleteEdge() { | ||
this.from.removeOuterEdge(this); | ||
this.to.removeInnerEdge(this); | ||
}; | ||
@@ -232,8 +273,8 @@ | ||
*/ | ||
Edge.prototype.isEqual = function isEqual (edge) { | ||
return this.from.id === edge.from.id && this.to.id === edge.to.id; | ||
Edge.prototype.isEqual = function isEqual(edge) { | ||
return this.from.id === edge.from.id && this.to.id === edge.to.id; | ||
}; | ||
Edge.prototype.toString = function toString () { | ||
return ("Edge { " + (this.from.id) + " -> " + (this.to.id) + " }"); | ||
Edge.prototype.toString = function toString() { | ||
return "Edge { " + this.from.id + " -> " + this.to.id + " }"; | ||
}; | ||
@@ -246,4 +287,4 @@ | ||
*/ | ||
Edge.prototype.toLineString = function toLineString () { | ||
return helpers.lineString([this.from.coordinates, this.to.coordinates]); | ||
Edge.prototype.toLineString = function toLineString() { | ||
return helpers.lineString([this.from.coordinates, this.to.coordinates]); | ||
}; | ||
@@ -261,4 +302,8 @@ | ||
*/ | ||
Edge.prototype.compareTo = function compareTo (edge) { | ||
return orientationIndex(edge.from.coordinates, edge.to.coordinates, this.to.coordinates); | ||
Edge.prototype.compareTo = function compareTo(edge) { | ||
return orientationIndex( | ||
edge.from.coordinates, | ||
edge.to.coordinates, | ||
this.to.coordinates | ||
); | ||
}; | ||
@@ -274,5 +319,5 @@ | ||
var EdgeRing = function EdgeRing() { | ||
this.edges = []; | ||
this.polygon = undefined; //< Caches Polygon representation | ||
this.envelope = undefined; //< Caches Envelope representation | ||
this.edges = []; | ||
this.polygon = undefined; //< Caches Polygon representation | ||
this.envelope = undefined; //< Caches Envelope representation | ||
}; | ||
@@ -288,7 +333,7 @@ | ||
*/ | ||
EdgeRing.prototype.push = function push (edge) { | ||
// Emulate Array getter ([]) behaviour | ||
this[this.edges.length] = edge; | ||
this.edges.push(edge); | ||
this.polygon = this.envelope = undefined; | ||
EdgeRing.prototype.push = function push(edge) { | ||
// Emulate Array getter ([]) behaviour | ||
this[this.edges.length] = edge; | ||
this.edges.push(edge); | ||
this.polygon = this.envelope = undefined; | ||
}; | ||
@@ -303,4 +348,4 @@ | ||
*/ | ||
EdgeRing.prototype.get = function get (i) { | ||
return this.edges[i]; | ||
EdgeRing.prototype.get = function get(i) { | ||
return this.edges[i]; | ||
}; | ||
@@ -315,3 +360,3 @@ | ||
prototypeAccessors.length.get = function () { | ||
return this.edges.length; | ||
return this.edges.length; | ||
}; | ||
@@ -325,4 +370,4 @@ | ||
*/ | ||
EdgeRing.prototype.forEach = function forEach (f) { | ||
this.edges.forEach(f); | ||
EdgeRing.prototype.forEach = function forEach(f) { | ||
this.edges.forEach(f); | ||
}; | ||
@@ -337,4 +382,4 @@ | ||
*/ | ||
EdgeRing.prototype.map = function map (f) { | ||
return this.edges.map(f); | ||
EdgeRing.prototype.map = function map(f) { | ||
return this.edges.map(f); | ||
}; | ||
@@ -349,4 +394,4 @@ | ||
*/ | ||
EdgeRing.prototype.some = function some (f) { | ||
return this.edges.some(f); | ||
EdgeRing.prototype.some = function some(f) { | ||
return this.edges.some(f); | ||
}; | ||
@@ -364,5 +409,5 @@ | ||
*/ | ||
EdgeRing.prototype.isValid = function isValid () { | ||
// TODO: stub | ||
return true; | ||
EdgeRing.prototype.isValid = function isValid() { | ||
// TODO: stub | ||
return true; | ||
}; | ||
@@ -379,19 +424,28 @@ | ||
*/ | ||
EdgeRing.prototype.isHole = function isHole () { | ||
var this$1 = this; | ||
EdgeRing.prototype.isHole = function isHole() { | ||
var this$1 = this; | ||
// XXX: Assuming Ring is valid | ||
// Find highest point | ||
var hiIndex = this.edges.reduce(function (high, edge, i) { | ||
if (edge.from.coordinates[1] > this$1.edges[high].from.coordinates[1]) | ||
{ high = i; } | ||
return high; | ||
}, 0), | ||
iPrev = (hiIndex === 0 ? this.length : hiIndex) - 1, | ||
iNext = (hiIndex + 1) % this.length, | ||
disc = orientationIndex(this.edges[iPrev].from.coordinates, this.edges[hiIndex].from.coordinates, this.edges[iNext].from.coordinates); | ||
// XXX: Assuming Ring is valid | ||
// Find highest point | ||
var hiIndex = this.edges.reduce(function (high, edge, i) { | ||
if (edge.from.coordinates[1] > this$1.edges[high].from.coordinates[1]) { | ||
high = i; | ||
} | ||
return high; | ||
}, 0), | ||
iPrev = (hiIndex === 0 ? this.length : hiIndex) - 1, | ||
iNext = (hiIndex + 1) % this.length, | ||
disc = orientationIndex( | ||
this.edges[iPrev].from.coordinates, | ||
this.edges[hiIndex].from.coordinates, | ||
this.edges[iNext].from.coordinates | ||
); | ||
if (disc === 0) | ||
{ return this.edges[iPrev].from.coordinates[0] > this.edges[iNext].from.coordinates[0]; } | ||
return disc > 0; | ||
if (disc === 0) { | ||
return ( | ||
this.edges[iPrev].from.coordinates[0] > | ||
this.edges[iNext].from.coordinates[0] | ||
); | ||
} | ||
return disc > 0; | ||
}; | ||
@@ -405,4 +459,8 @@ | ||
*/ | ||
EdgeRing.prototype.toMultiPoint = function toMultiPoint () { | ||
return helpers.multiPoint(this.edges.map(function (edge) { return edge.from.coordinates; })); | ||
EdgeRing.prototype.toMultiPoint = function toMultiPoint() { | ||
return helpers.multiPoint( | ||
this.edges.map(function (edge) { | ||
return edge.from.coordinates; | ||
}) | ||
); | ||
}; | ||
@@ -416,8 +474,11 @@ | ||
*/ | ||
EdgeRing.prototype.toPolygon = function toPolygon () { | ||
if (this.polygon) | ||
{ return this.polygon; } | ||
var coordinates = this.edges.map(function (edge) { return edge.from.coordinates; }); | ||
coordinates.push(this.edges[0].from.coordinates); | ||
return (this.polygon = helpers.polygon([coordinates])); | ||
EdgeRing.prototype.toPolygon = function toPolygon() { | ||
if (this.polygon) { | ||
return this.polygon; | ||
} | ||
var coordinates = this.edges.map(function (edge) { | ||
return edge.from.coordinates; | ||
}); | ||
coordinates.push(this.edges[0].from.coordinates); | ||
return (this.polygon = helpers.polygon([coordinates])); | ||
}; | ||
@@ -431,6 +492,7 @@ | ||
*/ | ||
EdgeRing.prototype.getEnvelope = function getEnvelope () { | ||
if (this.envelope) | ||
{ return this.envelope; } | ||
return (this.envelope = envelope(this.toPolygon())); | ||
EdgeRing.prototype.getEnvelope = function getEnvelope() { | ||
if (this.envelope) { | ||
return this.envelope; | ||
} | ||
return (this.envelope = envelope(this.toPolygon())); | ||
}; | ||
@@ -446,29 +508,41 @@ | ||
*/ | ||
EdgeRing.findEdgeRingContaining = function findEdgeRingContaining (testEdgeRing, shellList) { | ||
var testEnvelope = testEdgeRing.getEnvelope(); | ||
EdgeRing.findEdgeRingContaining = function findEdgeRingContaining( | ||
testEdgeRing, | ||
shellList | ||
) { | ||
var testEnvelope = testEdgeRing.getEnvelope(); | ||
var minEnvelope, | ||
minShell; | ||
shellList.forEach(function (shell) { | ||
var tryEnvelope = shell.getEnvelope(); | ||
var minEnvelope, minShell; | ||
shellList.forEach(function (shell) { | ||
var tryEnvelope = shell.getEnvelope(); | ||
if (minShell) | ||
{ minEnvelope = minShell.getEnvelope(); } | ||
if (minShell) { | ||
minEnvelope = minShell.getEnvelope(); | ||
} | ||
// the hole envelope cannot equal the shell envelope | ||
if (envelopeIsEqual(tryEnvelope, testEnvelope)) | ||
{ return; } | ||
// the hole envelope cannot equal the shell envelope | ||
if (envelopeIsEqual(tryEnvelope, testEnvelope)) { | ||
return; | ||
} | ||
if (envelopeContains(tryEnvelope, testEnvelope)) { | ||
var testPoint = testEdgeRing.map(function (edge) { return edge.from.coordinates; }) | ||
.find(function (pt) { return !shell.some(function (edge) { return coordinatesEqual(pt, edge.from.coordinates); }); }); | ||
if (envelopeContains(tryEnvelope, testEnvelope)) { | ||
var testPoint = testEdgeRing | ||
.map(function (edge) { | ||
return edge.from.coordinates; | ||
}) | ||
.find(function (pt) { | ||
return !shell.some(function (edge) { | ||
return coordinatesEqual(pt, edge.from.coordinates); | ||
}); | ||
}); | ||
if (testPoint && shell.inside(helpers.point(testPoint))) { | ||
if (!minShell || envelopeContains(minEnvelope, tryEnvelope)) | ||
{ minShell = shell; } | ||
} | ||
if (testPoint && shell.inside(helpers.point(testPoint))) { | ||
if (!minShell || envelopeContains(minEnvelope, tryEnvelope)) { | ||
minShell = shell; | ||
} | ||
}); | ||
} | ||
} | ||
}); | ||
return minShell; | ||
return minShell; | ||
}; | ||
@@ -482,7 +556,7 @@ | ||
*/ | ||
EdgeRing.prototype.inside = function inside (pt) { | ||
return booleanPointInPolygon(pt, this.toPolygon()); | ||
EdgeRing.prototype.inside = function inside(pt) { | ||
return booleanPointInPolygon(pt, this.toPolygon()); | ||
}; | ||
Object.defineProperties( EdgeRing.prototype, prototypeAccessors ); | ||
Object.defineProperties(EdgeRing.prototype, prototypeAccessors); | ||
@@ -496,12 +570,19 @@ /** | ||
function validateGeoJson(geoJson) { | ||
if (!geoJson) | ||
{ throw new Error('No geojson passed'); } | ||
if (!geoJson) { | ||
throw new Error("No geojson passed"); | ||
} | ||
if (geoJson.type !== 'FeatureCollection' && | ||
geoJson.type !== 'GeometryCollection' && | ||
geoJson.type !== 'MultiLineString' && | ||
geoJson.type !== 'LineString' && | ||
geoJson.type !== 'Feature' | ||
) | ||
{ throw new Error(("Invalid input type '" + (geoJson.type) + "'. Geojson must be FeatureCollection, GeometryCollection, LineString, MultiLineString or Feature")); } | ||
if ( | ||
geoJson.type !== "FeatureCollection" && | ||
geoJson.type !== "GeometryCollection" && | ||
geoJson.type !== "MultiLineString" && | ||
geoJson.type !== "LineString" && | ||
geoJson.type !== "Feature" | ||
) { | ||
throw new Error( | ||
"Invalid input type '" + | ||
geoJson.type + | ||
"'. Geojson must be FeatureCollection, GeometryCollection, LineString, MultiLineString or Feature" | ||
); | ||
} | ||
} | ||
@@ -519,6 +600,6 @@ | ||
var Graph = function Graph() { | ||
this.edges = []; //< {Edge[]} dirEdges | ||
this.edges = []; //< {Edge[]} dirEdges | ||
// The key is the `id` of the Node (ie: coordinates.join(',')) | ||
this.nodes = {}; | ||
// The key is the `id` of the Node (ie: coordinates.join(',')) | ||
this.nodes = {}; | ||
}; | ||
@@ -529,21 +610,21 @@ | ||
*/ | ||
Graph.fromGeoJson = function fromGeoJson (geoJson) { | ||
validateGeoJson(geoJson); | ||
Graph.fromGeoJson = function fromGeoJson(geoJson) { | ||
validateGeoJson(geoJson); | ||
var graph = new Graph(); | ||
meta.flattenEach(geoJson, function (feature) { | ||
invariant.featureOf(feature, 'LineString', 'Graph::fromGeoJson'); | ||
// When a LineString if formed by many segments, split them | ||
meta.coordReduce(feature, function (prev, cur) { | ||
if (prev) { | ||
var start = graph.getNode(prev), | ||
end = graph.getNode(cur); | ||
var graph = new Graph(); | ||
meta.flattenEach(geoJson, function (feature) { | ||
invariant.featureOf(feature, "LineString", "Graph::fromGeoJson"); | ||
// When a LineString if formed by many segments, split them | ||
meta.coordReduce(feature, function (prev, cur) { | ||
if (prev) { | ||
var start = graph.getNode(prev), | ||
end = graph.getNode(cur); | ||
graph.addEdge(start, end); | ||
} | ||
return cur; | ||
}); | ||
graph.addEdge(start, end); | ||
} | ||
return cur; | ||
}); | ||
}); | ||
return graph; | ||
return graph; | ||
}; | ||
@@ -557,9 +638,10 @@ | ||
*/ | ||
Graph.prototype.getNode = function getNode (coordinates) { | ||
var id = Node.buildId(coordinates); | ||
var node = this.nodes[id]; | ||
if (!node) | ||
{ node = this.nodes[id] = new Node(coordinates); } | ||
Graph.prototype.getNode = function getNode(coordinates) { | ||
var id = Node.buildId(coordinates); | ||
var node = this.nodes[id]; | ||
if (!node) { | ||
node = this.nodes[id] = new Node(coordinates); | ||
} | ||
return node; | ||
return node; | ||
}; | ||
@@ -575,16 +657,20 @@ | ||
*/ | ||
Graph.prototype.addEdge = function addEdge (from, to) { | ||
var edge = new Edge(from, to), | ||
symetricEdge = edge.getSymetric(); | ||
Graph.prototype.addEdge = function addEdge(from, to) { | ||
var edge = new Edge(from, to), | ||
symetricEdge = edge.getSymetric(); | ||
this.edges.push(edge); | ||
this.edges.push(symetricEdge); | ||
this.edges.push(edge); | ||
this.edges.push(symetricEdge); | ||
}; | ||
Graph.prototype.deleteDangles = function deleteDangles () { | ||
var this$1 = this; | ||
Graph.prototype.deleteDangles = function deleteDangles() { | ||
var this$1 = this; | ||
Object.keys(this.nodes) | ||
.map(function (id) { return this$1.nodes[id]; }) | ||
.forEach(function (node) { return this$1._removeIfDangle(node); }); | ||
Object.keys(this.nodes) | ||
.map(function (id) { | ||
return this$1.nodes[id]; | ||
}) | ||
.forEach(function (node) { | ||
return this$1._removeIfDangle(node); | ||
}); | ||
}; | ||
@@ -599,11 +685,15 @@ | ||
*/ | ||
Graph.prototype._removeIfDangle = function _removeIfDangle (node) { | ||
var this$1 = this; | ||
Graph.prototype._removeIfDangle = function _removeIfDangle(node) { | ||
var this$1 = this; | ||
// As edges are directed and symetrical, we count only innerEdges | ||
if (node.innerEdges.length <= 1) { | ||
var outerNodes = node.getOuterEdges().map(function (e) { return e.to; }); | ||
this.removeNode(node); | ||
outerNodes.forEach(function (n) { return this$1._removeIfDangle(n); }); | ||
} | ||
// As edges are directed and symetrical, we count only innerEdges | ||
if (node.innerEdges.length <= 1) { | ||
var outerNodes = node.getOuterEdges().map(function (e) { | ||
return e.to; | ||
}); | ||
this.removeNode(node); | ||
outerNodes.forEach(function (n) { | ||
return this$1._removeIfDangle(n); | ||
}); | ||
} | ||
}; | ||
@@ -618,15 +708,15 @@ | ||
*/ | ||
Graph.prototype.deleteCutEdges = function deleteCutEdges () { | ||
var this$1 = this; | ||
Graph.prototype.deleteCutEdges = function deleteCutEdges() { | ||
var this$1 = this; | ||
this._computeNextCWEdges(); | ||
this._findLabeledEdgeRings(); | ||
this._computeNextCWEdges(); | ||
this._findLabeledEdgeRings(); | ||
// Cut-edges (bridges) are edges where both edges have the same label | ||
this.edges.forEach(function (edge) { | ||
if (edge.label === edge.symetric.label) { | ||
this$1.removeEdge(edge.symetric); | ||
this$1.removeEdge(edge); | ||
} | ||
}); | ||
// Cut-edges (bridges) are edges where both edges have the same label | ||
this.edges.forEach(function (edge) { | ||
if (edge.label === edge.symetric.label) { | ||
this$1.removeEdge(edge.symetric); | ||
this$1.removeEdge(edge); | ||
} | ||
}); | ||
}; | ||
@@ -642,13 +732,16 @@ | ||
*/ | ||
Graph.prototype._computeNextCWEdges = function _computeNextCWEdges (node) { | ||
var this$1 = this; | ||
Graph.prototype._computeNextCWEdges = function _computeNextCWEdges(node) { | ||
var this$1 = this; | ||
if (typeof node === 'undefined') { | ||
Object.keys(this.nodes) | ||
.forEach(function (id) { return this$1._computeNextCWEdges(this$1.nodes[id]); }); | ||
} else { | ||
node.getOuterEdges().forEach(function (edge, i) { | ||
node.getOuterEdge((i === 0 ? node.getOuterEdges().length : i) - 1).symetric.next = edge; | ||
}); | ||
} | ||
if (typeof node === "undefined") { | ||
Object.keys(this.nodes).forEach(function (id) { | ||
return this$1._computeNextCWEdges(this$1.nodes[id]); | ||
}); | ||
} else { | ||
node.getOuterEdges().forEach(function (edge, i) { | ||
node.getOuterEdge( | ||
(i === 0 ? node.getOuterEdges().length : i) - 1 | ||
).symetric.next = edge; | ||
}); | ||
} | ||
}; | ||
@@ -667,41 +760,49 @@ | ||
*/ | ||
Graph.prototype._computeNextCCWEdges = function _computeNextCCWEdges (node, label) { | ||
var edges = node.getOuterEdges(); | ||
var firstOutDE, | ||
prevInDE; | ||
Graph.prototype._computeNextCCWEdges = function _computeNextCCWEdges( | ||
node, | ||
label | ||
) { | ||
var edges = node.getOuterEdges(); | ||
var firstOutDE, prevInDE; | ||
for (var i = edges.length - 1; i >= 0; --i) { | ||
var de = edges[i], | ||
sym = de.symetric, | ||
outDE = (void 0), | ||
inDE = (void 0); | ||
for (var i = edges.length - 1; i >= 0; --i) { | ||
var de = edges[i], | ||
sym = de.symetric, | ||
outDE = void 0, | ||
inDE = void 0; | ||
if (de.label === label) | ||
{ outDE = de; } | ||
if (de.label === label) { | ||
outDE = de; | ||
} | ||
if (sym.label === label) | ||
{ inDE = sym; } | ||
if (sym.label === label) { | ||
inDE = sym; | ||
} | ||
if (!outDE || !inDE) // This edge is not in edgering | ||
{ continue; } | ||
if (!outDE || !inDE) { | ||
// This edge is not in edgering | ||
continue; | ||
} | ||
if (inDE) | ||
{ prevInDE = inDE; } | ||
if (inDE) { | ||
prevInDE = inDE; | ||
} | ||
if (outDE) { | ||
if (prevInDE) { | ||
prevInDE.next = outDE; | ||
prevInDE = undefined; | ||
} | ||
if (outDE) { | ||
if (prevInDE) { | ||
prevInDE.next = outDE; | ||
prevInDE = undefined; | ||
} | ||
if (!firstOutDE) | ||
{ firstOutDE = outDE; } | ||
} | ||
if (!firstOutDE) { | ||
firstOutDE = outDE; | ||
} | ||
} | ||
} | ||
if (prevInDE) | ||
{ prevInDE.next = firstOutDE; } | ||
if (prevInDE) { | ||
prevInDE.next = firstOutDE; | ||
} | ||
}; | ||
/** | ||
@@ -714,21 +815,22 @@ * Finds rings and labels edges according to which rings are. | ||
*/ | ||
Graph.prototype._findLabeledEdgeRings = function _findLabeledEdgeRings () { | ||
var edgeRingStarts = []; | ||
var label = 0; | ||
this.edges.forEach(function (edge) { | ||
if (edge.label >= 0) | ||
{ return; } | ||
Graph.prototype._findLabeledEdgeRings = function _findLabeledEdgeRings() { | ||
var edgeRingStarts = []; | ||
var label = 0; | ||
this.edges.forEach(function (edge) { | ||
if (edge.label >= 0) { | ||
return; | ||
} | ||
edgeRingStarts.push(edge); | ||
edgeRingStarts.push(edge); | ||
var e = edge; | ||
do { | ||
e.label = label; | ||
e = e.next; | ||
} while (!edge.isEqual(e)); | ||
var e = edge; | ||
do { | ||
e.label = label; | ||
e = e.next; | ||
} while (!edge.isEqual(e)); | ||
label++; | ||
}); | ||
label++; | ||
}); | ||
return edgeRingStarts; | ||
return edgeRingStarts; | ||
}; | ||
@@ -741,29 +843,30 @@ | ||
*/ | ||
Graph.prototype.getEdgeRings = function getEdgeRings () { | ||
var this$1 = this; | ||
Graph.prototype.getEdgeRings = function getEdgeRings() { | ||
var this$1 = this; | ||
this._computeNextCWEdges(); | ||
this._computeNextCWEdges(); | ||
// Clear labels | ||
this.edges.forEach(function (edge) { | ||
edge.label = undefined; | ||
}); | ||
// Clear labels | ||
this.edges.forEach(function (edge) { | ||
edge.label = undefined; | ||
}); | ||
this._findLabeledEdgeRings().forEach(function (edge) { | ||
// convertMaximalToMinimalEdgeRings | ||
this$1._findIntersectionNodes(edge).forEach(function (node) { | ||
this$1._computeNextCCWEdges(node, edge.label); | ||
}); | ||
this._findLabeledEdgeRings().forEach(function (edge) { | ||
// convertMaximalToMinimalEdgeRings | ||
this$1._findIntersectionNodes(edge).forEach(function (node) { | ||
this$1._computeNextCCWEdges(node, edge.label); | ||
}); | ||
}); | ||
var edgeRingList = []; | ||
var edgeRingList = []; | ||
// find all edgerings | ||
this.edges.forEach(function (edge) { | ||
if (edge.ring) | ||
{ return; } | ||
edgeRingList.push(this$1._findEdgeRing(edge)); | ||
}); | ||
// find all edgerings | ||
this.edges.forEach(function (edge) { | ||
if (edge.ring) { | ||
return; | ||
} | ||
edgeRingList.push(this$1._findEdgeRing(edge)); | ||
}); | ||
return edgeRingList; | ||
return edgeRingList; | ||
}; | ||
@@ -777,24 +880,28 @@ | ||
*/ | ||
Graph.prototype._findIntersectionNodes = function _findIntersectionNodes (startEdge) { | ||
var intersectionNodes = []; | ||
var edge = startEdge; | ||
var loop = function () { | ||
// getDegree | ||
var degree = 0; | ||
edge.from.getOuterEdges().forEach(function (e) { | ||
if (e.label === startEdge.label) | ||
{ ++degree; } | ||
}); | ||
Graph.prototype._findIntersectionNodes = function _findIntersectionNodes( | ||
startEdge | ||
) { | ||
var intersectionNodes = []; | ||
var edge = startEdge; | ||
var loop = function () { | ||
// getDegree | ||
var degree = 0; | ||
edge.from.getOuterEdges().forEach(function (e) { | ||
if (e.label === startEdge.label) { | ||
++degree; | ||
} | ||
}); | ||
if (degree > 1) | ||
{ intersectionNodes.push(edge.from); } | ||
if (degree > 1) { | ||
intersectionNodes.push(edge.from); | ||
} | ||
edge = edge.next; | ||
}; | ||
edge = edge.next; | ||
}; | ||
do { | ||
loop(); | ||
} while (!startEdge.isEqual(edge)); | ||
do { | ||
loop(); | ||
} while (!startEdge.isEqual(edge)); | ||
return intersectionNodes; | ||
return intersectionNodes; | ||
}; | ||
@@ -808,13 +915,13 @@ | ||
*/ | ||
Graph.prototype._findEdgeRing = function _findEdgeRing (startEdge) { | ||
var edge = startEdge; | ||
var edgeRing = new EdgeRing(); | ||
Graph.prototype._findEdgeRing = function _findEdgeRing(startEdge) { | ||
var edge = startEdge; | ||
var edgeRing = new EdgeRing(); | ||
do { | ||
edgeRing.push(edge); | ||
edge.ring = edgeRing; | ||
edge = edge.next; | ||
} while (!startEdge.isEqual(edge)); | ||
do { | ||
edgeRing.push(edge); | ||
edge.ring = edgeRing; | ||
edge = edge.next; | ||
} while (!startEdge.isEqual(edge)); | ||
return edgeRing; | ||
return edgeRing; | ||
}; | ||
@@ -828,8 +935,12 @@ | ||
*/ | ||
Graph.prototype.removeNode = function removeNode (node) { | ||
var this$1 = this; | ||
Graph.prototype.removeNode = function removeNode(node) { | ||
var this$1 = this; | ||
node.getOuterEdges().forEach(function (edge) { return this$1.removeEdge(edge); }); | ||
node.innerEdges.forEach(function (edge) { return this$1.removeEdge(edge); }); | ||
delete this.nodes[node.id]; | ||
node.getOuterEdges().forEach(function (edge) { | ||
return this$1.removeEdge(edge); | ||
}); | ||
node.innerEdges.forEach(function (edge) { | ||
return this$1.removeEdge(edge); | ||
}); | ||
delete this.nodes[node.id]; | ||
}; | ||
@@ -842,5 +953,7 @@ | ||
*/ | ||
Graph.prototype.removeEdge = function removeEdge (edge) { | ||
this.edges = this.edges.filter(function (e) { return !e.isEqual(edge); }); | ||
edge.deleteEdge(); | ||
Graph.prototype.removeEdge = function removeEdge(edge) { | ||
this.edges = this.edges.filter(function (e) { | ||
return !e.isEqual(edge); | ||
}); | ||
edge.deleteEdge(); | ||
}; | ||
@@ -867,34 +980,42 @@ | ||
function polygonize(geoJson) { | ||
var graph = Graph.fromGeoJson(geoJson); | ||
var graph = Graph.fromGeoJson(geoJson); | ||
// 1. Remove dangle node | ||
graph.deleteDangles(); | ||
// 1. Remove dangle node | ||
graph.deleteDangles(); | ||
// 2. Remove cut-edges (bridge edges) | ||
graph.deleteCutEdges(); | ||
// 2. Remove cut-edges (bridge edges) | ||
graph.deleteCutEdges(); | ||
// 3. Get all holes and shells | ||
var holes = [], | ||
shells = []; | ||
// 3. Get all holes and shells | ||
var holes = [], | ||
shells = []; | ||
graph.getEdgeRings() | ||
.filter(function (edgeRing) { return edgeRing.isValid(); }) | ||
.forEach(function (edgeRing) { | ||
if (edgeRing.isHole()) | ||
{ holes.push(edgeRing); } | ||
else | ||
{ shells.push(edgeRing); } | ||
}); | ||
// 4. Assign Holes to Shells | ||
holes.forEach(function (hole) { | ||
if (EdgeRing.findEdgeRingContaining(hole, shells)) | ||
{ shells.push(hole); } | ||
graph | ||
.getEdgeRings() | ||
.filter(function (edgeRing) { | ||
return edgeRing.isValid(); | ||
}) | ||
.forEach(function (edgeRing) { | ||
if (edgeRing.isHole()) { | ||
holes.push(edgeRing); | ||
} else { | ||
shells.push(edgeRing); | ||
} | ||
}); | ||
// 5. EdgeRings to Polygons | ||
return helpers.featureCollection(shells.map(function (shell) { return shell.toPolygon(); })); | ||
// 4. Assign Holes to Shells | ||
holes.forEach(function (hole) { | ||
if (EdgeRing.findEdgeRingContaining(hole, shells)) { | ||
shells.push(hole); | ||
} | ||
}); | ||
// 5. EdgeRings to Polygons | ||
return helpers.featureCollection( | ||
shells.map(function (shell) { | ||
return shell.toPolygon(); | ||
}) | ||
); | ||
} | ||
module.exports = polygonize; | ||
module.exports.default = polygonize; |
@@ -1,2 +0,8 @@ | ||
import { Feature, FeatureCollection, Coord, Polygon, LineString, MultiLineString } from '@turf/helpers' | ||
import { | ||
Feature, | ||
FeatureCollection, | ||
Polygon, | ||
LineString, | ||
MultiLineString, | ||
} from "@turf/helpers"; | ||
@@ -7,3 +13,3 @@ /** | ||
export default function <T extends LineString | MultiLineString>( | ||
geojson: Feature<T> | FeatureCollection<T> | T | ||
geojson: Feature<T> | FeatureCollection<T> | T | ||
): FeatureCollection<Polygon>; |
{ | ||
"name": "@turf/polygonize", | ||
"version": "6.2.0-alpha.2", | ||
"version": "6.2.0-alpha.3", | ||
"description": "turf polygonize module", | ||
@@ -30,2 +30,6 @@ "author": "Turf Authors", | ||
"module": "dist/es/index.js", | ||
"exports": { | ||
"import": "./dist/es/index.js", | ||
"require": "./dist/js/index.js" | ||
}, | ||
"types": "index.d.ts", | ||
@@ -38,10 +42,9 @@ "sideEffects": false, | ||
"scripts": { | ||
"bench": "npm-run-all prepare bench:run", | ||
"bench:run": "node bench.js", | ||
"bench": "node -r esm bench.js", | ||
"build": "rollup -c ../../rollup.config.js && echo '{\"type\":\"module\"}' > dist/es/package.json", | ||
"docs": "node ../../scripts/generate-readmes", | ||
"posttest": "node -r esm ../../scripts/validate-es5-dependencies.js", | ||
"prepare": "rollup -c ../../rollup.config.js", | ||
"test": "npm-run-all prepare test:*", | ||
"test": "npm-run-all test:*", | ||
"test:tape": "node -r esm test.js", | ||
"test:types": "tsc --noEmit types.ts" | ||
"test:types": "tsc --esModuleInterop --noEmit types.ts" | ||
}, | ||
@@ -57,9 +60,9 @@ "devDependencies": { | ||
"dependencies": { | ||
"@turf/boolean-point-in-polygon": "^6.2.0-alpha.2", | ||
"@turf/envelope": "^6.2.0-alpha.2", | ||
"@turf/helpers": "^6.2.0-alpha.2", | ||
"@turf/invariant": "^6.2.0-alpha.2", | ||
"@turf/meta": "^6.2.0-alpha.2" | ||
"@turf/boolean-point-in-polygon": "^6.2.0-alpha.3", | ||
"@turf/envelope": "^6.2.0-alpha.3", | ||
"@turf/helpers": "^6.2.0-alpha.3", | ||
"@turf/invariant": "^6.2.0-alpha.3", | ||
"@turf/meta": "^6.2.0-alpha.3" | ||
}, | ||
"gitHead": "23d5cb91d77e0c1e2e903a2252f525797f1d0d09" | ||
"gitHead": "dce9edfc705352e8cb9e0083c9330ba0e8d77409" | ||
} |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
8
2463
81667