clipper2-ts 2.0.1-13 → 2.0.1-15
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/dist/Engine.d.ts.map +1 -1
- package/dist/Engine.js +13 -28
- package/dist/Engine.js.map +1 -1
- package/dist/Shewchuk.d.ts +3 -0
- package/dist/Shewchuk.d.ts.map +1 -0
- package/dist/Shewchuk.js +953 -0
- package/dist/Shewchuk.js.map +1 -0
- package/dist/Triangulation.d.ts +2 -5
- package/dist/Triangulation.d.ts.map +1 -1
- package/dist/Triangulation.js +85 -259
- package/dist/Triangulation.js.map +1 -1
- package/dist/cdt/SweepCDT.d.ts +7 -0
- package/dist/cdt/SweepCDT.d.ts.map +1 -0
- package/dist/cdt/SweepCDT.js +1272 -0
- package/dist/cdt/SweepCDT.js.map +1 -0
- package/dist/cdt/predicates.d.ts +3 -0
- package/dist/cdt/predicates.d.ts.map +1 -0
- package/dist/cdt/predicates.js +948 -0
- package/dist/cdt/predicates.js.map +1 -0
- package/dist/clipper2.min.mjs +6 -6
- package/dist/clipper2.min.mjs.map +1 -1
- package/package.json +1 -1
- package/src/Engine.ts +4 -17
- package/src/Shewchuk.ts +690 -0
- package/src/Triangulation.ts +87 -272
- package/src/cdt/SweepCDT.ts +1220 -0
- package/src/cdt/predicates.ts +682 -0
package/dist/Triangulation.js
CHANGED
|
@@ -7,10 +7,7 @@
|
|
|
7
7
|
* Purpose : Constrained Delaunay Triangulation *
|
|
8
8
|
* License : https://www.boost.org/LICENSE_1_0.txt *
|
|
9
9
|
*******************************************************************************/
|
|
10
|
-
import {
|
|
11
|
-
// BigInt constant — avoid BigInt literal syntax (0n) to sidestep
|
|
12
|
-
// terser BigInt constant-folding issues in some consuming build setups.
|
|
13
|
-
const B0 = BigInt(0);
|
|
10
|
+
import { adaptiveOrient2dSign, adaptiveIncircleSign } from './Shewchuk.js';
|
|
14
11
|
export var TriangulateResult;
|
|
15
12
|
(function (TriangulateResult) {
|
|
16
13
|
TriangulateResult[TriangulateResult["success"] = 0] = "success";
|
|
@@ -82,6 +79,8 @@ export class Delaunay {
|
|
|
82
79
|
firstActive = null;
|
|
83
80
|
lowermostVertex = null;
|
|
84
81
|
fastMath = false;
|
|
82
|
+
_edgesA = [null, null, null];
|
|
83
|
+
_edgesB = [null, null, null];
|
|
85
84
|
constructor(delaunay = true) {
|
|
86
85
|
this.useDelaunay = delaunay;
|
|
87
86
|
}
|
|
@@ -134,20 +133,18 @@ export class Delaunay {
|
|
|
134
133
|
let i0 = 0;
|
|
135
134
|
let iPrev;
|
|
136
135
|
let iNext;
|
|
137
|
-
|
|
138
|
-
if (
|
|
136
|
+
i0 = Delaunay.findLocMinIdx(path, len, i0);
|
|
137
|
+
if (i0 < 0)
|
|
139
138
|
return;
|
|
140
|
-
i0 = foundIdx.idx;
|
|
141
139
|
iPrev = Delaunay.prev(i0, len);
|
|
142
140
|
while (path[iPrev].x === path[i0].x && path[iPrev].y === path[i0].y)
|
|
143
141
|
iPrev = Delaunay.prev(iPrev, len);
|
|
144
142
|
iNext = Delaunay.next(i0, len);
|
|
145
143
|
let i = i0;
|
|
146
144
|
while (this.crossProductSign(path[iPrev], path[i], path[iNext]) === 0) {
|
|
147
|
-
|
|
148
|
-
if (
|
|
149
|
-
return;
|
|
150
|
-
i = result.idx;
|
|
145
|
+
i = Delaunay.findLocMinIdx(path, len, i);
|
|
146
|
+
if (i < 0)
|
|
147
|
+
return;
|
|
151
148
|
iPrev = Delaunay.prev(i, len);
|
|
152
149
|
while (path[iPrev].x === path[i].x && path[iPrev].y === path[i].y)
|
|
153
150
|
iPrev = Delaunay.prev(iPrev, len);
|
|
@@ -161,19 +158,18 @@ export class Delaunay {
|
|
|
161
158
|
let vPrev = v0;
|
|
162
159
|
i = iNext;
|
|
163
160
|
for (;;) {
|
|
161
|
+
iNext = Delaunay.next(i, len);
|
|
162
|
+
if (this.crossProductSign(vPrev.pt, path[i], path[iNext]) === 0) {
|
|
163
|
+
i = iNext;
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
164
166
|
// vPrev is a locMin here
|
|
165
167
|
this.locMinStack.push(vPrev);
|
|
166
|
-
// ? update lowermostVertex ...
|
|
167
168
|
if (this.lowermostVertex === null ||
|
|
168
169
|
vPrev.pt.y > this.lowermostVertex.pt.y ||
|
|
169
170
|
(vPrev.pt.y === this.lowermostVertex.pt.y &&
|
|
170
171
|
vPrev.pt.x < this.lowermostVertex.pt.x))
|
|
171
172
|
this.lowermostVertex = vPrev;
|
|
172
|
-
iNext = Delaunay.next(i, len);
|
|
173
|
-
if (this.crossProductSign(vPrev.pt, path[i], path[iNext]) === 0) {
|
|
174
|
-
i = iNext;
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
177
173
|
// ascend up next bound to LocMax
|
|
178
174
|
while (path[i].y <= vPrev.pt.y) {
|
|
179
175
|
const v = new Vertex2(path[i]);
|
|
@@ -212,9 +208,9 @@ export class Delaunay {
|
|
|
212
208
|
const pathLen = this.allVertices.length - vert_cnt;
|
|
213
209
|
const idx = vert_cnt;
|
|
214
210
|
if (pathLen < 3 || (pathLen === 3 &&
|
|
215
|
-
((this.
|
|
216
|
-
(this.
|
|
217
|
-
(this.
|
|
211
|
+
((this.distanceSqr(this.allVertices[idx].pt, this.allVertices[idx + 1].pt) <= 1) ||
|
|
212
|
+
(this.distanceSqr(this.allVertices[idx + 1].pt, this.allVertices[idx + 2].pt) <= 1) ||
|
|
213
|
+
(this.distanceSqr(this.allVertices[idx + 2].pt, this.allVertices[idx].pt) <= 1)))) {
|
|
218
214
|
for (let j = vert_cnt; j < this.allVertices.length; ++j)
|
|
219
215
|
this.allVertices[j].edges = []; // flag to ignore
|
|
220
216
|
}
|
|
@@ -411,8 +407,10 @@ export class Delaunay {
|
|
|
411
407
|
return;
|
|
412
408
|
let vertA = null;
|
|
413
409
|
let vertB = null;
|
|
414
|
-
const edgesA =
|
|
415
|
-
const edgesB =
|
|
410
|
+
const edgesA = this._edgesA;
|
|
411
|
+
const edgesB = this._edgesB;
|
|
412
|
+
edgesA[0] = edgesA[1] = edgesA[2] = null;
|
|
413
|
+
edgesB[0] = edgesB[1] = edgesB[2] = null;
|
|
416
414
|
for (let i = 0; i < 3; ++i) {
|
|
417
415
|
if (edge.triA.edges[i] === edge)
|
|
418
416
|
continue;
|
|
@@ -537,7 +535,7 @@ export class Delaunay {
|
|
|
537
535
|
}
|
|
538
536
|
return this.createEdge(vBest, vAbove, EdgeKind.loose);
|
|
539
537
|
}
|
|
540
|
-
doTriangulateLeft(edge, pivot, minY) {
|
|
538
|
+
doTriangulateLeft(edge, pivot, minY, limitFan = false) {
|
|
541
539
|
let vAlt = null;
|
|
542
540
|
let eAlt = null;
|
|
543
541
|
const v = (edge.vB === pivot) ? edge.vT : edge.vB;
|
|
@@ -559,6 +557,13 @@ export class Delaunay {
|
|
|
559
557
|
}
|
|
560
558
|
if (vAlt === null || vAlt.pt.y < minY || eAlt === null)
|
|
561
559
|
return;
|
|
560
|
+
// Domiter & Zalik 2008, §3.2: stop fan extension when angle at pivot > pi/2
|
|
561
|
+
if (limitFan) {
|
|
562
|
+
const dvx = v.pt.x - pivot.pt.x, dvy = v.pt.y - pivot.pt.y;
|
|
563
|
+
const dax = vAlt.pt.x - pivot.pt.x, day = vAlt.pt.y - pivot.pt.y;
|
|
564
|
+
if (dvx * dax + dvy * day < 0)
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
562
567
|
if (vAlt.pt.y < pivot.pt.y) {
|
|
563
568
|
if (Delaunay.isLeftEdge(eAlt))
|
|
564
569
|
return;
|
|
@@ -573,9 +578,9 @@ export class Delaunay {
|
|
|
573
578
|
}
|
|
574
579
|
this.createTriangle(edge, eAlt, eX);
|
|
575
580
|
if (!Delaunay.edgeCompleted(eX))
|
|
576
|
-
this.doTriangulateLeft(eX, vAlt, minY);
|
|
581
|
+
this.doTriangulateLeft(eX, vAlt, minY, true);
|
|
577
582
|
}
|
|
578
|
-
doTriangulateRight(edge, pivot, minY) {
|
|
583
|
+
doTriangulateRight(edge, pivot, minY, limitFan = false) {
|
|
579
584
|
let vAlt = null;
|
|
580
585
|
let eAlt = null;
|
|
581
586
|
const v = (edge.vB === pivot) ? edge.vT : edge.vB;
|
|
@@ -597,6 +602,13 @@ export class Delaunay {
|
|
|
597
602
|
}
|
|
598
603
|
if (vAlt === null || vAlt.pt.y < minY || eAlt === null)
|
|
599
604
|
return;
|
|
605
|
+
// Domiter & Zalik 2008, §3.2: stop fan extension when angle at pivot > pi/2
|
|
606
|
+
if (limitFan) {
|
|
607
|
+
const dvx = v.pt.x - pivot.pt.x, dvy = v.pt.y - pivot.pt.y;
|
|
608
|
+
const dax = vAlt.pt.x - pivot.pt.x, day = vAlt.pt.y - pivot.pt.y;
|
|
609
|
+
if (dvx * dax + dvy * day < 0)
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
600
612
|
if (vAlt.pt.y < pivot.pt.y) {
|
|
601
613
|
if (Delaunay.isRightEdge(eAlt))
|
|
602
614
|
return;
|
|
@@ -611,7 +623,7 @@ export class Delaunay {
|
|
|
611
623
|
}
|
|
612
624
|
this.createTriangle(edge, eX, eAlt);
|
|
613
625
|
if (!Delaunay.edgeCompleted(eX))
|
|
614
|
-
this.doTriangulateRight(eX, vAlt, minY);
|
|
626
|
+
this.doTriangulateRight(eX, vAlt, minY, true);
|
|
615
627
|
}
|
|
616
628
|
addEdgeToActives(edge) {
|
|
617
629
|
if (edge.isActive)
|
|
@@ -783,18 +795,12 @@ export class Delaunay {
|
|
|
783
795
|
return { result: TriangulateResult.success, solution: sol };
|
|
784
796
|
}
|
|
785
797
|
crossProductSign(p1, p2, p3) {
|
|
786
|
-
if (
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
const prod1 = a * b;
|
|
793
|
-
const prod2 = c * d;
|
|
794
|
-
return (prod1 > prod2) ? 1 : (prod1 < prod2) ? -1 : 0;
|
|
795
|
-
}
|
|
796
|
-
distSqr(pt1, pt2) {
|
|
797
|
-
return this.distanceSqr(pt1, pt2);
|
|
798
|
+
if (this.fastMath) {
|
|
799
|
+
const prod1 = (p2.x - p1.x) * (p3.y - p2.y);
|
|
800
|
+
const prod2 = (p2.y - p1.y) * (p3.x - p2.x);
|
|
801
|
+
return (prod1 > prod2) ? 1 : (prod1 < prod2) ? -1 : 0;
|
|
802
|
+
}
|
|
803
|
+
return -adaptiveOrient2dSign(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y);
|
|
798
804
|
}
|
|
799
805
|
distanceSqr(a, b) {
|
|
800
806
|
if (!this.fastMath)
|
|
@@ -858,48 +864,16 @@ export class Delaunay {
|
|
|
858
864
|
return IntersectKind.none;
|
|
859
865
|
}
|
|
860
866
|
inCircleTest(ptA, ptB, ptC, ptD) {
|
|
861
|
-
if (
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
const cadet = cx * ay - ax * cy;
|
|
872
|
-
const alift = ax * ax + ay * ay;
|
|
873
|
-
const blift = bx * bx + by * by;
|
|
874
|
-
const clift = cx * cx + cy * cy;
|
|
875
|
-
const det = alift * bcdet + blift * cadet + clift * abdet;
|
|
876
|
-
const permanent = Math.abs(alift * bcdet) + Math.abs(blift * cadet) + Math.abs(clift * abdet);
|
|
877
|
-
// Error bound from Shewchuk's "Adaptive Precision Floating-Point Arithmetic
|
|
878
|
-
// and Fast Robust Geometric Predicates" (iccerrboundA for 2D in-circle test).
|
|
879
|
-
const eps = Number.EPSILON;
|
|
880
|
-
const errbound = (10 + 96 * eps) * eps * permanent;
|
|
881
|
-
if (det > errbound)
|
|
882
|
-
return 1;
|
|
883
|
-
if (-det > errbound)
|
|
884
|
-
return -1;
|
|
885
|
-
const axBig = BigInt(ptA.x) - BigInt(ptD.x);
|
|
886
|
-
const ayBig = BigInt(ptA.y) - BigInt(ptD.y);
|
|
887
|
-
const bxBig = BigInt(ptB.x) - BigInt(ptD.x);
|
|
888
|
-
const byBig = BigInt(ptB.y) - BigInt(ptD.y);
|
|
889
|
-
const cxBig = BigInt(ptC.x) - BigInt(ptD.x);
|
|
890
|
-
const cyBig = BigInt(ptC.y) - BigInt(ptD.y);
|
|
891
|
-
const abdetBig = axBig * byBig - bxBig * ayBig;
|
|
892
|
-
const bcdetBig = bxBig * cyBig - cxBig * byBig;
|
|
893
|
-
const cadetBig = cxBig * ayBig - axBig * cyBig;
|
|
894
|
-
const aliftBig = axBig * axBig + ayBig * ayBig;
|
|
895
|
-
const bliftBig = bxBig * bxBig + byBig * byBig;
|
|
896
|
-
const cliftBig = cxBig * cxBig + cyBig * cyBig;
|
|
897
|
-
const result = aliftBig * bcdetBig + bliftBig * cadetBig + cliftBig * abdetBig;
|
|
898
|
-
if (result > B0)
|
|
899
|
-
return 1;
|
|
900
|
-
if (result < B0)
|
|
901
|
-
return -1;
|
|
902
|
-
return 0;
|
|
867
|
+
if (this.fastMath) {
|
|
868
|
+
const ax = ptA.x - ptD.x, ay = ptA.y - ptD.y;
|
|
869
|
+
const bx = ptB.x - ptD.x, by = ptB.y - ptD.y;
|
|
870
|
+
const cx = ptC.x - ptD.x, cy = ptC.y - ptD.y;
|
|
871
|
+
const det = (ax * ax + ay * ay) * (bx * cy - cx * by) +
|
|
872
|
+
(bx * bx + by * by) * (cx * ay - ax * cy) +
|
|
873
|
+
(cx * cx + cy * cy) * (ax * by - bx * ay);
|
|
874
|
+
return det > 0 ? 1 : det < 0 ? -1 : 0;
|
|
875
|
+
}
|
|
876
|
+
return adaptiveIncircleSign(ptA.x, ptA.y, ptB.x, ptB.y, ptC.x, ptC.y, ptD.x, ptD.y);
|
|
903
877
|
}
|
|
904
878
|
// ---------------------------------------------------------------------
|
|
905
879
|
// Static / helper functions
|
|
@@ -971,20 +945,20 @@ export class Delaunay {
|
|
|
971
945
|
}
|
|
972
946
|
static findLocMinIdx(path, len, idx) {
|
|
973
947
|
if (len < 3)
|
|
974
|
-
return
|
|
948
|
+
return -1;
|
|
975
949
|
const i0 = idx;
|
|
976
950
|
let n = (idx + 1) % len;
|
|
977
951
|
while (path[n].y <= path[idx].y) {
|
|
978
952
|
idx = n;
|
|
979
953
|
n = (n + 1) % len;
|
|
980
954
|
if (idx === i0)
|
|
981
|
-
return
|
|
955
|
+
return -1;
|
|
982
956
|
}
|
|
983
957
|
while (path[n].y >= path[idx].y) {
|
|
984
958
|
idx = n;
|
|
985
959
|
n = (n + 1) % len;
|
|
986
960
|
}
|
|
987
|
-
return
|
|
961
|
+
return idx;
|
|
988
962
|
}
|
|
989
963
|
static prev(idx, len) {
|
|
990
964
|
if (idx === 0)
|
|
@@ -1019,213 +993,65 @@ export class Delaunay {
|
|
|
1019
993
|
res.push(e.vL.pt);
|
|
1020
994
|
return res;
|
|
1021
995
|
}
|
|
1022
|
-
static areSafePoints(...pts) {
|
|
1023
|
-
for (const pt of pts) {
|
|
1024
|
-
if (!Number.isSafeInteger(pt.x) || !Number.isSafeInteger(pt.y))
|
|
1025
|
-
return false;
|
|
1026
|
-
}
|
|
1027
|
-
return true;
|
|
1028
|
-
}
|
|
1029
996
|
static maxSafeDelta = Math.floor(Math.sqrt(Number.MAX_SAFE_INTEGER / 2));
|
|
1030
|
-
static areSafeDeltas(...vals) {
|
|
1031
|
-
for (const v of vals) {
|
|
1032
|
-
if (Math.abs(v) > Delaunay.maxSafeDelta)
|
|
1033
|
-
return false;
|
|
1034
|
-
}
|
|
1035
|
-
return true;
|
|
1036
|
-
}
|
|
1037
|
-
static inCircleTest(ptA, ptB, ptC, ptD) {
|
|
1038
|
-
const ax = ptA.x - ptD.x;
|
|
1039
|
-
const ay = ptA.y - ptD.y;
|
|
1040
|
-
const bx = ptB.x - ptD.x;
|
|
1041
|
-
const by = ptB.y - ptD.y;
|
|
1042
|
-
const cx = ptC.x - ptD.x;
|
|
1043
|
-
const cy = ptC.y - ptD.y;
|
|
1044
|
-
const abdet = ax * by - bx * ay;
|
|
1045
|
-
const bcdet = bx * cy - cx * by;
|
|
1046
|
-
const cadet = cx * ay - ax * cy;
|
|
1047
|
-
const alift = ax * ax + ay * ay;
|
|
1048
|
-
const blift = bx * bx + by * by;
|
|
1049
|
-
const clift = cx * cx + cy * cy;
|
|
1050
|
-
const det = alift * bcdet + blift * cadet + clift * abdet;
|
|
1051
|
-
const permanent = Math.abs(alift * bcdet) + Math.abs(blift * cadet) + Math.abs(clift * abdet);
|
|
1052
|
-
// Error bound from Shewchuk's "Adaptive Precision Floating-Point Arithmetic
|
|
1053
|
-
// and Fast Robust Geometric Predicates" (iccerrboundA for 2D in-circle test).
|
|
1054
|
-
// See: https://www.cs.cmu.edu/~quake/robust.html
|
|
1055
|
-
const eps = Number.EPSILON;
|
|
1056
|
-
const errbound = (10 + 96 * eps) * eps * permanent;
|
|
1057
|
-
if (det > errbound)
|
|
1058
|
-
return 1;
|
|
1059
|
-
if (-det > errbound)
|
|
1060
|
-
return -1;
|
|
1061
|
-
if (Delaunay.areSafePoints(ptA, ptB, ptC, ptD)) {
|
|
1062
|
-
const ax = BigInt(ptA.x) - BigInt(ptD.x);
|
|
1063
|
-
const ay = BigInt(ptA.y) - BigInt(ptD.y);
|
|
1064
|
-
const bx = BigInt(ptB.x) - BigInt(ptD.x);
|
|
1065
|
-
const by = BigInt(ptB.y) - BigInt(ptD.y);
|
|
1066
|
-
const cx = BigInt(ptC.x) - BigInt(ptD.x);
|
|
1067
|
-
const cy = BigInt(ptC.y) - BigInt(ptD.y);
|
|
1068
|
-
const abdet = ax * by - bx * ay;
|
|
1069
|
-
const bcdet = bx * cy - cx * by;
|
|
1070
|
-
const cadet = cx * ay - ax * cy;
|
|
1071
|
-
const alift = ax * ax + ay * ay;
|
|
1072
|
-
const blift = bx * bx + by * by;
|
|
1073
|
-
const clift = cx * cx + cy * cy;
|
|
1074
|
-
const result = alift * bcdet + blift * cadet + clift * abdet;
|
|
1075
|
-
if (result > B0)
|
|
1076
|
-
return 1;
|
|
1077
|
-
if (result < B0)
|
|
1078
|
-
return -1;
|
|
1079
|
-
return 0;
|
|
1080
|
-
}
|
|
1081
|
-
return det > 0 ? 1 : det < 0 ? -1 : 0;
|
|
1082
|
-
}
|
|
1083
997
|
static shortestDistFromSegment(pt, segPt1, segPt2) {
|
|
1084
998
|
const dx = segPt2.x - segPt1.x;
|
|
1085
999
|
const dy = segPt2.y - segPt1.y;
|
|
1086
1000
|
const ax = pt.x - segPt1.x;
|
|
1087
1001
|
const ay = pt.y - segPt1.y;
|
|
1088
|
-
const
|
|
1089
|
-
|
|
1090
|
-
if (Delaunay.areSafeDeltas(dx, dy, ax, ay)) {
|
|
1091
|
-
if (qNum < 0)
|
|
1092
|
-
return Delaunay.distanceSqr(pt, segPt1);
|
|
1093
|
-
if (qNum > denom)
|
|
1094
|
-
return Delaunay.distanceSqr(pt, segPt2);
|
|
1095
|
-
return (ax * dy - dx * ay) * (ax * dy - dx * ay) / denom;
|
|
1096
|
-
}
|
|
1097
|
-
if (Delaunay.areSafePoints(pt, segPt1, segPt2)) {
|
|
1098
|
-
const dx = BigInt(segPt2.x) - BigInt(segPt1.x);
|
|
1099
|
-
const dy = BigInt(segPt2.y) - BigInt(segPt1.y);
|
|
1100
|
-
const ax = BigInt(pt.x) - BigInt(segPt1.x);
|
|
1101
|
-
const ay = BigInt(pt.y) - BigInt(segPt1.y);
|
|
1002
|
+
const msd = Delaunay.maxSafeDelta;
|
|
1003
|
+
if (Math.abs(dx) <= msd && Math.abs(dy) <= msd && Math.abs(ax) <= msd && Math.abs(ay) <= msd) {
|
|
1102
1004
|
const qNum = ax * dx + ay * dy;
|
|
1103
1005
|
const denom = dx * dx + dy * dy;
|
|
1104
|
-
if (qNum <
|
|
1006
|
+
if (qNum < 0)
|
|
1105
1007
|
return Delaunay.distanceSqr(pt, segPt1);
|
|
1106
1008
|
if (qNum > denom)
|
|
1107
1009
|
return Delaunay.distanceSqr(pt, segPt2);
|
|
1108
|
-
|
|
1109
|
-
return Number(cross * cross) / Number(denom);
|
|
1010
|
+
return (ax * dy - dx * ay) * (ax * dy - dx * ay) / denom;
|
|
1110
1011
|
}
|
|
1111
|
-
|
|
1012
|
+
const dxB = BigInt(segPt2.x) - BigInt(segPt1.x);
|
|
1013
|
+
const dyB = BigInt(segPt2.y) - BigInt(segPt1.y);
|
|
1014
|
+
const axB = BigInt(pt.x) - BigInt(segPt1.x);
|
|
1015
|
+
const ayB = BigInt(pt.y) - BigInt(segPt1.y);
|
|
1016
|
+
const qNum = axB * dxB + ayB * dyB;
|
|
1017
|
+
const denom = dxB * dxB + dyB * dyB;
|
|
1018
|
+
const B0 = BigInt(0);
|
|
1019
|
+
if (qNum < B0)
|
|
1112
1020
|
return Delaunay.distanceSqr(pt, segPt1);
|
|
1113
1021
|
if (qNum > denom)
|
|
1114
1022
|
return Delaunay.distanceSqr(pt, segPt2);
|
|
1115
|
-
|
|
1023
|
+
const cross = axB * dyB - dxB * ayB;
|
|
1024
|
+
return Number(cross * cross) / Number(denom);
|
|
1116
1025
|
}
|
|
1117
1026
|
static segsIntersect(s1a, s1b, s2a, s2b) {
|
|
1118
|
-
// ignore segments sharing an end-point
|
|
1119
1027
|
if ((s1a.x === s2a.x && s1a.y === s2a.y) ||
|
|
1120
1028
|
(s1a.x === s2b.x && s1a.y === s2b.y) ||
|
|
1121
1029
|
(s1b.x === s2b.x && s1b.y === s2b.y))
|
|
1122
1030
|
return IntersectKind.none;
|
|
1123
|
-
const
|
|
1124
|
-
const
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
const dys = s1a.y - s2a.y;
|
|
1129
|
-
if (Delaunay.areSafeDeltas(dy1, dx1, dy2, dx2, dxs, dys)) {
|
|
1130
|
-
const cp = dy1 * dx2 - dy2 * dx1;
|
|
1131
|
-
if (cp === 0)
|
|
1132
|
-
return IntersectKind.collinear;
|
|
1133
|
-
let t = dxs * dy2 - dys * dx2;
|
|
1134
|
-
// nb: testing for t === 0 is unreliable due to float imprecision
|
|
1135
|
-
if (t >= 0) {
|
|
1136
|
-
if (cp < 0 || t >= cp)
|
|
1137
|
-
return IntersectKind.none;
|
|
1138
|
-
}
|
|
1139
|
-
else {
|
|
1140
|
-
if (cp > 0 || t <= cp)
|
|
1141
|
-
return IntersectKind.none;
|
|
1142
|
-
}
|
|
1143
|
-
t = dxs * dy1 - dys * dx1;
|
|
1144
|
-
if (t >= 0) {
|
|
1145
|
-
if (cp > 0 && t < cp)
|
|
1146
|
-
return IntersectKind.intersect;
|
|
1147
|
-
}
|
|
1148
|
-
else {
|
|
1149
|
-
if (cp < 0 && t > cp)
|
|
1150
|
-
return IntersectKind.intersect;
|
|
1151
|
-
}
|
|
1031
|
+
const d1 = adaptiveOrient2dSign(s2a.x, s2a.y, s2b.x, s2b.y, s1a.x, s1a.y);
|
|
1032
|
+
const d2 = adaptiveOrient2dSign(s2a.x, s2a.y, s2b.x, s2b.y, s1b.x, s1b.y);
|
|
1033
|
+
if (d1 === 0 && d2 === 0)
|
|
1034
|
+
return IntersectKind.collinear;
|
|
1035
|
+
if (d1 === 0 || d2 === 0 || d1 === d2)
|
|
1152
1036
|
return IntersectKind.none;
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
const dx1 = BigInt(s1b.x) - BigInt(s1a.x);
|
|
1157
|
-
const dy2 = BigInt(s2b.y) - BigInt(s2a.y);
|
|
1158
|
-
const dx2 = BigInt(s2b.x) - BigInt(s2a.x);
|
|
1159
|
-
const cp = dy1 * dx2 - dy2 * dx1;
|
|
1160
|
-
if (cp === B0)
|
|
1161
|
-
return IntersectKind.collinear;
|
|
1162
|
-
let t = (BigInt(s1a.x) - BigInt(s2a.x)) * dy2 -
|
|
1163
|
-
(BigInt(s1a.y) - BigInt(s2a.y)) * dx2;
|
|
1164
|
-
if (t === B0)
|
|
1165
|
-
return IntersectKind.none;
|
|
1166
|
-
if (t > B0) {
|
|
1167
|
-
if (cp < B0 || t >= cp)
|
|
1168
|
-
return IntersectKind.none;
|
|
1169
|
-
}
|
|
1170
|
-
else {
|
|
1171
|
-
if (cp > B0 || t <= cp)
|
|
1172
|
-
return IntersectKind.none;
|
|
1173
|
-
}
|
|
1174
|
-
t = (BigInt(s1a.x) - BigInt(s2a.x)) * dy1 -
|
|
1175
|
-
(BigInt(s1a.y) - BigInt(s2a.y)) * dx1;
|
|
1176
|
-
if (t === B0)
|
|
1177
|
-
return IntersectKind.none;
|
|
1178
|
-
if (t > B0) {
|
|
1179
|
-
if (cp > B0 && t < cp)
|
|
1180
|
-
return IntersectKind.intersect;
|
|
1181
|
-
}
|
|
1182
|
-
else {
|
|
1183
|
-
if (cp < B0 && t > cp)
|
|
1184
|
-
return IntersectKind.intersect;
|
|
1185
|
-
}
|
|
1037
|
+
const d3 = adaptiveOrient2dSign(s1a.x, s1a.y, s1b.x, s1b.y, s2a.x, s2a.y);
|
|
1038
|
+
const d4 = adaptiveOrient2dSign(s1a.x, s1a.y, s1b.x, s1b.y, s2b.x, s2b.y);
|
|
1039
|
+
if (d3 === 0 || d4 === 0 || d3 === d4)
|
|
1186
1040
|
return IntersectKind.none;
|
|
1187
|
-
|
|
1188
|
-
const cp = dy1 * dx2 - dy2 * dx1;
|
|
1189
|
-
if (cp === 0)
|
|
1190
|
-
return IntersectKind.collinear;
|
|
1191
|
-
let t = dxs * dy2 - dys * dx2;
|
|
1192
|
-
// nb: testing for t === 0 is unreliable due to float imprecision
|
|
1193
|
-
if (t >= 0) {
|
|
1194
|
-
if (cp < 0 || t >= cp)
|
|
1195
|
-
return IntersectKind.none;
|
|
1196
|
-
}
|
|
1197
|
-
else {
|
|
1198
|
-
if (cp > 0 || t <= cp)
|
|
1199
|
-
return IntersectKind.none;
|
|
1200
|
-
}
|
|
1201
|
-
t = dxs * dy1 - dys * dx1;
|
|
1202
|
-
if (t >= 0) {
|
|
1203
|
-
if (cp > 0 && t < cp)
|
|
1204
|
-
return IntersectKind.intersect;
|
|
1205
|
-
}
|
|
1206
|
-
else {
|
|
1207
|
-
if (cp < 0 && t > cp)
|
|
1208
|
-
return IntersectKind.intersect;
|
|
1209
|
-
}
|
|
1210
|
-
return IntersectKind.none;
|
|
1211
|
-
}
|
|
1212
|
-
static distSqr(pt1, pt2) {
|
|
1213
|
-
return Delaunay.distanceSqr(pt1, pt2);
|
|
1041
|
+
return IntersectKind.intersect;
|
|
1214
1042
|
}
|
|
1215
1043
|
static distanceSqr(a, b) {
|
|
1216
1044
|
const dx = a.x - b.x;
|
|
1217
1045
|
const dy = a.y - b.y;
|
|
1218
|
-
|
|
1046
|
+
const msd = Delaunay.maxSafeDelta;
|
|
1047
|
+
if (Math.abs(dx) <= msd && Math.abs(dy) <= msd) {
|
|
1219
1048
|
const dist = dx * dx + dy * dy;
|
|
1220
1049
|
if (dist <= Number.MAX_SAFE_INTEGER)
|
|
1221
1050
|
return dist;
|
|
1222
1051
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
return Number(dxBig * dxBig + dyBig * dyBig);
|
|
1227
|
-
}
|
|
1228
|
-
return dx * dx + dy * dy;
|
|
1052
|
+
const dxB = BigInt(a.x) - BigInt(b.x);
|
|
1053
|
+
const dyB = BigInt(a.y) - BigInt(b.y);
|
|
1054
|
+
return Number(dxB * dxB + dyB * dyB);
|
|
1229
1055
|
}
|
|
1230
1056
|
}
|
|
1231
1057
|
//# sourceMappingURL=Triangulation.js.map
|