115 lines
9.9 KiB
C#
115 lines
9.9 KiB
C#
namespace StellaOps.ElkSharp;
|
|
|
|
internal static partial class ElkEdgeRouterIterative
|
|
{
|
|
private static ElkRoutedEdge[] ApplyTerminalRuleCleanupRound(
|
|
ElkRoutedEdge[] edges,
|
|
ElkPositionedNode[] nodes,
|
|
ElkLayoutDirection direction,
|
|
double minLineClearance,
|
|
IReadOnlyCollection<string>? restrictedEdgeIds = null)
|
|
{
|
|
var result = edges;
|
|
result = ElkEdgePostProcessor.SeparateSharedLaneConflicts(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SeparateRepeatCollectorLocalLaneConflicts(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.PreferShortestBoundaryShortcuts(result, nodes, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.NormalizeBoundaryAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.NormalizeSourceExitAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.ElevateRepeatCollectorNodeClearanceViolations(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkRepeatCollectorCorridors.SeparateSharedLanes(result, nodes, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadSourceDepartureJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SeparateMixedNodeFaceLaneConflicts(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadTargetApproachJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadRectTargetApproachFeederBands(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.FinalizeDecisionTargetEntries(result, nodes, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.FinalizeGatewayBoundaryGeometry(result, nodes, restrictedEdgeIds);
|
|
result = ClampBelowGraphEdges(result, nodes, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.AvoidNodeCrossings(result, nodes, direction, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.NormalizeBoundaryAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.NormalizeSourceExitAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.SeparateSharedLaneConflicts(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadSourceDepartureJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadTargetApproachJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.FinalizeGatewayBoundaryGeometry(result, nodes, restrictedEdgeIds);
|
|
result = ClampBelowGraphEdges(result, nodes, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.AvoidNodeCrossings(result, nodes, direction, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.NormalizeBoundaryAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.NormalizeSourceExitAngles(result, nodes);
|
|
// Final late-stage verification: source/target boundary normalization can collapse
|
|
// lanes back onto the same node face, so restabilize the local geometry once more.
|
|
result = ElkEdgePostProcessor.SpreadSourceDepartureJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SeparateMixedNodeFaceLaneConflicts(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadTargetApproachJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadRectTargetApproachFeederBands(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SeparateSharedLaneConflicts(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ClampBelowGraphEdges(result, nodes, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.AvoidNodeCrossings(result, nodes, direction, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.NormalizeBoundaryAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.NormalizeSourceExitAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.SpreadSourceDepartureJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SeparateMixedNodeFaceLaneConflicts(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadTargetApproachJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadRectTargetApproachFeederBands(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SeparateSharedLaneConflicts(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.NormalizeBoundaryAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.NormalizeSourceExitAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadTargetApproachJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SeparateMixedNodeFaceLaneConflicts(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SeparateSharedLaneConflicts(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.ElevateRepeatCollectorNodeClearanceViolations(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.ElevateUnderNodeViolations(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.PreferShortestBoundaryShortcuts(result, nodes, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadTargetApproachJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadRectTargetApproachFeederBands(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.ElevateUnderNodeViolations(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.FinalizeGatewayBoundaryGeometry(result, nodes, restrictedEdgeIds);
|
|
result = ClampBelowGraphEdges(result, nodes, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.AvoidNodeCrossings(result, nodes, direction, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.NormalizeBoundaryAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.NormalizeSourceExitAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadTargetApproachJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadRectTargetApproachFeederBands(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.ElevateUnderNodeViolations(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.NormalizeBoundaryAngles(result, nodes);
|
|
// Final hard-rule restabilization after the last normalize pass: the final
|
|
// boundary normalization can still pull target slots and horizontal lanes back
|
|
// into a bad state, so re-apply the local rule fixers once more before scoring.
|
|
result = ElkEdgePostProcessor.NormalizeSourceExitAngles(result, nodes);
|
|
result = ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadTargetApproachJoins(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SpreadRectTargetApproachFeederBands(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.ElevateRepeatCollectorNodeClearanceViolations(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.ElevateUnderNodeViolations(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ClampBelowGraphEdges(result, nodes, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.AvoidNodeCrossings(result, nodes, direction, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.NormalizeBoundaryAngles(result, nodes, snapToSlots: true);
|
|
result = CloseRemainingTerminalViolations(result, nodes, direction, minLineClearance, restrictedEdgeIds);
|
|
var lateDetourShortcuts = ElkEdgePostProcessor.PreferShortestBoundaryShortcuts(result, nodes, restrictedEdgeIds);
|
|
result = ElkEdgeRoutingScoring.CountBoundarySlotViolations(result, nodes) > 0
|
|
? ChoosePreferredBoundarySlotRepairLayout(result, lateDetourShortcuts, nodes)
|
|
: ChoosePreferredHardRuleLayout(result, lateDetourShortcuts, nodes);
|
|
result = ApplyFinalDetourPolish(result, nodes, direction, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SnapBoundarySlotAssignments(
|
|
result,
|
|
nodes,
|
|
minLineClearance,
|
|
restrictedEdgeIds,
|
|
enforceAllNodeEndpoints: true);
|
|
result = ApplyPostSlotDetourClosure(result, nodes, minLineClearance, restrictedEdgeIds);
|
|
result = ElkEdgePostProcessor.SnapBoundarySlotAssignments(
|
|
result,
|
|
nodes,
|
|
minLineClearance,
|
|
restrictedEdgeIds,
|
|
enforceAllNodeEndpoints: true);
|
|
return result;
|
|
}
|
|
}
|