internal void UpdateCostCache(Station node) { RectangleNode <CdtTriangle> cdtTree = cdt.GetCdtTree(); node.CdtTriangle = cdtTree.FirstHitNode(node.Position, Test).UserData; node.cachedIdealRadius = HubRadiiCalculator.CalculateIdealHubRadiusWithNeighbors(metroGraphData, bundlingSettings, node); node.cachedRadiusCost = costCalculator.RadiusCost(node, node.Position); node.cachedBundleCost = 0; foreach (var adj in node.Neighbors) { if (!adj.IsRealNode) { adj.cachedIdealRadius = HubRadiiCalculator.CalculateIdealHubRadiusWithNeighbors(metroGraphData, bundlingSettings, adj); adj.cachedRadiusCost = costCalculator.RadiusCost(adj, adj.Position); } StationEdgeInfo edgeInfo = metroGraphData.GetIjInfo(node, adj); adj.cachedBundleCost -= edgeInfo.cachedBundleCost; edgeInfo.cachedBundleCost = costCalculator.BundleCost(node, adj, node.Position); node.cachedBundleCost += edgeInfo.cachedBundleCost; adj.cachedBundleCost += edgeInfo.cachedBundleCost; } }
internal double RadiusCost(Station node, Point newPosition) { double idealR; if (ApproximateComparer.Close(node.Position, newPosition)) { idealR = node.cachedIdealRadius; } else { idealR = HubRadiiCalculator.CalculateIdealHubRadiusWithNeighbors(metroGraphData, bundlingSettings, node, newPosition); } List <Tuple <Polyline, Point> > touchedObstacles; if (!metroGraphData.looseIntersections.HubAvoidsObstacles(node, newPosition, idealR, out touchedObstacles)) { return(Inf); } double cost = 0; foreach (var d in touchedObstacles) { double dist = (d.Item2 - newPosition).Length; cost += RError(idealR, dist, bundlingSettings); } return(cost); }
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); }
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 GetCurrentHubRadius(Station node) { if (node.IsRealNode) { return(node.BoundaryCurve.BoundingBox.Diagonal / 2); } else { double idealR = node.cachedIdealRadius = HubRadiiCalculator.CalculateIdealHubRadiusWithNeighbors(this.metroGraphData, this.bundlingSettings, node); double r = metroGraphData.looseIntersections.GetMinimalDistanceToObstacles(node, node.Position, idealR); Debug.Assert(r <= idealR); foreach (var adj in node.Neighbors) { r = Math.Min(r, (node.Position - adj.Position).Length); } return(r); } }
internal void InitializeCostCache() { foreach (var v in metroGraphData.VirtualNodes()) { v.cachedIdealRadius = HubRadiiCalculator.CalculateIdealHubRadiusWithNeighbors(metroGraphData, bundlingSettings, v); v.cachedRadiusCost = costCalculator.RadiusCost(v, v.Position); v.cachedBundleCost = 0; } foreach (var edge in metroGraphData.VirtualEdges()) { var v = edge.Item1; var u = edge.Item2; StationEdgeInfo edgeInfo = metroGraphData.GetIjInfo(v, u); edgeInfo.cachedBundleCost = costCalculator.BundleCost(v, u, v.Position); v.cachedBundleCost += edgeInfo.cachedBundleCost; u.cachedBundleCost += edgeInfo.cachedBundleCost; } }
IEnumerable <DebugCurve> IdealHubsWithNeighbors() { return(mgd.VirtualNodes().Select(station => new DebugCurve(200, 1, "black", CurveFactory.CreateCircle(HubRadiiCalculator.CalculateIdealHubRadiusWithNeighbors(mgd, bundlingSettings, station), station.Position)))); }