refactor: `point()` -> `pointFrom()` to fix compiler issue ()

pull/8539/merge^2
David Luzar committed by Mark Tolmacs
parent 0c02972695
commit b4d8b04d9e
No known key found for this signature in database

@ -15,7 +15,7 @@ import { isBindingElement, isLinearElement } from "../element/typeChecks";
import type { AppState } from "../types";
import { resetCursor } from "../cursor";
import { StoreAction } from "../store";
import { pathIsALoop, point } from "../../math";
import { pathIsALoop, pointFrom } from "../../math";
export const actionFinalize = register({
name: "finalize",
@ -114,7 +114,7 @@ export const actionFinalize = register({
mutateElement(multiPointElement, {
points: linePoints.map((p, index) =>
index === linePoints.length - 1
? point(firstPoint[0], firstPoint[1])
? pointFrom(firstPoint[0], firstPoint[1])
: p,
),
});

@ -9,7 +9,7 @@ import {
} from "../tests/test-utils";
import { API } from "../tests/helpers/api";
import type { LocalPoint } from "../../math";
import { point, radians } from "../../math";
import { pointFrom, radians } from "../../math";
import { actionFlipHorizontal, actionFlipVertical } from "./actionFlip";
import { Keyboard, Pointer, UI } from "../tests/helpers/ui";
import { vi } from "vitest";
@ -144,9 +144,9 @@ const createLinearElementWithCurveInsideMinMaxPoints = (
link: null,
locked: false,
points: [
point<LocalPoint>(0, 0),
point<LocalPoint>(-922.4761962890625, 300.3277587890625),
point<LocalPoint>(828.0126953125, 410.51605224609375),
pointFrom<LocalPoint>(0, 0),
pointFrom<LocalPoint>(-922.4761962890625, 300.3277587890625),
pointFrom<LocalPoint>(828.0126953125, 410.51605224609375),
],
});
};
@ -936,11 +936,11 @@ describe("flipping re-centers selection", () => {
startArrowhead: null,
endArrowhead: "arrow",
points: [
point(0, 0),
point(0, -35),
point(-90.9, -35),
point(-90.9, 204.9),
point(65.1, 204.9),
pointFrom(0, 0),
pointFrom(0, -35),
pointFrom(-90.9, -35),
pointFrom(-90.9, 204.9),
pointFrom(65.1, 204.9),
],
elbowed: true,
}),

@ -111,7 +111,7 @@ import {
import { mutateElbowArrow } from "../element/routing";
import { LinearElementEditor } from "../element/linearElementEditor";
import type { LocalPoint } from "../../math";
import { point, vector } from "../../math";
import { pointFrom, vector } from "../../math";
const FONT_SIZE_RELATIVE_INCREASE_STEP = 0.1;
@ -1644,7 +1644,7 @@ export const actionChangeArrowType = register({
elementsMap,
[finalStartPoint, finalEndPoint].map(
(p): LocalPoint =>
point(p[0] - newElement.x, p[1] - newElement.y),
pointFrom(p[0] - newElement.x, p[1] - newElement.y),
),
vector(0, 0),
{

@ -1,4 +1,4 @@
import { point, radians } from "../math";
import { pointFrom, radians } from "../math";
import {
COLOR_PALETTE,
DEFAULT_CHART_COLOR_INDEX,
@ -259,7 +259,7 @@ const chartLines = (
x,
y,
width: chartWidth,
points: [point(0, 0), point(chartWidth, 0)],
points: [pointFrom(0, 0), pointFrom(chartWidth, 0)],
});
const yLine = newLinearElement({
@ -270,7 +270,7 @@ const chartLines = (
x,
y,
height: chartHeight,
points: [point(0, 0), point(0, -chartHeight)],
points: [pointFrom(0, 0), pointFrom(0, -chartHeight)],
});
const maxLine = newLinearElement({
@ -283,7 +283,7 @@ const chartLines = (
strokeStyle: "dotted",
width: chartWidth,
opacity: GRID_OPACITY,
points: [point(0, 0), point(chartWidth, 0)],
points: [pointFrom(0, 0), pointFrom(chartWidth, 0)],
});
return [xLine, yLine, maxLine];
@ -440,7 +440,7 @@ const chartTypeLine = (
height: cy,
strokeStyle: "dotted",
opacity: GRID_OPACITY,
points: [point(0, 0), point(0, cy)],
points: [pointFrom(0, 0), pointFrom(0, cy)],
});
});

@ -449,7 +449,7 @@ import type {
} from "../../math";
import {
pathIsALoop,
point,
pointFrom,
pointCenter,
pointDistance,
pointSubtract,
@ -600,7 +600,7 @@ class App extends React.Component<AppProps, AppState> {
lastPointerUpEvent: React.PointerEvent<HTMLElement> | PointerEvent | null =
null;
lastPointerMoveEvent: PointerEvent | null = null;
lastViewportPosition = point<ViewportPoint>(0, 0);
lastViewportPosition = pointFrom<ViewportPoint>(0, 0);
animationFrameHandler = new AnimationFrameHandler();
@ -1008,7 +1008,7 @@ class App extends React.Component<AppProps, AppState> {
<>
{embeddableElements.map((el) => {
const [x, y] = sceneCoordsToViewportCoords(
point(el.x, el.y),
pointFrom(el.x, el.y),
this.state,
);
@ -1294,11 +1294,11 @@ class App extends React.Component<AppProps, AppState> {
if (frameNameDiv) {
const box = frameNameDiv.getBoundingClientRect();
const boxSceneTopLeft = viewportCoordsToSceneCoords(
point(box.x, box.y),
pointFrom(box.x, box.y),
this.state,
);
const boxSceneBottomRight = viewportCoordsToSceneCoords(
point(box.right, box.bottom),
pointFrom(box.right, box.bottom),
this.state,
);
@ -1354,7 +1354,10 @@ class App extends React.Component<AppProps, AppState> {
return null;
}
const [x1, y1] = sceneCoordsToViewportCoords(point(f.x, f.y), this.state);
const [x1, y1] = sceneCoordsToViewportCoords(
pointFrom(f.x, f.y),
this.state,
);
const FRAME_NAME_EDIT_PADDING = 6;
@ -3171,7 +3174,7 @@ class App extends React.Component<AppProps, AppState> {
: this.state.height / 2 + this.state.offsetTop;
const [x, y] = viewportCoordsToSceneCoords(
point(clientX, clientY),
pointFrom(clientX, clientY),
this.state,
);
@ -3197,7 +3200,7 @@ class App extends React.Component<AppProps, AppState> {
syncMovedIndices(nextElements, arrayToMap(newElements));
const topLayerFrame = this.getTopLayerFrameAtSceneCoords(point(x, y));
const topLayerFrame = this.getTopLayerFrameAtSceneCoords(pointFrom(x, y));
if (topLayerFrame) {
const eligibleElements = filterElementsEligibleAsFrameChildren(
@ -3407,7 +3410,7 @@ class App extends React.Component<AppProps, AppState> {
const originalText = normalizeText(line).trim();
if (originalText.length) {
const topLayerFrame = this.getTopLayerFrameAtSceneCoords(
point(x, currentY),
pointFrom(x, currentY),
);
let metrics = measureText(originalText, fontString, lineHeight);
@ -3848,7 +3851,7 @@ class App extends React.Component<AppProps, AppState> {
private updateCurrentCursorPosition = withBatchedUpdates(
(event: MouseEvent) => {
this.lastViewportPosition = point(event.clientX, event.clientY);
this.lastViewportPosition = pointFrom(event.clientX, event.clientY);
},
);
@ -4679,7 +4682,7 @@ class App extends React.Component<AppProps, AppState> {
canvas: this.canvas,
getViewportCoords: (x, y) => {
const [viewportX, viewportY] = sceneCoordsToViewportCoords(
point(x, y),
pointFrom(x, y),
this.state,
);
return [
@ -5039,7 +5042,7 @@ class App extends React.Component<AppProps, AppState> {
const newHeight = Math.max(container.height, minHeight);
const newWidth = Math.max(container.width, minWidth);
mutateElement(container, { height: newHeight, width: newWidth });
sceneCoords = point(
sceneCoords = pointFrom(
container.x + newWidth / 2,
container.y + newHeight / 2,
);
@ -5151,7 +5154,7 @@ class App extends React.Component<AppProps, AppState> {
resetCursor(this.interactiveCanvas);
let sceneCoords = viewportCoordsToSceneCoords(
point(event.clientX, event.clientY),
pointFrom(event.clientX, event.clientY),
this.state,
);
@ -5259,11 +5262,14 @@ class App extends React.Component<AppProps, AppState> {
isTouchScreen: boolean,
) => {
const draggedDistance = pointDistance(
point(
pointFrom(
this.lastPointerDownEvent!.clientX,
this.lastPointerDownEvent!.clientY,
),
point(this.lastPointerUpEvent!.clientX, this.lastPointerUpEvent!.clientY),
pointFrom(
this.lastPointerUpEvent!.clientX,
this.lastPointerUpEvent!.clientY,
),
);
if (
!this.hitLinkElement ||
@ -5274,7 +5280,7 @@ class App extends React.Component<AppProps, AppState> {
return;
}
const lastPointerDownCoords = viewportCoordsToSceneCoords(
point(
pointFrom(
this.lastPointerDownEvent!.clientX,
this.lastPointerDownEvent!.clientY,
),
@ -5289,7 +5295,10 @@ class App extends React.Component<AppProps, AppState> {
this.device.editor.isMobile,
);
const lastPointerUpCoords = viewportCoordsToSceneCoords(
point(this.lastPointerUpEvent!.clientX, this.lastPointerUpEvent!.clientY),
pointFrom(
this.lastPointerUpEvent!.clientX,
this.lastPointerUpEvent!.clientY,
),
this.state,
);
const lastPointerUpHittingLinkIcon = isPointHittingLink(
@ -5347,7 +5356,7 @@ class App extends React.Component<AppProps, AppState> {
if (gesture.pointers.has(event.pointerId)) {
gesture.pointers.set(
event.pointerId,
point(event.clientX, event.clientY),
pointFrom(event.clientX, event.clientY),
);
}
@ -5429,7 +5438,7 @@ class App extends React.Component<AppProps, AppState> {
}
const scenePointer = viewportCoordsToSceneCoords(
point(event.clientX, event.clientY),
pointFrom(event.clientX, event.clientY),
this.state,
);
@ -5543,7 +5552,7 @@ class App extends React.Component<AppProps, AppState> {
// threshold, add a point
if (
pointDistance(
point(scenePointer[0] - rx, scenePointer[1] - ry),
pointFrom(scenePointer[0] - rx, scenePointer[1] - ry),
lastPoint,
) >= LINE_CONFIRM_THRESHOLD
) {
@ -5552,7 +5561,10 @@ class App extends React.Component<AppProps, AppState> {
{
points: [
...points,
point<LocalPoint>(scenePointer[0] - rx, scenePointer[1] - ry),
pointFrom<LocalPoint>(
scenePointer[0] - rx,
scenePointer[1] - ry,
),
],
},
false,
@ -5566,7 +5578,7 @@ class App extends React.Component<AppProps, AppState> {
points.length > 2 &&
lastCommittedPoint &&
pointDistance(
point(scenePointer[0] - rx, scenePointer[1] - ry),
pointFrom(scenePointer[0] - rx, scenePointer[1] - ry),
lastCommittedPoint,
) < LINE_CONFIRM_THRESHOLD
) {
@ -5616,7 +5628,7 @@ class App extends React.Component<AppProps, AppState> {
this.scene.getNonDeletedElementsMap(),
[
...points.slice(0, -1),
point<LocalPoint>(
pointFrom<LocalPoint>(
lastCommittedX + dxFromLastCommitted,
lastCommittedY + dyFromLastCommitted,
),
@ -5635,7 +5647,7 @@ class App extends React.Component<AppProps, AppState> {
{
points: [
...points.slice(0, -1),
point<LocalPoint>(
pointFrom<LocalPoint>(
lastCommittedX + dxFromLastCommitted,
lastCommittedY + dyFromLastCommitted,
),
@ -5872,10 +5884,10 @@ class App extends React.Component<AppProps, AppState> {
(1 - distanceRatio) * p[0] + distanceRatio * scenePointer[0];
const nextY =
(1 - distanceRatio) * p[1] + distanceRatio * scenePointer[1];
p = point(nextX, nextY);
p = pointFrom(nextX, nextY);
}
pointerDownState.lastCoords = point(scenePointer[0], scenePointer[1]);
pointerDownState.lastCoords = pointFrom(scenePointer[0], scenePointer[1]);
if (didChange) {
for (const element of this.scene.getNonDeletedElements()) {
@ -6227,7 +6239,7 @@ class App extends React.Component<AppProps, AppState> {
});
const sceneCoords = viewportCoordsToSceneCoords(
point(event.clientX, event.clientY),
pointFrom(event.clientX, event.clientY),
this.state,
);
@ -6315,7 +6327,7 @@ class App extends React.Component<AppProps, AppState> {
this.lastPointerUpEvent = event;
const scenePointer = viewportCoordsToSceneCoords(
point(event.clientX, event.clientY),
pointFrom(event.clientX, event.clientY),
this.state,
);
const clicklength =
@ -6522,7 +6534,10 @@ class App extends React.Component<AppProps, AppState> {
private updateGestureOnPointerDown(
event: React.PointerEvent<HTMLElement>,
): void {
gesture.pointers.set(event.pointerId, point(event.clientX, event.clientY));
gesture.pointers.set(
event.pointerId,
pointFrom(event.clientX, event.clientY),
);
if (gesture.pointers.size === 2) {
const [pointer1, pointer2] = Array.from(gesture.pointers.values());
@ -6536,7 +6551,7 @@ class App extends React.Component<AppProps, AppState> {
event: React.PointerEvent<HTMLElement>,
): PointerDownState {
const origin = viewportCoordsToSceneCoords(
point(event.clientX, event.clientY),
pointFrom(event.clientX, event.clientY),
this.state,
);
const selectedElements = this.scene.getSelectedElements(this.state);
@ -6613,7 +6628,7 @@ class App extends React.Component<AppProps, AppState> {
return false;
}
isDraggingScrollBar = true;
pointerDownState.lastCoords = point(event.clientX, event.clientY);
pointerDownState.lastCoords = pointFrom(event.clientX, event.clientY);
const onPointerMove = withBatchedUpdatesThrottled((event: PointerEvent) => {
const target = event.target;
if (!(target instanceof HTMLElement)) {
@ -6977,7 +6992,7 @@ class App extends React.Component<AppProps, AppState> {
if (hasBoundTextElement(element)) {
container = element as ExcalidrawTextContainer;
sceneCoords = point(
sceneCoords = pointFrom(
element.x + element.width / 2,
element.y + element.height / 2,
);
@ -7010,7 +7025,7 @@ class App extends React.Component<AppProps, AppState> {
);
const topLayerFrame = this.getTopLayerFrameAtSceneCoords(
point(gridX, gridY),
pointFrom(gridX, gridY),
);
const simulatePressure = event.pressure === 0.5;
@ -7030,7 +7045,7 @@ class App extends React.Component<AppProps, AppState> {
simulatePressure,
locked: false,
frameId: topLayerFrame ? topLayerFrame.id : null,
points: [point<LocalPoint>(0, 0)],
points: [pointFrom<LocalPoint>(0, 0)],
pressures: simulatePressure ? [] : [event.pressure],
});
@ -7175,7 +7190,7 @@ class App extends React.Component<AppProps, AppState> {
);
const topLayerFrame = addToFrameUnderCursor
? this.getTopLayerFrameAtSceneCoords(point(gridX, gridY))
? this.getTopLayerFrameAtSceneCoords(pointFrom(gridX, gridY))
: null;
const element = newImageElement({
@ -7239,7 +7254,7 @@ class App extends React.Component<AppProps, AppState> {
multiElement.points.length > 1 &&
lastCommittedPoint &&
pointDistance(
point(
pointFrom(
pointerDownState.origin[0] - rx,
pointerDownState.origin[1] - ry,
),
@ -7273,7 +7288,7 @@ class App extends React.Component<AppProps, AppState> {
);
const topLayerFrame = this.getTopLayerFrameAtSceneCoords(
point(gridX, gridY),
pointFrom(gridX, gridY),
);
/* If arrow is pre-arrowheads, it will have undefined for both start and end arrowheads.
@ -7343,7 +7358,7 @@ class App extends React.Component<AppProps, AppState> {
};
});
mutateElement(element, {
points: [...element.points, point<LocalPoint>(0, 0)],
points: [...element.points, pointFrom<LocalPoint>(0, 0)],
});
const boundElement = getHoveredElementForBinding(
pointerDownState.origin,
@ -7392,7 +7407,7 @@ class App extends React.Component<AppProps, AppState> {
);
const topLayerFrame = this.getTopLayerFrameAtSceneCoords(
point(gridX, gridY),
pointFrom(gridX, gridY),
);
const baseElementAttributes = {
@ -7568,7 +7583,7 @@ class App extends React.Component<AppProps, AppState> {
}
const pointerCoords = viewportCoordsToSceneCoords(
point(event.clientX, event.clientY),
pointFrom(event.clientX, event.clientY),
this.state,
);
@ -7942,7 +7957,7 @@ class App extends React.Component<AppProps, AppState> {
mutateElement(
newElement,
{
points: [...points, point<LocalPoint>(dx, dy)],
points: [...points, pointFrom<LocalPoint>(dx, dy)],
pressures,
},
false,
@ -7971,7 +7986,7 @@ class App extends React.Component<AppProps, AppState> {
mutateElement(
newElement,
{
points: [...points, point<LocalPoint>(dx, dy)],
points: [...points, pointFrom<LocalPoint>(dx, dy)],
},
false,
);
@ -7979,7 +7994,7 @@ class App extends React.Component<AppProps, AppState> {
mutateElbowArrow(
newElement,
elementsMap,
[...points.slice(0, -1), point<LocalPoint>(dx, dy)],
[...points.slice(0, -1), pointFrom<LocalPoint>(dx, dy)],
vector(0, 0),
undefined,
{
@ -7991,7 +8006,7 @@ class App extends React.Component<AppProps, AppState> {
mutateElement(
newElement,
{
points: [...points.slice(0, -1), point<LocalPoint>(dx, dy)],
points: [...points.slice(0, -1), pointFrom<LocalPoint>(dx, dy)],
},
false,
);
@ -8128,7 +8143,10 @@ class App extends React.Component<AppProps, AppState> {
this.translateCanvas({
scrollX: this.state.scrollX - dx / this.state.zoom.value,
});
pointerDownState.lastCoords = point(x, pointerDownState.lastCoords[1]);
pointerDownState.lastCoords = pointFrom(
x,
pointerDownState.lastCoords[1],
);
return true;
}
@ -8138,7 +8156,10 @@ class App extends React.Component<AppProps, AppState> {
this.translateCanvas({
scrollY: this.state.scrollY - dy / this.state.zoom.value,
});
pointerDownState.lastCoords = point(pointerDownState.lastCoords[0], y);
pointerDownState.lastCoords = pointFrom(
pointerDownState.lastCoords[0],
y,
);
return true;
}
return false;
@ -8280,7 +8301,7 @@ class App extends React.Component<AppProps, AppState> {
if (newElement?.type === "freedraw") {
const pointerCoords = viewportCoordsToSceneCoords(
point(childEvent.clientX, childEvent.clientY),
pointFrom(childEvent.clientX, childEvent.clientY),
this.state,
);
@ -8299,9 +8320,9 @@ class App extends React.Component<AppProps, AppState> {
: [...newElement.pressures, childEvent.pressure];
mutateElement(newElement, {
points: [...points, point<LocalPoint>(dx, dy)],
points: [...points, pointFrom<LocalPoint>(dx, dy)],
pressures,
lastCommittedPoint: point<LocalPoint>(dx, dy),
lastCommittedPoint: pointFrom<LocalPoint>(dx, dy),
});
this.actionManager.executeAction(actionFinalize);
@ -8340,7 +8361,7 @@ class App extends React.Component<AppProps, AppState> {
this.store.shouldCaptureIncrement();
}
const pointerCoords = viewportCoordsToSceneCoords(
point(childEvent.clientX, childEvent.clientY),
pointFrom(childEvent.clientX, childEvent.clientY),
this.state,
);
@ -8348,7 +8369,7 @@ class App extends React.Component<AppProps, AppState> {
mutateElement(newElement, {
points: [
...newElement.points,
point<LocalPoint>(
pointFrom<LocalPoint>(
pointerCoords[0] - newElement.x,
pointerCoords[1] - newElement.y,
),
@ -8465,7 +8486,7 @@ class App extends React.Component<AppProps, AppState> {
if (pointerDownState.drag.hasOccurred) {
const sceneCoords = viewportCoordsToSceneCoords(
point(childEvent.clientX, childEvent.clientY),
pointFrom(childEvent.clientX, childEvent.clientY),
this.state,
);
@ -8665,13 +8686,13 @@ class App extends React.Component<AppProps, AppState> {
this.eraserTrail.endPath();
const draggedDistance = pointDistance(
point(pointerStart.clientX, pointerStart.clientY),
point(pointerEnd.clientX, pointerEnd.clientY),
pointFrom(pointerStart.clientX, pointerStart.clientY),
pointFrom(pointerEnd.clientX, pointerEnd.clientY),
);
if (draggedDistance === 0) {
const scenePointer = viewportCoordsToSceneCoords(
point(pointerEnd.clientX, pointerEnd.clientY),
pointFrom(pointerEnd.clientX, pointerEnd.clientY),
this.state,
);
const hitElements = this.getElementsAtPosition(scenePointer);
@ -9208,7 +9229,7 @@ class App extends React.Component<AppProps, AppState> {
const clientY = this.state.height / 2 + this.state.offsetTop;
const [x, y] = viewportCoordsToSceneCoords(
point(clientX, clientY),
pointFrom(clientX, clientY),
this.state,
);
@ -9500,7 +9521,7 @@ class App extends React.Component<AppProps, AppState> {
// must be retrieved first, in the same frame
const { file, fileHandle } = await getFileFromEvent(event);
const [sceneX, sceneY] = viewportCoordsToSceneCoords(
point(event.clientX, event.clientY),
pointFrom(event.clientX, event.clientY),
this.state,
);
@ -9693,7 +9714,7 @@ class App extends React.Component<AppProps, AppState> {
}
const position = viewportCoordsToSceneCoords(
point(event.clientX, event.clientY),
pointFrom(event.clientX, event.clientY),
this.state,
);
const element = this.getElementAtPosition(position, {
@ -10168,7 +10189,7 @@ class App extends React.Component<AppProps, AppState> {
container?: ExcalidrawTextContainer | null,
) {
if (container) {
let elementCenter = point<GlobalPoint>(
let elementCenter = pointFrom<GlobalPoint>(
container.x + container.width / 2,
container.y + container.height / 2,
);
@ -10203,7 +10224,7 @@ class App extends React.Component<AppProps, AppState> {
return;
}
const [sceneX, sceneY] = viewportCoordsToSceneCoords(
point(x, y),
pointFrom(x, y),
this.state,
);

@ -20,7 +20,7 @@ import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils";
import { getElementsInAtomicUnit, resizeElement } from "./utils";
import type { AtomicUnit } from "./utils";
import { MIN_WIDTH_OR_HEIGHT } from "../../constants";
import { point, type GlobalPoint } from "../../../math";
import { pointFrom, type GlobalPoint } from "../../../math";
interface MultiDimensionProps {
property: "width" | "height";
@ -182,7 +182,7 @@ const handleDimensionChange: DragInputCallbackType<
nextHeight,
initialHeight,
aspectRatio,
point(x1, y1),
pointFrom(x1, y1),
property,
latestElements,
originalElements,
@ -287,7 +287,7 @@ const handleDimensionChange: DragInputCallbackType<
nextHeight,
initialHeight,
aspectRatio,
point(x1, y1),
pointFrom(x1, y1),
property,
latestElements,
originalElements,

@ -13,7 +13,7 @@ import { useMemo } from "react";
import { getElementsInAtomicUnit, moveElement } from "./utils";
import type { AtomicUnit } from "./utils";
import type { AppState } from "../../types";
import { point, pointRotateRads } from "../../../math";
import { pointFrom, pointRotateRads } from "../../../math";
interface MultiPositionProps {
property: "x" | "y";
@ -44,8 +44,8 @@ const moveElements = (
origElement.y + origElement.height / 2,
];
const [topLeftX, topLeftY] = pointRotateRads(
point(origElement.x, origElement.y),
point(cx, cy),
pointFrom(origElement.x, origElement.y),
pointFrom(cx, cy),
origElement.angle,
);
@ -97,8 +97,8 @@ const moveGroupTo = (
];
const [topLeftX, topLeftY] = pointRotateRads(
point(latestElement.x, latestElement.y),
point(cx, cy),
pointFrom(latestElement.x, latestElement.y),
pointFrom(cx, cy),
latestElement.angle,
);
@ -171,8 +171,8 @@ const handlePositionChange: DragInputCallbackType<
origElement.y + origElement.height / 2,
];
const [topLeftX, topLeftY] = pointRotateRads(
point(origElement.x, origElement.y),
point(cx, cy),
pointFrom(origElement.x, origElement.y),
pointFrom(cx, cy),
origElement.angle,
);
@ -241,8 +241,8 @@ const MultiPosition = ({
const [cx, cy] = [el.x + el.width / 2, el.y + el.height / 2];
const [topLeftX, topLeftY] = pointRotateRads(
point(el.x, el.y),
point(cx, cy),
pointFrom(el.x, el.y),
pointFrom(cx, cy),
el.angle,
);

@ -4,7 +4,7 @@ import type { DragInputCallbackType } from "./DragInput";
import { getStepSizedValue, moveElement } from "./utils";
import type Scene from "../../scene/Scene";
import type { AppState } from "../../types";
import { point, pointRotateRads } from "../../../math";
import { pointFrom, pointRotateRads } from "../../../math";
interface PositionProps {
property: "x" | "y";
@ -33,8 +33,8 @@ const handlePositionChange: DragInputCallbackType<"x" | "y"> = ({
origElement.y + origElement.height / 2,
];
const [topLeftX, topLeftY] = pointRotateRads(
point(origElement.x, origElement.y),
point(cx, cy),
pointFrom(origElement.x, origElement.y),
pointFrom(cx, cy),
origElement.angle,
);
@ -93,8 +93,8 @@ const Position = ({
appState,
}: PositionProps) => {
const [topLeftX, topLeftY] = pointRotateRads(
point(element.x, element.y),
point(element.x + element.width / 2, element.y + element.height / 2),
pointFrom(element.x, element.y),
pointFrom(element.x + element.width / 2, element.y + element.height / 2),
element.angle,
);
const value =

@ -25,7 +25,7 @@ import { API } from "../../tests/helpers/api";
import { actionGroup } from "../../actions";
import { isInGroup } from "../../groups";
import type { Degrees } from "../../../math";
import { degreesToRadians, point, pointRotateRads } from "../../../math";
import { degreesToRadians, pointFrom, pointRotateRads } from "../../../math";
const { h } = window;
const mouse = new Pointer("mouse");
@ -264,8 +264,8 @@ describe("stats for a generic element", () => {
rectangle.y + rectangle.height / 2,
];
const [topLeftX, topLeftY] = pointRotateRads(
point(rectangle.x, rectangle.y),
point(cx, cy),
pointFrom(rectangle.x, rectangle.y),
pointFrom(cx, cy),
rectangle.angle,
);
@ -283,8 +283,8 @@ describe("stats for a generic element", () => {
testInputProperty(rectangle, "angle", "A", 0, 45);
let [newTopLeftX, newTopLeftY] = pointRotateRads(
point(rectangle.x, rectangle.y),
point(cx, cy),
pointFrom(rectangle.x, rectangle.y),
pointFrom(cx, cy),
rectangle.angle,
);
@ -294,8 +294,8 @@ describe("stats for a generic element", () => {
testInputProperty(rectangle, "angle", "A", 45, 66);
[newTopLeftX, newTopLeftY] = pointRotateRads(
point(rectangle.x, rectangle.y),
point(cx, cy),
pointFrom(rectangle.x, rectangle.y),
pointFrom(cx, cy),
rectangle.angle,
);
expect(newTopLeftX.toString()).not.toEqual(xInput.value);
@ -311,8 +311,8 @@ describe("stats for a generic element", () => {
rectangle.y + rectangle.height / 2,
];
const [topLeftX, topLeftY] = pointRotateRads(
point(rectangle.x, rectangle.y),
point(cx, cy),
pointFrom(rectangle.x, rectangle.y),
pointFrom(cx, cy),
rectangle.angle,
);
testInputProperty(rectangle, "width", "W", rectangle.width, 400);
@ -321,8 +321,8 @@ describe("stats for a generic element", () => {
rectangle.y + rectangle.height / 2,
];
let [currentTopLeftX, currentTopLeftY] = pointRotateRads(
point(rectangle.x, rectangle.y),
point(cx, cy),
pointFrom(rectangle.x, rectangle.y),
pointFrom(cx, cy),
rectangle.angle,
);
expect(currentTopLeftX).toBeCloseTo(topLeftX, 4);
@ -334,8 +334,8 @@ describe("stats for a generic element", () => {
rectangle.y + rectangle.height / 2,
];
[currentTopLeftX, currentTopLeftY] = pointRotateRads(
point(rectangle.x, rectangle.y),
point(cx, cy),
pointFrom(rectangle.x, rectangle.y),
pointFrom(cx, cy),
rectangle.angle,
);

@ -1,5 +1,5 @@
import type { Radians } from "../../../math";
import { point, pointRotateRads } from "../../../math";
import { pointFrom, pointRotateRads } from "../../../math";
import {
bindOrUnbindLinearElements,
updateBoundElements,
@ -231,8 +231,8 @@ export const moveElement = (
originalElement.y + originalElement.height / 2,
];
const [topLeftX, topLeftY] = pointRotateRads(
point(originalElement.x, originalElement.y),
point(cx, cy),
pointFrom(originalElement.x, originalElement.y),
pointFrom(cx, cy),
originalElement.angle,
);
@ -240,8 +240,8 @@ export const moveElement = (
const changeInY = newTopLeftY - topLeftY;
const [x, y] = pointRotateRads(
point(newTopLeftX, newTopLeftY),
point(cx + changeInX, cy + changeInY),
pointFrom(newTopLeftX, newTopLeftY),
pointFrom(cx + changeInX, cy + changeInY),
-originalElement.angle as Radians,
);

@ -37,7 +37,7 @@ import { useAppProps, useExcalidrawAppState } from "../App";
import { isEmbeddableElement } from "../../element/typeChecks";
import { getLinkHandleFromCoords } from "./helpers";
import type { ViewportPoint } from "../../../math";
import { point } from "../../../math";
import { pointFrom } from "../../../math";
const CONTAINER_WIDTH = 320;
const SPACE_BOTTOM = 85;
@ -182,7 +182,7 @@ export const Hyperlink = ({
element,
elementsMap,
appState,
point(event.clientX, event.clientY),
pointFrom(event.clientX, event.clientY),
) as boolean;
if (shouldHide) {
timeoutId = window.setTimeout(() => {
@ -326,7 +326,7 @@ const getCoordsForPopover = (
) => {
const [x1, y1] = getElementAbsoluteCoords(element, elementsMap);
const [viewportX, viewportY] = sceneCoordsToViewportCoords(
point(x1 + element.width / 2, y1),
pointFrom(x1 + element.width / 2, y1),
appState,
);
const x = viewportX - appState.offsetLeft - CONTAINER_WIDTH / 2;
@ -388,7 +388,7 @@ const renderTooltip = (
);
const linkViewportCoords = sceneCoordsToViewportCoords(
point(linkX, linkY),
pointFrom(linkX, linkY),
appState,
);

@ -1,5 +1,5 @@
import type { GlobalPoint, Radians } from "../../../math";
import { point, pointRotateRads } from "../../../math";
import { pointFrom, pointRotateRads } from "../../../math";
import { MIME_TYPES } from "../../constants";
import { getElementAbsoluteCoords } from "../../element/bounds";
import { hitElementBoundingBox } from "../../element/collision";
@ -35,8 +35,8 @@ export const getLinkHandleFromCoords = (
const y = y1 - dashedLineMargin - linkMarginY + centeringOffset;
const [rotatedX, rotatedY] = pointRotateRads(
point(x + linkWidth / 2, y + linkHeight / 2),
point(centerX, centerY),
pointFrom(x + linkWidth / 2, y + linkHeight / 2),
pointFrom(centerX, centerY),
angle,
);
return [
@ -85,5 +85,10 @@ export const isPointHittingLink = (
) {
return true;
}
return isPointHittingLinkIcon(element, elementsMap, appState, point(x, y));
return isPointHittingLinkIcon(
element,
elementsMap,
appState,
pointFrom(x, y),
);
};

@ -56,7 +56,7 @@ import {
getNormalizedZoom,
} from "../scene";
import type { LocalPoint } from "../../math";
import { pointExtent, isFiniteNumber, point, radians } from "../../math";
import { pointExtent, isFiniteNumber, pointFrom, radians } from "../../math";
type RestoredAppState = Omit<
AppState,
@ -267,7 +267,7 @@ const restoreElement = (
let y = element.y;
let points = // migrate old arrow model to new one
!Array.isArray(element.points) || element.points.length < 2
? [point(0, 0), point(element.width, element.height)]
? [pointFrom(0, 0), pointFrom(element.width, element.height)]
: element.points;
if (points[0][0] !== 0 || points[0][1] !== 0) {
@ -295,7 +295,7 @@ const restoreElement = (
let y: number | undefined = element.y;
let points: readonly LocalPoint[] | undefined = // migrate old arrow model to new one
!Array.isArray(element.points) || element.points.length < 2
? [point(0, 0), point(element.width, element.height)]
? [pointFrom(0, 0), pointFrom(element.width, element.height)]
: element.points;
if (points[0][0] !== 0 || points[0][1] !== 0) {

@ -2,7 +2,7 @@ import { vi } from "vitest";
import type { ExcalidrawElementSkeleton } from "./transform";
import { convertToExcalidrawElements } from "./transform";
import type { ExcalidrawArrowElement } from "../element/types";
import { point } from "../../math";
import { pointFrom } from "../../math";
const opts = { regenerateIds: false };
@ -917,7 +917,7 @@ describe("Test Transform", () => {
x: 111.262,
y: 57,
strokeWidth: 2,
points: [point(0, 0), point(272.985, 0)],
points: [pointFrom(0, 0), pointFrom(272.985, 0)],
label: {
text: "How are you?",
fontSize: 20,
@ -940,7 +940,7 @@ describe("Test Transform", () => {
x: 77.017,
y: 79,
strokeWidth: 2,
points: [point(0, 0)],
points: [pointFrom(0, 0)],
label: {
text: "Friendship",
fontSize: 20,

@ -53,7 +53,7 @@ import { randomId } from "../random";
import { syncInvalidIndices } from "../fractionalIndex";
import { getLineHeight } from "../fonts";
import { isArrowElement } from "../element/typeChecks";
import { pointExtent, point, type LocalPoint } from "../../math";
import { pointExtent, pointFrom, type LocalPoint } from "../../math";
export type ValidLinearElement = {
type: "arrow" | "line";
@ -536,7 +536,7 @@ export const convertToExcalidrawElements = (
excalidrawElement = newLinearElement({
width,
height,
points: [point(0, 0), point(width, height)],
points: [pointFrom(0, 0), pointFrom(width, height)],
...element,
});
@ -549,7 +549,7 @@ export const convertToExcalidrawElements = (
width,
height,
endArrowhead: "arrow",
points: [point(0, 0), point(width, height)],
points: [pointFrom(0, 0), pointFrom(width, height)],
...element,
type: "arrow",
});

@ -52,7 +52,7 @@ import {
import type { LocalPoint } from "../../math";
import {
segment,
point,
pointFrom,
pointRotateRads,
type GlobalPoint,
vectorFromPoint,
@ -701,7 +701,7 @@ export const getHeadingForElbowArrowSnap = (
return vectorToHeading(
vectorFromPoint(
p,
point<GlobalPoint>(
pointFrom<GlobalPoint>(
bindableElement.x + bindableElement.width / 2,
bindableElement.y + bindableElement.height / 2,
),
@ -741,14 +741,14 @@ export const bindPointToSnapToElementOutline = (
const intersections: GlobalPoint[] = [
...(intersectElementWithLine(
bindableElement,
point(p[0], p[1] - 2 * bindableElement.height),
point(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,
) ?? []),
...(intersectElementWithLine(
bindableElement,
point(p[0] - 2 * bindableElement.width, p[1]),
point(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,
) ?? []),
].filter((p) => p != null);
@ -786,25 +786,25 @@ const headingToMidBindPoint = (
switch (true) {
case compareHeading(heading, HEADING_UP):
return pointRotateRads(
point((aabb[0] + aabb[2]) / 2 + 0.1, aabb[1]),
pointFrom((aabb[0] + aabb[2]) / 2 + 0.1, aabb[1]),
center,
bindableElement.angle,
);
case compareHeading(heading, HEADING_RIGHT):
return pointRotateRads(
point(aabb[2], (aabb[1] + aabb[3]) / 2 + 0.1),
pointFrom(aabb[2], (aabb[1] + aabb[3]) / 2 + 0.1),
center,
bindableElement.angle,
);
case compareHeading(heading, HEADING_DOWN):
return pointRotateRads(
point((aabb[0] + aabb[2]) / 2 - 0.1, aabb[3]),
pointFrom((aabb[0] + aabb[2]) / 2 - 0.1, aabb[3]),
center,
bindableElement.angle,
);
default:
return pointRotateRads(
point(aabb[0], (aabb[1] + aabb[3]) / 2 - 0.1),
pointFrom(aabb[0], (aabb[1] + aabb[3]) / 2 - 0.1),
center,
bindableElement.angle,
);
@ -815,7 +815,7 @@ export const avoidRectangularCorner = (
element: ExcalidrawBindableElement,
p: GlobalPoint,
): GlobalPoint => {
const center = point<GlobalPoint>(
const center = pointFrom<GlobalPoint>(
element.x + element.width / 2,
element.y + element.height / 2,
);
@ -825,13 +825,13 @@ export const avoidRectangularCorner = (
// Top left
if (nonRotatedPoint[1] - element.y > -FIXED_BINDING_DISTANCE) {
return pointRotateRads<GlobalPoint>(
point(element.x - FIXED_BINDING_DISTANCE, element.y),
pointFrom(element.x - FIXED_BINDING_DISTANCE, element.y),
center,
element.angle,
);
}
return pointRotateRads(
point(element.x, element.y - FIXED_BINDING_DISTANCE),
pointFrom(element.x, element.y - FIXED_BINDING_DISTANCE),
center,
element.angle,
);
@ -842,13 +842,16 @@ export const avoidRectangularCorner = (
// Bottom left
if (nonRotatedPoint[0] - element.x > -FIXED_BINDING_DISTANCE) {
return pointRotateRads(
point(element.x, element.y + element.height + FIXED_BINDING_DISTANCE),
pointFrom(
element.x,
element.y + element.height + FIXED_BINDING_DISTANCE,
),
center,
element.angle,
);
}
return pointRotateRads(
point(element.x - FIXED_BINDING_DISTANCE, element.y + element.height),
pointFrom(element.x - FIXED_BINDING_DISTANCE, element.y + element.height),
center,
element.angle,
);
@ -862,7 +865,7 @@ export const avoidRectangularCorner = (
element.width + FIXED_BINDING_DISTANCE
) {
return pointRotateRads(
point(
pointFrom(
element.x + element.width,
element.y + element.height + FIXED_BINDING_DISTANCE,
),
@ -871,7 +874,7 @@ export const avoidRectangularCorner = (
);
}
return pointRotateRads(
point(
pointFrom(
element.x + element.width + FIXED_BINDING_DISTANCE,
element.y + element.height,
),
@ -888,13 +891,16 @@ export const avoidRectangularCorner = (
element.width + FIXED_BINDING_DISTANCE
) {
return pointRotateRads(
point(element.x + element.width, element.y - FIXED_BINDING_DISTANCE),
pointFrom(
element.x + element.width,
element.y - FIXED_BINDING_DISTANCE,
),
center,
element.angle,
);
}
return pointRotateRads(
point(element.x + element.width + FIXED_BINDING_DISTANCE, element.y),
pointFrom(element.x + element.width + FIXED_BINDING_DISTANCE, element.y),
center,
element.angle,
);
@ -909,7 +915,10 @@ export const snapToMid = (
tolerance: number = 0.05,
): GlobalPoint => {
const { x, y, width, height, angle } = element;
const center = point<GlobalPoint>(x + width / 2 - 0.1, y + height / 2 - 0.1);
const center = pointFrom<GlobalPoint>(
x + width / 2 - 0.1,
y + height / 2 - 0.1,
);
const nonRotated = pointRotateRads(p, center, radians(-angle));
// snap-to-center point is adaptive to element size, but we don't want to go
@ -924,7 +933,7 @@ export const snapToMid = (
) {
// LEFT
return pointRotateRads(
point(x - FIXED_BINDING_DISTANCE, center[1]),
pointFrom(x - FIXED_BINDING_DISTANCE, center[1]),
center,
angle,
);
@ -935,7 +944,7 @@ export const snapToMid = (
) {
// TOP
return pointRotateRads(
point(center[0], y - FIXED_BINDING_DISTANCE),
pointFrom(center[0], y - FIXED_BINDING_DISTANCE),
center,
angle,
);
@ -946,7 +955,7 @@ export const snapToMid = (
) {
// RIGHT
return pointRotateRads(
point(x + width + FIXED_BINDING_DISTANCE, center[1]),
pointFrom(x + width + FIXED_BINDING_DISTANCE, center[1]),
center,
angle,
);
@ -957,7 +966,7 @@ export const snapToMid = (
) {
// DOWN
return pointRotateRads(
point(center[0], y + height + FIXED_BINDING_DISTANCE),
pointFrom(center[0], y + height + FIXED_BINDING_DISTANCE),
center,
angle,
);
@ -994,11 +1003,11 @@ const updateBoundPoint = (
startOrEnd === "startBinding" ? "start" : "end",
elementsMap,
).fixedPoint;
const globalMidPoint = point<GlobalPoint>(
const globalMidPoint = pointFrom<GlobalPoint>(
bindableElement.x + bindableElement.width / 2,
bindableElement.y + bindableElement.height / 2,
);
const global = point<GlobalPoint>(
const global = pointFrom<GlobalPoint>(
bindableElement.x + fixedPoint[0] * bindableElement.width,
bindableElement.y + fixedPoint[1] * bindableElement.height,
);
@ -1086,7 +1095,7 @@ export const calculateFixedPointForElbowArrowBinding = (
otherGlobalPoint,
hoveredElement,
);
const globalMidPoint = point(
const globalMidPoint = pointFrom(
bounds[0] + (bounds[2] - bounds[0]) / 2,
bounds[1] + (bounds[3] - bounds[1]) / 2,
);
@ -1303,9 +1312,9 @@ export const bindingBorderTest = (
const threshold = maxBindingGap(element, element.width, element.height);
const shape = getElementShape(element, elementsMap);
return (
isPointOnShape(point(x, y), shape, threshold) ||
isPointOnShape(pointFrom(x, y), shape, threshold) ||
(fullShape === true &&
pointInsideBounds(point(x, y), aabbForElement(element)))
pointInsideBounds(pointFrom(x, y), aabbForElement(element)))
);
};
@ -1333,7 +1342,7 @@ const determineFocusDistance = (
// Another point on the line, in absolute coordinates (closer to element)
b: GlobalPoint,
): number => {
const center = point<GlobalPoint>(
const center = pointFrom<GlobalPoint>(
element.x + element.width / 2,
element.y + element.height / 2,
);
@ -1357,7 +1366,7 @@ const determineFocusPoint = (
focus: number,
adjacentPoint: GlobalPoint,
): GlobalPoint => {
const center = point<GlobalPoint>(
const center = pointFrom<GlobalPoint>(
element.x + element.width / 2,
element.y + element.height / 2,
);
@ -1373,7 +1382,7 @@ const determineFocusPoint = (
),
Math.sign(focus) *
Math.min(
pointDistance(point<GlobalPoint>(element.x, element.y), center) *
pointDistance(pointFrom<GlobalPoint>(element.x, element.y), center) *
Math.abs(focus),
element.width / 2,
element.height / 2,
@ -1698,11 +1707,11 @@ export const getGlobalFixedPointForBindableElement = (
const [fixedX, fixedY] = normalizeFixedPoint(fixedPointRatio);
return pointRotateRads(
point(
pointFrom(
element.x + element.width * fixedX,
element.y + element.height * fixedY,
),
point<GlobalPoint>(
pointFrom<GlobalPoint>(
element.x + element.width / 2,
element.y + element.height / 2,
),
@ -1730,7 +1739,7 @@ const getGlobalFixedPoints = (
arrow.startBinding.fixedPoint,
startElement as ExcalidrawBindableElement,
)
: point<GlobalPoint>(
: pointFrom<GlobalPoint>(
arrow.x + arrow.points[0][0],
arrow.y + arrow.points[0][1],
);
@ -1740,7 +1749,7 @@ const getGlobalFixedPoints = (
arrow.endBinding.fixedPoint,
endElement as ExcalidrawBindableElement,
)
: point<GlobalPoint>(
: pointFrom<GlobalPoint>(
arrow.x + arrow.points[arrow.points.length - 1][0],
arrow.y + arrow.points[arrow.points.length - 1][1],
);

@ -1,5 +1,5 @@
import type { LocalPoint } from "../../math";
import { point } from "../../math";
import { pointFrom } from "../../math";
import { ROUNDNESS } from "../constants";
import { arrayToMap } from "../utils";
import { getElementAbsoluteCoords, getElementBounds } from "./bounds";
@ -125,9 +125,9 @@ describe("getElementBounds", () => {
a: 0.6447741904932416,
}),
points: [
point<LocalPoint>(0, 0),
point<LocalPoint>(67.33984375, 92.48828125),
point<LocalPoint>(-102.7890625, 52.15625),
pointFrom<LocalPoint>(0, 0),
pointFrom<LocalPoint>(67.33984375, 92.48828125),
pointFrom<LocalPoint>(-102.7890625, 52.15625),
],
} as ExcalidrawLinearElement;

@ -24,7 +24,7 @@ import { ShapeCache } from "../scene/ShapeCache";
import { arrayToMap, invariant } from "../utils";
import type { GlobalPoint, LocalPoint, Segment } from "../../math";
import {
point,
pointFrom,
pointDistance,
pointFromArray,
pointRotateRads,
@ -95,8 +95,8 @@ class ElementBounds {
const [minX, minY, maxX, maxY] = getBoundsFromFreeDrawPoints(
element.points.map(([x, y]) =>
pointRotateRads(
point(x, y),
point(cx - element.x, cy - element.y),
pointFrom(x, y),
pointFrom(cx - element.x, cy - element.y),
element.angle,
),
),
@ -112,23 +112,23 @@ class ElementBounds {
bounds = getLinearElementRotatedBounds(element, cx, cy, elementsMap);
} else if (element.type === "diamond") {
const [x11, y11] = pointRotateRads(
point(cx, y1),
point(cx, cy),
pointFrom(cx, y1),
pointFrom(cx, cy),
element.angle,
);
const [x12, y12] = pointRotateRads(
point(cx, y2),
point(cx, cy),
pointFrom(cx, y2),
pointFrom(cx, cy),
element.angle,
);
const [x22, y22] = pointRotateRads(
point(x1, cy),
point(cx, cy),
pointFrom(x1, cy),
pointFrom(cx, cy),
element.angle,
);
const [x21, y21] = pointRotateRads(
point(x2, cy),
point(cx, cy),
pointFrom(x2, cy),
pointFrom(cx, cy),
element.angle,
);
const minX = Math.min(x11, x12, x22, x21);
@ -146,23 +146,23 @@ class ElementBounds {
bounds = [cx - ww, cy - hh, cx + ww, cy + hh];
} else {
const [x11, y11] = pointRotateRads(
point(x1, y1),
point(cx, cy),
pointFrom(x1, y1),
pointFrom(cx, cy),
element.angle,
);
const [x12, y12] = pointRotateRads(
point(x1, y2),
point(cx, cy),
pointFrom(x1, y2),
pointFrom(cx, cy),
element.angle,
);
const [x22, y22] = pointRotateRads(
point(x2, y2),
point(cx, cy),
pointFrom(x2, y2),
pointFrom(cx, cy),
element.angle,
);
const [x21, y21] = pointRotateRads(
point(x2, y1),
point(cx, cy),
pointFrom(x2, y1),
pointFrom(cx, cy),
element.angle,
);
const minX = Math.min(x11, x12, x22, x21);
@ -331,7 +331,7 @@ export const getMinMaxXYFromCurvePathOps = (
ops: Op[],
transformXY?: (p: GlobalPoint) => GlobalPoint,
): Bounds => {
let currentP: GlobalPoint = point(0, 0);
let currentP: GlobalPoint = pointFrom(0, 0);
const { minX, minY, maxX, maxY } = ops.reduce(
(limits, { op, data }) => {
@ -345,9 +345,9 @@ export const getMinMaxXYFromCurvePathOps = (
// move operation does not draw anything; so, it always
// returns false
} else if (op === "bcurveTo") {
const _p1 = point<GlobalPoint>(data[0], data[1]);
const _p2 = point<GlobalPoint>(data[2], data[3]);
const _p3 = point<GlobalPoint>(data[4], data[5]);
const _p1 = pointFrom<GlobalPoint>(data[0], data[1]);
const _p2 = pointFrom<GlobalPoint>(data[2], data[3]);
const _p3 = pointFrom<GlobalPoint>(data[4], data[5]);
const p1 = transformXY ? transformXY(_p1) : _p1;
const p2 = transformXY ? transformXY(_p2) : _p2;
@ -442,8 +442,8 @@ const getLinearElementRotatedBounds = (
if (element.points.length < 2) {
const [pointX, pointY] = element.points[0];
const [x, y] = pointRotateRads(
point(element.x + pointX, element.y + pointY),
point(cx, cy),
pointFrom(element.x + pointX, element.y + pointY),
pointFrom(cx, cy),
element.angle,
);
@ -471,8 +471,8 @@ const getLinearElementRotatedBounds = (
const ops = getCurvePathOps(shape);
const transformXY = ([x, y]: GlobalPoint) =>
pointRotateRads<GlobalPoint>(
point(element.x + x, element.y + y),
point(cx, cy),
pointFrom(element.x + x, element.y + y),
pointFrom(cx, cy),
element.angle,
);
const res = getMinMaxXYFromCurvePathOps(ops, transformXY);
@ -620,8 +620,8 @@ export const getClosestElementBounds = (
elements.forEach((element) => {
const [x1, y1, x2, y2] = getElementBounds(element, elementsMap);
const distance = pointDistance(
point((x1 + x2) / 2, (y1 + y2) / 2),
point(from.x, from.y),
pointFrom((x1 + x2) / 2, (y1 + y2) / 2),
pointFrom(from.x, from.y),
);
if (distance < minDistance) {
@ -652,7 +652,7 @@ export const getVisibleSceneBounds = ({
};
export const getCenterForBounds = (bounds: Bounds): GlobalPoint =>
point(
pointFrom(
bounds[0] + (bounds[2] - bounds[0]) / 2,
bounds[1] + (bounds[3] - bounds[1]) / 2,
);
@ -696,7 +696,7 @@ export const createDiamondArc = (
end: GlobalPoint,
r: number,
) => {
const c = point<GlobalPoint>(
const c = pointFrom<GlobalPoint>(
(start[0] + end[0]) / 2,
(start[1] + end[1]) / 2,
);

@ -31,7 +31,7 @@ import type { Arc, GlobalPoint, Polygon } from "../../math";
import {
pathIsALoop,
isPointWithinBounds,
point,
pointFrom,
rectangle,
pointRotateRads,
radians,
@ -119,7 +119,11 @@ export const hitElementBoundingBox = (
y1 -= tolerance;
x2 += tolerance;
y2 += tolerance;
return isPointWithinBounds(point(x1, y1), scenePointer, point(x2, y2));
return isPointWithinBounds(
pointFrom(x1, y1),
scenePointer,
pointFrom(x2, y2),
);
};
export const hitElementBoundingBoxOnly = (
@ -175,13 +179,13 @@ export const intersectRectanguloidWithLine = (
offset: number,
): GlobalPoint[] => {
const r = rectangle(
point(element.x - offset, element.y - offset),
point(
pointFrom(element.x - offset, element.y - offset),
pointFrom(
element.x + element.width + offset,
element.y + element.height + offset,
),
);
const center = point<GlobalPoint>(
const center = pointFrom<GlobalPoint>(
element.x + element.width / 2,
element.y + element.height / 2,
);
@ -203,20 +207,20 @@ export const intersectRectanguloidWithLine = (
);
const sideIntersections: GlobalPoint[] = [
segment<GlobalPoint>(
point<GlobalPoint>(r[0][0] + roundness, r[0][1]),
point<GlobalPoint>(r[1][0] - roundness, r[0][1]),
pointFrom<GlobalPoint>(r[0][0] + roundness, r[0][1]),
pointFrom<GlobalPoint>(r[1][0] - roundness, r[0][1]),
),
segment<GlobalPoint>(
point<GlobalPoint>(r[1][0], r[0][1] + roundness),
point<GlobalPoint>(r[1][0], r[1][1] - roundness),
pointFrom<GlobalPoint>(r[1][0], r[0][1] + roundness),
pointFrom<GlobalPoint>(r[1][0], r[1][1] - roundness),
),
segment<GlobalPoint>(
point<GlobalPoint>(r[1][0] - roundness, r[1][1]),
point<GlobalPoint>(r[0][0] + roundness, r[1][1]),
pointFrom<GlobalPoint>(r[1][0] - roundness, r[1][1]),
pointFrom<GlobalPoint>(r[0][0] + roundness, r[1][1]),
),
segment<GlobalPoint>(
point<GlobalPoint>(r[0][0], r[1][1] - roundness),
point<GlobalPoint>(r[0][0], r[0][1] + roundness),
pointFrom<GlobalPoint>(r[0][0], r[1][1] - roundness),
pointFrom<GlobalPoint>(r[0][0], r[0][1] + roundness),
),
]
.map((s) =>
@ -228,25 +232,25 @@ export const intersectRectanguloidWithLine = (
roundness > 0
? [
arc<GlobalPoint>(
point(r[0][0] + roundness, r[0][1] + roundness),
pointFrom(r[0][0] + roundness, r[0][1] + roundness),
roundness,
radians(Math.PI),
radians((3 / 4) * Math.PI),
),
arc<GlobalPoint>(
point(r[1][0] - roundness, r[0][1] + roundness),
pointFrom(r[1][0] - roundness, r[0][1] + roundness),
roundness,
radians((3 / 4) * Math.PI),
radians(0),
),
arc<GlobalPoint>(
point(r[1][0] - roundness, r[1][1] - roundness),
pointFrom(r[1][0] - roundness, r[1][1] - roundness),
roundness,
radians(0),
radians((1 / 2) * Math.PI),
),
arc<GlobalPoint>(
point(r[0][0] + roundness, r[1][1] - roundness),
pointFrom(r[0][0] + roundness, r[1][1] - roundness),
roundness,
radians((1 / 2) * Math.PI),
radians(Math.PI),
@ -277,7 +281,10 @@ export const intersectDiamondWithLine = (
): GlobalPoint[] => {
const [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY] =
getDiamondPoints(element, offset);
const center = point<GlobalPoint>((topX + bottomX) / 2, (topY + bottomY) / 2);
const center = pointFrom<GlobalPoint>(
(topX + bottomX) / 2,
(topY + bottomY) / 2,
);
const verticalRadius = getCornerRadius(Math.abs(topX - leftX), element);
const horizontalRadius = getCornerRadius(Math.abs(rightY - topY), element);
@ -286,10 +293,10 @@ export const intersectDiamondWithLine = (
const rotatedA = pointRotateRads(a, center, radians(-element.angle));
const rotatedB = pointRotateRads(b, center, radians(-element.angle));
const [top, right, bottom, left]: GlobalPoint[] = [
point(element.x + topX, element.y + topY),
point(element.x + rightX, element.y + rightY),
point(element.x + bottomX, element.y + bottomY),
point(element.x + leftX, element.y + leftY),
pointFrom(element.x + topX, element.y + topY),
pointFrom(element.x + rightX, element.y + rightY),
pointFrom(element.x + bottomX, element.y + bottomY),
pointFrom(element.x + leftX, element.y + leftY),
];
const topRight = createDiamondSide(
@ -353,7 +360,7 @@ export const intersectEllipseWithLine = (
b: GlobalPoint,
offset: number = 0,
): GlobalPoint[] => {
const center = point<GlobalPoint>(
const center = pointFrom<GlobalPoint>(
element.x + element.width / 2,
element.y + element.height / 2,
);

@ -29,7 +29,7 @@ import {
isFlowchartNodeElement,
} from "./typeChecks";
import { invariant } from "../utils";
import { point, type LocalPoint } from "../../math";
import { pointFrom, type LocalPoint } from "../../math";
import { aabbForElement } from "../shapes";
type LinkDirection = "up" | "right" | "down" | "left";
@ -421,7 +421,7 @@ const createBindingArrow = (
strokeColor: appState.currentItemStrokeColor,
strokeStyle: appState.currentItemStrokeStyle,
strokeWidth: appState.currentItemStrokeWidth,
points: [point(0, 0), point(endX, endY)],
points: [pointFrom(0, 0), pointFrom(endX, endY)],
elbowed: true,
});

@ -7,7 +7,7 @@ import type {
ViewportPoint,
} from "../../math";
import {
point,
pointFrom,
pointRotateRads,
pointScaleFromOrigin,
radiansToDegrees,
@ -85,7 +85,7 @@ export const headingForPointFromElement = <
const top = pointRotateRads(
pointScaleFromOrigin(
point(element.x + element.width / 2, element.y),
pointFrom(element.x + element.width / 2, element.y),
midPoint,
SEARCH_CONE_MULTIPLIER,
),
@ -94,7 +94,7 @@ export const headingForPointFromElement = <
);
const right = pointRotateRads(
pointScaleFromOrigin(
point(element.x + element.width, element.y + element.height / 2),
pointFrom(element.x + element.width, element.y + element.height / 2),
midPoint,
SEARCH_CONE_MULTIPLIER,
),
@ -103,7 +103,7 @@ export const headingForPointFromElement = <
);
const bottom = pointRotateRads(
pointScaleFromOrigin(
point(element.x + element.width / 2, element.y + element.height),
pointFrom(element.x + element.width / 2, element.y + element.height),
midPoint,
SEARCH_CONE_MULTIPLIER,
),
@ -112,7 +112,7 @@ export const headingForPointFromElement = <
);
const left = pointRotateRads(
pointScaleFromOrigin(
point(element.x, element.y + element.height / 2),
pointFrom(element.x, element.y + element.height / 2),
midPoint,
SEARCH_CONE_MULTIPLIER,
),
@ -136,22 +136,22 @@ export const headingForPointFromElement = <
}
const topLeft = pointScaleFromOrigin(
point(aabb[0], aabb[1]),
pointFrom(aabb[0], aabb[1]),
midPoint,
SEARCH_CONE_MULTIPLIER,
) as Point;
const topRight = pointScaleFromOrigin(
point(aabb[2], aabb[1]),
pointFrom(aabb[2], aabb[1]),
midPoint,
SEARCH_CONE_MULTIPLIER,
) as Point;
const bottomLeft = pointScaleFromOrigin(
point(aabb[0], aabb[3]),
pointFrom(aabb[0], aabb[3]),
midPoint,
SEARCH_CONE_MULTIPLIER,
) as Point;
const bottomRight = pointScaleFromOrigin(
point(aabb[2], aabb[3]),
pointFrom(aabb[2], aabb[3]),
midPoint,
SEARCH_CONE_MULTIPLIER,
) as Point;

@ -44,7 +44,7 @@ import type Scene from "../scene/Scene";
import type { Radians } from "../../math";
import {
pointCenter,
point,
pointFrom,
pointRotateRads,
pointsEqual,
vector,
@ -106,14 +106,14 @@ export class LinearElementEditor {
this.elementId = element.id as string & {
_brand: "excalidrawLinearElementId";
};
if (!pointsEqual(element.points[0], point(0, 0))) {
if (!pointsEqual(element.points[0], pointFrom(0, 0))) {
console.error("Linear element is not normalized", Error().stack);
}
this.selectedPointsIndices = null;
this.lastUncommittedPoint = null;
this.isDragging = false;
this.pointerOffset = point(0, 0);
this.pointerOffset = pointFrom(0, 0);
this.startBindingElement = "keep";
this.endBindingElement = "keep";
this.pointerDownState = {
@ -293,7 +293,7 @@ export class LinearElementEditor {
[
{
index: selectedIndex,
point: point(
point: pointFrom(
width + referencePoint[0],
height + referencePoint[1],
),
@ -327,7 +327,7 @@ export class LinearElementEditor {
),
event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
)
: point(
: pointFrom(
element.points[pointIndex][0] + deltaX,
element.points[pointIndex][1] + deltaY,
);
@ -478,7 +478,7 @@ export class LinearElementEditor {
? [pointerDownState.lastClickedPoint]
: selectedPointsIndices,
isDragging: false,
pointerOffset: point(0, 0),
pointerOffset: pointFrom(0, 0),
};
}
@ -586,7 +586,7 @@ export class LinearElementEditor {
linearElementEditor.segmentMidPointHoveredCoords;
if (existingSegmentMidpointHitCoords) {
const distance = pointDistance(
point(
pointFrom(
existingSegmentMidpointHitCoords[0],
existingSegmentMidpointHitCoords[1],
),
@ -602,7 +602,7 @@ export class LinearElementEditor {
while (index < midPoints.length) {
if (midPoints[index] !== null) {
const distance = pointDistance(
point(midPoints[index]![0], midPoints[index]![1]),
pointFrom(midPoints[index]![0], midPoints[index]![1]),
scenePointer,
);
if (distance <= threshold) {
@ -622,8 +622,8 @@ export class LinearElementEditor {
zoom: AppState["zoom"],
) {
let distance = pointDistance(
point(startPoint[0], startPoint[1]),
point(endPoint[0], endPoint[1]),
pointFrom(startPoint[0], startPoint[1]),
pointFrom(endPoint[0], endPoint[1]),
);
if (element.points.length > 2 && element.roundness) {
distance = getBezierCurveLength(element, endPoint);
@ -823,11 +823,11 @@ export class LinearElementEditor {
const targetPoint =
clickedPointIndex > -1 &&
pointRotateRads<GlobalPoint>(
point(
pointFrom(
element.x + element.points[clickedPointIndex][0],
element.y + element.points[clickedPointIndex][1],
),
point(cx, cy),
pointFrom(cx, cy),
element.angle,
);
@ -857,7 +857,7 @@ export class LinearElementEditor {
selectedPointsIndices: nextSelectedPointsIndices,
pointerOffset: targetPoint
? pointSubtract(scenePointer, targetPoint)
: point(0, 0),
: pointFrom(0, 0),
};
return ret;
@ -922,7 +922,7 @@ export class LinearElementEditor {
event[KEYS.CTRL_OR_CMD] ? null : app.getEffectiveGridSize(),
);
newPoint = point(
newPoint = pointFrom(
width + lastCommittedPoint[0],
height + lastCommittedPoint[1],
);
@ -976,8 +976,8 @@ export class LinearElementEditor {
const { x, y } = element;
return pointRotateRads(
point(x + p[0], y + p[1]),
point(cx, cy),
pointFrom(x + p[0], y + p[1]),
pointFrom(cx, cy),
element.angle,
);
}
@ -993,8 +993,8 @@ export class LinearElementEditor {
return element.points.map((p) => {
const { x, y } = element;
return pointRotateRads(
point(x + p[0], y + p[1]),
point(cx, cy),
pointFrom(x + p[0], y + p[1]),
pointFrom(cx, cy),
element.angle,
);
});
@ -1017,8 +1017,12 @@ export class LinearElementEditor {
const { x, y } = element;
return p
? pointRotateRads(point(x + p[0], y + p[1]), point(cx, cy), element.angle)
: pointRotateRads(point(x, y), point(cx, cy), element.angle);
? pointRotateRads(
pointFrom(x + p[0], y + p[1]),
pointFrom(cx, cy),
element.angle,
)
: pointRotateRads(pointFrom(x, y), pointFrom(cx, cy), element.angle);
}
static pointFromAbsoluteCoords(
@ -1028,7 +1032,7 @@ export class LinearElementEditor {
): LocalPoint {
if (isElbowArrow(element)) {
// No rotation for elbow arrows
return point(
return pointFrom(
absoluteCoords[0] - element.x,
absoluteCoords[1] - element.y,
);
@ -1038,11 +1042,11 @@ export class LinearElementEditor {
const cx = (x1 + x2) / 2;
const cy = (y1 + y2) / 2;
const [x, y] = pointRotateRads(
point(absoluteCoords[0], absoluteCoords[1]),
point(cx, cy),
pointFrom(absoluteCoords[0], absoluteCoords[1]),
pointFrom(cx, cy),
-element.angle as Radians,
);
return point(x - element.x, y - element.y);
return pointFrom(x - element.x, y - element.y);
}
static getPointIndexUnderCursor(
@ -1087,12 +1091,12 @@ export class LinearElementEditor {
const cx = (x1 + x2) / 2;
const cy = (y1 + y2) / 2;
const [rotatedX, rotatedY] = pointRotateRads(
point(pointerOnGrid[0], pointerOnGrid[1]),
point(cx, cy),
pointFrom(pointerOnGrid[0], pointerOnGrid[1]),
pointFrom(cx, cy),
-element.angle as Radians,
);
return point(rotatedX - element.x, rotatedY - element.y);
return pointFrom(rotatedX - element.x, rotatedY - element.y);
}
/**
@ -1112,7 +1116,7 @@ export class LinearElementEditor {
return {
points: points.map((p) => {
return point(p[0] - offsetX, p[1] - offsetY);
return pointFrom(p[0] - offsetX, p[1] - offsetY);
}),
x: element.x + offsetX,
y: element.y + offsetY,
@ -1166,8 +1170,8 @@ export class LinearElementEditor {
}
acc.push(
nextPoint
? point((p[0] + nextPoint[0]) / 2, (p[1] + nextPoint[1]) / 2)
: point(p[0], p[1]),
? pointFrom((p[0] + nextPoint[0]) / 2, (p[1] + nextPoint[1]) / 2)
: pointFrom(p[0], p[1]),
);
nextSelectedIndices.push(indexCursor + 1);
@ -1188,7 +1192,7 @@ export class LinearElementEditor {
[
{
index: element.points.length - 1,
point: point(lastPoint[0] + 30, lastPoint[1] + 30),
point: pointFrom(lastPoint[0] + 30, lastPoint[1] + 30),
},
],
elementsMap,
@ -1229,7 +1233,9 @@ export class LinearElementEditor {
const nextPoints = element.points.reduce((acc: LocalPoint[], p, idx) => {
if (!pointIndices.includes(idx)) {
acc.push(
!acc.length ? point(0, 0) : point(p[0] - offsetX, p[1] - offsetY),
!acc.length
? pointFrom(0, 0)
: pointFrom(p[0] - offsetX, p[1] - offsetY),
);
}
return acc;
@ -1306,9 +1312,9 @@ export class LinearElementEditor {
const deltaY =
selectedPointData.point[1] - points[selectedPointData.index][1];
return point(p[0] + deltaX - offsetX, p[1] + deltaY - offsetY);
return pointFrom(p[0] + deltaX - offsetX, p[1] + deltaY - offsetY);
}
return offsetX || offsetY ? point(p[0] - offsetX, p[1] - offsetY) : p;
return offsetX || offsetY ? pointFrom(p[0] - offsetX, p[1] - offsetY) : p;
});
LinearElementEditor._updatePoints(
@ -1483,8 +1489,8 @@ export class LinearElementEditor {
const dX = prevCenterX - nextCenterX;
const dY = prevCenterY - nextCenterY;
const rotated = pointRotateRads(
point(offsetX, offsetY),
point(dX, dY),
pointFrom(offsetX, offsetY),
pointFrom(dX, dY),
element.angle,
);
mutateElement(element, {
@ -1530,8 +1536,8 @@ export class LinearElementEditor {
);
return pointRotateRads(
point(width, height),
point(0, 0),
pointFrom(width, height),
pointFrom(0, 0),
-element.angle as Radians,
);
}
@ -1601,36 +1607,36 @@ export class LinearElementEditor {
);
const boundTextX2 = boundTextX1 + boundTextElement.width;
const boundTextY2 = boundTextY1 + boundTextElement.height;
const centerPoint = point(cx, cy);
const centerPoint = pointFrom(cx, cy);
const topLeftRotatedPoint = pointRotateRads(
point(x1, y1),
pointFrom(x1, y1),
centerPoint,
element.angle,
);
const topRightRotatedPoint = pointRotateRads(
point(x2, y1),
pointFrom(x2, y1),
centerPoint,
element.angle,
);
const counterRotateBoundTextTopLeft = pointRotateRads(
point(boundTextX1, boundTextY1),
pointFrom(boundTextX1, boundTextY1),
centerPoint,
-element.angle as Radians,
);
const counterRotateBoundTextTopRight = pointRotateRads(
point(boundTextX2, boundTextY1),
pointFrom(boundTextX2, boundTextY1),
centerPoint,
-element.angle as Radians,
);
const counterRotateBoundTextBottomLeft = pointRotateRads(
point(boundTextX1, boundTextY2),
pointFrom(boundTextX1, boundTextY2),
centerPoint,
-element.angle as Radians,
);
const counterRotateBoundTextBottomRight = pointRotateRads(
point(boundTextX2, boundTextY2),
pointFrom(boundTextX2, boundTextY2),
centerPoint,
-element.angle as Radians,
);

@ -5,7 +5,7 @@ import { FONT_FAMILY, ROUNDNESS } from "../constants";
import { isPrimitive } from "../utils";
import type { ExcalidrawLinearElement } from "./types";
import type { LocalPoint } from "../../math";
import { point } from "../../math";
import { pointFrom } from "../../math";
const assertCloneObjects = (source: any, clone: any) => {
for (const key in clone) {
@ -38,7 +38,7 @@ describe("duplicating single elements", () => {
element.__proto__ = { hello: "world" };
mutateElement(element, {
points: [point<LocalPoint>(1, 2), point<LocalPoint>(3, 4)],
points: [pointFrom<LocalPoint>(1, 2), pointFrom<LocalPoint>(3, 4)],
});
const copy = duplicateElement(null, new Map(), element);

@ -56,7 +56,7 @@ import type { GlobalPoint } from "../../math";
import {
pointCenter,
normalizeRadians,
point,
pointFrom,
pointFromPair,
pointRotateRads,
type Radians,
@ -239,8 +239,8 @@ const resizeSingleTextElement = (
);
// rotation pointer with reverse angle
const [rotatedX, rotatedY] = pointRotateRads(
point(pointerX, pointerY),
point(cx, cy),
pointFrom(pointerX, pointerY),
pointFrom(cx, cy),
-element.angle as Radians,
);
let scaleX = 0;
@ -275,23 +275,23 @@ const resizeSingleTextElement = (
const startBottomRight = [x2, y2];
const startCenter = [cx, cy];
let newTopLeft = point<GlobalPoint>(x1, y1);
let newTopLeft = pointFrom<GlobalPoint>(x1, y1);
if (["n", "w", "nw"].includes(transformHandleType)) {
newTopLeft = point<GlobalPoint>(
newTopLeft = pointFrom<GlobalPoint>(
startBottomRight[0] - Math.abs(nextWidth),
startBottomRight[1] - Math.abs(nextHeight),
);
}
if (transformHandleType === "ne") {
const bottomLeft = [startTopLeft[0], startBottomRight[1]];
newTopLeft = point<GlobalPoint>(
newTopLeft = pointFrom<GlobalPoint>(
bottomLeft[0],
bottomLeft[1] - Math.abs(nextHeight),
);
}
if (transformHandleType === "sw") {
const topRight = [startBottomRight[0], startTopLeft[1]];
newTopLeft = point<GlobalPoint>(
newTopLeft = pointFrom<GlobalPoint>(
topRight[0] - Math.abs(nextWidth),
topRight[1],
);
@ -310,12 +310,20 @@ const resizeSingleTextElement = (
}
const angle = element.angle;
const rotatedTopLeft = pointRotateRads(newTopLeft, point(cx, cy), angle);
const newCenter = point<GlobalPoint>(
const rotatedTopLeft = pointRotateRads(
newTopLeft,
pointFrom(cx, cy),
angle,
);
const newCenter = pointFrom<GlobalPoint>(
newTopLeft[0] + Math.abs(nextWidth) / 2,
newTopLeft[1] + Math.abs(nextHeight) / 2,
);
const rotatedNewCenter = pointRotateRads(newCenter, point(cx, cy), angle);
const rotatedNewCenter = pointRotateRads(
newCenter,
pointFrom(cx, cy),
angle,
);
newTopLeft = pointRotateRads(
rotatedTopLeft,
rotatedNewCenter,
@ -340,12 +348,12 @@ const resizeSingleTextElement = (
stateAtResizeStart.height,
true,
);
const startTopLeft = point<GlobalPoint>(x1, y1);
const startBottomRight = point<GlobalPoint>(x2, y2);
const startTopLeft = pointFrom<GlobalPoint>(x1, y1);
const startBottomRight = pointFrom<GlobalPoint>(x2, y2);
const startCenter = pointCenter(startTopLeft, startBottomRight);
const rotatedPointer = pointRotateRads(
point(pointerX, pointerY),
pointFrom(pointerX, pointerY),
startCenter,
-stateAtResizeStart.angle as Radians,
);
@ -418,7 +426,7 @@ const resizeSingleTextElement = (
startCenter,
angle,
);
const newCenter = point(
const newCenter = pointFrom(
newTopLeft[0] + Math.abs(newBoundsWidth) / 2,
newTopLeft[1] + Math.abs(newBoundsHeight) / 2,
);
@ -460,13 +468,13 @@ export const resizeSingleElement = (
stateAtResizeStart.height,
true,
);
const startTopLeft = point(x1, y1);
const startBottomRight = point(x2, y2);
const startTopLeft = pointFrom(x1, y1);
const startBottomRight = pointFrom(x2, y2);
const startCenter = pointCenter(startTopLeft, startBottomRight);
// Calculate new dimensions based on cursor position
const rotatedPointer = pointRotateRads(
point(pointerX, pointerY),
pointFrom(pointerX, pointerY),
startCenter,
-stateAtResizeStart.angle as Radians,
);
@ -647,7 +655,7 @@ export const resizeSingleElement = (
startCenter,
angle,
);
const newCenter = point(
const newCenter = pointFrom(
newTopLeft[0] + Math.abs(newBoundsWidth) / 2,
newTopLeft[1] + Math.abs(newBoundsHeight) / 2,
);
@ -818,20 +826,20 @@ export const resizeMultipleElements = (
const direction = transformHandleType;
const anchorsMap: Record<TransformHandleDirection, GlobalPoint> = {
ne: point(minX, maxY),
se: point(minX, minY),
sw: point(maxX, minY),
nw: point(maxX, maxY),
e: point(minX, minY + height / 2),
w: point(maxX, minY + height / 2),
n: point(minX + width / 2, maxY),
s: point(minX + width / 2, minY),
ne: pointFrom(minX, maxY),
se: pointFrom(minX, minY),
sw: pointFrom(maxX, minY),
nw: pointFrom(maxX, maxY),
e: pointFrom(minX, minY + height / 2),
w: pointFrom(maxX, minY + height / 2),
n: pointFrom(minX + width / 2, maxY),
s: pointFrom(minX + width / 2, minY),
};
// anchor point must be on the opposite side of the dragged selection handle
// or be the center of the selection if shouldResizeFromCenter
const [anchorX, anchorY] = shouldResizeFromCenter
? point(midX, midY)
? pointFrom(midX, midY)
: anchorsMap[direction];
const resizeFromCenterScale = shouldResizeFromCenter ? 2 : 1;
@ -1045,8 +1053,8 @@ const rotateMultipleElements = (
const origAngle =
originalElements.get(element.id)?.angle ?? element.angle;
const [rotatedCX, rotatedCY] = pointRotateRads(
point(cx, cy),
point(centerX, centerY),
pointFrom(cx, cy),
pointFrom(centerX, centerY),
(centerAngle + origAngle - element.angle) as Radians,
);
@ -1101,40 +1109,44 @@ export const getResizeOffsetXY = (
const angle = (
selectedElements.length === 1 ? selectedElements[0].angle : 0
) as Radians;
[x, y] = pointRotateRads(point(x, y), point(cx, cy), -angle as Radians);
[x, y] = pointRotateRads(
pointFrom(x, y),
pointFrom(cx, cy),
-angle as Radians,
);
switch (transformHandleType) {
case "n":
return pointRotateRads(
point(x - (x1 + x2) / 2, y - y1),
point(0, 0),
pointFrom(x - (x1 + x2) / 2, y - y1),
pointFrom(0, 0),
angle,
);
case "s":
return pointRotateRads(
point(x - (x1 + x2) / 2, y - y2),
point(0, 0),
pointFrom(x - (x1 + x2) / 2, y - y2),
pointFrom(0, 0),
angle,
);
case "w":
return pointRotateRads(
point(x - x1, y - (y1 + y2) / 2),
point(0, 0),
pointFrom(x - x1, y - (y1 + y2) / 2),
pointFrom(0, 0),
angle,
);
case "e":
return pointRotateRads(
point(x - x2, y - (y1 + y2) / 2),
point(0, 0),
pointFrom(x - x2, y - (y1 + y2) / 2),
pointFrom(0, 0),
angle,
);
case "nw":
return pointRotateRads(point(x - x1, y - y1), point(0, 0), angle);
return pointRotateRads(pointFrom(x - x1, y - y1), pointFrom(0, 0), angle);
case "ne":
return pointRotateRads(point(x - x2, y - y1), point(0, 0), angle);
return pointRotateRads(pointFrom(x - x2, y - y1), pointFrom(0, 0), angle);
case "sw":
return pointRotateRads(point(x - x1, y - y2), point(0, 0), angle);
return pointRotateRads(pointFrom(x - x1, y - y2), pointFrom(0, 0), angle);
case "se":
return pointRotateRads(point(x - x2, y - y2), point(0, 0), angle);
return pointRotateRads(pointFrom(x - x2, y - y2), pointFrom(0, 0), angle);
default:
return [0, 0];
}

@ -23,7 +23,7 @@ import { SIDE_RESIZING_THRESHOLD } from "../constants";
import { isLinearElement } from "./typeChecks";
import type { GlobalPoint, Segment, LocalPoint } from "../../math";
import {
point,
pointFrom,
segmentIncludesPoint,
pointRotateRads,
type Radians,
@ -92,9 +92,9 @@ export const resizeTest = <Point extends GlobalPoint | LocalPoint>(
if (!(isLinearElement(element) && element.points.length <= 2)) {
const SPACING = SIDE_RESIZING_THRESHOLD / zoom.value;
const sides = getSelectionBorders(
point<Point>(x1 - SPACING, y1 - SPACING),
point(x2 + SPACING, y2 + SPACING),
point(cx, cy),
pointFrom<Point>(x1 - SPACING, y1 - SPACING),
pointFrom(x2 + SPACING, y2 + SPACING),
pointFrom(cx, cy),
element.angle,
);
@ -102,7 +102,7 @@ export const resizeTest = <Point extends GlobalPoint | LocalPoint>(
// test to see if x, y are on the line segment
if (
segmentIncludesPoint(
point<Point>(x, y),
pointFrom<Point>(x, y),
side as Segment<Point>,
SPACING,
)
@ -178,9 +178,9 @@ export const getTransformHandleTypeFromCoords = (
const SPACING = SIDE_RESIZING_THRESHOLD / zoom.value;
const sides = getSelectionBorders(
point<GlobalPoint>(x1 - SPACING, y1 - SPACING),
point(x2 + SPACING, y2 + SPACING),
point(cx, cy),
pointFrom<GlobalPoint>(x1 - SPACING, y1 - SPACING),
pointFrom(x2 + SPACING, y2 + SPACING),
pointFrom(cx, cy),
0 as Radians,
);
@ -265,10 +265,10 @@ const getSelectionBorders = <Point extends LocalPoint | GlobalPoint>(
center: Point,
angle: Radians,
) => {
const topLeft = pointRotateRads(point(x1, y1), center, angle);
const topRight = pointRotateRads(point(x2, y1), center, angle);
const bottomLeft = pointRotateRads(point(x1, y2), center, angle);
const bottomRight = pointRotateRads(point(x2, y2), center, angle);
const topLeft = pointRotateRads(pointFrom(x1, y1), center, angle);
const topRight = pointRotateRads(pointFrom(x2, y1), center, angle);
const bottomLeft = pointRotateRads(pointFrom(x1, y2), center, angle);
const bottomRight = pointRotateRads(pointFrom(x2, y2), center, angle);
return {
n: [topLeft, topRight],

@ -17,7 +17,7 @@ import type {
ExcalidrawElbowArrowElement,
} from "./types";
import { ARROW_TYPE } from "../constants";
import { point } from "../../math";
import { pointFrom } from "../../math";
const { h } = window;
@ -32,8 +32,8 @@ describe("elbow arrow routing", () => {
}) as ExcalidrawElbowArrowElement;
scene.insertElement(arrow);
mutateElbowArrow(arrow, scene.getNonDeletedElementsMap(), [
point(-45 - arrow.x, -100.1 - arrow.y),
point(45 - arrow.x, 99.9 - arrow.y),
pointFrom(-45 - arrow.x, -100.1 - arrow.y),
pointFrom(45 - arrow.x, 99.9 - arrow.y),
]);
expect(arrow.points).toEqual([
[0, 0],
@ -69,7 +69,7 @@ describe("elbow arrow routing", () => {
y: -100.1,
width: 90,
height: 200,
points: [point(0, 0), point(90, 200)],
points: [pointFrom(0, 0), pointFrom(90, 200)],
}) as ExcalidrawElbowArrowElement;
scene.insertElement(rectangle1);
scene.insertElement(rectangle2);
@ -81,7 +81,7 @@ describe("elbow arrow routing", () => {
expect(arrow.startBinding).not.toBe(null);
expect(arrow.endBinding).not.toBe(null);
mutateElbowArrow(arrow, elementsMap, [point(0, 0), point(90, 200)]);
mutateElbowArrow(arrow, elementsMap, [pointFrom(0, 0), pointFrom(90, 200)]);
expect(arrow.points).toEqual([
[0, 0],

@ -1,7 +1,7 @@
import type { Radians } from "../../math";
import {
pointExtent,
point,
pointFrom,
pointScaleFromOrigin,
pointTranslate,
vector,
@ -743,13 +743,13 @@ const getDonglePosition = (
): GlobalPoint => {
switch (heading) {
case HEADING_UP:
return point(p[0], bounds[1]);
return pointFrom(p[0], bounds[1]);
case HEADING_RIGHT:
return point(bounds[2], p[1]);
return pointFrom(bounds[2], p[1]);
case HEADING_DOWN:
return point(p[0], bounds[3]);
return pointFrom(p[0], bounds[3]);
}
return point(bounds[0], p[1]);
return pointFrom(bounds[0], p[1]);
};
const estimateSegmentCount = (

@ -19,7 +19,7 @@ import type {
import { API } from "../tests/helpers/api";
import { getOriginalContainerHeightFromCache } from "./containerCache";
import { getTextEditor, updateTextEditor } from "../tests/queries/dom";
import { point } from "../../math";
import { pointFrom } from "../../math";
// Unmount ReactDOM from root
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
@ -42,7 +42,7 @@ describe("textWysiwyg", () => {
type: "line",
width: 100,
height: 0,
points: [point(0, 0), point(100, 0)],
points: [pointFrom(0, 0), pointFrom(100, 0)],
});
const textSize = 20;
const text = API.createElement({

@ -19,7 +19,7 @@ import {
isIOS,
} from "../constants";
import type { Radians } from "../../math";
import { point, pointRotateRads } from "../../math";
import { pointFrom, pointRotateRads } from "../../math";
export type TransformHandleDirection =
| "n"
@ -95,8 +95,8 @@ const generateTransformHandle = (
angle: Radians,
): TransformHandle => {
const [xx, yy] = pointRotateRads(
point(x + width / 2, y + height / 2),
point(cx, cy),
pointFrom(x + width / 2, y + height / 2),
pointFrom(cx, cy),
angle,
);
return [xx - width / 2, yy - height / 2, width, height];

@ -37,9 +37,9 @@ import type { GlobalPoint, Segment } from "../math";
import {
isPointWithinBounds,
segment,
point,
pointRotateRads,
segmentsIntersectAt,
pointFrom,
} from "../math";
// --------------------------- Frame State ------------------------------------
@ -88,7 +88,7 @@ const getElementLineSegments = (
elementsMap,
);
const center: GlobalPoint = point(cx, cy);
const center: GlobalPoint = pointFrom(cx, cy);
if (isLinearElement(element) || isFreeDrawElement(element)) {
const segments: Segment<GlobalPoint>[] = [];
@ -99,7 +99,7 @@ const getElementLineSegments = (
segments.push(
segment(
pointRotateRads(
point(
pointFrom(
element.points[i][0] + element.x,
element.points[i][1] + element.y,
),
@ -107,7 +107,7 @@ const getElementLineSegments = (
element.angle,
),
pointRotateRads(
point(
pointFrom(
element.points[i + 1][0] + element.x,
element.points[i + 1][1] + element.y,
),
@ -256,7 +256,11 @@ export const isCursorInFrame = (
) => {
const [fx1, fy1, fx2, fy2] = getElementAbsoluteCoords(frame, elementsMap);
return isPointWithinBounds(point(fx1, fy1), cursorCoords, point(fx2, fy2));
return isPointWithinBounds(
pointFrom(fx1, fy1),
cursorCoords,
pointFrom(fx2, fy2),
);
};
export const groupsAreAtLeastIntersectingTheFrame = (

@ -1,5 +1,5 @@
import type { ViewportPoint } from "../../math";
import { point, type GlobalPoint, type LocalPoint } from "../../math";
import { pointFrom, type GlobalPoint, type LocalPoint } from "../../math";
import { THEME } from "../constants";
import type { PointSnapLine, PointerSnapLine } from "../snapping";
import type { InteractiveCanvasAppState } from "../types";
@ -141,27 +141,31 @@ const drawGapLine = <Point extends LocalPoint | GlobalPoint | ViewportPoint>(
// (1)
if (!appState.zenModeEnabled) {
drawLine(
point(from[0], from[1] - FULL),
point(from[0], from[1] + FULL),
pointFrom(from[0], from[1] - FULL),
pointFrom(from[0], from[1] + FULL),
context,
);
}
// (3)
drawLine(
point(halfPoint[0] - QUARTER, halfPoint[1] - HALF),
point(halfPoint[0] - QUARTER, halfPoint[1] + HALF),
pointFrom(halfPoint[0] - QUARTER, halfPoint[1] - HALF),
pointFrom(halfPoint[0] - QUARTER, halfPoint[1] + HALF),
context,
);
drawLine(
point(halfPoint[0] + QUARTER, halfPoint[1] - HALF),
point(halfPoint[0] + QUARTER, halfPoint[1] + HALF),
pointFrom(halfPoint[0] + QUARTER, halfPoint[1] - HALF),
pointFrom(halfPoint[0] + QUARTER, halfPoint[1] + HALF),
context,
);
if (!appState.zenModeEnabled) {
// (4)
drawLine(point(to[0], to[1] - FULL), point(to[0], to[1] + FULL), context);
drawLine(
pointFrom(to[0], to[1] - FULL),
pointFrom(to[0], to[1] + FULL),
context,
);
// (2)
drawLine(from, to, context);
@ -171,27 +175,31 @@ const drawGapLine = <Point extends LocalPoint | GlobalPoint | ViewportPoint>(
// (1)
if (!appState.zenModeEnabled) {
drawLine(
point(from[0] - FULL, from[1]),
point(from[0] + FULL, from[1]),
pointFrom(from[0] - FULL, from[1]),
pointFrom(from[0] + FULL, from[1]),
context,
);
}
// (3)
drawLine(
point(halfPoint[0] - HALF, halfPoint[1] - QUARTER),
point(halfPoint[0] + HALF, halfPoint[1] - QUARTER),
pointFrom(halfPoint[0] - HALF, halfPoint[1] - QUARTER),
pointFrom(halfPoint[0] + HALF, halfPoint[1] - QUARTER),
context,
);
drawLine(
point(halfPoint[0] - HALF, halfPoint[1] + QUARTER),
point(halfPoint[0] + HALF, halfPoint[1] + QUARTER),
pointFrom(halfPoint[0] - HALF, halfPoint[1] + QUARTER),
pointFrom(halfPoint[0] + HALF, halfPoint[1] + QUARTER),
context,
);
if (!appState.zenModeEnabled) {
// (4)
drawLine(point(to[0] - FULL, to[1]), point(to[0] + FULL, to[1]), context);
drawLine(
pointFrom(to[0] - FULL, to[1]),
pointFrom(to[0] + FULL, to[1]),
context,
);
// (2)
drawLine(from, to, context);

@ -25,7 +25,7 @@ import { canChangeRoundness } from "./comparisons";
import type { EmbedsValidationStatus } from "../types";
import {
pathIsALoop,
point,
pointFrom,
pointDistance,
type GlobalPoint,
type LocalPoint,
@ -409,7 +409,7 @@ export const _generateElementShape = (
// initial position to it
const points = element.points.length
? element.points
: [point<LocalPoint>(0, 0)];
: [pointFrom<LocalPoint>(0, 0)];
if (isElbowArrow(element)) {
shape = [

@ -1,7 +1,7 @@
import type { GenericPoint, ViewportPoint } from "../math";
import {
isPoint,
point,
pointFrom,
pointDistance,
pointFromPair,
pointRotateRads,
@ -167,15 +167,15 @@ export const getElementShape = (
? getClosedCurveShape<GlobalPoint>(
element,
roughShape,
point<GlobalPoint>(element.x, element.y),
pointFrom<GlobalPoint>(element.x, element.y),
element.angle,
point(cx, cy),
pointFrom(cx, cy),
)
: getCurveShape<GlobalPoint>(
roughShape,
point<GlobalPoint>(element.x, element.y),
pointFrom<GlobalPoint>(element.x, element.y),
element.angle,
point(cx, cy),
pointFrom(cx, cy),
);
}
@ -186,7 +186,7 @@ export const getElementShape = (
const [, , , , cx, cy] = getElementAbsoluteCoords(element, elementsMap);
return getFreedrawShape(
element,
point(cx, cy),
pointFrom(cx, cy),
shouldTestInside(element),
);
}
@ -231,7 +231,7 @@ export const getControlPointsForBezierCurve = <P extends GenericPoint>(
}
const ops = getCurvePathOps(shape[0]);
let currentP = point<P>(0, 0);
let currentP = pointFrom<P>(0, 0);
let index = 0;
let minDistance = Infinity;
let controlPoints: P[] | null = null;
@ -247,9 +247,9 @@ export const getControlPointsForBezierCurve = <P extends GenericPoint>(
}
if (op === "bcurveTo") {
const p0 = currentP;
const p1 = point<P>(data[0], data[1]);
const p2 = point<P>(data[2], data[3]);
const p3 = point<P>(data[4], data[5]);
const p1 = pointFrom<P>(data[0], data[1]);
const p2 = pointFrom<P>(data[2], data[3]);
const p3 = pointFrom<P>(data[4], data[5]);
const distance = pointDistance(p3, endPoint);
if (distance < minDistance) {
minDistance = distance;
@ -277,7 +277,7 @@ export const getBezierXY = <P extends GenericPoint>(
p0[idx] * Math.pow(t, 3);
const tx = equation(t, 0);
const ty = equation(t, 1);
return point(tx, ty);
return pointFrom(tx, ty);
};
const getPointsInBezierCurve = <P extends GenericPoint>(
@ -299,12 +299,12 @@ const getPointsInBezierCurve = <P extends GenericPoint>(
controlPoints[3],
t,
);
pointsOnCurve.push(point(p[0], p[1]));
pointsOnCurve.push(pointFrom(p[0], p[1]));
t -= 0.05;
}
if (pointsOnCurve.length) {
if (pointsEqual(pointsOnCurve.at(-1)!, endPoint)) {
pointsOnCurve.push(point(endPoint[0], endPoint[1]));
pointsOnCurve.push(pointFrom(endPoint[0], endPoint[1]));
}
}
return pointsOnCurve;
@ -391,24 +391,24 @@ export const aabbForElement = (
midY: element.y + element.height / 2,
};
const center = point(bbox.midX, bbox.midY);
const center = pointFrom(bbox.midX, bbox.midY);
const [topLeftX, topLeftY] = pointRotateRads(
point(bbox.minX, bbox.minY),
pointFrom(bbox.minX, bbox.minY),
center,
element.angle,
);
const [topRightX, topRightY] = pointRotateRads(
point(bbox.maxX, bbox.minY),
pointFrom(bbox.maxX, bbox.minY),
center,
element.angle,
);
const [bottomRightX, bottomRightY] = pointRotateRads(
point(bbox.maxX, bbox.maxY),
pointFrom(bbox.maxX, bbox.maxY),
center,
element.angle,
);
const [bottomLeftX, bottomLeftY] = pointRotateRads(
point(bbox.minX, bbox.maxY),
pointFrom(bbox.minX, bbox.maxY),
center,
element.angle,
);
@ -442,14 +442,14 @@ export const pointInsideBounds = <
p[0] > bounds[0] && p[0] < bounds[2] && p[1] > bounds[1] && p[1] < bounds[3];
export const aabbsOverlapping = (a: Bounds, b: Bounds) =>
pointInsideBounds(point(a[0], a[1]), b) ||
pointInsideBounds(point(a[2], a[1]), b) ||
pointInsideBounds(point(a[2], a[3]), b) ||
pointInsideBounds(point(a[0], a[3]), b) ||
pointInsideBounds(point(b[0], b[1]), a) ||
pointInsideBounds(point(b[2], b[1]), a) ||
pointInsideBounds(point(b[2], b[3]), a) ||
pointInsideBounds(point(b[0], b[3]), a);
pointInsideBounds(pointFrom(a[0], a[1]), b) ||
pointInsideBounds(pointFrom(a[2], a[1]), b) ||
pointInsideBounds(pointFrom(a[2], a[3]), b) ||
pointInsideBounds(pointFrom(a[0], a[3]), b) ||
pointInsideBounds(pointFrom(b[0], b[1]), a) ||
pointInsideBounds(pointFrom(b[2], b[1]), a) ||
pointInsideBounds(pointFrom(b[2], b[3]), a) ||
pointInsideBounds(pointFrom(b[0], b[3]), a);
export const getCornerRadius = (x: number, element: ExcalidrawElement) => {
if (

@ -1,6 +1,6 @@
import type { InclusiveRange } from "../math";
import {
point,
pointFrom,
pointRotateRads,
rangeInclusive,
rangeIntersection,
@ -228,52 +228,52 @@ export const getElementsCorners = (
!boundingBoxCorners
) {
const leftMid = pointRotateRads<GlobalPoint>(
point(x1, y1 + halfHeight),
point(cx, cy),
pointFrom(x1, y1 + halfHeight),
pointFrom(cx, cy),
element.angle,
);
const topMid = pointRotateRads<GlobalPoint>(
point(x1 + halfWidth, y1),
point(cx, cy),
pointFrom(x1 + halfWidth, y1),
pointFrom(cx, cy),
element.angle,
);
const rightMid = pointRotateRads<GlobalPoint>(
point(x2, y1 + halfHeight),
point(cx, cy),
pointFrom(x2, y1 + halfHeight),
pointFrom(cx, cy),
element.angle,
);
const bottomMid = pointRotateRads<GlobalPoint>(
point(x1 + halfWidth, y2),
point(cx, cy),
pointFrom(x1 + halfWidth, y2),
pointFrom(cx, cy),
element.angle,
);
const center = point<GlobalPoint>(cx, cy);
const center = pointFrom<GlobalPoint>(cx, cy);
result = omitCenter
? [leftMid, topMid, rightMid, bottomMid]
: [leftMid, topMid, rightMid, bottomMid, center];
} else {
const topLeft = pointRotateRads<GlobalPoint>(
point(x1, y1),
point(cx, cy),
pointFrom(x1, y1),
pointFrom(cx, cy),
element.angle,
);
const topRight = pointRotateRads<GlobalPoint>(
point(x2, y1),
point(cx, cy),
pointFrom(x2, y1),
pointFrom(cx, cy),
element.angle,
);
const bottomLeft = pointRotateRads<GlobalPoint>(
point(x1, y2),
point(cx, cy),
pointFrom(x1, y2),
pointFrom(cx, cy),
element.angle,
);
const bottomRight = pointRotateRads<GlobalPoint>(
point(x2, y2),
point(cx, cy),
pointFrom(x2, y2),
pointFrom(cx, cy),
element.angle,
);
const center = point<GlobalPoint>(cx, cy);
const center = pointFrom<GlobalPoint>(cx, cy);
result = omitCenter
? [topLeft, topRight, bottomLeft, bottomRight]
@ -287,18 +287,18 @@ export const getElementsCorners = (
const width = maxX - minX;
const height = maxY - minY;
const topLeft = point<GlobalPoint>(minX, minY);
const topRight = point<GlobalPoint>(maxX, minY);
const bottomLeft = point<GlobalPoint>(minX, maxY);
const bottomRight = point<GlobalPoint>(maxX, maxY);
const center = point<GlobalPoint>(minX + width / 2, minY + height / 2);
const topLeft = pointFrom<GlobalPoint>(minX, minY);
const topRight = pointFrom<GlobalPoint>(maxX, minY);
const bottomLeft = pointFrom<GlobalPoint>(minX, maxY);
const bottomRight = pointFrom<GlobalPoint>(maxX, maxY);
const center = pointFrom<GlobalPoint>(minX + width / 2, minY + height / 2);
result = omitCenter
? [topLeft, topRight, bottomLeft, bottomRight]
: [topLeft, topRight, bottomLeft, bottomRight, center];
}
return result.map((p) => point(round(p[0]), round(p[1])));
return result.map((p) => pointFrom(round(p[0]), round(p[1])));
};
const getReferenceElements = (
@ -375,8 +375,11 @@ export const getVisibleGaps = (
horizontalGaps.push({
startBounds,
endBounds,
startSide: [point(startMaxX, startMinY), point(startMaxX, startMaxY)],
endSide: [point(endMinX, endMinY), point(endMinX, endMaxY)],
startSide: [
pointFrom(startMaxX, startMinY),
pointFrom(startMaxX, startMaxY),
],
endSide: [pointFrom(endMinX, endMinY), pointFrom(endMinX, endMaxY)],
length: endMinX - startMaxX,
overlap: rangeIntersection(
rangeInclusive(startMinY, startMaxY),
@ -415,8 +418,11 @@ export const getVisibleGaps = (
verticalGaps.push({
startBounds,
endBounds,
startSide: [point(startMinX, startMaxY), point(startMaxX, startMaxY)],
endSide: [point(endMinX, endMinY), point(endMaxX, endMinY)],
startSide: [
pointFrom(startMinX, startMaxY),
pointFrom(startMaxX, startMaxY),
],
endSide: [pointFrom(endMinX, endMinY), pointFrom(endMaxX, endMinY)],
length: endMinY - startMaxY,
overlap: rangeIntersection(
rangeInclusive(startMinX, startMaxX),
@ -832,7 +838,7 @@ const createPointSnapLines = (
}
snapsX[key].push(
...snap.points.map((p) =>
point<GlobalPoint>(round(p[0]), round(p[1])),
pointFrom<GlobalPoint>(round(p[0]), round(p[1])),
),
);
}
@ -849,7 +855,7 @@ const createPointSnapLines = (
}
snapsY[key].push(
...snap.points.map((p) =>
point<GlobalPoint>(round(p[0]), round(p[1])),
pointFrom<GlobalPoint>(round(p[0]), round(p[1])),
),
);
}
@ -863,7 +869,7 @@ const createPointSnapLines = (
points: dedupePoints(
points
.map((p) => {
return point<GlobalPoint>(Number(key), p[1]);
return pointFrom<GlobalPoint>(Number(key), p[1]);
})
.sort((a, b) => a[1] - b[1]),
),
@ -876,7 +882,7 @@ const createPointSnapLines = (
points: dedupePoints(
points
.map((p) => {
return point<GlobalPoint>(p[0], Number(key));
return pointFrom<GlobalPoint>(p[0], Number(key));
})
.sort((a, b) => a[0] - b[0]),
),
@ -940,16 +946,16 @@ const createGapSnapLines = (
type: "gap",
direction: "horizontal",
points: [
point(gapSnap.gap.startSide[0][0], gapLineY),
point(minX, gapLineY),
pointFrom(gapSnap.gap.startSide[0][0], gapLineY),
pointFrom(minX, gapLineY),
],
},
{
type: "gap",
direction: "horizontal",
points: [
point(maxX, gapLineY),
point(gapSnap.gap.endSide[0][0], gapLineY),
pointFrom(maxX, gapLineY),
pointFrom(gapSnap.gap.endSide[0][0], gapLineY),
],
},
);
@ -966,16 +972,16 @@ const createGapSnapLines = (
type: "gap",
direction: "vertical",
points: [
point(gapLineX, gapSnap.gap.startSide[0][1]),
point(gapLineX, minY),
pointFrom(gapLineX, gapSnap.gap.startSide[0][1]),
pointFrom(gapLineX, minY),
],
},
{
type: "gap",
direction: "vertical",
points: [
point(gapLineX, maxY),
point(gapLineX, gapSnap.gap.endSide[0][1]),
pointFrom(gapLineX, maxY),
pointFrom(gapLineX, gapSnap.gap.endSide[0][1]),
],
},
);
@ -991,12 +997,15 @@ const createGapSnapLines = (
{
type: "gap",
direction: "horizontal",
points: [point(startMaxX, gapLineY), point(endMinX, gapLineY)],
points: [
pointFrom(startMaxX, gapLineY),
pointFrom(endMinX, gapLineY),
],
},
{
type: "gap",
direction: "horizontal",
points: [point(endMaxX, gapLineY), point(minX, gapLineY)],
points: [pointFrom(endMaxX, gapLineY), pointFrom(minX, gapLineY)],
},
);
}
@ -1011,12 +1020,18 @@ const createGapSnapLines = (
{
type: "gap",
direction: "horizontal",
points: [point(maxX, gapLineY), point(startMinX, gapLineY)],
points: [
pointFrom(maxX, gapLineY),
pointFrom(startMinX, gapLineY),
],
},
{
type: "gap",
direction: "horizontal",
points: [point(startMaxX, gapLineY), point(endMinX, gapLineY)],
points: [
pointFrom(startMaxX, gapLineY),
pointFrom(endMinX, gapLineY),
],
},
);
}
@ -1031,12 +1046,18 @@ const createGapSnapLines = (
{
type: "gap",
direction: "vertical",
points: [point(gapLineX, maxY), point(gapLineX, startMinY)],
points: [
pointFrom(gapLineX, maxY),
pointFrom(gapLineX, startMinY),
],
},
{
type: "gap",
direction: "vertical",
points: [point(gapLineX, startMaxY), point(gapLineX, endMinY)],
points: [
pointFrom(gapLineX, startMaxY),
pointFrom(gapLineX, endMinY),
],
},
);
}
@ -1051,12 +1072,15 @@ const createGapSnapLines = (
{
type: "gap",
direction: "vertical",
points: [point(gapLineX, startMaxY), point(gapLineX, endMinY)],
points: [
pointFrom(gapLineX, startMaxY),
pointFrom(gapLineX, endMinY),
],
},
{
type: "gap",
direction: "vertical",
points: [point(gapLineX, endMaxY), point(gapLineX, minY)],
points: [pointFrom(gapLineX, endMaxY), pointFrom(gapLineX, minY)],
},
);
}
@ -1070,7 +1094,7 @@ const createGapSnapLines = (
return {
...gapSnapLine,
points: gapSnapLine.points.map((p) =>
point(round(p[0]), round(p[1])),
pointFrom(round(p[0]), round(p[1])),
) as PointPair,
};
}),
@ -1120,35 +1144,35 @@ export const snapResizingElements = (
if (transformHandle) {
switch (transformHandle) {
case "e": {
selectionSnapPoints.push(point(maxX, minY), point(maxX, maxY));
selectionSnapPoints.push(pointFrom(maxX, minY), pointFrom(maxX, maxY));
break;
}
case "w": {
selectionSnapPoints.push(point(minX, minY), point(minX, maxY));
selectionSnapPoints.push(pointFrom(minX, minY), pointFrom(minX, maxY));
break;
}
case "n": {
selectionSnapPoints.push(point(minX, minY), point(maxX, minY));
selectionSnapPoints.push(pointFrom(minX, minY), pointFrom(maxX, minY));
break;
}
case "s": {
selectionSnapPoints.push(point(minX, maxY), point(maxX, maxY));
selectionSnapPoints.push(pointFrom(minX, maxY), pointFrom(maxX, maxY));
break;
}
case "ne": {
selectionSnapPoints.push(point(maxX, minY));
selectionSnapPoints.push(pointFrom(maxX, minY));
break;
}
case "nw": {
selectionSnapPoints.push(point(minX, minY));
selectionSnapPoints.push(pointFrom(minX, minY));
break;
}
case "se": {
selectionSnapPoints.push(point(maxX, maxY));
selectionSnapPoints.push(pointFrom(maxX, maxY));
break;
}
case "sw": {
selectionSnapPoints.push(point(minX, maxY));
selectionSnapPoints.push(pointFrom(minX, maxY));
break;
}
}
@ -1191,10 +1215,10 @@ export const snapResizingElements = (
);
const corners: GlobalPoint[] = [
point(x1, y1),
point(x1, y2),
point(x2, y1),
point(x2, y2),
pointFrom(x1, y1),
pointFrom(x1, y2),
pointFrom(x2, y1),
pointFrom(x2, y2),
];
getPointSnaps(
@ -1231,7 +1255,7 @@ export const snapNewElement = (
}
const selectionSnapPoints: GlobalPoint[] = [
point(origin.x + dragOffset.x, origin.y + dragOffset.y),
pointFrom(origin.x + dragOffset.x, origin.y + dragOffset.y),
];
const snapDistance = getSnapDistance(app.state.zoom.value);
@ -1331,7 +1355,7 @@ export const getSnapLinesAtPointer = (
verticalSnapLines.push({
type: "pointer",
points: [corner, point(corner[0], pointer.y)],
points: [corner, pointFrom(corner[0], pointer.y)],
direction: "vertical",
});
@ -1347,7 +1371,7 @@ export const getSnapLinesAtPointer = (
horizontalSnapLines.push({
type: "pointer",
points: [corner, point(pointer.x, corner[1])],
points: [corner, pointFrom(pointer.x, corner[1])],
direction: "horizontal",
});

@ -7,7 +7,7 @@ import { API } from "./helpers/api";
import { KEYS } from "../keys";
import { actionWrapTextInContainer } from "../actions/actionBoundText";
import { arrayToMap } from "../utils";
import { point } from "../../math";
import { pointFrom } from "../../math";
const { h } = window;
@ -32,7 +32,12 @@ describe("element binding", () => {
y: 0,
width: 100,
height: 1,
points: [point(0, 0), point(0, 0), point(100, 0), point(100, 0)],
points: [
pointFrom(0, 0),
pointFrom(0, 0),
pointFrom(100, 0),
pointFrom(100, 0),
],
});
API.setElements([rect, arrow]);
expect(arrow.startBinding).toBe(null);
@ -310,7 +315,7 @@ describe("element binding", () => {
const arrow1 = API.createElement({
type: "arrow",
id: "arrow1",
points: [point(0, 0), point(0, -87.45777932247563)],
points: [pointFrom(0, 0), pointFrom(0, -87.45777932247563)],
startBinding: {
elementId: "rectangle1",
focus: 0.2,
@ -328,7 +333,7 @@ describe("element binding", () => {
const arrow2 = API.createElement({
type: "arrow",
id: "arrow2",
points: [point(0, 0), point(0, -87.45777932247563)],
points: [pointFrom(0, 0), pointFrom(0, -87.45777932247563)],
startBinding: {
elementId: "text1",
focus: 0.2,

@ -38,7 +38,7 @@ import type App from "../../components/App";
import { createTestHook } from "../../components/App";
import type { Action } from "../../actions/types";
import { mutateElement } from "../../element/mutateElement";
import { point, type LocalPoint, type Radians } from "../../../math";
import { pointFrom, type LocalPoint, type Radians } from "../../../math";
const readFile = util.promisify(fs.readFile);
// so that window.h is available when App.tsx is not imported as well.
@ -307,8 +307,8 @@ export class API {
height,
type,
points: rest.points ?? [
point<LocalPoint>(0, 0),
point<LocalPoint>(100, 100),
pointFrom<LocalPoint>(0, 0),
pointFrom<LocalPoint>(100, 100),
],
elbowed: rest.elbowed ?? false,
});
@ -320,8 +320,8 @@ export class API {
height,
type,
points: rest.points ?? [
point<LocalPoint>(0, 0),
point<LocalPoint>(100, 100),
pointFrom<LocalPoint>(0, 0),
pointFrom<LocalPoint>(100, 100),
],
});
break;

@ -34,7 +34,7 @@ import { getTextEditor } from "../queries/dom";
import { arrayToMap } from "../../utils";
import { createTestHook } from "../../components/App";
import type { GlobalPoint, LocalPoint, Radians } from "../../../math";
import { point, pointRotateRads } from "../../../math";
import { pointFrom, pointRotateRads } from "../../../math";
// so that window.h is available when App.tsx is not imported as well.
createTestHook();
@ -142,7 +142,7 @@ const getElementPointForSelection = (
element: ExcalidrawElement,
): GlobalPoint => {
const { x, y, width, height, angle } = element;
const target = point<GlobalPoint>(
const target = pointFrom<GlobalPoint>(
x +
(isLinearElement(element) || isFreeDrawElement(element) ? 0 : width / 2),
y,
@ -151,9 +151,12 @@ const getElementPointForSelection = (
if (isLinearElement(element)) {
const bounds = getElementPointsCoords(element, element.points);
center = point((bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2);
center = pointFrom(
(bounds[0] + bounds[2]) / 2,
(bounds[1] + bounds[3]) / 2,
);
} else {
center = point(x + width / 2, y + height / 2);
center = pointFrom(x + width / 2, y + height / 2);
}
if (isTextElement(element)) {
@ -469,8 +472,8 @@ export class UI {
const width = initialWidth ?? initialHeight ?? size;
const height = initialHeight ?? size;
const points: LocalPoint[] = initialPoints ?? [
point(0, 0),
point(width, height),
pointFrom(0, 0),
pointFrom(width, height),
];
UI.clickTool(type);

@ -46,7 +46,7 @@ import { HistoryEntry } from "../history";
import { AppStateChange, ElementsChange } from "../change";
import { Snapshot, StoreAction } from "../store";
import type { LocalPoint, Radians } from "../../math";
import { point } from "../../math";
import { pointFrom } from "../../math";
const { h } = window;
@ -2041,9 +2041,9 @@ describe("history", () => {
width: 178.9000000000001,
height: 236.10000000000002,
points: [
point(0, 0),
point(178.9000000000001, 0),
point(178.9000000000001, 236.10000000000002),
pointFrom(0, 0),
pointFrom(178.9000000000001, 0),
pointFrom(178.9000000000001, 236.10000000000002),
],
startBinding: {
elementId: "KPrBI4g_v9qUB1XxYLgSz",
@ -2159,11 +2159,11 @@ describe("history", () => {
elements: [
newElementWith(h.elements[0] as ExcalidrawLinearElement, {
points: [
point(0, 0),
point(5, 5),
point(10, 10),
point(15, 15),
point(20, 20),
pointFrom(0, 0),
pointFrom(5, 5),
pointFrom(10, 10),
pointFrom(15, 15),
pointFrom(20, 20),
] as LocalPoint[],
}),
],

@ -28,7 +28,7 @@ import { ROUNDNESS, VERTICAL_ALIGN } from "../constants";
import { vi } from "vitest";
import { arrayToMap } from "../utils";
import type { GlobalPoint } from "../../math";
import { pointCenter, point } from "../../math";
import { pointCenter, pointFrom } from "../../math";
const renderInteractiveScene = vi.spyOn(
InteractiveCanvas,
@ -57,8 +57,8 @@ describe("Test Linear Elements", () => {
interactiveCanvas = container.querySelector("canvas.interactive")!;
});
const p1 = point<GlobalPoint>(20, 20);
const p2 = point<GlobalPoint>(60, 20);
const p1 = pointFrom<GlobalPoint>(20, 20);
const p2 = pointFrom<GlobalPoint>(60, 20);
const midpoint = pointCenter<GlobalPoint>(p1, p2);
const delta = 50;
const mouse = new Pointer("mouse");
@ -75,7 +75,7 @@ describe("Test Linear Elements", () => {
height: 0,
type,
roughness,
points: [point(0, 0), point(p2[0] - p1[0], p2[1] - p1[1])],
points: [pointFrom(0, 0), pointFrom(p2[0] - p1[0], p2[1] - p1[1])],
roundness,
});
API.setElements([line]);
@ -99,9 +99,9 @@ describe("Test Linear Elements", () => {
type,
roughness,
points: [
point(0, 0),
point(p3[0], p3[1]),
point(p2[0] - p1[0], p2[1] - p1[1]),
pointFrom(0, 0),
pointFrom(p3[0], p3[1]),
pointFrom(p2[0] - p1[0], p2[1] - p1[1]),
],
roundness,
});
@ -161,7 +161,7 @@ describe("Test Linear Elements", () => {
expect(line.points.length).toEqual(2);
mouse.clickAt(midpoint[0], midpoint[1]);
drag(midpoint, point(midpoint[0] + 1, midpoint[1] + 1));
drag(midpoint, pointFrom(midpoint[0] + 1, midpoint[1] + 1));
expect(line.points.length).toEqual(2);
@ -169,7 +169,7 @@ describe("Test Linear Elements", () => {
expect(line.y).toBe(originalY);
expect(line.points.length).toEqual(2);
drag(midpoint, point(midpoint[0] + delta, midpoint[1] + delta));
drag(midpoint, pointFrom(midpoint[0] + delta, midpoint[1] + delta));
expect(line.x).toBe(originalX);
expect(line.y).toBe(originalY);
expect(line.points.length).toEqual(3);
@ -184,7 +184,7 @@ describe("Test Linear Elements", () => {
expect((h.elements[0] as ExcalidrawLinearElement).points.length).toEqual(2);
// drag line from midpoint
drag(midpoint, point(midpoint[0] + delta, midpoint[1] + delta));
drag(midpoint, pointFrom(midpoint[0] + delta, midpoint[1] + delta));
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(`9`);
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`);
expect(line.points.length).toEqual(3);
@ -248,7 +248,7 @@ describe("Test Linear Elements", () => {
mouse.clickAt(midpoint[0], midpoint[1]);
expect(line.points.length).toEqual(2);
drag(midpoint, point(midpoint[0] + 1, midpoint[1] + 1));
drag(midpoint, pointFrom(midpoint[0] + 1, midpoint[1] + 1));
expect(line.x).toBe(originalX);
expect(line.y).toBe(originalY);
expect(line.points.length).toEqual(3);
@ -261,7 +261,7 @@ describe("Test Linear Elements", () => {
enterLineEditingMode(line);
// drag line from midpoint
drag(midpoint, point(midpoint[0] + delta, midpoint[1] + delta));
drag(midpoint, pointFrom(midpoint[0] + delta, midpoint[1] + delta));
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`12`,
);
@ -356,7 +356,7 @@ describe("Test Linear Elements", () => {
const startPoint = pointCenter(points[0], midPoints[0]!);
const deltaX = 50;
const deltaY = 20;
const endPoint = point<GlobalPoint>(
const endPoint = pointFrom<GlobalPoint>(
startPoint[0] + deltaX,
startPoint[1] + deltaY,
);
@ -399,8 +399,8 @@ describe("Test Linear Elements", () => {
// This is the expected midpoint for line with round edge
// hence hardcoding it so if later some bug is introduced
// this will fail and we can fix it
const firstSegmentMidpoint = point<GlobalPoint>(55, 45);
const lastSegmentMidpoint = point<GlobalPoint>(75, 40);
const firstSegmentMidpoint = pointFrom<GlobalPoint>(55, 45);
const lastSegmentMidpoint = pointFrom<GlobalPoint>(75, 40);
let line: ExcalidrawLinearElement;
@ -416,7 +416,7 @@ describe("Test Linear Elements", () => {
// drag line via first segment midpoint
drag(
firstSegmentMidpoint,
point(
pointFrom(
firstSegmentMidpoint[0] + delta,
firstSegmentMidpoint[1] + delta,
),
@ -426,7 +426,10 @@ describe("Test Linear Elements", () => {
// drag line from last segment midpoint
drag(
lastSegmentMidpoint,
point(lastSegmentMidpoint[0] + delta, lastSegmentMidpoint[1] + delta),
pointFrom(
lastSegmentMidpoint[0] + delta,
lastSegmentMidpoint[1] + delta,
),
);
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
@ -475,10 +478,10 @@ describe("Test Linear Elements", () => {
h.state,
);
const hitCoords = point<GlobalPoint>(points[0][0], points[0][1]);
const hitCoords = pointFrom<GlobalPoint>(points[0][0], points[0][1]);
// Drag from first point
drag(hitCoords, point(hitCoords[0] - delta, hitCoords[1] - delta));
drag(hitCoords, pointFrom(hitCoords[0] - delta, hitCoords[1] - delta));
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`12`,
@ -516,10 +519,10 @@ describe("Test Linear Elements", () => {
h.state,
);
const hitCoords = point<GlobalPoint>(points[0][0], points[0][1]);
const hitCoords = pointFrom<GlobalPoint>(points[0][0], points[0][1]);
// Drag from first point
drag(hitCoords, point(hitCoords[0] + delta, hitCoords[1] + delta));
drag(hitCoords, pointFrom(hitCoords[0] + delta, hitCoords[1] + delta));
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`12`,
@ -556,7 +559,7 @@ describe("Test Linear Elements", () => {
// dragging line from last segment midpoint
drag(
lastSegmentMidpoint,
point(lastSegmentMidpoint[0] + 50, lastSegmentMidpoint[1] + 50),
pointFrom(lastSegmentMidpoint[0] + 50, lastSegmentMidpoint[1] + 50),
);
expect(line.points.length).toEqual(4);
@ -589,11 +592,11 @@ describe("Test Linear Elements", () => {
// This is the expected midpoint for line with round edge
// hence hardcoding it so if later some bug is introduced
// this will fail and we can fix it
const firstSegmentMidpoint = point<GlobalPoint>(
const firstSegmentMidpoint = pointFrom<GlobalPoint>(
55.9697848965255,
47.442326230998205,
);
const lastSegmentMidpoint = point<GlobalPoint>(
const lastSegmentMidpoint = pointFrom<GlobalPoint>(
76.08587175006699,
43.294165939653226,
);
@ -612,7 +615,7 @@ describe("Test Linear Elements", () => {
// drag line from first segment midpoint
drag(
firstSegmentMidpoint,
point(
pointFrom(
firstSegmentMidpoint[0] + delta,
firstSegmentMidpoint[1] + delta,
),
@ -622,7 +625,10 @@ describe("Test Linear Elements", () => {
// drag line from last segment midpoint
drag(
lastSegmentMidpoint,
point(lastSegmentMidpoint[0] + delta, lastSegmentMidpoint[1] + delta),
pointFrom(
lastSegmentMidpoint[0] + delta,
lastSegmentMidpoint[1] + delta,
),
);
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`16`,
@ -669,10 +675,10 @@ describe("Test Linear Elements", () => {
h.state,
);
const hitCoords = point<GlobalPoint>(points[0][0], points[0][1]);
const hitCoords = pointFrom<GlobalPoint>(points[0][0], points[0][1]);
// Drag from first point
drag(hitCoords, point(hitCoords[0] - delta, hitCoords[1] - delta));
drag(hitCoords, pointFrom(hitCoords[0] - delta, hitCoords[1] - delta));
const newPoints = LinearElementEditor.getPointsGlobalCoordinates(
line,
@ -717,10 +723,10 @@ describe("Test Linear Elements", () => {
h.state,
);
const hitCoords = point<GlobalPoint>(points[0][0], points[0][1]);
const hitCoords = pointFrom<GlobalPoint>(points[0][0], points[0][1]);
// Drag from first point
drag(hitCoords, point(hitCoords[0] + delta, hitCoords[1] + delta));
drag(hitCoords, pointFrom(hitCoords[0] + delta, hitCoords[1] + delta));
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`12`,
@ -751,7 +757,10 @@ describe("Test Linear Elements", () => {
drag(
lastSegmentMidpoint,
point(lastSegmentMidpoint[0] + delta, lastSegmentMidpoint[1] + delta),
pointFrom(
lastSegmentMidpoint[0] + delta,
lastSegmentMidpoint[1] + delta,
),
);
expect(line.points.length).toEqual(4);
@ -811,8 +820,8 @@ describe("Test Linear Elements", () => {
API.setSelectedElements([line]);
enterLineEditingMode(line, true);
drag(
point(line.points[0][0] + line.x, line.points[0][1] + line.y),
point(
pointFrom(line.points[0][0] + line.x, line.points[0][1] + line.y),
pointFrom(
dragEndPositionOffset[0] + line.x,
dragEndPositionOffset[1] + line.y,
),
@ -927,14 +936,14 @@ describe("Test Linear Elements", () => {
// This is the expected midpoint for line with round edge
// hence hardcoding it so if later some bug is introduced
// this will fail and we can fix it
const firstSegmentMidpoint = point<GlobalPoint>(
const firstSegmentMidpoint = pointFrom<GlobalPoint>(
55.9697848965255,
47.442326230998205,
);
// drag line from first segment midpoint
drag(
firstSegmentMidpoint,
point(
pointFrom(
firstSegmentMidpoint[0] + delta,
firstSegmentMidpoint[1] + delta,
),
@ -1151,7 +1160,7 @@ describe("Test Linear Elements", () => {
);
// Drag from last point
drag(points[1], point(points[1][0] + 300, points[1][1]));
drag(points[1], pointFrom(points[1][0] + 300, points[1][1]));
expect({ width: container.width, height: container.height })
.toMatchInlineSnapshot(`
@ -1350,11 +1359,11 @@ describe("Test Linear Elements", () => {
[
{
index: 0,
point: point(line.points[0][0] + 10, line.points[0][1] + 10),
point: pointFrom(line.points[0][0] + 10, line.points[0][1] + 10),
},
{
index: line.points.length - 1,
point: point(
point: pointFrom(
line.points[line.points.length - 1][0] - 10,
line.points[line.points.length - 1][1] - 10,
),

@ -17,7 +17,7 @@ import { isLinearElement } from "../element/typeChecks";
import { LinearElementEditor } from "../element/linearElementEditor";
import { arrayToMap } from "../utils";
import type { LocalPoint } from "../../math";
import { point } from "../../math";
import { pointFrom } from "../../math";
ReactDOM.unmountComponentAtNode(document.getElementById("root")!);
@ -220,12 +220,17 @@ describe("generic element", () => {
describe.each(["line", "freedraw"] as const)("%s element", (type) => {
const points: Record<typeof type, LocalPoint[]> = {
line: [point(0, 0), point(60, -20), point(20, 40), point(-40, 0)],
line: [
pointFrom(0, 0),
pointFrom(60, -20),
pointFrom(20, 40),
pointFrom(-40, 0),
],
freedraw: [
point(0, 0),
point(-2.474600807561444, 41.021700699972),
point(3.6627956000014024, 47.84174560617245),
point(40.495224145598115, 47.15909710753482),
pointFrom(0, 0),
pointFrom(-2.474600807561444, 41.021700699972),
pointFrom(3.6627956000014024, 47.84174560617245),
pointFrom(40.495224145598115, 47.15909710753482),
],
};
@ -293,11 +298,11 @@ describe("arrow element", () => {
it("resizes with a label", async () => {
const arrow = UI.createElement("arrow", {
points: [
point(0, 0),
point(40, 140),
point(80, 60), // label's anchor
point(180, 20),
point(200, 120),
pointFrom(0, 0),
pointFrom(40, 140),
pointFrom(80, 60), // label's anchor
pointFrom(180, 20),
pointFrom(200, 120),
],
});
const label = await UI.editText(arrow, "Hello");
@ -747,24 +752,24 @@ describe("multiple selection", () => {
x: 60,
y: 40,
points: [
point(0, 0),
point(-40, 40),
point(-60, 0),
point(0, -40),
point(40, 20),
point(0, 40),
pointFrom(0, 0),
pointFrom(-40, 40),
pointFrom(-60, 0),
pointFrom(0, -40),
pointFrom(40, 20),
pointFrom(0, 40),
],
});
const freedraw = UI.createElement("freedraw", {
x: 63.56072661326618,
y: 100,
points: [
point(0, 0),
point(-43.56072661326618, 18.15048126846341),
point(-43.56072661326618, 29.041198460587566),
point(-38.115368017204105, 42.652452795512204),
point(-19.964886748740696, 66.24829266003775),
point(19.056612930986716, 77.1390098521619),
pointFrom(0, 0),
pointFrom(-43.56072661326618, 18.15048126846341),
pointFrom(-43.56072661326618, 29.041198460587566),
pointFrom(-38.115368017204105, 42.652452795512204),
pointFrom(-19.964886748740696, 66.24829266003775),
pointFrom(19.056612930986716, 77.1390098521619),
],
});
@ -1101,13 +1106,13 @@ describe("multiple selection", () => {
x: 60,
y: 0,
points: [
point(0, 0),
point(-40, 40),
point(-20, 60),
point(20, 20),
point(40, 40),
point(-20, 100),
point(-60, 60),
pointFrom(0, 0),
pointFrom(-40, 40),
pointFrom(-20, 60),
pointFrom(20, 20),
pointFrom(40, 40),
pointFrom(-20, 100),
pointFrom(-60, 60),
],
});

@ -1,5 +1,5 @@
import type { Segment } from "../math";
import { isSegment, segment, point, type GlobalPoint } from "../math";
import { isSegment, segment, pointFrom, type GlobalPoint } from "../math";
import { isBounds } from "./element/typeChecks";
import type { Bounds } from "./element/types";
@ -52,8 +52,8 @@ export const debugDrawPoint = (
debugDrawLine(
segment(
point<GlobalPoint>(p[0] + xOffset - 10, p[1] + yOffset - 10),
point<GlobalPoint>(p[0] + xOffset + 10, p[1] + yOffset + 10),
pointFrom<GlobalPoint>(p[0] + xOffset - 10, p[1] + yOffset - 10),
pointFrom<GlobalPoint>(p[0] + xOffset + 10, p[1] + yOffset + 10),
),
{
color: opts?.color ?? "cyan",
@ -62,8 +62,8 @@ export const debugDrawPoint = (
);
debugDrawLine(
segment(
point<GlobalPoint>(p[0] + xOffset - 10, p[1] + yOffset + 10),
point<GlobalPoint>(p[0] + xOffset + 10, p[1] + yOffset - 10),
pointFrom<GlobalPoint>(p[0] + xOffset - 10, p[1] + yOffset + 10),
pointFrom<GlobalPoint>(p[0] + xOffset + 10, p[1] + yOffset - 10),
),
{
color: opts?.color ?? "cyan",
@ -83,20 +83,20 @@ export const debugDrawBounds = (
debugDrawLine(
[
segment(
point<GlobalPoint>(bbox[0], bbox[1]),
point<GlobalPoint>(bbox[2], bbox[1]),
pointFrom<GlobalPoint>(bbox[0], bbox[1]),
pointFrom<GlobalPoint>(bbox[2], bbox[1]),
),
segment(
point<GlobalPoint>(bbox[2], bbox[1]),
point<GlobalPoint>(bbox[2], bbox[3]),
pointFrom<GlobalPoint>(bbox[2], bbox[1]),
pointFrom<GlobalPoint>(bbox[2], bbox[3]),
),
segment(
point<GlobalPoint>(bbox[2], bbox[3]),
point<GlobalPoint>(bbox[0], bbox[3]),
pointFrom<GlobalPoint>(bbox[2], bbox[3]),
pointFrom<GlobalPoint>(bbox[0], bbox[3]),
),
segment(
point<GlobalPoint>(bbox[0], bbox[3]),
point<GlobalPoint>(bbox[0], bbox[1]),
pointFrom<GlobalPoint>(bbox[0], bbox[3]),
pointFrom<GlobalPoint>(bbox[0], bbox[1]),
),
],
{

@ -6,31 +6,31 @@ import {
arcSegmentInterceptPoints,
} from "./arc";
import { line } from "./line";
import { point } from "./point";
import { pointFrom } from "./point";
import { segment } from "./segment";
describe("point on arc", () => {
it("should detect point on simple arc", () => {
expect(
arcIncludesPoint(
arc(point(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
point(0.92291667, 0.385),
arc(pointFrom(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
pointFrom(0.92291667, 0.385),
),
).toBe(true);
});
it("should not detect point outside of a simple arc", () => {
expect(
arcIncludesPoint(
arc(point(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
point(-0.92291667, 0.385),
arc(pointFrom(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
pointFrom(-0.92291667, 0.385),
),
).toBe(false);
});
it("should not detect point with good angle but incorrect radius", () => {
expect(
arcIncludesPoint(
arc(point(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
point(-0.5, 0.5),
arc(pointFrom(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
pointFrom(-0.5, 0.5),
),
).toBe(false);
});
@ -40,42 +40,42 @@ describe("intersection", () => {
it("should report correct interception point for segment", () => {
expect(
arcSegmentInterceptPoints(
arc(point(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
segment(point(2, 1), point(0, 0)),
arc(pointFrom(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
segment(pointFrom(2, 1), pointFrom(0, 0)),
),
).toEqual([point(0.894427190999916, 0.447213595499958)]);
).toEqual([pointFrom(0.894427190999916, 0.447213595499958)]);
});
it("should report both interception points when present for segment", () => {
expect(
arcSegmentInterceptPoints(
arc(point(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
segment(point(0.9, -2), point(0.9, 2)),
arc(pointFrom(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
segment(pointFrom(0.9, -2), pointFrom(0.9, 2)),
),
).toEqual([
point(0.9, -0.4358898943540668),
point(0.9, 0.4358898943540668),
pointFrom(0.9, -0.4358898943540668),
pointFrom(0.9, 0.4358898943540668),
]);
});
it("should report correct interception point for line", () => {
expect(
arcLineInterceptPoints(
arc(point(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
line(point(2, 1), point(0, 0)),
arc(pointFrom(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
line(pointFrom(2, 1), pointFrom(0, 0)),
),
).toEqual([point(0.894427190999916, 0.447213595499958)]);
).toEqual([pointFrom(0.894427190999916, 0.447213595499958)]);
});
it("should report both interception points when present for line", () => {
expect(
arcLineInterceptPoints(
arc(point(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
line(point(0.9, -2), point(0.9, 2)),
arc(pointFrom(0, 0), 1, radians(-Math.PI / 4), radians(Math.PI / 4)),
line(pointFrom(0.9, -2), pointFrom(0.9, 2)),
),
).toEqual([
point(0.9, 0.4358898943540668),
point(0.9, -0.4358898943540668),
pointFrom(0.9, 0.4358898943540668),
pointFrom(0.9, -0.4358898943540668),
]);
});
});

@ -1,4 +1,4 @@
import { point, pointRotateRads } from "./point";
import { pointFrom, pointRotateRads } from "./point";
import type { Curve, GenericPoint, Radians } from "./types";
/**
@ -43,10 +43,10 @@ export function curveToBezier<Point extends GenericPoint>(
const out: Point[] = [];
if (len === 3) {
out.push(
point(pointsIn[0][0], pointsIn[0][1]), // Points need to be cloned
point(pointsIn[1][0], pointsIn[1][1]), // Points need to be cloned
point(pointsIn[2][0], pointsIn[2][1]), // Points need to be cloned
point(pointsIn[2][0], pointsIn[2][1]), // Points need to be cloned
pointFrom(pointsIn[0][0], pointsIn[0][1]), // Points need to be cloned
pointFrom(pointsIn[1][0], pointsIn[1][1]), // Points need to be cloned
pointFrom(pointsIn[2][0], pointsIn[2][1]), // Points need to be cloned
pointFrom(pointsIn[2][0], pointsIn[2][1]), // Points need to be cloned
);
} else {
const points: Point[] = [];
@ -59,19 +59,19 @@ export function curveToBezier<Point extends GenericPoint>(
}
const b: Point[] = [];
const s = 1 - curveTightness;
out.push(point(points[0][0], points[0][1]));
out.push(pointFrom(points[0][0], points[0][1]));
for (let i = 1; i + 2 < points.length; i++) {
const cachedVertArray = points[i];
b[0] = point(cachedVertArray[0], cachedVertArray[1]);
b[1] = point(
b[0] = pointFrom(cachedVertArray[0], cachedVertArray[1]);
b[1] = pointFrom(
cachedVertArray[0] + (s * points[i + 1][0] - s * points[i - 1][0]) / 6,
cachedVertArray[1] + (s * points[i + 1][1] - s * points[i - 1][1]) / 6,
);
b[2] = point(
b[2] = pointFrom(
points[i + 1][0] + (s * points[i][0] - s * points[i + 2][0]) / 6,
points[i + 1][1] + (s * points[i][1] - s * points[i + 2][1]) / 6,
);
b[3] = point(points[i + 1][0], points[i + 1][1]);
b[3] = pointFrom(points[i + 1][0], points[i + 1][1]);
out.push(b[1], b[2], b[3]);
}
}
@ -102,7 +102,7 @@ export const cubicBezierPoint = <Point extends GenericPoint>(
3 * (1 - t) * Math.pow(t, 2) * p2[1] +
Math.pow(t, 3) * p3[1];
return point(x, y);
return pointFrom(x, y);
};
/**

@ -1,4 +1,4 @@
import { point, pointRotateRads } from "./point";
import { pointFrom, pointRotateRads } from "./point";
import type { Radians } from "./types";
describe("rotate", () => {
@ -9,14 +9,14 @@ describe("rotate", () => {
const y2 = 30;
const angle = (Math.PI / 2) as Radians;
const [rotatedX, rotatedY] = pointRotateRads(
point(x1, y1),
point(x2, y2),
pointFrom(x1, y1),
pointFrom(x2, y2),
angle,
);
expect([rotatedX, rotatedY]).toEqual([30, 20]);
const res2 = pointRotateRads(
point(rotatedX, rotatedY),
point(x2, y2),
pointFrom(rotatedX, rotatedY),
pointFrom(x2, y2),
-angle as Radians,
);
expect(res2).toEqual([x1, x2]);

@ -10,7 +10,10 @@ import { vectorFromPoint, vectorScale } from "./vector";
* @param y The Y coordinate
* @returns The branded and created point
*/
export function point<Point extends GenericPoint>(x: number, y: number): Point {
export function pointFrom<Point extends GenericPoint>(
x: number,
y: number,
): Point {
return [x, y] as Point;
}
@ -24,7 +27,7 @@ export function pointFromArray<Point extends GenericPoint>(
numberArray: number[],
): Point | undefined {
return numberArray.length === 2
? point<Point>(numberArray[0], numberArray[1])
? pointFrom<Point>(numberArray[0], numberArray[1])
: undefined;
}
@ -48,9 +51,9 @@ export function pointFromPair<Point extends GenericPoint>(
*/
export function pointFromVector<P extends GenericPoint>(
v: Vector,
offset: P = point(0, 0),
offset: P = pointFrom(0, 0),
): P {
return point<P>(offset[0] + v[0], offset[1] + v[1]);
return pointFrom<P>(offset[0] + v[0], offset[1] + v[1]);
}
/**
@ -102,7 +105,7 @@ export function pointRotateRads<Point extends GenericPoint>(
const cos = Math.cos(angle);
const sin = Math.sin(angle);
return point(
return pointFrom(
(x - cx) * cos - (y - cy) * sin + cx,
(x - cx) * sin + (y - cy) * cos + cy,
);
@ -141,7 +144,7 @@ export function pointTranslate<
From extends GenericPoint,
To extends GenericPoint,
>(p: From, v: Vector = [0, 0] as Vector): To {
return point(p[0] + v[0], p[1] + v[1]);
return pointFrom(p[0] + v[0], p[1] + v[1]);
}
/**
@ -171,7 +174,7 @@ export function pointAdd<Point extends GenericPoint>(
a: Point,
b: Point,
): Point {
return point(a[0] + b[0], a[1] + b[1]);
return pointFrom(a[0] + b[0], a[1] + b[1]);
}
/**
@ -186,7 +189,7 @@ export function pointSubtract<Point extends GenericPoint>(
a: Point,
b: Point,
): Point {
return point(a[0] - b[0], a[1] - b[1]);
return pointFrom(a[0] - b[0], a[1] - b[1]);
}
/**

@ -4,7 +4,7 @@ import {
degreesToRadians,
segment,
segmentRotate,
point,
pointFrom,
pointRotateDegs,
} from "../math";
import { pointOnCurve, pointOnPolyline } from "./collision";
@ -12,21 +12,21 @@ import type { Polyline } from "./geometry/shape";
describe("point and curve", () => {
const c: Curve<GlobalPoint> = curve(
point(1.4, 1.65),
point(1.9, 7.9),
point(5.9, 1.65),
point(6.44, 4.84),
pointFrom(1.4, 1.65),
pointFrom(1.9, 7.9),
pointFrom(5.9, 1.65),
pointFrom(6.44, 4.84),
);
it("point on curve", () => {
expect(pointOnCurve(c[0], c, 10e-5)).toBe(true);
expect(pointOnCurve(c[3], c, 10e-5)).toBe(true);
expect(pointOnCurve(point(2, 4), c, 0.1)).toBe(true);
expect(pointOnCurve(point(4, 4.4), c, 0.1)).toBe(true);
expect(pointOnCurve(point(5.6, 3.85), c, 0.1)).toBe(true);
expect(pointOnCurve(pointFrom(2, 4), c, 0.1)).toBe(true);
expect(pointOnCurve(pointFrom(4, 4.4), c, 0.1)).toBe(true);
expect(pointOnCurve(pointFrom(5.6, 3.85), c, 0.1)).toBe(true);
expect(pointOnCurve(point(5.6, 4), c, 0.1)).toBe(false);
expect(pointOnCurve(pointFrom(5.6, 4), c, 0.1)).toBe(false);
expect(pointOnCurve(c[1], c, 0.1)).toBe(false);
expect(pointOnCurve(c[2], c, 0.1)).toBe(false);
});
@ -34,52 +34,52 @@ describe("point and curve", () => {
describe("point and polylines", () => {
const polyline: Polyline<GlobalPoint> = [
segment(point(1, 0), point(1, 2)),
segment(point(1, 2), point(2, 2)),
segment(point(2, 2), point(2, 1)),
segment(point(2, 1), point(3, 1)),
segment(pointFrom(1, 0), pointFrom(1, 2)),
segment(pointFrom(1, 2), pointFrom(2, 2)),
segment(pointFrom(2, 2), pointFrom(2, 1)),
segment(pointFrom(2, 1), pointFrom(3, 1)),
];
it("point on the line", () => {
expect(pointOnPolyline(point(1, 0), polyline)).toBe(true);
expect(pointOnPolyline(point(1, 2), polyline)).toBe(true);
expect(pointOnPolyline(point(2, 2), polyline)).toBe(true);
expect(pointOnPolyline(point(2, 1), polyline)).toBe(true);
expect(pointOnPolyline(point(3, 1), polyline)).toBe(true);
expect(pointOnPolyline(pointFrom(1, 0), polyline)).toBe(true);
expect(pointOnPolyline(pointFrom(1, 2), polyline)).toBe(true);
expect(pointOnPolyline(pointFrom(2, 2), polyline)).toBe(true);
expect(pointOnPolyline(pointFrom(2, 1), polyline)).toBe(true);
expect(pointOnPolyline(pointFrom(3, 1), polyline)).toBe(true);
expect(pointOnPolyline(point(1, 1), polyline)).toBe(true);
expect(pointOnPolyline(point(2, 1.5), polyline)).toBe(true);
expect(pointOnPolyline(point(2.5, 1), polyline)).toBe(true);
expect(pointOnPolyline(pointFrom(1, 1), polyline)).toBe(true);
expect(pointOnPolyline(pointFrom(2, 1.5), polyline)).toBe(true);
expect(pointOnPolyline(pointFrom(2.5, 1), polyline)).toBe(true);
expect(pointOnPolyline(point(0, 1), polyline)).toBe(false);
expect(pointOnPolyline(point(2.1, 1.5), polyline)).toBe(false);
expect(pointOnPolyline(pointFrom(0, 1), polyline)).toBe(false);
expect(pointOnPolyline(pointFrom(2.1, 1.5), polyline)).toBe(false);
});
it("point on the line with rotation", () => {
const truePoints = [
point(1, 0),
point(1, 2),
point(2, 2),
point(2, 1),
point(3, 1),
pointFrom(1, 0),
pointFrom(1, 2),
pointFrom(2, 2),
pointFrom(2, 1),
pointFrom(3, 1),
];
truePoints.forEach((p) => {
const rotation = (Math.random() * 360) as Degrees;
const rotatedPoint = pointRotateDegs(p, point(0, 0), rotation);
const rotatedPoint = pointRotateDegs(p, pointFrom(0, 0), rotation);
const rotatedPolyline = polyline.map((line) =>
segmentRotate(line, degreesToRadians(rotation), point(0, 0)),
segmentRotate(line, degreesToRadians(rotation), pointFrom(0, 0)),
);
expect(pointOnPolyline(rotatedPoint, rotatedPolyline)).toBe(true);
});
const falsePoints = [point(0, 1), point(2.1, 1.5)];
const falsePoints = [pointFrom(0, 1), pointFrom(2.1, 1.5)];
falsePoints.forEach((p) => {
const rotation = (Math.random() * 360) as Degrees;
const rotatedPoint = pointRotateDegs(p, point(0, 0), rotation);
const rotatedPoint = pointRotateDegs(p, pointFrom(0, 0), rotation);
const rotatedPolyline = polyline.map((line) =>
segmentRotate(line, degreesToRadians(rotation), point(0, 0)),
segmentRotate(line, degreesToRadians(rotation), pointFrom(0, 0)),
);
expect(pointOnPolyline(rotatedPoint, rotatedPolyline)).toBe(false);
});

@ -3,7 +3,7 @@ import { type GeometricShape } from "./geometry/shape";
import type { Curve, GenericPoint } from "../math";
import {
segment,
point,
pointFrom,
polygonIncludesPoint,
segmentIncludesPoint,
pointOnPolygon,
@ -95,7 +95,7 @@ const polyLineFromCurve = <Point extends GenericPoint>(
for (let i = 0; i < segments; i++) {
t += increment;
if (t <= 1) {
const nextPoint: Point = point(equation(t, 0), equation(t, 1));
const nextPoint: Point = pointFrom(equation(t, 0), equation(t, 1));
lineSegments.push(segment(startingPoint, nextPoint));
startingPoint = nextPoint;
}

@ -1,6 +1,6 @@
import type { GlobalPoint, Segment, Polygon } from "../../math";
import {
point,
pointFrom,
segment,
polygon,
segmentIncludesPoint,
@ -9,40 +9,40 @@ import {
} from "../../math";
describe("point and line", () => {
const s: Segment<GlobalPoint> = segment(point(1, 0), point(1, 2));
const s: Segment<GlobalPoint> = segment(pointFrom(1, 0), pointFrom(1, 2));
it("point on the line", () => {
expect(segmentIncludesPoint(point(0, 1), s)).toBe(false);
expect(segmentIncludesPoint(point(1, 1), s, 0)).toBe(true);
expect(segmentIncludesPoint(point(2, 1), s)).toBe(false);
expect(segmentIncludesPoint(pointFrom(0, 1), s)).toBe(false);
expect(segmentIncludesPoint(pointFrom(1, 1), s, 0)).toBe(true);
expect(segmentIncludesPoint(pointFrom(2, 1), s)).toBe(false);
});
});
describe("point and polygon", () => {
const poly: Polygon<GlobalPoint> = polygon(
point(10, 10),
point(50, 10),
point(50, 50),
point(10, 50),
pointFrom(10, 10),
pointFrom(50, 10),
pointFrom(50, 50),
pointFrom(10, 50),
);
it("point on polygon", () => {
expect(pointOnPolygon(point(30, 10), poly)).toBe(true);
expect(pointOnPolygon(point(50, 30), poly)).toBe(true);
expect(pointOnPolygon(point(30, 50), poly)).toBe(true);
expect(pointOnPolygon(point(10, 30), poly)).toBe(true);
expect(pointOnPolygon(point(30, 30), poly)).toBe(false);
expect(pointOnPolygon(point(30, 70), poly)).toBe(false);
expect(pointOnPolygon(pointFrom(30, 10), poly)).toBe(true);
expect(pointOnPolygon(pointFrom(50, 30), poly)).toBe(true);
expect(pointOnPolygon(pointFrom(30, 50), poly)).toBe(true);
expect(pointOnPolygon(pointFrom(10, 30), poly)).toBe(true);
expect(pointOnPolygon(pointFrom(30, 30), poly)).toBe(false);
expect(pointOnPolygon(pointFrom(30, 70), poly)).toBe(false);
});
it("point in polygon", () => {
const poly: Polygon<GlobalPoint> = polygon(
point(0, 0),
point(2, 0),
point(2, 2),
point(0, 2),
pointFrom(0, 0),
pointFrom(2, 0),
pointFrom(2, 2),
pointFrom(0, 2),
);
expect(polygonIncludesPoint(point(1, 1), poly)).toBe(true);
expect(polygonIncludesPoint(point(3, 3), poly)).toBe(false);
expect(polygonIncludesPoint(pointFrom(1, 1), poly)).toBe(true);
expect(polygonIncludesPoint(pointFrom(3, 3), poly)).toBe(false);
});
});

@ -25,7 +25,7 @@ import {
curve,
ellipse,
segment,
point,
pointFrom,
pointFromArray,
pointFromVector,
pointRotateRads,
@ -115,23 +115,23 @@ export const getPolygonShape = <Point extends GlobalPoint | LocalPoint>(
const cx = x + width / 2;
const cy = y + height / 2;
const center: Point = point(cx, cy);
const center: Point = pointFrom(cx, cy);
let data: Polygon<Point>;
if (element.type === "diamond") {
data = polygon(
pointRotateRads(point(cx, y), center, angle),
pointRotateRads(point(x + width, cy), center, angle),
pointRotateRads(point(cx, y + height), center, angle),
pointRotateRads(point(x, cy), center, angle),
pointRotateRads(pointFrom(cx, y), center, angle),
pointRotateRads(pointFrom(x + width, cy), center, angle),
pointRotateRads(pointFrom(cx, y + height), center, angle),
pointRotateRads(pointFrom(x, cy), center, angle),
);
} else {
data = polygon(
pointRotateRads(point(x, y), center, angle),
pointRotateRads(point(x + width, y), center, angle),
pointRotateRads(point(x + width, y + height), center, angle),
pointRotateRads(point(x, y + height), center, angle),
pointRotateRads(pointFrom(x, y), center, angle),
pointRotateRads(pointFrom(x + width, y), center, angle),
pointRotateRads(pointFrom(x + width, y + height), center, angle),
pointRotateRads(pointFrom(x, y + height), center, angle),
);
}
@ -159,11 +159,11 @@ export const getSelectionBoxShape = <Point extends GlobalPoint | LocalPoint>(
y2 += padding;
//const angleInDegrees = angleToDegrees(element.angle);
const center = point(cx, cy);
const topLeft = pointRotateRads(point(x1, y1), center, element.angle);
const topRight = pointRotateRads(point(x2, y1), center, element.angle);
const bottomLeft = pointRotateRads(point(x1, y2), center, element.angle);
const bottomRight = pointRotateRads(point(x2, y2), center, element.angle);
const center = pointFrom(cx, cy);
const topLeft = pointRotateRads(pointFrom(x1, y1), center, element.angle);
const topRight = pointRotateRads(pointFrom(x2, y1), center, element.angle);
const bottomLeft = pointRotateRads(pointFrom(x1, y2), center, element.angle);
const bottomRight = pointRotateRads(pointFrom(x2, y2), center, element.angle);
return {
type: "polygon",
@ -179,7 +179,11 @@ export const getEllipseShape = <Point extends GlobalPoint | LocalPoint>(
return {
type: "ellipse",
data: ellipse(point(x + width / 2, y + height / 2), width / 2, height / 2),
data: ellipse(
pointFrom(x + width / 2, y + height / 2),
width / 2,
height / 2,
),
};
};
@ -195,20 +199,20 @@ export const getCurvePathOps = (shape: Drawable): Op[] => {
// linear
export const getCurveShape = <Point extends GlobalPoint | LocalPoint>(
roughShape: Drawable,
startingPoint: Point = point(0, 0),
startingPoint: Point = pointFrom(0, 0),
angleInRadian: Radians,
center: Point,
): GeometricShape<Point> => {
const transform = (p: Point): Point =>
pointRotateRads(
point(p[0] + startingPoint[0], p[1] + startingPoint[1]),
pointFrom(p[0] + startingPoint[0], p[1] + startingPoint[1]),
center,
angleInRadian,
);
const ops = getCurvePathOps(roughShape);
const polycurve: Polycurve<Point> = [];
let p0 = point<Point>(0, 0);
let p0 = pointFrom<Point>(0, 0);
for (const op of ops) {
if (op.op === "move") {
@ -217,9 +221,9 @@ export const getCurveShape = <Point extends GlobalPoint | LocalPoint>(
p0 = transform(p);
}
if (op.op === "bcurveTo") {
const p1 = transform(point<Point>(op.data[0], op.data[1]));
const p2 = transform(point<Point>(op.data[2], op.data[3]));
const p3 = transform(point<Point>(op.data[4], op.data[5]));
const p1 = transform(pointFrom<Point>(op.data[0], op.data[1]));
const p2 = transform(pointFrom<Point>(op.data[2], op.data[3]));
const p3 = transform(pointFrom<Point>(op.data[4], op.data[5]));
polycurve.push(curve<Point>(p0, p1, p2, p3));
p0 = p3;
}
@ -280,13 +284,13 @@ export const getFreedrawShape = (
export const getClosedCurveShape = <Point extends GlobalPoint | LocalPoint>(
element: ExcalidrawLinearElement,
roughShape: Drawable,
startingPoint: Point = point<Point>(0, 0),
startingPoint: Point = pointFrom<Point>(0, 0),
angleInRadian: Radians,
center: Point,
): GeometricShape<Point> => {
const transform = (p: Point) =>
pointRotateRads(
point(p[0] + startingPoint[0], p[1] + startingPoint[1]),
pointFrom(p[0] + startingPoint[0], p[1] + startingPoint[1]),
center,
angleInRadian,
);
@ -308,17 +312,17 @@ export const getClosedCurveShape = <Point extends GlobalPoint | LocalPoint>(
if (operation.op === "move") {
odd = !odd;
if (odd) {
points.push(point(operation.data[0], operation.data[1]));
points.push(pointFrom(operation.data[0], operation.data[1]));
}
} else if (operation.op === "bcurveTo") {
if (odd) {
points.push(point(operation.data[0], operation.data[1]));
points.push(point(operation.data[2], operation.data[3]));
points.push(point(operation.data[4], operation.data[5]));
points.push(pointFrom(operation.data[0], operation.data[1]));
points.push(pointFrom(operation.data[2], operation.data[3]));
points.push(pointFrom(operation.data[4], operation.data[5]));
}
} else if (operation.op === "lineTo") {
if (odd) {
points.push(point(operation.data[0], operation.data[1]));
points.push(pointFrom(operation.data[0], operation.data[1]));
}
}
}
@ -356,27 +360,27 @@ export const segmentIntersectRectangleElement = <
element.x + element.width + gap,
element.y + element.height + gap,
];
const center = point(
const center = pointFrom(
(bounds[0] + bounds[2]) / 2,
(bounds[1] + bounds[3]) / 2,
);
return [
segment(
pointRotateRads(point(bounds[0], bounds[1]), center, element.angle),
pointRotateRads(point(bounds[2], bounds[1]), center, element.angle),
pointRotateRads(pointFrom(bounds[0], bounds[1]), center, element.angle),
pointRotateRads(pointFrom(bounds[2], bounds[1]), center, element.angle),
),
segment(
pointRotateRads(point(bounds[2], bounds[1]), center, element.angle),
pointRotateRads(point(bounds[2], bounds[3]), center, element.angle),
pointRotateRads(pointFrom(bounds[2], bounds[1]), center, element.angle),
pointRotateRads(pointFrom(bounds[2], bounds[3]), center, element.angle),
),
segment(
pointRotateRads(point(bounds[2], bounds[3]), center, element.angle),
pointRotateRads(point(bounds[0], bounds[3]), center, element.angle),
pointRotateRads(pointFrom(bounds[2], bounds[3]), center, element.angle),
pointRotateRads(pointFrom(bounds[0], bounds[3]), center, element.angle),
),
segment(
pointRotateRads(point(bounds[0], bounds[3]), center, element.angle),
pointRotateRads(point(bounds[0], bounds[1]), center, element.angle),
pointRotateRads(pointFrom(bounds[0], bounds[3]), center, element.angle),
pointRotateRads(pointFrom(bounds[0], bounds[1]), center, element.angle),
),
]
.map((l) => segmentsIntersectAt(s, l))

@ -17,7 +17,7 @@ import { arrayToMap } from "../excalidraw/utils";
import type { LocalPoint } from "../math";
import {
rangeIncludesValue,
point,
pointFrom,
pointRotateRads,
rangeInclusive,
} from "../math";
@ -36,17 +36,17 @@ const getNonLinearElementRelativePoints = (
] => {
if (element.type === "diamond") {
return [
point(element.width / 2, 0),
point(element.width, element.height / 2),
point(element.width / 2, element.height),
point(0, element.height / 2),
pointFrom(element.width / 2, 0),
pointFrom(element.width, element.height / 2),
pointFrom(element.width / 2, element.height),
pointFrom(0, element.height / 2),
];
}
return [
point(0, 0),
point(0 + element.width, 0),
point(0 + element.width, element.height),
point(0, element.height),
pointFrom(0, 0),
pointFrom(0 + element.width, 0),
pointFrom(0 + element.width, element.height),
pointFrom(0, element.height),
];
};
@ -91,7 +91,7 @@ const getRotatedBBox = (element: NonDeletedExcalidrawElement): Bounds => {
const points = getElementRelativePoints(element);
const { cx, cy } = getMinMaxPoints(points);
const centerPoint = point<LocalPoint>(cx, cy);
const centerPoint = pointFrom<LocalPoint>(cx, cy);
const rotatedPoints = points.map((p) =>
pointRotateRads(p, centerPoint, element.angle),

Loading…
Cancel
Save