@tscircuit/math-utils 0.0.19 → 0.0.21

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/README.md CHANGED
@@ -6,9 +6,11 @@ This repository contains a collection of TypeScript utility functions for geomet
6
6
 
7
7
  - Line intersection detection
8
8
  - Segment intersection detection
9
+ - Segment-rectangle intersection detection
9
10
  - Point-to-segment distance calculation
10
11
  - Orientation of points
11
12
  - Distance between points
13
+ - Bounds overlap and distance calculations
12
14
 
13
15
  ## Installation
14
16
 
@@ -39,29 +41,36 @@ console.log("Lines intersect:", intersects)
39
41
 
40
42
  ## API Reference
41
43
 
42
- ### `doesLineIntersectLine(line1: [Point, Point], line2: [Point, Point], options?: { lineThickness?: number }): boolean`
43
-
44
- Determines if two lines intersect, optionally considering line thickness.
45
-
46
- ### `doSegmentsIntersect(p1: Point, q1: Point, p2: Point, q2: Point): boolean`
47
-
48
- Checks if two line segments intersect.
49
-
50
- ### `orientation(p: Point, q: Point, r: Point): number`
51
-
52
- Calculates the orientation of three points.
53
-
54
- ### `onSegment(p: Point, q: Point, r: Point): boolean`
55
-
56
- Checks if point q lies on the segment p-r.
57
-
58
- ### `pointToSegmentDistance(p: Point, v: Point, w: Point): number`
59
-
60
- Calculates the minimum distance between a point and a line segment.
61
-
62
- ### `distance(p1: Point, p2: Point): number`
63
-
64
- Calculates the Euclidean distance between two points.
44
+ | Function | Description |
45
+ | -------- | ----------- |
46
+ | [`doesLineIntersectLine(line1, line2, options?)`](./src/line-intersections.ts) | Determine if two lines intersect, optionally considering line thickness. |
47
+ | [`doSegmentsIntersect(p1, q1, p2, q2)`](./src/line-intersections.ts) | Check if two line segments intersect. |
48
+ | [`doesSegmentIntersectRect(a, b, rect)`](./src/line-intersections.ts) | Check if a segment intersects an axis-aligned rectangle. |
49
+ | [`orientation(p, q, r)`](./src/line-intersections.ts) | Calculate the orientation of three points. |
50
+ | [`onSegment(p, q, r)`](./src/line-intersections.ts) | Determine if point `q` lies on the segment `p`–`r`. |
51
+ | [`pointToSegmentDistance(p, v, w)`](./src/line-intersections.ts) | Minimum distance between a point and a segment. |
52
+ | [`distance(p1, p2)`](./src/line-intersections.ts) | Euclidean distance between two points. |
53
+ | [`getSegmentIntersection(a, b, u, v)`](./src/line-intersections.ts) | Intersection point of two segments or `null` if none. |
54
+ | [`getBoundingBox(box)`](./src/nearest-box.ts) | Compute the bounding box of a box. |
55
+ | [`computeDistanceBetweenBoxes(boxA, boxB)`](./src/nearest-box.ts) | Minimum distance between two boxes and the nearest points. |
56
+ | [`clamp(value, min, max)`](./src/nearest-box.ts) | Clamp a value between `min` and `max`. |
57
+ | [`findNearestPointsBetweenBoxSets(setA, setB)`](./src/nearest-box.ts) | Find nearest points between two sets of boxes. |
58
+ | [`getUnitVectorFromPointAToB(a, b)`](./src/get-unit-vector.ts) | Unit vector pointing from point A to B. |
59
+ | [`getUnitVectorFromDirection(direction)`](./src/get-unit-vector.ts) | Unit vector for the given cardinal direction. |
60
+ | [`grid(options)`](./src/grid.ts) | Generate grid cell positions with spacing and offsets. |
61
+ | [`segmentToSegmentMinDistance(a, b, u, v)`](./src/segment-distance.ts) | Minimum distance between two line segments. |
62
+ | [`segmentToBoundsMinDistance(a, b, bounds)`](./src/segment-distance.ts) | Minimum distance from a segment to a bounds rectangle. |
63
+ | [`segmentToBoxMinDistance(a, b, box)`](./src/segment-distance.ts) | Minimum distance from a segment to a box. |
64
+ | [`segmentToCircleMinDistance(a, b, circle)`](./src/segment-distance.ts) | Minimum distance from a segment to a circle. |
65
+ | [`pointToSegmentClosestPoint(p, a, b)`](./src/segment-distance.ts) | Closest point on a segment to the given point. |
66
+ | [`pointToBoxDistance(p, box)`](./src/point-distance.ts) | Minimum distance from a point to a box. |
67
+ | [`pointToBoundsDistance(p, bounds)`](./src/point-distance.ts) | Minimum distance from a point to a bounds rectangle. |
68
+ | [`midpoint(p1, p2)`](./src/point-distance.ts) | Midpoint between two points. |
69
+ | [`distSq(p1, p2)`](./src/point-distance.ts) | Squared distance between two points. |
70
+ | [`range(start, end?, step?)`](./src/range.ts) | Create an array of numbers progressing from start up to, but not including, end. |
71
+ | [`doBoundsOverlap(bounds1, bounds2)`](./src/bounds-overlap.ts) | Determine if two bounding rectangles overlap. |
72
+ | [`boundsAreaOverlap(bounds1, bounds2)`](./src/bounds-area-overlap.ts) | Area of overlap between two bounding rectangles. |
73
+ | [`boundsDistance(bounds1, bounds2)`](./src/bounds-distance.ts) | Minimum distance between two bounding rectangles. |
65
74
 
