Fix snapping distance at mid points

This commit is contained in:
Mark Tolmacs 2025-05-12 13:14:41 +02:00
parent 59a986cb41
commit 47cb16822c
No known key found for this signature in database

View File

@ -959,6 +959,10 @@ export const bindPointToSnapToElementOutline = (
otherPoint, otherPoint,
), ),
), ),
FIXED_BINDING_DISTANCE *
(bindableElement.type === "diamond"
? 1.414 // sqrt(2)
: 1),
)[0]; )[0];
} else { } else {
intersection = intersectElementWithLineSegment( intersection = intersectElementWithLineSegment(
@ -989,24 +993,7 @@ export const bindPointToSnapToElementOutline = (
return edgePoint; return edgePoint;
} }
if (elbowed) { return elbowed ? intersection : edgePoint;
const scalar =
pointDistanceSq(edgePoint, center) -
pointDistanceSq(intersection, center) >
0
? FIXED_BINDING_DISTANCE
: -FIXED_BINDING_DISTANCE;
return pointFromVector(
vectorScale(
vectorNormalize(vectorFromPoint(edgePoint, intersection)),
scalar,
),
intersection,
);
}
return edgePoint;
}; };
export const avoidRectangularCorner = ( export const avoidRectangularCorner = (
@ -1117,55 +1104,83 @@ export const snapToMid = (
// snap-to-center point is adaptive to element size, but we don't want to go // snap-to-center point is adaptive to element size, but we don't want to go
// above and below certain px distance // above and below certain px distance
const verticalThrehsold = clamp(tolerance * height, 5, 80); const verticalThreshold = clamp(tolerance * height, 5, 80);
const horizontalThrehsold = clamp(tolerance * width, 5, 80); const horizontalThreshold = clamp(tolerance * width, 5, 80);
if ( if (
nonRotated[0] <= x + width / 2 && nonRotated[0] <= x + width / 2 &&
nonRotated[1] > center[1] - verticalThrehsold && nonRotated[1] > center[1] - verticalThreshold &&
nonRotated[1] < center[1] + verticalThrehsold nonRotated[1] < center[1] + verticalThreshold
) { ) {
// LEFT // LEFT
return pointRotateRads( const otherPoint = pointRotateRads<GlobalPoint>(
pointFrom(x - FIXED_BINDING_DISTANCE, center[1]), pointFrom(x - FIXED_BINDING_DISTANCE, center[1]),
center, center,
angle, angle,
); );
return (
intersectElementWithLineSegment(
element,
lineSegment(center, otherPoint),
FIXED_BINDING_DISTANCE,
)[0] ?? otherPoint
);
} else if ( } else if (
nonRotated[1] <= y + height / 2 && nonRotated[1] <= y + height / 2 &&
nonRotated[0] > center[0] - horizontalThrehsold && nonRotated[0] > center[0] - horizontalThreshold &&
nonRotated[0] < center[0] + horizontalThrehsold nonRotated[0] < center[0] + horizontalThreshold
) { ) {
// TOP // TOP
return pointRotateRads( const otherPoint = pointRotateRads<GlobalPoint>(
pointFrom(center[0], y - FIXED_BINDING_DISTANCE), pointFrom(center[0], y - FIXED_BINDING_DISTANCE),
center, center,
angle, angle,
); );
return (
intersectElementWithLineSegment(
element,
lineSegment(center, otherPoint),
FIXED_BINDING_DISTANCE,
)[0] ?? otherPoint
);
} else if ( } else if (
nonRotated[0] >= x + width / 2 && nonRotated[0] >= x + width / 2 &&
nonRotated[1] > center[1] - verticalThrehsold && nonRotated[1] > center[1] - verticalThreshold &&
nonRotated[1] < center[1] + verticalThrehsold nonRotated[1] < center[1] + verticalThreshold
) { ) {
// RIGHT // RIGHT
return pointRotateRads( const otherPoint = pointRotateRads<GlobalPoint>(
pointFrom(x + width + FIXED_BINDING_DISTANCE, center[1]), pointFrom(x + width + FIXED_BINDING_DISTANCE, center[1]),
center, center,
angle, angle,
); );
return (
intersectElementWithLineSegment(
element,
lineSegment(center, otherPoint),
FIXED_BINDING_DISTANCE,
)[0] ?? otherPoint
);
} else if ( } else if (
nonRotated[1] >= y + height / 2 && nonRotated[1] >= y + height / 2 &&
nonRotated[0] > center[0] - horizontalThrehsold && nonRotated[0] > center[0] - horizontalThreshold &&
nonRotated[0] < center[0] + horizontalThrehsold nonRotated[0] < center[0] + horizontalThreshold
) { ) {
// DOWN // DOWN
return pointRotateRads( const otherPoint = pointRotateRads<GlobalPoint>(
pointFrom(center[0], y + height + FIXED_BINDING_DISTANCE), pointFrom(center[0], y + height + FIXED_BINDING_DISTANCE),
center, center,
angle, angle,
); );
return (
intersectElementWithLineSegment(
element,
lineSegment(center, otherPoint),
FIXED_BINDING_DISTANCE,
)[0] ?? otherPoint
);
} else if (element.type === "diamond") { } else if (element.type === "diamond") {
const distance = FIXED_BINDING_DISTANCE - 1; const distance = FIXED_BINDING_DISTANCE * 0.7071; // 1 / sqrt(2)
const topLeft = pointFrom<GlobalPoint>( const topLeft = pointFrom<GlobalPoint>(
x + width / 4 - distance, x + width / 4 - distance,
y + height / 4 - distance, y + height / 4 - distance,
@ -1182,29 +1197,30 @@ export const snapToMid = (
x + (3 * width) / 4 + distance, x + (3 * width) / 4 + distance,
y + (3 * height) / 4 + distance, y + (3 * height) / 4 + distance,
); );
if ( if (
pointDistance(topLeft, nonRotated) < pointDistance(topLeft, nonRotated) <
Math.max(horizontalThrehsold, verticalThrehsold) Math.max(horizontalThreshold, verticalThreshold)
) { ) {
return pointRotateRads(topLeft, center, angle); return topLeft;
} }
if ( if (
pointDistance(topRight, nonRotated) < pointDistance(topRight, nonRotated) <
Math.max(horizontalThrehsold, verticalThrehsold) Math.max(horizontalThreshold, verticalThreshold)
) { ) {
return pointRotateRads(topRight, center, angle); return topRight;
} }
if ( if (
pointDistance(bottomLeft, nonRotated) < pointDistance(bottomLeft, nonRotated) <
Math.max(horizontalThrehsold, verticalThrehsold) Math.max(horizontalThreshold, verticalThreshold)
) { ) {
return pointRotateRads(bottomLeft, center, angle); return bottomLeft;
} }
if ( if (
pointDistance(bottomRight, nonRotated) < pointDistance(bottomRight, nonRotated) <
Math.max(horizontalThrehsold, verticalThrehsold) Math.max(horizontalThreshold, verticalThreshold)
) { ) {
return pointRotateRads(bottomRight, center, angle); return bottomRight;
} }
} }