@turf/kinks 6.5.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 +17 -24
- package/dist/es/index.js +10 -104
- package/dist/js/index.d.ts +2 -2
- package/dist/js/index.js +12 -105
- package/package.json +7 -5
- package/dist/es/lib/sweepline-intersections.js +0 -288
- package/dist/js/lib/sweepline-intersections.d.ts +0 -2
- package/dist/js/lib/sweepline-intersections.js +0 -290
package/README.md
CHANGED
|
@@ -4,53 +4,46 @@
|
|
|
4
4
|
|
|
5
5
|
## kinks
|
|
6
6
|
|
|
7
|
-
Takes a [linestring][1], [multi-linestring][2],
|
|
7
|
+
Takes a [linestring][1], [multi-linestring][2],
|
|
8
|
+
[multi-polygon][3] or [polygon][4] and
|
|
9
|
+
returns [points][5] at all self-intersections.
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
### Parameters
|
|
10
12
|
|
|
11
|
-
-
|
|
13
|
+
- `featureIn` **[Feature][6]<([LineString][7] | [MultiLineString][8] | [MultiPolygon][9] | [Polygon][10])>** input feature
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
### Examples
|
|
14
16
|
|
|
15
17
|
```javascript
|
|
16
|
-
var poly = turf.polygon([
|
|
17
|
-
[
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
]
|
|
18
|
+
var poly = turf.polygon([
|
|
19
|
+
[
|
|
20
|
+
[-12.034835, 8.901183],
|
|
21
|
+
[-12.060413, 8.899826],
|
|
22
|
+
[-12.03638, 8.873199],
|
|
23
|
+
[-12.059383, 8.871418],
|
|
24
|
+
[-12.034835, 8.901183],
|
|
25
|
+
],
|
|
26
|
+
]);
|
|
23
27
|
|
|
24
28
|
var kinks = turf.kinks(poly);
|
|
25
29
|
|
|
26
30
|
//addToMap
|
|
27
|
-
var addToMap = [poly, kinks]
|
|
31
|
+
var addToMap = [poly, kinks];
|
|
28
32
|
```
|
|
29
33
|
|
|
30
|
-
Returns **[FeatureCollection][11]
|
|
34
|
+
Returns **[FeatureCollection][11]<[Point][12]>** self-intersections
|
|
31
35
|
|
|
32
36
|
[1]: https://tools.ietf.org/html/rfc7946#section-3.1.4
|
|
33
|
-
|
|
34
37
|
[2]: https://tools.ietf.org/html/rfc7946#section-3.1.5
|
|
35
|
-
|
|
36
38
|
[3]: https://tools.ietf.org/html/rfc7946#section-3.1.7
|
|
37
|
-
|
|
38
39
|
[4]: https://tools.ietf.org/html/rfc7946#section-3.1.6
|
|
39
|
-
|
|
40
40
|
[5]: https://tools.ietf.org/html/rfc7946#section-3.1.2
|
|
41
|
-
|
|
42
41
|
[6]: https://tools.ietf.org/html/rfc7946#section-3.2
|
|
43
|
-
|
|
44
42
|
[7]: https://tools.ietf.org/html/rfc7946#section-3.1.4
|
|
45
|
-
|
|
46
43
|
[8]: https://tools.ietf.org/html/rfc7946#section-3.1.5
|
|
47
|
-
|
|
48
44
|
[9]: https://tools.ietf.org/html/rfc7946#section-3.1.7
|
|
49
|
-
|
|
50
45
|
[10]: https://tools.ietf.org/html/rfc7946#section-3.1.6
|
|
51
|
-
|
|
52
46
|
[11]: https://tools.ietf.org/html/rfc7946#section-3.3
|
|
53
|
-
|
|
54
47
|
[12]: https://tools.ietf.org/html/rfc7946#section-3.1.2
|
|
55
48
|
|
|
56
49
|
<!-- This file is automatically generated. Please don't edit it directly:
|
package/dist/es/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import findIntersections from "sweepline-intersections";
|
|
1
2
|
import { point } from "@turf/helpers";
|
|
2
3
|
/**
|
|
3
4
|
* Takes a {@link LineString|linestring}, {@link MultiLineString|multi-linestring},
|
|
@@ -22,115 +23,20 @@ import { point } from "@turf/helpers";
|
|
|
22
23
|
* var addToMap = [poly, kinks]
|
|
23
24
|
*/
|
|
24
25
|
export default function kinks(featureIn) {
|
|
25
|
-
|
|
26
|
-
var feature;
|
|
27
|
-
var results = {
|
|
26
|
+
const results = {
|
|
28
27
|
type: "FeatureCollection",
|
|
29
28
|
features: [],
|
|
30
29
|
};
|
|
31
|
-
if (featureIn.type === "Feature"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
else {
|
|
35
|
-
feature = featureIn;
|
|
36
|
-
}
|
|
37
|
-
if (feature.type === "LineString") {
|
|
38
|
-
coordinates = [feature.coordinates];
|
|
39
|
-
}
|
|
40
|
-
else if (feature.type === "MultiLineString") {
|
|
41
|
-
coordinates = feature.coordinates;
|
|
42
|
-
}
|
|
43
|
-
else if (feature.type === "MultiPolygon") {
|
|
44
|
-
coordinates = [].concat.apply([], feature.coordinates);
|
|
45
|
-
}
|
|
46
|
-
else if (feature.type === "Polygon") {
|
|
47
|
-
coordinates = feature.coordinates;
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
30
|
+
if (featureIn.type === "Feature" &&
|
|
31
|
+
(featureIn.geometry.type === "Point" ||
|
|
32
|
+
featureIn.geometry.type === "MultiPoint")) {
|
|
50
33
|
throw new Error("Input must be a LineString, MultiLineString, " +
|
|
51
34
|
"Polygon, or MultiPolygon Feature or Geometry");
|
|
52
35
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// been checked in previous outer loop iterations
|
|
58
|
-
for (var k = i; k < line2.length - 1; k++) {
|
|
59
|
-
if (line1 === line2) {
|
|
60
|
-
// segments are adjacent and always share a vertex, not a kink
|
|
61
|
-
if (Math.abs(i - k) === 1) {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
// first and last segment in a closed lineString or ring always share a vertex, not a kink
|
|
65
|
-
if (
|
|
66
|
-
// segments are first and last segment of lineString
|
|
67
|
-
i === 0 &&
|
|
68
|
-
k === line1.length - 2 &&
|
|
69
|
-
// lineString is closed
|
|
70
|
-
line1[i][0] === line1[line1.length - 1][0] &&
|
|
71
|
-
line1[i][1] === line1[line1.length - 1][1]) {
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
var intersection = lineIntersects(line1[i][0], line1[i][1], line1[i + 1][0], line1[i + 1][1], line2[k][0], line2[k][1], line2[k + 1][0], line2[k + 1][1]);
|
|
76
|
-
if (intersection) {
|
|
77
|
-
results.features.push(point([intersection[0], intersection[1]]));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
return results;
|
|
84
|
-
}
|
|
85
|
-
// modified from http://jsfiddle.net/justin_c_rounds/Gd2S2/light/
|
|
86
|
-
function lineIntersects(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {
|
|
87
|
-
// if the lines intersect, the result contains the x and y of the
|
|
88
|
-
// intersection (treating the lines as infinite) and booleans for whether
|
|
89
|
-
// line segment 1 or line segment 2 contain the point
|
|
90
|
-
var denominator;
|
|
91
|
-
var a;
|
|
92
|
-
var b;
|
|
93
|
-
var numerator1;
|
|
94
|
-
var numerator2;
|
|
95
|
-
var result = {
|
|
96
|
-
x: null,
|
|
97
|
-
y: null,
|
|
98
|
-
onLine1: false,
|
|
99
|
-
onLine2: false,
|
|
100
|
-
};
|
|
101
|
-
denominator =
|
|
102
|
-
(line2EndY - line2StartY) * (line1EndX - line1StartX) -
|
|
103
|
-
(line2EndX - line2StartX) * (line1EndY - line1StartY);
|
|
104
|
-
if (denominator === 0) {
|
|
105
|
-
if (result.x !== null && result.y !== null) {
|
|
106
|
-
return result;
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
a = line1StartY - line2StartY;
|
|
113
|
-
b = line1StartX - line2StartX;
|
|
114
|
-
numerator1 = (line2EndX - line2StartX) * a - (line2EndY - line2StartY) * b;
|
|
115
|
-
numerator2 = (line1EndX - line1StartX) * a - (line1EndY - line1StartY) * b;
|
|
116
|
-
a = numerator1 / denominator;
|
|
117
|
-
b = numerator2 / denominator;
|
|
118
|
-
// if we cast these lines infinitely in both directions, they intersect here:
|
|
119
|
-
result.x = line1StartX + a * (line1EndX - line1StartX);
|
|
120
|
-
result.y = line1StartY + a * (line1EndY - line1StartY);
|
|
121
|
-
// if line1 is a segment and line2 is infinite, they intersect if:
|
|
122
|
-
if (a >= 0 && a <= 1) {
|
|
123
|
-
result.onLine1 = true;
|
|
124
|
-
}
|
|
125
|
-
// if line2 is a segment and line1 is infinite, they intersect if:
|
|
126
|
-
if (b >= 0 && b <= 1) {
|
|
127
|
-
result.onLine2 = true;
|
|
128
|
-
}
|
|
129
|
-
// if line1 and line2 are segments, they intersect if both of the above are true
|
|
130
|
-
if (result.onLine1 && result.onLine2) {
|
|
131
|
-
return [result.x, result.y];
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
return false;
|
|
36
|
+
const intersections = findIntersections(featureIn, false);
|
|
37
|
+
for (let i = 0; i < intersections.length; ++i) {
|
|
38
|
+
const intersection = intersections[i];
|
|
39
|
+
results.features.push(point([intersection[0], intersection[1]]));
|
|
135
40
|
}
|
|
41
|
+
return results;
|
|
136
42
|
}
|
package/dist/js/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Feature, FeatureCollection, LineString, MultiLineString, MultiPolygon, Point, Polygon } from "
|
|
1
|
+
import { Feature, FeatureCollection, LineString, MultiLineString, MultiPolygon, Point, Polygon } from "geojson";
|
|
2
2
|
/**
|
|
3
3
|
* Takes a {@link LineString|linestring}, {@link MultiLineString|multi-linestring},
|
|
4
4
|
* {@link MultiPolygon|multi-polygon} or {@link Polygon|polygon} and
|
|
@@ -21,4 +21,4 @@ import { Feature, FeatureCollection, LineString, MultiLineString, MultiPolygon,
|
|
|
21
21
|
* //addToMap
|
|
22
22
|
* var addToMap = [poly, kinks]
|
|
23
23
|
*/
|
|
24
|
-
export default function kinks<T extends LineString | MultiLineString | Polygon | MultiPolygon>(featureIn: Feature<T>
|
|
24
|
+
export default function kinks<T extends LineString | MultiLineString | Polygon | MultiPolygon>(featureIn: Feature<T>): FeatureCollection<Point>;
|
package/dist/js/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const sweepline_intersections_1 = tslib_1.__importDefault(require("sweepline-intersections"));
|
|
5
|
+
const helpers_1 = require("@turf/helpers");
|
|
4
6
|
/**
|
|
5
7
|
* Takes a {@link LineString|linestring}, {@link MultiLineString|multi-linestring},
|
|
6
8
|
* {@link MultiPolygon|multi-polygon} or {@link Polygon|polygon} and
|
|
@@ -24,116 +26,21 @@ var helpers_1 = require("@turf/helpers");
|
|
|
24
26
|
* var addToMap = [poly, kinks]
|
|
25
27
|
*/
|
|
26
28
|
function kinks(featureIn) {
|
|
27
|
-
|
|
28
|
-
var feature;
|
|
29
|
-
var results = {
|
|
29
|
+
const results = {
|
|
30
30
|
type: "FeatureCollection",
|
|
31
31
|
features: [],
|
|
32
32
|
};
|
|
33
|
-
if (featureIn.type === "Feature"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
else {
|
|
37
|
-
feature = featureIn;
|
|
38
|
-
}
|
|
39
|
-
if (feature.type === "LineString") {
|
|
40
|
-
coordinates = [feature.coordinates];
|
|
41
|
-
}
|
|
42
|
-
else if (feature.type === "MultiLineString") {
|
|
43
|
-
coordinates = feature.coordinates;
|
|
44
|
-
}
|
|
45
|
-
else if (feature.type === "MultiPolygon") {
|
|
46
|
-
coordinates = [].concat.apply([], feature.coordinates);
|
|
47
|
-
}
|
|
48
|
-
else if (feature.type === "Polygon") {
|
|
49
|
-
coordinates = feature.coordinates;
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
33
|
+
if (featureIn.type === "Feature" &&
|
|
34
|
+
(featureIn.geometry.type === "Point" ||
|
|
35
|
+
featureIn.geometry.type === "MultiPoint")) {
|
|
52
36
|
throw new Error("Input must be a LineString, MultiLineString, " +
|
|
53
37
|
"Polygon, or MultiPolygon Feature or Geometry");
|
|
54
38
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
for (var k = i; k < line2.length - 1; k++) {
|
|
61
|
-
if (line1 === line2) {
|
|
62
|
-
// segments are adjacent and always share a vertex, not a kink
|
|
63
|
-
if (Math.abs(i - k) === 1) {
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
// first and last segment in a closed lineString or ring always share a vertex, not a kink
|
|
67
|
-
if (
|
|
68
|
-
// segments are first and last segment of lineString
|
|
69
|
-
i === 0 &&
|
|
70
|
-
k === line1.length - 2 &&
|
|
71
|
-
// lineString is closed
|
|
72
|
-
line1[i][0] === line1[line1.length - 1][0] &&
|
|
73
|
-
line1[i][1] === line1[line1.length - 1][1]) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
var intersection = lineIntersects(line1[i][0], line1[i][1], line1[i + 1][0], line1[i + 1][1], line2[k][0], line2[k][1], line2[k + 1][0], line2[k + 1][1]);
|
|
78
|
-
if (intersection) {
|
|
79
|
-
results.features.push(helpers_1.point([intersection[0], intersection[1]]));
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
});
|
|
39
|
+
const intersections = sweepline_intersections_1.default(featureIn, false);
|
|
40
|
+
for (let i = 0; i < intersections.length; ++i) {
|
|
41
|
+
const intersection = intersections[i];
|
|
42
|
+
results.features.push(helpers_1.point([intersection[0], intersection[1]]));
|
|
43
|
+
}
|
|
85
44
|
return results;
|
|
86
45
|
}
|
|
87
46
|
exports.default = kinks;
|
|
88
|
-
// modified from http://jsfiddle.net/justin_c_rounds/Gd2S2/light/
|
|
89
|
-
function lineIntersects(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {
|
|
90
|
-
// if the lines intersect, the result contains the x and y of the
|
|
91
|
-
// intersection (treating the lines as infinite) and booleans for whether
|
|
92
|
-
// line segment 1 or line segment 2 contain the point
|
|
93
|
-
var denominator;
|
|
94
|
-
var a;
|
|
95
|
-
var b;
|
|
96
|
-
var numerator1;
|
|
97
|
-
var numerator2;
|
|
98
|
-
var result = {
|
|
99
|
-
x: null,
|
|
100
|
-
y: null,
|
|
101
|
-
onLine1: false,
|
|
102
|
-
onLine2: false,
|
|
103
|
-
};
|
|
104
|
-
denominator =
|
|
105
|
-
(line2EndY - line2StartY) * (line1EndX - line1StartX) -
|
|
106
|
-
(line2EndX - line2StartX) * (line1EndY - line1StartY);
|
|
107
|
-
if (denominator === 0) {
|
|
108
|
-
if (result.x !== null && result.y !== null) {
|
|
109
|
-
return result;
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
a = line1StartY - line2StartY;
|
|
116
|
-
b = line1StartX - line2StartX;
|
|
117
|
-
numerator1 = (line2EndX - line2StartX) * a - (line2EndY - line2StartY) * b;
|
|
118
|
-
numerator2 = (line1EndX - line1StartX) * a - (line1EndY - line1StartY) * b;
|
|
119
|
-
a = numerator1 / denominator;
|
|
120
|
-
b = numerator2 / denominator;
|
|
121
|
-
// if we cast these lines infinitely in both directions, they intersect here:
|
|
122
|
-
result.x = line1StartX + a * (line1EndX - line1StartX);
|
|
123
|
-
result.y = line1StartY + a * (line1EndY - line1StartY);
|
|
124
|
-
// if line1 is a segment and line2 is infinite, they intersect if:
|
|
125
|
-
if (a >= 0 && a <= 1) {
|
|
126
|
-
result.onLine1 = true;
|
|
127
|
-
}
|
|
128
|
-
// if line2 is a segment and line1 is infinite, they intersect if:
|
|
129
|
-
if (b >= 0 && b <= 1) {
|
|
130
|
-
result.onLine2 = true;
|
|
131
|
-
}
|
|
132
|
-
// if line1 and line2 are segments, they intersect if both of the above are true
|
|
133
|
-
if (result.onLine1 && result.onLine2) {
|
|
134
|
-
return [result.x, result.y];
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@turf/kinks",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0-alpha.0",
|
|
4
4
|
"description": "turf kinks module",
|
|
5
5
|
"author": "Turf Authors",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
"docs": "node ../../scripts/generate-readmes",
|
|
44
44
|
"test": "npm-run-all test:*",
|
|
45
45
|
"test:tape": "ts-node -r esm test.js",
|
|
46
|
-
"test:types": "tsc --esModuleInterop --noEmit types.ts"
|
|
46
|
+
"test:types": "tsc --esModuleInterop --noEmit --strict types.ts"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@turf/meta": "^
|
|
49
|
+
"@turf/meta": "^7.0.0-alpha.0",
|
|
50
50
|
"benchmark": "*",
|
|
51
51
|
"load-json-file": "*",
|
|
52
52
|
"npm-run-all": "*",
|
|
@@ -56,7 +56,9 @@
|
|
|
56
56
|
"write-json-file": "*"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@turf/helpers": "^
|
|
59
|
+
"@turf/helpers": "^7.0.0-alpha.0",
|
|
60
|
+
"sweepline-intersections": "^1.5.0",
|
|
61
|
+
"tslib": "^2.3.0"
|
|
60
62
|
},
|
|
61
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "0edc4c491b999e5ace770a61e1cf549f7c004189"
|
|
62
64
|
}
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
// Inlined from
|
|
2
|
-
// https://github.com/rowanwins/sweepline-intersections
|
|
3
|
-
// Needed to go through babel to transform ES6 classes
|
|
4
|
-
var commonjsGlobal = typeof globalThis !== "undefined"
|
|
5
|
-
? globalThis
|
|
6
|
-
: typeof window !== "undefined"
|
|
7
|
-
? window
|
|
8
|
-
: typeof global !== "undefined"
|
|
9
|
-
? global
|
|
10
|
-
: typeof self !== "undefined"
|
|
11
|
-
? self
|
|
12
|
-
: {};
|
|
13
|
-
function createCommonjsModule(fn, module) {
|
|
14
|
-
return (module = { exports: {} }), fn(module, module.exports), module.exports;
|
|
15
|
-
}
|
|
16
|
-
var tinyqueue = createCommonjsModule(function (module) {
|
|
17
|
-
(function (global, factory) {
|
|
18
|
-
module.exports = factory();
|
|
19
|
-
})(commonjsGlobal, function () {
|
|
20
|
-
var TinyQueue = function TinyQueue(data, compare) {
|
|
21
|
-
if (data === void 0)
|
|
22
|
-
data = [];
|
|
23
|
-
if (compare === void 0)
|
|
24
|
-
compare = defaultCompare;
|
|
25
|
-
this.data = data;
|
|
26
|
-
this.length = this.data.length;
|
|
27
|
-
this.compare = compare;
|
|
28
|
-
if (this.length > 0) {
|
|
29
|
-
for (var i = (this.length >> 1) - 1; i >= 0; i--) {
|
|
30
|
-
this._down(i);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
TinyQueue.prototype.push = function push(item) {
|
|
35
|
-
this.data.push(item);
|
|
36
|
-
this.length++;
|
|
37
|
-
this._up(this.length - 1);
|
|
38
|
-
};
|
|
39
|
-
TinyQueue.prototype.pop = function pop() {
|
|
40
|
-
if (this.length === 0) {
|
|
41
|
-
return undefined;
|
|
42
|
-
}
|
|
43
|
-
var top = this.data[0];
|
|
44
|
-
var bottom = this.data.pop();
|
|
45
|
-
this.length--;
|
|
46
|
-
if (this.length > 0) {
|
|
47
|
-
this.data[0] = bottom;
|
|
48
|
-
this._down(0);
|
|
49
|
-
}
|
|
50
|
-
return top;
|
|
51
|
-
};
|
|
52
|
-
TinyQueue.prototype.peek = function peek() {
|
|
53
|
-
return this.data[0];
|
|
54
|
-
};
|
|
55
|
-
TinyQueue.prototype._up = function _up(pos) {
|
|
56
|
-
var ref = this;
|
|
57
|
-
var data = ref.data;
|
|
58
|
-
var compare = ref.compare;
|
|
59
|
-
var item = data[pos];
|
|
60
|
-
while (pos > 0) {
|
|
61
|
-
var parent = (pos - 1) >> 1;
|
|
62
|
-
var current = data[parent];
|
|
63
|
-
if (compare(item, current) >= 0) {
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
data[pos] = current;
|
|
67
|
-
pos = parent;
|
|
68
|
-
}
|
|
69
|
-
data[pos] = item;
|
|
70
|
-
};
|
|
71
|
-
TinyQueue.prototype._down = function _down(pos) {
|
|
72
|
-
var ref = this;
|
|
73
|
-
var data = ref.data;
|
|
74
|
-
var compare = ref.compare;
|
|
75
|
-
var halfLength = this.length >> 1;
|
|
76
|
-
var item = data[pos];
|
|
77
|
-
while (pos < halfLength) {
|
|
78
|
-
var left = (pos << 1) + 1;
|
|
79
|
-
var best = data[left];
|
|
80
|
-
var right = left + 1;
|
|
81
|
-
if (right < this.length && compare(data[right], best) < 0) {
|
|
82
|
-
left = right;
|
|
83
|
-
best = data[right];
|
|
84
|
-
}
|
|
85
|
-
if (compare(best, item) >= 0) {
|
|
86
|
-
break;
|
|
87
|
-
}
|
|
88
|
-
data[pos] = best;
|
|
89
|
-
pos = left;
|
|
90
|
-
}
|
|
91
|
-
data[pos] = item;
|
|
92
|
-
};
|
|
93
|
-
function defaultCompare(a, b) {
|
|
94
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
95
|
-
}
|
|
96
|
-
return TinyQueue;
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
function checkWhichEventIsLeft(e1, e2) {
|
|
100
|
-
if (e1.p.x > e2.p.x)
|
|
101
|
-
return 1;
|
|
102
|
-
if (e1.p.x < e2.p.x)
|
|
103
|
-
return -1;
|
|
104
|
-
if (e1.p.y !== e2.p.y)
|
|
105
|
-
return e1.p.y > e2.p.y ? 1 : -1;
|
|
106
|
-
return 1;
|
|
107
|
-
}
|
|
108
|
-
function checkWhichSegmentHasRightEndpointFirst(seg1, seg2) {
|
|
109
|
-
if (seg1.rightSweepEvent.p.x > seg2.rightSweepEvent.p.x)
|
|
110
|
-
return 1;
|
|
111
|
-
if (seg1.rightSweepEvent.p.x < seg2.rightSweepEvent.p.x)
|
|
112
|
-
return -1;
|
|
113
|
-
if (seg1.rightSweepEvent.p.y !== seg2.rightSweepEvent.p.y)
|
|
114
|
-
return seg1.rightSweepEvent.p.y < seg2.rightSweepEvent.p.y ? 1 : -1;
|
|
115
|
-
return 1;
|
|
116
|
-
}
|
|
117
|
-
function _classCallCheck(instance, Constructor) {
|
|
118
|
-
if (!(instance instanceof Constructor)) {
|
|
119
|
-
throw new TypeError("Cannot call a class as a function");
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
function _defineProperties(target, props) {
|
|
123
|
-
for (var i = 0; i < props.length; i++) {
|
|
124
|
-
var descriptor = props[i];
|
|
125
|
-
descriptor.enumerable = descriptor.enumerable || false;
|
|
126
|
-
descriptor.configurable = true;
|
|
127
|
-
if ("value" in descriptor)
|
|
128
|
-
descriptor.writable = true;
|
|
129
|
-
Object.defineProperty(target, descriptor.key, descriptor);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
function _createClass(Constructor, protoProps, staticProps) {
|
|
133
|
-
if (protoProps)
|
|
134
|
-
_defineProperties(Constructor.prototype, protoProps);
|
|
135
|
-
if (staticProps)
|
|
136
|
-
_defineProperties(Constructor, staticProps);
|
|
137
|
-
return Constructor;
|
|
138
|
-
}
|
|
139
|
-
var Event = /*#__PURE__*/ (function () {
|
|
140
|
-
function Event(p, featureId, ringId, eventId) {
|
|
141
|
-
_classCallCheck(this, Event);
|
|
142
|
-
this.p = {
|
|
143
|
-
x: p[0],
|
|
144
|
-
y: p[1],
|
|
145
|
-
};
|
|
146
|
-
this.featureId = featureId;
|
|
147
|
-
this.ringId = ringId;
|
|
148
|
-
this.eventId = eventId;
|
|
149
|
-
this.otherEvent = null;
|
|
150
|
-
this.isLeftEndpoint = null;
|
|
151
|
-
}
|
|
152
|
-
_createClass(Event, [
|
|
153
|
-
{
|
|
154
|
-
key: "isSamePoint",
|
|
155
|
-
value: function isSamePoint(eventToCheck) {
|
|
156
|
-
return this.p.x === eventToCheck.p.x && this.p.y === eventToCheck.p.y;
|
|
157
|
-
},
|
|
158
|
-
},
|
|
159
|
-
]);
|
|
160
|
-
return Event;
|
|
161
|
-
})();
|
|
162
|
-
function fillEventQueue(geojson, eventQueue) {
|
|
163
|
-
if (geojson.type === "FeatureCollection") {
|
|
164
|
-
var features = geojson.features;
|
|
165
|
-
for (var i = 0; i < features.length; i++) {
|
|
166
|
-
processFeature(features[i], eventQueue);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
else {
|
|
170
|
-
processFeature(geojson, eventQueue);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
var featureId = 0;
|
|
174
|
-
var ringId = 0;
|
|
175
|
-
var eventId = 0;
|
|
176
|
-
function processFeature(featureOrGeometry, eventQueue) {
|
|
177
|
-
var geom = featureOrGeometry.type === "Feature"
|
|
178
|
-
? featureOrGeometry.geometry
|
|
179
|
-
: featureOrGeometry;
|
|
180
|
-
var coords = geom.coordinates; // standardise the input
|
|
181
|
-
if (geom.type === "Polygon" || geom.type === "MultiLineString")
|
|
182
|
-
coords = [coords];
|
|
183
|
-
if (geom.type === "LineString")
|
|
184
|
-
coords = [[coords]];
|
|
185
|
-
for (var i = 0; i < coords.length; i++) {
|
|
186
|
-
for (var ii = 0; ii < coords[i].length; ii++) {
|
|
187
|
-
var currentP = coords[i][ii][0];
|
|
188
|
-
var nextP = null;
|
|
189
|
-
ringId = ringId + 1;
|
|
190
|
-
for (var iii = 0; iii < coords[i][ii].length - 1; iii++) {
|
|
191
|
-
nextP = coords[i][ii][iii + 1];
|
|
192
|
-
var e1 = new Event(currentP, featureId, ringId, eventId);
|
|
193
|
-
var e2 = new Event(nextP, featureId, ringId, eventId + 1);
|
|
194
|
-
e1.otherEvent = e2;
|
|
195
|
-
e2.otherEvent = e1;
|
|
196
|
-
if (checkWhichEventIsLeft(e1, e2) > 0) {
|
|
197
|
-
e2.isLeftEndpoint = true;
|
|
198
|
-
e1.isLeftEndpoint = false;
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
201
|
-
e1.isLeftEndpoint = true;
|
|
202
|
-
e2.isLeftEndpoint = false;
|
|
203
|
-
}
|
|
204
|
-
eventQueue.push(e1);
|
|
205
|
-
eventQueue.push(e2);
|
|
206
|
-
currentP = nextP;
|
|
207
|
-
eventId = eventId + 1;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
featureId = featureId + 1;
|
|
212
|
-
}
|
|
213
|
-
var Segment = function Segment(event) {
|
|
214
|
-
_classCallCheck(this, Segment);
|
|
215
|
-
this.leftSweepEvent = event;
|
|
216
|
-
this.rightSweepEvent = event.otherEvent;
|
|
217
|
-
};
|
|
218
|
-
function testSegmentIntersect(seg1, seg2) {
|
|
219
|
-
if (seg1 === null || seg2 === null)
|
|
220
|
-
return false;
|
|
221
|
-
if (seg1.leftSweepEvent.ringId === seg2.leftSweepEvent.ringId &&
|
|
222
|
-
(seg1.rightSweepEvent.isSamePoint(seg2.leftSweepEvent) ||
|
|
223
|
-
seg1.rightSweepEvent.isSamePoint(seg2.leftSweepEvent) ||
|
|
224
|
-
seg1.rightSweepEvent.isSamePoint(seg2.rightSweepEvent) ||
|
|
225
|
-
seg1.leftSweepEvent.isSamePoint(seg2.leftSweepEvent) ||
|
|
226
|
-
seg1.leftSweepEvent.isSamePoint(seg2.rightSweepEvent)))
|
|
227
|
-
return false;
|
|
228
|
-
var x1 = seg1.leftSweepEvent.p.x;
|
|
229
|
-
var y1 = seg1.leftSweepEvent.p.y;
|
|
230
|
-
var x2 = seg1.rightSweepEvent.p.x;
|
|
231
|
-
var y2 = seg1.rightSweepEvent.p.y;
|
|
232
|
-
var x3 = seg2.leftSweepEvent.p.x;
|
|
233
|
-
var y3 = seg2.leftSweepEvent.p.y;
|
|
234
|
-
var x4 = seg2.rightSweepEvent.p.x;
|
|
235
|
-
var y4 = seg2.rightSweepEvent.p.y;
|
|
236
|
-
var denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
|
|
237
|
-
var numeA = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
|
|
238
|
-
var numeB = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);
|
|
239
|
-
if (denom === 0) {
|
|
240
|
-
if (numeA === 0 && numeB === 0)
|
|
241
|
-
return false;
|
|
242
|
-
return false;
|
|
243
|
-
}
|
|
244
|
-
var uA = numeA / denom;
|
|
245
|
-
var uB = numeB / denom;
|
|
246
|
-
if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {
|
|
247
|
-
var x = x1 + uA * (x2 - x1);
|
|
248
|
-
var y = y1 + uA * (y2 - y1);
|
|
249
|
-
return [x, y];
|
|
250
|
-
}
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
|
-
function runCheck(eventQueue, ignoreSelfIntersections) {
|
|
254
|
-
ignoreSelfIntersections = ignoreSelfIntersections
|
|
255
|
-
? ignoreSelfIntersections
|
|
256
|
-
: false;
|
|
257
|
-
var intersectionPoints = [];
|
|
258
|
-
var outQueue = new tinyqueue([], checkWhichSegmentHasRightEndpointFirst);
|
|
259
|
-
while (eventQueue.length) {
|
|
260
|
-
var event = eventQueue.pop();
|
|
261
|
-
if (event.isLeftEndpoint) {
|
|
262
|
-
// debugEventAndSegments(event.p, outQueue.data)
|
|
263
|
-
var segment = new Segment(event);
|
|
264
|
-
for (var i = 0; i < outQueue.data.length; i++) {
|
|
265
|
-
var otherSeg = outQueue.data[i];
|
|
266
|
-
if (ignoreSelfIntersections) {
|
|
267
|
-
if (otherSeg.leftSweepEvent.featureId === event.featureId)
|
|
268
|
-
continue;
|
|
269
|
-
}
|
|
270
|
-
var intersection = testSegmentIntersect(segment, otherSeg);
|
|
271
|
-
if (intersection !== false)
|
|
272
|
-
intersectionPoints.push(intersection);
|
|
273
|
-
}
|
|
274
|
-
outQueue.push(segment);
|
|
275
|
-
}
|
|
276
|
-
else if (event.isLeftEndpoint === false) {
|
|
277
|
-
outQueue.pop(); // const seg = outQueue.pop()
|
|
278
|
-
// debugRemovingSegment(event.p, seg)
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return intersectionPoints;
|
|
282
|
-
}
|
|
283
|
-
function sweeplineIntersections(geojson, ignoreSelfIntersections) {
|
|
284
|
-
var eventQueue = new tinyqueue([], checkWhichEventIsLeft);
|
|
285
|
-
fillEventQueue(geojson, eventQueue);
|
|
286
|
-
return runCheck(eventQueue, ignoreSelfIntersections);
|
|
287
|
-
}
|
|
288
|
-
export default sweeplineIntersections;
|
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
// Inlined from
|
|
4
|
-
// https://github.com/rowanwins/sweepline-intersections
|
|
5
|
-
// Needed to go through babel to transform ES6 classes
|
|
6
|
-
var commonjsGlobal = typeof globalThis !== "undefined"
|
|
7
|
-
? globalThis
|
|
8
|
-
: typeof window !== "undefined"
|
|
9
|
-
? window
|
|
10
|
-
: typeof global !== "undefined"
|
|
11
|
-
? global
|
|
12
|
-
: typeof self !== "undefined"
|
|
13
|
-
? self
|
|
14
|
-
: {};
|
|
15
|
-
function createCommonjsModule(fn, module) {
|
|
16
|
-
return (module = { exports: {} }), fn(module, module.exports), module.exports;
|
|
17
|
-
}
|
|
18
|
-
var tinyqueue = createCommonjsModule(function (module) {
|
|
19
|
-
(function (global, factory) {
|
|
20
|
-
module.exports = factory();
|
|
21
|
-
})(commonjsGlobal, function () {
|
|
22
|
-
var TinyQueue = function TinyQueue(data, compare) {
|
|
23
|
-
if (data === void 0)
|
|
24
|
-
data = [];
|
|
25
|
-
if (compare === void 0)
|
|
26
|
-
compare = defaultCompare;
|
|
27
|
-
this.data = data;
|
|
28
|
-
this.length = this.data.length;
|
|
29
|
-
this.compare = compare;
|
|
30
|
-
if (this.length > 0) {
|
|
31
|
-
for (var i = (this.length >> 1) - 1; i >= 0; i--) {
|
|
32
|
-
this._down(i);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
TinyQueue.prototype.push = function push(item) {
|
|
37
|
-
this.data.push(item);
|
|
38
|
-
this.length++;
|
|
39
|
-
this._up(this.length - 1);
|
|
40
|
-
};
|
|
41
|
-
TinyQueue.prototype.pop = function pop() {
|
|
42
|
-
if (this.length === 0) {
|
|
43
|
-
return undefined;
|
|
44
|
-
}
|
|
45
|
-
var top = this.data[0];
|
|
46
|
-
var bottom = this.data.pop();
|
|
47
|
-
this.length--;
|
|
48
|
-
if (this.length > 0) {
|
|
49
|
-
this.data[0] = bottom;
|
|
50
|
-
this._down(0);
|
|
51
|
-
}
|
|
52
|
-
return top;
|
|
53
|
-
};
|
|
54
|
-
TinyQueue.prototype.peek = function peek() {
|
|
55
|
-
return this.data[0];
|
|
56
|
-
};
|
|
57
|
-
TinyQueue.prototype._up = function _up(pos) {
|
|
58
|
-
var ref = this;
|
|
59
|
-
var data = ref.data;
|
|
60
|
-
var compare = ref.compare;
|
|
61
|
-
var item = data[pos];
|
|
62
|
-
while (pos > 0) {
|
|
63
|
-
var parent = (pos - 1) >> 1;
|
|
64
|
-
var current = data[parent];
|
|
65
|
-
if (compare(item, current) >= 0) {
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
data[pos] = current;
|
|
69
|
-
pos = parent;
|
|
70
|
-
}
|
|
71
|
-
data[pos] = item;
|
|
72
|
-
};
|
|
73
|
-
TinyQueue.prototype._down = function _down(pos) {
|
|
74
|
-
var ref = this;
|
|
75
|
-
var data = ref.data;
|
|
76
|
-
var compare = ref.compare;
|
|
77
|
-
var halfLength = this.length >> 1;
|
|
78
|
-
var item = data[pos];
|
|
79
|
-
while (pos < halfLength) {
|
|
80
|
-
var left = (pos << 1) + 1;
|
|
81
|
-
var best = data[left];
|
|
82
|
-
var right = left + 1;
|
|
83
|
-
if (right < this.length && compare(data[right], best) < 0) {
|
|
84
|
-
left = right;
|
|
85
|
-
best = data[right];
|
|
86
|
-
}
|
|
87
|
-
if (compare(best, item) >= 0) {
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
data[pos] = best;
|
|
91
|
-
pos = left;
|
|
92
|
-
}
|
|
93
|
-
data[pos] = item;
|
|
94
|
-
};
|
|
95
|
-
function defaultCompare(a, b) {
|
|
96
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
97
|
-
}
|
|
98
|
-
return TinyQueue;
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
function checkWhichEventIsLeft(e1, e2) {
|
|
102
|
-
if (e1.p.x > e2.p.x)
|
|
103
|
-
return 1;
|
|
104
|
-
if (e1.p.x < e2.p.x)
|
|
105
|
-
return -1;
|
|
106
|
-
if (e1.p.y !== e2.p.y)
|
|
107
|
-
return e1.p.y > e2.p.y ? 1 : -1;
|
|
108
|
-
return 1;
|
|
109
|
-
}
|
|
110
|
-
function checkWhichSegmentHasRightEndpointFirst(seg1, seg2) {
|
|
111
|
-
if (seg1.rightSweepEvent.p.x > seg2.rightSweepEvent.p.x)
|
|
112
|
-
return 1;
|
|
113
|
-
if (seg1.rightSweepEvent.p.x < seg2.rightSweepEvent.p.x)
|
|
114
|
-
return -1;
|
|
115
|
-
if (seg1.rightSweepEvent.p.y !== seg2.rightSweepEvent.p.y)
|
|
116
|
-
return seg1.rightSweepEvent.p.y < seg2.rightSweepEvent.p.y ? 1 : -1;
|
|
117
|
-
return 1;
|
|
118
|
-
}
|
|
119
|
-
function _classCallCheck(instance, Constructor) {
|
|
120
|
-
if (!(instance instanceof Constructor)) {
|
|
121
|
-
throw new TypeError("Cannot call a class as a function");
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
function _defineProperties(target, props) {
|
|
125
|
-
for (var i = 0; i < props.length; i++) {
|
|
126
|
-
var descriptor = props[i];
|
|
127
|
-
descriptor.enumerable = descriptor.enumerable || false;
|
|
128
|
-
descriptor.configurable = true;
|
|
129
|
-
if ("value" in descriptor)
|
|
130
|
-
descriptor.writable = true;
|
|
131
|
-
Object.defineProperty(target, descriptor.key, descriptor);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
function _createClass(Constructor, protoProps, staticProps) {
|
|
135
|
-
if (protoProps)
|
|
136
|
-
_defineProperties(Constructor.prototype, protoProps);
|
|
137
|
-
if (staticProps)
|
|
138
|
-
_defineProperties(Constructor, staticProps);
|
|
139
|
-
return Constructor;
|
|
140
|
-
}
|
|
141
|
-
var Event = /*#__PURE__*/ (function () {
|
|
142
|
-
function Event(p, featureId, ringId, eventId) {
|
|
143
|
-
_classCallCheck(this, Event);
|
|
144
|
-
this.p = {
|
|
145
|
-
x: p[0],
|
|
146
|
-
y: p[1],
|
|
147
|
-
};
|
|
148
|
-
this.featureId = featureId;
|
|
149
|
-
this.ringId = ringId;
|
|
150
|
-
this.eventId = eventId;
|
|
151
|
-
this.otherEvent = null;
|
|
152
|
-
this.isLeftEndpoint = null;
|
|
153
|
-
}
|
|
154
|
-
_createClass(Event, [
|
|
155
|
-
{
|
|
156
|
-
key: "isSamePoint",
|
|
157
|
-
value: function isSamePoint(eventToCheck) {
|
|
158
|
-
return this.p.x === eventToCheck.p.x && this.p.y === eventToCheck.p.y;
|
|
159
|
-
},
|
|
160
|
-
},
|
|
161
|
-
]);
|
|
162
|
-
return Event;
|
|
163
|
-
})();
|
|
164
|
-
function fillEventQueue(geojson, eventQueue) {
|
|
165
|
-
if (geojson.type === "FeatureCollection") {
|
|
166
|
-
var features = geojson.features;
|
|
167
|
-
for (var i = 0; i < features.length; i++) {
|
|
168
|
-
processFeature(features[i], eventQueue);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
processFeature(geojson, eventQueue);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
var featureId = 0;
|
|
176
|
-
var ringId = 0;
|
|
177
|
-
var eventId = 0;
|
|
178
|
-
function processFeature(featureOrGeometry, eventQueue) {
|
|
179
|
-
var geom = featureOrGeometry.type === "Feature"
|
|
180
|
-
? featureOrGeometry.geometry
|
|
181
|
-
: featureOrGeometry;
|
|
182
|
-
var coords = geom.coordinates; // standardise the input
|
|
183
|
-
if (geom.type === "Polygon" || geom.type === "MultiLineString")
|
|
184
|
-
coords = [coords];
|
|
185
|
-
if (geom.type === "LineString")
|
|
186
|
-
coords = [[coords]];
|
|
187
|
-
for (var i = 0; i < coords.length; i++) {
|
|
188
|
-
for (var ii = 0; ii < coords[i].length; ii++) {
|
|
189
|
-
var currentP = coords[i][ii][0];
|
|
190
|
-
var nextP = null;
|
|
191
|
-
ringId = ringId + 1;
|
|
192
|
-
for (var iii = 0; iii < coords[i][ii].length - 1; iii++) {
|
|
193
|
-
nextP = coords[i][ii][iii + 1];
|
|
194
|
-
var e1 = new Event(currentP, featureId, ringId, eventId);
|
|
195
|
-
var e2 = new Event(nextP, featureId, ringId, eventId + 1);
|
|
196
|
-
e1.otherEvent = e2;
|
|
197
|
-
e2.otherEvent = e1;
|
|
198
|
-
if (checkWhichEventIsLeft(e1, e2) > 0) {
|
|
199
|
-
e2.isLeftEndpoint = true;
|
|
200
|
-
e1.isLeftEndpoint = false;
|
|
201
|
-
}
|
|
202
|
-
else {
|
|
203
|
-
e1.isLeftEndpoint = true;
|
|
204
|
-
e2.isLeftEndpoint = false;
|
|
205
|
-
}
|
|
206
|
-
eventQueue.push(e1);
|
|
207
|
-
eventQueue.push(e2);
|
|
208
|
-
currentP = nextP;
|
|
209
|
-
eventId = eventId + 1;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
featureId = featureId + 1;
|
|
214
|
-
}
|
|
215
|
-
var Segment = function Segment(event) {
|
|
216
|
-
_classCallCheck(this, Segment);
|
|
217
|
-
this.leftSweepEvent = event;
|
|
218
|
-
this.rightSweepEvent = event.otherEvent;
|
|
219
|
-
};
|
|
220
|
-
function testSegmentIntersect(seg1, seg2) {
|
|
221
|
-
if (seg1 === null || seg2 === null)
|
|
222
|
-
return false;
|
|
223
|
-
if (seg1.leftSweepEvent.ringId === seg2.leftSweepEvent.ringId &&
|
|
224
|
-
(seg1.rightSweepEvent.isSamePoint(seg2.leftSweepEvent) ||
|
|
225
|
-
seg1.rightSweepEvent.isSamePoint(seg2.leftSweepEvent) ||
|
|
226
|
-
seg1.rightSweepEvent.isSamePoint(seg2.rightSweepEvent) ||
|
|
227
|
-
seg1.leftSweepEvent.isSamePoint(seg2.leftSweepEvent) ||
|
|
228
|
-
seg1.leftSweepEvent.isSamePoint(seg2.rightSweepEvent)))
|
|
229
|
-
return false;
|
|
230
|
-
var x1 = seg1.leftSweepEvent.p.x;
|
|
231
|
-
var y1 = seg1.leftSweepEvent.p.y;
|
|
232
|
-
var x2 = seg1.rightSweepEvent.p.x;
|
|
233
|
-
var y2 = seg1.rightSweepEvent.p.y;
|
|
234
|
-
var x3 = seg2.leftSweepEvent.p.x;
|
|
235
|
-
var y3 = seg2.leftSweepEvent.p.y;
|
|
236
|
-
var x4 = seg2.rightSweepEvent.p.x;
|
|
237
|
-
var y4 = seg2.rightSweepEvent.p.y;
|
|
238
|
-
var denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
|
|
239
|
-
var numeA = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
|
|
240
|
-
var numeB = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);
|
|
241
|
-
if (denom === 0) {
|
|
242
|
-
if (numeA === 0 && numeB === 0)
|
|
243
|
-
return false;
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
var uA = numeA / denom;
|
|
247
|
-
var uB = numeB / denom;
|
|
248
|
-
if (uA >= 0 && uA <= 1 && uB >= 0 && uB <= 1) {
|
|
249
|
-
var x = x1 + uA * (x2 - x1);
|
|
250
|
-
var y = y1 + uA * (y2 - y1);
|
|
251
|
-
return [x, y];
|
|
252
|
-
}
|
|
253
|
-
return false;
|
|
254
|
-
}
|
|
255
|
-
function runCheck(eventQueue, ignoreSelfIntersections) {
|
|
256
|
-
ignoreSelfIntersections = ignoreSelfIntersections
|
|
257
|
-
? ignoreSelfIntersections
|
|
258
|
-
: false;
|
|
259
|
-
var intersectionPoints = [];
|
|
260
|
-
var outQueue = new tinyqueue([], checkWhichSegmentHasRightEndpointFirst);
|
|
261
|
-
while (eventQueue.length) {
|
|
262
|
-
var event = eventQueue.pop();
|
|
263
|
-
if (event.isLeftEndpoint) {
|
|
264
|
-
// debugEventAndSegments(event.p, outQueue.data)
|
|
265
|
-
var segment = new Segment(event);
|
|
266
|
-
for (var i = 0; i < outQueue.data.length; i++) {
|
|
267
|
-
var otherSeg = outQueue.data[i];
|
|
268
|
-
if (ignoreSelfIntersections) {
|
|
269
|
-
if (otherSeg.leftSweepEvent.featureId === event.featureId)
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
var intersection = testSegmentIntersect(segment, otherSeg);
|
|
273
|
-
if (intersection !== false)
|
|
274
|
-
intersectionPoints.push(intersection);
|
|
275
|
-
}
|
|
276
|
-
outQueue.push(segment);
|
|
277
|
-
}
|
|
278
|
-
else if (event.isLeftEndpoint === false) {
|
|
279
|
-
outQueue.pop(); // const seg = outQueue.pop()
|
|
280
|
-
// debugRemovingSegment(event.p, seg)
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
return intersectionPoints;
|
|
284
|
-
}
|
|
285
|
-
function sweeplineIntersections(geojson, ignoreSelfIntersections) {
|
|
286
|
-
var eventQueue = new tinyqueue([], checkWhichEventIsLeft);
|
|
287
|
-
fillEventQueue(geojson, eventQueue);
|
|
288
|
-
return runCheck(eventQueue, ignoreSelfIntersections);
|
|
289
|
-
}
|
|
290
|
-
exports.default = sweeplineIntersections;
|