Binding distance fix

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
Mark Tolmacs 2024-07-23 19:49:49 +02:00
parent 2d72ef421d
commit f5908dad18
No known key found for this signature in database
3 changed files with 81 additions and 21 deletions

View File

@ -48,12 +48,20 @@ import { KEYS } from "../keys";
import { getBoundTextElement, handleBindTextResize } from "./textElement";
import { getElementShape } from "../shapes";
import { headingForPointFromElement } from "./routing";
import type { Heading } from "../math";
import {
aabbForElement,
compareHeading,
HEADING_DOWN,
HEADING_LEFT,
HEADING_RIGHT,
HEADING_UP,
pointInsideBounds,
pointToVector,
rotatePoint,
scaleVector,
translatePoint,
vectorToHeading,
} from "../math";
export type SuggestedBinding =
@ -671,18 +679,53 @@ const getSimultaneouslyUpdatedElementIds = (
export const bindPointToSnapToElementOutline = (
point: Point,
otherPoint: Point,
bindableElement: ExcalidrawBindableElement,
elementsMap: ElementsMap,
): Point => {
const heading = headingForPointFromElement(
const distance = distanceToBindableElement(
bindableElement,
aabbForElement(bindableElement),
point,
elementsMap,
);
const distance =
distanceToBindableElement(bindableElement, point, elementsMap) -
const bindDistance = maxBindingGap(
bindableElement,
bindableElement.width,
bindableElement.height,
);
if (distance > bindDistance) {
return point;
}
const aabb = aabbForElement(bindableElement);
const pointHeading = headingForPointFromElement(bindableElement, aabb, point);
const otherPointHeading = scaleVector(
vectorToHeading(pointToVector(point, otherPoint)),
-1,
) as Heading;
const isInner =
otherPointHeading === HEADING_LEFT || otherPointHeading === HEADING_RIGHT
? distance < bindableElement.width * -0.2
: distance < bindableElement.height * -0.2;
const heading = isInner ? otherPointHeading : pointHeading;
const pointOnAABB: Point = compareHeading(heading, HEADING_UP)
? [point[0], aabb[1]]
: compareHeading(heading, HEADING_RIGHT)
? [aabb[2], point[1]]
: compareHeading(heading, HEADING_DOWN)
? [point[0], aabb[3]]
: [aabb[0], point[1]];
const distanceFromAABB =
distanceToBindableElement(bindableElement, pointOnAABB, elementsMap) -
FIXED_BINDING_DISTANCE;
return translatePoint(point, scaleVector(heading, -distance));
const result = translatePoint(
pointOnAABB,
scaleVector(heading, -distanceFromAABB),
);
return result;
};
export const avoidRectangularCorner = (
@ -880,6 +923,8 @@ const calculateFixedPointForElbowArrowBinding = (
] as Bounds;
const edgePointIndex =
startOrEnd === "start" ? 0 : linearElement.points.length - 1;
const otherPointIndex =
startOrEnd === "end" ? 0 : linearElement.points.length - 1;
const globalPoint = LinearElementEditor.getPointAtIndexGlobalCoordinates(
linearElement,
edgePointIndex,
@ -893,9 +938,15 @@ const calculateFixedPointForElbowArrowBinding = (
globalPoint,
globalMidPoint,
-hoveredElement.angle,
) as Point;
const otherPoint = LinearElementEditor.getPointAtIndexGlobalCoordinates(
linearElement,
otherPointIndex,
elementsMap,
);
const snappedPoint = bindPointToSnapToElementOutline(
[nonRotatedGlobalPoint[0], nonRotatedGlobalPoint[1]],
nonRotatedGlobalPoint,
otherPoint,
hoveredElement,
elementsMap,
);

View File

@ -24,7 +24,6 @@ import { getSizeFromPoints } from "../points";
import type Scene from "../scene/Scene";
import type { Point } from "../types";
import { toBrandedType, tupleToCoors } from "../utils";
import { debugDrawBounds } from "../visualdebug";
import {
bindPointToSnapToElementOutline,
distanceToBindableElement,
@ -119,15 +118,19 @@ export const mutateElbowArrow = (
const startGlobalPoint = getGlobalPoint(
origStartGlobalPoint,
origEndGlobalPoint,
elementsMap,
startElement,
hoveredStartElement,
options?.isDragging,
);
const endGlobalPoint = getGlobalPoint(
origEndGlobalPoint,
origStartGlobalPoint,
elementsMap,
endElement,
hoveredEndElement,
options?.isDragging,
);
const startHeading = getBindPointHeading(
@ -244,11 +247,11 @@ export const mutateElbowArrow = (
endHeading,
commonBounds,
);
console.log(boundsOverlap);
dynamicAABBs.forEach((bbox) => debugDrawBounds(bbox));
[startElementBounds, endElementBounds]
.filter((aabb) => aabb !== null)
.forEach((bbox) => debugDrawBounds(bbox, "red"));
// dynamicAABBs.forEach((bbox) => debugDrawBounds(bbox));
// [startElementBounds, endElementBounds]
// .filter((aabb) => aabb !== null)
// .forEach((bbox) => debugDrawBounds(bbox, "red"));
// debugDrawBounds(commonBounds, "cyan");
// grid.data.forEach((node) => node && debugDrawPoint(node.pos));
@ -1116,15 +1119,15 @@ export const getArrowLocalFixedPoints = (
];
};
const aabbsOverlapping = (a: Bounds, b: Bounds) =>
pointInsideBounds([a[0], a[1]], b) ||
pointInsideBounds([a[2], a[1]], b) ||
pointInsideBounds([a[2], a[3]], b) ||
pointInsideBounds([a[0], a[3]], b) ||
pointInsideBounds([b[0], b[1]], a) ||
pointInsideBounds([b[2], b[1]], a) ||
pointInsideBounds([b[2], b[3]], a) ||
pointInsideBounds([b[0], b[3]], a);
// const aabbsOverlapping = (a: Bounds, b: Bounds) =>
// pointInsideBounds([a[0], a[1]], b) ||
// pointInsideBounds([a[2], a[1]], b) ||
// pointInsideBounds([a[2], a[3]], b) ||
// pointInsideBounds([a[0], a[3]], b) ||
// pointInsideBounds([b[0], b[1]], a) ||
// pointInsideBounds([b[2], b[1]], a) ||
// pointInsideBounds([b[2], b[3]], a) ||
// pointInsideBounds([b[0], b[3]], a);
const getAllElementsMap = (
scene: Scene,
@ -1149,6 +1152,7 @@ const getAllElements = (
const getGlobalPoint = (
initialPoint: Point,
otherPoint: Point,
elementsMap: NonDeletedSceneElementsMap,
boundElement?: ExcalidrawBindableElement | null,
hoveredElement?: ExcalidrawBindableElement | null,
@ -1159,6 +1163,7 @@ const getGlobalPoint = (
hoveredElement &&
bindPointToSnapToElementOutline(
initialPoint,
otherPoint,
hoveredElement,
elementsMap,
);
@ -1172,6 +1177,7 @@ const getGlobalPoint = (
} else if (boundElement) {
return bindPointToSnapToElementOutline(
initialPoint,
otherPoint,
boundElement,
elementsMap,
);

View File

@ -563,6 +563,9 @@ export const vectorToHeading = (vec: Vector): Heading => {
return HEADING_UP;
};
export const compareHeading = (a: Heading, b: Heading) =>
a[0] === b[0] && a[1] === b[1];
export const scalePointFromOrigin = (
p: Point,
mid: Point,