Refactor ElkSharp hybrid routing and document speed path
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
namespace StellaOps.ElkSharp;
|
||||
|
||||
internal static partial class ElkEdgeRouterIterative
|
||||
{
|
||||
private static CandidateSolution ApplyFinalDirectUnderNodePolish(
|
||||
CandidateSolution solution,
|
||||
ElkPositionedNode[] nodes,
|
||||
double minLineClearance)
|
||||
{
|
||||
var current = solution;
|
||||
var underNodeSeverity = new Dictionary<string, int>(StringComparer.Ordinal);
|
||||
ElkEdgeRoutingScoring.CountUnderNodeViolations(current.Edges, nodes, underNodeSeverity, 10);
|
||||
if (underNodeSeverity.Count == 0)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
foreach (var edgeId in underNodeSeverity
|
||||
.OrderByDescending(pair => pair.Value)
|
||||
.ThenBy(pair => pair.Key, StringComparer.Ordinal)
|
||||
.Select(pair => pair.Key))
|
||||
{
|
||||
var candidateEdges = ElkEdgePostProcessor.ElevateUnderNodeViolations(
|
||||
current.Edges,
|
||||
nodes,
|
||||
minLineClearance,
|
||||
[edgeId]);
|
||||
var candidateScore = ElkEdgeRoutingScoring.ComputeScore(candidateEdges, nodes);
|
||||
var candidateRetryState = BuildRetryState(
|
||||
candidateScore,
|
||||
HighwayProcessingEnabled
|
||||
? ElkEdgeRouterHighway.DetectRemainingBrokenHighways(candidateEdges, nodes).Count
|
||||
: 0);
|
||||
if (!IsBetterCandidate(candidateScore, candidateRetryState, current.Score, current.RetryState))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
current = current with
|
||||
{
|
||||
Score = candidateScore,
|
||||
RetryState = candidateRetryState,
|
||||
Edges = candidateEdges,
|
||||
};
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
private static CandidateSolution ApplyFinalProtectedLocalBundlePolish(
|
||||
CandidateSolution solution,
|
||||
ElkPositionedNode[] nodes,
|
||||
double minLineClearance)
|
||||
{
|
||||
var current = solution;
|
||||
var underNodeSeverity = new Dictionary<string, int>(StringComparer.Ordinal);
|
||||
ElkEdgeRoutingScoring.CountUnderNodeViolations(current.Edges, nodes, underNodeSeverity, 10);
|
||||
|
||||
var focusSeverity = new Dictionary<string, int>(underNodeSeverity, StringComparer.Ordinal);
|
||||
ElkEdgeRoutingScoring.CountTargetApproachJoinViolations(current.Edges, nodes, focusSeverity, 10);
|
||||
if (focusSeverity.Count == 0)
|
||||
{
|
||||
return current;
|
||||
}
|
||||
|
||||
foreach (var edgeId in focusSeverity
|
||||
.OrderByDescending(pair => pair.Value)
|
||||
.ThenBy(pair => pair.Key, StringComparer.Ordinal)
|
||||
.Select(pair => pair.Key))
|
||||
{
|
||||
var focusEdgeIds = ExpandWinningSolutionFocus(current.Edges, [edgeId]).ToArray();
|
||||
if (focusEdgeIds.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var focusedRepairSeeds = focusEdgeIds
|
||||
.Where(underNodeSeverity.ContainsKey)
|
||||
.OrderBy(id => id, StringComparer.Ordinal)
|
||||
.ToArray();
|
||||
if (focusedRepairSeeds.Length == 0)
|
||||
{
|
||||
focusedRepairSeeds = [edgeId];
|
||||
}
|
||||
|
||||
var candidateEdges = ElkEdgePostProcessor.ElevateUnderNodeViolations(
|
||||
current.Edges,
|
||||
nodes,
|
||||
minLineClearance,
|
||||
focusedRepairSeeds);
|
||||
candidateEdges = ElkEdgePostProcessor.SpreadTargetApproachJoins(
|
||||
candidateEdges,
|
||||
nodes,
|
||||
minLineClearance,
|
||||
focusEdgeIds,
|
||||
forceOutwardAxisSpacing: true);
|
||||
candidateEdges = ElkEdgePostProcessor.SpreadRectTargetApproachFeederBands(
|
||||
candidateEdges,
|
||||
nodes,
|
||||
minLineClearance,
|
||||
focusEdgeIds);
|
||||
candidateEdges = ElkEdgePostProcessor.SeparateSharedLaneConflicts(
|
||||
candidateEdges,
|
||||
nodes,
|
||||
minLineClearance,
|
||||
focusEdgeIds);
|
||||
candidateEdges = ElkEdgePostProcessor.ElevateUnderNodeViolations(
|
||||
candidateEdges,
|
||||
nodes,
|
||||
minLineClearance,
|
||||
focusEdgeIds);
|
||||
candidateEdges = ElkEdgePostProcessor.SpreadTargetApproachJoins(
|
||||
candidateEdges,
|
||||
nodes,
|
||||
minLineClearance,
|
||||
focusEdgeIds,
|
||||
forceOutwardAxisSpacing: true);
|
||||
candidateEdges = ElkEdgePostProcessor.SpreadRectTargetApproachFeederBands(
|
||||
candidateEdges,
|
||||
nodes,
|
||||
minLineClearance,
|
||||
focusEdgeIds);
|
||||
candidateEdges = ChoosePreferredHardRuleLayout(current.Edges, candidateEdges, nodes);
|
||||
|
||||
var candidateScore = ElkEdgeRoutingScoring.ComputeScore(candidateEdges, nodes);
|
||||
var candidateRetryState = BuildRetryState(
|
||||
candidateScore,
|
||||
HighwayProcessingEnabled
|
||||
? ElkEdgeRouterHighway.DetectRemainingBrokenHighways(candidateEdges, nodes).Count
|
||||
: 0);
|
||||
if (!IsBetterCandidate(candidateScore, candidateRetryState, current.Score, current.RetryState))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
current = current with
|
||||
{
|
||||
Score = candidateScore,
|
||||
RetryState = candidateRetryState,
|
||||
Edges = candidateEdges,
|
||||
};
|
||||
|
||||
underNodeSeverity.Clear();
|
||||
ElkEdgeRoutingScoring.CountUnderNodeViolations(current.Edges, nodes, underNodeSeverity, 10);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user