@stemy/ngx-utils 19.7.1 → 19.7.2

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,261 @@ 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
+ let intersection = gjkIntersection(A, B);
1899
+ if (intersection.hit)
1900
+ return { distance: 0 };
1901
+ const ca = A.center;
1902
+ const cb = B.center;
1903
+ let s = 0;
1904
+ let e = 1;
1905
+ let center = ca;
1906
+ let iters = 0;
1907
+ while (e - s > EPSILON) {
1908
+ iters++;
1909
+ const t = (e + s) / 2;
1910
+ const a = A.move(lerpPts(ca, cb, t));
1911
+ const test = gjkIntersection(a, B);
1912
+ center = a.center;
1913
+ if (test.hit) {
1914
+ intersection = test;
1915
+ e = t;
1916
+ if (iters >= MAX_ITERS)
1917
+ break;
1918
+ }
1919
+ else {
1920
+ s = t;
1921
+ }
1922
+ }
1923
+ const result = distance(ca, center);
1924
+ return {
1925
+ distance: result,
1926
+ pa: result > 0 ? addPts(intersection.pa, subPts(ca, center)) : null,
1927
+ pb: result > 0 ? intersection.pb : null
1928
+ };
1929
+ }
1930
+ // =========================
1931
+ // Boolean GJK (robust)
1932
+ // =========================
1933
+ function gjkIntersection(A, B) {
1934
+ const MAX = 64, EPS = 1e-12;
1935
+ const sup = (dir) => {
1936
+ const a = ensurePoint(A.support(dir), A.center);
1937
+ const b = ensurePoint(B.support(negatePt(dir)), B.center);
1938
+ return { p: subPts(a, b), a, b };
1939
+ };
1940
+ // initial direction: center-to-center; fall back to x-axis
1941
+ let d = subPts(B.center, A.center);
1855
1942
  if (Math.abs(d.x) < EPS && Math.abs(d.y) < EPS)
1856
1943
  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 };
