mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-11-16 10:45:44 +01:00
refactor: separate elements logic into a standalone package (#9285)
This commit is contained in:
73
packages/utils/src/bbox.ts
Normal file
73
packages/utils/src/bbox.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import {
|
||||
vectorCross,
|
||||
vectorFromPoint,
|
||||
type GlobalPoint,
|
||||
type LocalPoint,
|
||||
} from "@excalidraw/math";
|
||||
|
||||
import type { Bounds } from "@excalidraw/element/bounds";
|
||||
|
||||
export type LineSegment<P extends LocalPoint | GlobalPoint> = [P, P];
|
||||
|
||||
export function getBBox<P extends LocalPoint | GlobalPoint>(
|
||||
line: LineSegment<P>,
|
||||
): Bounds {
|
||||
return [
|
||||
Math.min(line[0][0], line[1][0]),
|
||||
Math.min(line[0][1], line[1][1]),
|
||||
Math.max(line[0][0], line[1][0]),
|
||||
Math.max(line[0][1], line[1][1]),
|
||||
];
|
||||
}
|
||||
|
||||
export function doBBoxesIntersect(a: Bounds, b: Bounds) {
|
||||
return a[0] <= b[2] && a[2] >= b[0] && a[1] <= b[3] && a[3] >= b[1];
|
||||
}
|
||||
|
||||
const EPSILON = 0.000001;
|
||||
|
||||
export function isPointOnLine<P extends GlobalPoint | LocalPoint>(
|
||||
l: LineSegment<P>,
|
||||
p: P,
|
||||
) {
|
||||
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 isPointRightOfLine<P extends GlobalPoint | LocalPoint>(
|
||||
l: LineSegment<P>,
|
||||
p: P,
|
||||
) {
|
||||
const p1 = vectorFromPoint(l[1], l[0]);
|
||||
const p2 = vectorFromPoint(p, l[0]);
|
||||
|
||||
return vectorCross(p1, p2) < 0;
|
||||
}
|
||||
|
||||
export function isLineSegmentTouchingOrCrossingLine<
|
||||
P extends GlobalPoint | LocalPoint,
|
||||
>(a: LineSegment<P>, b: LineSegment<P>) {
|
||||
return (
|
||||
isPointOnLine(a, b[0]) ||
|
||||
isPointOnLine(a, b[1]) ||
|
||||
(isPointRightOfLine(a, b[0])
|
||||
? !isPointRightOfLine(a, b[1])
|
||||
: isPointRightOfLine(a, b[1]))
|
||||
);
|
||||
}
|
||||
|
||||
// https://martin-thoma.com/how-to-check-if-two-line-segments-intersect/
|
||||
export function doLineSegmentsIntersect<P extends GlobalPoint | LocalPoint>(
|
||||
a: LineSegment<P>,
|
||||
b: LineSegment<P>,
|
||||
) {
|
||||
return (
|
||||
doBBoxesIntersect(getBBox(a), getBBox(b)) &&
|
||||
isLineSegmentTouchingOrCrossingLine(a, b) &&
|
||||
isLineSegmentTouchingOrCrossingLine(b, a)
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user