@thi.ng/geom-closest-point 2.1.87 → 2.1.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Change Log
2
2
 
3
- - **Last updated**: 2023-12-09T19:12:03Z
3
+ - **Last updated**: 2023-12-11T10:07:09Z
4
4
  - **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
5
5
 
6
6
  All notable changes to this project will be documented in this file.
package/README.md CHANGED
@@ -59,7 +59,7 @@ For Node.js REPL:
59
59
  const geomClosestPoint = await import("@thi.ng/geom-closest-point");
60
60
  ```
61
61
 
62
- Package sizes (brotli'd, pre-treeshake): ESM: 1.05 KB
62
+ Package sizes (brotli'd, pre-treeshake): ESM: 1.06 KB
63
63
 
64
64
  ## Dependencies
65
65
 
package/box.js CHANGED
@@ -1,32 +1,45 @@
1
1
  import { clamp } from "@thi.ng/math/interval";
2
2
  import { setC2, setC3 } from "@thi.ng/vectors/setc";
3
- export const closestPointRect = (p, bmin, bmax, out = []) => {
4
- const [minID, minW] = closestBoxEdge(p, bmin, bmax, 4);
5
- return minID === 0
6
- ? setC2(out, minW, clamp(p[1], bmin[1], bmax[1]))
7
- : setC2(out, clamp(p[0], bmin[0], bmax[0]), minW);
3
+ const closestPointRect = (p, bmin, bmax, out = []) => {
4
+ const [minID, minW] = closestBoxEdge(p, bmin, bmax, 4);
5
+ return minID === 0 ? setC2(out, minW, clamp(p[1], bmin[1], bmax[1])) : setC2(out, clamp(p[0], bmin[0], bmax[0]), minW);
8
6
  };
9
- export const closestPointAABB = (p, bmin, bmax, out = []) => {
10
- const [minID, minW] = closestBoxEdge(p, bmin, bmax, 6);
11
- return minID === 0
12
- ? setC3(out, minW, clamp(p[1], bmin[1], bmax[1]), clamp(p[2], bmin[2], bmax[2]))
13
- : minID === 1
14
- ? setC3(out, clamp(p[0], bmin[0], bmax[0]), minW, clamp(p[2], bmin[2], bmax[2]))
15
- : setC3(out, clamp(p[0], bmin[0], bmax[0]), clamp(p[1], bmin[1], bmax[1]), minW);
7
+ const closestPointAABB = (p, bmin, bmax, out = []) => {
8
+ const [minID, minW] = closestBoxEdge(p, bmin, bmax, 6);
9
+ return minID === 0 ? setC3(
10
+ out,
11
+ minW,
12
+ clamp(p[1], bmin[1], bmax[1]),
13
+ clamp(p[2], bmin[2], bmax[2])
14
+ ) : minID === 1 ? setC3(
15
+ out,
16
+ clamp(p[0], bmin[0], bmax[0]),
17
+ minW,
18
+ clamp(p[2], bmin[2], bmax[2])
19
+ ) : setC3(
20
+ out,
21
+ clamp(p[0], bmin[0], bmax[0]),
22
+ clamp(p[1], bmin[1], bmax[1]),
23
+ minW
24
+ );
16
25
  };
17
26
  const closestBoxEdge = (p, bmin, bmax, n) => {
18
- let minD = Infinity;
19
- let minID;
20
- let minW;
21
- for (let i = 0; i < n; i++) {
22
- const j = i >> 1;
23
- const w = (i & 1 ? bmax : bmin)[j];
24
- const d = Math.abs(p[j] - w);
25
- if (d < minD) {
26
- minD = d;
27
- minID = j;
28
- minW = w;
29
- }
27
+ let minD = Infinity;
28
+ let minID;
29
+ let minW;
30
+ for (let i = 0; i < n; i++) {
31
+ const j = i >> 1;
32
+ const w = (i & 1 ? bmax : bmin)[j];
33
+ const d = Math.abs(p[j] - w);
34
+ if (d < minD) {
35
+ minD = d;
36
+ minID = j;
37
+ minW = w;
30
38
  }
31
- return [minID, minW];
39
+ }
40
+ return [minID, minW];
41
+ };
42
+ export {
43
+ closestPointAABB,
44
+ closestPointRect
32
45
  };
package/circle.js CHANGED
@@ -1,15 +1,8 @@
1
1
  import { add } from "@thi.ng/vectors/add";
2
2
  import { direction } from "@thi.ng/vectors/direction";
3
- /**
4
- * Returns closest point to `p` on circle defined by origin `c` and radius `r`.
5
- *
6
- * @param p -
7
- * @param c -
8
- * @param r -
9
- * @param out -
10
- */
11
- export const closestPointCircle = (p, c, r, out = []) => add(out, c, direction(out, c, p, r));
12
- /**
13
- * Same as {@link closestPointCircle}.
14
- */
15
- export const closestPointSphere = closestPointCircle;
3
+ const closestPointCircle = (p, c, r, out = []) => add(out, c, direction(out, c, p, r));
4
+ const closestPointSphere = closestPointCircle;
5
+ export {
6
+ closestPointCircle,
7
+ closestPointSphere
8
+ };
package/ellipse.js CHANGED
@@ -1,38 +1,26 @@
1
1
  import { SQRT2_2 } from "@thi.ng/math/api";
2
2
  import { clamp01 } from "@thi.ng/math/interval";
3
- /**
4
- * @remarks
5
- * Based on iterative solution by Luc Maisonobe:
6
- *
7
- * - https://www.spaceroots.org/documents/distance/distance-to-ellipse.pdf
8
- * - https://gist.github.com/JohannesMP/777bdc8e84df6ddfeaa4f0ddb1c7adb3
9
- *
10
- * Further optimizations: constant folding, avoiding duplicate calculations in
11
- * loop
12
- *
13
- * @param p - query point
14
- * @param eo - ellipse center/origin
15
- * @param er - ellipse radii
16
- * @param n - number of iterations
17
- */
18
- export const closestPointEllipse = ([px, py], [ex, ey], [rx, ry], n = 3) => {
19
- const apx = Math.abs(px - ex);
20
- const apy = Math.abs(py - ey);
21
- const ab = (rx * rx - ry * ry) / rx;
22
- const ba = (ry * ry - rx * rx) / ry;
23
- let tx = SQRT2_2;
24
- let ty = tx;
25
- for (; n-- > 0;) {
26
- const _ex = ab * tx * tx * tx;
27
- const _ey = ba * ty * ty * ty;
28
- const qx = apx - _ex;
29
- const qy = apy - _ey;
30
- const q = Math.hypot(rx * tx - _ex, ry * ty - _ey) / Math.hypot(qx, qy);
31
- tx = clamp01((qx * q + _ex) / rx);
32
- ty = clamp01((qy * q + _ey) / ry);
33
- const t = Math.hypot(tx, ty);
34
- tx /= t;
35
- ty /= t;
36
- }
37
- return [rx * (px < ex ? -tx : tx) + ex, ry * (py < ey ? -ty : ty) + ey];
3
+ const closestPointEllipse = ([px, py], [ex, ey], [rx, ry], n = 3) => {
4
+ const apx = Math.abs(px - ex);
5
+ const apy = Math.abs(py - ey);
6
+ const ab = (rx * rx - ry * ry) / rx;
7
+ const ba = (ry * ry - rx * rx) / ry;
8
+ let tx = SQRT2_2;
9
+ let ty = tx;
10
+ for (; n-- > 0; ) {
11
+ const _ex = ab * tx * tx * tx;
12
+ const _ey = ba * ty * ty * ty;
13
+ const qx = apx - _ex;
14
+ const qy = apy - _ey;
15
+ const q = Math.hypot(rx * tx - _ex, ry * ty - _ey) / Math.hypot(qx, qy);
16
+ tx = clamp01((qx * q + _ex) / rx);
17
+ ty = clamp01((qy * q + _ey) / ry);
18
+ const t = Math.hypot(tx, ty);
19
+ tx /= t;
20
+ ty /= t;
21
+ }
22
+ return [rx * (px < ex ? -tx : tx) + ex, ry * (py < ey ? -ty : ty) + ey];
23
+ };
24
+ export {
25
+ closestPointEllipse
38
26
  };
package/line.js CHANGED
@@ -6,143 +6,65 @@ import { magSq } from "@thi.ng/vectors/magsq";
6
6
  import { mixN } from "@thi.ng/vectors/mixn";
7
7
  import { set } from "@thi.ng/vectors/set";
8
8
  import { sub } from "@thi.ng/vectors/sub";
9
- /**
10
- * Computes the parametric distance `t` of point `p` projected onto line
11
- * `a` -> `b`, relative to `a`. I.e. the projection of `p` can then be
12
- * computed like so:
13
- *
14
- * @example
15
- * ```ts
16
- * mixN([], a, b, closestT(p, a, b))
17
- * ```
18
- *
19
- * If the return value is outside the closed [0,1] interval, the
20
- * projected point lies outside the line segment. Returns `undefined` if
21
- * `a` and `b` are coincident.
22
- *
23
- * - {@link closestPointLine}
24
- * - {@link closestPointSegment}
25
- *
26
- * @param p - query point
27
- * @param a - line point A
28
- * @param b - line point B
29
- */
30
- export const closestT = (p, a, b) => {
31
- const d = sub([], b, a);
32
- const l = magSq(d);
33
- return l > 1e-6 ? dot(sub([], p, a), d) / l : undefined;
9
+ const closestT = (p, a, b) => {
10
+ const d = sub([], b, a);
11
+ const l = magSq(d);
12
+ return l > 1e-6 ? dot(sub([], p, a), d) / l : void 0;
34
13
  };
35
- /**
36
- * Returns closest point to `p` on infinite line defined by points `a`
37
- * and `b`. Use {@link closestPointSegment} to only consider the actual line
38
- * segment between these two points.
39
- *
40
- * {@link closestPointSegment}
41
- *
42
- * @param p - query point
43
- * @param a - line point A
44
- * @param b - line point B
45
- */
46
- export const closestPointLine = (p, a, b) => mixN([], a, b, closestT(p, a, b) || 0);
47
- /**
48
- * Returns distance from `p` to closest point to infinite line `a` ->
49
- * `b`. Use {@link distToSegment} to only consider the actual line segment
50
- * between these two points.
51
- *
52
- * {@link distToSegment}
53
- *
54
- * @param p - query point
55
- * @param a - line point A
56
- * @param b - line point B
57
- */
58
- export const distToLine = (p, a, b) => dist(p, closestPointLine(p, a, b) || a);
59
- /**
60
- * Returns closest point to `p` on line segment `a` -> `b`. By default,
61
- * if the result point lies outside the segment, returns a copy of the
62
- * closest end point. The result is written to the optional `out` vector
63
- * (or if omitted, a new one is created).
64
- *
65
- * If `insideOnly` is true, only returns the closest point iff it
66
- * actually is inside the segment. The behavior of this configurable via
67
- * the optional `eps` arg and by default includes both end points. This
68
- * function uses {@link closestT} to compute the parametric position of the
69
- * result point and determine if it lies within the line segment. If
70
- * `eps > 0`, the end points `a` and `b` will be excluded from the
71
- * match, effectively shortening the valid line segment from both ends,
72
- * i.e. the valid interval of the parametric position will be
73
- * [eps,1-eps]. If the result lies outside this interval, the function
74
- * returns `undefined`. Likewise, if `a` and `b` are coincident.
75
- *
76
- * @param p - query point
77
- * @param a - line point A
78
- * @param b - line point B
79
- * @param out - result
80
- * @param eps - epsilon value
81
- */
82
- export const closestPointSegment = (p, a, b, out, insideOnly = false, eps = 0) => {
83
- const t = closestT(p, a, b);
84
- if (t !== undefined && (!insideOnly || (t >= eps && t <= 1 - eps))) {
85
- out = out || empty(p);
86
- return t <= 0 ? set(out, a) : t >= 1 ? set(out, b) : mixN(out, a, b, t);
87
- }
14
+ const closestPointLine = (p, a, b) => mixN([], a, b, closestT(p, a, b) || 0);
15
+ const distToLine = (p, a, b) => dist(p, closestPointLine(p, a, b) || a);
16
+ const closestPointSegment = (p, a, b, out, insideOnly = false, eps = 0) => {
17
+ const t = closestT(p, a, b);
18
+ if (t !== void 0 && (!insideOnly || t >= eps && t <= 1 - eps)) {
19
+ out = out || empty(p);
20
+ return t <= 0 ? set(out, a) : t >= 1 ? set(out, b) : mixN(out, a, b, t);
21
+ }
88
22
  };
89
- /**
90
- * Returns distance from `p` to closest point on line segment `a` ->
91
- * `b`.
92
- *
93
- * @param p - query point
94
- * @param a - line point A
95
- * @param b - line point B
96
- */
97
- export const distToSegment = (p, a, b) => dist(p, closestPointSegment(p, a, b) || a);
98
- export const closestPointPolyline = (p, pts, closed = false, out = []) => {
99
- if (!pts.length)
100
- return;
101
- const tmp = [];
102
- const n = pts.length - 1;
103
- let minD = Infinity, i, j;
104
- if (closed) {
105
- i = n;
106
- j = 0;
107
- }
108
- else {
109
- i = 0;
110
- j = 1;
23
+ const distToSegment = (p, a, b) => dist(p, closestPointSegment(p, a, b) || a);
24
+ const closestPointPolyline = (p, pts, closed = false, out = []) => {
25
+ if (!pts.length)
26
+ return;
27
+ const tmp = [];
28
+ const n = pts.length - 1;
29
+ let minD = Infinity, i, j;
30
+ if (closed) {
31
+ i = n;
32
+ j = 0;
33
+ } else {
34
+ i = 0;
35
+ j = 1;
36
+ }
37
+ for (; j <= n; i = j, j++) {
38
+ if (closestPointSegment(p, pts[i], pts[j], tmp)) {
39
+ const d = distSq(p, tmp);
40
+ if (d < minD) {
41
+ minD = d;
42
+ set(out, tmp);
43
+ }
111
44
  }
112
- for (; j <= n; i = j, j++) {
113
- if (closestPointSegment(p, pts[i], pts[j], tmp)) {
114
- const d = distSq(p, tmp);
115
- if (d < minD) {
116
- minD = d;
117
- set(out, tmp);
118
- }
119
- }
120
- }
121
- return minD < Infinity ? out : undefined;
45
+ }
46
+ return minD < Infinity ? out : void 0;
122
47
  };
123
- /**
124
- * Returns the index of the start point containing the segment in the
125
- * polyline array `points` farthest away from `p` with regards to the
126
- * line segment `a` to `b`. `points` is only checked between indices
127
- * `from` and `to` (not including the latter).
128
- *
129
- * @param a - line point A
130
- * @param b - line point B
131
- * @param points - points
132
- * @param from - start search index
133
- * @param to - end search index
134
- */
135
- export const farthestPointSegment = (a, b, points, from = 0, to = points.length) => {
136
- let maxD = -1;
137
- let maxIdx = -1;
138
- const tmp = empty(a);
139
- for (let i = from; i < to; i++) {
140
- const p = points[i];
141
- const d = distSq(p, closestPointSegment(p, a, b, tmp) || a);
142
- if (d > maxD) {
143
- maxD = d;
144
- maxIdx = i;
145
- }
48
+ const farthestPointSegment = (a, b, points, from = 0, to = points.length) => {
49
+ let maxD = -1;
50
+ let maxIdx = -1;
51
+ const tmp = empty(a);
52
+ for (let i = from; i < to; i++) {
53
+ const p = points[i];
54
+ const d = distSq(p, closestPointSegment(p, a, b, tmp) || a);
55
+ if (d > maxD) {
56
+ maxD = d;
57
+ maxIdx = i;
146
58
  }
147
- return [maxIdx, Math.sqrt(maxD)];
59
+ }
60
+ return [maxIdx, Math.sqrt(maxD)];
61
+ };
62
+ export {
63
+ closestPointLine,
64
+ closestPointPolyline,
65
+ closestPointSegment,
66
+ closestT,
67
+ distToLine,
68
+ distToSegment,
69
+ farthestPointSegment
148
70
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thi.ng/geom-closest-point",
3
- "version": "2.1.87",
3
+ "version": "2.1.89",
4
4
  "description": "2D / 3D closest point / proximity helpers",
5
5
  "type": "module",
6
6
  "module": "./index.js",
@@ -24,7 +24,9 @@
24
24
  "author": "Karsten Schmidt (https://thi.ng)",
25
25
  "license": "Apache-2.0",
26
26
  "scripts": {
27
- "build": "yarn clean && tsc --declaration",
27
+ "build": "yarn build:esbuild && yarn build:decl",
28
+ "build:decl": "tsc --declaration --emitDeclarationOnly",
29
+ "build:esbuild": "esbuild --format=esm --platform=neutral --target=es2022 --tsconfig=tsconfig.json --outdir=. src/**/*.ts",
28
30
  "clean": "rimraf --glob '*.js' '*.d.ts' '*.map' doc",
29
31
  "doc": "typedoc --excludePrivate --excludeInternal --out doc src/index.ts",
30
32
  "doc:ae": "mkdir -p .ae/doc .ae/temp && api-extractor run --local --verbose",
@@ -33,12 +35,13 @@
33
35
  "test": "bun test"
34
36
  },
35
37
  "dependencies": {
36
- "@thi.ng/api": "^8.9.11",
37
- "@thi.ng/math": "^5.7.6",
38
- "@thi.ng/vectors": "^7.8.8"
38
+ "@thi.ng/api": "^8.9.12",
39
+ "@thi.ng/math": "^5.7.7",
40
+ "@thi.ng/vectors": "^7.8.10"
39
41
  },
40
42
  "devDependencies": {
41
43
  "@microsoft/api-extractor": "^7.38.3",
44
+ "esbuild": "^0.19.8",
42
45
  "rimraf": "^5.0.5",
43
46
  "tools": "^0.0.1",
44
47
  "typedoc": "^0.25.4",
@@ -101,5 +104,5 @@
101
104
  ],
102
105
  "year": 2018
103
106
  },
104
- "gitHead": "25f2ac8ff795a432a930119661b364d4d93b59a0\n"
107
+ "gitHead": "22e36fa838e5431d40165384918b395603bbd92f\n"
105
108
  }
package/plane.js CHANGED
@@ -1,26 +1,9 @@
1
1
  import { dot } from "@thi.ng/vectors/dot";
2
2
  import { normalize } from "@thi.ng/vectors/normalize";
3
3
  import { sub } from "@thi.ng/vectors/sub";
4
- /**
5
- * Returns signed distance between point `p` and plane defined by normal `n` and
6
- * `w`. In 2D this also works for lines.
7
- *
8
- * @remarks
9
- * If result is > 0 the point lies "above" the plane, if < 0 below the plane or
10
- * if zero on the plane.
11
- *
12
- * @param p -
13
- * @param n -
14
- * @param w -
15
- */
16
- export const distToPlane = (p, n, w) => dot(n, p) - w;
17
- /**
18
- * Returns closest point to `p` on the plane defined by normal `n` and `w`. In
19
- * 2D this also works for lines.
20
- *
21
- * @param p -
22
- * @param normal -
23
- * @param w -
24
- * @param out -
25
- */
26
- export const closestPointPlane = (p, normal, w, out = []) => sub(out, p, normalize(out, normal, distToPlane(p, normal, w)));
4
+ const distToPlane = (p, n, w) => dot(n, p) - w;
5
+ const closestPointPlane = (p, normal, w, out = []) => sub(out, p, normalize(out, normal, distToPlane(p, normal, w)));
6
+ export {
7
+ closestPointPlane,
8
+ distToPlane
9
+ };
package/points.js CHANGED
@@ -1,24 +1,17 @@
1
1
  import { distSq } from "@thi.ng/vectors/distsq";
2
2
  import { set } from "@thi.ng/vectors/set";
3
- /**
4
- * Returns closest point to `p` in given point array, optionally using custom
5
- * distance function `dist` (default:
6
- * [`distSq()`](https://docs.thi.ng/umbrella/vectors/functions/distSq.html)).
7
- *
8
- * @param p -
9
- * @param pts -
10
- * @param out -
11
- * @param dist -
12
- */
13
- export const closestPointArray = (p, pts, out = [], dist = distSq) => {
14
- let minD = Infinity;
15
- let closest;
16
- for (let i = pts.length; i-- > 0;) {
17
- const d = dist(pts[i], p);
18
- if (d < minD) {
19
- minD = d;
20
- closest = pts[i];
21
- }
3
+ const closestPointArray = (p, pts, out = [], dist = distSq) => {
4
+ let minD = Infinity;
5
+ let closest;
6
+ for (let i = pts.length; i-- > 0; ) {
7
+ const d = dist(pts[i], p);
8
+ if (d < minD) {
9
+ minD = d;
10
+ closest = pts[i];
22
11
  }
23
- return closest ? set(out, closest) : undefined;
12
+ }
13
+ return closest ? set(out, closest) : void 0;
14
+ };
15
+ export {
16
+ closestPointArray
24
17
  };