import { EPSILON } from "../excalidraw/constants"; import { pointCenter, pointDistanceSq, pointFrom, pointRotateRads, pointsEqual, } from "./point"; import type { GlobalPoint, Line, LocalPoint, Radians } from "./types"; import { vectorCross, vectorFromPoint } from "./vector"; /** * Create a line from two points. * * @param points The two points lying on the line * @returns The line on which the points lie */ export function line
(a: P, b: P): Line
{ return [a, b] as Line
; } /** * Convenient point creation from an array of two points. * * @param param0 The array with the two points to convert to a line * @returns The created line */ export function lineFromPointPair
([a, b]: [ P, P, ]): Line
{ return line(a, b); } /** * TODO * * @param pointArray * @returns */ export function lineFromPointArray
( pointArray: P[], ): Line
| undefined { return pointArray.length === 2 ? line
(pointArray[0], pointArray[1])
: undefined;
}
/**
* Return the coordinates resulting from rotating the given line about an
* origin by an angle in degrees note that when the origin is not given,
* the midpoint of the given line is used as the origin
*
* @param l
* @param angle
* @param origin
* @returns
*/
export function lineRotate (
l: Line ,
p: P,
epsilon: number = EPSILON,
) {
const p1 = vectorFromPoint(l[1], l[0]);
const p2 = vectorFromPoint(p, l[0]);
const r = vectorCross(p1, p2);
return Math.abs(r) < epsilon;
}
export function lineClosestPoint (
l: Line ,
p: P,
): P {
if (pointsEqual(l[0], l[1])) {
return l[0];
}
const t =
((p[0] - l[0][0]) * (l[1][0] - l[0][0]) +
(p[1] - l[0][1]) * (l[1][1] - l[0][1])) /
pointDistanceSq(l[0], l[1]);
return pointFrom(
l[0][0] + t * (l[1][0] - l[0][0]),
l[0][1] + t * (l[1][1] - l[0][1]),
);
}