1944
+ const simplex = [sup(d)];
1945
+ d = { x: -simplex[0].p.x, y: -simplex[0].p.y };
1946
+ for (let i = 0; i < MAX; i++) {
1947
+ // If direction collapses, steer toward origin from last point
1948
+ const dLen = Math.hypot(d.x, d.y);
1949
+ if (dLen <= EPS) {
1950
+ const last = simplex[simplex.length - 1];
1951
+ const AO = { x: -last.p.x, y: -last.p.y };
1952
+ const aoLen = Math.hypot(AO.x, AO.y);
1953
+ d = (aoLen > EPS) ? AO : { x: 1, y: 0 };
1954
+ }
1955
+ const a = sup(d);
1956
+ const s = a.p.x * d.x + a.p.y * d.y;
1957
+ if (s < -1e-12)
1958
+ return { hit: false }; // definite separation
1959
+ if (Math.abs(s) <= 1e-12) { // tangential contact: use normal ±d
1960
+ const L = Math.hypot(d.x, d.y) || 1;
1961
+ const n = { x: d.x / L, y: d.y / L };
1962
+ const pa = ensurePoint(A.support(n), A.center);
1963
+ const pb = ensurePoint(B.support(negatePt(n)), B.center);
1964
+ const point = { x: (pa.x + pb.x) / 2, y: (pa.y + pb.y) / 2 };
1965
+ return { hit: true, pa, pb, point };
1966
+ }
1967
+ simplex.push(a);
1968
+ {
1969
+ const info = doSimplexBoolean(simplex, d);
1970
+ if (info.hit)
1971
+ return info;
1972
+ }
1973
+ }
1974
+ // Max iterations without resolution → disjoint
1975
+ return { hit: false };
1976
+ }
1977
+ function doSimplexBoolean(simplex, d) {
1978
+ const last = simplex[simplex.length - 1];
1979
+ const AO = { x: -last.p.x, y: -last.p.y };
1980
+ if (simplex.length === 2) {
1981
+ const B = simplex[0];
1982
+ const AB = { x: B.p.x - last.p.x, y: B.p.y - last.p.y };
1983
+ // Perpendicular to AB toward origin
1984
+ const abPerp = tripleProduct(AB, AO, AB);
1985
+ const perpLen2 = abPerp.x * abPerp.x + abPerp.y * abPerp.y;
1986
+ if (perpLen2 < 1e-24) {
1987
+ // Colinear: project origin onto segment AB
1988
+ const ab2 = AB.x * AB.x + AB.y * AB.y;
1989
+ if (ab2 > 0) {
1990
+ const t = ((AO.x * AB.x + AO.y * AB.y) / ab2);
1991
+ if (t >= 0 && t <= 1) {
1992
+ // Contact at segment
1993
+ const pa = { x: last.a.x + t * (B.a.x - last.a.x), y: last.a.y + t * (B.a.y - last.a.y) };
1994
+ const pb = { x: last.b.x + t * (B.b.x - last.b.x), y: last.b.y + t * (B.b.y - last.b.y) };
1995
+ const point = { x: (pa.x + pb.x) / 2, y: (pa.y + pb.y) / 2 };
1996
+ return { hit: true, pa, pb, point };
1997
+ }
1998
+ }
1999
+ // Otherwise, move toward origin from A, keep only last point to progress
2000
+ d.x = -AO.x;
2001
+ d.y = -AO.y;
2002
+ simplex.splice(0, simplex.length - 1);
2003
+ return { hit: false };
2004
+ }
2005
+ d.x = abPerp.x;
2006
+ d.y = abPerp.y;
2007
+ return { hit: false };
2008
+ }
2009
+ // Triangle case: [C, B, A] with A = last
2010
+ const A = last, B = simplex[simplex.length - 2], C = simplex[simplex.length - 3];
2011
+ const AB = { x: B.p.x - A.p.x, y: B.p.y - A.p.y };
2012
+ const AC = { x: C.p.x - A.p.x, y: C.p.y - A.p.y };
2013
+ const ABperp = tripleProduct(AC, AB, AB);
2014
+ const ACperp = tripleProduct(AB, AC, AC);
2015
+ // If origin is outside AB region
2016
+ if (ABperp.x * AO.x + ABperp.y * AO.y > 0) {
2017
+ simplex.splice(simplex.length - 3, 1);
2018
+ d.x = ABperp.x;
2019
+ d.y = ABperp.y;
2020
+ return { hit: false };
2021
+ }
2022
+ // If origin is outside AC region
2023
+ if (ACperp.x * AO.x + ACperp.y * AO.y > 0) {
2024
+ simplex.splice(simplex.length - 2, 1);
2025
+ d.x = ACperp.x;
2026
+ d.y = ACperp.y;
2027
+ return { hit: false };
2028
+ }
2029
+ // Otherwise the origin is inside the triangle → overlap
2030
+ // Compute barycentric weights of origin w.r.t triangle (A,B,C)
2031
+ const v0 = AB; // B-A
2032
+ const v1 = AC; // C-A
2033
+ const b = { x: -A.p.x, y: -A.p.y };
2034
+ const det = v0.x * v1.y - v0.y * v1.x;
2035
+ let uA, uB, uC;
2036
+ if (Math.abs(det) > 1e-24) {
2037
+ const alpha = (b.x * v1.y - v1.x * b.y) / det; // weight for v0 (B)
2038
+ const beta = (v0.x * b.y - b.x * v0.y) / det; // weight for v1 (C)
2039
+ uB = alpha;
2040
+ uC = beta;
2041
+ uA = 1 - alpha - beta;
2042
+ }
2043
+ else {
2044
+ // Fallback: equal weights
2045
+ uA = uB = uC = 1 / 3;
2046
+ }
2047
+ const pa = {
2048
+ x: uA * A.a.x + uB * B.a.x + uC * C.a.x,
2049
+ y: uA * A.a.y + uB * B.a.y + uC * C.a.y
2050
+ };
2051
+ const pb = {
2052
+ x: uA * A.b.x + uB * B.b.x + uC * C.b.x,
2053
+ y: uA * A.b.y + uB * B.b.y + uC * C.b.y
1861
2054
  };
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 };
2055
+ const point = { x: (pa.x + pb.x) / 2, y: (pa.y + pb.y) / 2 };
2056
+ return { hit: true, pa, pb, point };
1892
2057
  }
1893
2058
 
