namespace StellaOps.ElkSharp; internal static partial class ElkEdgePostProcessor { internal static ElkRoutedEdge[] PreferShortestBoundaryShortcuts( ElkRoutedEdge[] edges, ElkPositionedNode[] nodes, IReadOnlyCollection? restrictedEdgeIds = null) { if (edges.Length == 0 || nodes.Length == 0) { return edges; } var restrictedSet = restrictedEdgeIds is null ? null : restrictedEdgeIds.ToHashSet(StringComparer.Ordinal); var nodesById = nodes.ToDictionary(node => node.Id, StringComparer.Ordinal); var graphMinY = nodes.Min(node => node.Y); var graphMaxY = nodes.Max(node => node.Y + node.Height); var minLineClearance = ResolveMinLineClearance(nodes); var result = edges.ToArray(); for (var i = 0; i < result.Length; i++) { var edge = result[i]; if (restrictedSet is not null && !restrictedSet.Contains(edge.Id)) { continue; } if (!string.IsNullOrWhiteSpace(edge.SourcePortId) || !string.IsNullOrWhiteSpace(edge.TargetPortId) || !nodesById.TryGetValue(edge.SourceNodeId ?? string.Empty, out var sourceNode) || !nodesById.TryGetValue(edge.TargetNodeId ?? string.Empty, out var targetNode)) { continue; } if (!string.IsNullOrWhiteSpace(edge.Kind) && edge.Kind.StartsWith("backward|", StringComparison.OrdinalIgnoreCase)) { continue; } if (HasProtectedUnderNodeGeometry(edge) && ElkEdgeRoutingScoring.CountUnderNodeViolations([edge], nodes) > 0) { continue; } if (IsRepeatCollectorLabel(edge.Label) && HasCorridorBendPoints(edge, graphMinY, graphMaxY)) { continue; } var path = ExtractFullPath(edge); if (path.Count < 2) { continue; } List? bestShortcut = null; var currentLength = ComputePathLength(path); bool IsAcceptableShortcutCandidate(IReadOnlyList candidate) { if (candidate.Count < 2 || HasNodeObstacleCrossing(candidate, nodes, edge.SourceNodeId, edge.TargetNodeId)) { return false; } if (ElkShapeBoundaries.IsGatewayShape(sourceNode)) { if (!HasAcceptableGatewayBoundaryPath( candidate, nodes, edge.SourceNodeId, edge.TargetNodeId, sourceNode, fromStart: true)) { return false; } } else if (!HasValidBoundaryAngle(candidate[0], candidate[1], sourceNode)) { return false; } if (ElkShapeBoundaries.IsGatewayShape(targetNode)) { return CanAcceptGatewayTargetRepair(candidate, targetNode) && HasAcceptableGatewayBoundaryPath( candidate, nodes, edge.SourceNodeId, edge.TargetNodeId, targetNode, fromStart: false); } return !HasTargetApproachBacktracking(candidate, targetNode) && HasValidBoundaryAngle(candidate[^1], candidate[^2], targetNode); } void ConsiderShortcutCandidate(List? candidate) { if (candidate is null || ComputePathLength(candidate) + 16d >= currentLength || !IsAcceptableShortcutCandidate(candidate)) { return; } if (bestShortcut is not null && ComputePathLength(candidate) + 0.5d >= ComputePathLength(bestShortcut)) { return; } bestShortcut = candidate; } if (TryBuildDominantPreferredBoundaryShortcutPath( sourceNode, targetNode, nodes, edge.SourceNodeId, edge.TargetNodeId, out var dominantShortcut)) { ConsiderShortcutCandidate(dominantShortcut); } if (TryBuildPreferredBoundaryShortcutPath( sourceNode, targetNode, nodes, edge.SourceNodeId, edge.TargetNodeId, out var preferredShortcut)) { ConsiderShortcutCandidate(preferredShortcut); } var localSkirtShortcut = TryBuildLocalObstacleSkirtBoundaryShortcut( path, path[0], path[^1], nodes, edge.SourceNodeId, edge.TargetNodeId, targetNode, minLineClearance); ConsiderShortcutCandidate(localSkirtShortcut); if (bestShortcut is null) { continue; } result[i] = BuildSingleSectionEdge(edge, bestShortcut); } return result; } }