double GetInkgain(PolylinePoint pp, Dictionary <PointPair, Set <Metroline> > segsToPolylines, Point a, Point b, Point c) { Set <Metroline> abPolylines, bcPolylines, abcPolylines; FindPolylines(pp, segsToPolylines, out abPolylines, out bcPolylines, out abcPolylines); double gain = 0; //ink double oldInk = ink; double newInk = ink; double ab = (a - b).Length; double bc = (b - c).Length; double ac = (a - c).Length; if (abPolylines.Count == abcPolylines.Count) { newInk -= ab; } if (bcPolylines.Count == abcPolylines.Count) { newInk -= bc; } if (!segsToPolylines.ContainsKey(new PointPair(a, c)) || segsToPolylines[new PointPair(a, c)].Count == 0) { newInk += ac; } gain += CostCalculator.InkError(oldInk, newInk, bundlingSettings); //path lengths foreach (var metroline in abcPolylines) { double oldLength = polylineLength[metroline]; double newLength = polylineLength[metroline]; newLength -= ab + bc - ac; gain += CostCalculator.PathLengthsError(oldLength, newLength, metroline.IdealLength, bundlingSettings); } //radii double nowR = GetCurrentHubRadius(metroGraphData.PointToStations[a]); double widthABC = metroGraphData.GetWidth(abcPolylines, bundlingSettings.EdgeSeparation); double widthABD = metroGraphData.GetWidth(abPolylines - abcPolylines, bundlingSettings.EdgeSeparation); double idealR = HubRadiiCalculator.GetMinRadiusForTwoAdjacentBundles(nowR, a, c, b, widthABC, widthABD, metroGraphData, bundlingSettings); if (idealR > nowR) { gain -= CostCalculator.RError(idealR, nowR, bundlingSettings); } //check opposite side nowR = GetCurrentHubRadius(metroGraphData.PointToStations[c]); double widthCBD = metroGraphData.GetWidth(bcPolylines - abcPolylines, bundlingSettings.EdgeSeparation); idealR = HubRadiiCalculator.GetMinRadiusForTwoAdjacentBundles(nowR, c, b, a, widthCBD, widthABC, metroGraphData, bundlingSettings); if (idealR > nowR) { gain -= CostCalculator.RError(idealR, nowR, bundlingSettings); } return(gain); }
SimulatedAnnealing(MetroGraphData metroGraphData, BundlingSettings bundlingSettings) { this.metroGraphData = metroGraphData; this.bundlingSettings = bundlingSettings; costCalculator = new CostCalculator(metroGraphData, bundlingSettings); cache = new IntersectionCache(metroGraphData, bundlingSettings, costCalculator, metroGraphData.Cdt); }
public IntersectionCache(MetroGraphData metroGraphData, BundlingSettings bundlingSettings, CostCalculator costCalculator, Cdt cdt) { Debug.Assert(cdt!=null); this.metroGraphData = metroGraphData; this.bundlingSettings = bundlingSettings; this.costCalculator = costCalculator; this.cdt = cdt; }
public IntersectionCache(MetroGraphData metroGraphData, BundlingSettings bundlingSettings, CostCalculator costCalculator, Cdt cdt) { Debug.Assert(cdt != null); this.metroGraphData = metroGraphData; this.bundlingSettings = bundlingSettings; this.costCalculator = costCalculator; this.cdt = cdt; }
double Cost() { double cost = 0; foreach (var v in metroGraphData.VirtualNodes()) { double idealR = v.cachedIdealRadius; cost += CostCalculator.RError(idealR, v.Radius, bundlingSettings); } return(cost); }
double ComputeCostDeltaAfterEdgeGluing(Station node, Station a, Station b, Point newp) { double gain = 0; //ink double oldInk = metroGraphData.Ink; double newInk = metroGraphData.Ink - (node.Position - b.Position).Length - (node.Position - a.Position).Length + (node.Position - newp).Length + (newp - a.Position).Length + (newp - b.Position).Length; gain += CostCalculator.InkError(oldInk, newInk, bundlingSettings); //path lengths foreach (var metroline in metroGraphData.GetIjInfo(node, b).Metrolines) { double oldLength = metroline.Length; double newLength = metroline.Length - (node.Position - b.Position).Length + (node.Position - newp).Length + (newp - b.Position).Length; gain += CostCalculator.PathLengthsError(oldLength, newLength, metroline.IdealLength, bundlingSettings); } foreach (var metroline in metroGraphData.GetIjInfo(node, a).Metrolines) { double oldLength = metroline.Length; double newLength = metroline.Length - (node.Position - a.Position).Length + (node.Position - newp).Length + (newp - a.Position).Length; gain += CostCalculator.PathLengthsError(oldLength, newLength, metroline.IdealLength, bundlingSettings); } //also compute radii gain //double nowR = Math.Min(GetCurrentHubRadius(node), (node.Position - newp).Length); //double id2 = HubRadiiCalculator.CalculateIdealHubRadiusWithNeighbors(metroGraphData, bundlingSettings, node); double id2 = node.cachedIdealRadius; double nowR = GetCurrentHubRadius(node); double idealR = HubRadiiCalculator.GetMinRadiusForTwoAdjacentBundles(nowR, node, node.Position, a, b, metroGraphData, bundlingSettings); if (idealR > nowR) { gain += CostCalculator.RError(idealR, nowR, bundlingSettings); } if (id2 > (node.Position - newp).Length && !node.IsRealNode) { gain -= CostCalculator.RError(id2, (node.Position - newp).Length, bundlingSettings); } return(gain); }
double ComputeCostDeltaAfterNodeGluing(Station i, Station j, Dictionary <Station, Station> gluingMap) { double d = (i.Position - j.Position).Length; if (i.Radius >= d || j.Radius >= d) { return(1.0); } double gain = 0; //ink double oldInk = metroGraphData.Ink; double newInk = metroGraphData.Ink - (j.Position - i.Position).Length; foreach (var adj in i.Neighbors) { var k = Glued(adj, gluingMap); newInk -= (k.Position - i.Position).Length; newInk += (metroGraphData.RealEdgeCount(k, j) == 0 ? (k.Position - j.Position).Length : 0); } gain += CostCalculator.InkError(oldInk, newInk, bundlingSettings); //path lengths foreach (var metroInfo in metroGraphData.MetroNodeInfosOfNode(i)) { double oldLength = metroInfo.Metroline.Length; double newLength = metroInfo.Metroline.Length; PolylinePoint pi = metroInfo.PolyPoint; PolylinePoint pa = pi.Prev; PolylinePoint pb = pi.Next; newLength -= (pa.Point - i.Position).Length + (pb.Point - i.Position).Length; newLength += (pa.Point - j.Position).Length + (pb.Point - j.Position).Length; gain += CostCalculator.PathLengthsError(oldLength, newLength, metroInfo.Metroline.IdealLength, bundlingSettings); } return(gain); }
bool FixRouting(HashSet <Point> changedPoints) { stationsForOptimizations = GetStationsForOptimizations(changedPoints); cache.InitializeCostCache(); double step = MaxStep; double energy = double.PositiveInfinity; List <Point> x = new List <Point>(metroGraphData.VirtualNodes().Select(v => v.Position)); int iteration = 0; while (iteration++ < MaxIterations) { bool coordinatesChanged = TryMoveNodes(); //TimeMeasurer.DebugOutput(" #iter = " + iteration + " moved: " + cnt + "/" + metroGraphData.VirtualNodes().Count() + " step: " + step); if (iteration <= 1 && !coordinatesChanged) { return(false); } if (!coordinatesChanged) { break; } double oldEnergy = energy; energy = CostCalculator.Cost(metroGraphData, bundlingSettings); //TimeMeasurer.DebugOutput("energy: " + energy); step = UpdateMaxStep(step, oldEnergy, energy); List <Point> oldX = x; x = new List <Point>(metroGraphData.VirtualNodes().Select(v => v.Position)); if (step < MinStep || Converged(step, oldX, x)) { break; } } //TimeMeasurer.DebugOutput("SA completed after " + iteration + " iterations"); return(true); }