@tscircuit/math-utils 0.0.8 → 0.0.10
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-CHQOCSFB.js +76 -0
- package/dist/chunk-CHQOCSFB.js.map +1 -0
- package/dist/chunk-GIGMPRPV.js +30 -0
- package/dist/chunk-GIGMPRPV.js.map +1 -0
- package/dist/chunk-GYQ2KZV6.js +1 -0
- package/dist/chunk-GYQ2KZV6.js.map +1 -0
- package/dist/chunk-MHHTZHOJ.js +62 -0
- package/dist/chunk-MHHTZHOJ.js.map +1 -0
- package/dist/chunk-U45EKA3R.js +51 -0
- package/dist/chunk-U45EKA3R.js.map +1 -0
- package/dist/common.d.ts +6 -0
- package/dist/common.js +2 -0
- package/dist/common.js.map +1 -0
- package/dist/get-unit-vector.d.ts +6 -0
- package/dist/get-unit-vector.js +9 -0
- package/dist/get-unit-vector.js.map +1 -0
- package/dist/grid.d.ts +25 -0
- package/dist/grid.js +7 -0
- package/dist/grid.js.map +1 -0
- package/dist/index.d.ts +5 -83
- package/dist/index.js +22 -191
- package/dist/index.js.map +1 -1
- package/dist/line-intersections.d.ts +30 -0
- package/dist/line-intersections.js +17 -0
- package/dist/line-intersections.js.map +1 -0
- package/dist/nearest-box.d.ts +30 -0
- package/dist/nearest-box.js +13 -0
- package/dist/nearest-box.js.map +1 -0
- package/package.json +16 -2
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// src/line-intersections.ts
|
|
2
|
+
function doesLineIntersectLine([a1, a2], [b1, b2], {
|
|
3
|
+
lineThickness = 0
|
|
4
|
+
} = {}) {
|
|
5
|
+
if (lineThickness === 0) {
|
|
6
|
+
return doSegmentsIntersect(a1, a2, b1, b2);
|
|
7
|
+
}
|
|
8
|
+
const minDist = segmentsDistance(a1, a2, b1, b2);
|
|
9
|
+
return minDist <= lineThickness;
|
|
10
|
+
}
|
|
11
|
+
function doSegmentsIntersect(p1, q1, p2, q2) {
|
|
12
|
+
const o1 = orientation(p1, q1, p2);
|
|
13
|
+
const o2 = orientation(p1, q1, q2);
|
|
14
|
+
const o3 = orientation(p2, q2, p1);
|
|
15
|
+
const o4 = orientation(p2, q2, q1);
|
|
16
|
+
if (o1 !== o2 && o3 !== o4) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
if (o1 === 0 && onSegment(p1, p2, q1)) return true;
|
|
20
|
+
if (o2 === 0 && onSegment(p1, q2, q1)) return true;
|
|
21
|
+
if (o3 === 0 && onSegment(p2, p1, q2)) return true;
|
|
22
|
+
if (o4 === 0 && onSegment(p2, q1, q2)) return true;
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
function orientation(p, q, r) {
|
|
26
|
+
const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
27
|
+
if (val === 0) return 0;
|
|
28
|
+
return val > 0 ? 1 : 2;
|
|
29
|
+
}
|
|
30
|
+
function onSegment(p, q, r) {
|
|
31
|
+
return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
|
|
32
|
+
}
|
|
33
|
+
function segmentsDistance(a1, a2, b1, b2) {
|
|
34
|
+
if (a1.x === a2.x && a1.y === a2.y) {
|
|
35
|
+
return pointToSegmentDistance(a1, b1, b2);
|
|
36
|
+
}
|
|
37
|
+
if (b1.x === b2.x && b1.y === b2.y) {
|
|
38
|
+
return pointToSegmentDistance(b1, a1, a2);
|
|
39
|
+
}
|
|
40
|
+
if (doSegmentsIntersect(a1, a2, b1, b2)) {
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
const distances = [
|
|
44
|
+
pointToSegmentDistance(a1, b1, b2),
|
|
45
|
+
pointToSegmentDistance(a2, b1, b2),
|
|
46
|
+
pointToSegmentDistance(b1, a1, a2),
|
|
47
|
+
pointToSegmentDistance(b2, a1, a2)
|
|
48
|
+
];
|
|
49
|
+
return Math.min(...distances);
|
|
50
|
+
}
|
|
51
|
+
function pointToSegmentDistance(p, v, w) {
|
|
52
|
+
const l2 = (w.x - v.x) ** 2 + (w.y - v.y) ** 2;
|
|
53
|
+
if (l2 === 0) return distance(p, v);
|
|
54
|
+
let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
|
|
55
|
+
t = Math.max(0, Math.min(1, t));
|
|
56
|
+
const projection = {
|
|
57
|
+
x: v.x + t * (w.x - v.x),
|
|
58
|
+
y: v.y + t * (w.y - v.y)
|
|
59
|
+
};
|
|
60
|
+
return distance(p, projection);
|
|
61
|
+
}
|
|
62
|
+
function distance(p1, p2) {
|
|
63
|
+
const dx = p1.x - p2.x;
|
|
64
|
+
const dy = p1.y - p2.y;
|
|
65
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export {
|
|
69
|
+
doesLineIntersectLine,
|
|
70
|
+
doSegmentsIntersect,
|
|
71
|
+
orientation,
|
|
72
|
+
onSegment,
|
|
73
|
+
pointToSegmentDistance,
|
|
74
|
+
distance
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=chunk-CHQOCSFB.js.map
|
|
@@ -0,0 +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"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/get-unit-vector.ts
|
|
2
|
+
var getUnitVectorFromPointAToB = (a, b) => {
|
|
3
|
+
const delta = {
|
|
4
|
+
x: b.x - a.x,
|
|
5
|
+
y: b.y - a.y
|
|
6
|
+
};
|
|
7
|
+
const magnitude = Math.sqrt(delta.x ** 2 + delta.y ** 2);
|
|
8
|
+
return {
|
|
9
|
+
x: delta.x / magnitude,
|
|
10
|
+
y: delta.y / magnitude
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
var getUnitVectorFromDirection = (direction) => {
|
|
14
|
+
switch (direction) {
|
|
15
|
+
case "up":
|
|
16
|
+
return { x: 0, y: 1 };
|
|
17
|
+
case "down":
|
|
18
|
+
return { x: 0, y: -1 };
|
|
19
|
+
case "left":
|
|
20
|
+
return { x: -1, y: 0 };
|
|
21
|
+
case "right":
|
|
22
|
+
return { x: 1, y: 0 };
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
getUnitVectorFromPointAToB,
|
|
28
|
+
getUnitVectorFromDirection
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=chunk-GIGMPRPV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/get-unit-vector.ts"],"sourcesContent":["import type { Point } from \"./common\"\n\nexport const getUnitVectorFromPointAToB = (a: Point, b: Point): Point => {\n const delta = {\n x: b.x - a.x,\n y: b.y - a.y,\n }\n\n const magnitude = Math.sqrt(delta.x ** 2 + delta.y ** 2)\n\n return {\n x: delta.x / magnitude,\n y: delta.y / magnitude,\n }\n}\n\nexport const getUnitVectorFromDirection = (\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n): Point => {\n switch (direction) {\n case \"up\":\n return { x: 0, y: 1 }\n case \"down\":\n return { x: 0, y: -1 }\n case \"left\":\n return { x: -1, y: 0 }\n case \"right\":\n return { x: 1, y: 0 }\n }\n}\n"],"mappings":";AAEO,IAAM,6BAA6B,CAAC,GAAU,MAAoB;AACvE,QAAM,QAAQ;AAAA,IACZ,GAAG,EAAE,IAAI,EAAE;AAAA,IACX,GAAG,EAAE,IAAI,EAAE;AAAA,EACb;AAEA,QAAM,YAAY,KAAK,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK,CAAC;AAEvD,SAAO;AAAA,IACL,GAAG,MAAM,IAAI;AAAA,IACb,GAAG,MAAM,IAAI;AAAA,EACf;AACF;AAEO,IAAM,6BAA6B,CACxC,cACU;AACV,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACtB,KAAK;AACH,aAAO,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,IACvB,KAAK;AACH,aAAO,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,IACvB,KAAK;AACH,aAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACxB;AACF;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=chunk-GYQ2KZV6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/nearest-box.ts
|
|
2
|
+
function getBoundingBox(box) {
|
|
3
|
+
const halfWidth = box.width / 2;
|
|
4
|
+
const halfHeight = box.height / 2;
|
|
5
|
+
return {
|
|
6
|
+
minX: box.center.x - halfWidth,
|
|
7
|
+
maxX: box.center.x + halfWidth,
|
|
8
|
+
minY: box.center.y - halfHeight,
|
|
9
|
+
maxY: box.center.y + halfHeight
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function computeDistanceBetweenBoxes(boxA, boxB) {
|
|
13
|
+
const a = getBoundingBox(boxA);
|
|
14
|
+
const b = getBoundingBox(boxB);
|
|
15
|
+
const dx = Math.max(a.minX - b.maxX, b.minX - a.maxX, 0);
|
|
16
|
+
const dy = Math.max(a.minY - b.maxY, b.minY - a.maxY, 0);
|
|
17
|
+
const pointA = { x: 0, y: 0 };
|
|
18
|
+
const pointB = { x: 0, y: 0 };
|
|
19
|
+
if (dx === 0 && dy === 0) {
|
|
20
|
+
return { distance: 0, pointA: boxA.center, pointB: boxB.center };
|
|
21
|
+
}
|
|
22
|
+
pointA.x = clamp(boxA.center.x, b.minX, b.maxX);
|
|
23
|
+
pointA.y = clamp(boxA.center.y, b.minY, b.maxY);
|
|
24
|
+
pointB.x = clamp(boxB.center.x, a.minX, a.maxX);
|
|
25
|
+
pointB.y = clamp(boxB.center.y, a.minY, a.maxY);
|
|
26
|
+
const distance = Math.hypot(pointA.x - pointB.x, pointA.y - pointB.y);
|
|
27
|
+
return { distance, pointA, pointB };
|
|
28
|
+
}
|
|
29
|
+
function clamp(value, min, max) {
|
|
30
|
+
return Math.max(min, Math.min(max, value));
|
|
31
|
+
}
|
|
32
|
+
function findNearestPointsBetweenBoxSets(boxSetA, boxSetB) {
|
|
33
|
+
let minDistance = Number.POSITIVE_INFINITY;
|
|
34
|
+
let nearestPointA = { x: 0, y: 0 };
|
|
35
|
+
let nearestPointB = { x: 0, y: 0 };
|
|
36
|
+
for (const boxA of boxSetA) {
|
|
37
|
+
for (const boxB of boxSetB) {
|
|
38
|
+
const { distance, pointA, pointB } = computeDistanceBetweenBoxes(
|
|
39
|
+
boxA,
|
|
40
|
+
boxB
|
|
41
|
+
);
|
|
42
|
+
if (distance < minDistance) {
|
|
43
|
+
minDistance = distance;
|
|
44
|
+
nearestPointA = pointA;
|
|
45
|
+
nearestPointB = pointB;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
pointA: nearestPointA,
|
|
51
|
+
pointB: nearestPointB,
|
|
52
|
+
distance: minDistance
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
getBoundingBox,
|
|
58
|
+
computeDistanceBetweenBoxes,
|
|
59
|
+
clamp,
|
|
60
|
+
findNearestPointsBetweenBoxSets
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=chunk-MHHTZHOJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/nearest-box.ts"],"sourcesContent":["import type { Point } from \"./common\"\n\nexport type Box = { center: Point; width: number; height: number }\nexport type BoxSet = Box[]\n\nexport type GridCell = { boxes: Box[] }\n\nexport function getBoundingBox(box: Box) {\n const halfWidth = box.width / 2\n const halfHeight = box.height / 2\n return {\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\nexport function computeDistanceBetweenBoxes(\n boxA: Box,\n boxB: Box,\n): { distance: number; pointA: Point; pointB: Point } {\n const a = getBoundingBox(boxA)\n const b = getBoundingBox(boxB)\n\n const dx = Math.max(a.minX - b.maxX, b.minX - a.maxX, 0)\n const dy = Math.max(a.minY - b.maxY, b.minY - a.maxY, 0)\n\n const pointA: Point = { x: 0, y: 0 }\n const pointB: Point = { x: 0, y: 0 }\n\n if (dx === 0 && dy === 0) {\n // Boxes overlap\n return { distance: 0, pointA: boxA.center, pointB: boxB.center }\n }\n\n // Compute the closest points on the edges\n pointA.x = clamp(boxA.center.x, b.minX, b.maxX)\n pointA.y = clamp(boxA.center.y, b.minY, b.maxY)\n\n pointB.x = clamp(boxB.center.x, a.minX, a.maxX)\n pointB.y = clamp(boxB.center.y, a.minY, a.maxY)\n\n const distance = Math.hypot(pointA.x - pointB.x, pointA.y - pointB.y)\n return { distance, pointA, pointB }\n}\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value))\n}\n\nexport function findNearestPointsBetweenBoxSets(\n boxSetA: BoxSet,\n boxSetB: BoxSet,\n): { pointA: Point; pointB: Point; distance: number } {\n let minDistance = Number.POSITIVE_INFINITY\n let nearestPointA: Point = { x: 0, y: 0 }\n let nearestPointB: Point = { x: 0, y: 0 }\n\n for (const boxA of boxSetA) {\n for (const boxB of boxSetB) {\n const { distance, pointA, pointB } = computeDistanceBetweenBoxes(\n boxA,\n boxB,\n )\n if (distance < minDistance) {\n minDistance = distance\n nearestPointA = pointA\n nearestPointB = pointB\n }\n }\n }\n\n return {\n pointA: nearestPointA,\n pointB: nearestPointB,\n distance: minDistance,\n }\n}\n"],"mappings":";AAOO,SAAS,eAAe,KAAU;AACvC,QAAM,YAAY,IAAI,QAAQ;AAC9B,QAAM,aAAa,IAAI,SAAS;AAChC,SAAO;AAAA,IACL,MAAM,IAAI,OAAO,IAAI;AAAA,IACrB,MAAM,IAAI,OAAO,IAAI;AAAA,IACrB,MAAM,IAAI,OAAO,IAAI;AAAA,IACrB,MAAM,IAAI,OAAO,IAAI;AAAA,EACvB;AACF;AAEO,SAAS,4BACd,MACA,MACoD;AACpD,QAAM,IAAI,eAAe,IAAI;AAC7B,QAAM,IAAI,eAAe,IAAI;AAE7B,QAAM,KAAK,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC;AACvD,QAAM,KAAK,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC;AAEvD,QAAM,SAAgB,EAAE,GAAG,GAAG,GAAG,EAAE;AACnC,QAAM,SAAgB,EAAE,GAAG,GAAG,GAAG,EAAE;AAEnC,MAAI,OAAO,KAAK,OAAO,GAAG;AAExB,WAAO,EAAE,UAAU,GAAG,QAAQ,KAAK,QAAQ,QAAQ,KAAK,OAAO;AAAA,EACjE;AAGA,SAAO,IAAI,MAAM,KAAK,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI;AAC9C,SAAO,IAAI,MAAM,KAAK,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI;AAE9C,SAAO,IAAI,MAAM,KAAK,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI;AAC9C,SAAO,IAAI,MAAM,KAAK,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI;AAE9C,QAAM,WAAW,KAAK,MAAM,OAAO,IAAI,OAAO,GAAG,OAAO,IAAI,OAAO,CAAC;AACpE,SAAO,EAAE,UAAU,QAAQ,OAAO;AACpC;AAEO,SAAS,MAAM,OAAe,KAAa,KAAqB;AACrE,SAAO,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAC3C;AAEO,SAAS,gCACd,SACA,SACoD;AACpD,MAAI,cAAc,OAAO;AACzB,MAAI,gBAAuB,EAAE,GAAG,GAAG,GAAG,EAAE;AACxC,MAAI,gBAAuB,EAAE,GAAG,GAAG,GAAG,EAAE;AAExC,aAAW,QAAQ,SAAS;AAC1B,eAAW,QAAQ,SAAS;AAC1B,YAAM,EAAE,UAAU,QAAQ,OAAO,IAAI;AAAA,QACnC;AAAA,QACA;AAAA,MACF;AACA,UAAI,WAAW,aAAa;AAC1B,sBAAc;AACd,wBAAgB;AAChB,wBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACF;","names":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// src/grid.ts
|
|
2
|
+
function grid({
|
|
3
|
+
rows,
|
|
4
|
+
cols,
|
|
5
|
+
xSpacing,
|
|
6
|
+
ySpacing,
|
|
7
|
+
width,
|
|
8
|
+
height,
|
|
9
|
+
offsetX = 0,
|
|
10
|
+
offsetY = 0,
|
|
11
|
+
yDirection = "cartesian",
|
|
12
|
+
centered = true
|
|
13
|
+
}) {
|
|
14
|
+
const effectiveXSpacing = xSpacing ?? 1;
|
|
15
|
+
const effectiveYSpacing = ySpacing ?? 1;
|
|
16
|
+
const totalWidth = width ?? cols * effectiveXSpacing;
|
|
17
|
+
const totalHeight = height ?? rows * effectiveYSpacing;
|
|
18
|
+
const centeringOffsetX = centered ? -totalWidth / 2 : 0;
|
|
19
|
+
const centeringOffsetY = centered ? -totalHeight / 2 : 0;
|
|
20
|
+
const cellWidth = width ? width / cols : effectiveXSpacing;
|
|
21
|
+
const cellHeight = height ? height / rows : effectiveYSpacing;
|
|
22
|
+
const cells = [];
|
|
23
|
+
for (let row = 0; row < rows; row++) {
|
|
24
|
+
for (let col = 0; col < cols; col++) {
|
|
25
|
+
const index = row * cols + col;
|
|
26
|
+
const centerX = offsetX + centeringOffsetX + col * cellWidth + cellWidth / 2;
|
|
27
|
+
const rawCenterY = offsetY + row * cellHeight + cellHeight / 2;
|
|
28
|
+
const centerY = yDirection === "cartesian" ? offsetY + centeringOffsetY + (rows - 1 - row) * cellHeight + cellHeight / 2 : offsetY + centeringOffsetY + row * cellHeight + cellHeight / 2;
|
|
29
|
+
cells.push({
|
|
30
|
+
index,
|
|
31
|
+
center: { x: centerX, y: centerY },
|
|
32
|
+
topLeft: {
|
|
33
|
+
x: centerX - cellWidth / 2,
|
|
34
|
+
y: centerY + cellHeight / 2
|
|
35
|
+
},
|
|
36
|
+
bottomRight: {
|
|
37
|
+
x: centerX + cellWidth / 2,
|
|
38
|
+
y: centerY - cellHeight / 2
|
|
39
|
+
},
|
|
40
|
+
row,
|
|
41
|
+
col
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return cells;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export {
|
|
49
|
+
grid
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=chunk-U45EKA3R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/grid.ts"],"sourcesContent":["import type { Point } from \"./common\"\n\nexport type GridCellPositions = {\n index: number\n row: number\n col: number\n center: Point\n topLeft: Point\n bottomRight: Point\n}\n\nexport type GridOptions = {\n rows: number\n cols: number\n xSpacing?: number\n ySpacing?: number\n width?: number\n height?: number\n offsetX?: number\n offsetY?: number\n yDirection?: \"cartesian\" | \"up-is-negative\"\n centered?: boolean\n}\n\nexport function grid({\n rows,\n cols,\n xSpacing,\n ySpacing,\n width,\n height,\n offsetX = 0,\n offsetY = 0,\n yDirection = \"cartesian\",\n centered = true,\n}: GridOptions): GridCellPositions[] {\n // Set default spacing if neither spacing nor dimensions are specified\n const effectiveXSpacing = xSpacing ?? 1\n const effectiveYSpacing = ySpacing ?? 1\n\n // Calculate cell dimensions\n const totalWidth = width ?? cols * effectiveXSpacing\n const totalHeight = height ?? rows * effectiveYSpacing\n\n // Calculate centering offsets if needed\n const centeringOffsetX = centered ? -totalWidth / 2 : 0\n const centeringOffsetY = centered ? -totalHeight / 2 : 0\n\n const cellWidth = width ? width / cols : effectiveXSpacing\n const cellHeight = height ? height / rows : effectiveYSpacing\n\n const cells: GridCellPositions[] = []\n\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const index = row * cols + col\n\n // Calculate center position\n const centerX =\n offsetX + centeringOffsetX + col * cellWidth + cellWidth / 2\n const rawCenterY = offsetY + row * cellHeight + cellHeight / 2\n\n // Adjust Y coordinate based on yDirection\n const centerY =\n yDirection === \"cartesian\"\n ? offsetY +\n centeringOffsetY +\n (rows - 1 - row) * cellHeight +\n cellHeight / 2\n : offsetY + centeringOffsetY + row * cellHeight + cellHeight / 2\n\n cells.push({\n index,\n center: { x: centerX, y: centerY },\n topLeft: {\n x: centerX - cellWidth / 2,\n y: centerY + cellHeight / 2,\n },\n bottomRight: {\n x: centerX + cellWidth / 2,\n y: centerY - cellHeight / 2,\n },\n row,\n col,\n })\n }\n }\n\n return cells\n}\n"],"mappings":";AAwBO,SAAS,KAAK;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,UAAU;AAAA,EACV,aAAa;AAAA,EACb,WAAW;AACb,GAAqC;AAEnC,QAAM,oBAAoB,YAAY;AACtC,QAAM,oBAAoB,YAAY;AAGtC,QAAM,aAAa,SAAS,OAAO;AACnC,QAAM,cAAc,UAAU,OAAO;AAGrC,QAAM,mBAAmB,WAAW,CAAC,aAAa,IAAI;AACtD,QAAM,mBAAmB,WAAW,CAAC,cAAc,IAAI;AAEvD,QAAM,YAAY,QAAQ,QAAQ,OAAO;AACzC,QAAM,aAAa,SAAS,SAAS,OAAO;AAE5C,QAAM,QAA6B,CAAC;AAEpC,WAAS,MAAM,GAAG,MAAM,MAAM,OAAO;AACnC,aAAS,MAAM,GAAG,MAAM,MAAM,OAAO;AACnC,YAAM,QAAQ,MAAM,OAAO;AAG3B,YAAM,UACJ,UAAU,mBAAmB,MAAM,YAAY,YAAY;AAC7D,YAAM,aAAa,UAAU,MAAM,aAAa,aAAa;AAG7D,YAAM,UACJ,eAAe,cACX,UACA,oBACC,OAAO,IAAI,OAAO,aACnB,aAAa,IACb,UAAU,mBAAmB,MAAM,aAAa,aAAa;AAEnE,YAAM,KAAK;AAAA,QACT;AAAA,QACA,QAAQ,EAAE,GAAG,SAAS,GAAG,QAAQ;AAAA,QACjC,SAAS;AAAA,UACP,GAAG,UAAU,YAAY;AAAA,UACzB,GAAG,UAAU,aAAa;AAAA,QAC5B;AAAA,QACA,aAAa;AAAA,UACX,GAAG,UAAU,YAAY;AAAA,UACzB,GAAG,UAAU,aAAa;AAAA,QAC5B;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
|
package/dist/common.d.ts
ADDED
package/dist/common.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Point } from './common.js';
|
|
2
|
+
|
|
3
|
+
declare const getUnitVectorFromPointAToB: (a: Point, b: Point) => Point;
|
|
4
|
+
declare const getUnitVectorFromDirection: (direction: "up" | "down" | "left" | "right") => Point;
|
|
5
|
+
|
|
6
|
+
export { getUnitVectorFromDirection, getUnitVectorFromPointAToB };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/grid.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Point } from './common.js';
|
|
2
|
+
|
|
3
|
+
type GridCellPositions = {
|
|
4
|
+
index: number;
|
|
5
|
+
row: number;
|
|
6
|
+
col: number;
|
|
7
|
+
center: Point;
|
|
8
|
+
topLeft: Point;
|
|
9
|
+
bottomRight: Point;
|
|
10
|
+
};
|
|
11
|
+
type GridOptions = {
|
|
12
|
+
rows: number;
|
|
13
|
+
cols: number;
|
|
14
|
+
xSpacing?: number;
|
|
15
|
+
ySpacing?: number;
|
|
16
|
+
width?: number;
|
|
17
|
+
height?: number;
|
|
18
|
+
offsetX?: number;
|
|
19
|
+
offsetY?: number;
|
|
20
|
+
yDirection?: "cartesian" | "up-is-negative";
|
|
21
|
+
centered?: boolean;
|
|
22
|
+
};
|
|
23
|
+
declare function grid({ rows, cols, xSpacing, ySpacing, width, height, offsetX, offsetY, yDirection, centered, }: GridOptions): GridCellPositions[];
|
|
24
|
+
|
|
25
|
+
export { type GridCellPositions, type GridOptions, grid };
|
package/dist/grid.js
ADDED
package/dist/grid.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,83 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Returns true if the two lines intersect.
|
|
8
|
-
*/
|
|
9
|
-
declare function doesLineIntersectLine([a1, a2]: [Point, Point], [b1, b2]: [Point, Point], { lineThickness, }?: {
|
|
10
|
-
lineThickness?: number;
|
|
11
|
-
}): boolean;
|
|
12
|
-
/**
|
|
13
|
-
* Returns true if the two segments intersect.
|
|
14
|
-
*/
|
|
15
|
-
declare function doSegmentsIntersect(p1: Point, q1: Point, p2: Point, q2: Point): boolean;
|
|
16
|
-
/**
|
|
17
|
-
* Returns 0 if the points are colinear, 1 if they are clockwise, and 2 if they are counterclockwise.
|
|
18
|
-
*/
|
|
19
|
-
declare function orientation(p: Point, q: Point, r: Point): number;
|
|
20
|
-
/**
|
|
21
|
-
* Returns true if q is on the segment p->r.
|
|
22
|
-
*/
|
|
23
|
-
declare function onSegment(p: Point, q: Point, r: Point): boolean;
|
|
24
|
-
/**
|
|
25
|
-
* Returns the minimum distance between a point and a segment.
|
|
26
|
-
*/
|
|
27
|
-
declare function pointToSegmentDistance(p: Point, v: Point, w: Point): number;
|
|
28
|
-
/**
|
|
29
|
-
* Returns the distance between two points.
|
|
30
|
-
*/
|
|
31
|
-
declare function distance(p1: Point, p2: Point): number;
|
|
32
|
-
|
|
33
|
-
type Box = {
|
|
34
|
-
center: Point;
|
|
35
|
-
width: number;
|
|
36
|
-
height: number;
|
|
37
|
-
};
|
|
38
|
-
type BoxSet = Box[];
|
|
39
|
-
type GridCell = {
|
|
40
|
-
boxes: Box[];
|
|
41
|
-
};
|
|
42
|
-
declare function getBoundingBox(box: Box): {
|
|
43
|
-
minX: number;
|
|
44
|
-
maxX: number;
|
|
45
|
-
minY: number;
|
|
46
|
-
maxY: number;
|
|
47
|
-
};
|
|
48
|
-
declare function computeDistanceBetweenBoxes(boxA: Box, boxB: Box): {
|
|
49
|
-
distance: number;
|
|
50
|
-
pointA: Point;
|
|
51
|
-
pointB: Point;
|
|
52
|
-
};
|
|
53
|
-
declare function clamp(value: number, min: number, max: number): number;
|
|
54
|
-
declare function findNearestPointsBetweenBoxSets(boxSetA: BoxSet, boxSetB: BoxSet): {
|
|
55
|
-
pointA: Point;
|
|
56
|
-
pointB: Point;
|
|
57
|
-
distance: number;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
declare const getUnitVectorFromPointAToB: (a: Point, b: Point) => Point;
|
|
61
|
-
declare const getUnitVectorFromDirection: (direction: "up" | "down" | "left" | "right") => Point;
|
|
62
|
-
|
|
63
|
-
type GridCellPositions = {
|
|
64
|
-
index: number;
|
|
65
|
-
center: Point;
|
|
66
|
-
topLeft: Point;
|
|
67
|
-
bottomRight: Point;
|
|
68
|
-
};
|
|
69
|
-
type GridOptions = {
|
|
70
|
-
rows: number;
|
|
71
|
-
cols: number;
|
|
72
|
-
xSpacing?: number;
|
|
73
|
-
ySpacing?: number;
|
|
74
|
-
width?: number;
|
|
75
|
-
height?: number;
|
|
76
|
-
offsetX?: number;
|
|
77
|
-
offsetY?: number;
|
|
78
|
-
yDirection?: "cartesian" | "up-is-negative";
|
|
79
|
-
centered?: boolean;
|
|
80
|
-
};
|
|
81
|
-
declare function grid({ rows, cols, xSpacing, ySpacing, width, height, offsetX, offsetY, yDirection, centered, }: GridOptions): GridCellPositions[];
|
|
82
|
-
|
|
83
|
-
export { type Box, type BoxSet, type GridCell, type GridCellPositions, type GridOptions, type Point, clamp, computeDistanceBetweenBoxes, distance, doSegmentsIntersect, doesLineIntersectLine, findNearestPointsBetweenBoxSets, getBoundingBox, getUnitVectorFromDirection, getUnitVectorFromPointAToB, grid, onSegment, orientation, pointToSegmentDistance };
|
|
1
|
+
export { distance, doSegmentsIntersect, doesLineIntersectLine, onSegment, orientation, pointToSegmentDistance } from './line-intersections.js';
|
|
2
|
+
export { Box, BoxSet, GridCell, clamp, computeDistanceBetweenBoxes, findNearestPointsBetweenBoxSets, getBoundingBox } from './nearest-box.js';
|
|
3
|
+
export { Point } from './common.js';
|
|
4
|
+
export { getUnitVectorFromDirection, getUnitVectorFromPointAToB } from './get-unit-vector.js';
|
|
5
|
+
export { GridCellPositions, GridOptions, grid } from './grid.js';
|
package/dist/index.js
CHANGED
|
@@ -1,194 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
function orientation(p, q, r) {
|
|
26
|
-
const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
27
|
-
if (val === 0) return 0;
|
|
28
|
-
return val > 0 ? 1 : 2;
|
|
29
|
-
}
|
|
30
|
-
function onSegment(p, q, r) {
|
|
31
|
-
return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);
|
|
32
|
-
}
|
|
33
|
-
function segmentsDistance(a1, a2, b1, b2) {
|
|
34
|
-
if (a1.x === a2.x && a1.y === a2.y) {
|
|
35
|
-
return pointToSegmentDistance(a1, b1, b2);
|
|
36
|
-
}
|
|
37
|
-
if (b1.x === b2.x && b1.y === b2.y) {
|
|
38
|
-
return pointToSegmentDistance(b1, a1, a2);
|
|
39
|
-
}
|
|
40
|
-
if (doSegmentsIntersect(a1, a2, b1, b2)) {
|
|
41
|
-
return 0;
|
|
42
|
-
}
|
|
43
|
-
const distances = [
|
|
44
|
-
pointToSegmentDistance(a1, b1, b2),
|
|
45
|
-
pointToSegmentDistance(a2, b1, b2),
|
|
46
|
-
pointToSegmentDistance(b1, a1, a2),
|
|
47
|
-
pointToSegmentDistance(b2, a1, a2)
|
|
48
|
-
];
|
|
49
|
-
return Math.min(...distances);
|
|
50
|
-
}
|
|
51
|
-
function pointToSegmentDistance(p, v, w) {
|
|
52
|
-
const l2 = (w.x - v.x) ** 2 + (w.y - v.y) ** 2;
|
|
53
|
-
if (l2 === 0) return distance(p, v);
|
|
54
|
-
let t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2;
|
|
55
|
-
t = Math.max(0, Math.min(1, t));
|
|
56
|
-
const projection = {
|
|
57
|
-
x: v.x + t * (w.x - v.x),
|
|
58
|
-
y: v.y + t * (w.y - v.y)
|
|
59
|
-
};
|
|
60
|
-
return distance(p, projection);
|
|
61
|
-
}
|
|
62
|
-
function distance(p1, p2) {
|
|
63
|
-
const dx = p1.x - p2.x;
|
|
64
|
-
const dy = p1.y - p2.y;
|
|
65
|
-
return Math.sqrt(dx * dx + dy * dy);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// src/nearest-box.ts
|
|
69
|
-
function getBoundingBox(box) {
|
|
70
|
-
const halfWidth = box.width / 2;
|
|
71
|
-
const halfHeight = box.height / 2;
|
|
72
|
-
return {
|
|
73
|
-
minX: box.center.x - halfWidth,
|
|
74
|
-
maxX: box.center.x + halfWidth,
|
|
75
|
-
minY: box.center.y - halfHeight,
|
|
76
|
-
maxY: box.center.y + halfHeight
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
function computeDistanceBetweenBoxes(boxA, boxB) {
|
|
80
|
-
const a = getBoundingBox(boxA);
|
|
81
|
-
const b = getBoundingBox(boxB);
|
|
82
|
-
const dx = Math.max(a.minX - b.maxX, b.minX - a.maxX, 0);
|
|
83
|
-
const dy = Math.max(a.minY - b.maxY, b.minY - a.maxY, 0);
|
|
84
|
-
const pointA = { x: 0, y: 0 };
|
|
85
|
-
const pointB = { x: 0, y: 0 };
|
|
86
|
-
if (dx === 0 && dy === 0) {
|
|
87
|
-
return { distance: 0, pointA: boxA.center, pointB: boxB.center };
|
|
88
|
-
}
|
|
89
|
-
pointA.x = clamp(boxA.center.x, b.minX, b.maxX);
|
|
90
|
-
pointA.y = clamp(boxA.center.y, b.minY, b.maxY);
|
|
91
|
-
pointB.x = clamp(boxB.center.x, a.minX, a.maxX);
|
|
92
|
-
pointB.y = clamp(boxB.center.y, a.minY, a.maxY);
|
|
93
|
-
const distance2 = Math.hypot(pointA.x - pointB.x, pointA.y - pointB.y);
|
|
94
|
-
return { distance: distance2, pointA, pointB };
|
|
95
|
-
}
|
|
96
|
-
function clamp(value, min, max) {
|
|
97
|
-
return Math.max(min, Math.min(max, value));
|
|
98
|
-
}
|
|
99
|
-
function findNearestPointsBetweenBoxSets(boxSetA, boxSetB) {
|
|
100
|
-
let minDistance = Number.POSITIVE_INFINITY;
|
|
101
|
-
let nearestPointA = { x: 0, y: 0 };
|
|
102
|
-
let nearestPointB = { x: 0, y: 0 };
|
|
103
|
-
for (const boxA of boxSetA) {
|
|
104
|
-
for (const boxB of boxSetB) {
|
|
105
|
-
const { distance: distance2, pointA, pointB } = computeDistanceBetweenBoxes(
|
|
106
|
-
boxA,
|
|
107
|
-
boxB
|
|
108
|
-
);
|
|
109
|
-
if (distance2 < minDistance) {
|
|
110
|
-
minDistance = distance2;
|
|
111
|
-
nearestPointA = pointA;
|
|
112
|
-
nearestPointB = pointB;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
return {
|
|
117
|
-
pointA: nearestPointA,
|
|
118
|
-
pointB: nearestPointB,
|
|
119
|
-
distance: minDistance
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// src/get-unit-vector.ts
|
|
124
|
-
var getUnitVectorFromPointAToB = (a, b) => {
|
|
125
|
-
const delta = {
|
|
126
|
-
x: b.x - a.x,
|
|
127
|
-
y: b.y - a.y
|
|
128
|
-
};
|
|
129
|
-
const magnitude = Math.sqrt(delta.x ** 2 + delta.y ** 2);
|
|
130
|
-
return {
|
|
131
|
-
x: delta.x / magnitude,
|
|
132
|
-
y: delta.y / magnitude
|
|
133
|
-
};
|
|
134
|
-
};
|
|
135
|
-
var getUnitVectorFromDirection = (direction) => {
|
|
136
|
-
switch (direction) {
|
|
137
|
-
case "up":
|
|
138
|
-
return { x: 0, y: 1 };
|
|
139
|
-
case "down":
|
|
140
|
-
return { x: 0, y: -1 };
|
|
141
|
-
case "left":
|
|
142
|
-
return { x: -1, y: 0 };
|
|
143
|
-
case "right":
|
|
144
|
-
return { x: 1, y: 0 };
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
// src/grid.ts
|
|
149
|
-
function grid({
|
|
150
|
-
rows,
|
|
151
|
-
cols,
|
|
152
|
-
xSpacing,
|
|
153
|
-
ySpacing,
|
|
154
|
-
width,
|
|
155
|
-
height,
|
|
156
|
-
offsetX = 0,
|
|
157
|
-
offsetY = 0,
|
|
158
|
-
yDirection = "cartesian",
|
|
159
|
-
centered = true
|
|
160
|
-
}) {
|
|
161
|
-
const effectiveXSpacing = xSpacing ?? 1;
|
|
162
|
-
const effectiveYSpacing = ySpacing ?? 1;
|
|
163
|
-
const totalWidth = width ?? cols * effectiveXSpacing;
|
|
164
|
-
const totalHeight = height ?? rows * effectiveYSpacing;
|
|
165
|
-
const centeringOffsetX = centered ? -totalWidth / 2 : 0;
|
|
166
|
-
const centeringOffsetY = centered ? -totalHeight / 2 : 0;
|
|
167
|
-
const cellWidth = width ? width / cols : effectiveXSpacing;
|
|
168
|
-
const cellHeight = height ? height / rows : effectiveYSpacing;
|
|
169
|
-
const cells = [];
|
|
170
|
-
for (let row = 0; row < rows; row++) {
|
|
171
|
-
for (let col = 0; col < cols; col++) {
|
|
172
|
-
const index = row * cols + col;
|
|
173
|
-
const centerX = offsetX + centeringOffsetX + col * cellWidth + cellWidth / 2;
|
|
174
|
-
const rawCenterY = offsetY + row * cellHeight + cellHeight / 2;
|
|
175
|
-
const centerY = yDirection === "cartesian" ? offsetY + centeringOffsetY + (rows - 1 - row) * cellHeight + cellHeight / 2 : offsetY + centeringOffsetY + row * cellHeight + cellHeight / 2;
|
|
176
|
-
cells.push({
|
|
177
|
-
index,
|
|
178
|
-
center: { x: centerX, y: centerY },
|
|
179
|
-
topLeft: {
|
|
180
|
-
x: centerX - cellWidth / 2,
|
|
181
|
-
y: centerY + cellHeight / 2
|
|
182
|
-
},
|
|
183
|
-
bottomRight: {
|
|
184
|
-
x: centerX + cellWidth / 2,
|
|
185
|
-
y: centerY - cellHeight / 2
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return cells;
|
|
191
|
-
}
|
|
1
|
+
import "./chunk-GYQ2KZV6.js";
|
|
2
|
+
import {
|
|
3
|
+
getUnitVectorFromDirection,
|
|
4
|
+
getUnitVectorFromPointAToB
|
|
5
|
+
} from "./chunk-GIGMPRPV.js";
|
|
6
|
+
import {
|
|
7
|
+
grid
|
|
8
|
+
} from "./chunk-U45EKA3R.js";
|
|
9
|
+
import {
|
|
10
|
+
distance,
|
|
11
|
+
doSegmentsIntersect,
|
|
12
|
+
doesLineIntersectLine,
|
|
13
|
+
onSegment,
|
|
14
|
+
orientation,
|
|
15
|
+
pointToSegmentDistance
|
|
16
|
+
} from "./chunk-CHQOCSFB.js";
|
|
17
|
+
import {
|
|
18
|
+
clamp,
|
|
19
|
+
computeDistanceBetweenBoxes,
|
|
20
|
+
findNearestPointsBetweenBoxSets,
|
|
21
|
+
getBoundingBox
|
|
22
|
+
} from "./chunk-MHHTZHOJ.js";
|
|
192
23
|
export {
|
|
193
24
|
clamp,
|
|
194
25
|
computeDistanceBetweenBoxes,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/line-intersections.ts","../src/nearest-box.ts","../src/get-unit-vector.ts","../src/grid.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","import type { Point } from \"./common\"\n\nexport type Box = { center: Point; width: number; height: number }\nexport type BoxSet = Box[]\n\nexport type GridCell = { boxes: Box[] }\n\nexport function getBoundingBox(box: Box) {\n const halfWidth = box.width / 2\n const halfHeight = box.height / 2\n return {\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\nexport function computeDistanceBetweenBoxes(\n boxA: Box,\n boxB: Box,\n): { distance: number; pointA: Point; pointB: Point } {\n const a = getBoundingBox(boxA)\n const b = getBoundingBox(boxB)\n\n const dx = Math.max(a.minX - b.maxX, b.minX - a.maxX, 0)\n const dy = Math.max(a.minY - b.maxY, b.minY - a.maxY, 0)\n\n const pointA: Point = { x: 0, y: 0 }\n const pointB: Point = { x: 0, y: 0 }\n\n if (dx === 0 && dy === 0) {\n // Boxes overlap\n return { distance: 0, pointA: boxA.center, pointB: boxB.center }\n }\n\n // Compute the closest points on the edges\n pointA.x = clamp(boxA.center.x, b.minX, b.maxX)\n pointA.y = clamp(boxA.center.y, b.minY, b.maxY)\n\n pointB.x = clamp(boxB.center.x, a.minX, a.maxX)\n pointB.y = clamp(boxB.center.y, a.minY, a.maxY)\n\n const distance = Math.hypot(pointA.x - pointB.x, pointA.y - pointB.y)\n return { distance, pointA, pointB }\n}\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(max, value))\n}\n\nexport function findNearestPointsBetweenBoxSets(\n boxSetA: BoxSet,\n boxSetB: BoxSet,\n): { pointA: Point; pointB: Point; distance: number } {\n let minDistance = Number.POSITIVE_INFINITY\n let nearestPointA: Point = { x: 0, y: 0 }\n let nearestPointB: Point = { x: 0, y: 0 }\n\n for (const boxA of boxSetA) {\n for (const boxB of boxSetB) {\n const { distance, pointA, pointB } = computeDistanceBetweenBoxes(\n boxA,\n boxB,\n )\n if (distance < minDistance) {\n minDistance = distance\n nearestPointA = pointA\n nearestPointB = pointB\n }\n }\n }\n\n return {\n pointA: nearestPointA,\n pointB: nearestPointB,\n distance: minDistance,\n }\n}\n","import type { Point } from \"./common\"\n\nexport const getUnitVectorFromPointAToB = (a: Point, b: Point): Point => {\n const delta = {\n x: b.x - a.x,\n y: b.y - a.y,\n }\n\n const magnitude = Math.sqrt(delta.x ** 2 + delta.y ** 2)\n\n return {\n x: delta.x / magnitude,\n y: delta.y / magnitude,\n }\n}\n\nexport const getUnitVectorFromDirection = (\n direction: \"up\" | \"down\" | \"left\" | \"right\",\n): Point => {\n switch (direction) {\n case \"up\":\n return { x: 0, y: 1 }\n case \"down\":\n return { x: 0, y: -1 }\n case \"left\":\n return { x: -1, y: 0 }\n case \"right\":\n return { x: 1, y: 0 }\n }\n}\n","import type { Point } from \"./common\"\n\nexport type GridCellPositions = {\n index: number\n center: Point\n topLeft: Point\n bottomRight: Point\n}\n\nexport type GridOptions = {\n rows: number\n cols: number\n xSpacing?: number\n ySpacing?: number\n width?: number\n height?: number\n offsetX?: number\n offsetY?: number\n yDirection?: \"cartesian\" | \"up-is-negative\"\n centered?: boolean\n}\n\nexport function grid({\n rows,\n cols,\n xSpacing,\n ySpacing,\n width,\n height,\n offsetX = 0,\n offsetY = 0,\n yDirection = \"cartesian\",\n centered = true,\n}: GridOptions): GridCellPositions[] {\n // Set default spacing if neither spacing nor dimensions are specified\n const effectiveXSpacing = xSpacing ?? 1\n const effectiveYSpacing = ySpacing ?? 1\n\n // Calculate cell dimensions\n const totalWidth = width ?? cols * effectiveXSpacing\n const totalHeight = height ?? rows * effectiveYSpacing\n\n // Calculate centering offsets if needed\n const centeringOffsetX = centered ? -totalWidth / 2 : 0\n const centeringOffsetY = centered ? -totalHeight / 2 : 0\n\n const cellWidth = width ? width / cols : effectiveXSpacing\n const cellHeight = height ? height / rows : effectiveYSpacing\n\n const cells: GridCellPositions[] = []\n\n for (let row = 0; row < rows; row++) {\n for (let col = 0; col < cols; col++) {\n const index = row * cols + col\n\n // Calculate center position\n const centerX =\n offsetX + centeringOffsetX + col * cellWidth + cellWidth / 2\n const rawCenterY = offsetY + row * cellHeight + cellHeight / 2\n\n // Adjust Y coordinate based on yDirection\n const centerY =\n yDirection === \"cartesian\"\n ? offsetY +\n centeringOffsetY +\n (rows - 1 - row) * cellHeight +\n cellHeight / 2\n : offsetY + centeringOffsetY + row * cellHeight + cellHeight / 2\n\n cells.push({\n index,\n center: { x: centerX, y: centerY },\n topLeft: {\n x: centerX - cellWidth / 2,\n y: centerY + cellHeight / 2,\n },\n bottomRight: {\n x: centerX + cellWidth / 2,\n y: centerY - cellHeight / 2,\n },\n })\n }\n }\n\n return cells\n}\n"],"mappings":";AAKO,SAAS,sBACd,CAAC,IAAI,EAAE,GACP,CAAC,IAAI,EAAE,GACP;AAAA,EACE,gBAAgB;AAClB,IAEI,CAAC,GACI;AACT,MAAI,kBAAkB,GAAG;AACvB,WAAO,oBAAoB,IAAI,IAAI,IAAI,EAAE;AAAA,EAC3C;AACA,QAAM,UAAU,iBAAiB,IAAI,IAAI,IAAI,EAAE;AAC/C,SAAO,WAAW;AACpB;AAKO,SAAS,oBACd,IACA,IACA,IACA,IACS;AACT,QAAM,KAAK,YAAY,IAAI,IAAI,EAAE;AACjC,QAAM,KAAK,YAAY,IAAI,IAAI,EAAE;AACjC,QAAM,KAAK,YAAY,IAAI,IAAI,EAAE;AACjC,QAAM,KAAK,YAAY,IAAI,IAAI,EAAE;AAGjC,MAAI,OAAO,MAAM,OAAO,IAAI;AAC1B,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,KAAK,UAAU,IAAI,IAAI,EAAE,EAAG,QAAO;AAC9C,MAAI,OAAO,KAAK,UAAU,IAAI,IAAI,EAAE,EAAG,QAAO;AAC9C,MAAI,OAAO,KAAK,UAAU,IAAI,IAAI,EAAE,EAAG,QAAO;AAC9C,MAAI,OAAO,KAAK,UAAU,IAAI,IAAI,EAAE,EAAG,QAAO;AAE9C,SAAO;AACT;AAKO,SAAS,YAAY,GAAU,GAAU,GAAkB;AAChE,QAAM,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;AAC/D,MAAI,QAAQ,EAAG,QAAO;AACtB,SAAO,MAAM,IAAI,IAAI;AACvB;AAKO,SAAS,UAAU,GAAU,GAAU,GAAmB;AAC/D,SACE,EAAE,KAAK,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC,KACxB,EAAE,KAAK,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC,KACxB,EAAE,KAAK,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC,KACxB,EAAE,KAAK,KAAK,IAAI,EAAE,GAAG,EAAE,CAAC;AAE5B;AAKA,SAAS,iBAAiB,IAAW,IAAW,IAAW,IAAmB;AAE5E,MAAI,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,GAAG;AAClC,WAAO,uBAAuB,IAAI,IAAI,EAAE;AAAA,EAC1C;AACA,MAAI,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,GAAG;AAClC,WAAO,uBAAuB,IAAI,IAAI,EAAE;AAAA,EAC1C;AAGA,MAAI,oBAAoB,IAAI,IAAI,IAAI,EAAE,GAAG;AACvC,WAAO;AAAA,EACT;AAGA,QAAM,YAAY;AAAA,IAChB,uBAAuB,IAAI,IAAI,EAAE;AAAA,IACjC,uBAAuB,IAAI,IAAI,EAAE;AAAA,IACjC,uBAAuB,IAAI,IAAI,EAAE;AAAA,IACjC,uBAAuB,IAAI,IAAI,EAAE;AAAA,EACnC;AAEA,SAAO,KAAK,IAAI,GAAG,SAAS;AAC9B;AAKO,SAAS,uBAAuB,GAAU,GAAU,GAAkB;AAC3E,QAAM,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,EAAE,IAAI,EAAE,MAAM;AAC7C,MAAI,OAAO,EAAG,QAAO,SAAS,GAAG,CAAC;AAElC,MAAI,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;AAClE,MAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,CAAC,CAAC;AAE9B,QAAM,aAAa;AAAA,IACjB,GAAG,EAAE,IAAI,KAAK,EAAE,IAAI,EAAE;AAAA,IACtB,GAAG,EAAE,IAAI,KAAK,EAAE,IAAI,EAAE;AAAA,EACxB;AAEA,SAAO,SAAS,GAAG,UAAU;AAC/B;AAKO,SAAS,SAAS,IAAW,IAAmB;AACrD,QAAM,KAAK,GAAG,IAAI,GAAG;AACrB,QAAM,KAAK,GAAG,IAAI,GAAG;AACrB,SAAO,KAAK,KAAK,KAAK,KAAK,KAAK,EAAE;AACpC;;;ACpHO,SAAS,eAAe,KAAU;AACvC,QAAM,YAAY,IAAI,QAAQ;AAC9B,QAAM,aAAa,IAAI,SAAS;AAChC,SAAO;AAAA,IACL,MAAM,IAAI,OAAO,IAAI;AAAA,IACrB,MAAM,IAAI,OAAO,IAAI;AAAA,IACrB,MAAM,IAAI,OAAO,IAAI;AAAA,IACrB,MAAM,IAAI,OAAO,IAAI;AAAA,EACvB;AACF;AAEO,SAAS,4BACd,MACA,MACoD;AACpD,QAAM,IAAI,eAAe,IAAI;AAC7B,QAAM,IAAI,eAAe,IAAI;AAE7B,QAAM,KAAK,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC;AACvD,QAAM,KAAK,KAAK,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC;AAEvD,QAAM,SAAgB,EAAE,GAAG,GAAG,GAAG,EAAE;AACnC,QAAM,SAAgB,EAAE,GAAG,GAAG,GAAG,EAAE;AAEnC,MAAI,OAAO,KAAK,OAAO,GAAG;AAExB,WAAO,EAAE,UAAU,GAAG,QAAQ,KAAK,QAAQ,QAAQ,KAAK,OAAO;AAAA,EACjE;AAGA,SAAO,IAAI,MAAM,KAAK,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI;AAC9C,SAAO,IAAI,MAAM,KAAK,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI;AAE9C,SAAO,IAAI,MAAM,KAAK,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI;AAC9C,SAAO,IAAI,MAAM,KAAK,OAAO,GAAG,EAAE,MAAM,EAAE,IAAI;AAE9C,QAAMA,YAAW,KAAK,MAAM,OAAO,IAAI,OAAO,GAAG,OAAO,IAAI,OAAO,CAAC;AACpE,SAAO,EAAE,UAAAA,WAAU,QAAQ,OAAO;AACpC;AAEO,SAAS,MAAM,OAAe,KAAa,KAAqB;AACrE,SAAO,KAAK,IAAI,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC;AAC3C;AAEO,SAAS,gCACd,SACA,SACoD;AACpD,MAAI,cAAc,OAAO;AACzB,MAAI,gBAAuB,EAAE,GAAG,GAAG,GAAG,EAAE;AACxC,MAAI,gBAAuB,EAAE,GAAG,GAAG,GAAG,EAAE;AAExC,aAAW,QAAQ,SAAS;AAC1B,eAAW,QAAQ,SAAS;AAC1B,YAAM,EAAE,UAAAA,WAAU,QAAQ,OAAO,IAAI;AAAA,QACnC;AAAA,QACA;AAAA,MACF;AACA,UAAIA,YAAW,aAAa;AAC1B,sBAAcA;AACd,wBAAgB;AAChB,wBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,UAAU;AAAA,EACZ;AACF;;;AC5EO,IAAM,6BAA6B,CAAC,GAAU,MAAoB;AACvE,QAAM,QAAQ;AAAA,IACZ,GAAG,EAAE,IAAI,EAAE;AAAA,IACX,GAAG,EAAE,IAAI,EAAE;AAAA,EACb;AAEA,QAAM,YAAY,KAAK,KAAK,MAAM,KAAK,IAAI,MAAM,KAAK,CAAC;AAEvD,SAAO;AAAA,IACL,GAAG,MAAM,IAAI;AAAA,IACb,GAAG,MAAM,IAAI;AAAA,EACf;AACF;AAEO,IAAM,6BAA6B,CACxC,cACU;AACV,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,IACtB,KAAK;AACH,aAAO,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,IACvB,KAAK;AACH,aAAO,EAAE,GAAG,IAAI,GAAG,EAAE;AAAA,IACvB,KAAK;AACH,aAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACxB;AACF;;;ACPO,SAAS,KAAK;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,UAAU;AAAA,EACV,aAAa;AAAA,EACb,WAAW;AACb,GAAqC;AAEnC,QAAM,oBAAoB,YAAY;AACtC,QAAM,oBAAoB,YAAY;AAGtC,QAAM,aAAa,SAAS,OAAO;AACnC,QAAM,cAAc,UAAU,OAAO;AAGrC,QAAM,mBAAmB,WAAW,CAAC,aAAa,IAAI;AACtD,QAAM,mBAAmB,WAAW,CAAC,cAAc,IAAI;AAEvD,QAAM,YAAY,QAAQ,QAAQ,OAAO;AACzC,QAAM,aAAa,SAAS,SAAS,OAAO;AAE5C,QAAM,QAA6B,CAAC;AAEpC,WAAS,MAAM,GAAG,MAAM,MAAM,OAAO;AACnC,aAAS,MAAM,GAAG,MAAM,MAAM,OAAO;AACnC,YAAM,QAAQ,MAAM,OAAO;AAG3B,YAAM,UACJ,UAAU,mBAAmB,MAAM,YAAY,YAAY;AAC7D,YAAM,aAAa,UAAU,MAAM,aAAa,aAAa;AAG7D,YAAM,UACJ,eAAe,cACX,UACA,oBACC,OAAO,IAAI,OAAO,aACnB,aAAa,IACb,UAAU,mBAAmB,MAAM,aAAa,aAAa;AAEnE,YAAM,KAAK;AAAA,QACT;AAAA,QACA,QAAQ,EAAE,GAAG,SAAS,GAAG,QAAQ;AAAA,QACjC,SAAS;AAAA,UACP,GAAG,UAAU,YAAY;AAAA,UACzB,GAAG,UAAU,aAAa;AAAA,QAC5B;AAAA,QACA,aAAa;AAAA,UACX,GAAG,UAAU,YAAY;AAAA,UACzB,GAAG,UAAU,aAAa;AAAA,QAC5B;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;","names":["distance"]}
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Point } from './common.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns true if the two lines intersect.
|
|
5
|
+
*/
|
|
6
|
+
declare function doesLineIntersectLine([a1, a2]: [Point, Point], [b1, b2]: [Point, Point], { lineThickness, }?: {
|
|
7
|
+
lineThickness?: number;
|
|
8
|
+
}): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Returns true if the two segments intersect.
|
|
11
|
+
*/
|
|
12
|
+
declare function doSegmentsIntersect(p1: Point, q1: Point, p2: Point, q2: Point): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Returns 0 if the points are colinear, 1 if they are clockwise, and 2 if they are counterclockwise.
|
|
15
|
+
*/
|
|
16
|
+
declare function orientation(p: Point, q: Point, r: Point): number;
|
|
17
|
+
/**
|
|
18
|
+
* Returns true if q is on the segment p->r.
|
|
19
|
+
*/
|
|
20
|
+
declare function onSegment(p: Point, q: Point, r: Point): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Returns the minimum distance between a point and a segment.
|
|
23
|
+
*/
|
|
24
|
+
declare function pointToSegmentDistance(p: Point, v: Point, w: Point): number;
|
|
25
|
+
/**
|
|
26
|
+
* Returns the distance between two points.
|
|
27
|
+
*/
|
|
28
|
+
declare function distance(p1: Point, p2: Point): number;
|
|
29
|
+
|
|
30
|
+
export { distance, doSegmentsIntersect, doesLineIntersectLine, onSegment, orientation, pointToSegmentDistance };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
distance,
|
|
3
|
+
doSegmentsIntersect,
|
|
4
|
+
doesLineIntersectLine,
|
|
5
|
+
onSegment,
|
|
6
|
+
orientation,
|
|
7
|
+
pointToSegmentDistance
|
|
8
|
+
} from "./chunk-CHQOCSFB.js";
|
|
9
|
+
export {
|
|
10
|
+
distance,
|
|
11
|
+
doSegmentsIntersect,
|
|
12
|
+
doesLineIntersectLine,
|
|
13
|
+
onSegment,
|
|
14
|
+
orientation,
|
|
15
|
+
pointToSegmentDistance
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=line-intersections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Point } from './common.js';
|
|
2
|
+
|
|
3
|
+
type Box = {
|
|
4
|
+
center: Point;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
};
|
|
8
|
+
type BoxSet = Box[];
|
|
9
|
+
type GridCell = {
|
|
10
|
+
boxes: Box[];
|
|
11
|
+
};
|
|
12
|
+
declare function getBoundingBox(box: Box): {
|
|
13
|
+
minX: number;
|
|
14
|
+
maxX: number;
|
|
15
|
+
minY: number;
|
|
16
|
+
maxY: number;
|
|
17
|
+
};
|
|
18
|
+
declare function computeDistanceBetweenBoxes(boxA: Box, boxB: Box): {
|
|
19
|
+
distance: number;
|
|
20
|
+
pointA: Point;
|
|
21
|
+
pointB: Point;
|
|
22
|
+
};
|
|
23
|
+
declare function clamp(value: number, min: number, max: number): number;
|
|
24
|
+
declare function findNearestPointsBetweenBoxSets(boxSetA: BoxSet, boxSetB: BoxSet): {
|
|
25
|
+
pointA: Point;
|
|
26
|
+
pointB: Point;
|
|
27
|
+
distance: number;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export { type Box, type BoxSet, type GridCell, clamp, computeDistanceBetweenBoxes, findNearestPointsBetweenBoxSets, getBoundingBox };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clamp,
|
|
3
|
+
computeDistanceBetweenBoxes,
|
|
4
|
+
findNearestPointsBetweenBoxSets,
|
|
5
|
+
getBoundingBox
|
|
6
|
+
} from "./chunk-MHHTZHOJ.js";
|
|
7
|
+
export {
|
|
8
|
+
clamp,
|
|
9
|
+
computeDistanceBetweenBoxes,
|
|
10
|
+
findNearestPointsBetweenBoxSets,
|
|
11
|
+
getBoundingBox
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=nearest-box.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/math-utils",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.10",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./line-intersections": {
|
|
14
|
+
"import": "./dist/line-intersections.js",
|
|
15
|
+
"types": "./dist/line-intersections.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./nearest-box": {
|
|
18
|
+
"import": "./dist/nearest-box.js",
|
|
19
|
+
"types": "./dist/nearest-box.d.ts"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
8
22
|
"files": [
|
|
9
23
|
"dist"
|
|
10
24
|
],
|
|
11
25
|
"scripts": {
|
|
12
|
-
"build": "tsup-node src
|
|
26
|
+
"build": "tsup-node src --format esm --dts --sourcemap"
|
|
13
27
|
},
|
|
14
28
|
"devDependencies": {
|
|
15
29
|
"@biomejs/biome": "^1.9.4",
|