Skip to content

Commit f4f7b06

Browse files
authored
Merge pull request #244 from pathsim/routing-tweaks
routing tweaks
2 parents 4b7a0c1 + e7f6b4b commit f4f7b06

2 files changed

Lines changed: 33 additions & 10 deletions

File tree

src/lib/components/edges/OrthogonalEdge.svelte

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
</script>
2020

2121
<script lang="ts">
22-
import { BaseEdge, type EdgeProps, Position } from '@xyflow/svelte';
22+
import { BaseEdge, getSmoothStepPath, type EdgeProps, Position } from '@xyflow/svelte';
2323
import { hoveredHandle, selectedNodeHighlight } from '$lib/stores/hoveredHandle';
2424
import { routingStore, type PortInfo } from '$lib/stores/routing';
2525
import { historyStore } from '$lib/stores/history';
@@ -294,9 +294,26 @@
294294
}
295295
});
296296
297-
// Always use the cached path - never show fallback routes
297+
// Smooth-step fallback when no valid orthogonal path exists
298+
const smoothStepFallback = $derived(() => {
299+
const src = adjustedSource();
300+
const tgt = adjustedTarget();
301+
const [edgePath] = getSmoothStepPath({
302+
sourceX: src.x,
303+
sourceY: src.y,
304+
sourcePosition,
305+
targetX: tgt.x,
306+
targetY: tgt.y,
307+
targetPosition,
308+
borderRadius: 8
309+
});
310+
return edgePath;
311+
});
312+
313+
// Use cached orthogonal path, or fall back to smooth-step
298314
const pathInfo = $derived(() => {
299-
return { path: cachedPath, isFallback: !cachedPath };
315+
if (cachedPath) return { path: cachedPath, isFallback: false };
316+
return { path: smoothStepFallback(), isFallback: true };
300317
});
301318
302319
// Get user waypoints from route result or data
@@ -488,13 +505,19 @@
488505
return { x: endPoint.x, y: endPoint.y, angle };
489506
}
490507
491-
// Fallback (smoothstep): arrow based on target position, use unadjusted target
492-
let angle = 0;
493-
if (targetPosition === 'left') angle = 180;
494-
else if (targetPosition === 'top') angle = -90;
495-
else if (targetPosition === 'bottom') angle = 90;
508+
// Fallback (smoothstep): derive arrow position and angle from SVG path geometry
509+
const { path } = pathInfo();
510+
if (path) {
511+
const svgPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
512+
svgPath.setAttribute('d', path);
513+
const totalLength = svgPath.getTotalLength();
514+
const endPoint = svgPath.getPointAtLength(totalLength);
515+
const nearEnd = svgPath.getPointAtLength(totalLength - 5);
516+
const angle = Math.atan2(endPoint.y - nearEnd.y, endPoint.x - nearEnd.x) * (180 / Math.PI);
517+
return { x: endPoint.x, y: endPoint.y, angle };
518+
}
496519
497-
return { x: targetX, y: targetY, angle };
520+
return { x: tgt.x, y: tgt.y, angle: 0 };
498521
});
499522
</script>
500523

src/lib/routing/constants.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { G } from '$lib/constants/grid';
77
/** Margin around nodes for routing (1G = 10px) */
88
export const ROUTING_MARGIN = G.unit;
99

10-
/** Minimum distance from source port before first turn (0 - handle offset provides clearance) */
10+
/** Minimum distance from source port before first turn (0 - handle provides clearance) */
1111
export const SOURCE_CLEARANCE = 0;
1212

1313
/** Minimum distance from target port before first turn (1G = 10px) */

0 commit comments

Comments
 (0)