Small refactor

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
Mark Tolmacs 2025-01-14 14:09:49 +01:00
parent 028c397c0a
commit 47064a3662
No known key found for this signature in database
4 changed files with 35 additions and 48 deletions

View file

@ -798,14 +798,18 @@ export const bindPointToSnapToElementOutline = (
const intersections: GlobalPoint[] = [
...(intersectElementWithLine(
bindableElement,
pointFrom(p[0], p[1] - 2 * bindableElement.height),
pointFrom(p[0], p[1] + 2 * bindableElement.height),
line(
pointFrom(p[0], p[1] - 2 * bindableElement.height),
pointFrom(p[0], p[1] + 2 * bindableElement.height),
),
FIXED_BINDING_DISTANCE,
) ?? []),
...(intersectElementWithLine(
bindableElement,
pointFrom(p[0] - 2 * bindableElement.width, p[1]),
pointFrom(p[0] + 2 * bindableElement.width, p[1]),
line(
pointFrom(p[0] - 2 * bindableElement.width, p[1]),
pointFrom(p[0] + 2 * bindableElement.width, p[1]),
),
FIXED_BINDING_DISTANCE,
) ?? []),
].filter((p) => p != null);
@ -1102,8 +1106,7 @@ const updateBoundPoint = (
} else {
const intersections = intersectElementWithLine(
bindableElement,
adjacentPoint,
focusPointAbsolute,
line<GlobalPoint>(adjacentPoint, focusPointAbsolute),
binding.gap,
);
if (!intersections || intersections.length === 0) {

View file

@ -1,6 +1,7 @@
import { intersectElementWithLine } from "./collision";
import { newElement } from "./newElement";
import { pointFrom } from "../../math";
import type { GlobalPoint } from "../../math";
import { lineFromPointPair, pointFrom } from "../../math";
import { ROUNDNESS } from "..";
describe("intersection with element", () => {
@ -150,8 +151,7 @@ describe("intersection with element", () => {
type: ROUNDNESS.PROPORTIONAL_RADIUS,
},
}),
pointFrom(0, -30),
pointFrom(0, -25),
lineFromPointPair<GlobalPoint>([pointFrom(0, -30), pointFrom(0, -25)]),
).map((p) =>
pointFrom(Math.round(p[0] * 100) / 100, Math.round(p[1] * 100) / 100),
),
@ -169,8 +169,7 @@ describe("intersection with element", () => {
type: ROUNDNESS.PROPORTIONAL_RADIUS,
},
}),
pointFrom(-30, 0),
pointFrom(-25, 0),
lineFromPointPair<GlobalPoint>([pointFrom(-30, 0), pointFrom(-25, 0)]),
).map((p) =>
pointFrom(Math.round(p[0] * 100) / 100, Math.round(p[1] * 100) / 100),
),

View file

@ -6,11 +6,7 @@ import type {
ExcalidrawRectangleElement,
ExcalidrawRectanguloidElement,
} from "./types";
import {
createDiamondArc,
createDiamondSide,
getElementBounds,
} from "./bounds";
import { createDiamondArc, getElementBounds } from "./bounds";
import type { FrameNameBounds } from "../types";
import type { GeometricShape } from "../../utils/geometry/shape";
import { getPolygonShape } from "../../utils/geometry/shape";
@ -23,7 +19,7 @@ import {
isTextElement,
} from "./typeChecks";
import { getBoundTextShape, getCornerRadius } from "../shapes";
import type { Arc, GlobalPoint, Polygon } from "../../math";
import type { Arc, GlobalPoint, Line, Polygon } from "../../math";
import {
pathIsALoop,
isPointWithinBounds,
@ -148,8 +144,7 @@ export const hitElementBoundText = (
export const intersectElementWithLine = (
element: ExcalidrawElement,
a: GlobalPoint,
b: GlobalPoint,
line: Line<GlobalPoint>,
offset: number = 0,
): GlobalPoint[] => {
switch (element.type) {
@ -160,11 +155,11 @@ export const intersectElementWithLine = (
case "embeddable":
case "frame":
case "magicframe":
return intersectRectanguloidWithLine(element, a, b, offset);
return intersectRectanguloidWithLine(element, line, offset);
case "diamond":
return intersectDiamondWithLine(element, a, b, offset);
return intersectDiamondWithLine(element, line, offset);
case "ellipse":
return intersectEllipseWithLine(element, a, b, offset);
return intersectEllipseWithLine(element, line, offset);
default:
throw new Error(`Unimplemented element type '${element.type}'`);
}
@ -172,8 +167,7 @@ export const intersectElementWithLine = (
const intersectRectanguloidWithLine = (
element: ExcalidrawRectanguloidElement,
a: GlobalPoint,
b: GlobalPoint,
l: Line<GlobalPoint>,
offset: number,
): GlobalPoint[] => {
const r = rectangle(
@ -190,12 +184,12 @@ const intersectRectanguloidWithLine = (
// To emulate a rotated rectangle we rotate the point in the inverse angle
// instead. It's all the same distance-wise.
const rotatedA = pointRotateRads<GlobalPoint>(
a,
l[0],
center,
radians(-element.angle),
);
const rotatedB = pointRotateRads<GlobalPoint>(
b,
l[1],
center,
radians(-element.angle),
);
@ -265,7 +259,7 @@ const intersectRectanguloidWithLine = (
.filter(
(p, idx, points) => points.findIndex((d) => pointsEqual(p, d)) === idx,
)
.sort((g, h) => pointDistanceSq(g!, a) - pointDistanceSq(h!, a))
.sort((g, h) => pointDistanceSq(g!, l[0]) - pointDistanceSq(h!, l[1]))
);
};
@ -278,8 +272,7 @@ const intersectRectanguloidWithLine = (
*/
const intersectDiamondWithLine = (
element: ExcalidrawDiamondElement,
a: GlobalPoint,
b: GlobalPoint,
l: Line<GlobalPoint>,
offset: number = 0,
): GlobalPoint[] => {
const top = pointFrom<GlobalPoint>(
@ -310,8 +303,8 @@ const intersectDiamondWithLine = (
// Rotate the point to the inverse direction to simulate the rotated diamond
// points. It's all the same distance-wise.
const rotatedA = pointRotateRads(a, center, radians(-element.angle));
const rotatedB = pointRotateRads(b, center, radians(-element.angle));
const rotatedA = pointRotateRads(l[0], center, radians(-element.angle));
const rotatedB = pointRotateRads(l[1], center, radians(-element.angle));
const topRight = segment<GlobalPoint>(
pointFrom(top[0] + verticalRadius, top[1] + horizontalRadius),
@ -393,7 +386,7 @@ const intersectDiamondWithLine = (
.filter(
(p, idx, points) => points.findIndex((d) => pointsEqual(p, d)) === idx,
)
.sort((g, h) => pointDistanceSq(g!, a) - pointDistanceSq(h!, a))
.sort((g, h) => pointDistanceSq(g!, l[0]) - pointDistanceSq(h!, l[1]))
);
};
@ -406,8 +399,7 @@ const intersectDiamondWithLine = (
*/
const intersectEllipseWithLine = (
element: ExcalidrawEllipseElement,
a: GlobalPoint,
b: GlobalPoint,
l: Line<GlobalPoint>,
offset: number = 0,
): GlobalPoint[] => {
const center = pointFrom<GlobalPoint>(
@ -415,13 +407,13 @@ const intersectEllipseWithLine = (
element.y + element.height / 2,
);
const rotatedA = pointRotateRads(a, center, radians(-element.angle));
const rotatedB = pointRotateRads(b, center, radians(-element.angle));
const rotatedA = pointRotateRads(l[0], center, radians(-element.angle));
const rotatedB = pointRotateRads(l[1], center, radians(-element.angle));
return ellipseLineIntersectionPoints(
ellipse(center, element.width / 2 + offset, element.height / 2 + offset),
line(rotatedA, rotatedB),
)
.map((p) => pointRotateRads(p, center, element.angle))
.sort((g, h) => pointDistanceSq(g!, a) - pointDistanceSq(h!, a));
.sort((g, h) => pointDistanceSq(g!, l[0]) - pointDistanceSq(h!, l[1]));
};

View file

@ -262,7 +262,7 @@ const generateElementCanvas = (
context.filter = IMAGE_INVERT_FILTER;
}
drawElementOnCanvas(element, rc, context, renderConfig, appState);
drawElementOnCanvas(element, rc, context, renderConfig);
context.restore();
@ -392,7 +392,6 @@ const drawElementOnCanvas = (
rc: RoughCanvas,
context: CanvasRenderingContext2D,
renderConfig: StaticCanvasRenderConfig,
appState: StaticCanvasAppState,
) => {
switch (element.type) {
case "rectangle":
@ -779,7 +778,7 @@ export const renderElement = (
context.translate(cx, cy);
context.rotate(element.angle);
context.translate(-shiftX, -shiftY);
drawElementOnCanvas(element, rc, context, renderConfig, appState);
drawElementOnCanvas(element, rc, context, renderConfig);
context.restore();
} else {
const elementWithCanvas = generateElementWithCanvas(
@ -875,13 +874,7 @@ export const renderElement = (
tempCanvasContext.translate(-shiftX, -shiftY);
drawElementOnCanvas(
element,
tempRc,
tempCanvasContext,
renderConfig,
appState,
);
drawElementOnCanvas(element, tempRc, tempCanvasContext, renderConfig);
tempCanvasContext.translate(shiftX, shiftY);
@ -920,7 +913,7 @@ export const renderElement = (
}
context.translate(-shiftX, -shiftY);
drawElementOnCanvas(element, rc, context, renderConfig, appState);
drawElementOnCanvas(element, rc, context, renderConfig);
}
context.restore();