@stemy/ngx-utils 19.7.1 → 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.
@@ -1146,6 +1146,9 @@ function drawOval(ctx, w, h) {
1146
1146
  ctx.ellipse(0, 0, w / 2, h / 2, 0, 0, Math.PI * 2);
1147
1147
  ctx.closePath();
1148
1148
  }
1149
+ function drawPoint(ctx) {
1150
+ drawOval(ctx, 4, 4);
1151
+ }
1149
1152
  class CanvasUtils {
1150
1153
  static manipulatePixels(canvas, ctx, colorTransformer) {
1151
1154
  const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
@@ -1732,28 +1735,54 @@ class FileSystemEntry {
1732
1735
  function dotProduct(a, b) {
1733
1736
  return a.x * b.x + a.y * b.y;
1734
1737
  }
1738
+ function tripleProduct(a, b, c) {
1739
+ const ac = a.x * c.x + a.y * c.y;
1740
+ const bc = b.x * c.x + b.y * c.y;
1741
+ return { x: b.x * ac - a.x * bc, y: b.y * ac - a.y * bc };
1742
+ }
1735
1743
  function isPoint(v) {
1736
- return typeof v === "object" && !isNaN(v.x) && !isNaN(v.y);
1744
+ return typeof v === "object" && Number.isFinite(v.x) && Number.isFinite(v.y);
1745
+ }
1746
+ function ensurePoint(p, fallback = { x: 0, y: 0 }) {
1747
+ return isPoint(p) ? { x: +p.x, y: +p.y } : fallback;
1737
1748
  }
1738
1749
  function perpendicular(p) {
1739
1750
  return { x: -p.y, y: +p.x };
1740
1751
  }
1741
- function ptAdd(a, b) {
1752
+ function negatePt(p) {
1753
+ return { x: -p.x, y: -p.y };
1754
+ }
1755
+ function normalizePt(p) {
1756
+ const length = lengthOfPt(p);
1757
+ return dividePts(p, length);
1758
+ }
1759
+ function addPts(a, b) {
1742
1760
  return { x: a.x + b.x, y: a.y + b.y };
1743
1761
  }
1744
- function ptDistance(a, b) {
1762
+ function distanceSq(a, b) {
1745
1763
  const x = b.x - a.x;
1746
1764
  const y = b.y - a.y;
1747
- return Math.sqrt(x * x + y * y);
1765
+ return x * x + y * y;
1766
+ }
1767
+ function distance(a, b) {
1768
+ return Math.sqrt(distanceSq(a, b));
1748
1769
  }
1749
- function ptLength(p) {
1770
+ function lerpPts(a, b, t) {
1771
+ const diff = subPts(b, a);
1772
+ return addPts(a, multiplyPts(diff, t));
1773
+ }
1774
+ function lengthOfPt(p) {
1750
1775
  return Math.hypot(p.x, p.y);
1751
1776
  }
1752
- function ptMultiply(a, b) {
1777
+ function multiplyPts(a, b) {
1753
1778
  const s = isPoint(b) ? b : { x: b, y: b };
1754
1779
  return { x: a.x * s.x, y: a.y * s.y };
1755
1780
  }
1756
- function ptSubtract(a, b) {
1781
+ function dividePts(a, b) {
1782
+ const s = isPoint(b) ? b : { x: b, y: b };
1783
+ return { x: a.x / s.x, y: a.y / s.y };
1784
+ }
1785
+ function subPts(a, b) {
1757
1786
  return { x: a.x - b.x, y: a.y - b.y };
1758
1787
  }
1759
1788
  function rotateDeg(p, ang) {
@@ -1770,125 +1799,289 @@ function toRadians(deg) {
1770
1799
  return deg * Math.PI / 180;
1771
1800
  }
1772
1801
 
1773
- function combineA(simplex, bary) {
1774
- let out = { x: 0, y: 0 };
1775
- for (let i = 0; i < simplex.length; i++)
1776
- out = ptAdd(out, ptMultiply(simplex[i].a, bary[i] || 0));
1777
- return out;
1802
+ const EPSILON = 1e-9;
1803
+ /**
1804
+ * Normalize a range
1805
+ * @param minOrRange
1806
+ * @param max
1807
+ */
1808
+ function normalizeRange(minOrRange, max) {
1809
+ const min = (Array.isArray(minOrRange) ? minOrRange[0] : minOrRange) ?? 0;
1810
+ max = (Array.isArray(minOrRange) ? minOrRange[1] : max) ?? 1;
1811
+ return (max < min) ? [max, min] : [min, max];
1778
1812
  }
1779
- function combineB(simplex, bary) {
1780
- let out = { x: 0, y: 0 };
1781
- for (let i = 0; i < simplex.length; i++)
1782
- out = ptAdd(out, ptMultiply(simplex[i].b, bary[i] || 0));
1783
- return out;
1813
+ /**
1814
+ * Clamps a value to a range
1815
+ * @param value
1816
+ * @param min
1817
+ * @param max
1818
+ */
1819
+ function clamp(value, min, max) {
1820
+ const range = normalizeRange(min, max);
1821
+ return Math.max(Math.min(value, range[1]), range[0]);
1784
1822
  }
1785
- function closestPointToOrigin(simplex) {
1786
- // returns { simplex: prunedSimplex, closest: vec, bary: weights[] }
1787
- if (simplex.length === 1) {
1788
- return { simplex, closest: simplex[0].p, bary: [1] };
1789
- }
1790
- if (simplex.length === 2) {
1791
- const A = simplex[0], B = simplex[1];
1792
- const ab = ptSubtract(B.p, A.p);
1793
- const ab2 = dotProduct(ab, ab);
1794
- if (ab2 <= 1e-18) {
1795
- return { simplex: [B], closest: B.p, bary: [1] };
1796
- }
1797
- const t = Math.max(0, Math.min(1, -dotProduct(A.p, ab) / ab2));
1798
- const closest = ptAdd(A.p, ptMultiply(ab, t));
1799
- if (t <= 1e-9) {
1800
- return { simplex: [A], closest: A.p, bary: [1] };
1801
- }
1802
- if (t >= 1 - 1e-9) {
1803
- return { simplex: [B], closest: B.p, bary: [1] };
1804
- }
1805
- return { simplex: [A, B], closest, bary: [1 - t, t] };
1806
- }
1807
- // Triangle case (A,B,C) – use Ericson's closest-point to triangle (p=origin)
1808
- const A = simplex[0], B = simplex[1], C = simplex[2];
1809
- const a = A.p, b = B.p, c = C.p;
1810
- const ab = ptSubtract(b, a), ac = ptSubtract(c, a), ap = { x: -a.x, y: -a.y };
1811
- const d1 = dotProduct(ab, ap), d2 = dotProduct(ac, ap);
1812
- if (d1 <= 0 && d2 <= 0)
1813
- return { simplex: [A], closest: a, bary: [1] };
1814
- const bp = { x: -b.x, y: -b.y };
1815
- const d3 = dotProduct(ab, bp), d4 = dotProduct(ac, bp);
1816
- if (d3 >= 0 && d4 <= d3)
1817
- return { simplex: [B], closest: b, bary: [1] };
1818
- const vc = d1 * d4 - d3 * d2;
1819
- if (vc <= 0 && d1 >= 0 && d3 <= 0) {
1820
- const v = d1 / (d1 - d3);
1821
- const closest = ptAdd(a, ptMultiply(ab, v));
1822
- return { simplex: [A, B], closest, bary: [1 - v, v] };
1823
- }
1824
- const cp = { x: -c.x, y: -c.y };
1825
- const bc = ptSubtract(c, b);
1826
- const d5 = dotProduct(bc, cp), d6 = dotProduct(ac, cp);
1827
- if (d6 >= 0 && d5 <= d6)
1828
- return { simplex: [C], closest: c, bary: [1] };
1829
- const vb = d5 * d2 - d1 * d6;
1830
- if (vb <= 0 && d2 >= 0 && d6 <= 0) {
1831
- const w = d2 / (d2 - d6);
1832
- const closest = ptAdd(a, ptMultiply(ac, w));
1833
- return { simplex: [A, C], closest, bary: [1 - w, 0, w] };
1834
- }
1835
- const va = d3 * d6 - d5 * d4;
1836
- if (va <= 0) {
1837
- const denom = (d4 - d3) + (d5 - d6);
1838
- const w = denom !== 0 ? (d4 - d3) / denom : 0.5;
1839
- const closest = ptAdd(b, ptMultiply(bc, w));
1840
- return { simplex: [B, C], closest, bary: [0, 1 - w, w] };
1841
- }
1842
- // Origin inside triangle – distance is zero
1843
- return { simplex: [A, B, C], closest: { x: 0, y: 0 }, bary: [0, 0, 0] };
1823
+ /**
1824
+ * Clamps a value to a range in a way, that when it is over in one end, then it appears from the other end
1825
+ * @param value
1826
+ * @param min
1827
+ * @param max
1828
+ */
1829
+ function overflow(value, min, max) {
1830
+ const range = normalizeRange(min, max);
1831
+ const length = range[1] - range[0];
1832
+ return ((((value - range[0]) % length) + length) % length) + range[0];
1844
1833
  }
1845
1834
  /**
1846
- * ====== GJK distance (2D) ======
1847
- * We keep, for each simplex vertex, the Minkowski point p = a - b and the witnesses a,b.
1848
- * @param A
1849
- * @param B
1835
+ * Checks if a number is equal to b number with epsilon tolerance
1836
+ * @param a
1837
+ * @param b
1838
+ * @param epsilon
1850
1839
  */
1840
+ function isEqual(a, b, epsilon = null) {
1841
+ epsilon = ObjectUtils.isNumber(epsilon) ? epsilon : EPSILON;
1842
+ return Math.abs(a - b) <= epsilon;
1843
+ }
1844
+ /**
1845
+ * Checks if a number is equal to zero with epsilon tolerance
1846
+ * @param a
1847
+ * @param epsilon
1848
+ */
1849
+ function isZero(a, epsilon = null) {
1850
+ return isEqual(a, 0, epsilon);
1851
+ }
1852
+ class MathUtils {
1853
+ static equal(a, b, epsilon = null) {
1854
+ return isEqual(a, b, epsilon);
1855
+ }
1856
+ static clamp(value, min, max) {
1857
+ return clamp(value, min, max);
1858
+ }
1859
+ static round(value, precision = 2, divider = 1) {
1860
+ precision = Math.pow(10, precision);
1861
+ return Math.round(value * precision / divider) / precision;
1862
+ }
1863
+ static approxIndex(x, values, epsilon = null) {
1864
+ if (!Array.isArray(values) || values.length == 0) {
1865
+ return -1;
1866
+ }
1867
+ let s = 0;
1868
+ let e = values.length - 1;
1869
+ while (s <= e) {
1870
+ const i = Math.floor((s + e) / 2);
1871
+ const v = values[i];
1872
+ if (MathUtils.equal(v, x, epsilon)) {
1873
+ return i;
1874
+ }
1875
+ if (v < x) {
1876
+ s = i + 1;
1877
+ }
1878
+ else {
1879
+ e = i - 1;
1880
+ }
1881
+ }
1882
+ const m = Math.max(e, 0);
1883
+ const a = values[s];
1884
+ const b = values[m];
1885
+ return Math.abs(a - x) < Math.abs(b - x) ? s : m;
1886
+ }
1887
+ static approximate(x, values, epsilon = null) {
1888
+ const index = MathUtils.approxIndex(x, values, epsilon);
1889
+ return values[index] ?? null;
1890
+ }
1891
+ }
1892
+
1893
+ const MAX_ITERS = 40;
1894
+ // =========================
1895
+ // GJK distance (robust)
1896
+ // =========================
1851
1897
  function gjkDistance(A, B) {
1852
- const MAX = 64, EPS = 1e-9;
1853
- const centerA = { x: A.x, y: A.y }, centerB = { x: B.x, y: B.y };
1854
- let d = ptSubtract(centerB, centerA);
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
+ }
1904
+ const ca = A.center;
1905
+ const cb = B.center;
1906
+ // 2) Bisection along the center-line to find the first hit pose
1907
+ let s = 0;
1908
+ let e = 1;
1909
+ let iters = 0;
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) {
1914
+ iters++;
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);
1919
+ if (test.hit) {
1920
+ hitSnap = test;
1921
+ hitCenter = aMoved.center;
1922
+ e = t; // shrink toward contact
1923
+ }
1924
+ else {
1925
+ s = t; // still separated
1926
+ }
1927
+ }
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);
1952
+ return {
1953
+ distance: d,
1954
+ pa: d > 0 ? pa0 : null,
1955
+ pb: d > 0 ? pb0 : null
1956
+ };
1957
+ }
1958
+ // =========================
1959
+ // Boolean GJK (robust)
1960
+ // =========================
1961
+ function gjkIntersection(A, B) {
1962
+ const MAX = 64, EPS = 1e-12;
1963
+ const sup = (dir) => {
1964
+ const a = ensurePoint(A.support(dir), A.center);
1965
+ const b = ensurePoint(B.support(negatePt(dir)), B.center);
1966
+ return { p: subPts(a, b), a, b };
1967
+ };
1968
+ // initial direction: center-to-center; fall back to x-axis
1969
+ let d = subPts(B.center, A.center);
1855
1970
  if (Math.abs(d.x) < EPS && Math.abs(d.y) < EPS)
1856
1971
  d = { x: 1, y: 0 };
1857
- const sup = (dir) => {
1858
- const a = A.support(dir);
1859
- const b = B.support({ x: -dir.x, y: -dir.y });
1860
- return { p: ptSubtract(a, b), a, b };
1972
+ const simplex = [sup(d)];
1973
+ d = { x: -simplex[0].p.x, y: -simplex[0].p.y };
1974
+ for (let i = 0; i < MAX; i++) {
1975
+ // If direction collapses, steer toward origin from last point
1976
+ const dLen = Math.hypot(d.x, d.y);
1977
+ if (dLen <= EPS) {
1978
+ const last = simplex[simplex.length - 1];
1979
+ const AO = { x: -last.p.x, y: -last.p.y };
1980
+ const aoLen = Math.hypot(AO.x, AO.y);
1981
+ d = (aoLen > EPS) ? AO : { x: 1, y: 0 };
1982
+ }
1983
+ const a = sup(d);
1984
+ const s = a.p.x * d.x + a.p.y * d.y;
1985
+ if (s < -1e-12)
1986
+ return { hit: false }; // definite separation
1987
+ if (Math.abs(s) <= 1e-12) { // tangential contact: use normal ±d
1988
+ const L = Math.hypot(d.x, d.y) || 1;
1989
+ const n = { x: d.x / L, y: d.y / L };
1990
+ const pa = ensurePoint(A.support(n), A.center);
1991
+ const pb = ensurePoint(B.support(negatePt(n)), B.center);
1992
+ const point = { x: (pa.x + pb.x) / 2, y: (pa.y + pb.y) / 2 };
1993
+ return { hit: true, pa, pb, point };
1994
+ }
1995
+ simplex.push(a);
1996
+ {
1997
+ const info = doSimplexBoolean(simplex, d);
1998
+ if (info.hit)
1999
+ return info;
2000
+ }
2001
+ }
2002
+ // Max iterations without resolution → disjoint
2003
+ return { hit: false };
2004
+ }
2005
+ function doSimplexBoolean(simplex, d) {
2006
+ const last = simplex[simplex.length - 1];
2007
+ const AO = { x: -last.p.x, y: -last.p.y };
2008
+ if (simplex.length === 2) {
2009
+ const B = simplex[0];
2010
+ const AB = { x: B.p.x - last.p.x, y: B.p.y - last.p.y };
2011
+ // Perpendicular to AB toward origin
2012
+ const abPerp = tripleProduct(AB, AO, AB);
2013
+ const perpLen2 = abPerp.x * abPerp.x + abPerp.y * abPerp.y;
2014
+ if (perpLen2 < 1e-24) {
2015
+ // Colinear: project origin onto segment AB
2016
+ const ab2 = AB.x * AB.x + AB.y * AB.y;
2017
+ if (ab2 > 0) {
2018
+ const t = ((AO.x * AB.x + AO.y * AB.y) / ab2);
2019
+ if (t >= 0 && t <= 1) {
2020
+ // Contact at segment
2021
+ const pa = { x: last.a.x + t * (B.a.x - last.a.x), y: last.a.y + t * (B.a.y - last.a.y) };
2022
+ const pb = { x: last.b.x + t * (B.b.x - last.b.x), y: last.b.y + t * (B.b.y - last.b.y) };
2023
+ const point = { x: (pa.x + pb.x) / 2, y: (pa.y + pb.y) / 2 };
2024
+ return { hit: true, pa, pb, point };
2025
+ }
2026
+ }
2027
+ // Otherwise, move toward origin from A, keep only last point to progress
2028
+ d.x = -AO.x;
2029
+ d.y = -AO.y;
2030
+ simplex.splice(0, simplex.length - 1);
2031
+ return { hit: false };
2032
+ }
2033
+ d.x = abPerp.x;
2034
+ d.y = abPerp.y;
2035
+ return { hit: false };
2036
+ }
2037
+ // Triangle case: [C, B, A] with A = last
2038
+ const A = last, B = simplex[simplex.length - 2], C = simplex[simplex.length - 3];
2039
+ const AB = { x: B.p.x - A.p.x, y: B.p.y - A.p.y };
2040
+ const AC = { x: C.p.x - A.p.x, y: C.p.y - A.p.y };
2041
+ const perpAB = tripleProduct(AC, AB, AB);
2042
+ const perpAC = tripleProduct(AB, AC, AC);
2043
+ // If origin is outside AB region
2044
+ if (perpAB.x * AO.x + perpAB.y * AO.y > 0) {
2045
+ simplex.splice(simplex.length - 3, 1);
2046
+ d.x = perpAB.x;
2047
+ d.y = perpAB.y;
2048
+ return { hit: false };
2049
+ }
2050
+ // If origin is outside AC region
2051
+ if (perpAC.x * AO.x + perpAC.y * AO.y > 0) {
2052
+ simplex.splice(simplex.length - 2, 1);
2053
+ d.x = perpAC.x;
2054
+ d.y = perpAC.y;
2055
+ return { hit: false };
2056
+ }
2057
+ // Otherwise the origin is inside the triangle → overlap
2058
+ // Compute barycentric weights of origin w.r.t triangle (A,B,C)
2059
+ const v0 = AB; // B-A
2060
+ const v1 = AC; // C-A
2061
+ const b = { x: -A.p.x, y: -A.p.y };
2062
+ const det = v0.x * v1.y - v0.y * v1.x;
2063
+ let uA, uB, uC;
2064
+ if (Math.abs(det) > 1e-24) {
2065
+ const alpha = (b.x * v1.y - v1.x * b.y) / det; // weight for v0 (B)
2066
+ const beta = (v0.x * b.y - b.x * v0.y) / det; // weight for v1 (C)
2067
+ uB = alpha;
2068
+ uC = beta;
2069
+ uA = 1 - alpha - beta;
2070
+ }
2071
+ else {
2072
+ // Fallback: equal weights
2073
+ uA = uB = uC = 1 / 3;
2074
+ }
2075
+ const pa = {
2076
+ x: uA * A.a.x + uB * B.a.x + uC * C.a.x,
2077
+ y: uA * A.a.y + uB * B.a.y + uC * C.a.y
1861
2078
  };
1862
- let simplex = [sup(d)];
1863
- let closest = simplex[0].p; // vector to origin
1864
- let dir = { x: -closest.x, y: -closest.y };
1865
- let best2 = dotProduct(closest, closest);
1866
- for (let iter = 0; iter < MAX; iter++) {
1867
- if (ptLength(dir) <= EPS) { // origin reached
1868
- const a = simplex[simplex.length - 1].a, b = simplex[simplex.length - 1].b;
1869
- return { distance: 0, pa: a, pb: b };
1870
- }
1871
- const vtx = sup(dir);
1872
- // termination: support didn't pass beyond previous closest along dir
1873
- if (dotProduct(vtx.p, dir) - Math.sqrt(best2) <= EPS) {
1874
- break;
1875
- }
1876
- simplex.push(vtx);
1877
- const reduced = closestPointToOrigin(simplex);
1878
- simplex = reduced.simplex;
1879
- closest = reduced.closest;
1880
- best2 = dotProduct(closest, closest);
1881
- dir = { x: -closest.x, y: -closest.y };
1882
- if (best2 <= EPS * EPS) {
1883
- const pa = combineA(simplex, reduced.bary);
1884
- const pb = combineB(simplex, reduced.bary);
1885
- return { distance: 0, pa, pb };
1886
- }
1887
- }
1888
- const res = closestPointToOrigin(simplex);
1889
- const pa = combineA(simplex, res.bary);
1890
- const pb = combineB(simplex, res.bary);
1891
- return { distance: Math.sqrt(dotProduct(res.closest, res.closest)), pa, pb };
2079
+ const pb = {
2080
+ x: uA * A.b.x + uB * B.b.x + uC * C.b.x,
2081
+ y: uA * A.b.y + uB * B.b.y + uC * C.b.y
2082
+ };
2083
+ const point = { x: (pa.x + pb.x) / 2, y: (pa.y + pb.y) / 2 };
2084
+ return { hit: true, pa, pb, point };
1892
2085
  }
1893
2086
 
1894
2087
  class Shape {
@@ -1904,17 +2097,23 @@ class Shape {
1904
2097
  constructor(x, y) {
1905
2098
  this.pt = { x, y };
1906
2099
  }
1907
- distance(p) {
1908
- return ptDistance(this.center, p);
2100
+ intersection(shape) {
2101
+ return gjkIntersection(this, shape);
2102
+ }
2103
+ intersects(shape) {
2104
+ return this.intersection(shape).hit;
1909
2105
  }
1910
2106
  minDistance(shape) {
1911
- return gjkDistance(this, shape).distance;
2107
+ return gjkDistance(this, shape);
2108
+ }
2109
+ distance(shape) {
2110
+ return this.minDistance(shape).distance;
1912
2111
  }
1913
2112
  }
1914
2113
  class Point extends Shape {
1915
2114
  static { this.Zero = new Point(0, 0); }
1916
2115
  get length() {
1917
- return ptLength(this);
2116
+ return lengthOfPt(this);
1918
2117
  }
1919
2118
  get perpendicular() {
1920
2119
  return new Point(perpendicular(this));
@@ -1925,32 +2124,35 @@ class Point extends Shape {
1925
2124
  this.pt = isPoint(xOrP) ? xOrP : { x: isNaN(x) ? 0 : xOrP, y };
1926
2125
  }
1927
2126
  support() {
1928
- return this.pt;
2127
+ return this.center;
2128
+ }
2129
+ move(pos) {
2130
+ return new Point(pos);
1929
2131
  }
1930
2132
  add(p) {
1931
- return new Point(ptAdd(this, p));
2133
+ return new Point(addPts(this, p));
2134
+ }
2135
+ subtract(p) {
2136
+ return new Point(subPts(this, p));
1932
2137
  }
1933
- sub(p) {
1934
- return new Point(ptSubtract(this, p));
2138
+ multiply(p) {
2139
+ return new Point(multiplyPts(this, p));
1935
2140
  }
1936
- mul(p) {
1937
- return new Point(ptMultiply(this, p));
2141
+ divide(p) {
2142
+ return new Point(multiplyPts(this, p));
1938
2143
  }
1939
2144
  dot(p) {
1940
2145
  return new Point(dotProduct(this, p));
1941
2146
  }
1942
- distance(p) {
1943
- return ptDistance(this, p);
1944
- }
1945
2147
  lerp(p, ratio) {
1946
- const diff = p.sub(this);
1947
- return this.add(diff.mul(ratio));
2148
+ const diff = p.subtract(this);
2149
+ return this.add(diff.multiply(ratio));
1948
2150
  }
1949
2151
  perpendicularTo(p, length) {
1950
- const diff = p.perpendicular.sub(this.perpendicular);
2152
+ const diff = p.perpendicular.subtract(this.perpendicular);
1951
2153
  const ratio = length / diff.length;
1952
2154
  const center = this.lerp(p, .5);
1953
- return center.add(diff.mul(ratio));
2155
+ return center.add(diff.multiply(ratio));
1954
2156
  }
1955
2157
  circleWith(a, b) {
1956
2158
  const yDelta_a = b.y - a.y;
@@ -1965,8 +2167,8 @@ class Point extends Shape {
1965
2167
  return new Circle(center.x, center.y, center.distance(this));
1966
2168
  }
1967
2169
  tangents(c) {
1968
- const pd = ptSubtract(c.center, this);
1969
- const a = Math.asin(c.radius / ptLength(pd));
2170
+ const pd = subPts(c.center, this);
2171
+ const a = Math.asin(c.radius / lengthOfPt(pd));
1970
2172
  const b = Math.atan2(pd.y, pd.x);
1971
2173
  // Tangent points
1972
2174
  let t = b - a;
@@ -1976,7 +2178,7 @@ class Point extends Shape {
1976
2178
  return [t1, t2];
1977
2179
  }
1978
2180
  angle(p) {
1979
- const diff = p.sub(this);
2181
+ const diff = p.subtract(this);
1980
2182
  return Math.atan2(diff.y, diff.x) * 180 / Math.PI;
1981
2183
  }
1982
2184
  rotateAround(p, angle) {
@@ -1995,11 +2197,16 @@ class Rect extends Shape {
1995
2197
  }
1996
2198
  support(dir) {
1997
2199
  const ang = this.rotation ?? 0;
1998
- const dLocal = rotateDeg(dir, -ang);
2200
+ const dLocal = rotateDeg(ensurePoint(dir, { x: 1, y: 0 }), -ang);
1999
2201
  const hw = Math.max(0, this.width / 2), hh = Math.max(0, this.height / 2);
2202
+ if (hw === 0 && hh === 0)
2203
+ return ensurePoint(this.center);
2000
2204
  const lx = dLocal.x >= 0 ? hw : -hw;
2001
2205
  const ly = dLocal.y >= 0 ? hh : -hh;
2002
- return ptAdd(rotateDeg({ x: lx, y: ly }, ang), { x: this.x, y: this.y });
2206
+ return addPts(rotateDeg({ x: lx, y: ly }, ang), this.center);
2207
+ }
2208
+ move(pos) {
2209
+ return new Rect(pos.x, pos.y, this.width, this.height, this.rotation);
2003
2210
  }
2004
2211
  }
2005
2212
  class Oval extends Shape {
@@ -2011,15 +2218,16 @@ class Oval extends Shape {
2011
2218
  }
2012
2219
  support(dir) {
2013
2220
  const ang = this.rotation ?? 0;
2014
- const d = rotateDeg(dir, -ang);
2015
- const a = Math.max(0, this.width / 2);
2016
- const b = Math.max(0, this.height / 2);
2017
- if (Math.abs(d.x) < 1e-12 && Math.abs(d.y) < 1e-12)
2018
- return { x: this.x, y: this.y };
2019
- const q = Math.hypot(a * d.x, b * d.y) || 1; // sqrt((a*dx)^2 + (b*dy)^2)
2020
- const lx = (a * a * d.x) / q;
2021
- const ly = (b * b * d.y) / q;
2022
- return ptAdd(rotateDeg({ x: lx, y: ly }, ang), { x: this.x, y: this.y });
2221
+ const d = rotateDeg(ensurePoint(dir, { x: 1, y: 0 }), -ang);
2222
+ const a = Math.max(0, this.width / 2), b = Math.max(0, this.height / 2);
2223
+ if (a === 0 && b === 0)
2224
+ return ensurePoint(this.center);
2225
+ const q = Math.hypot(a * d.x, b * d.y) || 1;
2226
+ const lx = (a * a * d.x) / q, ly = (b * b * d.y) / q;
2227
+ return addPts(rotateDeg({ x: lx, y: ly }, ang), this.center);
2228
+ }
2229
+ move(pos) {
2230
+ return new Oval(pos.x, pos.y, this.width, this.height, this.rotation);
2023
2231
  }
2024
2232
  }
2025
2233
  class Circle extends Oval {
@@ -2027,6 +2235,9 @@ class Circle extends Oval {
2027
2235
  super(x, y, radius * 2, radius * 2, rotation);
2028
2236
  this.radius = radius;
2029
2237
  }
2238
+ move(pos) {
2239
+ return new Circle(pos.x, pos.y, this.radius, this.rotation);
2240
+ }
2030
2241
  }
2031
2242
 
2032
2243
  class Initializer {
@@ -2158,49 +2369,6 @@ class LoaderUtils {
2158
2369
  }
2159
2370
  }
2160
2371
 
2161
- const EPSILON = 1e-9;
2162
- class MathUtils {
2163
- static equal(a, b, epsilon = null) {
2164
- epsilon = ObjectUtils.isNumber(epsilon) ? epsilon : EPSILON;
2165
- return Math.abs(a - b) < epsilon;
2166
- }
2167
- static clamp(value, min, max) {
2168
- return Math.max(Math.min(value, max), min);
2169
- }
2170
- static round(value, precision = 2, divider = 1) {
2171
- precision = Math.pow(10, precision);
2172
- return Math.round(value * precision / divider) / precision;
2173
- }
2174
- static approxIndex(x, values, epsilon = null) {
2175
- if (!Array.isArray(values) || values.length == 0) {
2176
- return -1;
2177
- }
2178
- let s = 0;
2179
- let e = values.length - 1;
2180
- while (s <= e) {
2181
- const i = Math.floor((s + e) / 2);
2182
- const v = values[i];
2183
- if (MathUtils.equal(v, x, epsilon)) {
2184
- return i;
2185
- }
2186
- if (v < x) {
2187
- s = i + 1;
2188
- }
2189
- else {
2190
- e = i - 1;
2191
- }
2192
- }
2193
- const m = Math.max(e, 0);
2194
- const a = values[s];
2195
- const b = values[m];
2196
- return Math.abs(a - x) < Math.abs(b - x) ? s : m;
2197
- }
2198
- static approximate(x, values, epsilon = null) {
2199
- const index = MathUtils.approxIndex(x, values, epsilon);
2200
- return values[index] ?? null;
2201
- }
2202
- }
2203
-
2204
2372
  function isBrowser() {
2205
2373
  return typeof window !== "undefined";
2206
2374
  }
@@ -7669,29 +7837,31 @@ class InteractiveItemComponent {
7669
7837
  }
7670
7838
  hit(point) {
7671
7839
  for (const shape of this.shapes) {
7672
- if (shape.minDistance(point) <= 0)
7840
+ if (shape.intersects(point))
7673
7841
  return true;
7674
7842
  }
7675
7843
  return false;
7676
7844
  }
7677
- moveBy(dx, dy) {
7678
- if (this.direction === "none")
7845
+ moveTo(x, y) {
7846
+ if (!this.canvas || this.direction === "none")
7679
7847
  return;
7680
- switch (this.direction) {
7681
- case "horizontal":
7682
- this.pos = new Point(this.pos.x + dx, this.pos.y);
7683
- break;
7684
- case "vertical":
7685
- this.pos = new Point(this.pos.x, this.pos.y + dy);
7686
- break;
7687
- default:
7688
- this.pos = new Point(this.pos.x + dx, this.pos.y + dy);
7689
- break;
7690
- }
7848
+ const target = this.restrictPosition(this.direction === "vertical" ? this.pos.x : x, this.direction === "horizontal" ? this.pos.y : y);
7849
+ this.pos = new Point(target);
7691
7850
  this.calcShapes();
7692
- this.valid = this.isValidByParams() && this.canvas.items.every(other => this === other || this.isValidByDistance(other));
7851
+ this.valid = this.isValidByParams() &&
7852
+ this.canvas.items.every(other => this === other || this.isValidByDistance(other));
7693
7853
  this.validPos = this.valid ? this.pos : this.validPos;
7694
7854
  }
7855
+ moveBy(dx, dy) {
7856
+ const { x, y } = this.pos;
7857
+ this.moveTo(x + dx, y + dy);
7858
+ }
7859
+ moveX(x) {
7860
+ this.moveTo(x, this.pos.y);
7861
+ }
7862
+ moveY(y) {
7863
+ this.moveTo(this.pos.x, y);
7864
+ }
7695
7865
  moveEnd() {
7696
7866
  if (this.valid)
7697
7867
  return;
@@ -7699,14 +7869,26 @@ class InteractiveItemComponent {
7699
7869
  this.valid = true;
7700
7870
  this.calcShapes();
7701
7871
  }
7872
+ restrictPosition(x, y) {
7873
+ return {
7874
+ x: clamp(x, this.canvas.xRange),
7875
+ y: this.canvas.infinite
7876
+ ? overflow(y, this.canvas.yRange)
7877
+ : clamp(y, this.canvas.yRange)
7878
+ };
7879
+ }
7702
7880
  isValidByParams() {
7703
- return true;
7881
+ return !this.shapes.some(shape => {
7882
+ return this.canvas.excludedAreas.some(ex => {
7883
+ return shape.intersects(ex);
7884
+ });
7885
+ });
7704
7886
  }
7705
7887
  isValidByDistance(other) {
7706
7888
  const minPixels = this.distToPixels(this.getMinDistance(other));
7707
7889
  return !this.shapes.some(shape => {
7708
7890
  return other.shapes.some(os => {
7709
- return os.minDistance(shape) <= minPixels;
7891
+ return shape.distance(os) <= minPixels;
7710
7892
  });
7711
7893
  });
7712
7894
  }
@@ -7760,19 +7942,19 @@ class InteractiveCanvasComponent {
7760
7942
  set hoveredItem(item) {
7761
7943
  this.hoveredIndex = !item ? -1 : this.items.indexOf(item);
7762
7944
  }
7763
- constructor(renderer, universal, element, rootElement) {
7945
+ constructor(renderer, universal) {
7764
7946
  this.renderer = renderer;
7765
7947
  this.universal = universal;
7766
- this.element = element;
7767
- this.rootElement = rootElement;
7948
+ this.infinite = false;
7949
+ this.resizeMode = "fit";
7950
+ this.params = {};
7768
7951
  this.debug = false;
7769
7952
  this.horizontal = false;
7770
7953
  this.selectedIndex = 0;
7771
- this.resizeMode = "fit";
7772
7954
  this.realWidth = 100;
7773
7955
  this.realHeight = 100;
7774
7956
  this.panOffset = 0;
7775
- this.params = {};
7957
+ this.renderCtx = {};
7776
7958
  this.beforeItems = [];
7777
7959
  this.afterItems = [];
7778
7960
  this.selectedIndexChange = new EventEmitter();
@@ -7784,16 +7966,21 @@ class InteractiveCanvasComponent {
7784
7966
  this.$items = new BehaviorSubject([]);
7785
7967
  this.tempCanvas = this.universal.isServer ? null : document.createElement("canvas");
7786
7968
  this.shouldDraw = !this.universal.isServer;
7787
- this.rotation = 0;
7969
+ this.hoveredIndex = null;
7970
+ this.xRange = [0, 1];
7971
+ this.yRange = [0, 1];
7972
+ this.ratio = 1;
7973
+ this.styles = null;
7974
+ this.ctx = null;
7788
7975
  this.canvasWidth = 0;
7789
7976
  this.canvasHeight = 0;
7790
- this.hoveredIndex = null;
7977
+ this.rotation = 0;
7978
+ this.basePan = 0;
7979
+ this.cycles = [0];
7980
+ this.excludedAreas = [];
7791
7981
  this.touched = false;
7792
- this.deltaX = 0;
7793
- this.deltaY = 0;
7794
- this.ctrInit();
7795
- }
7796
- ctrInit() {
7982
+ this.panStartRotation = 0;
7983
+ this.panStartPos = Point.Zero;
7797
7984
  }
7798
7985
  ngOnInit() {
7799
7986
  this.redraw();
@@ -7807,6 +7994,8 @@ class InteractiveCanvasComponent {
7807
7994
  this.renderCtx = this.renderCtx || {};
7808
7995
  this.beforeItems = this.beforeItems || [];
7809
7996
  this.afterItems = this.afterItems || [];
7997
+ this.xRange = normalizeRange(this.params.xRange || [0, this.realWidth]);
7998
+ this.yRange = normalizeRange(this.params.yRange || [0, this.realHeight]);
7810
7999
  this.resize();
7811
8000
  }
7812
8001
  ngAfterViewInit() {
@@ -7872,20 +8061,21 @@ class InteractiveCanvasComponent {
7872
8061
  this.updateCursor();
7873
8062
  }
7874
8063
  onMouseLeave() {
8064
+ if (this.touched)
8065
+ return;
7875
8066
  this.hoveredIndex = null;
7876
8067
  this.updateCursor();
7877
8068
  }
7878
8069
  onPanStart() {
7879
- this.deltaX = 0;
7880
- this.deltaY = 0;
8070
+ this.panStartRotation = this.rotation;
8071
+ this.panStartPos = this.lockedItem?.position || Point.Zero;
7881
8072
  }
7882
8073
  onPanMove($event) {
7883
8074
  const item = this.lockedItem;
7884
- const deltaX = ($event.deltaX - this.deltaX) / this.ratio;
7885
- const deltaY = ($event.deltaY - this.deltaY) / this.ratio;
8075
+ const deltaX = $event.deltaX / this.ratio;
8076
+ const deltaY = $event.deltaY / this.ratio;
7886
8077
  const data = {
7887
8078
  canvas: this,
7888
- pointers: $event.pointers,
7889
8079
  item,
7890
8080
  deltaX,
7891
8081
  deltaY
@@ -7895,22 +8085,19 @@ class InteractiveCanvasComponent {
7895
8085
  data.deltaY = +deltaX;
7896
8086
  }
7897
8087
  if (item) {
7898
- item.moveBy(data.deltaX, data.deltaY);
8088
+ item.moveTo(this.panStartPos.x + data.deltaX, this.panStartPos.y + data.deltaY);
7899
8089
  this.onItemPan.emit(data);
7900
8090
  }
7901
- else if (this.resizeMode == "fill") {
7902
- this.rotation += (this.horizontal ? deltaX : deltaY) / this.realHeight * 360;
8091
+ else if (this.infinite) {
8092
+ this.rotation = this.panStartRotation + (this.horizontal ? deltaX : deltaY) / this.realHeight * 360;
7903
8093
  this.fixRotation();
7904
8094
  this.onPan.emit(data);
7905
8095
  }
7906
- this.deltaX = $event.deltaX;
7907
- this.deltaY = $event.deltaY;
7908
8096
  }
7909
8097
  onPanEnd() {
7910
8098
  const item = this.lockedItem;
7911
8099
  const data = {
7912
8100
  canvas: this,
7913
- pointers: [],
7914
8101
  deltaX: 0,
7915
8102
  deltaY: 0,
7916
8103
  item
@@ -7927,11 +8114,20 @@ class InteractiveCanvasComponent {
7927
8114
  fixRotation() {
7928
8115
  if (this.fullHeight <= 0)
7929
8116
  return;
7930
- this.rotation = ((this.rotation + 180) % 360 + 360) % 360 - 180;
7931
- this.rotation = Math.round(this.rotation * 100) / 100;
7932
- this.basePan = (this.rotation / 360 - 1) * this.fullHeight + this.canvasHeight * this.panOffset;
7933
- this.cycles = this.resizeMode == "fit"
7934
- ? [0] : [this.basePan - this.fullHeight, this.basePan, this.basePan + this.fullHeight];
8117
+ this.rotation = overflow(Math.round(this.rotation * 100) / 100, -180, 180);
8118
+ this.basePan = (this.rotation / 360 - 1) * this.fullHeight
8119
+ + this.canvasHeight * this.panOffset;
8120
+ this.cycles = this.infinite
8121
+ ? [this.basePan - this.fullHeight, this.basePan, this.basePan + this.fullHeight] : [0];
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;
8127
+ return this.cycles.map(cycle => {
8128
+ return new Rect(x, y + cycle, width, height);
8129
+ });
8130
+ });
7935
8131
  this.items.forEach(item => {
7936
8132
  item.calcShapes();
7937
8133
  });
@@ -7957,19 +8153,25 @@ class InteractiveCanvasComponent {
7957
8153
  return;
7958
8154
  item.active = !item.active;
7959
8155
  }
8156
+ this.hoveredIndex = selected;
7960
8157
  }
7961
- getIndexUnderPointer(pointer) {
7962
- if (!pointer || !this.canvasElem || !this.items)
8158
+ toCanvasPoint(pointer) {
8159
+ if (!pointer || !this.canvas)
7963
8160
  return null;
7964
- const canvasRect = this.canvasElem.nativeElement.getBoundingClientRect();
7965
- const point = this.horizontal
8161
+ const canvasRect = this.canvas?.getBoundingClientRect();
8162
+ return this.horizontal
7966
8163
  ? new Point(canvasRect.bottom - pointer.clientY, pointer.clientX - canvasRect.left)
7967
8164
  : new Point(pointer.clientX - canvasRect.left, pointer.clientY - canvasRect.top);
8165
+ }
8166
+ getIndexUnderPointer(pointer) {
8167
+ const point = this.toCanvasPoint(pointer);
8168
+ if (!point || !this.items)
8169
+ return -1;
7968
8170
  const length = this.items.length;
7969
8171
  for (let ix = 0; ix < length; ix++) {
7970
8172
  const item = this.items[ix];
7971
8173
  if (item?.hit(point)) {
7972
- return item.disabled ? null : ix;
8174
+ return item.disabled ? -1 : ix;
7973
8175
  }
7974
8176
  }
7975
8177
  return -1;
@@ -8005,17 +8207,15 @@ class InteractiveCanvasComponent {
8005
8207
  }
8006
8208
  async drawItems() {
8007
8209
  const ctx = this.ctx;
8210
+ const lockedItem = this.lockedItem;
8008
8211
  for (const item of this.items) {
8009
- for (const shape of item.shapes) {
8010
- ctx.save();
8011
- ctx.translate(shape.x, shape.y);
8012
- ctx.lineWidth = 1;
8013
- ctx.strokeStyle = "black";
8014
- ctx.fillStyle = "white";
8015
- await item.draw(ctx);
8016
- ctx.restore();
8212
+ if (item !== lockedItem) {
8213
+ await this.drawItem(ctx, item);
8017
8214
  }
8018
8215
  }
8216
+ if (lockedItem) {
8217
+ await this.drawItem(ctx, lockedItem);
8218
+ }
8019
8219
  if (!this.debug)
8020
8220
  return;
8021
8221
  ctx.lineWidth = 2;
@@ -8038,6 +8238,17 @@ class InteractiveCanvasComponent {
8038
8238
  }
8039
8239
  }
8040
8240
  }
8241
+ async drawItem(ctx, item) {
8242
+ for (const shape of item.shapes) {
8243
+ ctx.save();
8244
+ ctx.translate(shape.x, shape.y);
8245
+ ctx.lineWidth = 1;
8246
+ ctx.strokeStyle = "black";
8247
+ ctx.fillStyle = "white";
8248
+ await item.draw(ctx);
8249
+ ctx.restore();
8250
+ }
8251
+ }
8041
8252
  async draw() {
8042
8253
  const ctx = this.ctx;
8043
8254
  const canvas = ctx.canvas;
@@ -8063,30 +8274,29 @@ class InteractiveCanvasComponent {
8063
8274
  }
8064
8275
  ctx.restore();
8065
8276
  }
8066
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: InteractiveCanvasComponent, deps: [{ token: i0.Renderer2 }, { token: UniversalService }, { token: i0.ElementRef }, { token: ROOT_ELEMENT }], target: i0.ɵɵFactoryTarget.Component }); }
8067
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: InteractiveCanvasComponent, isStandalone: false, selector: "interactive-canvas", inputs: { debug: "debug", horizontal: "horizontal", selectedIndex: "selectedIndex", resizeMode: "resizeMode", realWidth: "realWidth", realHeight: "realHeight", panOffset: "panOffset", params: "params", renderCtx: "renderCtx", beforeItems: "beforeItems", afterItems: "afterItems" }, outputs: { selectedIndexChange: "selectedIndexChange", onRotate: "onRotate", onItemPan: "onItemPan", onItemPanned: "onItemPanned", onPan: "onPan", onPanned: "onPanned" }, host: { listeners: { "window:touchend": "onTouchEnd($event)", "window:mouseup": "onMouseUp($event)" } }, queries: [{ propertyName: "itemList", predicate: InteractiveItemComponent }], viewQueries: [{ propertyName: "containerElem", first: true, predicate: ["containerElem"], descendants: true, static: true }, { propertyName: "canvasElem", first: true, predicate: ["canvasElem"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #containerElem\n [ngClass]=\"['interactive-canvas-container', horizontal ? 'horizontal' : 'vertical']\"\n (resize)=\"resize()\"\n (touchstart)=\"onTouchStart($event)\"\n (mousedown)=\"onMouseDown($event)\"\n (mousemove)=\"onMouseMove($event)\"\n (mouseleave)=\"onMouseLeave()\"\n (panend)=\"onPanEnd()\"\n (panmove)=\"onPanMove($event)\"\n (panstart)=\"onPanStart()\">\n <canvas #canvasElem class=\"interactive-canvas-element\"></canvas>\n</div>\n", styles: [".interactive-canvas-container{width:100%;height:100%;position:relative;display:flex;align-items:center;justify-content:center}.interactive-canvas-container .interactive-canvas-element{position:absolute;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
8277
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: InteractiveCanvasComponent, deps: [{ token: i0.Renderer2 }, { token: UniversalService }], target: i0.ɵɵFactoryTarget.Component }); }
8278
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.14", type: InteractiveCanvasComponent, isStandalone: false, selector: "interactive-canvas", inputs: { infinite: "infinite", resizeMode: "resizeMode", params: "params", realWidth: "realWidth", realHeight: "realHeight", debug: "debug", horizontal: "horizontal", selectedIndex: "selectedIndex", panOffset: "panOffset", renderCtx: "renderCtx", beforeItems: "beforeItems", afterItems: "afterItems" }, outputs: { selectedIndexChange: "selectedIndexChange", onRotate: "onRotate", onItemPan: "onItemPan", onItemPanned: "onItemPanned", onPan: "onPan", onPanned: "onPanned" }, host: { listeners: { "window:touchend": "onTouchEnd($event)", "window:mouseup": "onMouseUp($event)" } }, queries: [{ propertyName: "itemList", predicate: InteractiveItemComponent }], viewQueries: [{ propertyName: "containerElem", first: true, predicate: ["containerElem"], descendants: true, static: true }, { propertyName: "canvasElem", first: true, predicate: ["canvasElem"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<div #containerElem\n [ngClass]=\"['interactive-canvas-container', horizontal ? 'horizontal' : 'vertical']\"\n (resize)=\"resize()\"\n (touchstart)=\"onTouchStart($event)\"\n (mousedown)=\"onMouseDown($event)\"\n (mousemove)=\"onMouseMove($event)\"\n (mouseleave)=\"onMouseLeave()\"\n (panend)=\"onPanEnd()\"\n (panmove)=\"onPanMove($event)\"\n (panstart)=\"onPanStart()\">\n <canvas #canvasElem class=\"interactive-canvas-element\"></canvas>\n</div>\n", styles: [".interactive-canvas-container{width:100%;height:100%;position:relative;display:flex;align-items:center;justify-content:center}.interactive-canvas-container .interactive-canvas-element{position:absolute;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: i1$3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
8068
8279
  }
8069
8280
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: InteractiveCanvasComponent, decorators: [{
8070
8281
  type: Component,
8071
8282
  args: [{ standalone: false, selector: "interactive-canvas", template: "<div #containerElem\n [ngClass]=\"['interactive-canvas-container', horizontal ? 'horizontal' : 'vertical']\"\n (resize)=\"resize()\"\n (touchstart)=\"onTouchStart($event)\"\n (mousedown)=\"onMouseDown($event)\"\n (mousemove)=\"onMouseMove($event)\"\n (mouseleave)=\"onMouseLeave()\"\n (panend)=\"onPanEnd()\"\n (panmove)=\"onPanMove($event)\"\n (panstart)=\"onPanStart()\">\n <canvas #canvasElem class=\"interactive-canvas-element\"></canvas>\n</div>\n", styles: [".interactive-canvas-container{width:100%;height:100%;position:relative;display:flex;align-items:center;justify-content:center}.interactive-canvas-container .interactive-canvas-element{position:absolute;pointer-events:none}\n"] }]
8072
- }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: UniversalService }, { type: i0.ElementRef }, { type: HTMLElement, decorators: [{
8073
- type: Inject,
8074
- args: [ROOT_ELEMENT]
8075
- }] }], propDecorators: { debug: [{
8076
- type: Input
8077
- }], horizontal: [{
8078
- type: Input
8079
- }], selectedIndex: [{
8283
+ }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: UniversalService }], propDecorators: { infinite: [{
8080
8284
  type: Input
8081
8285
  }], resizeMode: [{
8082
8286
  type: Input
8287
+ }], params: [{
8288
+ type: Input
8083
8289
  }], realWidth: [{
8084
8290
  type: Input
8085
8291
  }], realHeight: [{
8086
8292
  type: Input
8087
- }], panOffset: [{
8293
+ }], debug: [{
8088
8294
  type: Input
8089
- }], params: [{
8295
+ }], horizontal: [{
8296
+ type: Input
8297
+ }], selectedIndex: [{
8298
+ type: Input
8299
+ }], panOffset: [{
8090
8300
  type: Input
8091
8301
  }], renderCtx: [{
8092
8302
  type: Input
@@ -8913,5 +9123,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
8913
9123
  * Generated bundle index. Do not edit.
8914
9124
  */
8915
9125
 
8916
- export { API_SERVICE, APP_BASE_URL, AUTH_SERVICE, AclService, AjaxRequestHandler, ApiService, ArrayUtils, AsyncMethodBase, AsyncMethodDirective, AsyncMethodTargetDirective, AuthGuard, BASE_CONFIG, BUTTON_TYPE, BackgroundDirective, BaseDialogService, BaseHttpClient, BaseHttpService, BaseToasterService, BtnComponent, BtnDefaultComponent, CONFIG_SERVICE, CacheService, CanvasColor, CanvasUtils, ChipsComponent, ChunkPipe, Circle, CloseBtnComponent, ComponentLoaderDirective, ComponentLoaderService, ConfigService, DIALOG_SERVICE, DateUtils, DragDropEventPlugin, DropListComponent, DropdownBoxComponent, DropdownContentDirective, DropdownDirective, DropdownToggleDirective, DynamicTableComponent, DynamicTableTemplateDirective, ERROR_HANDLER, EXPRESS_REQUEST, EntriesPipe, ErrorHandlerService, EventsService, ExtraItemPropertiesPipe, FactoryDependencies, FakeModuleComponent, FileSystemEntry, FileUtils, FilterPipe, FindPipe, ForbiddenZone, FormatNumberPipe, FormatterService, GenericValue, GetOffsetPipe, GetTypePipe, GetValuePipe, GlobalTemplateDirective, GlobalTemplatePipe, GlobalTemplateService, GroupByPipe, ICON_MAP, ICON_SERVICE, ICON_TYPE, IConfiguration, IconComponent, IconDefaultComponent, IconDirective, IconService, IncludesPipe, Initializer, InteractiveCanvasComponent, InteractiveCircleComponent, InteractiveItemComponent, InteractiveRectComponent, IsTypePipe, JSONfn, JoinPipe, KeysPipe, LANGUAGE_SERVICE, LanguageService, LoaderUtils, LocalHttpService, MapPipe, MathUtils, MaxPipe, MinPipe, NgxTemplateOutletDirective, NgxUtilsModule, OPTIONS_TOKEN, ObjectType, ObjectUtils, ObservableUtils, OpenApiService, Oval, PROMISE_SERVICE, PaginationDirective, PaginationItemContext, PaginationItemDirective, PaginationMenuComponent, Point, PopPipe, PromiseService, RESIZE_DELAY, RESIZE_STRATEGY, ROOT_ELEMENT, Rect, ReducePipe, ReflectUtils, RemapPipe, ReplacePipe, ResizeEventPlugin, ResourceIfContext, ResourceIfDirective, ReversePipe, RoundPipe, SCRIPT_PARAMS, STATIC_SCHEMAS, SafeHtmlPipe, ScrollEventPlugin, SetUtils, ShiftPipe, SocketClient, SocketService, SplitPipe, StateService, StaticAuthService, StaticLanguageService, StickyClassDirective, StickyDirective, StorageMode, StorageService, StringUtils, TOASTER_SERVICE, TabsComponent, TabsItemDirective, TabsTemplateDirective, TimerUtils, TranslatePipe, TranslatedUrlSerializer, UniqueUtils, UniversalService, UnorderedListComponent, UnorderedListItemDirective, UnorderedListTemplateDirective, UploadComponent, ValuedPromise, ValuesPipe, cachedFactory, cancelablePromise, checkTransitions, computedPrevious, createTypedProvider, cssStyles, cssVariables, dotProduct, drawOval, drawRect, getComponentDef, getCssVariables, getRoot, hashCode, impatientPromise, isBrowser, isPoint, parseSelector, perpendicular, provideEntryComponents, provideWithOptions, ptAdd, ptDistance, ptLength, ptMultiply, ptSubtract, rotateDeg, rotateRad, selectorMatchesList, switchClass, toDegrees, toRadians };
9126
+ export { API_SERVICE, APP_BASE_URL, AUTH_SERVICE, AclService, AjaxRequestHandler, ApiService, ArrayUtils, AsyncMethodBase, AsyncMethodDirective, AsyncMethodTargetDirective, AuthGuard, BASE_CONFIG, BUTTON_TYPE, BackgroundDirective, BaseDialogService, BaseHttpClient, BaseHttpService, BaseToasterService, BtnComponent, BtnDefaultComponent, CONFIG_SERVICE, CacheService, CanvasColor, CanvasUtils, ChipsComponent, ChunkPipe, Circle, CloseBtnComponent, ComponentLoaderDirective, ComponentLoaderService, ConfigService, DIALOG_SERVICE, DateUtils, DragDropEventPlugin, DropListComponent, DropdownBoxComponent, DropdownContentDirective, DropdownDirective, DropdownToggleDirective, DynamicTableComponent, DynamicTableTemplateDirective, EPSILON, ERROR_HANDLER, EXPRESS_REQUEST, EntriesPipe, ErrorHandlerService, EventsService, ExtraItemPropertiesPipe, FactoryDependencies, FakeModuleComponent, FileSystemEntry, FileUtils, FilterPipe, FindPipe, ForbiddenZone, FormatNumberPipe, FormatterService, GenericValue, GetOffsetPipe, GetTypePipe, GetValuePipe, GlobalTemplateDirective, GlobalTemplatePipe, GlobalTemplateService, GroupByPipe, ICON_MAP, ICON_SERVICE, ICON_TYPE, IConfiguration, IconComponent, IconDefaultComponent, IconDirective, IconService, IncludesPipe, Initializer, InteractiveCanvasComponent, InteractiveCircleComponent, InteractiveItemComponent, InteractiveRectComponent, IsTypePipe, JSONfn, JoinPipe, KeysPipe, LANGUAGE_SERVICE, LanguageService, LoaderUtils, LocalHttpService, MapPipe, MathUtils, MaxPipe, MinPipe, NgxTemplateOutletDirective, NgxUtilsModule, OPTIONS_TOKEN, ObjectType, ObjectUtils, ObservableUtils, OpenApiService, Oval, PROMISE_SERVICE, PaginationDirective, PaginationItemContext, PaginationItemDirective, PaginationMenuComponent, Point, PopPipe, PromiseService, RESIZE_DELAY, RESIZE_STRATEGY, ROOT_ELEMENT, Rect, ReducePipe, ReflectUtils, RemapPipe, ReplacePipe, ResizeEventPlugin, ResourceIfContext, ResourceIfDirective, ReversePipe, RoundPipe, SCRIPT_PARAMS, STATIC_SCHEMAS, SafeHtmlPipe, ScrollEventPlugin, SetUtils, ShiftPipe, SocketClient, SocketService, SplitPipe, StateService, StaticAuthService, StaticLanguageService, StickyClassDirective, StickyDirective, StorageMode, StorageService, StringUtils, TOASTER_SERVICE, TabsComponent, TabsItemDirective, TabsTemplateDirective, TimerUtils, TranslatePipe, TranslatedUrlSerializer, UniqueUtils, UniversalService, UnorderedListComponent, UnorderedListItemDirective, UnorderedListTemplateDirective, UploadComponent, ValuedPromise, ValuesPipe, addPts, cachedFactory, cancelablePromise, checkTransitions, clamp, computedPrevious, createTypedProvider, cssStyles, cssVariables, distance, distanceSq, dividePts, dotProduct, drawOval, drawRect, ensurePoint, getComponentDef, getCssVariables, getRoot, gjkDistance, gjkIntersection, hashCode, impatientPromise, isBrowser, isPoint, lengthOfPt, lerpPts, multiplyPts, negatePt, normalizePt, normalizeRange, overflow, parseSelector, perpendicular, provideEntryComponents, provideWithOptions, rotateDeg, rotateRad, selectorMatchesList, subPts, switchClass, toDegrees, toRadians, tripleProduct };
8917
9127
  //# sourceMappingURL=stemy-ngx-utils.mjs.map