@stemy/ngx-utils 19.7.2 → 19.7.5
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
|
|
@@ -3768,8 +3796,9 @@ class FormatterService {
|
|
|
3768
3796
|
precision = this.getPrecision(precision);
|
|
3769
3797
|
minDigits = minDigits ?? precision;
|
|
3770
3798
|
divider = divider || this.defaultDivider;
|
|
3771
|
-
const num = ObjectUtils.isNumber(value) ? value : parseFloat(value)
|
|
3772
|
-
const
|
|
3799
|
+
const num = (ObjectUtils.isNumber(value) ? value : parseFloat(value) ?? 0) / divider;
|
|
3800
|
+
const rounded = isNaN(num) ? 0 : MathUtils.round(0, 12);
|
|
3801
|
+
const str = rounded.toLocaleString(this.language.currentLanguage, {
|
|
3773
3802
|
minimumFractionDigits: minDigits,
|
|
3774
3803
|
maximumFractionDigits: precision,
|
|
3775
3804
|
useGrouping: false
|
|
@@ -7851,8 +7880,8 @@ class InteractiveItemComponent {
|
|
|
7851
7880
|
}
|
|
7852
7881
|
isValidByParams() {
|
|
7853
7882
|
return !this.shapes.some(shape => {
|
|
7854
|
-
return this.canvas.
|
|
7855
|
-
return shape.
|
|
7883
|
+
return this.canvas.excludedAreas.some(ex => {
|
|
7884
|
+
return shape.intersects(ex);
|
|
7856
7885
|
});
|
|
7857
7886
|
});
|
|
7858
7887
|
}
|
|
@@ -7949,7 +7978,7 @@ class InteractiveCanvasComponent {
|
|
|
7949
7978
|
this.rotation = 0;
|
|
7950
7979
|
this.basePan = 0;
|
|
7951
7980
|
this.cycles = [0];
|
|
7952
|
-
this.
|
|
7981
|
+
this.excludedAreas = [];
|
|
7953
7982
|
this.touched = false;
|
|
7954
7983
|
this.panStartRotation = 0;
|
|
7955
7984
|
this.panStartPos = Point.Zero;
|
|
@@ -8091,11 +8120,11 @@ class InteractiveCanvasComponent {
|
|
|
8091
8120
|
+ this.canvasHeight * this.panOffset;
|
|
8092
8121
|
this.cycles = this.infinite
|
|
8093
8122
|
? [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 =
|
|
8123
|
+
this.excludedAreas = (this.params.excludedAreas || []).flatMap(coords => {
|
|
8124
|
+
const x = coords.x * this.ratio;
|
|
8125
|
+
const y = coords.y * this.ratio;
|
|
8126
|
+
const width = coords.width * this.ratio;
|
|
8127
|
+
const height = coords.height * this.ratio;
|
|
8099
8128
|
return this.cycles.map(cycle => {
|
|
8100
8129
|
return new Rect(x, y + cycle, width, height);
|
|
8101
8130
|
});
|