66
75
  ## Contributing
67
76
 
@@ -0,0 +1,11 @@
1
+ import { Bounds } from './common.js';
2
+
3
+ /**
4
+ * Computes the overlapping area between two bounding rectangles
5
+ * @param bounds1 First bounding rectangle
6
+ * @param bounds2 Second bounding rectangle
7
+ * @returns The area of overlap. Returns 0 if the bounds do not overlap
8
+ */
9
+ declare const boundsAreaOverlap: (bounds1: Bounds, bounds2: Bounds) => number;
10
+
11
+ export { boundsAreaOverlap };
@@ -0,0 +1,7 @@
1
+ import {
2
+ boundsAreaOverlap
3
+ } from "./chunk-YA3GC5BB.js";
4
+ export {
5
+ boundsAreaOverlap
6
+ };
7
+ //# sourceMappingURL=bounds-area-overlap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,11 @@
1
+ import { Bounds } from './common.js';
2
+
3
+ /**
4
+ * Computes the minimum distance between two bounding rectangles
5
+ * @param bounds1 First bounding rectangle
6
+ * @param bounds2 Second bounding rectangle
7
+ * @returns The minimum distance. Returns 0 if the bounds overlap or touch
8
+ */
9
+ declare const boundsDistance: (bounds1: Bounds, bounds2: Bounds) => number;
10
+
11
+ export { boundsDistance };
@@ -0,0 +1,7 @@
1
+ import {
2
+ boundsDistance
3
+ } from "./chunk-KVGAXIWH.js";
4
+ export {
5
+ boundsDistance
6
+ };
7
+ //# sourceMappingURL=bounds-distance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,11 @@
1
+ import { Bounds } from './common.js';
2
+
3
+ /**
4
+ * Determines if two bounding rectangles overlap
5
+ * @param bounds1 First bounding rectangle
6
+ * @param bounds2 Second bounding rectangle
7
+ * @returns true if the bounds overlap, false otherwise
8
+ */
9
+ declare const doBoundsOverlap: (bounds1: Bounds, bounds2: Bounds) => boolean;
10
+
11
+ export { doBoundsOverlap };
@@ -0,0 +1,7 @@
1
+ import {
2
+ doBoundsOverlap
3
+ } from "./chunk-CA5ORSO4.js";
4
+ export {
5
+ doBoundsOverlap
6
+ };
7
+ //# sourceMappingURL=bounds-overlap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,9 @@
1
+ // src/bounds-overlap.ts
2
+ var doBoundsOverlap = (bounds1, bounds2) => {
3
+ return !(bounds1.maxX < bounds2.minX || bounds2.maxX < bounds1.minX || bounds1.maxY < bounds2.minY || bounds2.maxY < bounds1.minY);
4
+ };
5
+
6
+ export {
7
+ doBoundsOverlap
8
+ };
9
+ //# sourceMappingURL=chunk-CA5ORSO4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bounds-overlap.ts"],"sourcesContent":["import type { Bounds } from \"./common\"\n\n/**\n * Determines if two bounding rectangles overlap\n * @param bounds1 First bounding rectangle\n * @param bounds2 Second bounding rectangle\n * @returns true if the bounds overlap, false otherwise\n */\nexport const doBoundsOverlap = (bounds1: Bounds, bounds2: Bounds): boolean => {\n return !(\n bounds1.maxX < bounds2.minX ||\n bounds2.maxX < bounds1.minX ||\n bounds1.maxY < bounds2.minY ||\n bounds2.maxY < bounds1.minY\n )\n}\n"],"mappings":";AAQO,IAAM,kBAAkB,CAAC,SAAiB,YAA6B;AAC5E,SAAO,EACL,QAAQ,OAAO,QAAQ,QACvB,QAAQ,OAAO,QAAQ,QACvB,QAAQ,OAAO,QAAQ,QACvB,QAAQ,OAAO,QAAQ;AAE3B;","names":[]}
@@ -85,6 +85,17 @@ function getSegmentIntersection(a, b, u, v) {
85
85
  }
86
86
  return null;
87
87
  }
