using System.Collections.Concurrent; using System.Diagnostics; using System.Globalization; namespace StellaOps.ElkSharp; internal static partial class ElkEdgeRouterIterative { private static IEnumerable ExpandWinningSolutionFocus( IReadOnlyCollection edges, IEnumerable focusEdgeIds) { var edgesById = edges.ToDictionary(edge => edge.Id, StringComparer.Ordinal); var expanded = new HashSet(StringComparer.Ordinal); foreach (var edgeId in focusEdgeIds) { if (!expanded.Add(edgeId) || !edgesById.TryGetValue(edgeId, out var edge)) { continue; } foreach (var peer in edges) { if (string.Equals(peer.Id, edge.Id, StringComparison.Ordinal)) { continue; } if (string.Equals(peer.SourceNodeId, edge.SourceNodeId, StringComparison.Ordinal) || string.Equals(peer.TargetNodeId, edge.TargetNodeId, StringComparison.Ordinal) || string.Equals(peer.SourceNodeId, edge.TargetNodeId, StringComparison.Ordinal) || string.Equals(peer.TargetNodeId, edge.SourceNodeId, StringComparison.Ordinal)) { expanded.Add(peer.Id); } } } return expanded.OrderBy(edgeId => edgeId, StringComparer.Ordinal); } private static IEnumerable ExpandSharedLanePolishFocus( IReadOnlyCollection edges, IReadOnlyCollection nodes, string focusEdgeId) { var edgesById = edges.ToDictionary(edge => edge.Id, StringComparer.Ordinal); if (!edgesById.TryGetValue(focusEdgeId, out var focusEdge)) { return []; } var focusedEdgeIds = new HashSet(StringComparer.Ordinal) { focusEdgeId, }; var sharedNodeIds = new HashSet(StringComparer.Ordinal); foreach (var (leftEdgeId, rightEdgeId) in ElkEdgeRoutingScoring.DetectSharedLaneConflicts(edges, nodes)) { string partnerEdgeId; if (string.Equals(leftEdgeId, focusEdgeId, StringComparison.Ordinal)) { partnerEdgeId = rightEdgeId; } else if (string.Equals(rightEdgeId, focusEdgeId, StringComparison.Ordinal)) { partnerEdgeId = leftEdgeId; } else { continue; } if (!edgesById.TryGetValue(partnerEdgeId, out var partnerEdge)) { continue; } focusedEdgeIds.Add(partnerEdgeId); CollectSharedConflictNodeIds(focusEdge, partnerEdge, sharedNodeIds); } if (sharedNodeIds.Count == 0) { return ExpandWinningSolutionFocus(edges, [focusEdgeId]); } foreach (var edge in edges) { if (focusedEdgeIds.Contains(edge.Id)) { continue; } if ((edge.SourceNodeId is not null && sharedNodeIds.Contains(edge.SourceNodeId)) || (edge.TargetNodeId is not null && sharedNodeIds.Contains(edge.TargetNodeId))) { focusedEdgeIds.Add(edge.Id); } } return focusedEdgeIds.OrderBy(edgeId => edgeId, StringComparer.Ordinal); } private static void CollectSharedConflictNodeIds( ElkRoutedEdge edge, ElkRoutedEdge partner, ISet sharedNodeIds) { if (edge.SourceNodeId is not null && (string.Equals(edge.SourceNodeId, partner.SourceNodeId, StringComparison.Ordinal) || string.Equals(edge.SourceNodeId, partner.TargetNodeId, StringComparison.Ordinal))) { sharedNodeIds.Add(edge.SourceNodeId); } if (edge.TargetNodeId is not null && (string.Equals(edge.TargetNodeId, partner.SourceNodeId, StringComparison.Ordinal) || string.Equals(edge.TargetNodeId, partner.TargetNodeId, StringComparison.Ordinal))) { sharedNodeIds.Add(edge.TargetNodeId); } } }