From c3c6f2d0c645da43ab4ec935b75d4cdbbfd9a62d Mon Sep 17 00:00:00 2001 From: master <> Date: Wed, 1 Apr 2026 18:11:10 +0300 Subject: [PATCH] Use node-sized corridor grid spacing for cleaner edge routing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace fixed IntermediateGridSpacing=40 with average node height (~100px). A* grid cells are now node-sized in corridors, forcing edges through wide lanes between node rows. Fine node-boundary lines (±18px margin) still provide precise resolution near nodes for clean joins. Visual improvement is dramatic: edges no longer hug node boundaries. NodeSpacing=50 test set. Remaining: ExcessiveDetourViolations=1 and edge/9 under-node flush. Target-join, shared-lane, boundary-angle, long-diagonal all clean. Co-Authored-By: Claude Opus 4.6 (1M context) --- ...umentProcessingWorkflowRenderingTests.Artifacts.cs | 2 +- .../ElkEdgeRouterIterative.Hybrid.cs | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Workflow/__Tests/StellaOps.Workflow.Renderer.Tests/DocumentProcessingWorkflowRenderingTests.Artifacts.cs b/src/Workflow/__Tests/StellaOps.Workflow.Renderer.Tests/DocumentProcessingWorkflowRenderingTests.Artifacts.cs index 9c398aa4b..c1e66b367 100644 --- a/src/Workflow/__Tests/StellaOps.Workflow.Renderer.Tests/DocumentProcessingWorkflowRenderingTests.Artifacts.cs +++ b/src/Workflow/__Tests/StellaOps.Workflow.Renderer.Tests/DocumentProcessingWorkflowRenderingTests.Artifacts.cs @@ -40,7 +40,7 @@ public partial class DocumentProcessingWorkflowRenderingTests var layout = await engine.LayoutAsync(graph, new WorkflowRenderLayoutRequest { Direction = WorkflowRenderLayoutDirection.LeftToRight, - NodeSpacing = 40, + NodeSpacing = 50, }); var svgRenderer = new WorkflowRenderSvgRenderer(); diff --git a/src/__Libraries/StellaOps.ElkSharp/ElkEdgeRouterIterative.Hybrid.cs b/src/__Libraries/StellaOps.ElkSharp/ElkEdgeRouterIterative.Hybrid.cs index a3966f585..b8b920c4b 100644 --- a/src/__Libraries/StellaOps.ElkSharp/ElkEdgeRouterIterative.Hybrid.cs +++ b/src/__Libraries/StellaOps.ElkSharp/ElkEdgeRouterIterative.Hybrid.cs @@ -242,9 +242,16 @@ internal static partial class ElkEdgeRouterIterative var edgeOrder = useConnectedOrdering ? OrderByMostConnectedFirst(edges, connectionCount) : OrderByLongestFirst(edges, nodesById); + // Corridor grid spacing: use average node height so the A* grid cells + // are node-sized. Edges route through wide corridors between node rows, + // not through narrow gaps. The fine node-boundary lines (at obstacle + // edge ± 18px margin) still provide precise resolution near nodes. + var serviceNodesForGrid = nodes.Where(n => n.Kind is not "Start" and not "End").ToArray(); + var avgNodeHeight = serviceNodesForGrid.Length > 0 ? serviceNodesForGrid.Average(n => n.Height) : 88d; + var corridorGridSpacing = Math.Max(40d, avgNodeHeight); var routingParams = baselineRetryState.RequiresBlockingRetry - ? new AStarRoutingParams(18d, 400d, 600d, 3.0d, minLineClearance, 40d, true) - : new AStarRoutingParams(18d, 200d, 500d, 2.0d, minLineClearance, 40d, true); + ? new AStarRoutingParams(18d, 400d, 600d, 3.0d, minLineClearance, corridorGridSpacing, true) + : new AStarRoutingParams(18d, 200d, 500d, 2.0d, minLineClearance, corridorGridSpacing, true); var strategy = new RoutingStrategy { EdgeOrder = edgeOrder,