/// <summary> /// unite the nodes that are close to each other /// </summary> bool GlueConflictingNodes() { var circlesHierarchy = GetCirclesHierarchy(); if (circlesHierarchy == null) { return(false); } var gluingMap = new Dictionary <Station, Station>(); var gluedDomain = new Set <Station>(); RectangleNodeUtils.CrossRectangleNodes <Station>(circlesHierarchy, circlesHierarchy, (i, j) => TryToGlueNodes(i, j, gluingMap, gluedDomain)); if (gluingMap.Count == 0) { return(false); } for (int i = 0; i < metroGraphData.Edges.Length; i++) { RegenerateEdge(gluingMap, i); } //can it be more efficient? HashSet <Point> affectedPoints = new HashSet <Point>(); foreach (var s in gluedDomain) { affectedPoints.Add(s.Position); foreach (var neig in s.Neighbors) { if (!neig.IsRealNode) { affectedPoints.Add(neig.Position); } } } //TimeMeasurer.DebugOutput("gluing nodes"); metroGraphData.Initialize(false); SimulatedAnnealing.FixRouting(metroGraphData, bundlingSettings, affectedPoints); return(true); }
/// <summary> /// apply a number of heuristics to improve current routing /// </summary> internal static void FixRouting(MetroGraphData metroGraphData, BundlingSettings bundlingSettings) { // #if DEBUG && TEST_MSAGL // Debug.Assert(metroGraphData.looseIntersections.HubPositionsAreOK()); // #endif //TimeMeasurer.DebugOutput("Initial cost = " + CostCalculator.Cost(metroGraphData, bundlingSettings)); //TimeMeasurer.DebugOutput("Initial cost of forces: " + CostCalculator.CostOfForces(metroGraphData, bundlingSettings)); var adjuster = new NodePositionsAdjuster(metroGraphData, bundlingSettings); adjuster.GlueConflictingNodes(); adjuster.UnglueEdgesFromBundleToSaveInk(true); var step = 0; int MaxSteps = 10; while (++step < MaxSteps) { /*#if DEBUG && TEST_MSAGL * Debug.Assert(metroGraphData.looseIntersections.HubPositionsAreOK()); #endif*/ //heuristics to improve routing bool progress = adjuster.GlueConflictingNodes(); progress |= adjuster.RelaxConstrainedEdges(); progress |= (step <= 3 && adjuster.UnglueEdgesFromBundleToSaveInk(false)); progress |= adjuster.GlueCollinearNeighbors(step); progress |= (step == 3 && adjuster.RemoveDoublePathCrossings()); if (!progress) { break; } } //one SA has to be executed with bundle forces metroGraphData.cdtIntersections.ComputeForcesForBundles = true; adjuster.RemoveDoublePathCrossings(); adjuster.UnglueEdgesFromBundleToSaveInk(true); while (adjuster.GlueConflictingNodes()) { } metroGraphData.Initialize(true); //this time initialize the tight enterables also // HubDebugger.ShowHubs(metroGraphData, bundlingSettings); //TimeMeasurer.DebugOutput("NodePositionsAdjuster stopped after " + step + " steps"); //HubDebugger.ShowHubs(metroGraphData, bundlingSettings, true); //TimeMeasurer.DebugOutput("Final cost: " + CostCalculator.Cost(metroGraphData, bundlingSettings)); //TimeMeasurer.DebugOutput("Final cost of forces: " + CostCalculator.CostOfForces(metroGraphData, bundlingSettings)); }
/// <summary> /// apply a number of heuristics to improve current routing /// </summary> internal static void FixRouting(MetroGraphData metroGraphData, BundlingSettings bundlingSettings) { #if DEBUG && TEST_MSAGL Debug.Assert(metroGraphData.looseIntersections.HubPositionsAreOK()); #endif //TimeMeasurer.DebugOutput("Initial cost = " + CostCalculator.Cost(metroGraphData, bundlingSettings)); //TimeMeasurer.DebugOutput("Initial cost of forces: " + CostCalculator.CostOfForces(metroGraphData, bundlingSettings)); var adjuster = new NodePositionsAdjuster(metroGraphData, bundlingSettings); adjuster.GlueConflictingNodes(); adjuster.UnglueEdgesFromBundleToSaveInk(true); var step = 0; int MaxSteps = 10; while (++step < MaxSteps) { /*#if DEBUG && TEST_MSAGL Debug.Assert(metroGraphData.looseIntersections.HubPositionsAreOK()); #endif*/ //heuristics to improve routing bool progress = adjuster.GlueConflictingNodes(); progress |= adjuster.RelaxConstrainedEdges(); progress |= (step <= 3 && adjuster.UnglueEdgesFromBundleToSaveInk(false)); progress |= adjuster.GlueCollinearNeighbors(step); progress |= (step == 3 && adjuster.RemoveDoublePathCrossings()); if (!progress) break; } //one SA has to be executed with bundle forces metroGraphData.cdtIntersections.ComputeForcesForBundles = true; adjuster.RemoveDoublePathCrossings(); adjuster.UnglueEdgesFromBundleToSaveInk(true); while (adjuster.GlueConflictingNodes()) { } metroGraphData.Initialize(true); //this time initialize the tight enterables also // HubDebugger.ShowHubs(metroGraphData, bundlingSettings); //TimeMeasurer.DebugOutput("NodePositionsAdjuster stopped after " + step + " steps"); //HubDebugger.ShowHubs(metroGraphData, bundlingSettings, true); //TimeMeasurer.DebugOutput("Final cost: " + CostCalculator.Cost(metroGraphData, bundlingSettings)); //TimeMeasurer.DebugOutput("Final cost of forces: " + CostCalculator.CostOfForces(metroGraphData, bundlingSettings)); }