From e8abddeecf7424aca9ad28a0fb6dc94b3c6af999 Mon Sep 17 00:00:00 2001 From: Mark Tolmacs Date: Wed, 19 Feb 2025 21:57:50 +0100 Subject: [PATCH] [skip ci] Refactor Signed-off-by: Mark Tolmacs --- packages/excalidraw/tests/rotate.test.tsx | 8 +++--- packages/math/line.test.ts | 22 +--------------- packages/math/line.ts | 31 +---------------------- packages/math/rectangle.ts | 8 ++++-- packages/math/segment.test.ts | 21 +++++++++++++++ packages/math/segment.ts | 24 ++++++++++++++++++ 6 files changed, 57 insertions(+), 57 deletions(-) create mode 100644 packages/math/segment.test.ts diff --git a/packages/excalidraw/tests/rotate.test.tsx b/packages/excalidraw/tests/rotate.test.tsx index c44f7c4317..16de171683 100644 --- a/packages/excalidraw/tests/rotate.test.tsx +++ b/packages/excalidraw/tests/rotate.test.tsx @@ -70,13 +70,13 @@ test("unselected bound arrows update when rotating their target elements", async expect(ellipseArrow.x).toEqual(0); expect(ellipseArrow.y).toEqual(0); expect(ellipseArrow.points[0]).toEqual([0, 0]); - expect(ellipseArrow.points[1][0]).toBeCloseTo(56.1, 1); - expect(ellipseArrow.points[1][1]).toBeCloseTo(116.85, 1); + expect(ellipseArrow.points[1][0]).toBeCloseTo(28.49, 1); + expect(ellipseArrow.points[1][1]).toBeCloseTo(155.9, 1); expect(textArrow.endBinding?.elementId).toEqual(text.id); expect(textArrow.x).toEqual(360); expect(textArrow.y).toEqual(300); expect(textArrow.points[0]).toEqual([0, 0]); - expect(textArrow.points[1][0]).toBeCloseTo(-89, 0); - expect(textArrow.points[1][1]).toBeCloseTo(-120.39, 0); + expect(textArrow.points[1][0]).toBeCloseTo(-95, 0); + expect(textArrow.points[1][1]).toBeCloseTo(-114.59, 0); }); diff --git a/packages/math/line.test.ts b/packages/math/line.test.ts index 8e398c42a1..0e6bb1cc8f 100644 --- a/packages/math/line.test.ts +++ b/packages/math/line.test.ts @@ -1,6 +1,5 @@ -import { line, lineSegmentIntersectionPoints, linesIntersectAt } from "./line"; +import { line, linesIntersectAt } from "./line"; import { pointFrom } from "./point"; -import { lineSegment } from "./segment"; describe("line-line intersections", () => { it("should correctly detect intersection at origin", () => { @@ -30,22 +29,3 @@ describe("line-line intersections", () => { ).toBe(null); }); }); - -describe("line-segment intersections", () => { - it("should correctly detect intersection", () => { - expect( - lineSegmentIntersectionPoints( - lineSegment(pointFrom(0, 0), pointFrom(5, 0)), - lineSegment(pointFrom(2, -2), pointFrom(3, 2)), - ), - ).toEqual(pointFrom(2.5, 0)); - }); - it("should correctly detect non-intersection", () => { - expect( - lineSegmentIntersectionPoints( - lineSegment(pointFrom(0, 0), pointFrom(5, 0)), - lineSegment(pointFrom(3, 1), pointFrom(4, 4)), - ), - ).toEqual(null); - }); -}); diff --git a/packages/math/line.ts b/packages/math/line.ts index 020a1a9877..bacd48e242 100644 --- a/packages/math/line.ts +++ b/packages/math/line.ts @@ -6,14 +6,7 @@ import { pointRotateRads, pointsEqual, } from "./point"; -import { pointOnLineSegment } from "./segment"; -import type { - GlobalPoint, - Line, - LineSegment, - LocalPoint, - Radians, -} from "./types"; +import type { GlobalPoint, Line, LocalPoint, Radians } from "./types"; import { vectorCross, vectorFromPoint } from "./vector"; /** @@ -100,28 +93,6 @@ export function linesIntersectAt( return null; } -/** - * Returns the intersection point of a segment and a line - * - * @param l - * @param s - * @returns - */ -export function lineSegmentIntersectionPoints< - Point extends GlobalPoint | LocalPoint, ->(l: LineSegment, s: LineSegment): Point | null { - const candidate = linesIntersectAt(line(l[0], l[1]), line(s[0], s[1])); - if ( - !candidate || - !pointOnLineSegment(candidate, s) || - !pointOnLineSegment(candidate, l) - ) { - return null; - } - - return candidate; -} - export function isPointOnLine

( l: Line

, p: P, diff --git a/packages/math/rectangle.ts b/packages/math/rectangle.ts index 88df59f9ea..519c83a27c 100644 --- a/packages/math/rectangle.ts +++ b/packages/math/rectangle.ts @@ -1,7 +1,11 @@ import { invariant } from "../excalidraw/utils"; -import { line, lineSegmentIntersectionPoints, linesIntersectAt } from "./line"; +import { line, linesIntersectAt } from "./line"; import { pointFrom } from "./point"; -import { distanceToLineSegment, lineSegment } from "./segment"; +import { + distanceToLineSegment, + lineSegment, + lineSegmentIntersectionPoints, +} from "./segment"; import type { GlobalPoint, Line, diff --git a/packages/math/segment.test.ts b/packages/math/segment.test.ts new file mode 100644 index 0000000000..4237a3c855 --- /dev/null +++ b/packages/math/segment.test.ts @@ -0,0 +1,21 @@ +import { pointFrom } from "./point"; +import { lineSegment, lineSegmentIntersectionPoints } from "./segment"; + +describe("line-segment intersections", () => { + it("should correctly detect intersection", () => { + expect( + lineSegmentIntersectionPoints( + lineSegment(pointFrom(0, 0), pointFrom(5, 0)), + lineSegment(pointFrom(2, -2), pointFrom(3, 2)), + ), + ).toEqual(pointFrom(2.5, 0)); + }); + it("should correctly detect non-intersection", () => { + expect( + lineSegmentIntersectionPoints( + lineSegment(pointFrom(0, 0), pointFrom(5, 0)), + lineSegment(pointFrom(3, 1), pointFrom(4, 4)), + ), + ).toEqual(null); + }); +}); diff --git a/packages/math/segment.ts b/packages/math/segment.ts index 6c0c2de342..d86681bbdd 100644 --- a/packages/math/segment.ts +++ b/packages/math/segment.ts @@ -1,3 +1,4 @@ +import { line, linesIntersectAt } from "./line"; import { isPoint, pointCenter, @@ -156,3 +157,26 @@ export const distanceToLineSegment = ( const dy = y - yy; return Math.sqrt(dx * dx + dy * dy); }; + +/** + * Returns the intersection point of a segment and a line + * + * @param l + * @param s + * @returns + */ +export function lineSegmentIntersectionPoints< + Point extends GlobalPoint | LocalPoint, +>(l: LineSegment, s: LineSegment): Point | null { + const candidate = linesIntersectAt(line(l[0], l[1]), line(s[0], s[1])); + + if ( + !candidate || + !pointOnLineSegment(candidate, s) || + !pointOnLineSegment(candidate, l) + ) { + return null; + } + + return candidate; +}