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); }
internal static double GetMinRadiusForTwoAdjacentBundlesOld(double r, Station node, Point nodePosition, Station adj0, Station adj1, MetroGraphData metroGraphData, BundlingSettings bundlingSettings) { double w0 = metroGraphData.GetWidth(node, adj0, bundlingSettings.EdgeSeparation); double w1 = metroGraphData.GetWidth(node, adj1, bundlingSettings.EdgeSeparation); return(GetMinRadiusForTwoAdjacentBundlesOld(r, nodePosition, adj0.Position, adj1.Position, w0, w1, metroGraphData, bundlingSettings)); }
/// <summary> /// direction to push a bundle away from obstacle /// </summary> Point BuildForceForBundle(Station node) { var direction = new Point(); foreach (var adj in node.Neighbors) { double idealWidth = metroGraphData.GetWidth(node, adj, bundlingSettings.EdgeSeparation); List <Tuple <Point, Point> > closestPoints; bool res = metroGraphData.cdtIntersections.BundleAvoidsObstacles(node, adj, node.Position, adj.Position, idealWidth / 2, out closestPoints); if (!res) { #if DEBUG && TEST_MSAGL HubDebugger.ShowHubs(metroGraphData, bundlingSettings, new LineSegment(node.Position, adj.Position)); #endif } //Debug.Assert(res); //todo : still unsolved foreach (var d in closestPoints) { double dist = (d.Item1 - d.Item2).Length; Debug.Assert(ApproximateComparer.LessOrEqual(dist, idealWidth / 2)); double lforce = 2.0 * (1.0 - dist / (idealWidth / 2)); Point dir = -(d.Item1 - d.Item2).Normalize(); direction += dir * lforce; } } //derivative Point force = direction * bundlingSettings.BundleRepulsionImportance; return(force); }
/// <summary> /// Returns the ideal radius of the hub /// </summary> static double CalculateIdealHubRadius(MetroGraphData metroGraphData, BundlingSettings bundlingSettings, Station node) { double r = 1.0; foreach (Station adj in node.Neighbors) { double width = metroGraphData.GetWidth(adj, node, bundlingSettings.EdgeSeparation); double nr = width / 2.0 + bundlingSettings.EdgeSeparation; r = Math.Max(r, nr); } r = Math.Min(r, 2 * bundlingSettings.MaxHubRadius); return(r); }
IEnumerable <DebugCurve> IdealBundles() { List <DebugCurve> dc = new List <DebugCurve>(); foreach (var edge in mgd.VirtualEdges()) { var node = edge.Item1; var adj = edge.Item2; double width = mgd.GetWidth(node, adj, bundlingSettings.EdgeSeparation); dc.Add(new DebugCurve(0.1, "black", Intersections.Create4gon(node.Position, adj.Position, width, width))); } return(dc); }
internal double BundleCost(Station node, Station adj, Point newPosition) { double idealWidth = metroGraphData.GetWidth(node, adj, bundlingSettings.EdgeSeparation); List <Tuple <Point, Point> > closestDist; double cost = 0; //find conflicting obstacles if (!metroGraphData.cdtIntersections.BundleAvoidsObstacles(node, adj, newPosition, adj.Position, idealWidth, out closestDist)) { return(Inf); } foreach (var pair in closestDist) { double dist = (pair.Item1 - pair.Item2).Length; cost += BundleError(idealWidth / 2, dist, bundlingSettings); } return(cost); }
internal static double GetMinRadiusForTwoAdjacentBundlesOld(double r, Station node, Point nodePosition, Station adj0, Station adj1, MetroGraphData metroGraphData, BundlingSettings bundlingSettings) { double w0 = metroGraphData.GetWidth(node, adj0, bundlingSettings.EdgeSeparation); double w1 = metroGraphData.GetWidth(node, adj1, bundlingSettings.EdgeSeparation); return GetMinRadiusForTwoAdjacentBundlesOld(r, nodePosition, adj0.Position, adj1.Position, w0, w1, metroGraphData, bundlingSettings); }
/// <summary> /// Returns the ideal radius of the hub /// </summary> static double CalculateIdealHubRadius(MetroGraphData metroGraphData, BundlingSettings bundlingSettings, Station node) { double r = 1.0; foreach (Station adj in node.Neighbors) { double width = metroGraphData.GetWidth(adj, node, bundlingSettings.EdgeSeparation); double nr = width / 2.0 + bundlingSettings.EdgeSeparation; r = Math.Max(r, nr); } r = Math.Min(r, 2 * bundlingSettings.MaxHubRadius); return r; }