@turf/polygonize 6.5.0 → 7.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -6
- package/dist/es/index.js +6 -6
- package/dist/es/lib/Edge.js +16 -18
- package/dist/es/lib/EdgeRing.js +49 -60
- package/dist/es/lib/Graph.js +73 -86
- package/dist/es/lib/Node.js +35 -38
- package/dist/es/lib/util.js +3 -5
- package/dist/js/index.d.ts +1 -1
- package/dist/js/index.js +10 -12
- package/dist/js/lib/Edge.d.ts +1 -1
- package/dist/js/lib/Edge.js +18 -19
- package/dist/js/lib/EdgeRing.d.ts +2 -2
- package/dist/js/lib/EdgeRing.js +53 -65
- package/dist/js/lib/Graph.d.ts +1 -1
- package/dist/js/lib/Graph.js +79 -93
- package/dist/js/lib/Node.js +36 -38
- package/dist/js/lib/util.d.ts +1 -1
- package/dist/js/lib/util.js +6 -10
- package/package.json +14 -12
package/dist/es/lib/Graph.js
CHANGED
|
@@ -17,7 +17,7 @@ function validateGeoJson(geoJson) {
|
|
|
17
17
|
geoJson.type !== "MultiLineString" &&
|
|
18
18
|
geoJson.type !== "LineString" &&
|
|
19
19
|
geoJson.type !== "Feature")
|
|
20
|
-
throw new Error(
|
|
20
|
+
throw new Error(`Invalid input type '${geoJson.type}'. Geojson must be FeatureCollection, GeometryCollection, LineString, MultiLineString or Feature`);
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* Represents a planar graph of edges and nodes that can be used to compute a polygonization.
|
|
@@ -28,8 +28,8 @@ function validateGeoJson(geoJson) {
|
|
|
28
28
|
*
|
|
29
29
|
* This graph is directed (both directions are created)
|
|
30
30
|
*/
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
export default class Graph {
|
|
32
|
+
constructor() {
|
|
33
33
|
this.edges = []; //< {Edge[]} dirEdges
|
|
34
34
|
// The key is the `id` of the Node (ie: coordinates.join(','))
|
|
35
35
|
this.nodes = {};
|
|
@@ -41,35 +41,35 @@ var Graph = /** @class */ (function () {
|
|
|
41
41
|
* @returns {Graph} - The newly created graph
|
|
42
42
|
* @throws {Error} if geoJson is invalid.
|
|
43
43
|
*/
|
|
44
|
-
|
|
44
|
+
static fromGeoJson(geoJson) {
|
|
45
45
|
validateGeoJson(geoJson);
|
|
46
|
-
|
|
47
|
-
flattenEach(geoJson,
|
|
46
|
+
const graph = new Graph();
|
|
47
|
+
flattenEach(geoJson, (feature) => {
|
|
48
48
|
featureOf(feature, "LineString", "Graph::fromGeoJson");
|
|
49
49
|
// When a LineString if formed by many segments, split them
|
|
50
|
-
coordReduce(feature,
|
|
50
|
+
coordReduce(feature, (prev, cur) => {
|
|
51
51
|
if (prev) {
|
|
52
|
-
|
|
52
|
+
const start = graph.getNode(prev), end = graph.getNode(cur);
|
|
53
53
|
graph.addEdge(start, end);
|
|
54
54
|
}
|
|
55
55
|
return cur;
|
|
56
56
|
});
|
|
57
57
|
});
|
|
58
58
|
return graph;
|
|
59
|
-
}
|
|
59
|
+
}
|
|
60
60
|
/**
|
|
61
61
|
* Creates or get a Node.
|
|
62
62
|
*
|
|
63
63
|
* @param {number[]} coordinates - Coordinates of the node
|
|
64
64
|
* @returns {Node} - The created or stored node
|
|
65
65
|
*/
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
getNode(coordinates) {
|
|
67
|
+
const id = Node.buildId(coordinates);
|
|
68
|
+
let node = this.nodes[id];
|
|
69
69
|
if (!node)
|
|
70
70
|
node = this.nodes[id] = new Node(coordinates);
|
|
71
71
|
return node;
|
|
72
|
-
}
|
|
72
|
+
}
|
|
73
73
|
/**
|
|
74
74
|
* Adds an Edge and its symetricall.
|
|
75
75
|
*
|
|
@@ -78,20 +78,19 @@ var Graph = /** @class */ (function () {
|
|
|
78
78
|
* @param {Node} from - Node which starts the Edge
|
|
79
79
|
* @param {Node} to - Node which ends the Edge
|
|
80
80
|
*/
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
addEdge(from, to) {
|
|
82
|
+
const edge = new Edge(from, to), symetricEdge = edge.getSymetric();
|
|
83
83
|
this.edges.push(edge);
|
|
84
84
|
this.edges.push(symetricEdge);
|
|
85
|
-
}
|
|
85
|
+
}
|
|
86
86
|
/**
|
|
87
87
|
* Removes Dangle Nodes (nodes with grade 1).
|
|
88
88
|
*/
|
|
89
|
-
|
|
90
|
-
var _this = this;
|
|
89
|
+
deleteDangles() {
|
|
91
90
|
Object.keys(this.nodes)
|
|
92
|
-
.map(
|
|
93
|
-
.forEach(
|
|
94
|
-
}
|
|
91
|
+
.map((id) => this.nodes[id])
|
|
92
|
+
.forEach((node) => this._removeIfDangle(node));
|
|
93
|
+
}
|
|
95
94
|
/**
|
|
96
95
|
* Check if node is dangle, if so, remove it.
|
|
97
96
|
*
|
|
@@ -99,15 +98,14 @@ var Graph = /** @class */ (function () {
|
|
|
99
98
|
*
|
|
100
99
|
* @param {Node} node - Node to check if it's a dangle
|
|
101
100
|
*/
|
|
102
|
-
|
|
103
|
-
var _this = this;
|
|
101
|
+
_removeIfDangle(node) {
|
|
104
102
|
// As edges are directed and symetrical, we count only innerEdges
|
|
105
103
|
if (node.innerEdges.length <= 1) {
|
|
106
|
-
|
|
104
|
+
const outerNodes = node.getOuterEdges().map((e) => e.to);
|
|
107
105
|
this.removeNode(node);
|
|
108
|
-
outerNodes.forEach(
|
|
106
|
+
outerNodes.forEach((n) => this._removeIfDangle(n));
|
|
109
107
|
}
|
|
110
|
-
}
|
|
108
|
+
}
|
|
111
109
|
/**
|
|
112
110
|
* Delete cut-edges (bridge edges).
|
|
113
111
|
*
|
|
@@ -115,18 +113,17 @@ var Graph = /** @class */ (function () {
|
|
|
115
113
|
* in which they are. (The label is a number incremented by 1). Edges with the same
|
|
116
114
|
* label are cut-edges.
|
|
117
115
|
*/
|
|
118
|
-
|
|
119
|
-
var _this = this;
|
|
116
|
+
deleteCutEdges() {
|
|
120
117
|
this._computeNextCWEdges();
|
|
121
118
|
this._findLabeledEdgeRings();
|
|
122
119
|
// Cut-edges (bridges) are edges where both edges have the same label
|
|
123
|
-
this.edges.forEach(
|
|
120
|
+
this.edges.forEach((edge) => {
|
|
124
121
|
if (edge.label === edge.symetric.label) {
|
|
125
|
-
|
|
126
|
-
|
|
122
|
+
this.removeEdge(edge.symetric);
|
|
123
|
+
this.removeEdge(edge);
|
|
127
124
|
}
|
|
128
125
|
});
|
|
129
|
-
}
|
|
126
|
+
}
|
|
130
127
|
/**
|
|
131
128
|
* Set the `next` property of each Edge.
|
|
132
129
|
*
|
|
@@ -135,19 +132,16 @@ var Graph = /** @class */ (function () {
|
|
|
135
132
|
*
|
|
136
133
|
* @param {Node} [node] - If no node is passed, the function calls itself for every node in the Graph
|
|
137
134
|
*/
|
|
138
|
-
|
|
139
|
-
var _this = this;
|
|
135
|
+
_computeNextCWEdges(node) {
|
|
140
136
|
if (typeof node === "undefined") {
|
|
141
|
-
Object.keys(this.nodes).forEach(
|
|
142
|
-
return _this._computeNextCWEdges(_this.nodes[id]);
|
|
143
|
-
});
|
|
137
|
+
Object.keys(this.nodes).forEach((id) => this._computeNextCWEdges(this.nodes[id]));
|
|
144
138
|
}
|
|
145
139
|
else {
|
|
146
|
-
node.getOuterEdges().forEach(
|
|
140
|
+
node.getOuterEdges().forEach((edge, i) => {
|
|
147
141
|
node.getOuterEdge((i === 0 ? node.getOuterEdges().length : i) - 1).symetric.next = edge;
|
|
148
142
|
});
|
|
149
143
|
}
|
|
150
|
-
}
|
|
144
|
+
}
|
|
151
145
|
/**
|
|
152
146
|
* Computes the next edge pointers going CCW around the given node, for the given edgering label.
|
|
153
147
|
*
|
|
@@ -159,11 +153,11 @@ var Graph = /** @class */ (function () {
|
|
|
159
153
|
* @param {Node} node - Node
|
|
160
154
|
* @param {number} label - Ring's label
|
|
161
155
|
*/
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
for (
|
|
166
|
-
|
|
156
|
+
_computeNextCCWEdges(node, label) {
|
|
157
|
+
const edges = node.getOuterEdges();
|
|
158
|
+
let firstOutDE, prevInDE;
|
|
159
|
+
for (let i = edges.length - 1; i >= 0; --i) {
|
|
160
|
+
let de = edges[i], sym = de.symetric, outDE, inDE;
|
|
167
161
|
if (de.label === label)
|
|
168
162
|
outDE = de;
|
|
169
163
|
if (sym.label === label)
|
|
@@ -184,7 +178,7 @@ var Graph = /** @class */ (function () {
|
|
|
184
178
|
}
|
|
185
179
|
if (prevInDE)
|
|
186
180
|
prevInDE.next = firstOutDE;
|
|
187
|
-
}
|
|
181
|
+
}
|
|
188
182
|
/**
|
|
189
183
|
* Finds rings and labels edges according to which rings are.
|
|
190
184
|
*
|
|
@@ -192,14 +186,14 @@ var Graph = /** @class */ (function () {
|
|
|
192
186
|
*
|
|
193
187
|
* @returns {Edge[]} edges that start rings
|
|
194
188
|
*/
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
this.edges.forEach(
|
|
189
|
+
_findLabeledEdgeRings() {
|
|
190
|
+
const edgeRingStarts = [];
|
|
191
|
+
let label = 0;
|
|
192
|
+
this.edges.forEach((edge) => {
|
|
199
193
|
if (edge.label >= 0)
|
|
200
194
|
return;
|
|
201
195
|
edgeRingStarts.push(edge);
|
|
202
|
-
|
|
196
|
+
let e = edge;
|
|
203
197
|
do {
|
|
204
198
|
e.label = label;
|
|
205
199
|
e = e.next;
|
|
@@ -207,96 +201,89 @@ var Graph = /** @class */ (function () {
|
|
|
207
201
|
label++;
|
|
208
202
|
});
|
|
209
203
|
return edgeRingStarts;
|
|
210
|
-
}
|
|
204
|
+
}
|
|
211
205
|
/**
|
|
212
206
|
* Computes the EdgeRings formed by the edges in this graph.
|
|
213
207
|
*
|
|
214
208
|
* @returns {EdgeRing[]} - A list of all the EdgeRings in the graph.
|
|
215
209
|
*/
|
|
216
|
-
|
|
217
|
-
var _this = this;
|
|
210
|
+
getEdgeRings() {
|
|
218
211
|
this._computeNextCWEdges();
|
|
219
212
|
// Clear labels
|
|
220
|
-
this.edges.forEach(
|
|
213
|
+
this.edges.forEach((edge) => {
|
|
221
214
|
edge.label = undefined;
|
|
222
215
|
});
|
|
223
|
-
this._findLabeledEdgeRings().forEach(
|
|
216
|
+
this._findLabeledEdgeRings().forEach((edge) => {
|
|
224
217
|
// convertMaximalToMinimalEdgeRings
|
|
225
|
-
|
|
226
|
-
|
|
218
|
+
this._findIntersectionNodes(edge).forEach((node) => {
|
|
219
|
+
this._computeNextCCWEdges(node, edge.label);
|
|
227
220
|
});
|
|
228
221
|
});
|
|
229
|
-
|
|
222
|
+
const edgeRingList = [];
|
|
230
223
|
// find all edgerings
|
|
231
|
-
this.edges.forEach(
|
|
224
|
+
this.edges.forEach((edge) => {
|
|
232
225
|
if (edge.ring)
|
|
233
226
|
return;
|
|
234
|
-
edgeRingList.push(
|
|
227
|
+
edgeRingList.push(this._findEdgeRing(edge));
|
|
235
228
|
});
|
|
236
229
|
return edgeRingList;
|
|
237
|
-
}
|
|
230
|
+
}
|
|
238
231
|
/**
|
|
239
232
|
* Find all nodes in a Maxima EdgeRing which are self-intersection nodes.
|
|
240
233
|
*
|
|
241
234
|
* @param {Node} startEdge - Start Edge of the Ring
|
|
242
235
|
* @returns {Node[]} - intersection nodes
|
|
243
236
|
*/
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
237
|
+
_findIntersectionNodes(startEdge) {
|
|
238
|
+
const intersectionNodes = [];
|
|
239
|
+
let edge = startEdge;
|
|
240
|
+
do {
|
|
248
241
|
// getDegree
|
|
249
|
-
|
|
250
|
-
edge.from.getOuterEdges().forEach(
|
|
242
|
+
let degree = 0;
|
|
243
|
+
edge.from.getOuterEdges().forEach((e) => {
|
|
251
244
|
if (e.label === startEdge.label)
|
|
252
245
|
++degree;
|
|
253
246
|
});
|
|
254
247
|
if (degree > 1)
|
|
255
248
|
intersectionNodes.push(edge.from);
|
|
256
249
|
edge = edge.next;
|
|
257
|
-
};
|
|
258
|
-
do {
|
|
259
|
-
_loop_1();
|
|
260
250
|
} while (!startEdge.isEqual(edge));
|
|
261
251
|
return intersectionNodes;
|
|
262
|
-
}
|
|
252
|
+
}
|
|
263
253
|
/**
|
|
264
254
|
* Get the edge-ring which starts from the provided Edge.
|
|
265
255
|
*
|
|
266
256
|
* @param {Edge} startEdge - starting edge of the edge ring
|
|
267
257
|
* @returns {EdgeRing} - EdgeRing which start Edge is the provided one.
|
|
268
258
|
*/
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
259
|
+
_findEdgeRing(startEdge) {
|
|
260
|
+
let edge = startEdge;
|
|
261
|
+
const edgeRing = new EdgeRing();
|
|
272
262
|
do {
|
|
273
263
|
edgeRing.push(edge);
|
|
274
264
|
edge.ring = edgeRing;
|
|
275
265
|
edge = edge.next;
|
|
276
266
|
} while (!startEdge.isEqual(edge));
|
|
277
267
|
return edgeRing;
|
|
278
|
-
}
|
|
268
|
+
}
|
|
279
269
|
/**
|
|
280
270
|
* Removes a node from the Graph.
|
|
281
271
|
*
|
|
282
272
|
* It also removes edges asociated to that node
|
|
283
273
|
* @param {Node} node - Node to be removed
|
|
284
274
|
*/
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
node.
|
|
288
|
-
node.innerEdges.forEach(function (edge) { return _this.removeEdge(edge); });
|
|
275
|
+
removeNode(node) {
|
|
276
|
+
node.getOuterEdges().forEach((edge) => this.removeEdge(edge));
|
|
277
|
+
node.innerEdges.forEach((edge) => this.removeEdge(edge));
|
|
289
278
|
delete this.nodes[node.id];
|
|
290
|
-
}
|
|
279
|
+
}
|
|
291
280
|
/**
|
|
292
281
|
* Remove edge from the graph and deletes the edge.
|
|
293
282
|
*
|
|
294
283
|
* @param {Edge} edge - Edge to be removed
|
|
295
284
|
*/
|
|
296
|
-
|
|
297
|
-
this.edges = this.edges.filter(
|
|
285
|
+
removeEdge(edge) {
|
|
286
|
+
this.edges = this.edges.filter((e) => !e.isEqual(edge));
|
|
298
287
|
edge.deleteEdge();
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
}());
|
|
302
|
-
export default Graph;
|
|
288
|
+
}
|
|
289
|
+
}
|
package/dist/es/lib/Node.js
CHANGED
|
@@ -2,8 +2,8 @@ import { orientationIndex } from "./util.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Node
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
export default class Node {
|
|
6
|
+
constructor(coordinates) {
|
|
7
7
|
this.id = Node.buildId(coordinates);
|
|
8
8
|
this.coordinates = coordinates; //< {Number[]}
|
|
9
9
|
this.innerEdges = []; //< {Edge[]}
|
|
@@ -11,64 +11,63 @@ var Node = /** @class */ (function () {
|
|
|
11
11
|
this.outerEdges = []; //< {Edge[]}
|
|
12
12
|
this.outerEdgesSorted = false; //< {Boolean} flag that stores if the outer Edges had been sorted
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
static buildId(coordinates) {
|
|
15
15
|
return coordinates.join(",");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
this.innerEdges = this.innerEdges.filter(
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
this.outerEdges = this.outerEdges.filter(
|
|
22
|
-
}
|
|
16
|
+
}
|
|
17
|
+
removeInnerEdge(edge) {
|
|
18
|
+
this.innerEdges = this.innerEdges.filter((e) => e.from.id !== edge.from.id);
|
|
19
|
+
}
|
|
20
|
+
removeOuterEdge(edge) {
|
|
21
|
+
this.outerEdges = this.outerEdges.filter((e) => e.to.id !== edge.to.id);
|
|
22
|
+
}
|
|
23
23
|
/**
|
|
24
24
|
* Outer edges are stored CCW order.
|
|
25
25
|
*
|
|
26
26
|
* @memberof Node
|
|
27
27
|
* @param {Edge} edge - Edge to add as an outerEdge.
|
|
28
28
|
*/
|
|
29
|
-
|
|
29
|
+
addOuterEdge(edge) {
|
|
30
30
|
this.outerEdges.push(edge);
|
|
31
31
|
this.outerEdgesSorted = false;
|
|
32
|
-
}
|
|
32
|
+
}
|
|
33
33
|
/**
|
|
34
34
|
* Sorts outer edges in CCW way.
|
|
35
35
|
*
|
|
36
36
|
* @memberof Node
|
|
37
37
|
* @private
|
|
38
38
|
*/
|
|
39
|
-
|
|
40
|
-
var _this = this;
|
|
39
|
+
sortOuterEdges() {
|
|
41
40
|
if (!this.outerEdgesSorted) {
|
|
42
41
|
//this.outerEdges.sort((a, b) => a.compareTo(b));
|
|
43
42
|
// Using this comparator in order to be deterministic
|
|
44
|
-
this.outerEdges.sort(
|
|
45
|
-
|
|
46
|
-
if (aNode.coordinates[0] -
|
|
47
|
-
bNode.coordinates[0] -
|
|
43
|
+
this.outerEdges.sort((a, b) => {
|
|
44
|
+
const aNode = a.to, bNode = b.to;
|
|
45
|
+
if (aNode.coordinates[0] - this.coordinates[0] >= 0 &&
|
|
46
|
+
bNode.coordinates[0] - this.coordinates[0] < 0)
|
|
48
47
|
return 1;
|
|
49
|
-
if (aNode.coordinates[0] -
|
|
50
|
-
bNode.coordinates[0] -
|
|
48
|
+
if (aNode.coordinates[0] - this.coordinates[0] < 0 &&
|
|
49
|
+
bNode.coordinates[0] - this.coordinates[0] >= 0)
|
|
51
50
|
return -1;
|
|
52
|
-
if (aNode.coordinates[0] -
|
|
53
|
-
bNode.coordinates[0] -
|
|
54
|
-
if (aNode.coordinates[1] -
|
|
55
|
-
bNode.coordinates[1] -
|
|
51
|
+
if (aNode.coordinates[0] - this.coordinates[0] === 0 &&
|
|
52
|
+
bNode.coordinates[0] - this.coordinates[0] === 0) {
|
|
53
|
+
if (aNode.coordinates[1] - this.coordinates[1] >= 0 ||
|
|
54
|
+
bNode.coordinates[1] - this.coordinates[1] >= 0)
|
|
56
55
|
return aNode.coordinates[1] - bNode.coordinates[1];
|
|
57
56
|
return bNode.coordinates[1] - aNode.coordinates[1];
|
|
58
57
|
}
|
|
59
|
-
|
|
58
|
+
const det = orientationIndex(this.coordinates, aNode.coordinates, bNode.coordinates);
|
|
60
59
|
if (det < 0)
|
|
61
60
|
return 1;
|
|
62
61
|
if (det > 0)
|
|
63
62
|
return -1;
|
|
64
|
-
|
|
65
|
-
Math.pow(aNode.coordinates[1] -
|
|
66
|
-
Math.pow(bNode.coordinates[1] -
|
|
63
|
+
const d1 = Math.pow(aNode.coordinates[0] - this.coordinates[0], 2) +
|
|
64
|
+
Math.pow(aNode.coordinates[1] - this.coordinates[1], 2), d2 = Math.pow(bNode.coordinates[0] - this.coordinates[0], 2) +
|
|
65
|
+
Math.pow(bNode.coordinates[1] - this.coordinates[1], 2);
|
|
67
66
|
return d1 - d2;
|
|
68
67
|
});
|
|
69
68
|
this.outerEdgesSorted = true;
|
|
70
69
|
}
|
|
71
|
-
}
|
|
70
|
+
}
|
|
72
71
|
/**
|
|
73
72
|
* Retrieves outer edges.
|
|
74
73
|
*
|
|
@@ -77,17 +76,15 @@ var Node = /** @class */ (function () {
|
|
|
77
76
|
* @memberof Node
|
|
78
77
|
* @returns {Edge[]} - List of outer edges sorted in a CCW order.
|
|
79
78
|
*/
|
|
80
|
-
|
|
79
|
+
getOuterEdges() {
|
|
81
80
|
this.sortOuterEdges();
|
|
82
81
|
return this.outerEdges;
|
|
83
|
-
}
|
|
84
|
-
|
|
82
|
+
}
|
|
83
|
+
getOuterEdge(i) {
|
|
85
84
|
this.sortOuterEdges();
|
|
86
85
|
return this.outerEdges[i];
|
|
87
|
-
}
|
|
88
|
-
|
|
86
|
+
}
|
|
87
|
+
addInnerEdge(edge) {
|
|
89
88
|
this.innerEdges.push(edge);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
}());
|
|
93
|
-
export default Node;
|
|
89
|
+
}
|
|
90
|
+
}
|
package/dist/es/lib/util.js
CHANGED
|
@@ -19,7 +19,7 @@ function mathSign(x) {
|
|
|
19
19
|
* 0 if q is colinear with p1->p2
|
|
20
20
|
*/
|
|
21
21
|
export function orientationIndex(p1, p2, q) {
|
|
22
|
-
|
|
22
|
+
const dx1 = p2[0] - p1[0], dy1 = p2[1] - p1[1], dx2 = q[0] - p2[0], dy2 = q[1] - p2[1];
|
|
23
23
|
return mathSign(dx1 * dy2 - dx2 * dy1);
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
@@ -32,7 +32,7 @@ export function orientationIndex(p1, p2, q) {
|
|
|
32
32
|
* @returns {boolean} - True if the envelopes are equal
|
|
33
33
|
*/
|
|
34
34
|
export function envelopeIsEqual(env1, env2) {
|
|
35
|
-
|
|
35
|
+
const envX1 = env1.geometry.coordinates[0].map((c) => c[0]), envY1 = env1.geometry.coordinates[0].map((c) => c[1]), envX2 = env2.geometry.coordinates[0].map((c) => c[0]), envY2 = env2.geometry.coordinates[0].map((c) => c[1]);
|
|
36
36
|
return (Math.max.apply(null, envX1) === Math.max.apply(null, envX2) &&
|
|
37
37
|
Math.max.apply(null, envY1) === Math.max.apply(null, envY2) &&
|
|
38
38
|
Math.min.apply(null, envX1) === Math.min.apply(null, envX2) &&
|
|
@@ -50,9 +50,7 @@ export function envelopeIsEqual(env1, env2) {
|
|
|
50
50
|
* @returns {boolean} - True if env is contained in self
|
|
51
51
|
*/
|
|
52
52
|
export function envelopeContains(self, env) {
|
|
53
|
-
return env.geometry.coordinates[0].every(
|
|
54
|
-
return booleanPointInPolygon(point(c), self);
|
|
55
|
-
});
|
|
53
|
+
return env.geometry.coordinates[0].every((c) => booleanPointInPolygon(point(c), self));
|
|
56
54
|
}
|
|
57
55
|
/**
|
|
58
56
|
* Checks if two coordinates are equal.
|
package/dist/js/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Feature, FeatureCollection, LineString, MultiLineString, Polygon } from "
|
|
1
|
+
import { Feature, FeatureCollection, LineString, MultiLineString, Polygon } from "geojson";
|
|
2
2
|
/**
|
|
3
3
|
* Polygonizes {@link LineString|(Multi)LineString(s)} into {@link Polygons}.
|
|
4
4
|
*
|
package/dist/js/index.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const helpers_1 = require("@turf/helpers");
|
|
5
|
+
const Graph_1 = tslib_1.__importDefault(require("./lib/Graph"));
|
|
6
|
+
const EdgeRing_1 = tslib_1.__importDefault(require("./lib/EdgeRing"));
|
|
9
7
|
/**
|
|
10
8
|
* Polygonizes {@link LineString|(Multi)LineString(s)} into {@link Polygons}.
|
|
11
9
|
*
|
|
@@ -25,28 +23,28 @@ var EdgeRing_1 = __importDefault(require("./lib/EdgeRing"));
|
|
|
25
23
|
* @throws {Error} if geoJson is invalid.
|
|
26
24
|
*/
|
|
27
25
|
function polygonize(geoJson) {
|
|
28
|
-
|
|
26
|
+
const graph = Graph_1.default.fromGeoJson(geoJson);
|
|
29
27
|
// 1. Remove dangle node
|
|
30
28
|
graph.deleteDangles();
|
|
31
29
|
// 2. Remove cut-edges (bridge edges)
|
|
32
30
|
graph.deleteCutEdges();
|
|
33
31
|
// 3. Get all holes and shells
|
|
34
|
-
|
|
32
|
+
const holes = [], shells = [];
|
|
35
33
|
graph
|
|
36
34
|
.getEdgeRings()
|
|
37
|
-
.filter(
|
|
38
|
-
.forEach(
|
|
35
|
+
.filter((edgeRing) => edgeRing.isValid())
|
|
36
|
+
.forEach((edgeRing) => {
|
|
39
37
|
if (edgeRing.isHole())
|
|
40
38
|
holes.push(edgeRing);
|
|
41
39
|
else
|
|
42
40
|
shells.push(edgeRing);
|
|
43
41
|
});
|
|
44
42
|
// 4. Assign Holes to Shells
|
|
45
|
-
holes.forEach(
|
|
43
|
+
holes.forEach((hole) => {
|
|
46
44
|
if (EdgeRing_1.default.findEdgeRingContaining(hole, shells))
|
|
47
45
|
shells.push(hole);
|
|
48
46
|
});
|
|
49
47
|
// 5. EdgeRings to Polygons
|
|
50
|
-
return helpers_1.featureCollection(shells.map(
|
|
48
|
+
return helpers_1.featureCollection(shells.map((shell) => shell.toPolygon()));
|
|
51
49
|
}
|
|
52
50
|
exports.default = polygonize;
|
package/dist/js/lib/Edge.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export default class Edge {
|
|
|
40
40
|
*
|
|
41
41
|
* @returns {Feature<LineString>} - LineString representation of the Edge
|
|
42
42
|
*/
|
|
43
|
-
toLineString(): import("
|
|
43
|
+
toLineString(): import("geojson").Feature<import("geojson").LineString, import("geojson").GeoJsonProperties>;
|
|
44
44
|
/**
|
|
45
45
|
* Comparator of two edges.
|
|
46
46
|
*
|
package/dist/js/lib/Edge.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const helpers_1 = require("@turf/helpers");
|
|
4
|
+
const util_1 = require("./util");
|
|
5
5
|
/**
|
|
6
6
|
* This class is inspired by GEOS's geos::operation::polygonize::PolygonizeDirectedEdge
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
class Edge {
|
|
9
9
|
/**
|
|
10
10
|
* @param {Node} from - start node of the Edge
|
|
11
11
|
* @param {Node} to - end node of the edge
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
constructor(from, to) {
|
|
14
14
|
this.from = from; //< start
|
|
15
15
|
this.to = to; //< End
|
|
16
16
|
this.next = undefined; //< The edge to be computed after
|
|
@@ -25,20 +25,20 @@ var Edge = /** @class */ (function () {
|
|
|
25
25
|
*
|
|
26
26
|
* @returns {Edge} - Symetric Edge.
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
getSymetric() {
|
|
29
29
|
if (!this.symetric) {
|
|
30
30
|
this.symetric = new Edge(this.to, this.from);
|
|
31
31
|
this.symetric.symetric = this;
|
|
32
32
|
}
|
|
33
33
|
return this.symetric;
|
|
34
|
-
}
|
|
34
|
+
}
|
|
35
35
|
/**
|
|
36
36
|
* Removes edge from from and to nodes.
|
|
37
37
|
*/
|
|
38
|
-
|
|
38
|
+
deleteEdge() {
|
|
39
39
|
this.from.removeOuterEdge(this);
|
|
40
40
|
this.to.removeInnerEdge(this);
|
|
41
|
-
}
|
|
41
|
+
}
|
|
42
42
|
/**
|
|
43
43
|
* Compares Edge equallity.
|
|
44
44
|
*
|
|
@@ -47,20 +47,20 @@ var Edge = /** @class */ (function () {
|
|
|
47
47
|
* @param {Edge} edge - Another Edge
|
|
48
48
|
* @returns {boolean} - True if Edges are equal, False otherwise
|
|
49
49
|
*/
|
|
50
|
-
|
|
50
|
+
isEqual(edge) {
|
|
51
51
|
return this.from.id === edge.from.id && this.to.id === edge.to.id;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return
|
|
55
|
-
}
|
|
52
|
+
}
|
|
53
|
+
toString() {
|
|
54
|
+
return `Edge { ${this.from.id} -> ${this.to.id} }`;
|
|
55
|
+
}
|
|
56
56
|
/**
|
|
57
57
|
* Returns a LineString representation of the Edge
|
|
58
58
|
*
|
|
59
59
|
* @returns {Feature<LineString>} - LineString representation of the Edge
|
|
60
60
|
*/
|
|
61
|
-
|
|
61
|
+
toLineString() {
|
|
62
62
|
return helpers_1.lineString([this.from.coordinates, this.to.coordinates]);
|
|
63
|
-
}
|
|
63
|
+
}
|
|
64
64
|
/**
|
|
65
65
|
* Comparator of two edges.
|
|
66
66
|
*
|
|
@@ -71,9 +71,8 @@ var Edge = /** @class */ (function () {
|
|
|
71
71
|
* 0 if the Edges are colinear,
|
|
72
72
|
* 1 otherwise
|
|
73
73
|
*/
|
|
74
|
-
|
|
74
|
+
compareTo(edge) {
|
|
75
75
|
return util_1.orientationIndex(edge.from.coordinates, edge.to.coordinates, this.to.coordinates);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
}());
|
|
76
|
+
}
|
|
77
|
+
}
|
|
79
78
|
exports.default = Edge;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Polygon, Feature, Point } from "
|
|
1
|
+
import { Polygon, Feature, Point } from "geojson";
|
|
2
2
|
import Edge from "./Edge";
|
|
3
3
|
/**
|
|
4
4
|
* Ring of edges which form a polygon.
|
|
@@ -84,7 +84,7 @@ export default class EdgeRing {
|
|
|
84
84
|
* @memberof EdgeRing
|
|
85
85
|
* @returns {Feature<MultiPoint>} - Multipoint representation of the EdgeRing
|
|
86
86
|
*/
|
|
87
|
-
toMultiPoint(): Feature<import("
|
|
87
|
+
toMultiPoint(): Feature<import("geojson").MultiPoint, import("geojson").GeoJsonProperties>;
|
|
88
88
|
/**
|
|
89
89
|
* Creates a Polygon representing the EdgeRing.
|
|
90
90
|
*
|