1894
2059
  class Shape {
@@ -1904,17 +2069,23 @@ class Shape {
1904
2069
  constructor(x, y) {
1905
2070
  this.pt = { x, y };
1906
2071
  }
1907
- distance(p) {
1908
- return ptDistance(this.center, p);
2072
+ intersection(shape) {
2073
+ return gjkIntersection(this, shape);
2074
+ }
2075
+ intersects(shape) {
2076
+ return this.intersection(shape).hit;
1909
2077
  }
1910
2078
  minDistance(shape) {
1911
- return gjkDistance(this, shape).distance;
2079
+ return gjkDistance(this, shape);
2080
+ }
2081
+ distance(shape) {
2082
+ return this.minDistance(shape).distance;
1912
2083
  }
1913
2084
  }
1914
2085
  class Point extends Shape {
1915
2086
  static { this.Zero = new Point(0, 0); }
1916
2087
  get length() {
1917
- return ptLength(this);
2088
+ return lengthOfPt(this);
1918
2089
  }
1919
2090
  get perpendicular() {
1920
2091
  return new Point(perpendicular(this));
@@ -1925,32 +2096,35 @@ class Point extends Shape {
1925
2096
  this.pt = isPoint(xOrP) ? xOrP : { x: isNaN(x) ? 0 : xOrP, y };
1926
2097
  }
1927
2098
  support() {
1928
- return this.pt;
2099
+ return this.center;
2100
+ }
2101
+ move(pos) {
2102
+ return new Point(pos);
1929
2103
  }
1930
2104
  add(p) {
1931
- return new Point(ptAdd(this, p));
2105
+ return new Point(addPts(this, p));
2106
+ }
2107
+ subtract(p) {
2108
+ return new Point(subPts(this, p));
1932
2109
  }
1933
- sub(p) {
1934
- return new Point(ptSubtract(this, p));
2110
+ multiply(p) {
2111
+ return new Point(multiplyPts(this, p));
1935
2112
  }
1936
- mul(p) {
1937
- return new Point(ptMultiply(this, p));
2113
+ divide(p) {
2114
+ return new Point(multiplyPts(this, p));
1938
2115
  }
1939
2116
  dot(p) {
1940
2117
  return new Point(dotProduct(this, p));
1941
2118
  }
1942
- distance(p) {
1943
- return ptDistance(this, p);
1944
- }
1945
2119
  lerp(p, ratio) {
1946
- const diff = p.sub(this);
1947
- return this.add(diff.mul(ratio));
2120
+ const diff = p.subtract(this);
2121
+ return this.add(diff.multiply(ratio));
1948
2122
  }
1949
2123
  perpendicularTo(p, length) {
1950
- const diff = p.perpendicular.sub(this.perpendicular);
2124
+ const diff = p.perpendicular.subtract(this.perpendicular);
1951
2125
  const ratio = length / diff.length;
1952
2126
  const center = this.lerp(p, .5);
1953
- return center.add(diff.mul(ratio));
2127
+ return center.add(diff.multiply(ratio));
1954
2128
  }
1955
2129
  circleWith(a, b) {
1956
2130
  const yDelta_a = b.y - a.y;
@@ -1965,8 +2139,8 @@ class Point extends Shape {
1965
2139
  return new Circle(center.x, center.y, center.distance(this));
1966
2140
  }
1967
2141
  tangents(c) {
1968
- const pd = ptSubtract(c.center, this);
1969
- const a = Math.asin(c.radius / ptLength(pd));
2142
+ const pd = subPts(c.center, this);
2143
+ const a = Math.asin(c.radius / lengthOfPt(pd));
1970
2144
  const b = Math.atan2(pd.y, pd.x);
1971
2145
  // Tangent points
1972
2146
  let t = b - a;
@@ -1976,7 +2150,7 @@ class Point extends Shape {
1976
2150
  return [t1, t2];
1977
2151
  }
1978
2152
  angle(p) {
1979
- const diff = p.sub(this);
2153
+ const diff = p.subtract(this);
1980
2154
  return Math.atan2(diff.y, diff.x) * 180 / Math.PI;
1981
2155
  }
1982
2156
  rotateAround(p, angle) {
@@ -1995,11 +2169,16 @@ class Rect extends Shape {
1995
2169
  }
1996
2170
  support(dir) {
1997
2171
  const ang = this.rotation ?? 0;
1998
- const dLocal = rotateDeg(dir, -ang);
2172
+ const dLocal = rotateDeg(ensurePoint(dir, { x: 1, y: 0 }), -ang);
1999
2173
  const hw = Math.max(0, this.width / 2), hh = Math.max(0, this.height / 2);
2174
+ if (hw === 0 && hh === 0)
2175
+ return ensurePoint(this.center);
2000
2176
  const lx = dLocal.x >= 0 ? hw : -hw;
2001
2177
  const ly = dLocal.y >= 0 ? hh : -hh;
2002
- return ptAdd(rotateDeg({ x: lx, y: ly }, ang), { x: this.x, y: this.y });
2178
+ return addPts(rotateDeg({ x: lx, y: ly }, ang), this.center);
2179
+ }
2180
+ move(pos) {
2181
+ return new Rect(pos.x, pos.y, this.width, this.height, this.rotation);
2003
2182
  }
2004
2183
  }
2005
2184
  class Oval extends Shape {
@@ -2011,15 +2190,16 @@ class Oval extends Shape {
2011
2190
  }
2012
2191
  support(dir) {
2013
2192
  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 });
2193
+ const d = rotateDeg(ensurePoint(dir, { x: 1, y: 0 }), -ang);
2194
+ const a = Math.max(0, this.width / 2), b = Math.max(0, this.height / 2);
2195
+ if (a === 0 && b === 0)
2196
+ return ensurePoint(this.center);
2197
+ const q = Math.hypot(a * d.x, b * d.y) || 1;
2198
+ const lx = (a * a * d.x) / q, ly = (b * b * d.y) / q;
2199
+ return addPts(rotateDeg({ x: lx, y: ly }, ang), this.center);
2200
+ }
2201
+ move(pos) {
2202
+ return new Oval(pos.x, pos.y, this.width, this.height, this.rotation);
2023
2203
  }
2024
2204
  }
2025
2205
  class Circle extends Oval {
@@ -2027,6 +2207,9 @@ class Circle extends Oval {
2027
2207
  super(x, y, radius * 2, radius * 2, rotation);
2028
2208
  this.radius = radius;
2029
2209
  }
2210
+ move(pos) {
2211
+ return new Circle(pos.x, pos.y, this.radius, this.rotation);
2212
+ }
2030
2213
  }
2031
2214
 
2032
2215
  class Initializer {
@@ -2158,49 +2341,6 @@ class LoaderUtils {
2158
2341
  }
2159
2342
  }
2160
2343
 
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
2344
  function isBrowser() {
2205
2345
  return typeof window !== "undefined";
2206
2346
  }
@@ -7669,29 +7809,31 @@ class InteractiveItemComponent {
7669
7809
  }
7670
7810
  hit(point) {
7671
7811
  for (const shape of this.shapes) {
7672
- if (shape.minDistance(point) <= 0)
7812
+ if (shape.intersects(point))
7673
7813
  return true;
7674
7814
  }
7675
7815
  return false;
7676
7816
  }
7677
- moveBy(dx, dy) {
7678
- if (this.direction === "none")
7817
+ moveTo(x, y) {
7818
+ if (!this.canvas || this.direction === "none")
7679
7819
  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
- }
7820
+ const target = this.restrictPosition(this.direction === "vertical" ? this.pos.x : x, this.direction === "horizontal" ? this.pos.y : y);
7821
+ this.pos = new Point(target);
7691
7822
  this.calcShapes();
7692
- this.valid = this.isValidByParams() && this.canvas.items.every(other => this === other || this.isValidByDistance(other));
7823
+ this.valid = this.isValidByParams() &&
7824
+ this.canvas.items.every(other => this === other || this.isValidByDistance(other));
7693
7825
  this.validPos = this.valid ? this.pos : this.validPos;
7694
7826
  }
7827
+ moveBy(dx, dy) {
7828
+ const { x, y } = this.pos;
7829
+ this.moveTo(x + dx, y + dy);
7830
+ }
7831
+ moveX(x) {
7832
+ this.moveTo(x, this.pos.y);
7833
+ }
7834
+ moveY(y) {
7835
+ this.moveTo(this.pos.x, y);
7836
+ }
7695
7837
  moveEnd() {
7696
7838
  if (this.valid)
7697
7839
  return;
@@ -7699,14 +7841,26 @@ class InteractiveItemComponent {
7699
7841
  this.valid = true;
7700
7842
  this.calcShapes();
7701
7843
  }
7844
+ restrictPosition(x, y) {
7845
+ return {
7846
+ x: clamp(x, this.canvas.xRange),
7847
+ y: this.canvas.infinite
7848
+ ? overflow(y, this.canvas.yRange)
7849
+ : clamp(y, this.canvas.yRange)
7850
+ };
7851
+ }
7702
7852
  isValidByParams() {
7703
- return true;
7853
+ return !this.shapes.some(shape => {
7854
+ return this.canvas.exclusions.some(ex => {
7855
+ return shape.distance(ex) < 1;
7856
+ });
7857
+ });
7704
7858
  }
7705
7859
  isValidByDistance(other) {
7706
7860
  const minPixels = this.distToPixels(this.getMinDistance(other));
7707
7861
  return !this.shapes.some(shape => {
7708
7862
  return other.shapes.some(os => {
7709
- return os.minDistance(shape) <= minPixels;
7863
+ return shape.distance(os) <= minPixels;
7710
7864
  });
7711
7865
  });
7712
7866
  }
@@ -7760,19 +7914,19 @@ class InteractiveCanvasComponent {
7760
7914
  set hoveredItem(item) {
7761
7915
  this.hoveredIndex = !item ? -1 : this.items.indexOf(item);
7762
7916
  }
7763
- constructor(renderer, universal, element, rootElement) {
7917
+ constructor(renderer, universal) {
7764
7918
  this.renderer = renderer;
7765
7919
  this.universal = universal;
7766
- this.element = element;
7767
- this.rootElement = rootElement;
7920
+ this.infinite = false;
7921
+ this.resizeMode = "fit";
7922
+ this.params = {};
7768
7923
  this.debug = false;
7769
7924
  this.horizontal = false;
7770
7925
  this.selectedIndex = 0;
7771
- this.resizeMode = "fit";
7772
7926
  this.realWidth = 100;
7773
7927
  this.realHeight = 100;
7774
7928
  this.panOffset = 0;
7775
- this.params = {};
7929
+ this.renderCtx = {};
7776
7930
  this.beforeItems = [];
7777
7931
  this.afterItems = [];
7778
7932
  this.selectedIndexChange = new EventEmitter();
@@ -7784,16 +7938,21 @@ class InteractiveCanvasComponent {
7784
7938
  this.$items = new BehaviorSubject([]);
7785
7939
  this.tempCanvas = this.universal.isServer ? null : document.createElement("canvas");
7786
7940
  this.shouldDraw = !this.universal.isServer;
7787
- this.rotation = 0;
7941
+ this.hoveredIndex = null;
7942
+ this.xRange = [0, 1];
7943
+ this.yRange = [0, 1];
7944
+ this.ratio = 1;
7945
+ this.styles = null;
7946
+ this.ctx = null;
7788
7947
  this.canvasWidth = 0;
7789
7948
  this.canvasHeight = 0;
7790
- this.hoveredIndex = null;
7949
+ this.rotation = 0;
7950
+ this.basePan = 0;
7951
+ this.cycles = [0];
7952
+ this.exclusions = [];
7791
7953
  this.touched = false;
7792
- this.deltaX = 0;
7793
- this.deltaY = 0;
7794
- this.ctrInit();
7795
- }
7796
- ctrInit() {
7954
+ this.panStartRotation = 0;
7955
+ this.panStartPos = Point.Zero;
7797
7956
  }
7798
7957
  ngOnInit() {
7799
7958
  this.redraw();
@@ -7807,6 +7966,8 @@ class InteractiveCanvasComponent {
7807
7966
  this.renderCtx = this.renderCtx || {};
7808
7967
  this.beforeItems = this.beforeItems || [];
7809
7968
  this.afterItems = this.afterItems || [];
7969
+ this.xRange = normalizeRange(this.params.xRange || [0, this.realWidth]);
7970
+ this.yRange = normalizeRange(this.params.yRange || [0, this.realHeight]);
7810
7971
  this.resize();
7811
7972
  }
7812
7973
  ngAfterViewInit() {
@@ -7872,20 +8033,21 @@ class InteractiveCanvasComponent {
7872
8033
  this.updateCursor();
7873
8034
  }
7874
8035
  onMouseLeave() {
8036
+ if (this.touched)
8037
+ return;
7875
8038
  this.hoveredIndex = null;
7876
8039
  this.updateCursor();
7877
8040
  }
7878
8041
  onPanStart() {
7879
- this.deltaX = 0;
7880
- this.deltaY = 0;
8042
+ this.panStartRotation = this.rotation;
8043
+ this.panStartPos = this.lockedItem?.position || Point.Zero;
7881
8044
  }
7882
8045
  onPanMove($event) {
7883
8046
  const item = this.lockedItem;
7884
- const deltaX = ($event.deltaX - this.deltaX) / this.ratio;
7885
- const deltaY = ($event.deltaY - this.deltaY) / this.ratio;
8047
+ const deltaX = $event.deltaX / this.ratio;
8048
+ const deltaY = $event.deltaY / this.ratio;
7886
8049
  const data = {
7887
8050
  canvas: this,
7888
- pointers: $event.pointers,
7889
8051
  item,
7890
8052
  deltaX,
7891
8053
  deltaY
@@ -7895,22 +8057,19 @@ class InteractiveCanvasComponent {
7895
8057
  data.deltaY = +deltaX;
7896
8058
  }
7897
8059
  if (item) {
7898
- item.moveBy(data.deltaX, data.deltaY);
8060
+ item.moveTo(this.panStartPos.x + data.deltaX, this.panStartPos.y + data.deltaY);
7899
8061
  this.onItemPan.emit(data);
7900
8062
  }
7901
- else if (this.resizeMode == "fill") {
7902
- this.rotation += (this.horizontal ? deltaX : deltaY) / this.realHeight * 360;
8063
+ else if (this.infinite) {
8064
+ this.rotation = this.panStartRotation + (this.horizontal ? deltaX : deltaY) / this.realHeight * 360;
7903
8065
  this.fixRotation();
7904
8066
  this.onPan.emit(data);
7905
8067
  }
7906
- this.deltaX = $event.deltaX;
7907
- this.deltaY = $event.deltaY;
7908
8068
  }
7909
8069
  onPanEnd() {
7910
8070
  const item = this.lockedItem;
7911
8071
  const data = {
7912
8072
  canvas: this,
7913
- pointers: [],
7914
8073
  deltaX: 0,
7915
8074
  deltaY: 0,
7916
8075
  item
@@ -7927,11 +8086,20 @@ class InteractiveCanvasComponent {
7927
8086
  fixRotation() {
7928
8087
  if (this.fullHeight <= 0)
7929
8088
  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];
8089
+ this.rotation = overflow(Math.round(this.rotation * 100) / 100, -180, 180);
8090
+ this.basePan = (this.rotation / 360 - 1) * this.fullHeight
8091
+ + this.canvasHeight * this.panOffset;
8092
+ this.cycles = this.infinite
8093
+ ? [this.basePan - this.fullHeight, this.basePan, this.basePan + this.fullHeight] : [0];
8094
+ this.exclusions = (this.params.exclusions || []).flatMap(coords => {
8095
+ const x = (coords[2] + coords[0]) * .5 * this.ratio;
8096
+ const y = (coords[3] + coords[1]) * .5 * this.ratio;
8097
+ const width = Math.abs(coords[2] - coords[0]) * this.ratio;
8098
+ const height = Math.abs(coords[3] - coords[1]) * this.ratio;
8099
+ return this.cycles.map(cycle => {
8100
+ return new Rect(x, y + cycle, width, height);
8101
+ });
8102
+ });
7935
8103
  this.items.forEach(item => {
7936
8104
  item.calcShapes();
7937
8105
  });
@@ -7957,19 +8125,25 @@ class InteractiveCanvasComponent {
7957
8125
  return;
7958
8126
  item.active = !item.active;
7959
8127
  }
8128
+ this.hoveredIndex = selected;
7960
8129
  }
7961
- getIndexUnderPointer(pointer) {
7962
- if (!pointer || !this.canvasElem || !this.items)
8130
+ toCanvasPoint(pointer) {
8131
+ if (!pointer || !this.canvas)
7963
8132
  return null;
7964
- const canvasRect = this.canvasElem.nativeElement.getBoundingClientRect();
7965
- const point = this.horizontal
8133
+ const canvasRect = this.canvas?.getBoundingClientRect();
8134
+ return this.horizontal
7966
8135
  ? new Point(canvasRect.bottom - pointer.clientY, pointer.clientX - canvasRect.left)
7967
8136
  : new Point(pointer.clientX - canvasRect.left, pointer.clientY - canvasRect.top);
8137
+ }
8138
+ getIndexUnderPointer(pointer) {
8139
+ const point = this.toCanvasPoint(pointer);
8140
+ if (!point || !this.items)
8141
+ return -1;
7968
8142
  const length = this.items.length;
7969
8143
  for (let ix = 0; ix < length; ix++) {
7970
8144
  const item = this.items[ix];
7971
8145
  if (item?.hit(point)) {
7972
- return item.disabled ? null : ix;
8146
+ return item.disabled ? -1 : ix;
7973
8147
  }
7974
8148
  }
7975
8149
  return -1;
@@ -8005,17 +8179,15 @@ class InteractiveCanvasComponent {
8005
8179
  }
8006
8180
  async drawItems() {
8007
8181
  const ctx = this.ctx;
8182
+ const lockedItem = this.lockedItem;
8008
8183
  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();
8184
+ if (item !== lockedItem) {
8185
+ await this.drawItem(ctx, item);
8017
8186
  }
8018
8187
  }
8188
+ if (lockedItem) {
8189
+ await this.drawItem(ctx, lockedItem);
8190
+ }
8019
8191
  if (!this.debug)
8020
8192
  return;
8021
8193
  ctx.lineWidth = 2;
@@ -8038,6 +8210,17 @@ class InteractiveCanvasComponent {
8038
8210
  }
8039
8211
  }
8040
8212
  }
8213
+ async drawItem(ctx, item) {
8214
+ for (const shape of item.shapes) {
8215
+ ctx.save();
8216
+ ctx.translate(shape.x, shape.y);
8217
+ ctx.lineWidth = 1;
8218
+ ctx.strokeStyle = "black";
8219
+ ctx.fillStyle = "white";
8220
+ await item.draw(ctx);
8221
+ ctx.restore();
8222
+ }
8223
+ }
8041
8224
  async draw() {
8042
8225
  const ctx = this.ctx;
8043
8226
  const canvas = ctx.canvas;
@@ -8063,30 +8246,29 @@ class InteractiveCanvasComponent {
8063
8246
  }
8064
8247
  ctx.restore();
8065
8248
  }
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"] }] }); }
8249
+ 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 }); }
8250
+ 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
8251
  }
8069
8252
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: InteractiveCanvasComponent, decorators: [{
8070
8253
  type: Component,
8071
8254
  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: [{
8255
+ }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: UniversalService }], propDecorators: { infinite: [{
8080
8256
  type: Input
8081
8257
  }], resizeMode: [{
8082
8258
  type: Input
8259
+ }], params: [{
8260
+ type: Input
8083
8261
  }], realWidth: [{
8084
8262
  type: Input
8085
8263
  }], realHeight: [{
8086
8264
  type: Input
8087
- }], panOffset: [{
8265
+ }], debug: [{
8088
8266
  type: Input
8089
- }], params: [{
8267
+ }], horizontal: [{
8268
+ type: Input
8269
+ }], selectedIndex: [{
8270
+ type: Input
8271
+ }], panOffset: [{
8090
8272
  type: Input
8091
8273
  }], renderCtx: [{
8092
8274
  type: Input
@@ -8913,5 +9095,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImpo
8913
9095
  * Generated bundle index. Do not edit.
8914
9096
  */
8915
9097
 
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 };
9098
+ 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
9099
  //# sourceMappingURL=stemy-ngx-utils.mjs.map