@tscircuit/math-utils 0.0.15 → 0.0.16
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/dist/{chunk-W6CW26U5.js → chunk-572TQ3QB.js} +8 -2
- package/dist/{chunk-W6CW26U5.js.map → chunk-572TQ3QB.js.map} +1 -1
- package/dist/{chunk-K7F26NYD.js → chunk-RNQKFERU.js} +16 -2
- package/dist/{chunk-K7F26NYD.js.map → chunk-RNQKFERU.js.map} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +6 -2
- package/dist/point-distance.d.ts +2 -1
- package/dist/point-distance.js +3 -1
- package/dist/segment-distance.d.ts +2 -1
- package/dist/segment-distance.js +3 -1
- package/package.json +1 -1
|
@@ -34,10 +34,16 @@ function midpoint(p1, p2) {
|
|
|
34
34
|
y: (p1.y + p2.y) / 2
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
|
+
function distSq(p1, p2) {
|
|
38
|
+
const dx = p1.x - p2.x;
|
|
39
|
+
const dy = p1.y - p2.y;
|
|
40
|
+
return dx * dx + dy * dy;
|
|
41
|
+
}
|
|
37
42
|
|
|
38
43
|
export {
|
|
39
44
|
pointToBoxDistance,
|
|
40
45
|
pointToBoundsDistance,
|
|
41
|
-
midpoint
|
|
46
|
+
midpoint,
|
|
47
|
+
distSq
|
|
42
48
|
};
|
|
43
|
-
//# sourceMappingURL=chunk-
|
|
49
|
+
//# sourceMappingURL=chunk-572TQ3QB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/point-distance.ts"],"sourcesContent":["import type { Point, Bounds } from \"./common\"\nimport { distance } from \"./line-intersections\"\nimport { clamp } from \"./nearest-box\"\nimport type { Box } from \"./nearest-box\"\n\n/**\n * Returns the minimum distance from a point to a box.\n * If the point is inside the box, the distance is 0.\n */\nexport function pointToBoxDistance(p: Point, box: Box): number {\n const halfWidth = box.width / 2\n const halfHeight = box.height / 2\n const minX = box.center.x - halfWidth\n const maxX = box.center.x + halfWidth\n const minY = box.center.y - halfHeight\n const maxY = box.center.y + halfHeight\n\n // Check if the point is inside the box\n if (p.x >= minX && p.x <= maxX && p.y >= minY && p.y <= maxY) {\n return 0\n }\n\n // Find the closest point on the box boundary\n const closestX = clamp(p.x, minX, maxX)\n const closestY = clamp(p.y, minY, maxY)\n\n // Calculate the distance to the closest point\n return distance(p, { x: closestX, y: closestY })\n}\n\n/**\n * Returns the minimum distance from a point to a bounds rectangle.\n * If the point is inside the bounds, the distance is 0.\n */\nexport function pointToBoundsDistance(p: Point, bounds: Bounds): number {\n // Check if the point is inside the bounds\n if (\n p.x >= bounds.minX &&\n p.x <= bounds.maxX &&\n p.y >= bounds.minY &&\n p.y <= bounds.maxY\n ) {\n return 0\n }\n\n // Find the closest point on the bounds boundary\n const closestX = clamp(p.x, bounds.minX, bounds.maxX)\n const closestY = clamp(p.y, bounds.minY, bounds.maxY)\n\n // Calculate the distance to the closest point\n return distance(p, { x: closestX, y: closestY })\n}\n\nexport function midpoint(p1: Point, p2: Point): Point {\n return {\n x: (p1.x + p2.x) / 2,\n y: (p1.y + p2.y) / 2,\n }\n}\n"],"mappings":";;;;;;;;AASO,SAAS,mBAAmB,GAAU,KAAkB;AAC7D,QAAM,YAAY,IAAI,QAAQ;AAC9B,QAAM,aAAa,IAAI,SAAS;AAChC,QAAM,OAAO,IAAI,OAAO,IAAI;AAC5B,QAAM,OAAO,IAAI,OAAO,IAAI;AAC5B,QAAM,OAAO,IAAI,OAAO,IAAI;AAC5B,QAAM,OAAO,IAAI,OAAO,IAAI;AAG5B,MAAI,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM;AAC5D,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,MAAM,EAAE,GAAG,MAAM,IAAI;AACtC,QAAM,WAAW,MAAM,EAAE,GAAG,MAAM,IAAI;AAGtC,SAAO,SAAS,GAAG,EAAE,GAAG,UAAU,GAAG,SAAS,CAAC;AACjD;AAMO,SAAS,sBAAsB,GAAU,QAAwB;AAEtE,MACE,EAAE,KAAK,OAAO,QACd,EAAE,KAAK,OAAO,QACd,EAAE,KAAK,OAAO,QACd,EAAE,KAAK,OAAO,MACd;AACA,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,MAAM,EAAE,GAAG,OAAO,MAAM,OAAO,IAAI;AACpD,QAAM,WAAW,MAAM,EAAE,GAAG,OAAO,MAAM,OAAO,IAAI;AAGpD,SAAO,SAAS,GAAG,EAAE,GAAG,UAAU,GAAG,SAAS,CAAC;AACjD;AAEO,SAAS,SAAS,IAAW,IAAkB;AACpD,SAAO;AAAA,IACL,IAAI,GAAG,IAAI,GAAG,KAAK;AAAA,IACnB,IAAI,GAAG,IAAI,GAAG,KAAK;AAAA,EACrB;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/point-distance.ts"],"sourcesContent":["import type { Point, Bounds } from \"./common\"\nimport { distance } from \"./line-intersections\"\nimport { clamp } from \"./nearest-box\"\nimport type { Box } from \"./nearest-box\"\n\n/**\n * Returns the minimum distance from a point to a box.\n * If the point is inside the box, the distance is 0.\n */\nexport function pointToBoxDistance(p: Point, box: Box): number {\n const halfWidth = box.width / 2\n const halfHeight = box.height / 2\n const minX = box.center.x - halfWidth\n const maxX = box.center.x + halfWidth\n const minY = box.center.y - halfHeight\n const maxY = box.center.y + halfHeight\n\n // Check if the point is inside the box\n if (p.x >= minX && p.x <= maxX && p.y >= minY && p.y <= maxY) {\n return 0\n }\n\n // Find the closest point on the box boundary\n const closestX = clamp(p.x, minX, maxX)\n const closestY = clamp(p.y, minY, maxY)\n\n // Calculate the distance to the closest point\n return distance(p, { x: closestX, y: closestY })\n}\n\n/**\n * Returns the minimum distance from a point to a bounds rectangle.\n * If the point is inside the bounds, the distance is 0.\n */\nexport function pointToBoundsDistance(p: Point, bounds: Bounds): number {\n // Check if the point is inside the bounds\n if (\n p.x >= bounds.minX &&\n p.x <= bounds.maxX &&\n p.y >= bounds.minY &&\n p.y <= bounds.maxY\n ) {\n return 0\n }\n\n // Find the closest point on the bounds boundary\n const closestX = clamp(p.x, bounds.minX, bounds.maxX)\n const closestY = clamp(p.y, bounds.minY, bounds.maxY)\n\n // Calculate the distance to the closest point\n return distance(p, { x: closestX, y: closestY })\n}\n\nexport function midpoint(p1: Point, p2: Point): Point {\n return {\n x: (p1.x + p2.x) / 2,\n y: (p1.y + p2.y) / 2,\n }\n}\n\nexport function distSq(p1: Point, p2: Point): number {\n const dx = p1.x - p2.x\n const dy = p1.y - p2.y\n return dx * dx + dy * dy\n}\n"],"mappings":";;;;;;;;AASO,SAAS,mBAAmB,GAAU,KAAkB;AAC7D,QAAM,YAAY,IAAI,QAAQ;AAC9B,QAAM,aAAa,IAAI,SAAS;AAChC,QAAM,OAAO,IAAI,OAAO,IAAI;AAC5B,QAAM,OAAO,IAAI,OAAO,IAAI;AAC5B,QAAM,OAAO,IAAI,OAAO,IAAI;AAC5B,QAAM,OAAO,IAAI,OAAO,IAAI;AAG5B,MAAI,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM;AAC5D,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,MAAM,EAAE,GAAG,MAAM,IAAI;AACtC,QAAM,WAAW,MAAM,EAAE,GAAG,MAAM,IAAI;AAGtC,SAAO,SAAS,GAAG,EAAE,GAAG,UAAU,GAAG,SAAS,CAAC;AACjD;AAMO,SAAS,sBAAsB,GAAU,QAAwB;AAEtE,MACE,EAAE,KAAK,OAAO,QACd,EAAE,KAAK,OAAO,QACd,EAAE,KAAK,OAAO,QACd,EAAE,KAAK,OAAO,MACd;AACA,WAAO;AAAA,EACT;AAGA,QAAM,WAAW,MAAM,EAAE,GAAG,OAAO,MAAM,OAAO,IAAI;AACpD,QAAM,WAAW,MAAM,EAAE,GAAG,OAAO,MAAM,OAAO,IAAI;AAGpD,SAAO,SAAS,GAAG,EAAE,GAAG,UAAU,GAAG,SAAS,CAAC;AACjD;AAEO,SAAS,SAAS,IAAW,IAAkB;AACpD,SAAO;AAAA,IACL,IAAI,GAAG,IAAI,GAAG,KAAK;AAAA,IACnB,IAAI,GAAG,IAAI,GAAG,KAAK;AAAA,EACrB;AACF;AAEO,SAAS,OAAO,IAAW,IAAmB;AACnD,QAAM,KAAK,GAAG,IAAI,GAAG;AACrB,QAAM,KAAK,GAAG,IAAI,GAAG;AACrB,SAAO,KAAK,KAAK,KAAK;AACxB;","names":[]}
|
|
@@ -88,11 +88,25 @@ function segmentToCircleMinDistance(a, b, circle) {
|
|
|
88
88
|
const distToCenter = distance(closestPoint, circleCenter);
|
|
89
89
|
return Math.max(0, distToCenter - circle.radius);
|
|
90
90
|
}
|
|
91
|
+
function pointToSegmentClosestPoint(p, a, b) {
|
|
92
|
+
const dx_ab = b.x - a.x;
|
|
93
|
+
const dy_ab = b.y - a.y;
|
|
94
|
+
const l2 = dx_ab * dx_ab + dy_ab * dy_ab;
|
|
95
|
+
if (l2 === 0) return { x: a.x, y: a.y };
|
|
96
|
+
let t = ((p.x - a.x) * dx_ab + (p.y - a.y) * dy_ab) / l2;
|
|
97
|
+
t = Math.max(0, Math.min(1, t));
|
|
98
|
+
const closestPoint = {
|
|
99
|
+
x: a.x + t * dx_ab,
|
|
100
|
+
y: a.y + t * dy_ab
|
|
101
|
+
};
|
|
102
|
+
return closestPoint;
|
|
103
|
+
}
|
|
91
104
|
|
|
92
105
|
export {
|
|
93
106
|
segmentToSegmentMinDistance,
|
|
94
107
|
segmentToBoundsMinDistance,
|
|
95
108
|
segmentToBoxMinDistance,
|
|
96
|
-
segmentToCircleMinDistance
|
|
109
|
+
segmentToCircleMinDistance,
|
|
110
|
+
pointToSegmentClosestPoint
|
|
97
111
|
};
|
|
98
|
-
//# sourceMappingURL=chunk-
|
|
112
|
+
//# sourceMappingURL=chunk-RNQKFERU.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/segment-distance.ts"],"sourcesContent":["import type { Point } from \"./common\"\nimport {\n distance,\n doSegmentsIntersect,\n pointToSegmentDistance,\n} from \"./line-intersections\"\nimport { clamp } from \"./nearest-box\"\n\n/**\n * Returns the minimum distance between two line segments.\n */\nexport function segmentToSegmentMinDistance(\n a: Point,\n b: Point,\n u: Point,\n v: Point,\n): number {\n // Handle degenerate cases: segments of zero length\n if (a.x === b.x && a.y === b.y) {\n return pointToSegmentDistance(a, u, v)\n }\n if (u.x === v.x && u.y === v.y) {\n return pointToSegmentDistance(u, a, b)\n }\n\n // Check if segments intersect\n if (doSegmentsIntersect(a, b, u, v)) {\n return 0\n }\n\n // Compute the minimum distance between the segments\n const distances = [\n pointToSegmentDistance(a, u, v),\n pointToSegmentDistance(b, u, v),\n pointToSegmentDistance(u, a, b),\n pointToSegmentDistance(v, a, b),\n ]\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance from a line segment to a bounding box.\n */\nexport function segmentToBoundsMinDistance(\n a: Point,\n b: Point,\n bounds: { minX: number; minY: number; maxX: number; maxY: number },\n): number {\n // Check if segment intersects with the bounds\n // Create the four edges of the bounds\n const topLeft = { x: bounds.minX, y: bounds.minY }\n const topRight = { x: bounds.maxX, y: bounds.minY }\n const bottomLeft = { x: bounds.minX, y: bounds.maxY }\n const bottomRight = { x: bounds.maxX, y: bounds.maxY }\n\n // Check if segment intersects with any of the bounds edges\n if (\n doSegmentsIntersect(a, b, topLeft, topRight) ||\n doSegmentsIntersect(a, b, topRight, bottomRight) ||\n doSegmentsIntersect(a, b, bottomRight, bottomLeft) ||\n doSegmentsIntersect(a, b, bottomLeft, topLeft)\n ) {\n return 0\n }\n\n // Check if segment is entirely inside the bounds\n if (\n a.x >= bounds.minX &&\n a.x <= bounds.maxX &&\n a.y >= bounds.minY &&\n a.y <= bounds.maxY &&\n b.x >= bounds.minX &&\n b.x <= bounds.maxX &&\n b.y >= bounds.minY &&\n b.y <= bounds.maxY\n ) {\n return 0\n }\n\n // If not intersecting, calculate the minimum distance\n const distances = [\n pointToSegmentDistance(topLeft, a, b),\n pointToSegmentDistance(topRight, a, b),\n pointToSegmentDistance(bottomLeft, a, b),\n pointToSegmentDistance(bottomRight, a, b),\n ]\n\n // If one of the segment endpoints is inside the bounds, we need to consider its distance to the bounds as 0\n if (\n a.x >= bounds.minX &&\n a.x <= bounds.maxX &&\n a.y >= bounds.minY &&\n a.y <= bounds.maxY\n ) {\n return 0\n }\n\n if (\n b.x >= bounds.minX &&\n b.x <= bounds.maxX &&\n b.y >= bounds.minY &&\n b.y <= bounds.maxY\n ) {\n return 0\n }\n\n // Calculate distances from segment endpoints to bounds if outside\n if (\n a.x < bounds.minX ||\n a.x > bounds.maxX ||\n a.y < bounds.minY ||\n a.y > bounds.maxY\n ) {\n const closestX = clamp(a.x, bounds.minX, bounds.maxX)\n const closestY = clamp(a.y, bounds.minY, bounds.maxY)\n distances.push(distance(a, { x: closestX, y: closestY }))\n }\n\n if (\n b.x < bounds.minX ||\n b.x > bounds.maxX ||\n b.y < bounds.minY ||\n b.y > bounds.maxY\n ) {\n const closestX = clamp(b.x, bounds.minX, bounds.maxX)\n const closestY = clamp(b.y, bounds.minY, bounds.maxY)\n distances.push(distance(b, { x: closestX, y: closestY }))\n }\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance from a line segment to a box.\n */\nexport function segmentToBoxMinDistance(\n a: Point,\n b: Point,\n box: { center: Point; width: number; height: number },\n): number {\n const halfWidth = box.width / 2\n const halfHeight = box.height / 2\n const bounds = {\n minX: box.center.x - halfWidth,\n maxX: box.center.x + halfWidth,\n minY: box.center.y - halfHeight,\n maxY: box.center.y + halfHeight,\n }\n\n return segmentToBoundsMinDistance(a, b, bounds)\n}\n\n/**\n * Returns the minimum distance from a line segment to a circle.\n */\nexport function segmentToCircleMinDistance(\n a: Point,\n b: Point,\n circle: { x: number; y: number; radius: number },\n): number {\n // Calculate the distance from the circle center to the line segment\n const circleCenter = { x: circle.x, y: circle.y }\n\n // Handle degenerate case: segment of zero length (point to circle)\n if (a.x === b.x && a.y === b.y) {\n return Math.max(0, distance(a, circleCenter) - circle.radius)\n }\n\n // Vector from a to b\n const ab = { x: b.x - a.x, y: b.y - a.y }\n // Vector from a to circle center\n const ac = { x: circleCenter.x - a.x, y: circleCenter.y - a.y }\n\n // Length of segment ab squared\n const abLengthSq = ab.x * ab.x + ab.y * ab.y\n\n // Calculate projection of ac onto ab, normalized by the length of ab\n const t = Math.max(0, Math.min(1, (ab.x * ac.x + ab.y * ac.y) / abLengthSq))\n\n // Find the closest point on the segment to the circle center\n const closestPoint = {\n x: a.x + t * ab.x,\n y: a.y + t * ab.y,\n }\n\n // Calculate distance from closest point to circle center\n const distToCenter = distance(closestPoint, circleCenter)\n\n // Return the distance to the circle (subtract radius from distance to center)\n return Math.max(0, distToCenter - circle.radius)\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/segment-distance.ts"],"sourcesContent":["import type { Point } from \"./common\"\nimport {\n distance,\n doSegmentsIntersect,\n pointToSegmentDistance,\n} from \"./line-intersections\"\nimport { clamp } from \"./nearest-box\"\n\n/**\n * Returns the minimum distance between two line segments.\n */\nexport function segmentToSegmentMinDistance(\n a: Point,\n b: Point,\n u: Point,\n v: Point,\n): number {\n // Handle degenerate cases: segments of zero length\n if (a.x === b.x && a.y === b.y) {\n return pointToSegmentDistance(a, u, v)\n }\n if (u.x === v.x && u.y === v.y) {\n return pointToSegmentDistance(u, a, b)\n }\n\n // Check if segments intersect\n if (doSegmentsIntersect(a, b, u, v)) {\n return 0\n }\n\n // Compute the minimum distance between the segments\n const distances = [\n pointToSegmentDistance(a, u, v),\n pointToSegmentDistance(b, u, v),\n pointToSegmentDistance(u, a, b),\n pointToSegmentDistance(v, a, b),\n ]\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance from a line segment to a bounding box.\n */\nexport function segmentToBoundsMinDistance(\n a: Point,\n b: Point,\n bounds: { minX: number; minY: number; maxX: number; maxY: number },\n): number {\n // Check if segment intersects with the bounds\n // Create the four edges of the bounds\n const topLeft = { x: bounds.minX, y: bounds.minY }\n const topRight = { x: bounds.maxX, y: bounds.minY }\n const bottomLeft = { x: bounds.minX, y: bounds.maxY }\n const bottomRight = { x: bounds.maxX, y: bounds.maxY }\n\n // Check if segment intersects with any of the bounds edges\n if (\n doSegmentsIntersect(a, b, topLeft, topRight) ||\n doSegmentsIntersect(a, b, topRight, bottomRight) ||\n doSegmentsIntersect(a, b, bottomRight, bottomLeft) ||\n doSegmentsIntersect(a, b, bottomLeft, topLeft)\n ) {\n return 0\n }\n\n // Check if segment is entirely inside the bounds\n if (\n a.x >= bounds.minX &&\n a.x <= bounds.maxX &&\n a.y >= bounds.minY &&\n a.y <= bounds.maxY &&\n b.x >= bounds.minX &&\n b.x <= bounds.maxX &&\n b.y >= bounds.minY &&\n b.y <= bounds.maxY\n ) {\n return 0\n }\n\n // If not intersecting, calculate the minimum distance\n const distances = [\n pointToSegmentDistance(topLeft, a, b),\n pointToSegmentDistance(topRight, a, b),\n pointToSegmentDistance(bottomLeft, a, b),\n pointToSegmentDistance(bottomRight, a, b),\n ]\n\n // If one of the segment endpoints is inside the bounds, we need to consider its distance to the bounds as 0\n if (\n a.x >= bounds.minX &&\n a.x <= bounds.maxX &&\n a.y >= bounds.minY &&\n a.y <= bounds.maxY\n ) {\n return 0\n }\n\n if (\n b.x >= bounds.minX &&\n b.x <= bounds.maxX &&\n b.y >= bounds.minY &&\n b.y <= bounds.maxY\n ) {\n return 0\n }\n\n // Calculate distances from segment endpoints to bounds if outside\n if (\n a.x < bounds.minX ||\n a.x > bounds.maxX ||\n a.y < bounds.minY ||\n a.y > bounds.maxY\n ) {\n const closestX = clamp(a.x, bounds.minX, bounds.maxX)\n const closestY = clamp(a.y, bounds.minY, bounds.maxY)\n distances.push(distance(a, { x: closestX, y: closestY }))\n }\n\n if (\n b.x < bounds.minX ||\n b.x > bounds.maxX ||\n b.y < bounds.minY ||\n b.y > bounds.maxY\n ) {\n const closestX = clamp(b.x, bounds.minX, bounds.maxX)\n const closestY = clamp(b.y, bounds.minY, bounds.maxY)\n distances.push(distance(b, { x: closestX, y: closestY }))\n }\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance from a line segment to a box.\n */\nexport function segmentToBoxMinDistance(\n a: Point,\n b: Point,\n box: { center: Point; width: number; height: number },\n): number {\n const halfWidth = box.width / 2\n const halfHeight = box.height / 2\n const bounds = {\n minX: box.center.x - halfWidth,\n maxX: box.center.x + halfWidth,\n minY: box.center.y - halfHeight,\n maxY: box.center.y + halfHeight,\n }\n\n return segmentToBoundsMinDistance(a, b, bounds)\n}\n\n/**\n * Returns the minimum distance from a line segment to a circle.\n */\nexport function segmentToCircleMinDistance(\n a: Point,\n b: Point,\n circle: { x: number; y: number; radius: number },\n): number {\n // Calculate the distance from the circle center to the line segment\n const circleCenter = { x: circle.x, y: circle.y }\n\n // Handle degenerate case: segment of zero length (point to circle)\n if (a.x === b.x && a.y === b.y) {\n return Math.max(0, distance(a, circleCenter) - circle.radius)\n }\n\n // Vector from a to b\n const ab = { x: b.x - a.x, y: b.y - a.y }\n // Vector from a to circle center\n const ac = { x: circleCenter.x - a.x, y: circleCenter.y - a.y }\n\n // Length of segment ab squared\n const abLengthSq = ab.x * ab.x + ab.y * ab.y\n\n // Calculate projection of ac onto ab, normalized by the length of ab\n const t = Math.max(0, Math.min(1, (ab.x * ac.x + ab.y * ac.y) / abLengthSq))\n\n // Find the closest point on the segment to the circle center\n const closestPoint = {\n x: a.x + t * ab.x,\n y: a.y + t * ab.y,\n }\n\n // Calculate distance from closest point to circle center\n const distToCenter = distance(closestPoint, circleCenter)\n\n // Return the distance to the circle (subtract radius from distance to center)\n return Math.max(0, distToCenter - circle.radius)\n}\n\nexport function pointToSegmentClosestPoint(\n p: Point,\n a: Point,\n b: Point,\n): Point {\n const dx_ab = b.x - a.x\n const dy_ab = b.y - a.y\n const l2 = dx_ab * dx_ab + dy_ab * dy_ab\n\n if (l2 === 0) return { x: a.x, y: a.y } // Segment is a point\n\n // Project p onto the line defined by a, b\n // t = [(p - a) . (b - a)] / |b - a|^2\n let t = ((p.x - a.x) * dx_ab + (p.y - a.y) * dy_ab) / l2\n\n // Clamp t to the range [0, 1] to stay on the segment\n t = Math.max(0, Math.min(1, t))\n\n // Calculate the projection point\n const closestPoint = {\n x: a.x + t * dx_ab,\n y: a.y + t * dy_ab,\n }\n\n return closestPoint\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,5 +3,5 @@ export { Box, BoxSet, GridCell, clamp, computeDistanceBetweenBoxes, findNearestP
|
|
|
3
3
|
export { Bounds, Point } from './common.js';
|
|
4
4
|
export { getUnitVectorFromDirection, getUnitVectorFromPointAToB } from './get-unit-vector.js';
|
|
5
5
|
export { GridCellPositions, GridOptions, grid } from './grid.js';
|
|
6
|
-
export { segmentToBoundsMinDistance, segmentToBoxMinDistance, segmentToCircleMinDistance, segmentToSegmentMinDistance } from './segment-distance.js';
|
|
7
|
-
export { midpoint, pointToBoundsDistance, pointToBoxDistance } from './point-distance.js';
|
|
6
|
+
export { pointToSegmentClosestPoint, segmentToBoundsMinDistance, segmentToBoxMinDistance, segmentToCircleMinDistance, segmentToSegmentMinDistance } from './segment-distance.js';
|
|
7
|
+
export { distSq, midpoint, pointToBoundsDistance, pointToBoxDistance } from './point-distance.js';
|
package/dist/index.js
CHANGED
|
@@ -7,16 +7,18 @@ import {
|
|
|
7
7
|
grid
|
|
8
8
|
} from "./chunk-U45EKA3R.js";
|
|
9
9
|
import {
|
|
10
|
+
distSq,
|
|
10
11
|
midpoint,
|
|
11
12
|
pointToBoundsDistance,
|
|
12
13
|
pointToBoxDistance
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-572TQ3QB.js";
|
|
14
15
|
import {
|
|
16
|
+
pointToSegmentClosestPoint,
|
|
15
17
|
segmentToBoundsMinDistance,
|
|
16
18
|
segmentToBoxMinDistance,
|
|
17
19
|
segmentToCircleMinDistance,
|
|
18
20
|
segmentToSegmentMinDistance
|
|
19
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-RNQKFERU.js";
|
|
20
22
|
import {
|
|
21
23
|
distance,
|
|
22
24
|
doSegmentsIntersect,
|
|
@@ -34,6 +36,7 @@ import {
|
|
|
34
36
|
export {
|
|
35
37
|
clamp,
|
|
36
38
|
computeDistanceBetweenBoxes,
|
|
39
|
+
distSq,
|
|
37
40
|
distance,
|
|
38
41
|
doSegmentsIntersect,
|
|
39
42
|
doesLineIntersectLine,
|
|
@@ -47,6 +50,7 @@ export {
|
|
|
47
50
|
orientation,
|
|
48
51
|
pointToBoundsDistance,
|
|
49
52
|
pointToBoxDistance,
|
|
53
|
+
pointToSegmentClosestPoint,
|
|
50
54
|
pointToSegmentDistance,
|
|
51
55
|
segmentToBoundsMinDistance,
|
|
52
56
|
segmentToBoxMinDistance,
|
package/dist/point-distance.d.ts
CHANGED
|
@@ -12,5 +12,6 @@ declare function pointToBoxDistance(p: Point, box: Box): number;
|
|
|
12
12
|
*/
|
|
13
13
|
declare function pointToBoundsDistance(p: Point, bounds: Bounds): number;
|
|
14
14
|
declare function midpoint(p1: Point, p2: Point): Point;
|
|
15
|
+
declare function distSq(p1: Point, p2: Point): number;
|
|
15
16
|
|
|
16
|
-
export { midpoint, pointToBoundsDistance, pointToBoxDistance };
|
|
17
|
+
export { distSq, midpoint, pointToBoundsDistance, pointToBoxDistance };
|
package/dist/point-distance.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
distSq,
|
|
2
3
|
midpoint,
|
|
3
4
|
pointToBoundsDistance,
|
|
4
5
|
pointToBoxDistance
|
|
5
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-572TQ3QB.js";
|
|
6
7
|
import "./chunk-CHQOCSFB.js";
|
|
7
8
|
import "./chunk-MHHTZHOJ.js";
|
|
8
9
|
export {
|
|
10
|
+
distSq,
|
|
9
11
|
midpoint,
|
|
10
12
|
pointToBoundsDistance,
|
|
11
13
|
pointToBoxDistance
|
|
@@ -29,5 +29,6 @@ declare function segmentToCircleMinDistance(a: Point, b: Point, circle: {
|
|
|
29
29
|
y: number;
|
|
30
30
|
radius: number;
|
|
31
31
|
}): number;
|
|
32
|
+
declare function pointToSegmentClosestPoint(p: Point, a: Point, b: Point): Point;
|
|
32
33
|
|
|
33
|
-
export { segmentToBoundsMinDistance, segmentToBoxMinDistance, segmentToCircleMinDistance, segmentToSegmentMinDistance };
|
|
34
|
+
export { pointToSegmentClosestPoint, segmentToBoundsMinDistance, segmentToBoxMinDistance, segmentToCircleMinDistance, segmentToSegmentMinDistance };
|
package/dist/segment-distance.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
+
pointToSegmentClosestPoint,
|
|
2
3
|
segmentToBoundsMinDistance,
|
|
3
4
|
segmentToBoxMinDistance,
|
|
4
5
|
segmentToCircleMinDistance,
|
|
5
6
|
segmentToSegmentMinDistance
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-RNQKFERU.js";
|
|
7
8
|
import "./chunk-CHQOCSFB.js";
|
|
8
9
|
import "./chunk-MHHTZHOJ.js";
|
|
9
10
|
export {
|
|
11
|
+
pointToSegmentClosestPoint,
|
|
10
12
|
segmentToBoundsMinDistance,
|
|
11
13
|
segmentToBoxMinDistance,
|
|
12
14
|
segmentToCircleMinDistance,
|