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

View file

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

View file

@ -6,11 +6,7 @@ import type {
ExcalidrawRectangleElement, ExcalidrawRectangleElement,
ExcalidrawRectanguloidElement, ExcalidrawRectanguloidElement,
} from "./types"; } from "./types";
import { import { createDiamondArc, getElementBounds } from "./bounds";
createDiamondArc,
createDiamondSide,
getElementBounds,
} from "./bounds";
import type { FrameNameBounds } from "../types"; import type { FrameNameBounds } from "../types";
import type { GeometricShape } from "../../utils/geometry/shape"; import type { GeometricShape } from "../../utils/geometry/shape";
import { getPolygonShape } from "../../utils/geometry/shape"; import { getPolygonShape } from "../../utils/geometry/shape";
@ -23,7 +19,7 @@ import {
isTextElement, isTextElement,
} from "./typeChecks"; } from "./typeChecks";
import { getBoundTextShape, getCornerRadius } from "../shapes"; import { getBoundTextShape, getCornerRadius } from "../shapes";
import type { Arc, GlobalPoint, Polygon } from "../../math"; import type { Arc, GlobalPoint, Line, Polygon } from "../../math";
import { import {
pathIsALoop, pathIsALoop,
isPointWithinBounds, isPointWithinBounds,
@ -148,8 +144,7 @@ export const hitElementBoundText = (
export const intersectElementWithLine = ( export const intersectElementWithLine = (
element: ExcalidrawElement, element: ExcalidrawElement,
a: GlobalPoint, line: Line<GlobalPoint>,
b: GlobalPoint,
offset: number = 0, offset: number = 0,
): GlobalPoint[] => { ): GlobalPoint[] => {
switch (element.type) { switch (element.type) {
@ -160,11 +155,11 @@ export const intersectElementWithLine = (
case "embeddable": case "embeddable":
case "frame": case "frame":
case "magicframe": case "magicframe":
return intersectRectanguloidWithLine(element, a, b, offset); return intersectRectanguloidWithLine(element, line, offset);
case "diamond": case "diamond":
return intersectDiamondWithLine(element, a, b, offset); return intersectDiamondWithLine(element, line, offset);
case "ellipse": case "ellipse":
return intersectEllipseWithLine(element, a, b, offset); return intersectEllipseWithLine(element, line, offset);
default: default:
throw new Error(`Unimplemented element type '${element.type}'`); throw new Error(`Unimplemented element type '${element.type}'`);
} }
@ -172,8 +167,7 @@ export const intersectElementWithLine = (
const intersectRectanguloidWithLine = ( const intersectRectanguloidWithLine = (
element: ExcalidrawRectanguloidElement, element: ExcalidrawRectanguloidElement,
a: GlobalPoint, l: Line<GlobalPoint>,
b: GlobalPoint,
offset: number, offset: number,
): GlobalPoint[] => { ): GlobalPoint[] => {
const r = rectangle( const r = rectangle(
@ -190,12 +184,12 @@ const intersectRectanguloidWithLine = (
// To emulate a rotated rectangle we rotate the point in the inverse angle // To emulate a rotated rectangle we rotate the point in the inverse angle
// instead. It's all the same distance-wise. // instead. It's all the same distance-wise.
const rotatedA = pointRotateRads<GlobalPoint>( const rotatedA = pointRotateRads<GlobalPoint>(
a, l[0],
center, center,
radians(-element.angle), radians(-element.angle),
); );
const rotatedB = pointRotateRads<GlobalPoint>( const rotatedB = pointRotateRads<GlobalPoint>(
b, l[1],
center, center,
radians(-element.angle), radians(-element.angle),
); );
@ -265,7 +259,7 @@ const intersectRectanguloidWithLine = (
.filter( .filter(
(p, idx, points) => points.findIndex((d) => pointsEqual(p, d)) === idx, (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 = ( const intersectDiamondWithLine = (
element: ExcalidrawDiamondElement, element: ExcalidrawDiamondElement,
a: GlobalPoint, l: Line<GlobalPoint>,
b: GlobalPoint,
offset: number = 0, offset: number = 0,
): GlobalPoint[] => { ): GlobalPoint[] => {
const top = pointFrom<GlobalPoint>( const top = pointFrom<GlobalPoint>(
@ -310,8 +303,8 @@ const intersectDiamondWithLine = (
// Rotate the point to the inverse direction to simulate the rotated diamond // Rotate the point to the inverse direction to simulate the rotated diamond
// points. It's all the same distance-wise. // points. It's all the same distance-wise.
const rotatedA = pointRotateRads(a, center, radians(-element.angle)); const rotatedA = pointRotateRads(l[0], center, radians(-element.angle));
const rotatedB = pointRotateRads(b, center, radians(-element.angle)); const rotatedB = pointRotateRads(l[1], center, radians(-element.angle));
const topRight = segment<GlobalPoint>( const topRight = segment<GlobalPoint>(
pointFrom(top[0] + verticalRadius, top[1] + horizontalRadius), pointFrom(top[0] + verticalRadius, top[1] + horizontalRadius),
@ -393,7 +386,7 @@ const intersectDiamondWithLine = (
.filter( .filter(
(p, idx, points) => points.findIndex((d) => pointsEqual(p, d)) === idx, (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 = ( const intersectEllipseWithLine = (
element: ExcalidrawEllipseElement, element: ExcalidrawEllipseElement,
a: GlobalPoint, l: Line<GlobalPoint>,
b: GlobalPoint,
offset: number = 0, offset: number = 0,
): GlobalPoint[] => { ): GlobalPoint[] => {
const center = pointFrom<GlobalPoint>( const center = pointFrom<GlobalPoint>(
@ -415,13 +407,13 @@ const intersectEllipseWithLine = (
element.y + element.height / 2, element.y + element.height / 2,
); );
const rotatedA = pointRotateRads(a, center, radians(-element.angle)); const rotatedA = pointRotateRads(l[0], center, radians(-element.angle));
const rotatedB = pointRotateRads(b, center, radians(-element.angle)); const rotatedB = pointRotateRads(l[1], center, radians(-element.angle));
return ellipseLineIntersectionPoints( return ellipseLineIntersectionPoints(
ellipse(center, element.width / 2 + offset, element.height / 2 + offset), ellipse(center, element.width / 2 + offset, element.height / 2 + offset),
line(rotatedA, rotatedB), line(rotatedA, rotatedB),
) )
.map((p) => pointRotateRads(p, center, element.angle)) .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; context.filter = IMAGE_INVERT_FILTER;
} }
drawElementOnCanvas(element, rc, context, renderConfig, appState); drawElementOnCanvas(element, rc, context, renderConfig);
context.restore(); context.restore();
@ -392,7 +392,6 @@ const drawElementOnCanvas = (
rc: RoughCanvas, rc: RoughCanvas,
context: CanvasRenderingContext2D, context: CanvasRenderingContext2D,
renderConfig: StaticCanvasRenderConfig, renderConfig: StaticCanvasRenderConfig,
appState: StaticCanvasAppState,
) => { ) => {
switch (element.type) { switch (element.type) {
case "rectangle": case "rectangle":
@ -779,7 +778,7 @@ export const renderElement = (
context.translate(cx, cy); context.translate(cx, cy);
context.rotate(element.angle); context.rotate(element.angle);
context.translate(-shiftX, -shiftY); context.translate(-shiftX, -shiftY);
drawElementOnCanvas(element, rc, context, renderConfig, appState); drawElementOnCanvas(element, rc, context, renderConfig);
context.restore(); context.restore();
} else { } else {
const elementWithCanvas = generateElementWithCanvas( const elementWithCanvas = generateElementWithCanvas(
@ -875,13 +874,7 @@ export const renderElement = (
tempCanvasContext.translate(-shiftX, -shiftY); tempCanvasContext.translate(-shiftX, -shiftY);
drawElementOnCanvas( drawElementOnCanvas(element, tempRc, tempCanvasContext, renderConfig);
element,
tempRc,
tempCanvasContext,
renderConfig,
appState,
);
tempCanvasContext.translate(shiftX, shiftY); tempCanvasContext.translate(shiftX, shiftY);
@ -920,7 +913,7 @@ export const renderElement = (
} }
context.translate(-shiftX, -shiftY); context.translate(-shiftX, -shiftY);
drawElementOnCanvas(element, rc, context, renderConfig, appState); drawElementOnCanvas(element, rc, context, renderConfig);
} }
context.restore(); context.restore();