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);
        }