@turf/polygonize 6.4.0 → 7.0.0-alpha.0
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 +51 -58
- package/dist/es/lib/Graph.js +73 -86
- package/dist/es/lib/Node.js +35 -38
- package/dist/es/lib/util.js +11 -14
- package/dist/js/index.d.ts +1 -1
- package/dist/js/index.js +10 -12
- package/dist/js/lib/Edge.d.ts +8 -10
- package/dist/js/lib/Edge.js +18 -19
- package/dist/js/lib/EdgeRing.d.ts +11 -13
- package/dist/js/lib/EdgeRing.js +56 -64
- package/dist/js/lib/Graph.d.ts +4 -4
- package/dist/js/lib/Graph.js +79 -93
- package/dist/js/lib/Node.d.ts +5 -5
- package/dist/js/lib/Node.js +36 -38
- package/dist/js/lib/util.d.ts +5 -5
- package/dist/js/lib/util.js +10 -14
- package/package.json +10 -8
package/README.md
CHANGED
|
@@ -13,17 +13,18 @@ noded, i.e., they must only meet at their endpoints.
|
|
|
13
13
|
|
|
14
14
|
The implementation correctly handles:
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
* Dangles: edges which have one or both ends which are not incident on another edge endpoint.
|
|
17
|
+
* Cut Edges (bridges): edges that are connected at both ends but which do not form part of a polygon.
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
### Parameters
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
* `geoJson` **([FeatureCollection][3] | [Geometry][4] | [Feature][5]<([LineString][6] | [MultiLineString][7])>)** Lines in order to polygonize
|
|
22
22
|
|
|
23
|
+
<!---->
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
* Throws **[Error][8]** if geoJson is invalid.
|
|
25
26
|
|
|
26
|
-
Returns **[FeatureCollection][3]
|
|
27
|
+
Returns **[FeatureCollection][3]<[Polygon][9]>** Polygons created
|
|
27
28
|
|
|
28
29
|
[1]: https://tools.ietf.org/html/rfc7946#section-3.1.4
|
|
29
30
|
|
package/dist/es/index.js
CHANGED
|
@@ -20,27 +20,27 @@ import EdgeRing from "./lib/EdgeRing.js";
|
|
|
20
20
|
* @throws {Error} if geoJson is invalid.
|
|
21
21
|
*/
|
|
22
22
|
export default function polygonize(geoJson) {
|
|
23
|
-
|
|
23
|
+
const graph = Graph.fromGeoJson(geoJson);
|
|
24
24
|
// 1. Remove dangle node
|
|
25
25
|
graph.deleteDangles();
|
|
26
26
|
// 2. Remove cut-edges (bridge edges)
|
|
27
27
|
graph.deleteCutEdges();
|
|
28
28
|
// 3. Get all holes and shells
|
|
29
|
-
|
|
29
|
+
const holes = [], shells = [];
|
|
30
30
|
graph
|
|
31
31
|
.getEdgeRings()
|
|
32
|
-
.filter(
|
|
33
|
-
.forEach(
|
|
32
|
+
.filter((edgeRing) => edgeRing.isValid())
|
|
33
|
+
.forEach((edgeRing) => {
|
|
34
34
|
if (edgeRing.isHole())
|
|
35
35
|
holes.push(edgeRing);
|
|
36
36
|
else
|
|
37
37
|
shells.push(edgeRing);
|
|
38
38
|
});
|
|
39
39
|
// 4. Assign Holes to Shells
|
|
40
|
-
holes.forEach(
|
|
40
|
+
holes.forEach((hole) => {
|
|
41
41
|
if (EdgeRing.findEdgeRingContaining(hole, shells))
|
|
42
42
|
shells.push(hole);
|
|
43
43
|
});
|
|
44
44
|
// 5. EdgeRings to Polygons
|
|
45
|
-
return featureCollection(shells.map(
|
|
45
|
+
return featureCollection(shells.map((shell) => shell.toPolygon()));
|
|
46
46
|
}
|
package/dist/es/lib/Edge.js
CHANGED
|
@@ -3,12 +3,12 @@ import { orientationIndex } from "./util.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* This class is inspired by GEOS's geos::operation::polygonize::PolygonizeDirectedEdge
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
export default class Edge {
|
|
7
7
|
/**
|
|
8
8
|
* @param {Node} from - start node of the Edge
|
|
9
9
|
* @param {Node} to - end node of the edge
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
constructor(from, to) {
|
|
12
12
|
this.from = from; //< start
|
|
13
13
|
this.to = to; //< End
|
|
14
14
|
this.next = undefined; //< The edge to be computed after
|
|
@@ -23,20 +23,20 @@ var Edge = /** @class */ (function () {
|
|
|
23
23
|
*
|
|
24
24
|
* @returns {Edge} - Symetric Edge.
|
|
25
25
|
*/
|
|
26
|
-
|
|
26
|
+
getSymetric() {
|
|
27
27
|
if (!this.symetric) {
|
|
28
28
|
this.symetric = new Edge(this.to, this.from);
|
|
29
29
|
this.symetric.symetric = this;
|
|
30
30
|
}
|
|
31
31
|
return this.symetric;
|
|
32
|
-
}
|
|
32
|
+
}
|
|
33
33
|
/**
|
|
34
34
|
* Removes edge from from and to nodes.
|
|
35
35
|
*/
|
|
36
|
-
|
|
36
|
+
deleteEdge() {
|
|
37
37
|
this.from.removeOuterEdge(this);
|
|
38
38
|
this.to.removeInnerEdge(this);
|
|
39
|
-
}
|
|
39
|
+
}
|
|
40
40
|
/**
|
|
41
41
|
* Compares Edge equallity.
|
|
42
42
|
*
|
|
@@ -45,20 +45,20 @@ var Edge = /** @class */ (function () {
|
|
|
45
45
|
* @param {Edge} edge - Another Edge
|
|
46
46
|
* @returns {boolean} - True if Edges are equal, False otherwise
|
|
47
47
|
*/
|
|
48
|
-
|
|
48
|
+
isEqual(edge) {
|
|
49
49
|
return this.from.id === edge.from.id && this.to.id === edge.to.id;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return
|
|
53
|
-
}
|
|
50
|
+
}
|
|
51
|
+
toString() {
|
|
52
|
+
return `Edge { ${this.from.id} -> ${this.to.id} }`;
|
|
53
|
+
}
|
|
54
54
|
/**
|
|
55
55
|
* Returns a LineString representation of the Edge
|
|
56
56
|
*
|
|
57
57
|
* @returns {Feature<LineString>} - LineString representation of the Edge
|
|
58
58
|
*/
|
|
59
|
-
|
|
59
|
+
toLineString() {
|
|
60
60
|
return lineString([this.from.coordinates, this.to.coordinates]);
|
|
61
|
-
}
|
|
61
|
+
}
|
|
62
62
|
/**
|
|
63
63
|
* Comparator of two edges.
|
|
64
64
|
*
|
|
@@ -69,9 +69,7 @@ var Edge = /** @class */ (function () {
|
|
|
69
69
|
* 0 if the Edges are colinear,
|
|
70
70
|
* 1 otherwise
|
|
71
71
|
*/
|
|
72
|
-
|
|
72
|
+
compareTo(edge) {
|
|
73
73
|
return orientationIndex(edge.from.coordinates, edge.to.coordinates, this.to.coordinates);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
}());
|
|
77
|
-
export default Edge;
|
|
74
|
+
}
|
|
75
|
+
}
|
package/dist/es/lib/EdgeRing.js
CHANGED
|
@@ -9,8 +9,8 @@ import booleanPointInPolygon from "@turf/boolean-point-in-polygon";
|
|
|
9
9
|
*
|
|
10
10
|
* This class is inspired in GEOS's geos::operation::polygonize::EdgeRing
|
|
11
11
|
*/
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
export default class EdgeRing {
|
|
13
|
+
constructor() {
|
|
14
14
|
this.edges = [];
|
|
15
15
|
this.polygon = undefined; //< Caches Polygon representation
|
|
16
16
|
this.envelope = undefined; //< Caches Envelope representation
|
|
@@ -21,12 +21,10 @@ var EdgeRing = /** @class */ (function () {
|
|
|
21
21
|
* @memberof EdgeRing
|
|
22
22
|
* @param {Edge} edge - Edge to be inserted
|
|
23
23
|
*/
|
|
24
|
-
|
|
25
|
-
// Emulate Array getter ([]) behaviour
|
|
26
|
-
this[this.edges.length] = edge;
|
|
24
|
+
push(edge) {
|
|
27
25
|
this.edges.push(edge);
|
|
28
26
|
this.polygon = this.envelope = undefined;
|
|
29
|
-
}
|
|
27
|
+
}
|
|
30
28
|
/**
|
|
31
29
|
* Get Edge.
|
|
32
30
|
*
|
|
@@ -34,31 +32,27 @@ var EdgeRing = /** @class */ (function () {
|
|
|
34
32
|
* @param {number} i - Index
|
|
35
33
|
* @returns {Edge} - Edge in the i position
|
|
36
34
|
*/
|
|
37
|
-
|
|
35
|
+
get(i) {
|
|
38
36
|
return this.edges[i];
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
},
|
|
50
|
-
enumerable: true,
|
|
51
|
-
configurable: true
|
|
52
|
-
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Getter of length property.
|
|
40
|
+
*
|
|
41
|
+
* @memberof EdgeRing
|
|
42
|
+
* @returns {number} - Length of the edge ring.
|
|
43
|
+
*/
|
|
44
|
+
get length() {
|
|
45
|
+
return this.edges.length;
|
|
46
|
+
}
|
|
53
47
|
/**
|
|
54
48
|
* Similar to Array.prototype.forEach for the list of Edges in the EdgeRing.
|
|
55
49
|
*
|
|
56
50
|
* @memberof EdgeRing
|
|
57
51
|
* @param {Function} f - The same function to be passed to Array.prototype.forEach
|
|
58
52
|
*/
|
|
59
|
-
|
|
53
|
+
forEach(f) {
|
|
60
54
|
this.edges.forEach(f);
|
|
61
|
-
}
|
|
55
|
+
}
|
|
62
56
|
/**
|
|
63
57
|
* Similar to Array.prototype.map for the list of Edges in the EdgeRing.
|
|
64
58
|
*
|
|
@@ -66,9 +60,9 @@ var EdgeRing = /** @class */ (function () {
|
|
|
66
60
|
* @param {Function} f - The same function to be passed to Array.prototype.map
|
|
67
61
|
* @returns {Array} - The mapped values in the function
|
|
68
62
|
*/
|
|
69
|
-
|
|
63
|
+
map(f) {
|
|
70
64
|
return this.edges.map(f);
|
|
71
|
-
}
|
|
65
|
+
}
|
|
72
66
|
/**
|
|
73
67
|
* Similar to Array.prototype.some for the list of Edges in the EdgeRing.
|
|
74
68
|
*
|
|
@@ -76,9 +70,9 @@ var EdgeRing = /** @class */ (function () {
|
|
|
76
70
|
* @param {Function} f - The same function to be passed to Array.prototype.some
|
|
77
71
|
* @returns {boolean} - True if an Edge check the condition
|
|
78
72
|
*/
|
|
79
|
-
|
|
73
|
+
some(f) {
|
|
80
74
|
return this.edges.some(f);
|
|
81
|
-
}
|
|
75
|
+
}
|
|
82
76
|
/**
|
|
83
77
|
* Check if the ring is valid in geomtry terms.
|
|
84
78
|
*
|
|
@@ -89,10 +83,10 @@ var EdgeRing = /** @class */ (function () {
|
|
|
89
83
|
* @memberof EdgeRing
|
|
90
84
|
* @returns {boolean} - Validity of the EdgeRing
|
|
91
85
|
*/
|
|
92
|
-
|
|
86
|
+
isValid() {
|
|
93
87
|
// TODO: stub
|
|
94
88
|
return true;
|
|
95
|
-
}
|
|
89
|
+
}
|
|
96
90
|
/**
|
|
97
91
|
* Tests whether this ring is a hole.
|
|
98
92
|
*
|
|
@@ -102,12 +96,11 @@ var EdgeRing = /** @class */ (function () {
|
|
|
102
96
|
* @memberof EdgeRing
|
|
103
97
|
* @returns {boolean} - true: if it is a hole
|
|
104
98
|
*/
|
|
105
|
-
|
|
106
|
-
var _this = this;
|
|
99
|
+
isHole() {
|
|
107
100
|
// XXX: Assuming Ring is valid
|
|
108
101
|
// Find highest point
|
|
109
|
-
|
|
110
|
-
if (edge.from.coordinates[1] >
|
|
102
|
+
const hiIndex = this.edges.reduce((high, edge, i) => {
|
|
103
|
+
if (edge.from.coordinates[1] > this.edges[high].from.coordinates[1])
|
|
111
104
|
high = i;
|
|
112
105
|
return high;
|
|
113
106
|
}, 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);
|
|
@@ -115,40 +108,40 @@ var EdgeRing = /** @class */ (function () {
|
|
|
115
108
|
return (this.edges[iPrev].from.coordinates[0] >
|
|
116
109
|
this.edges[iNext].from.coordinates[0]);
|
|
117
110
|
return disc > 0;
|
|
118
|
-
}
|
|
111
|
+
}
|
|
119
112
|
/**
|
|
120
113
|
* Creates a MultiPoint representing the EdgeRing (discarts edges directions).
|
|
121
114
|
*
|
|
122
115
|
* @memberof EdgeRing
|
|
123
116
|
* @returns {Feature<MultiPoint>} - Multipoint representation of the EdgeRing
|
|
124
117
|
*/
|
|
125
|
-
|
|
126
|
-
return multiPoint(this.edges.map(
|
|
127
|
-
}
|
|
118
|
+
toMultiPoint() {
|
|
119
|
+
return multiPoint(this.edges.map((edge) => edge.from.coordinates));
|
|
120
|
+
}
|
|
128
121
|
/**
|
|
129
122
|
* Creates a Polygon representing the EdgeRing.
|
|
130
123
|
*
|
|
131
124
|
* @memberof EdgeRing
|
|
132
125
|
* @returns {Feature<Polygon>} - Polygon representation of the Edge Ring
|
|
133
126
|
*/
|
|
134
|
-
|
|
127
|
+
toPolygon() {
|
|
135
128
|
if (this.polygon)
|
|
136
129
|
return this.polygon;
|
|
137
|
-
|
|
130
|
+
const coordinates = this.edges.map((edge) => edge.from.coordinates);
|
|
138
131
|
coordinates.push(this.edges[0].from.coordinates);
|
|
139
132
|
return (this.polygon = polygon([coordinates]));
|
|
140
|
-
}
|
|
133
|
+
}
|
|
141
134
|
/**
|
|
142
135
|
* Calculates the envelope of the EdgeRing.
|
|
143
136
|
*
|
|
144
137
|
* @memberof EdgeRing
|
|
145
138
|
* @returns {Feature<Polygon>} - envelope
|
|
146
139
|
*/
|
|
147
|
-
|
|
140
|
+
getEnvelope() {
|
|
148
141
|
if (this.envelope)
|
|
149
142
|
return this.envelope;
|
|
150
143
|
return (this.envelope = envelope(this.toPolygon()));
|
|
151
|
-
}
|
|
144
|
+
}
|
|
152
145
|
/**
|
|
153
146
|
* `geos::operation::polygonize::EdgeRing::findEdgeRingContaining`
|
|
154
147
|
*
|
|
@@ -157,22 +150,24 @@ var EdgeRing = /** @class */ (function () {
|
|
|
157
150
|
*
|
|
158
151
|
* @returns {EdgeRing} - EdgeRing which contains the testEdgeRing
|
|
159
152
|
*/
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
shellList.forEach(
|
|
164
|
-
|
|
153
|
+
static findEdgeRingContaining(testEdgeRing, shellList) {
|
|
154
|
+
const testEnvelope = testEdgeRing.getEnvelope();
|
|
155
|
+
let minEnvelope, minShell;
|
|
156
|
+
shellList.forEach((shell) => {
|
|
157
|
+
const tryEnvelope = shell.getEnvelope();
|
|
165
158
|
if (minShell)
|
|
166
159
|
minEnvelope = minShell.getEnvelope();
|
|
167
160
|
// the hole envelope cannot equal the shell envelope
|
|
168
161
|
if (envelopeIsEqual(tryEnvelope, testEnvelope))
|
|
169
162
|
return;
|
|
170
163
|
if (envelopeContains(tryEnvelope, testEnvelope)) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
164
|
+
const testEdgeRingCoordinates = testEdgeRing.map((edge) => edge.from.coordinates);
|
|
165
|
+
let testPoint;
|
|
166
|
+
for (const pt of testEdgeRingCoordinates) {
|
|
167
|
+
if (!shell.some((edge) => coordinatesEqual(pt, edge.from.coordinates))) {
|
|
168
|
+
testPoint = pt;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
176
171
|
if (testPoint && shell.inside(point(testPoint))) {
|
|
177
172
|
if (!minShell || envelopeContains(minEnvelope, tryEnvelope))
|
|
178
173
|
minShell = shell;
|
|
@@ -180,16 +175,14 @@ var EdgeRing = /** @class */ (function () {
|
|
|
180
175
|
}
|
|
181
176
|
});
|
|
182
177
|
return minShell;
|
|
183
|
-
}
|
|
178
|
+
}
|
|
184
179
|
/**
|
|
185
180
|
* Checks if the point is inside the edgeRing
|
|
186
181
|
*
|
|
187
182
|
* @param {Feature<Point>} pt - Point to check if it is inside the edgeRing
|
|
188
183
|
* @returns {boolean} - True if it is inside, False otherwise
|
|
189
184
|
*/
|
|
190
|
-
|
|
185
|
+
inside(pt) {
|
|
191
186
|
return booleanPointInPolygon(pt, this.toPolygon());
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
}());
|
|
195
|
-
export default EdgeRing;
|
|
187
|
+
}
|
|
188
|
+
}
|