flo-mat 4.1.3 → 4.1.4
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/__tests__/find-2-prong/get-medial/dd-get-medial-point-coeffs-same-curve.spec.ts +1 -1
- package/__tests__/specific-cases/specific-cases.spec.ts +1 -14
- package/__tests__/specific-cases/test-svgs/achispado.svg +37 -24
- package/browser/index.js +404 -195
- package/browser/index.min.js +1 -1
- package/node/cp-node/fs/insert-cp-node.d.ts +12 -1
- package/node/cp-node/fs/insert-cp-node.js +21 -6
- package/node/cp-node/fs/insert-cp-node.js.map +1 -1
- package/node/cp-node/fs/is-order-correct.d.ts +9 -1
- package/node/cp-node/fs/is-order-correct.js +51 -10
- package/node/cp-node/fs/is-order-correct.js.map +1 -1
- package/node/cp-node/fs/remove-cp-node.js +1 -1
- package/node/cp-node/fs/remove-cp-node.js.map +1 -1
- package/node/debug/functions/check-ordering.d.ts +4 -0
- package/node/debug/functions/check-ordering.js +43 -0
- package/node/debug/functions/check-ordering.js.map +1 -0
- package/node/find-2-prong/add-2-prong.js +4 -2
- package/node/find-2-prong/add-2-prong.js.map +1 -1
- package/node/find-2-prong/find-and-add-2-prongs.js +1 -1
- package/node/find-2-prong/find-and-add-2-prongs.js.map +1 -1
- package/node/find-2-prong/get-initial-bezier-pieces.js +2 -2
- package/node/find-2-prong/get-initial-bezier-pieces.js.map +1 -1
- package/node/find-3-prong/find-3-prong-for-delta3s.d.ts +1 -1
- package/node/find-3-prong/find-3-prong-for-delta3s.js.map +1 -1
- package/node/find-3-prong/find-3-prong.d.ts +1 -1
- package/node/find-3-prong/find-3-prong.js.map +1 -1
- package/node/find-3-prong/find-and-add-3-prong.js +1 -1
- package/node/find-3-prong/find-and-add-3-prong.js.map +1 -1
- package/node/find-3-prong/find-and-add-3-prongs-on-loop.d.ts +1 -1
- package/node/find-3-prong/find-and-add-3-prongs-on-loop.js +6 -2
- package/node/find-3-prong/find-and-add-3-prongs-on-loop.js.map +1 -1
- package/node/find-3-prong/three-prong-info.d.ts +1 -1
- package/node/find-mat/create-initial-cp-tree.js +2 -2
- package/node/find-mat/create-initial-cp-tree.js.map +1 -1
- package/node/find-mat/find-mat.js +2 -2
- package/node/find-mat/find-mat.js.map +1 -1
- package/node/find-mat/get-for-1-prongs-on-loop.js +3 -1
- package/node/find-mat/get-for-1-prongs-on-loop.js.map +1 -1
- package/node/mat/add-to-cp-tree.d.ts +4 -1
- package/node/mat/add-to-cp-tree.js +11 -4
- package/node/mat/add-to-cp-tree.js.map +1 -1
- package/node/mat/get-boundary-piece-beziers.d.ts +2 -2
- package/node/mat/get-boundary-piece-beziers.js +1 -1
- package/node/mat/get-boundary-piece-beziers.js.map +1 -1
- package/node/mat/get-closeby-cp-if-exist.js +2 -2
- package/node/mat/get-closeby-cp-if-exist.js.map +1 -1
- package/node/mat/{get-cp-node-to-left-or-same.d.ts → get-cp-node-neighbors.d.ts} +2 -2
- package/node/mat/get-cp-node-neighbors.js +31 -0
- package/node/mat/get-cp-node-neighbors.js.map +1 -0
- package/package.json +8 -8
- package/src/cp-node/fs/insert-cp-node.ts +22 -7
- package/src/cp-node/fs/is-order-correct copy.ts +60 -0
- package/src/cp-node/fs/is-order-correct.ts +61 -13
- package/src/cp-node/fs/remove-cp-node.ts +1 -1
- package/src/debug/functions/check-ordering.ts +44 -61
- package/src/find-2-prong/add-2-prong.ts +3 -1
- package/src/find-2-prong/find-and-add-2-prongs.ts +1 -1
- package/src/find-2-prong/get-initial-bezier-pieces.ts +2 -2
- package/src/find-3-prong/find-3-prong-for-delta3s.ts +14 -6
- package/src/find-3-prong/find-3-prong.ts +1 -1
- package/src/find-3-prong/find-and-add-3-prong.ts +1 -4
- package/src/find-3-prong/find-and-add-3-prongs-on-loop.ts +6 -3
- package/src/find-3-prong/three-prong-info.ts +1 -1
- package/src/find-mat/create-initial-cp-tree.ts +2 -2
- package/src/find-mat/find-mat.ts +3 -2
- package/src/find-mat/get-for-1-prongs-on-loop.ts +3 -1
- package/src/mat/add-to-cp-tree copy.ts +71 -0
- package/src/mat/add-to-cp-tree.ts +12 -4
- package/src/mat/get-boundary-piece-beziers.ts +2 -2
- package/src/mat/get-closeby-cp-if-exist.ts +2 -2
- package/src/mat/{get-cp-node-to-left-or-same.ts → get-cp-node-neighbors.ts} +12 -10
- package/node/mat/get-cp-node-to-left-or-same.js +0 -30
- package/node/mat/get-cp-node-to-left-or-same.js.map +0 -1
package/browser/index.js
CHANGED
|
@@ -1903,7 +1903,7 @@ function removeCpNode(cpNode, meta) {
|
|
|
1903
1903
|
prev.next = next;
|
|
1904
1904
|
next.prev = prev;
|
|
1905
1905
|
const cpTree = cpTrees.get(cpNode.pointOnShape.curve.loop);
|
|
1906
|
-
cpTree.remove(cpNode
|
|
1906
|
+
cpTree.remove(cpNode);
|
|
1907
1907
|
}
|
|
1908
1908
|
|
|
1909
1909
|
|
|
@@ -2722,8 +2722,8 @@ function toPowerBasis_1stDerivative(ps) {
|
|
|
2722
2722
|
function toPowerBasis3_1stDerivative(ps) {
|
|
2723
2723
|
const [[x0, y0], [x1, y1], [x2, y2], [x3, y3]] = ps;
|
|
2724
2724
|
return [[
|
|
2725
|
-
3 * ((x3 - x0) + 3 * (x1 - x2)),
|
|
2726
|
-
6 * ((x2 + x0) - 2 * x1),
|
|
2725
|
+
3 * ((x3 - x0) + 3 * (x1 - x2)), // max === 24*max(c); max 5 bit-length increase
|
|
2726
|
+
6 * ((x2 + x0) - 2 * x1), // max === 24*max(c); max 5 bit-length increase
|
|
2727
2727
|
3 * (x1 - x0)
|
|
2728
2728
|
], [
|
|
2729
2729
|
3 * ((y3 - y0) + 3 * (y1 - y2)),
|
|
@@ -19053,9 +19053,9 @@ function toPowerBasis(ps) {
|
|
|
19053
19053
|
function to_power_basis_toPowerBasis3(ps) {
|
|
19054
19054
|
const [[x0, y0], [x1, y1], [x2, y2], [x3, y3]] = ps;
|
|
19055
19055
|
return [[
|
|
19056
|
-
(x3 - x0) + 3 * (x1 - x2),
|
|
19057
|
-
3 * ((x2 + x0) - 2 * x1),
|
|
19058
|
-
3 * (x1 - x0),
|
|
19056
|
+
(x3 - x0) + 3 * (x1 - x2), // max 3 bit-length increase
|
|
19057
|
+
3 * ((x2 + x0) - 2 * x1), // max 4 bit-length increase
|
|
19058
|
+
3 * (x1 - x0), // max 3 bit-length increase
|
|
19059
19059
|
x0
|
|
19060
19060
|
], [
|
|
19061
19061
|
(y3 - y0) + 3 * (y1 - y2),
|
|
@@ -19082,10 +19082,10 @@ function to_power_basis_toPowerBasis1(ps) {
|
|
|
19082
19082
|
const [[x0, y0], [x1, y1]] = ps;
|
|
19083
19083
|
return [[
|
|
19084
19084
|
x1 - x0,
|
|
19085
|
-
x0
|
|
19085
|
+
x0
|
|
19086
19086
|
], [
|
|
19087
19087
|
y1 - y0,
|
|
19088
|
-
y0
|
|
19088
|
+
y0
|
|
19089
19089
|
]];
|
|
19090
19090
|
}
|
|
19091
19091
|
/** @internal */
|
|
@@ -23541,12 +23541,7 @@ function getCurvatureExtrema(ps) {
|
|
|
23541
23541
|
const dp2_ = Horner(dp2, t);
|
|
23542
23542
|
const p1_ = Horner(p1, t);
|
|
23543
23543
|
const secondDerivative = p1_ * dp2_;
|
|
23544
|
-
|
|
23545
|
-
minima.push(t);
|
|
23546
|
-
}
|
|
23547
|
-
else {
|
|
23548
|
-
maxima.push(t);
|
|
23549
|
-
}
|
|
23544
|
+
(secondDerivative >= 0 ? minima : maxima).push(t);
|
|
23550
23545
|
}
|
|
23551
23546
|
const inflections = roots(p1, 0, 1)?.map(r => r.t) || [];
|
|
23552
23547
|
return { minima, maxima, inflections };
|
|
@@ -23558,23 +23553,6 @@ function getCurvatureExtrema(ps) {
|
|
|
23558
23553
|
|
|
23559
23554
|
|
|
23560
23555
|
const { sqrt: curvature_sqrt } = Math;
|
|
23561
|
-
/**
|
|
23562
|
-
* Returns the numerator and denominator of curvature `[N,D]`, i.e. `κ = N/D`
|
|
23563
|
-
*
|
|
23564
|
-
* @param ps
|
|
23565
|
-
* @param t
|
|
23566
|
-
*/
|
|
23567
|
-
function curvatureND(ps, t) {
|
|
23568
|
-
const [dX, dY] = toPowerBasis_1stDerivative(ps);
|
|
23569
|
-
const [ddX, ddY] = toPowerBasis_2ndDerivative(ps);
|
|
23570
|
-
const dx = Horner(dX, t);
|
|
23571
|
-
const dy = Horner(dY, t);
|
|
23572
|
-
const ddx = Horner(ddX, t);
|
|
23573
|
-
const ddy = Horner(ddY, t);
|
|
23574
|
-
const a = dx * ddy - dy * ddx;
|
|
23575
|
-
const b = curvature_sqrt((dx * dx + dy * dy) ** 3);
|
|
23576
|
-
return [a, b];
|
|
23577
|
-
}
|
|
23578
23556
|
/**
|
|
23579
23557
|
* Returns the curvature `κ` of the given linear, quadratic or cubic bezier
|
|
23580
23558
|
* curve at a specific given parameter value `t`.
|
|
@@ -23590,16 +23568,6 @@ function curvature(ps, t) {
|
|
|
23590
23568
|
const [N, D] = curvatureND(ps, t);
|
|
23591
23569
|
return N / D;
|
|
23592
23570
|
}
|
|
23593
|
-
/**
|
|
23594
|
-
* Returns the radius of curvature.
|
|
23595
|
-
*
|
|
23596
|
-
* @param ps
|
|
23597
|
-
* @param t
|
|
23598
|
-
*/
|
|
23599
|
-
function radiusOfCurvature(ps, t) {
|
|
23600
|
-
const [N, D] = curvatureND(ps, t);
|
|
23601
|
-
return D / N;
|
|
23602
|
-
}
|
|
23603
23571
|
/**
|
|
23604
23572
|
* Alias for [[κ]].
|
|
23605
23573
|
*
|
|
@@ -23614,6 +23582,33 @@ function radiusOfCurvature(ps, t) {
|
|
|
23614
23582
|
* @doc
|
|
23615
23583
|
*/
|
|
23616
23584
|
const κ = (/* unused pure expression or super */ null && (curvature));
|
|
23585
|
+
/**
|
|
23586
|
+
* Returns the radius of curvature.
|
|
23587
|
+
*
|
|
23588
|
+
* @param ps
|
|
23589
|
+
* @param t
|
|
23590
|
+
*/
|
|
23591
|
+
function radiusOfCurvature(ps, t) {
|
|
23592
|
+
const [N, D] = curvatureND(ps, t);
|
|
23593
|
+
return D / N;
|
|
23594
|
+
}
|
|
23595
|
+
/**
|
|
23596
|
+
* Returns the numerator and denominator of curvature `[N,D]`, i.e. `κ = N/D`
|
|
23597
|
+
*
|
|
23598
|
+
* @param ps
|
|
23599
|
+
* @param t
|
|
23600
|
+
*/
|
|
23601
|
+
function curvatureND(ps, t) {
|
|
23602
|
+
const [dX, dY] = toPowerBasis_1stDerivative(ps);
|
|
23603
|
+
const [ddX, ddY] = toPowerBasis_2ndDerivative(ps);
|
|
23604
|
+
const dx = Horner(dX, t);
|
|
23605
|
+
const dy = Horner(dY, t);
|
|
23606
|
+
const ddx = Horner(ddX, t);
|
|
23607
|
+
const ddy = Horner(ddY, t);
|
|
23608
|
+
const a = dx * ddy - dy * ddx;
|
|
23609
|
+
const b = curvature_sqrt((dx * dx + dy * dy) ** 3);
|
|
23610
|
+
return [a, b];
|
|
23611
|
+
}
|
|
23617
23612
|
|
|
23618
23613
|
//# sourceMappingURL=curvature.js.map
|
|
23619
23614
|
;// ./node_modules/flo-boolean/node/get-critical-points/get-excessive-curvatures.js
|
|
@@ -24900,7 +24895,7 @@ class Heap {
|
|
|
24900
24895
|
}
|
|
24901
24896
|
|
|
24902
24897
|
//# sourceMappingURL=heap.js.map
|
|
24903
|
-
;// ./node_modules/flo-bezier3/node/simultaneous-properties/hausdorff-distance/hausdorff-distance-one-sided.js
|
|
24898
|
+
;// ./node_modules/flo-bezier3/node/simultaneous-properties/hausdorff-distance/hausdorff-distance-one-sided-extra.js
|
|
24904
24899
|
|
|
24905
24900
|
|
|
24906
24901
|
|
|
@@ -24912,26 +24907,15 @@ class Heap {
|
|
|
24912
24907
|
|
|
24913
24908
|
|
|
24914
24909
|
/** @internal */
|
|
24915
|
-
const { max:
|
|
24916
|
-
// We need to calculate `H(A,B)`, the two sided Hausdorff distance between
|
|
24917
|
-
// the bezier curves `A` and `B` which equals `max(h(A,B), h(B,A))`, where
|
|
24918
|
-
// `h(A,B)` is the one sided Hausdorff distance from `A` to `B`
|
|
24919
|
-
// Let: ωf(σ) = sup{ |f(t) − f(t′)| : t, t′ ∈ [a,b] with |t − t′| ≤ σ }
|
|
24920
|
-
// where: δS = max[ (1 ≤ i ≤ M+1)(ti − ti−1) ] is the maximum distance between
|
|
24921
|
-
// two consecutive parameter values
|
|
24922
|
-
// Lemma 2.1:
|
|
24923
|
-
// h(A,S) ≤ ωf(δS/2) and
|
|
24924
|
-
// h(B,T) ≤ ωg(δT/2)
|
|
24925
|
-
// Theorem 2.3: (both curves discretized)
|
|
24926
|
-
// |h(S,T) − h(A,B)| ≤ max[ h(A,S), h(B,T) ]
|
|
24927
|
-
// ≤ max[ ωf(δS/2), ωg(δT/2) ]
|
|
24928
|
-
//
|
|
24929
|
-
// (only A discretized)
|
|
24930
|
-
// |h(S,B) − h(A,B)| ≤ ωf(δS/2)
|
|
24910
|
+
const { max: hausdorff_distance_one_sided_extra_max } = Math;
|
|
24931
24911
|
/**
|
|
24932
24912
|
* Calculates and returns an accurate approximation to the one-sided Hausdorff
|
|
24933
|
-
* distance from the bezier curve `A` to the bezier curve `B
|
|
24913
|
+
* distance from the bezier curve `A` to the bezier curve `B`, together with the
|
|
24914
|
+
* parameter values and points on both curves where the distance is
|
|
24915
|
+
* (approximately) achieved.
|
|
24934
24916
|
*
|
|
24917
|
+
* * this is the implementation backing `hausdorffDistanceOneSided`, which simply
|
|
24918
|
+
* returns the `.d` property of this function's result
|
|
24935
24919
|
* * partially based off [Computing the Hausdorff distance between two sets of parametric curves](https://www.semanticscholar.org/paper/COMPUTING-THE-HAUSDORFF-DISTANCE-BETWEEN-TWO-SETS-Kim-McLean/d2bd6529c4b118e389e1db209d8f1bf7467f9016)
|
|
24936
24920
|
*
|
|
24937
24921
|
* @param A a bezier curve (the 'from' curve) given by an ordered array of its
|
|
@@ -24949,21 +24933,25 @@ const { max: hausdorff_distance_one_sided_max } = Math;
|
|
|
24949
24933
|
*
|
|
24950
24934
|
* @doc mdx
|
|
24951
24935
|
*/
|
|
24952
|
-
function
|
|
24936
|
+
function hausdorffDistanceOneSidedExtra(A, B, tolerance, maxIterations = 50) {
|
|
24953
24937
|
if (A.length === 1) {
|
|
24954
|
-
|
|
24938
|
+
const c = closestPointOnBezier(B, A[0]);
|
|
24939
|
+
return { d: c.d, tA: 0, pA: A[0], tB: c.t, pB: c.p };
|
|
24955
24940
|
}
|
|
24956
24941
|
if (B.length === 1) {
|
|
24957
|
-
|
|
24942
|
+
const f = furthestPointOnBezier(A, B[0]);
|
|
24943
|
+
return { d: f.d, tA: f.t, pA: f.p, tB: 0, pB: B[0] };
|
|
24958
24944
|
}
|
|
24959
24945
|
if (A.length === 2 && B.length === 2) {
|
|
24960
24946
|
// Seperately handle the simple case of two lines
|
|
24961
24947
|
// Find minimum distance from endpoints of A to B:
|
|
24962
|
-
const
|
|
24963
|
-
const
|
|
24964
|
-
return
|
|
24948
|
+
const c0 = closestPointOnBezier(B, A[0]);
|
|
24949
|
+
const c1 = closestPointOnBezier(B, A[A.length - 1]);
|
|
24950
|
+
return c0.d > c1.d
|
|
24951
|
+
? { d: c0.d, tA: 0, pA: A[0], tB: c0.t, pB: c0.p }
|
|
24952
|
+
: { d: c1.d, tA: 1, pA: A[A.length - 1], tB: c1.t, pB: c1.p };
|
|
24965
24953
|
}
|
|
24966
|
-
const l =
|
|
24954
|
+
const l = hausdorff_distance_one_sided_extra_max(maxAbsCoordinate(A), maxAbsCoordinate(B));
|
|
24967
24955
|
tolerance = tolerance || l / 1000_000;
|
|
24968
24956
|
// an array of intervals
|
|
24969
24957
|
const [eL, eR] = calcHErrorBound(A, 0, 1);
|
|
@@ -24976,8 +24964,8 @@ function hausdorffDistanceOneSided(A, B, tolerance, maxIterations = 50) {
|
|
|
24976
24964
|
const heap = new Heap(hausdorffCompare);
|
|
24977
24965
|
heap.insert(initialInterval);
|
|
24978
24966
|
let j = 0;
|
|
24979
|
-
let bestHUpper = Infinity;
|
|
24980
24967
|
let bestHLower = -Infinity;
|
|
24968
|
+
let bestTA = 0; // parameter on `A` achieving the running max lower bound
|
|
24981
24969
|
while (true) {
|
|
24982
24970
|
const interval = heap.heap[0]; // peek max
|
|
24983
24971
|
const { tS, tE, hL, hR } = interval;
|
|
@@ -24989,24 +24977,37 @@ function hausdorffDistanceOneSided(A, B, tolerance, maxIterations = 50) {
|
|
|
24989
24977
|
const pB = closestPointOnBezier(B, pM).p;
|
|
24990
24978
|
const hM = distanceBetween(pM, pB);
|
|
24991
24979
|
//---------------------------------------
|
|
24992
|
-
|
|
24993
|
-
|
|
24994
|
-
|
|
24980
|
+
// track *which* of the three parameters (tS, tM, tE) achieves the max
|
|
24981
|
+
let hBest = hL, tABest = tS;
|
|
24982
|
+
if (hM > hBest) {
|
|
24983
|
+
hBest = hM;
|
|
24984
|
+
tABest = tM;
|
|
24985
|
+
}
|
|
24986
|
+
if (hR > hBest) {
|
|
24987
|
+
hBest = hR;
|
|
24988
|
+
tABest = tE;
|
|
24989
|
+
}
|
|
24990
|
+
if (hBest > bestHLower) {
|
|
24991
|
+
bestHLower = hBest;
|
|
24992
|
+
bestTA = tABest;
|
|
24995
24993
|
}
|
|
24996
|
-
bestHUpper = getMaxHausdorff(interval);
|
|
24994
|
+
const bestHUpper = getMaxHausdorff(interval);
|
|
24997
24995
|
if (bestHUpper - bestHLower < tolerance) {
|
|
24998
24996
|
// The lower bound is by far the best approximation for difficult cases (see the paper).
|
|
24999
|
-
|
|
24997
|
+
break;
|
|
25000
24998
|
}
|
|
25001
24999
|
if (j++ > maxIterations) {
|
|
25002
25000
|
// The lower bound is by far the best approximation for difficult cases (see the paper).
|
|
25003
|
-
|
|
25001
|
+
break;
|
|
25004
25002
|
}
|
|
25005
25003
|
const iL = { tS, tE: tM, hL, hR: hM, hEL: ELL, hER: ELR };
|
|
25006
25004
|
const iR = { tS: tM, tE, hL: hM, hR, hEL: ERL, hER: ERR };
|
|
25007
25005
|
heap.swapMinOrMax(iL);
|
|
25008
25006
|
heap.insert(iR);
|
|
25009
25007
|
}
|
|
25008
|
+
const pA = evalDeCasteljau(A, bestTA);
|
|
25009
|
+
const cB = closestPointOnBezier(B, pA);
|
|
25010
|
+
return { d: bestHLower, tA: bestTA, pA, tB: cB.t, pB: cB.p };
|
|
25010
25011
|
}
|
|
25011
25012
|
// Let: ωf(σ) = sup{ |f(t) − f(t′)| : t, t′ ∈ [a,b] with |t − t′| ≤ σ }
|
|
25012
25013
|
//
|
|
@@ -25028,28 +25029,51 @@ function calcHErrorBound(A, tS, tE) {
|
|
|
25028
25029
|
return [eL, eR];
|
|
25029
25030
|
}
|
|
25030
25031
|
|
|
25031
|
-
|
|
25032
|
-
|
|
25033
|
-
|
|
25034
|
-
//
|
|
25035
|
-
//
|
|
25036
|
-
//
|
|
25037
|
-
//
|
|
25038
|
-
// ]
|
|
25039
|
-
//
|
|
25040
|
-
//
|
|
25041
|
-
//
|
|
25042
|
-
//
|
|
25043
|
-
//
|
|
25044
|
-
//
|
|
25045
|
-
//
|
|
25046
|
-
//
|
|
25047
|
-
//
|
|
25048
|
-
//
|
|
25049
|
-
|
|
25050
|
-
|
|
25051
|
-
|
|
25052
|
-
|
|
25032
|
+
//# sourceMappingURL=hausdorff-distance-one-sided-extra.js.map
|
|
25033
|
+
;// ./node_modules/flo-bezier3/node/simultaneous-properties/hausdorff-distance/hausdorff-distance-one-sided.js
|
|
25034
|
+
|
|
25035
|
+
// We need to calculate `H(A,B)`, the two sided Hausdorff distance between
|
|
25036
|
+
// the bezier curves `A` and `B` which equals `max(h(A,B), h(B,A))`, where
|
|
25037
|
+
// `h(A,B)` is the one sided Hausdorff distance from `A` to `B`
|
|
25038
|
+
// Let: ωf(σ) = sup{ |f(t) − f(t′)| : t, t′ ∈ [a,b] with |t − t′| ≤ σ }
|
|
25039
|
+
// where: δS = max[ (1 ≤ i ≤ M+1)(ti − ti−1) ] is the maximum distance between
|
|
25040
|
+
// two consecutive parameter values
|
|
25041
|
+
// Lemma 2.1:
|
|
25042
|
+
// h(A,S) ≤ ωf(δS/2) and
|
|
25043
|
+
// h(B,T) ≤ ωg(δT/2)
|
|
25044
|
+
// Theorem 2.3: (both curves discretized)
|
|
25045
|
+
// |h(S,T) − h(A,B)| ≤ max[ h(A,S), h(B,T) ]
|
|
25046
|
+
// ≤ max[ ωf(δS/2), ωg(δT/2) ]
|
|
25047
|
+
//
|
|
25048
|
+
// (only A discretized)
|
|
25049
|
+
// |h(S,B) − h(A,B)| ≤ ωf(δS/2)
|
|
25050
|
+
/**
|
|
25051
|
+
* Calculates and returns an accurate approximation to the one-sided Hausdorff
|
|
25052
|
+
* distance from the bezier curve `A` to the bezier curve `B`.
|
|
25053
|
+
*
|
|
25054
|
+
* * to also obtain the parameter values and points at which the distance is
|
|
25055
|
+
* achieved, use `hausdorffDistanceOneSidedExtra`
|
|
25056
|
+
* * partially based off [Computing the Hausdorff distance between two sets of parametric curves](https://www.semanticscholar.org/paper/COMPUTING-THE-HAUSDORFF-DISTANCE-BETWEEN-TWO-SETS-Kim-McLean/d2bd6529c4b118e389e1db209d8f1bf7467f9016)
|
|
25057
|
+
*
|
|
25058
|
+
* @param A a bezier curve (the 'from' curve) given by an ordered array of its
|
|
25059
|
+
* control points e.g. `[[0,0],[1,1],[2,1],[2,0]]`
|
|
25060
|
+
* @param B a bezier curve (the 'to' curve) given by an ordered array of its
|
|
25061
|
+
* control points e.g. `[[0,0],[1,1],[2,1],[2,0]]`
|
|
25062
|
+
* @param tolerance optional; defaults to `max(maxAbsCoordinate(A),maxAbsCoordinate(B))/1000_000`;
|
|
25063
|
+
* if the calculated absolute error bound is less than this, the result is
|
|
25064
|
+
* returned; this is *not* a hard tolerance and the bound can be less
|
|
25065
|
+
* accurate in hard cases (due to the `maxIterations` parameter). Luckily
|
|
25066
|
+
* however, specifically the lower bound will be very accurate due to
|
|
25067
|
+
* its fast convergence in such hard cases (see the paper)
|
|
25068
|
+
* @param maxIterations optional; defaults to `50`; if the desired guaranteed error bound
|
|
25069
|
+
* has not been achieved after `maxIterations` then the result will be returned
|
|
25070
|
+
*
|
|
25071
|
+
* @doc mdx
|
|
25072
|
+
*/
|
|
25073
|
+
function hausdorffDistanceOneSided(A, B, tolerance, maxIterations = 50) {
|
|
25074
|
+
return hausdorffDistanceOneSidedExtra(A, B, tolerance, maxIterations).d;
|
|
25075
|
+
}
|
|
25076
|
+
|
|
25053
25077
|
//# sourceMappingURL=hausdorff-distance-one-sided.js.map
|
|
25054
25078
|
;// ./src/cp-node/fs/get-non-terminating-on-circle.ts
|
|
25055
25079
|
|
|
@@ -25109,24 +25133,32 @@ function getBranches(cpNode) {
|
|
|
25109
25133
|
|
|
25110
25134
|
|
|
25111
25135
|
;// ./node_modules/flo-ll-rb-tree/node/rb-tree/rb-tree.js
|
|
25112
|
-
|
|
25113
|
-
|
|
25114
|
-
|
|
25115
|
-
|
|
25116
|
-
|
|
25117
|
-
|
|
25118
|
-
|
|
25119
|
-
|
|
25120
|
-
|
|
25121
|
-
this.datum = datum;
|
|
25122
|
-
}
|
|
25136
|
+
|
|
25137
|
+
function createNode(datum) {
|
|
25138
|
+
return {
|
|
25139
|
+
color: (/* inlined export .RED */0),
|
|
25140
|
+
parent: undefined,
|
|
25141
|
+
left: undefined,
|
|
25142
|
+
right: undefined,
|
|
25143
|
+
datum
|
|
25144
|
+
};
|
|
25123
25145
|
}
|
|
25124
25146
|
class RbTree {
|
|
25125
25147
|
compare;
|
|
25126
25148
|
root;
|
|
25149
|
+
size;
|
|
25150
|
+
minNode;
|
|
25151
|
+
maxNode;
|
|
25152
|
+
minNodeStale = true;
|
|
25153
|
+
maxNodeStale = true;
|
|
25127
25154
|
constructor(compare) {
|
|
25128
25155
|
this.compare = compare;
|
|
25129
25156
|
this.root = undefined;
|
|
25157
|
+
this.size = 0;
|
|
25158
|
+
this.minNode = undefined;
|
|
25159
|
+
this.maxNode = undefined;
|
|
25160
|
+
this.minNodeStale = true;
|
|
25161
|
+
this.maxNodeStale = true;
|
|
25130
25162
|
}
|
|
25131
25163
|
isEmpty() {
|
|
25132
25164
|
return this.root === undefined;
|
|
@@ -25143,9 +25175,12 @@ class RbTree {
|
|
|
25143
25175
|
return undefined;
|
|
25144
25176
|
}
|
|
25145
25177
|
insert(datum) {
|
|
25178
|
+
this.minNodeStale = true;
|
|
25179
|
+
this.maxNodeStale = true;
|
|
25146
25180
|
if (this.root === undefined) {
|
|
25147
|
-
this.root =
|
|
25148
|
-
this.root.color = BLACK;
|
|
25181
|
+
this.root = createNode(datum);
|
|
25182
|
+
this.root.color = (/* inlined export .BLACK */1);
|
|
25183
|
+
this.size = 1;
|
|
25149
25184
|
return;
|
|
25150
25185
|
}
|
|
25151
25186
|
let parent;
|
|
@@ -25159,7 +25194,7 @@ class RbTree {
|
|
|
25159
25194
|
}
|
|
25160
25195
|
node = c < 0 ? node.left : node.right;
|
|
25161
25196
|
}
|
|
25162
|
-
const inserted =
|
|
25197
|
+
const inserted = createNode(datum);
|
|
25163
25198
|
inserted.parent = parent;
|
|
25164
25199
|
if (this.compare(datum, parent.datum) < 0) {
|
|
25165
25200
|
parent.left = inserted;
|
|
@@ -25167,15 +25202,19 @@ class RbTree {
|
|
|
25167
25202
|
else {
|
|
25168
25203
|
parent.right = inserted;
|
|
25169
25204
|
}
|
|
25205
|
+
this.size++;
|
|
25170
25206
|
this.fixInsert(inserted);
|
|
25171
25207
|
}
|
|
25172
|
-
remove(datum
|
|
25208
|
+
remove(datum) {
|
|
25173
25209
|
const node = this.find(datum);
|
|
25174
25210
|
if (node === undefined) {
|
|
25175
25211
|
return undefined;
|
|
25176
25212
|
}
|
|
25177
25213
|
const removed = node.datum;
|
|
25178
25214
|
this.removeNode(node);
|
|
25215
|
+
this.size--;
|
|
25216
|
+
this.minNodeStale = true;
|
|
25217
|
+
this.maxNodeStale = true;
|
|
25179
25218
|
return removed;
|
|
25180
25219
|
}
|
|
25181
25220
|
findBounds(datum) {
|
|
@@ -25194,21 +25233,116 @@ class RbTree {
|
|
|
25194
25233
|
}
|
|
25195
25234
|
return bounds;
|
|
25196
25235
|
}
|
|
25197
|
-
getMinNode(
|
|
25198
|
-
|
|
25236
|
+
getMinNode() {
|
|
25237
|
+
if (!this.minNodeStale) {
|
|
25238
|
+
return this.minNode;
|
|
25239
|
+
}
|
|
25240
|
+
let curr = this.root;
|
|
25199
25241
|
while (curr && curr.left) {
|
|
25200
25242
|
curr = curr.left;
|
|
25201
25243
|
}
|
|
25244
|
+
this.minNode = curr;
|
|
25245
|
+
this.minNodeStale = false;
|
|
25202
25246
|
return curr;
|
|
25203
25247
|
}
|
|
25204
|
-
getMaxNode(
|
|
25205
|
-
|
|
25248
|
+
getMaxNode() {
|
|
25249
|
+
if (!this.maxNodeStale) {
|
|
25250
|
+
return this.maxNode;
|
|
25251
|
+
}
|
|
25252
|
+
let curr = this.root;
|
|
25206
25253
|
while (curr && curr.right) {
|
|
25207
25254
|
curr = curr.right;
|
|
25208
25255
|
}
|
|
25256
|
+
this.maxNode = curr;
|
|
25257
|
+
this.maxNodeStale = false;
|
|
25209
25258
|
return curr;
|
|
25210
25259
|
}
|
|
25260
|
+
/**
|
|
25261
|
+
* Checks that the tree satisfies the binary search tree ordering property
|
|
25262
|
+
* and the red-black constraints (root is black, no red node has a red
|
|
25263
|
+
* child, and every root-to-leaf path has the same number of black nodes).
|
|
25264
|
+
*
|
|
25265
|
+
* Returns `true` if all checks pass, `false` otherwise.
|
|
25266
|
+
*/
|
|
25267
|
+
checkIntegrity() {
|
|
25268
|
+
if (this.root === undefined) {
|
|
25269
|
+
return true;
|
|
25270
|
+
}
|
|
25271
|
+
if (this.root.color !== (/* inlined export .BLACK */1)) {
|
|
25272
|
+
return false;
|
|
25273
|
+
}
|
|
25274
|
+
const compare = this.compare;
|
|
25275
|
+
// in-order predecessor for the BST ordering check
|
|
25276
|
+
let prev = undefined;
|
|
25277
|
+
// Returns the black-height of the subtree, or -1 if a violation was found.
|
|
25278
|
+
function check(node) {
|
|
25279
|
+
if (node === undefined) {
|
|
25280
|
+
return 1;
|
|
25281
|
+
}
|
|
25282
|
+
const { left, right } = node;
|
|
25283
|
+
// no red node has a red child
|
|
25284
|
+
if (node.color === (/* inlined export .RED */0) &&
|
|
25285
|
+
(left?.color === (/* inlined export .RED */0) || right?.color === (/* inlined export .RED */0))) {
|
|
25286
|
+
return -1;
|
|
25287
|
+
}
|
|
25288
|
+
const leftHeight = check(left);
|
|
25289
|
+
if (leftHeight === -1) {
|
|
25290
|
+
return -1;
|
|
25291
|
+
}
|
|
25292
|
+
// BST ordering (in-order traversal must be strictly increasing)
|
|
25293
|
+
if (prev !== undefined && compare(prev.datum, node.datum) >= 0) {
|
|
25294
|
+
return -1;
|
|
25295
|
+
}
|
|
25296
|
+
prev = node;
|
|
25297
|
+
const rightHeight = check(right);
|
|
25298
|
+
if (rightHeight === -1) {
|
|
25299
|
+
return -1;
|
|
25300
|
+
}
|
|
25301
|
+
// equal black-height on both sides
|
|
25302
|
+
if (leftHeight !== rightHeight) {
|
|
25303
|
+
return -1;
|
|
25304
|
+
}
|
|
25305
|
+
return leftHeight + (node.color === (/* inlined export .BLACK */1) ? 1 : 0);
|
|
25306
|
+
}
|
|
25307
|
+
return check(this.root) !== -1;
|
|
25308
|
+
}
|
|
25309
|
+
toStr(nodeToStrFunc) {
|
|
25310
|
+
let treeStr = '';
|
|
25311
|
+
if (this.root === undefined) {
|
|
25312
|
+
return treeStr;
|
|
25313
|
+
}
|
|
25314
|
+
f(this.root);
|
|
25315
|
+
return treeStr;
|
|
25316
|
+
function f(node) {
|
|
25317
|
+
treeStr += nodeToStrFunc(node);
|
|
25318
|
+
if (node.left !== undefined) {
|
|
25319
|
+
treeStr += '(';
|
|
25320
|
+
f(node.left);
|
|
25321
|
+
treeStr += ')';
|
|
25322
|
+
}
|
|
25323
|
+
if (node.right !== undefined) {
|
|
25324
|
+
treeStr += '[';
|
|
25325
|
+
f(node.right);
|
|
25326
|
+
treeStr += ']';
|
|
25327
|
+
}
|
|
25328
|
+
}
|
|
25329
|
+
}
|
|
25330
|
+
toArr() {
|
|
25331
|
+
const values = [];
|
|
25332
|
+
f(this.root);
|
|
25333
|
+
return values;
|
|
25334
|
+
function f(node) {
|
|
25335
|
+
if (node === undefined) {
|
|
25336
|
+
return;
|
|
25337
|
+
}
|
|
25338
|
+
f(node.left);
|
|
25339
|
+
values.push(node.datum);
|
|
25340
|
+
f(node.right);
|
|
25341
|
+
}
|
|
25342
|
+
}
|
|
25211
25343
|
removeNode(z) {
|
|
25344
|
+
this.minNodeStale = true;
|
|
25345
|
+
this.maxNodeStale = true;
|
|
25212
25346
|
let y = z;
|
|
25213
25347
|
let yOriginalColor = y.color;
|
|
25214
25348
|
let x;
|
|
@@ -25224,7 +25358,10 @@ class RbTree {
|
|
|
25224
25358
|
this.transplant(z, z.left);
|
|
25225
25359
|
}
|
|
25226
25360
|
else {
|
|
25227
|
-
y =
|
|
25361
|
+
y = z.right;
|
|
25362
|
+
while (y.left) {
|
|
25363
|
+
y = y.left;
|
|
25364
|
+
}
|
|
25228
25365
|
yOriginalColor = y.color;
|
|
25229
25366
|
x = y.right;
|
|
25230
25367
|
if (y.parent === z) {
|
|
@@ -25244,21 +25381,21 @@ class RbTree {
|
|
|
25244
25381
|
y.left.parent = y;
|
|
25245
25382
|
y.color = z.color;
|
|
25246
25383
|
}
|
|
25247
|
-
if (yOriginalColor === BLACK) {
|
|
25384
|
+
if (yOriginalColor === (/* inlined export .BLACK */1)) {
|
|
25248
25385
|
this.fixDelete(x, xParent);
|
|
25249
25386
|
}
|
|
25250
25387
|
}
|
|
25251
25388
|
fixInsert(z) {
|
|
25252
25389
|
let node = z;
|
|
25253
|
-
while (node.parent && node.parent.color === RED) {
|
|
25390
|
+
while (node.parent && node.parent.color === (/* inlined export .RED */0)) {
|
|
25254
25391
|
const parent = node.parent;
|
|
25255
25392
|
const grandParent = parent.parent;
|
|
25256
25393
|
if (parent === grandParent.left) {
|
|
25257
25394
|
const uncle = grandParent.right;
|
|
25258
|
-
if (this.colorOf(uncle) === RED) {
|
|
25259
|
-
parent.color = BLACK;
|
|
25260
|
-
uncle.color = BLACK;
|
|
25261
|
-
grandParent.color = RED;
|
|
25395
|
+
if (this.colorOf(uncle) === (/* inlined export .RED */0)) {
|
|
25396
|
+
parent.color = (/* inlined export .BLACK */1);
|
|
25397
|
+
uncle.color = (/* inlined export .BLACK */1);
|
|
25398
|
+
grandParent.color = (/* inlined export .RED */0);
|
|
25262
25399
|
node = grandParent;
|
|
25263
25400
|
}
|
|
25264
25401
|
else {
|
|
@@ -25266,17 +25403,17 @@ class RbTree {
|
|
|
25266
25403
|
node = parent;
|
|
25267
25404
|
this.rotateLeft(node);
|
|
25268
25405
|
}
|
|
25269
|
-
node.parent.color = BLACK;
|
|
25270
|
-
grandParent.color = RED;
|
|
25406
|
+
node.parent.color = (/* inlined export .BLACK */1);
|
|
25407
|
+
grandParent.color = (/* inlined export .RED */0);
|
|
25271
25408
|
this.rotateRight(grandParent);
|
|
25272
25409
|
}
|
|
25273
25410
|
}
|
|
25274
25411
|
else {
|
|
25275
25412
|
const uncle = grandParent.left;
|
|
25276
|
-
if (this.colorOf(uncle) === RED) {
|
|
25277
|
-
parent.color = BLACK;
|
|
25278
|
-
uncle.color = BLACK;
|
|
25279
|
-
grandParent.color = RED;
|
|
25413
|
+
if (this.colorOf(uncle) === (/* inlined export .RED */0)) {
|
|
25414
|
+
parent.color = (/* inlined export .BLACK */1);
|
|
25415
|
+
uncle.color = (/* inlined export .BLACK */1);
|
|
25416
|
+
grandParent.color = (/* inlined export .RED */0);
|
|
25280
25417
|
node = grandParent;
|
|
25281
25418
|
}
|
|
25282
25419
|
else {
|
|
@@ -25284,43 +25421,43 @@ class RbTree {
|
|
|
25284
25421
|
node = parent;
|
|
25285
25422
|
this.rotateRight(node);
|
|
25286
25423
|
}
|
|
25287
|
-
node.parent.color = BLACK;
|
|
25288
|
-
grandParent.color = RED;
|
|
25424
|
+
node.parent.color = (/* inlined export .BLACK */1);
|
|
25425
|
+
grandParent.color = (/* inlined export .RED */0);
|
|
25289
25426
|
this.rotateLeft(grandParent);
|
|
25290
25427
|
}
|
|
25291
25428
|
}
|
|
25292
25429
|
}
|
|
25293
|
-
this.root.color = BLACK;
|
|
25430
|
+
this.root.color = (/* inlined export .BLACK */1);
|
|
25294
25431
|
}
|
|
25295
25432
|
fixDelete(x, parent) {
|
|
25296
25433
|
let node = x;
|
|
25297
25434
|
let nodeParent = parent;
|
|
25298
|
-
while (node !== this.root && this.colorOf(node) === BLACK) {
|
|
25435
|
+
while (node !== this.root && this.colorOf(node) === (/* inlined export .BLACK */1)) {
|
|
25299
25436
|
if (nodeParent === undefined) {
|
|
25300
25437
|
break;
|
|
25301
25438
|
}
|
|
25302
25439
|
if (node === nodeParent?.left) {
|
|
25303
25440
|
let sibling = nodeParent.right;
|
|
25304
|
-
if (this.colorOf(sibling) === RED) {
|
|
25305
|
-
sibling.color = BLACK;
|
|
25306
|
-
nodeParent.color = RED;
|
|
25441
|
+
if (this.colorOf(sibling) === (/* inlined export .RED */0)) {
|
|
25442
|
+
sibling.color = (/* inlined export .BLACK */1);
|
|
25443
|
+
nodeParent.color = (/* inlined export .RED */0);
|
|
25307
25444
|
this.rotateLeft(nodeParent);
|
|
25308
25445
|
sibling = nodeParent.right;
|
|
25309
25446
|
}
|
|
25310
|
-
if (this.colorOf(sibling?.left) === BLACK && this.colorOf(sibling?.right) === BLACK) {
|
|
25447
|
+
if (this.colorOf(sibling?.left) === (/* inlined export .BLACK */1) && this.colorOf(sibling?.right) === (/* inlined export .BLACK */1)) {
|
|
25311
25448
|
if (sibling) {
|
|
25312
|
-
sibling.color = RED;
|
|
25449
|
+
sibling.color = (/* inlined export .RED */0);
|
|
25313
25450
|
}
|
|
25314
25451
|
node = nodeParent;
|
|
25315
25452
|
nodeParent = node?.parent;
|
|
25316
25453
|
}
|
|
25317
25454
|
else {
|
|
25318
|
-
if (this.colorOf(sibling?.right) === BLACK) {
|
|
25455
|
+
if (this.colorOf(sibling?.right) === (/* inlined export .BLACK */1)) {
|
|
25319
25456
|
if (sibling?.left) {
|
|
25320
|
-
sibling.left.color = BLACK;
|
|
25457
|
+
sibling.left.color = (/* inlined export .BLACK */1);
|
|
25321
25458
|
}
|
|
25322
25459
|
if (sibling) {
|
|
25323
|
-
sibling.color = RED;
|
|
25460
|
+
sibling.color = (/* inlined export .RED */0);
|
|
25324
25461
|
this.rotateRight(sibling);
|
|
25325
25462
|
}
|
|
25326
25463
|
sibling = nodeParent.right;
|
|
@@ -25328,9 +25465,9 @@ class RbTree {
|
|
|
25328
25465
|
if (sibling) {
|
|
25329
25466
|
sibling.color = nodeParent.color;
|
|
25330
25467
|
}
|
|
25331
|
-
nodeParent.color = BLACK;
|
|
25468
|
+
nodeParent.color = (/* inlined export .BLACK */1);
|
|
25332
25469
|
if (sibling?.right) {
|
|
25333
|
-
sibling.right.color = BLACK;
|
|
25470
|
+
sibling.right.color = (/* inlined export .BLACK */1);
|
|
25334
25471
|
}
|
|
25335
25472
|
this.rotateLeft(nodeParent);
|
|
25336
25473
|
node = this.root;
|
|
@@ -25339,26 +25476,26 @@ class RbTree {
|
|
|
25339
25476
|
}
|
|
25340
25477
|
else {
|
|
25341
25478
|
let sibling = nodeParent?.left;
|
|
25342
|
-
if (this.colorOf(sibling) === RED) {
|
|
25343
|
-
sibling.color = BLACK;
|
|
25344
|
-
nodeParent.color = RED;
|
|
25479
|
+
if (this.colorOf(sibling) === (/* inlined export .RED */0)) {
|
|
25480
|
+
sibling.color = (/* inlined export .BLACK */1);
|
|
25481
|
+
nodeParent.color = (/* inlined export .RED */0);
|
|
25345
25482
|
this.rotateRight(nodeParent);
|
|
25346
25483
|
sibling = nodeParent.left;
|
|
25347
25484
|
}
|
|
25348
|
-
if (this.colorOf(sibling?.left) === BLACK && this.colorOf(sibling?.right) === BLACK) {
|
|
25485
|
+
if (this.colorOf(sibling?.left) === (/* inlined export .BLACK */1) && this.colorOf(sibling?.right) === (/* inlined export .BLACK */1)) {
|
|
25349
25486
|
if (sibling) {
|
|
25350
|
-
sibling.color = RED;
|
|
25487
|
+
sibling.color = (/* inlined export .RED */0);
|
|
25351
25488
|
}
|
|
25352
25489
|
node = nodeParent;
|
|
25353
25490
|
nodeParent = nodeParent?.parent;
|
|
25354
25491
|
}
|
|
25355
25492
|
else {
|
|
25356
|
-
if (this.colorOf(sibling?.left) === BLACK) {
|
|
25493
|
+
if (this.colorOf(sibling?.left) === (/* inlined export .BLACK */1)) {
|
|
25357
25494
|
if (sibling?.right) {
|
|
25358
|
-
sibling.right.color = BLACK;
|
|
25495
|
+
sibling.right.color = (/* inlined export .BLACK */1);
|
|
25359
25496
|
}
|
|
25360
25497
|
if (sibling) {
|
|
25361
|
-
sibling.color = RED;
|
|
25498
|
+
sibling.color = (/* inlined export .RED */0);
|
|
25362
25499
|
this.rotateLeft(sibling);
|
|
25363
25500
|
}
|
|
25364
25501
|
sibling = nodeParent?.left;
|
|
@@ -25366,9 +25503,9 @@ class RbTree {
|
|
|
25366
25503
|
if (sibling) {
|
|
25367
25504
|
sibling.color = nodeParent.color;
|
|
25368
25505
|
}
|
|
25369
|
-
nodeParent.color = BLACK;
|
|
25506
|
+
nodeParent.color = (/* inlined export .BLACK */1);
|
|
25370
25507
|
if (sibling?.left) {
|
|
25371
|
-
sibling.left.color = BLACK;
|
|
25508
|
+
sibling.left.color = (/* inlined export .BLACK */1);
|
|
25372
25509
|
}
|
|
25373
25510
|
this.rotateRight(nodeParent);
|
|
25374
25511
|
node = this.root;
|
|
@@ -25377,7 +25514,7 @@ class RbTree {
|
|
|
25377
25514
|
}
|
|
25378
25515
|
}
|
|
25379
25516
|
if (node) {
|
|
25380
|
-
node.color = BLACK;
|
|
25517
|
+
node.color = (/* inlined export .BLACK */1);
|
|
25381
25518
|
}
|
|
25382
25519
|
}
|
|
25383
25520
|
transplant(u, v) {
|
|
@@ -25433,7 +25570,7 @@ class RbTree {
|
|
|
25433
25570
|
x.parent = y;
|
|
25434
25571
|
}
|
|
25435
25572
|
colorOf(node) {
|
|
25436
|
-
return node ? node.color : BLACK;
|
|
25573
|
+
return node ? node.color : (/* inlined export .BLACK */1);
|
|
25437
25574
|
}
|
|
25438
25575
|
}
|
|
25439
25576
|
|
|
@@ -26706,7 +26843,7 @@ function find3ProngForDelta3s(δs, idx, k, curvePiecess, maxCoordPowerOf2) {
|
|
|
26706
26843
|
;// ./src/mat/get-boundary-piece-beziers.ts
|
|
26707
26844
|
|
|
26708
26845
|
/**
|
|
26709
|
-
* Returns the ordered bezier pieces between
|
|
26846
|
+
* Returns the ordered bezier pieces between the two given `CpNode`s.
|
|
26710
26847
|
*
|
|
26711
26848
|
* @param cpNodes - An ordered pair that represents the start and end points of
|
|
26712
26849
|
* the boundary piece
|
|
@@ -26904,7 +27041,7 @@ function find3Prong(δs, maxCoordPowerOf2) {
|
|
|
26904
27041
|
}
|
|
26905
27042
|
|
|
26906
27043
|
|
|
26907
|
-
;// ./src/mat/get-cp-node-
|
|
27044
|
+
;// ./src/mat/get-cp-node-neighbors.ts
|
|
26908
27045
|
/**
|
|
26909
27046
|
* @internal
|
|
26910
27047
|
*
|
|
@@ -26918,50 +27055,107 @@ function find3Prong(δs, maxCoordPowerOf2) {
|
|
|
26918
27055
|
* @param order
|
|
26919
27056
|
* @param order2
|
|
26920
27057
|
*/
|
|
26921
|
-
function
|
|
27058
|
+
function getCpNodeNeighbors(cpTree, pos, order, order2) {
|
|
26922
27059
|
const pointOnShape = { ...pos, order, order2 };
|
|
26923
27060
|
const cps = cpTree.findBounds({ pointOnShape });
|
|
26924
|
-
|
|
27061
|
+
const [cp0, cp1] = cps;
|
|
27062
|
+
if (cp0 === undefined && cp1 === undefined) {
|
|
26925
27063
|
// The tree is still empty
|
|
26926
27064
|
return undefined;
|
|
26927
27065
|
}
|
|
26928
|
-
if (
|
|
26929
|
-
// Smaller than all
|
|
26930
|
-
|
|
26931
|
-
|
|
26932
|
-
return
|
|
27066
|
+
if (cp0 === undefined || cp1 === undefined) {
|
|
27067
|
+
// Smaller than all OR larger than all
|
|
27068
|
+
const minNode = cpTree.getMinNode()?.datum;
|
|
27069
|
+
const maxNode = cpTree.getMaxNode()?.datum;
|
|
27070
|
+
return [maxNode, minNode];
|
|
26933
27071
|
}
|
|
26934
|
-
return
|
|
27072
|
+
return [cp0.datum, cp1.datum];
|
|
26935
27073
|
}
|
|
26936
27074
|
|
|
26937
27075
|
|
|
26938
27076
|
;// ./src/cp-node/fs/is-order-correct.ts
|
|
26939
27077
|
|
|
26940
|
-
|
|
26941
|
-
|
|
26942
|
-
|
|
27078
|
+
/**
|
|
27079
|
+
*
|
|
27080
|
+
* @param cpTree
|
|
27081
|
+
* @param pos
|
|
27082
|
+
* @param succ
|
|
27083
|
+
* @param alreadyInserted set to `true` if the given `pos` has already been
|
|
27084
|
+
* inserted, `false` otherwise.
|
|
27085
|
+
*/
|
|
27086
|
+
function isOrderCorrect(cpTree, pred, pos, succ, alreadyInserted) {
|
|
27087
|
+
if (cpTree.size <= (alreadyInserted ? 2 : 1)) {
|
|
26943
27088
|
return true;
|
|
26944
27089
|
}
|
|
26945
|
-
|
|
27090
|
+
const a = pred.pointOnShape;
|
|
27091
|
+
const b = pos;
|
|
27092
|
+
const c = succ.pointOnShape;
|
|
27093
|
+
// Let a = pred, b = pos, and c = succ.
|
|
27094
|
+
// For a cyclic order we need:
|
|
27095
|
+
// `(a < b && b < c)` || `(b < c && c < a)` || `(c < a && a < b)`
|
|
27096
|
+
// Let `X = a < b, Y = b < c, Z = c < a` then
|
|
27097
|
+
// `(X && Y)` || `(Y && Z)` || `(Z && X)`
|
|
27098
|
+
const _X = comparePoss(a, b);
|
|
27099
|
+
if (_X === 0) { // two points must have different order
|
|
27100
|
+
// console.log('aaa');
|
|
27101
|
+
// throw 'a';
|
|
27102
|
+
return false;
|
|
27103
|
+
}
|
|
27104
|
+
const _Y = comparePoss(b, c);
|
|
27105
|
+
if (_Y === 0) { // two points must have different order
|
|
27106
|
+
// console.log('bbb');
|
|
27107
|
+
// throw 'b';
|
|
26946
27108
|
return false;
|
|
26947
27109
|
}
|
|
26948
|
-
const
|
|
26949
|
-
if (
|
|
27110
|
+
const _Z = comparePoss(c, a);
|
|
27111
|
+
if (_Z === 0) {
|
|
27112
|
+
// console.log('bbb');
|
|
27113
|
+
// throw 'c';
|
|
27114
|
+
return false;
|
|
27115
|
+
} // impossible anyway at this point
|
|
27116
|
+
// Now neither `_X` nor `_Y` nor `_Z` === `0`
|
|
27117
|
+
const X = _X < 0;
|
|
27118
|
+
const Y = _Y < 0;
|
|
27119
|
+
const Z = _Z < 0;
|
|
27120
|
+
// Cyclic order condition
|
|
27121
|
+
if ((X && Y) || (Y && Z) || (Z && X)) {
|
|
26950
27122
|
return true;
|
|
26951
27123
|
}
|
|
26952
|
-
|
|
26953
|
-
|
|
26954
|
-
//
|
|
26955
|
-
return
|
|
27124
|
+
// throw 'd';
|
|
27125
|
+
// console.log(_X, _Y, _Z);
|
|
27126
|
+
// console.log(cpTree.toArr().map(v => {
|
|
27127
|
+
// return {
|
|
27128
|
+
// curveIdx: v.pointOnShape.curve.idx,
|
|
27129
|
+
// t: v.pointOnShape.t,
|
|
27130
|
+
// order: v.pointOnShape.order,
|
|
27131
|
+
// order2: v.pointOnShape.order2
|
|
27132
|
+
// }
|
|
27133
|
+
// }));
|
|
27134
|
+
return false;
|
|
26956
27135
|
}
|
|
26957
27136
|
|
|
26958
27137
|
|
|
26959
27138
|
;// ./src/cp-node/fs/insert-cp-node.ts
|
|
26960
27139
|
|
|
26961
|
-
|
|
26962
|
-
|
|
26963
|
-
|
|
26964
|
-
|
|
27140
|
+
/**
|
|
27141
|
+
*
|
|
27142
|
+
* @param insertIfOrderWrong order cannot be checked for hole-closers since they're on different loops
|
|
27143
|
+
* @param isHoleClosing
|
|
27144
|
+
* @param isIntersection
|
|
27145
|
+
* @param cpTree
|
|
27146
|
+
* @param pos
|
|
27147
|
+
* @param pred predecessor (to `pos`) on sampe loop (found via `cpTree`)
|
|
27148
|
+
* @param succ successor (to `pos`) on sampe loop (found via `cpTree`)
|
|
27149
|
+
* @param lastInsertId
|
|
27150
|
+
*/
|
|
27151
|
+
function insertCpNode(insertIfOrderWrong, isHoleClosing, isIntersection, cpTree, pos, pred, succ, lastInsertId) {
|
|
27152
|
+
if (pred !== undefined && succ !== undefined) {
|
|
27153
|
+
// !isOrderCorrect(cpTree, pos, pred.next, false)) {
|
|
27154
|
+
const orderCorrect = isOrderCorrect(cpTree, pred, pos, succ, false);
|
|
27155
|
+
// if (!orderCorrect) {
|
|
27156
|
+
// console.log('aaaaa');
|
|
27157
|
+
// }
|
|
27158
|
+
if (!insertIfOrderWrong && !orderCorrect) {
|
|
26965
27159
|
return undefined;
|
|
26966
27160
|
}
|
|
26967
27161
|
}
|
|
@@ -26976,8 +27170,8 @@ function insertCpNode(insertIfOrderWrong, isHoleClosing, isIntersection, cpTree,
|
|
|
26976
27170
|
prevOnCircle: undefined
|
|
26977
27171
|
};
|
|
26978
27172
|
lastInsertId.id++;
|
|
26979
|
-
const prev =
|
|
26980
|
-
const next =
|
|
27173
|
+
const prev = pred === undefined ? cpNode : pred;
|
|
27174
|
+
const next = pred === undefined ? cpNode : prev.next;
|
|
26981
27175
|
next.prev = cpNode;
|
|
26982
27176
|
prev.next = cpNode;
|
|
26983
27177
|
cpNode.prev = prev;
|
|
@@ -27018,6 +27212,9 @@ function byAngle(circle) {
|
|
|
27018
27212
|
|
|
27019
27213
|
|
|
27020
27214
|
/**
|
|
27215
|
+
* Insert the given `poss` into the `cpTree` (within `meta`) and returns the
|
|
27216
|
+
* newly inserted `CpNode`s.
|
|
27217
|
+
*
|
|
27021
27218
|
* @param circle
|
|
27022
27219
|
* @param orders
|
|
27023
27220
|
* @param cpTrees
|
|
@@ -27033,10 +27230,14 @@ function addToCpTree(insertIfOrderIsWrong, isHoleClosing, circle, orders, meta,
|
|
|
27033
27230
|
const order = orders[i];
|
|
27034
27231
|
const cpTree = cpTrees.get(ppos.curve.loop);
|
|
27035
27232
|
const pos = { ...ppos, circle, order, order2: 0 };
|
|
27036
|
-
const
|
|
27037
|
-
?
|
|
27233
|
+
const r = neighbors === undefined
|
|
27234
|
+
? getCpNodeNeighbors(cpTree, ppos, order, 0)
|
|
27038
27235
|
: neighbors[i];
|
|
27039
|
-
const
|
|
27236
|
+
const pred = r?.[0];
|
|
27237
|
+
const succ = r?.[1];
|
|
27238
|
+
const cpNode = insertCpNode(insertIfOrderIsWrong, isHoleClosing, false, cpTree, pos, pred,
|
|
27239
|
+
// pred?.next,
|
|
27240
|
+
succ, meta.lastInsertId);
|
|
27040
27241
|
if (cpNode === undefined) {
|
|
27041
27242
|
anyFailed = true;
|
|
27042
27243
|
}
|
|
@@ -27071,7 +27272,7 @@ function getCloseByCpIfExist(meta, pos, circle, order, order2, forProngCount) {
|
|
|
27071
27272
|
const DISTANCE_THRESHOLD = 2 ** (maxCoordPowerOf2 - 40); // approx. 1e-9 for 1024 x 1024 shapes
|
|
27072
27273
|
const DISTANCE_THRESHOLD_2 = 2 ** (maxCoordPowerOf2 - 46);
|
|
27073
27274
|
const cpTree = cpTrees.get(pos.curve.loop);
|
|
27074
|
-
const cur =
|
|
27275
|
+
const cur = getCpNodeNeighbors(cpTree, pos, order, order2)?.[0];
|
|
27075
27276
|
if (!cur) {
|
|
27076
27277
|
return undefined;
|
|
27077
27278
|
}
|
|
@@ -27142,7 +27343,7 @@ function findAndAdd3Prong(meta, visitedCps) {
|
|
|
27142
27343
|
}
|
|
27143
27344
|
}
|
|
27144
27345
|
const cpNodes = closeBysFor3Prong.length === 0
|
|
27145
|
-
? addToCpTree(true, false, circle, orders, meta, poss, δ3s
|
|
27346
|
+
? addToCpTree(true, false, circle, orders, meta, poss, δ3s).cpNodes
|
|
27146
27347
|
: [];
|
|
27147
27348
|
return { closeBysFor3Prong, cpNodes: cpNodes };
|
|
27148
27349
|
}
|
|
@@ -27206,7 +27407,7 @@ function findAndAdd3Prongs(meta, cpStart) {
|
|
|
27206
27407
|
*
|
|
27207
27408
|
* @param meta
|
|
27208
27409
|
* @param cpStart The CpNode to start traversing from.
|
|
27209
|
-
|
|
27410
|
+
*/
|
|
27210
27411
|
function findAndAdd3ProngsOnLoop(meta, cpStart) {
|
|
27211
27412
|
if (cpStart === undefined) {
|
|
27212
27413
|
return undefined;
|
|
@@ -27217,7 +27418,11 @@ function findAndAdd3ProngsOnLoop(meta, cpStart) {
|
|
|
27217
27418
|
reLoop = false;
|
|
27218
27419
|
const cpNodeSet = new Set(getAllOnLoop(cpStart));
|
|
27219
27420
|
for (const cpNode of cpNodeSet) {
|
|
27220
|
-
const
|
|
27421
|
+
const threeProngs = findAndAdd3Prongs(meta, cpNode);
|
|
27422
|
+
if (threeProngs === undefined) {
|
|
27423
|
+
return getFirstItemOfSet(cpNodeGoodSet);
|
|
27424
|
+
}
|
|
27425
|
+
const { closeBysFor3Prong, addedCpNodes } = threeProngs;
|
|
27221
27426
|
if (addedCpNodes.length > 0) {
|
|
27222
27427
|
reLoop = true;
|
|
27223
27428
|
}
|
|
@@ -27280,8 +27485,8 @@ function createInitialCpTree(loops, sharpCornerss, lastInsertId) {
|
|
|
27280
27485
|
const { curve } = ppos;
|
|
27281
27486
|
const pos1 = { ...ppos, curve, t: 1, circle, order: -1, order2: 0 };
|
|
27282
27487
|
const pos2 = { ...ppos, curve: curve.next, t: 0, circle, order: +1, order2: 0 };
|
|
27283
|
-
cpNode1 = insertCpNode(true, false, false, cpTree, pos1, cpNode2, lastInsertId);
|
|
27284
|
-
cpNode2 = insertCpNode(true, false, false, cpTree, pos2, cpNode1, lastInsertId);
|
|
27488
|
+
cpNode1 = insertCpNode(true, false, false, cpTree, pos1, cpNode2, undefined, /* unused */ lastInsertId);
|
|
27489
|
+
cpNode2 = insertCpNode(true, false, false, cpTree, pos2, cpNode1, undefined, /* unused */ lastInsertId);
|
|
27285
27490
|
cpNode1.prevOnCircle = cpNode2;
|
|
27286
27491
|
cpNode2.prevOnCircle = cpNode1;
|
|
27287
27492
|
cpNode1.nextOnCircle = cpNode2;
|
|
@@ -27434,7 +27639,7 @@ function getInitialCurvePieces(angle, isHoleClosing, loop, loops, meta, yPos, xO
|
|
|
27434
27639
|
? +1
|
|
27435
27640
|
: calcPosOrder(xO, yPos)
|
|
27436
27641
|
: 0;
|
|
27437
|
-
const cpNode =
|
|
27642
|
+
const cpNode = getCpNodeNeighbors(cpTrees.get(loop), yPos, order, 0)?.[0];
|
|
27438
27643
|
if (!cpNode ||
|
|
27439
27644
|
// The special case if there is only a single sharp corner or
|
|
27440
27645
|
// two-way terminating 2-prong currently in the MAT. Don't remove!
|
|
@@ -29295,12 +29500,14 @@ function closeHole(meta, cpNodes) {
|
|
|
29295
29500
|
const [cpNodeSource, cpNodeAntipode] = cpNodes;
|
|
29296
29501
|
// Antipode - create and insert twin
|
|
29297
29502
|
const posAntipode = cpNodeAntipode.pointOnShape;
|
|
29298
|
-
const cpNodeAntipodeTwin = insertCpNode(true, true, false, cpTrees.get(posAntipode.curve.loop), { ...posAntipode, order2: +1 }, cpNodeAntipode,
|
|
29503
|
+
const cpNodeAntipodeTwin = insertCpNode(true, true, false, cpTrees.get(posAntipode.curve.loop), { ...posAntipode, order2: +1 }, cpNodeAntipode, undefined, // unused
|
|
29504
|
+
meta.lastInsertId);
|
|
29299
29505
|
cpNodeAntipodeTwin.holeCloserTwin = cpNodeAntipode;
|
|
29300
29506
|
cpNodeAntipode.holeCloserTwin = cpNodeAntipodeTwin;
|
|
29301
29507
|
// Source - create and insert twin
|
|
29302
29508
|
const posSource = cpNodeSource.pointOnShape;
|
|
29303
|
-
const cpNodeSourceTwin = insertCpNode(true, true, false, cpTrees.get(posSource.curve.loop), { ...
|
|
29509
|
+
const cpNodeSourceTwin = insertCpNode(true, true, false, cpTrees.get(posSource.curve.loop), { ...posSource, order2: -1 }, cpNodeSource.prev, undefined, // unused
|
|
29510
|
+
meta.lastInsertId);
|
|
29304
29511
|
cpNodeSourceTwin.holeCloserTwin = cpNodeSource;
|
|
29305
29512
|
cpNodeSource.holeCloserTwin = cpNodeSourceTwin;
|
|
29306
29513
|
// Connect graph
|
|
@@ -29337,7 +29544,7 @@ function findAndAdd2Prongs(meta, angleIncrement, for2Prongs, for1Prong) {
|
|
|
29337
29544
|
const angleIncrement_ = angleIncrement * find_and_add_2_prongs_PI / 180;
|
|
29338
29545
|
for (let i = 0; i < for2Prongs.length; i++) {
|
|
29339
29546
|
const pos = for2Prongs[i];
|
|
29340
|
-
const angles = getValidAngles(angleIncrement_, pos);
|
|
29547
|
+
const angles = for1Prong ? [0] : getValidAngles(angleIncrement_, pos);
|
|
29341
29548
|
for (const angle of angles) {
|
|
29342
29549
|
const twoProngInfo = find2Prong_(false, for1Prong, angle, pos);
|
|
29343
29550
|
if (twoProngInfo) {
|
|
@@ -29872,7 +30079,9 @@ function getFor1ProngsOnLoop(minBezLength) {
|
|
|
29872
30079
|
return { curve, t, isSource: true, p, pDd };
|
|
29873
30080
|
}));
|
|
29874
30081
|
}
|
|
29875
|
-
return poss
|
|
30082
|
+
return poss
|
|
30083
|
+
// keep away from edges
|
|
30084
|
+
.filter(pos => pos.t > 2 ** -20 && pos.t < 2 ** -20);
|
|
29876
30085
|
};
|
|
29877
30086
|
}
|
|
29878
30087
|
|
|
@@ -30077,10 +30286,10 @@ function findMat(loops, maxCoordPowerOf2, options) {
|
|
|
30077
30286
|
}
|
|
30078
30287
|
if (typeof _debug_ !== 'undefined') {
|
|
30079
30288
|
if (_debug_.directives.stopAfterThreeProngs) {
|
|
30080
|
-
return { cpNode
|
|
30289
|
+
return { cpNode, meta };
|
|
30081
30290
|
}
|
|
30082
30291
|
}
|
|
30083
|
-
// if (cpNode !== undefined) { checkOrdering(
|
|
30292
|
+
// if (cpNode !== undefined) { checkOrdering(meta, cpNode); }
|
|
30084
30293
|
const mat = { cpNode, meta };
|
|
30085
30294
|
addDebugInfo4();
|
|
30086
30295
|
return mat;
|