171 lines
7.5 KiB
C#
171 lines
7.5 KiB
C#
using System.Collections.Concurrent;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
|
|
namespace StellaOps.ElkSharp;
|
|
|
|
internal static partial class ElkEdgeRouterIterative
|
|
{
|
|
private static ElkRoutedEdge[] ApplyLateBoundarySlotRestabilization(
|
|
ElkRoutedEdge[] edges,
|
|
ElkPositionedNode[] nodes,
|
|
double minLineClearance,
|
|
IReadOnlyCollection<string> focusEdgeIds)
|
|
{
|
|
if (focusEdgeIds.Count == 0)
|
|
{
|
|
return edges;
|
|
}
|
|
|
|
var candidate = ElkEdgePostProcessor.SeparateMixedNodeFaceLaneConflicts(
|
|
edges,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after mixed-face separation");
|
|
candidate = ElkEdgePostProcessor.SeparateRepeatCollectorLocalLaneConflicts(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after collector separation");
|
|
candidate = ElkEdgePostProcessor.SpreadSourceDepartureJoins(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after source-join spread");
|
|
candidate = ElkEdgePostProcessor.SeparateSharedLaneConflicts(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after shared-lane separation");
|
|
candidate = ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after boundary/target repair");
|
|
candidate = ElkEdgePostProcessor.SpreadTargetApproachJoins(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after target-join spread");
|
|
candidate = ElkEdgePostProcessor.SpreadRectTargetApproachFeederBands(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after feeder-band spread");
|
|
candidate = ElkEdgePostProcessor.FinalizeGatewayBoundaryGeometry(candidate, nodes, focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after gateway finalize");
|
|
candidate = ElkEdgePostProcessor.NormalizeBoundaryAngles(candidate, nodes);
|
|
candidate = ElkEdgePostProcessor.NormalizeSourceExitAngles(candidate, nodes);
|
|
candidate = ElkEdgePostProcessor.SnapBoundarySlotAssignments(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds,
|
|
enforceAllNodeEndpoints: true);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after first normalization snap");
|
|
candidate = ElkEdgePostProcessor.SeparateRepeatCollectorLocalLaneConflicts(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after second collector separation");
|
|
candidate = ElkEdgePostProcessor.SpreadSourceDepartureJoins(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after second source-join spread");
|
|
candidate = ElkEdgePostProcessor.SeparateMixedNodeFaceLaneConflicts(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after second mixed-face separation");
|
|
candidate = ElkEdgePostProcessor.SeparateSharedLaneConflicts(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after second shared-lane separation");
|
|
candidate = ElkEdgePostProcessor.RepairBoundaryAnglesAndTargetApproaches(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after second boundary/target repair");
|
|
candidate = ElkEdgePostProcessor.SpreadTargetApproachJoins(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after second target-join spread");
|
|
candidate = ElkEdgePostProcessor.SpreadRectTargetApproachFeederBands(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after second feeder-band spread");
|
|
candidate = ElkEdgePostProcessor.FinalizeGatewayBoundaryGeometry(candidate, nodes, focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after second gateway finalize");
|
|
candidate = ApplyPostSlotDetourClosure(candidate, nodes, minLineClearance, focusEdgeIds);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization after detour closure");
|
|
candidate = ElkEdgePostProcessor.NormalizeBoundaryAngles(candidate, nodes);
|
|
candidate = ElkEdgePostProcessor.NormalizeSourceExitAngles(candidate, nodes);
|
|
candidate = ElkEdgePostProcessor.SnapBoundarySlotAssignments(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
focusEdgeIds,
|
|
enforceAllNodeEndpoints: true);
|
|
ElkLayoutDiagnostics.LogProgress("Late boundary-slot restabilization complete");
|
|
|
|
return ChoosePreferredBoundarySlotRepairLayout(edges, candidate, nodes);
|
|
}
|
|
|
|
private static ElkRoutedEdge[] ApplyLateFocusedBoundarySlotClosure(
|
|
ElkRoutedEdge[] edges,
|
|
ElkPositionedNode[] nodes,
|
|
ElkLayoutDirection direction,
|
|
double minLineClearance,
|
|
IReadOnlyCollection<string> focusEdgeIds,
|
|
IReadOnlyCollection<string>? restrictedEdgeIds)
|
|
{
|
|
var candidate = ChoosePreferredHardRuleLayout(
|
|
edges,
|
|
ApplyAggressiveSharedLaneClosure(edges, nodes, direction, minLineClearance, focusEdgeIds),
|
|
nodes);
|
|
candidate = ChoosePreferredBoundarySlotRepairLayout(
|
|
candidate,
|
|
ElkEdgePostProcessor.SnapBoundarySlotAssignments(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
restrictedEdgeIds,
|
|
enforceAllNodeEndpoints: true),
|
|
nodes);
|
|
candidate = ChoosePreferredBoundarySlotRepairLayout(
|
|
candidate,
|
|
CloseRemainingTerminalViolations(candidate, nodes, direction, minLineClearance, restrictedEdgeIds),
|
|
nodes);
|
|
candidate = ApplyLateBoundarySlotRestabilization(candidate, nodes, minLineClearance, focusEdgeIds);
|
|
candidate = ChoosePreferredBoundarySlotRepairLayout(
|
|
candidate,
|
|
ElkEdgePostProcessor.SnapBoundarySlotAssignments(
|
|
candidate,
|
|
nodes,
|
|
minLineClearance,
|
|
restrictedEdgeIds,
|
|
enforceAllNodeEndpoints: true),
|
|
nodes);
|
|
return candidate;
|
|
}
|
|
|
|
}
|