mirror of
https://github.com/OFFIS-ESC/constellation-analyzer
synced 2026-03-13 12:08:46 +00:00
Fix pill shape self-loop geometry to follow cap curvature
Some checks failed
CI / test (push) Has been cancelled
Some checks failed
CI / test (push) Has been cancelled
Previously the pill branches behaved like rectangles: the target point was pinned to the rightmost cap point with a linearly growing y, and the vertical pill source started from the wrong end of the cap. - Horizontal pill: target now travels along the right cap surface via a cap angle (-PI/2 → 0), so both tx/ty stay on the curve - Horizontal pill: source clamped to the straight top section so it never crosses into the left cap area - Vertical pill: source now starts at the corner (angle=0, rightmost point of top cap) and rotates toward the top as loopOffset grows, matching the corner-anchoring used by other shapes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ed18b11dc9
commit
4322f3cf63
1 changed files with 23 additions and 12 deletions
|
|
@ -574,25 +574,36 @@ function getSelfLoopParams(
|
||||||
const capRadius = isHorizontal ? nodeHeight / 2 : nodeWidth / 2;
|
const capRadius = isHorizontal ? nodeHeight / 2 : nodeWidth / 2;
|
||||||
|
|
||||||
if (isHorizontal) {
|
if (isHorizontal) {
|
||||||
// Horizontal pill: source on top straight edge (left of corner), target on right cap (below corner)
|
// The top-right corner is where the top straight edge meets the right semicircle cap.
|
||||||
sx = rightEdge - loopOffset * 0.8;
|
// Source: spreads leftward along the top straight edge from the corner.
|
||||||
|
// Target: spreads downward along the right cap surface from the top of the cap.
|
||||||
|
const rightCapCenterX = nodePosition.x + nodeWidth - capRadius;
|
||||||
|
|
||||||
|
sx = Math.max(nodePosition.x + capRadius, rightCapCenterX - loopOffset * 0.6);
|
||||||
sy = topEdge;
|
sy = topEdge;
|
||||||
sourceAngle = -Math.PI / 2;
|
sourceAngle = -Math.PI / 2;
|
||||||
|
|
||||||
const rightCapCenterX = nodePosition.x + nodeWidth - capRadius;
|
// Angle on the right cap: -PI/2 = top of cap (corner), 0 = rightmost point.
|
||||||
tx = rightCapCenterX + capRadius + 2;
|
// Innermost loop targets near the top; outer loops rotate toward the right.
|
||||||
ty = topEdge + loopOffset * 0.5;
|
const targetCapAngle = -Math.PI / 2 + Math.min(Math.PI / 2, (loopOffset / capRadius) * 0.8);
|
||||||
targetAngle = 0;
|
tx = rightCapCenterX + Math.cos(targetCapAngle) * (capRadius + 2);
|
||||||
|
ty = centerY + Math.sin(targetCapAngle) * (capRadius + 2);
|
||||||
|
targetAngle = targetCapAngle;
|
||||||
} else {
|
} else {
|
||||||
// Vertical pill: source on top cap (near right), target on right straight edge (near top)
|
// The top-right corner is where the right straight edge meets the top semicircle cap.
|
||||||
|
// Source: spreads upward along the top cap from the corner.
|
||||||
|
// Target: spreads downward along the right straight edge from the corner.
|
||||||
const topCapCenterY = nodePosition.y + capRadius;
|
const topCapCenterY = nodePosition.y + capRadius;
|
||||||
const sourceAngleRad = -Math.PI / 2 + (loopOffset / nodeWidth) * Math.PI / 4;
|
|
||||||
sx = centerX + Math.cos(sourceAngleRad) * (capRadius + 2);
|
// Angle on the top cap: 0 = rightmost point of cap (corner), -PI/2 = top of cap.
|
||||||
sy = topCapCenterY + Math.sin(sourceAngleRad) * (capRadius + 2);
|
// Innermost loop sources near the corner; outer loops rotate toward the top.
|
||||||
sourceAngle = sourceAngleRad;
|
const sourceCapAngle = Math.max(-Math.PI / 2, -(loopOffset / capRadius) * 0.8);
|
||||||
|
sx = centerX + Math.cos(sourceCapAngle) * (capRadius + 2);
|
||||||
|
sy = topCapCenterY + Math.sin(sourceCapAngle) * (capRadius + 2);
|
||||||
|
sourceAngle = sourceCapAngle;
|
||||||
|
|
||||||
tx = rightEdge;
|
tx = rightEdge;
|
||||||
ty = topEdge + loopOffset * 0.5;
|
ty = topCapCenterY + loopOffset * 0.5;
|
||||||
targetAngle = 0;
|
targetAngle = 0;
|
||||||
}
|
}
|
||||||
} else if (sourceShape === 'ellipse') {
|
} else if (sourceShape === 'ellipse') {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue