194 lines
6.8 KiB
C#
194 lines
6.8 KiB
C#
using System.Collections.Concurrent;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
|
|
namespace StellaOps.ElkSharp;
|
|
|
|
internal static partial class ElkEdgeRouterIterative
|
|
{
|
|
private static IEnumerable<RoutingStrategy> GenerateStrategies(
|
|
ElkRoutedEdge[] edges,
|
|
ElkPositionedNode[] nodes,
|
|
IterativeRoutingConfig config,
|
|
double minLineClearance)
|
|
{
|
|
var nodesById = nodes.ToDictionary(n => n.Id, StringComparer.Ordinal);
|
|
var connectionCount = new Dictionary<string, int>(StringComparer.Ordinal);
|
|
foreach (var edge in edges)
|
|
{
|
|
var srcId = edge.SourceNodeId ?? "";
|
|
var tgtId = edge.TargetNodeId ?? "";
|
|
connectionCount[srcId] = connectionCount.GetValueOrDefault(srcId) + 1;
|
|
connectionCount[tgtId] = connectionCount.GetValueOrDefault(tgtId) + 1;
|
|
}
|
|
|
|
var orderings = new[]
|
|
{
|
|
OrderByLongestFirst(edges, nodesById),
|
|
OrderByShortestFirst(edges, nodesById),
|
|
OrderByMostConnectedFirst(edges, connectionCount),
|
|
OrderByReverse(edges),
|
|
};
|
|
|
|
// Strategies 1-4: base params, clearance = half avg node dimension
|
|
var baseParams = new AStarRoutingParams(18d, 200d, 500d, 2.0d, minLineClearance, 40d, true);
|
|
foreach (var order in orderings)
|
|
{
|
|
yield return new RoutingStrategy
|
|
{
|
|
EdgeOrder = order,
|
|
BaseLineClearance = minLineClearance,
|
|
MinLineClearance = minLineClearance,
|
|
RoutingParams = baseParams,
|
|
};
|
|
}
|
|
|
|
// Strategies 5-8: higher penalties and tighter clearance
|
|
var highParams = new AStarRoutingParams(18d, 400d, 600d, 3.0d, minLineClearance, 40d, true);
|
|
foreach (var order in orderings)
|
|
{
|
|
yield return new RoutingStrategy
|
|
{
|
|
EdgeOrder = order,
|
|
BaseLineClearance = minLineClearance,
|
|
MinLineClearance = minLineClearance,
|
|
RoutingParams = highParams,
|
|
};
|
|
}
|
|
|
|
// Strategies 9+: seeded random with clearance
|
|
for (var i = 0; i < 8; i++)
|
|
{
|
|
var seed = HashCode.Combine(edges.Length, nodes.Length, i + 8);
|
|
var rng = new Random(seed);
|
|
var order = Enumerable.Range(0, edges.Length).ToArray();
|
|
Shuffle(order, rng);
|
|
var randomParams = new AStarRoutingParams(
|
|
18d,
|
|
80d + (rng.NextDouble() * 420d),
|
|
300d + (rng.NextDouble() * 500d),
|
|
1.0d + (rng.NextDouble() * 3.0d),
|
|
minLineClearance * (0.5d + rng.NextDouble()),
|
|
40d,
|
|
true);
|
|
yield return new RoutingStrategy
|
|
{
|
|
EdgeOrder = order,
|
|
BaseLineClearance = minLineClearance,
|
|
MinLineClearance = minLineClearance,
|
|
RoutingParams = randomParams,
|
|
};
|
|
}
|
|
}
|
|
|
|
private static RoutingRetryState BuildRetryState(EdgeRoutingScore score, int remainingBrokenHighways)
|
|
{
|
|
return new RoutingRetryState(
|
|
RemainingShortHighways: remainingBrokenHighways,
|
|
RepeatCollectorCorridorViolations: score.RepeatCollectorCorridorViolations,
|
|
RepeatCollectorNodeClearanceViolations: score.RepeatCollectorNodeClearanceViolations,
|
|
TargetApproachJoinViolations: score.TargetApproachJoinViolations,
|
|
TargetApproachBacktrackingViolations: score.TargetApproachBacktrackingViolations,
|
|
ExcessiveDetourViolations: score.ExcessiveDetourViolations,
|
|
SharedLaneViolations: score.SharedLaneViolations,
|
|
BoundarySlotViolations: score.BoundarySlotViolations,
|
|
BelowGraphViolations: score.BelowGraphViolations,
|
|
UnderNodeViolations: score.UnderNodeViolations,
|
|
LongDiagonalViolations: score.LongDiagonalViolations,
|
|
ProximityViolations: score.ProximityViolations,
|
|
EntryAngleViolations: score.EntryAngleViolations,
|
|
GatewaySourceExitViolations: score.GatewaySourceExitViolations,
|
|
LabelProximityViolations: score.LabelProximityViolations,
|
|
EdgeCrossings: score.EdgeCrossings);
|
|
}
|
|
|
|
private static string DescribeRetryState(RoutingRetryState retryState)
|
|
{
|
|
var parts = new List<string>(5);
|
|
if (retryState.RemainingShortHighways > 0)
|
|
{
|
|
parts.Add($"short-highways={retryState.RemainingShortHighways}");
|
|
}
|
|
|
|
if (retryState.RepeatCollectorCorridorViolations > 0)
|
|
{
|
|
parts.Add($"collector-corridors={retryState.RepeatCollectorCorridorViolations}");
|
|
}
|
|
|
|
if (retryState.RepeatCollectorNodeClearanceViolations > 0)
|
|
{
|
|
parts.Add($"collector-clearance={retryState.RepeatCollectorNodeClearanceViolations}");
|
|
}
|
|
|
|
if (retryState.TargetApproachJoinViolations > 0)
|
|
{
|
|
parts.Add($"target-joins={retryState.TargetApproachJoinViolations}");
|
|
}
|
|
|
|
if (retryState.TargetApproachBacktrackingViolations > 0)
|
|
{
|
|
parts.Add($"approach-backtracking={retryState.TargetApproachBacktrackingViolations}");
|
|
}
|
|
|
|
if (retryState.ExcessiveDetourViolations > 0)
|
|
{
|
|
parts.Add($"detour={retryState.ExcessiveDetourViolations}");
|
|
}
|
|
|
|
if (retryState.GatewaySourceExitViolations > 0)
|
|
{
|
|
parts.Add($"gateway-source={retryState.GatewaySourceExitViolations}");
|
|
}
|
|
|
|
if (retryState.SharedLaneViolations > 0)
|
|
{
|
|
parts.Add($"shared-lanes={retryState.SharedLaneViolations}");
|
|
}
|
|
|
|
if (retryState.BoundarySlotViolations > 0)
|
|
{
|
|
parts.Add($"boundary-slots={retryState.BoundarySlotViolations}");
|
|
}
|
|
|
|
if (retryState.BelowGraphViolations > 0)
|
|
{
|
|
parts.Add($"below-graph={retryState.BelowGraphViolations}");
|
|
}
|
|
|
|
if (retryState.UnderNodeViolations > 0)
|
|
{
|
|
parts.Add($"under-node={retryState.UnderNodeViolations}");
|
|
}
|
|
|
|
if (retryState.LongDiagonalViolations > 0)
|
|
{
|
|
parts.Add($"long-diagonal={retryState.LongDiagonalViolations}");
|
|
}
|
|
|
|
if (retryState.ProximityViolations > 0)
|
|
{
|
|
parts.Add($"proximity={retryState.ProximityViolations}");
|
|
}
|
|
|
|
if (retryState.EntryAngleViolations > 0)
|
|
{
|
|
parts.Add($"entry={retryState.EntryAngleViolations}");
|
|
}
|
|
|
|
if (retryState.LabelProximityViolations > 0)
|
|
{
|
|
parts.Add($"label={retryState.LabelProximityViolations}");
|
|
}
|
|
|
|
if (retryState.EdgeCrossings > 0)
|
|
{
|
|
parts.Add($"edge-crossings={retryState.EdgeCrossings}");
|
|
}
|
|
|
|
return parts.Count > 0
|
|
? string.Join(", ", parts)
|
|
: "none";
|
|
}
|
|
|
|
}
|