Linear distance calc

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
Mark Tolmacs 2025-05-07 22:27:49 +02:00
parent 3b1c6444e2
commit 2082ef149c
No known key found for this signature in database

View File

@ -1,8 +1,8 @@
import { import {
curvePointDistance, curvePointDistance,
distanceToLineSegment, distanceToLineSegment,
lineSegment, isCurve,
pointFrom, isLineSegment,
pointRotateRads, pointRotateRads,
} from "@excalidraw/math"; } from "@excalidraw/math";
@ -10,10 +10,16 @@ import { ellipse, ellipseDistanceFromPoint } from "@excalidraw/math/ellipse";
import { elementCenterPoint } from "@excalidraw/common"; import { elementCenterPoint } from "@excalidraw/common";
import type { GlobalPoint, Radians } from "@excalidraw/math"; import type {
Curve,
GlobalPoint,
LineSegment,
Radians,
} from "@excalidraw/math";
import { import {
deconstructDiamondElement, deconstructDiamondElement,
deconstructLinearOrFreeDrawElement,
deconstructRectanguloidElement, deconstructRectanguloidElement,
} from "./utils"; } from "./utils";
@ -21,6 +27,8 @@ import type {
ExcalidrawDiamondElement, ExcalidrawDiamondElement,
ExcalidrawElement, ExcalidrawElement,
ExcalidrawEllipseElement, ExcalidrawEllipseElement,
ExcalidrawFreeDrawElement,
ExcalidrawLinearElement,
ExcalidrawRectanguloidElement, ExcalidrawRectanguloidElement,
} from "./types"; } from "./types";
@ -45,20 +53,7 @@ export const distanceToElement = (
case "line": case "line":
case "arrow": case "arrow":
case "freedraw": case "freedraw":
return element.points.reduce((acc, point, idx) => { return distanceToLinearOrFreeDraElement(element, p);
if (idx === 0) {
return acc;
}
const prevPoint = element.points[idx - 1];
const segment = lineSegment(
pointFrom<GlobalPoint>(
element.x + prevPoint[0],
element.y + prevPoint[1],
),
pointFrom<GlobalPoint>(element.x + point[0], element.y + point[1]),
);
return Math.min(acc, distanceToLineSegment(p, segment));
}, Infinity);
} }
}; };
@ -137,3 +132,36 @@ const distanceToEllipseElement = (
ellipse(center, element.width / 2, element.height / 2), ellipse(center, element.width / 2, element.height / 2),
); );
}; };
const distanceToLinearOrFreeDraElement = (
element: ExcalidrawLinearElement | ExcalidrawFreeDrawElement,
p: GlobalPoint,
) => {
const shapes = deconstructLinearOrFreeDrawElement(element);
let distance = Infinity;
for (const shape of shapes) {
switch (true) {
case isCurve(shape): {
const d = curvePointDistance(shape as Curve<GlobalPoint>, p);
if (d < distance) {
distance = d;
}
continue;
}
case isLineSegment(shape): {
const d = distanceToLineSegment(p, shape as LineSegment<GlobalPoint>);
if (d < distance) {
distance = d;
}
continue;
}
}
}
return distance;
};