You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
1.8 KiB
72 lines
1.8 KiB
import { |
|
vectorCross, |
|
vectorFromPoint, |
|
type GlobalPoint, |
|
type LocalPoint, |
|
} from "../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) |
|
); |
|
}
|
|
|