mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
Refactoring bounds, arrows, bboxes
This commit is contained in:
parent
9eb08df3ea
commit
dff60e6f6f
10 changed files with 318 additions and 408 deletions
|
@ -1,71 +0,0 @@
|
|||
import type { LineSegment } from "../math";
|
||||
import {
|
||||
vectorCross,
|
||||
vectorFromPoint,
|
||||
type GlobalPoint,
|
||||
type LocalPoint,
|
||||
} from "../math";
|
||||
import type { Bounds } from "../excalidraw/element/bounds";
|
||||
|
||||
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)
|
||||
);
|
||||
}
|
|
@ -89,22 +89,3 @@ describe("point and ellipse", () => {
|
|||
expect(pointInEllipse(point(-1.4, 0.8), ellipse)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("line and line", () => {
|
||||
const lineA: LineSegment<GlobalPoint> = lineSegment(point(1, 4), point(3, 4));
|
||||
const lineB: LineSegment<GlobalPoint> = lineSegment(point(2, 1), point(2, 7));
|
||||
const lineC: LineSegment<GlobalPoint> = lineSegment(point(1, 8), point(3, 8));
|
||||
const lineD: LineSegment<GlobalPoint> = lineSegment(point(1, 8), point(3, 8));
|
||||
const lineE: LineSegment<GlobalPoint> = lineSegment(point(1, 9), point(3, 9));
|
||||
const lineF: LineSegment<GlobalPoint> = lineSegment(point(1, 2), point(3, 4));
|
||||
const lineG: LineSegment<GlobalPoint> = lineSegment(point(0, 1), point(2, 3));
|
||||
|
||||
it("intersection", () => {
|
||||
expect(segmentsIntersectAt(lineA, lineB)).toEqual([2, 4]);
|
||||
expect(segmentsIntersectAt(lineA, lineC)).toBe(null);
|
||||
expect(segmentsIntersectAt(lineB, lineC)).toBe(null);
|
||||
expect(segmentsIntersectAt(lineC, lineD)).toBe(null); // Line overlapping line is not intersection!
|
||||
expect(segmentsIntersectAt(lineE, lineD)).toBe(null);
|
||||
expect(segmentsIntersectAt(lineF, lineG)).toBe(null);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
export * from "./export";
|
||||
export * from "./withinBounds";
|
||||
export * from "./bbox";
|
||||
export { getCommonBounds } from "../excalidraw/element/bounds";
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue