double SeparationCost(BundleInfo bundleInfo) {
     return SeparationCostForBundleBase(bundleInfo.SourceBase) + SeparationCostForBundleBase(bundleInfo.TargetBase);
 }
        void AllocateBundleBases() {
            externalBases = new Dictionary<ICurve, List<BundleBase>>();
            internalBases = new Dictionary<ICurve, List<BundleBase>>();
            Bundles = new List<BundleInfo>();

            foreach (var station in metroGraphData.Stations) {
                if (station.BoundaryCurve == null)
                    station.BoundaryCurve = new Ellipse(station.Radius, station.Radius, station.Position);
            }

            foreach (var station in metroGraphData.Stations) {
                foreach (Station neighbor in station.Neighbors) {
                    if (station < neighbor) {
                        var bb = new BundleBase(metroGraphData.RealEdgeCount(station, neighbor), station.BoundaryCurve, station.Position, station.IsRealNode, neighbor.SerialNumber);
                        station.BundleBases[neighbor] = bb;

                        var bb2 = new BundleBase(metroGraphData.RealEdgeCount(station, neighbor), neighbor.BoundaryCurve, neighbor.Position, neighbor.IsRealNode, station.SerialNumber);
                        neighbor.BundleBases[station] = bb2;

                        if (Curve.PointRelativeToCurveLocation(neighbor.Position, station.BoundaryCurve) != PointLocation.Outside) {
                            bb.IsParent = true;
                            CollectionUtilities.AddToMap(internalBases, station.BoundaryCurve, bb);
                            CollectionUtilities.AddToMap(externalBases, neighbor.BoundaryCurve, bb2);
                        }
                        else if (Curve.PointRelativeToCurveLocation(station.Position, neighbor.BoundaryCurve) != PointLocation.Outside) {
                            bb2.IsParent = true;
                            CollectionUtilities.AddToMap(externalBases, station.BoundaryCurve, bb);
                            CollectionUtilities.AddToMap(internalBases, neighbor.BoundaryCurve, bb2);
                        }
                        else {
                            CollectionUtilities.AddToMap(externalBases, station.BoundaryCurve, bb);
                            CollectionUtilities.AddToMap(externalBases, neighbor.BoundaryCurve, bb2);
                        }

                        Set<Polyline> obstaclesToIgnore = metroGraphData.tightIntersections.ObstaclesToIgnoreForBundle(station, neighbor);
                        var bundle = new BundleInfo(bb, bb2, obstaclesToIgnore, bundlingSettings.EdgeSeparation, metroOrdering.GetOrder(station, neighbor).Select(l => l.Width / 2).ToArray());
                        bb.OutgoingBundleInfo = bb2.IncomingBundleInfo = bundle;
                        Bundles.Add(bundle);
                    }

                }
            }

            //neighbors
            SetBundleBaseNeighbors();
        }
        double CenterCost(BundleInfo bundleInfo) {
            if (!bundleInfo.SourceBase.BelongsToRealNode && !bundleInfo.TargetBase.BelongsToRealNode)
                return 0;

            return CenterCost(bundleInfo.SourceBase) + CenterCost(bundleInfo.TargetBase);
        }
 double AssymetryCost(BundleInfo bundleInfo) {
     return GetAssymetryCostForBase(bundleInfo.SourceBase) + GetAssymetryCostForBase(bundleInfo.TargetBase);
 }
 //this is an accelerated version of the above function (calculate cost partly)
 double Cost(BundleInfo bundleInfo, double limit) {
     double cost = 0;
     cost += CenterCoeff * CenterCost(bundleInfo);
     if (cost > limit)
         return cost;
     cost += SeparationCoeff * SeparationCost(bundleInfo);
     if (cost > limit)
         return cost;
     cost += SqueezeCoeff * SqueezeCost(bundleInfo);
     if (cost > limit)
         return cost;
     cost += AssymetryCoeff * AssymetryCost(bundleInfo);
     return cost;
 }
        double SqueezeCost(BundleInfo bundleInfo) {
            var middleLineDir = (bundleInfo.TargetBase.MidPoint - bundleInfo.SourceBase.MidPoint).Normalize();
            var perp = middleLineDir.Rotate90Ccw();
            var projecton0 = Math.Abs((bundleInfo.SourceBase.RightPoint - bundleInfo.SourceBase.LeftPoint) * perp);
            var projecton1 = Math.Abs((bundleInfo.TargetBase.RightPoint - bundleInfo.TargetBase.LeftPoint) * perp);

            double del0 = Math.Abs(bundleInfo.TotalRequiredWidth - projecton0) / bundleInfo.TotalRequiredWidth;
            double del1 = Math.Abs(bundleInfo.TotalRequiredWidth - projecton1) / bundleInfo.TotalRequiredWidth;
            double del = Math.Abs(projecton0 - projecton1) / bundleInfo.TotalRequiredWidth;

            double cost = Math.Exp(del0 * 10) - 1 + Math.Exp(del1 * 10) - 1;

            cost += del;
            return cost;
        }
 double Cost(BundleInfo bundleInfo) {
     return
         SeparationCoeff * SeparationCost(bundleInfo) +
         SqueezeCoeff * SqueezeCost(bundleInfo) +
         AssymetryCoeff * AssymetryCost(bundleInfo) +
         CenterCoeff * CenterCost(bundleInfo);
 }
        double DeltaWithChangedAngles(int rotationOfSourceRigthPoint, int rotationOfSourceLeftPoint, int rotationOfTargetRigthPoint, int rotationOfTargetLeftPoint,
            BundleInfo bundleInfo, double bundleCost, double parameterChange) {
            if (!bundleInfo.RotationIsLegal(rotationOfSourceRigthPoint, rotationOfSourceLeftPoint, rotationOfTargetRigthPoint, rotationOfTargetLeftPoint, parameterChange))
                return 0;

            bundleInfo.RotateBy(rotationOfSourceRigthPoint, rotationOfSourceLeftPoint, rotationOfTargetRigthPoint, rotationOfTargetLeftPoint, parameterChange);
            var newCost = Cost(bundleInfo, bundleCost);

            //restoring
            bundleInfo.RotateBy(-rotationOfSourceRigthPoint, -rotationOfSourceLeftPoint, -rotationOfTargetRigthPoint, -rotationOfTargetLeftPoint, parameterChange);

            return bundleCost - newCost;
        }
        bool OptimizeBundle(BundleInfo bundleInfo, double parameterChange, ref double cost) {
            double bundleCost = Cost(bundleInfo);
            if (bundleCost < CostThreshold)
                return false;

            //choose the best step
            double bestDelta = 0;
            int bestI = -1, bestJ = -1;

            for (int i = 0; i < Deltas.Length - 1; i++) {
                double delta = DeltaWithChangedAngles(Deltas[i][0], Deltas[i][1], 0, 0, bundleInfo, bundleCost, parameterChange);
                if (delta > CostDeltaThreshold && delta > bestDelta) {
                    bestI = i;
                    bestJ = Deltas.Length - 1;
                    bestDelta = delta;
                }

                delta = DeltaWithChangedAngles(0, 0, Deltas[i][0], Deltas[i][1], bundleInfo, bundleCost, parameterChange);
                if (delta > CostDeltaThreshold && delta > bestDelta) {
                    bestI = Deltas.Length - 1;
                    bestJ = i;
                    bestDelta = delta;
                }
            }

            if (bestDelta < CostDeltaThreshold)
                return false;
            //do the change
            cost -= bestDelta;

            bundleInfo.RotateBy(Deltas[bestI][0], Deltas[bestI][1], Deltas[bestJ][0], Deltas[bestJ][1], parameterChange);

            return true;
        }
Пример #10
0
 double SeparationCost(BundleInfo bundleInfo)
 {
     return(SeparationCostForBundleBase(bundleInfo.SourceBase) + SeparationCostForBundleBase(bundleInfo.TargetBase));
 }
Пример #11
0
 double AssymetryCost(BundleInfo bundleInfo)
 {
     return(GetAssymetryCostForBase(bundleInfo.SourceBase) + GetAssymetryCostForBase(bundleInfo.TargetBase));
 }