150 lines
5.8 KiB
C#
150 lines
5.8 KiB
C#
using System.Collections.Concurrent;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
|
|
namespace StellaOps.ElkSharp;
|
|
|
|
internal static partial class ElkEdgeRouterIterative
|
|
{
|
|
private static bool ShouldPreferFastTerminalOnlyHardRuleClosure(RoutingRetryState retryState)
|
|
{
|
|
return retryState.RemainingShortHighways == 0
|
|
&& retryState.RepeatCollectorCorridorViolations == 0
|
|
&& retryState.RepeatCollectorNodeClearanceViolations == 0
|
|
&& retryState.TargetApproachBacktrackingViolations == 0
|
|
&& retryState.ExcessiveDetourViolations == 0
|
|
&& retryState.BoundarySlotViolations == 0
|
|
&& retryState.BelowGraphViolations == 0
|
|
&& retryState.UnderNodeViolations == 0
|
|
&& retryState.LongDiagonalViolations == 0
|
|
&& retryState.SharedLaneViolations <= 2
|
|
&& (retryState.TargetApproachJoinViolations > 0
|
|
|| retryState.EntryAngleViolations > 0
|
|
|| retryState.GatewaySourceExitViolations > 0
|
|
|| retryState.SharedLaneViolations > 0);
|
|
}
|
|
|
|
private static ElkRoutedEdge[] BuildFastTerminalOnlyHardRuleCandidate(
|
|
ElkRoutedEdge[] edges,
|
|
ElkPositionedNode[] nodes,
|
|
ElkLayoutDirection direction,
|
|
double minLineClearance,
|
|
IReadOnlyCollection<string> restrictedEdgeIds)
|
|
{
|
|
var candidate = edges;
|
|
candidate = ChoosePreferredHardRuleLayout(
|
|
candidate,
|
|
ElkEdgePostProcessor.SeparateSharedLaneConflicts(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
restrictedEdgeIds),
|
|
nodes);
|
|
candidate = ChoosePreferredHardRuleLayout(
|
|
candidate,
|
|
ElkEdgePostProcessor.SpreadSourceDepartureJoins(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
restrictedEdgeIds),
|
|
nodes);
|
|
candidate = ChoosePreferredHardRuleLayout(
|
|
candidate,
|
|
ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
restrictedEdgeIds),
|
|
nodes);
|
|
candidate = ChoosePreferredHardRuleLayout(
|
|
candidate,
|
|
ElkEdgePostProcessor.SpreadTargetApproachJoins(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
restrictedEdgeIds,
|
|
forceOutwardAxisSpacing: true),
|
|
nodes);
|
|
candidate = ChoosePreferredHardRuleLayout(
|
|
candidate,
|
|
ElkEdgePostProcessor.NormalizeBoundaryAngles(candidate, nodes),
|
|
nodes);
|
|
candidate = ChoosePreferredHardRuleLayout(
|
|
candidate,
|
|
ElkEdgePostProcessor.NormalizeSourceExitAngles(candidate, nodes),
|
|
nodes);
|
|
candidate = ChoosePreferredHardRuleLayout(
|
|
candidate,
|
|
ElkEdgePostProcessor.SeparateSharedLaneConflicts(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
restrictedEdgeIds),
|
|
nodes);
|
|
return candidate;
|
|
}
|
|
|
|
private static bool ShouldPreferCompactFocusedTerminalClosure(
|
|
RoutingRetryState retryState,
|
|
int focusEdgeCount)
|
|
{
|
|
return focusEdgeCount <= 4
|
|
&& retryState.BoundarySlotViolations == 0
|
|
&& retryState.BelowGraphViolations == 0
|
|
&& retryState.UnderNodeViolations == 0
|
|
&& retryState.GatewaySourceExitViolations == 0
|
|
&& retryState.EntryAngleViolations == 0
|
|
&& retryState.TargetApproachBacktrackingViolations == 0
|
|
&& retryState.ExcessiveDetourViolations == 0
|
|
&& retryState.TargetApproachJoinViolations <= 1
|
|
&& retryState.SharedLaneViolations <= 1
|
|
&& (retryState.TargetApproachJoinViolations > 0
|
|
|| retryState.SharedLaneViolations > 0);
|
|
}
|
|
|
|
private static ElkRoutedEdge[] ApplyCompactFocusedTerminalClosure(
|
|
ElkRoutedEdge[] edges,
|
|
ElkPositionedNode[] nodes,
|
|
ElkLayoutDirection direction,
|
|
double minLineClearance,
|
|
IReadOnlyCollection<string> focusedEdgeIds)
|
|
{
|
|
var candidate = edges;
|
|
candidate = ApplyGuardedFocusedHardRulePass(
|
|
candidate,
|
|
nodes,
|
|
current => ElkEdgePostProcessor.SeparateSharedLaneConflicts(current, nodes, minLineClearance, focusedEdgeIds));
|
|
candidate = ApplyGuardedFocusedHardRulePass(
|
|
candidate,
|
|
nodes,
|
|
current => ElkEdgePostProcessor.SpreadSourceDepartureJoins(current, nodes, minLineClearance, focusedEdgeIds));
|
|
candidate = ApplyGuardedFocusedHardRulePass(
|
|
candidate,
|
|
nodes,
|
|
current => ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(current, nodes, minLineClearance, focusedEdgeIds));
|
|
candidate = ApplyGuardedFocusedHardRulePass(
|
|
candidate,
|
|
nodes,
|
|
current => ElkEdgePostProcessor.SpreadTargetApproachJoins(
|
|
current,
|
|
nodes,
|
|
minLineClearance,
|
|
focusedEdgeIds,
|
|
forceOutwardAxisSpacing: true));
|
|
candidate = ApplyGuardedFocusedHardRulePass(
|
|
candidate,
|
|
nodes,
|
|
current => ElkEdgePostProcessor.SeparateSharedLaneConflicts(current, nodes, minLineClearance, focusedEdgeIds));
|
|
candidate = ApplyGuardedFocusedHardRulePass(
|
|
candidate,
|
|
nodes,
|
|
current => ElkEdgePostProcessor.NormalizeBoundaryAngles(current, nodes));
|
|
candidate = ApplyGuardedFocusedHardRulePass(
|
|
candidate,
|
|
nodes,
|
|
current => ElkEdgePostProcessor.NormalizeSourceExitAngles(current, nodes));
|
|
return candidate;
|
|
}
|
|
|
|
}
|