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);
        }
Beispiel #2
0
        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);
        }
Beispiel #4
0
        /// <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;
        }