88
+ function doesSegmentIntersectRect(a, b, rect) {
89
+ const pointInside = (p) => p.x >= rect.minX && p.x <= rect.maxX && p.y >= rect.minY && p.y <= rect.maxY;
90
+ if (pointInside(a) || pointInside(b)) {
91
+ return true;
92
+ }
93
+ const topLeft = { x: rect.minX, y: rect.minY };
94
+ const topRight = { x: rect.maxX, y: rect.minY };
95
+ const bottomLeft = { x: rect.minX, y: rect.maxY };
96
+ const bottomRight = { x: rect.maxX, y: rect.maxY };
97
+ return doSegmentsIntersect(a, b, topLeft, topRight) || doSegmentsIntersect(a, b, topRight, bottomRight) || doSegmentsIntersect(a, b, bottomRight, bottomLeft) || doSegmentsIntersect(a, b, bottomLeft, topLeft);
98
+ }
88
99
 
89
100
  export {
90
101
  doesLineIntersectLine,
@@ -93,6 +104,7 @@ export {
93
104
  onSegment,
94
105
  pointToSegmentDistance,
95
106
  distance,
96
- getSegmentIntersection
107
+ getSegmentIntersection,
108
+ doesSegmentIntersectRect
97
109
  };
98
- //# sourceMappingURL=chunk-3453HRP7.js.map
110
+ //# sourceMappingURL=chunk-EFLPMB4J.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/line-intersections.ts"],"sourcesContent":["import type { Point } from \"./common\"\n\n/**\n * Returns true if the two lines intersect.\n */\nexport function doesLineIntersectLine(\n [a1, a2]: [Point, Point],\n [b1, b2]: [Point, Point],\n {\n lineThickness = 0,\n }: {\n lineThickness?: number\n } = {},\n): boolean {\n if (lineThickness === 0) {\n return doSegmentsIntersect(a1, a2, b1, b2)\n }\n const minDist = segmentsDistance(a1, a2, b1, b2)\n return minDist <= lineThickness\n}\n\n/**\n * Returns true if the two segments intersect.\n */\nexport function doSegmentsIntersect(\n p1: Point,\n q1: Point,\n p2: Point,\n q2: Point,\n): boolean {\n const o1 = orientation(p1, q1, p2)\n const o2 = orientation(p1, q1, q2)\n const o3 = orientation(p2, q2, p1)\n const o4 = orientation(p2, q2, q1)\n\n // General case\n if (o1 !== o2 && o3 !== o4) {\n return true\n }\n\n // Special Cases\n if (o1 === 0 && onSegment(p1, p2, q1)) return true\n if (o2 === 0 && onSegment(p1, q2, q1)) return true\n if (o3 === 0 && onSegment(p2, p1, q2)) return true\n if (o4 === 0 && onSegment(p2, q1, q2)) return true\n\n return false\n}\n\n/**\n * Returns 0 if the points are colinear, 1 if they are clockwise, and 2 if they are counterclockwise.\n */\nexport function orientation(p: Point, q: Point, r: Point): number {\n const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)\n if (val === 0) return 0 // colinear\n return val > 0 ? 1 : 2 // clock or counterclock wise\n}\n\n/**\n * Returns true if q is on the segment p->r.\n */\nexport function onSegment(p: Point, q: Point, r: Point): boolean {\n return (\n q.x <= Math.max(p.x, r.x) &&\n q.x >= Math.min(p.x, r.x) &&\n q.y <= Math.max(p.y, r.y) &&\n q.y >= Math.min(p.y, r.y)\n )\n}\n\n/**\n * Returns the minimum distance between two segments.\n */\nfunction segmentsDistance(a1: Point, a2: Point, b1: Point, b2: Point): number {\n // Handle degenerate cases: segments of zero length\n if (a1.x === a2.x && a1.y === a2.y) {\n return pointToSegmentDistance(a1, b1, b2)\n }\n if (b1.x === b2.x && b1.y === b2.y) {\n return pointToSegmentDistance(b1, a1, a2)\n }\n\n // Check if segments intersect\n if (doSegmentsIntersect(a1, a2, b1, b2)) {\n return 0\n }\n\n // Compute the minimum distance between the segments\n const distances = [\n pointToSegmentDistance(a1, b1, b2),\n pointToSegmentDistance(a2, b1, b2),\n pointToSegmentDistance(b1, a1, a2),\n pointToSegmentDistance(b2, a1, a2),\n ]\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance between a point and a segment.\n */\nexport function pointToSegmentDistance(p: Point, v: Point, w: Point): number {\n const l2 = (w.x - v.x) ** 2 + (w.y - v.y) ** 2\n if (l2 === 0) return distance(p, v)\n\n let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2\n t = Math.max(0, Math.min(1, t))\n\n const projection = {\n x: v.x + t * (w.x - v.x),\n y: v.y + t * (w.y - v.y),\n }\n\n return distance(p, projection)\n}\n\n/**\n * Returns the distance between two points.\n */\nexport function distance(p1: Point, p2: Point): number {\n const dx = p1.x - p2.x\n const dy = p1.y - p2.y\n return Math.sqrt(dx * dx + dy * dy)\n}\n\n/**\n * Calculates the intersection point of two line segments.\n * Returns the intersection point {x, y} if the segments intersect, otherwise returns null.\n */\nexport function getSegmentIntersection(\n a: Point,\n b: Point,\n u: Point,\n v: Point,\n): Point | null {\n const dx1 = b.x - a.x\n const dy1 = b.y - a.y\n const dx2 = v.x - u.x\n const dy2 = v.y - u.y\n const dx3 = a.x - u.x\n const dy3 = a.y - u.y\n\n const denominator = dx1 * dy2 - dy1 * dx2\n\n // Check if lines are parallel or collinear\n if (Math.abs(denominator) < 1e-10) {\n // Lines are parallel or collinear\n // We could add checks for collinear overlapping segments if needed,\n // but for now, we return null as a single intersection point doesn't exist.\n // The doSegmentsIntersect function handles collinearity checks if only a boolean is needed.\n return null\n }\n\n // Correct formula for t (parameter for segment ab)\n // t = (dy3 * dx2 - dx3 * dy2) / denominator\n // The formula previously used was -(dy3 * dx2 - dx3 * dy2) / denominator\n const t = (dy3 * dx2 - dx3 * dy2) / denominator\n // Correct formula for s (parameter for segment uv)\n // s = (dx1 * dy3 - dy1 * dx3) / denominator\n // The formula previously used was incorrect.\n const s = (dx1 * dy3 - dy1 * dx3) / denominator\n\n // Check if the intersection point lies within both segments\n // Use a small epsilon for floating point comparisons near 0 and 1\n const epsilon = 1e-9\n if (t >= -epsilon && t <= 1 + epsilon && s >= -epsilon && s <= 1 + epsilon) {\n const intersectionX = a.x + t * dx1\n const intersectionY = a.y + t * dy1\n return { x: intersectionX, y: intersectionY }\n }\n\n // Segments do not intersect within their bounds\n return null\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/line-intersections.ts"],"sourcesContent":["import type { Point } from \"./common\"\n\n/**\n * Returns true if the two lines intersect.\n */\nexport function doesLineIntersectLine(\n [a1, a2]: [Point, Point],\n [b1, b2]: [Point, Point],\n {\n lineThickness = 0,\n }: {\n lineThickness?: number\n } = {},\n): boolean {\n if (lineThickness === 0) {\n return doSegmentsIntersect(a1, a2, b1, b2)\n }\n const minDist = segmentsDistance(a1, a2, b1, b2)\n return minDist <= lineThickness\n}\n\n/**\n * Returns true if the two segments intersect.\n */\nexport function doSegmentsIntersect(\n p1: Point,\n q1: Point,\n p2: Point,\n q2: Point,\n): boolean {\n const o1 = orientation(p1, q1, p2)\n const o2 = orientation(p1, q1, q2)\n const o3 = orientation(p2, q2, p1)\n const o4 = orientation(p2, q2, q1)\n\n // General case\n if (o1 !== o2 && o3 !== o4) {\n return true\n }\n\n // Special Cases\n if (o1 === 0 && onSegment(p1, p2, q1)) return true\n if (o2 === 0 && onSegment(p1, q2, q1)) return true\n if (o3 === 0 && onSegment(p2, p1, q2)) return true\n if (o4 === 0 && onSegment(p2, q1, q2)) return true\n\n return false\n}\n\n/**\n * Returns 0 if the points are colinear, 1 if they are clockwise, and 2 if they are counterclockwise.\n */\nexport function orientation(p: Point, q: Point, r: Point): number {\n const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y)\n if (val === 0) return 0 // colinear\n return val > 0 ? 1 : 2 // clock or counterclock wise\n}\n\n/**\n * Returns true if q is on the segment p->r.\n */\nexport function onSegment(p: Point, q: Point, r: Point): boolean {\n return (\n q.x <= Math.max(p.x, r.x) &&\n q.x >= Math.min(p.x, r.x) &&\n q.y <= Math.max(p.y, r.y) &&\n q.y >= Math.min(p.y, r.y)\n )\n}\n\n/**\n * Returns the minimum distance between two segments.\n */\nfunction segmentsDistance(a1: Point, a2: Point, b1: Point, b2: Point): number {\n // Handle degenerate cases: segments of zero length\n if (a1.x === a2.x && a1.y === a2.y) {\n return pointToSegmentDistance(a1, b1, b2)\n }\n if (b1.x === b2.x && b1.y === b2.y) {\n return pointToSegmentDistance(b1, a1, a2)\n }\n\n // Check if segments intersect\n if (doSegmentsIntersect(a1, a2, b1, b2)) {\n return 0\n }\n\n // Compute the minimum distance between the segments\n const distances = [\n pointToSegmentDistance(a1, b1, b2),\n pointToSegmentDistance(a2, b1, b2),\n pointToSegmentDistance(b1, a1, a2),\n pointToSegmentDistance(b2, a1, a2),\n ]\n\n return Math.min(...distances)\n}\n\n/**\n * Returns the minimum distance between a point and a segment.\n */\nexport function pointToSegmentDistance(p: Point, v: Point, w: Point): number {\n const l2 = (w.x - v.x) ** 2 + (w.y - v.y) ** 2\n if (l2 === 0) return distance(p, v)\n\n let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2\n t = Math.max(0, Math.min(1, t))\n\n const projection = {\n x: v.x + t * (w.x - v.x),\n y: v.y + t * (w.y - v.y),\n }\n\n return distance(p, projection)\n}\n\n/**\n * Returns the distance between two points.\n */\nexport function distance(p1: Point, p2: Point): number {\n const dx = p1.x - p2.x\n const dy = p1.y - p2.y\n return Math.sqrt(dx * dx + dy * dy)\n}\n\n/**\n * Calculates the intersection point of two line segments.\n * Returns the intersection point {x, y} if the segments intersect, otherwise returns null.\n */\nexport function getSegmentIntersection(\n a: Point,\n b: Point,\n u: Point,\n v: Point,\n): Point | null {\n const dx1 = b.x - a.x\n const dy1 = b.y - a.y\n const dx2 = v.x - u.x\n const dy2 = v.y - u.y\n const dx3 = a.x - u.x\n const dy3 = a.y - u.y\n\n const denominator = dx1 * dy2 - dy1 * dx2\n\n // Check if lines are parallel or collinear\n if (Math.abs(denominator) < 1e-10) {\n // Lines are parallel or collinear\n // We could add checks for collinear overlapping segments if needed,\n // but for now, we return null as a single intersection point doesn't exist.\n // The doSegmentsIntersect function handles collinearity checks if only a boolean is needed.\n return null\n }\n\n // Correct formula for t (parameter for segment ab)\n // t = (dy3 * dx2 - dx3 * dy2) / denominator\n // The formula previously used was -(dy3 * dx2 - dx3 * dy2) / denominator\n const t = (dy3 * dx2 - dx3 * dy2) / denominator\n // Correct formula for s (parameter for segment uv)\n // s = (dx1 * dy3 - dy1 * dx3) / denominator\n // The formula previously used was incorrect.\n const s = (dx1 * dy3 - dy1 * dx3) / denominator\n\n // Check if the intersection point lies within both segments\n // Use a small epsilon for floating point comparisons near 0 and 1\n const epsilon = 1e-9\n if (t >= -epsilon && t <= 1 + epsilon && s >= -epsilon && s <= 1 + epsilon) {\n const intersectionX = a.x + t * dx1\n const intersectionY = a.y + t * dy1\n return { x: intersectionX, y: intersectionY }\n }\n\n // Segments do not intersect within their bounds\n return null\n}\n\nexport function doesSegmentIntersectRect(\n a: Point,\n b: Point,\n rect: { minX: number; minY: number; maxX: number; maxY: number },\n): boolean {\n const pointInside = (p: Point) =>\n p.x >= rect.minX && p.x <= rect.maxX && p.y >= rect.minY && p.y <= rect.maxY\n\n if (pointInside(a) || pointInside(b)) {\n return true\n }\n\n const topLeft = { x: rect.minX, y: rect.minY }\n const topRight = { x: rect.maxX, y: rect.minY }\n const bottomLeft = { x: rect.minX, y: rect.maxY }\n const bottomRight = { x: rect.maxX, y: rect.maxY }\n\n return (\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}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,9 @@
1
- import {
2
- distance
3
- } from "./chunk-3453HRP7.js";
4
1
  import {
5
2
  clamp
6
3
  } from "./chunk-MHHTZHOJ.js";
4
+ import {
5
+ distance
6
+ } from "./chunk-EFLPMB4J.js";
7
7
 
8
8
  // src/point-distance.ts
9
9
  function pointToBoxDistance(p, box) {
@@ -46,4 +46,4 @@ export {
46
46
  midpoint,
47
47
  distSq
48
48
  };
49
- //# sourceMappingURL=chunk-SLG2OU3P.js.map
49
+ //# sourceMappingURL=chunk-KJEUHNRF.js.map
@@ -0,0 +1,11 @@
1
+ // src/bounds-distance.ts
2
+ var boundsDistance = (bounds1, bounds2) => {
3
+ const dx = bounds1.maxX < bounds2.minX ? bounds2.minX - bounds1.maxX : bounds2.maxX < bounds1.minX ? bounds1.minX - bounds2.maxX : 0;
4
+ const dy = bounds1.maxY < bounds2.minY ? bounds2.minY - bounds1.maxY : bounds2.maxY < bounds1.minY ? bounds1.minY - bounds2.maxY : 0;
5
+ return Math.sqrt(dx * dx + dy * dy);
6
+ };
7
+
8
+ export {
9
+ boundsDistance
10
+ };
11
+ //# sourceMappingURL=chunk-KVGAXIWH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bounds-distance.ts"],"sourcesContent":["import type { Bounds } from \"./common\"\n\n/**\n * Computes the minimum distance between two bounding rectangles\n * @param bounds1 First bounding rectangle\n * @param bounds2 Second bounding rectangle\n * @returns The minimum distance. Returns 0 if the bounds overlap or touch\n */\nexport const boundsDistance = (bounds1: Bounds, bounds2: Bounds): number => {\n const dx =\n bounds1.maxX < bounds2.minX\n ? bounds2.minX - bounds1.maxX\n : bounds2.maxX < bounds1.minX\n ? bounds1.minX - bounds2.maxX\n : 0\n\n const dy =\n bounds1.maxY < bounds2.minY\n ? bounds2.minY - bounds1.maxY\n : bounds2.maxY < bounds1.minY\n ? bounds1.minY - bounds2.maxY\n : 0\n\n return Math.sqrt(dx * dx + dy * dy)\n}\n"],"mappings":";AAQO,IAAM,iBAAiB,CAAC,SAAiB,YAA4B;AAC1E,QAAM,KACJ,QAAQ,OAAO,QAAQ,OACnB,QAAQ,OAAO,QAAQ,OACvB,QAAQ,OAAO,QAAQ,OACrB,QAAQ,OAAO,QAAQ,OACvB;AAER,QAAM,KACJ,QAAQ,OAAO,QAAQ,OACnB,QAAQ,OAAO,QAAQ,OACvB,QAAQ,OAAO,QAAQ,OACrB,QAAQ,OAAO,QAAQ,OACvB;AAER,SAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACpC;","names":[]}
@@ -0,0 +1,29 @@
1
+ // src/range.ts
2
+ function range(start, end, step = 1) {
3
+ if (step === 0) throw new Error("step cannot be 0");
4
+ let _start;
5
+ let _end;
6
+ if (end === void 0) {
7
+ _start = 0;
8
+ _end = start;
9
+ } else {
10
+ _start = start;
11
+ _end = end;
12
+ }
13
+ const result = [];
14
+ if (step > 0) {
15
+ for (let i = _start; i < _end; i += step) {
16
+ result.push(i);
17
+ }
18
+ } else {
19
+ for (let i = _start; i > _end; i += step) {
20
+ result.push(i);
21
+ }
22
+ }
23
+ return result;
24
+ }
25
+
26
+ export {
27
+ range
28
+ };
29
+ //# sourceMappingURL=chunk-KY53E6CT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/range.ts"],"sourcesContent":["export function range(start: number, end?: number, step = 1): number[] {\n if (step === 0) throw new Error(\"step cannot be 0\")\n let _start: number\n let _end: number\n\n if (end === undefined) {\n _start = 0\n _end = start\n } else {\n _start = start\n _end = end\n }\n\n const result: number[] = []\n\n if (step > 0) {\n for (let i = _start; i < _end; i += step) {\n result.push(i)\n }\n } else {\n for (let i = _start; i > _end; i += step) {\n result.push(i)\n }\n }\n return result\n}\n"],"mappings":";AAAO,SAAS,MAAM,OAAe,KAAc,OAAO,GAAa;AACrE,MAAI,SAAS,EAAG,OAAM,IAAI,MAAM,kBAAkB;AAClD,MAAI;AACJ,MAAI;AAEJ,MAAI,QAAQ,QAAW;AACrB,aAAS;AACT,WAAO;AAAA,EACT,OAAO;AACL,aAAS;AACT,WAAO;AAAA,EACT;AAEA,QAAM,SAAmB,CAAC;AAE1B,MAAI,OAAO,GAAG;AACZ,aAAS,IAAI,QAAQ,IAAI,MAAM,KAAK,MAAM;AACxC,aAAO,KAAK,CAAC;AAAA,IACf;AAAA,EACF,OAAO;AACL,aAAS,IAAI,QAAQ,IAAI,MAAM,KAAK,MAAM;AACxC,aAAO,KAAK,CAAC;AAAA,IACf;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
@@ -1,11 +1,11 @@
1
+ import {
2
+ clamp
3
+ } from "./chunk-MHHTZHOJ.js";
1
4
  import {
2
5
  distance,
3
6
  doSegmentsIntersect,
4
7
  pointToSegmentDistance
5
- } from "./chunk-3453HRP7.js";
6
- import {
7
- clamp
8
- } from "./chunk-MHHTZHOJ.js";
8
+ } from "./chunk-EFLPMB4J.js";
9
9
 
10
10
  // src/segment-distance.ts
11
11
  function segmentToSegmentMinDistance(a, b, u, v) {
@@ -109,4 +109,4 @@ export {
109
109
  segmentToCircleMinDistance,
110
110
  pointToSegmentClosestPoint
111
111
  };
112
- //# sourceMappingURL=chunk-FWQGMQBW.js.map
112
+ //# sourceMappingURL=chunk-OONG4FBI.js.map
@@ -0,0 +1,17 @@
1
+ // src/bounds-area-overlap.ts
2
+ var boundsAreaOverlap = (bounds1, bounds2) => {
3
+ const overlapX = Math.max(
4
+ 0,
5
+ Math.min(bounds1.maxX, bounds2.maxX) - Math.max(bounds1.minX, bounds2.minX)
6
+ );
7
+ const overlapY = Math.max(
8
+ 0,
9
+ Math.min(bounds1.maxY, bounds2.maxY) - Math.max(bounds1.minY, bounds2.minY)
10
+ );
11
+ return overlapX * overlapY;
12
+ };
13
+
14
+ export {
15
+ boundsAreaOverlap
16
+ };
17
+ //# sourceMappingURL=chunk-YA3GC5BB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/bounds-area-overlap.ts"],"sourcesContent":["import type { Bounds } from \"./common\"\n\n/**\n * Computes the overlapping area between two bounding rectangles\n * @param bounds1 First bounding rectangle\n * @param bounds2 Second bounding rectangle\n * @returns The area of overlap. Returns 0 if the bounds do not overlap\n */\nexport const boundsAreaOverlap = (bounds1: Bounds, bounds2: Bounds): number => {\n const overlapX = Math.max(\n 0,\n Math.min(bounds1.maxX, bounds2.maxX) - Math.max(bounds1.minX, bounds2.minX),\n )\n const overlapY = Math.max(\n 0,\n Math.min(bounds1.maxY, bounds2.maxY) - Math.max(bounds1.minY, bounds2.minY),\n )\n return overlapX * overlapY\n}\n"],"mappings":";AAQO,IAAM,oBAAoB,CAAC,SAAiB,YAA4B;AAC7E,QAAM,WAAW,KAAK;AAAA,IACpB;AAAA,IACA,KAAK,IAAI,QAAQ,MAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,QAAQ,MAAM,QAAQ,IAAI;AAAA,EAC5E;AACA,QAAM,WAAW,KAAK;AAAA,IACpB;AAAA,IACA,KAAK,IAAI,QAAQ,MAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,QAAQ,MAAM,QAAQ,IAAI;AAAA,EAC5E;AACA,SAAO,WAAW;AACpB;","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { distance, doSegmentsIntersect, doesLineIntersectLine, getSegmentIntersection, onSegment, orientation, pointToSegmentDistance } from './line-intersections.js';
1
+ export { distance, doSegmentsIntersect, doesLineIntersectLine, doesSegmentIntersectRect, getSegmentIntersection, onSegment, orientation, pointToSegmentDistance } from './line-intersections.js';
2
2
  export { Box, BoxSet, GridCell, clamp, computeDistanceBetweenBoxes, findNearestPointsBetweenBoxSets, getBoundingBox } from './nearest-box.js';
3
3
  export { Bounds, Point } from './common.js';
4
4
  export { getUnitVectorFromDirection, getUnitVectorFromPointAToB } from './get-unit-vector.js';
@@ -6,3 +6,7 @@ export { GridCellPositions, GridOptions, grid } from './grid.js';
6
6
  export { pointToSegmentClosestPoint, segmentToBoundsMinDistance, segmentToBoxMinDistance, segmentToCircleMinDistance, segmentToSegmentMinDistance } from './segment-distance.js';
7
7
  export { distSq, midpoint, pointToBoundsDistance, pointToBoxDistance } from './point-distance.js';
8
8
  export { Point3 } from './point3.js';
9
+ export { range } from './range.js';
10
+ export { doBoundsOverlap } from './bounds-overlap.js';
11
+ export { boundsAreaOverlap } from './bounds-area-overlap.js';
12
+ export { boundsDistance } from './bounds-distance.js';
package/dist/index.js CHANGED
@@ -1,10 +1,35 @@
1
+ import {
2
+ distSq,
3
+ midpoint,
4
+ pointToBoundsDistance,
5
+ pointToBoxDistance
6
+ } from "./chunk-KJEUHNRF.js";
7
+ import "./chunk-MTORG67J.js";
8
+ import {
9
+ range
10
+ } from "./chunk-KY53E6CT.js";
1
11
  import {
2
12
  pointToSegmentClosestPoint,
3
13
  segmentToBoundsMinDistance,
4
14
  segmentToBoxMinDistance,
5
15
  segmentToCircleMinDistance,
6
16
  segmentToSegmentMinDistance
7
- } from "./chunk-FWQGMQBW.js";
17
+ } from "./chunk-OONG4FBI.js";
18
+ import {
19
+ clamp,
20
+ computeDistanceBetweenBoxes,
21
+ findNearestPointsBetweenBoxSets,
22
+ getBoundingBox
23
+ } from "./chunk-MHHTZHOJ.js";
24
+ import {
25
+ boundsAreaOverlap
26
+ } from "./chunk-YA3GC5BB.js";
27
+ import {
28
+ boundsDistance
29
+ } from "./chunk-KVGAXIWH.js";
30
+ import {
31
+ doBoundsOverlap
32
+ } from "./chunk-CA5ORSO4.js";
8
33
  import "./chunk-GYQ2KZV6.js";
9
34
  import {
10
35
  getUnitVectorFromDirection,
@@ -13,35 +38,27 @@ import {
13
38
  import {
14
39
  grid
15
40
  } from "./chunk-U45EKA3R.js";
16
- import {
17
- distSq,
18
- midpoint,
19
- pointToBoundsDistance,
20
- pointToBoxDistance
21
- } from "./chunk-SLG2OU3P.js";
22
41
  import {
23
42
  distance,
24
43
  doSegmentsIntersect,
25
44
  doesLineIntersectLine,
45
+ doesSegmentIntersectRect,
26
46
  getSegmentIntersection,
27
47
  onSegment,
28
48
  orientation,
29
49
  pointToSegmentDistance
30
- } from "./chunk-3453HRP7.js";
31
- import {
32
- clamp,
33
- computeDistanceBetweenBoxes,
34
- findNearestPointsBetweenBoxSets,
35
- getBoundingBox
36
- } from "./chunk-MHHTZHOJ.js";
37
- import "./chunk-MTORG67J.js";
50
+ } from "./chunk-EFLPMB4J.js";
38
51
  export {
52
+ boundsAreaOverlap,
53
+ boundsDistance,
39
54
  clamp,
40
55
  computeDistanceBetweenBoxes,
41
56
  distSq,
42
57
  distance,
58
+ doBoundsOverlap,
43
59
  doSegmentsIntersect,
44
60
  doesLineIntersectLine,
61
+ doesSegmentIntersectRect,
45
62
  findNearestPointsBetweenBoxSets,
46
63
  getBoundingBox,
47
64
  getSegmentIntersection,
@@ -55,6 +72,7 @@ export {
55
72
  pointToBoxDistance,
56
73
  pointToSegmentClosestPoint,
57
74
  pointToSegmentDistance,
75
+ range,
58
76
  segmentToBoundsMinDistance,
59
77
  segmentToBoxMinDistance,
60
78
  segmentToCircleMinDistance,
@@ -31,5 +31,11 @@ declare function distance(p1: Point, p2: Point): number;
31
31
  * Returns the intersection point {x, y} if the segments intersect, otherwise returns null.
32
32
  */
33
33
  declare function getSegmentIntersection(a: Point, b: Point, u: Point, v: Point): Point | null;
34
+ declare function doesSegmentIntersectRect(a: Point, b: Point, rect: {
35
+ minX: number;
36
+ minY: number;
37
+ maxX: number;
38
+ maxY: number;
39
+ }): boolean;
34
40
 
35
- export { distance, doSegmentsIntersect, doesLineIntersectLine, getSegmentIntersection, onSegment, orientation, pointToSegmentDistance };
41
+ export { distance, doSegmentsIntersect, doesLineIntersectLine, doesSegmentIntersectRect, getSegmentIntersection, onSegment, orientation, pointToSegmentDistance };
@@ -2,15 +2,17 @@ import {
2
2
  distance,
3
3
  doSegmentsIntersect,
4
4
  doesLineIntersectLine,
5
+ doesSegmentIntersectRect,
5
6
  getSegmentIntersection,
6
7
  onSegment,
7
8
  orientation,
8
9
  pointToSegmentDistance
9
- } from "./chunk-3453HRP7.js";
10
+ } from "./chunk-EFLPMB4J.js";
10
11
  export {
11
12
  distance,
12
13
  doSegmentsIntersect,
13
14
  doesLineIntersectLine,
15
+ doesSegmentIntersectRect,
14
16
  getSegmentIntersection,
15
17
  onSegment,
16
18
  orientation,
@@ -3,9 +3,9 @@ import {
3
3
  midpoint,
4
4
  pointToBoundsDistance,
5
5
  pointToBoxDistance
6
- } from "./chunk-SLG2OU3P.js";
7
- import "./chunk-3453HRP7.js";
6
+ } from "./chunk-KJEUHNRF.js";
8
7
  import "./chunk-MHHTZHOJ.js";
8
+ import "./chunk-EFLPMB4J.js";
9
9
  export {
10
10
  distSq,
11
11
  midpoint,
@@ -0,0 +1,3 @@
1
+ declare function range(start: number, end?: number, step?: number): number[];
2
+
3
+ export { range };
package/dist/range.js ADDED
@@ -0,0 +1,7 @@
1
+ import {
2
+ range
3
+ } from "./chunk-KY53E6CT.js";
4
+ export {
5
+ range
6
+ };
7
+ //# sourceMappingURL=range.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -4,9 +4,9 @@ import {
4
4
  segmentToBoxMinDistance,
5
5
  segmentToCircleMinDistance,
6
6
  segmentToSegmentMinDistance
7
- } from "./chunk-FWQGMQBW.js";
8
- import "./chunk-3453HRP7.js";
7
+ } from "./chunk-OONG4FBI.js";
9
8
  import "./chunk-MHHTZHOJ.js";
9
+ import "./chunk-EFLPMB4J.js";
10
10
  export {
11
11
  pointToSegmentClosestPoint,
12
12
  segmentToBoundsMinDistance,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tscircuit/math-utils",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.19",
4
+ "version": "0.0.21",
5
5
  "type": "module",
6
6
  "module": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -23,11 +23,13 @@
23
23
  "dist"
24
24
  ],
25
25
  "scripts": {
26
- "build": "tsup-node src --format esm --dts --sourcemap"
26
+ "build": "tsup-node src --format esm --dts --sourcemap",
27
+ "format": "biome format . --write",
28
+ "format:check": "biome format . --check"
27
29
  },
28
30
  "devDependencies": {
29
31
  "@biomejs/biome": "^1.9.4",
30
- "@types/bun": "latest",
32
+ "@types/bun": "^1.2.18",
31
33
  "tsup": "^8.2.4"
32
34
  },
33
35
  "peerDependencies": {