@stemy/ngx-utils 19.7.2 → 19.7.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.
|
@@ -1895,36 +1895,64 @@ const MAX_ITERS = 40;
|
|
|
1895
1895
|
// GJK distance (robust)
|
|
1896
1896
|
// =========================
|
|
1897
1897
|
function gjkDistance(A, B) {
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1898
|
+
// 1) Quick overlap
|
|
1899
|
+
const inter = gjkIntersection(A, B);
|
|
1900
|
+
if (inter.hit) {
|
|
1901
|
+
// Pass through pa/pb
|
|
1902
|
+
return { distance: 0, pa: inter.pa ?? null, pb: inter.pb ?? null };
|
|
1903
|
+
}
|
|
1901
1904
|
const ca = A.center;
|
|
1902
1905
|
const cb = B.center;
|
|
1906
|
+
// 2) Bisection along the center-line to find the first hit pose
|
|
1903
1907
|
let s = 0;
|
|
1904
1908
|
let e = 1;
|
|
1905
|
-
let center = ca;
|
|
1906
1909
|
let iters = 0;
|
|
1907
|
-
|
|
1910
|
+
// Keep the best "hit" snapshot and its center so we can map witnesses back
|
|
1911
|
+
let hitSnap = null;
|
|
1912
|
+
let hitCenter = ca;
|
|
1913
|
+
while ((e - s) > EPSILON && iters < MAX_ITERS) {
|
|
1908
1914
|
iters++;
|
|
1909
|
-
const t = (e + s)
|
|
1910
|
-
|
|
1911
|
-
const
|
|
1912
|
-
|
|
1915
|
+
const t = (e + s) * 0.5;
|
|
1916
|
+
// Assumes A.move(newCenter) returns a NEW shape whose center is exactly this point
|
|
1917
|
+
const aMoved = A.move(lerpPts(ca, cb, t));
|
|
1918
|
+
const test = gjkIntersection(aMoved, B);
|
|
1913
1919
|
if (test.hit) {
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
break;
|
|
1920
|
+
hitSnap = test;
|
|
1921
|
+
hitCenter = aMoved.center;
|
|
1922
|
+
e = t; // shrink toward contact
|
|
1918
1923
|
}
|
|
1919
1924
|
else {
|
|
1920
|
-
s = t;
|
|
1925
|
+
s = t; // still separated
|
|
1921
1926
|
}
|
|
1922
1927
|
}
|
|
1923
|
-
|
|
1928
|
+
// 3) Make sure we end with a hit snapshot (in case we stopped on iteration cap)
|
|
1929
|
+
if (!hitSnap) {
|
|
1930
|
+
const aMoved = A.move(lerpPts(ca, cb, e));
|
|
1931
|
+
const test = gjkIntersection(aMoved, B);
|
|
1932
|
+
if (test.hit) {
|
|
1933
|
+
hitSnap = test;
|
|
1934
|
+
hitCenter = aMoved.center;
|
|
1935
|
+
}
|
|
1936
|
+
else {
|
|
1937
|
+
// Extremely degenerate: no hit even at e ~ 1 (shouldn't happen for non-degenerate shapes).
|
|
1938
|
+
// Fall back to center-line direction as a last resort.
|
|
1939
|
+
const dir = normalizePt(subPts(cb, ca));
|
|
1940
|
+
const pa0 = A.support(dir);
|
|
1941
|
+
const pb0 = B.support(negatePt(dir));
|
|
1942
|
+
return { distance: distance(pa0, pb0), pa: pa0, pb: pb0 };
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
// 4) Map witnesses back to the original A pose
|
|
1946
|
+
// (We moved A by (hitCenter - ca); to undo, offset A's witness by (ca - hitCenter))
|
|
1947
|
+
const offset = subPts(ca, hitCenter);
|
|
1948
|
+
const pa0 = addPts(hitSnap.pa, offset);
|
|
1949
|
+
const pb0 = hitSnap.pb;
|
|
1950
|
+
// 5) True geometric separation is the distance between these boundary points
|
|
1951
|
+
const d = distance(pa0, pb0);
|
|
1924
1952
|
return {
|
|
1925
|
-
distance:
|
|
1926
|
-
pa:
|
|
1927
|
-
pb:
|
|
1953
|
+
distance: d,
|
|
1954
|
+
pa: d > 0 ? pa0 : null,
|
|
1955
|
+
pb: d > 0 ? pb0 : null
|
|
1928
1956
|
};
|
|
1929
1957
|
}
|
|
1930
1958
|
// =========================
|
|
@@ -2010,20 +2038,20 @@ function doSimplexBoolean(simplex, d) {
|
|
|
2010
2038
|
const A = last, B = simplex[simplex.length - 2], C = simplex[simplex.length - 3];
|
|
2011
2039
|
const AB = { x: B.p.x - A.p.x, y: B.p.y - A.p.y };
|
|
2012
2040
|
const AC = { x: C.p.x - A.p.x, y: C.p.y - A.p.y };
|
|
2013
|
-
const
|
|
2014
|
-
const
|
|
2041
|
+
const perpAB = tripleProduct(AC, AB, AB);
|
|
2042
|
+
const perpAC = tripleProduct(AB, AC, AC);
|
|
2015
2043
|
// If origin is outside AB region
|
|
2016
|
-
if (
|
|
2044
|
+
if (perpAB.x * AO.x + perpAB.y * AO.y > 0) {
|
|
2017
2045
|
simplex.splice(simplex.length - 3, 1);
|
|
2018
|
-
d.x =
|
|
2019
|
-
d.y =
|
|
2046
|
+
d.x = perpAB.x;
|
|
2047
|
+
d.y = perpAB.y;
|
|
2020
2048
|
return { hit: false };
|
|
2021
2049
|
}
|
|
2022
2050
|
// If origin is outside AC region
|
|
2023
|
-
if (
|
|
2051
|
+
if (perpAC.x * AO.x + perpAC.y * AO.y > 0) {
|
|
2024
2052
|
simplex.splice(simplex.length - 2, 1);
|
|
2025
|
-
d.x =
|
|
2026
|
-
d.y =
|
|
2053
|
+
d.x = perpAC.x;
|
|
2054
|
+
d.y = perpAC.y;
|
|
2027
2055
|
return { hit: false };
|
|
2028
2056
|
}
|
|
2029
2057
|
// Otherwise the origin is inside the triangle → overlap
|
|
@@ -7851,8 +7879,8 @@ class InteractiveItemComponent {
|
|
|
7851
7879
|
}
|
|
7852
7880
|
isValidByParams() {
|
|
7853
7881
|
return !this.shapes.some(shape => {
|
|
7854
|
-
return this.canvas.
|
|
7855
|
-
return shape.
|
|
7882
|
+
return this.canvas.excludedAreas.some(ex => {
|
|
7883
|
+
return shape.intersects(ex);
|
|
7856
7884
|
});
|
|
7857
7885
|
});
|
|
7858
7886
|
}
|
|
@@ -7949,7 +7977,7 @@ class InteractiveCanvasComponent {
|
|
|
7949
7977
|
this.rotation = 0;
|
|
7950
7978
|
this.basePan = 0;
|
|
7951
7979
|
this.cycles = [0];
|
|
7952
|
-
this.
|
|
7980
|
+
this.excludedAreas = [];
|
|
7953
7981
|
this.touched = false;
|
|
7954
7982
|
this.panStartRotation = 0;
|
|
7955
7983
|
this.panStartPos = Point.Zero;
|
|
@@ -8091,11 +8119,11 @@ class InteractiveCanvasComponent {
|
|
|
8091
8119
|
+ this.canvasHeight * this.panOffset;
|
|
8092
8120
|
this.cycles = this.infinite
|
|
8093
8121
|
? [this.basePan - this.fullHeight, this.basePan, this.basePan + this.fullHeight] : [0];
|
|
8094
|
-
this.
|
|
8095
|
-
const x =
|
|
8096
|
-
const y =
|
|
8097
|
-
const width =
|
|
8098
|
-
const height =
|
|
8122
|
+
this.excludedAreas = (this.params.excludedAreas || []).flatMap(coords => {
|
|
8123
|
+
const x = coords.x * this.ratio;
|
|
8124
|
+
const y = coords.y * this.ratio;
|
|
8125
|
+
const width = coords.width * this.ratio;
|
|
8126
|
+
const height = coords.height * this.ratio;
|
|
8099
8127
|
return this.cycles.map(cycle => {
|
|
8100
8128
|
return new Rect(x, y + cycle, width, height);
|
|
8101
8129
|
});
|