public IntersectionCache(MetroGraphData metroGraphData, BundlingSettings bundlingSettings, CostCalculator costCalculator, Cdt cdt) {
     Debug.Assert(cdt!=null);
     this.metroGraphData = metroGraphData;
     this.bundlingSettings = bundlingSettings;
     this.costCalculator = costCalculator;
     this.cdt = cdt;
 }
 internal IEnumerable<Point> Calculate(){
     if (BoundingBox.Width==0)
         FillBoundingBoxWithSites();
     Cdt cdt = new Cdt(cites, null,null);
     cdt.Run();
     var triangles = cdt.GetTriangles();
     foreach (var triangle in triangles)
         AddVoronoiCite(triangle);
     return voronoiSiteTree.GetAllLeaves();
 }
        /// <summary>
        /// Computes the minimum spanning tree on a DT with given weights.
        /// </summary>
        /// <param name="cdt"></param>
        /// <param name="weights"></param>
        /// <returns></returns>
        static internal List<CdtEdge> GetMstOnCdt(Cdt cdt, Func<CdtEdge, double> weights) {
            var siteArray = cdt.PointsToSites.Values.ToArray();
            var siteIndex = new Dictionary<CdtSite, int>();
            for (int i = 0; i < siteArray.Length; i++)
                siteIndex[siteArray[i]] = i;

            Dictionary<IntPair, CdtEdge> intPairsToCdtEdges = GetEdges(siteArray, siteIndex);

            var graph = new BasicGraph<IEdge>( intPairsToCdtEdges.Keys, siteArray.Length);

            var mstOnBasicGraph = new MinimumSpanningTreeByPrim(graph, intPair => weights(intPairsToCdtEdges[(IntPair)intPair]), 0);

            return new List<CdtEdge>(mstOnBasicGraph.GetTreeEdges().Select(e=>intPairsToCdtEdges[(IntPair)e]));
        }
        internal MetroGraphData(EdgeGeometry[] regularEdges,
            RectangleNode<Polyline> looseTree, RectangleNode<Polyline> tightTree,
            BundlingSettings bundlingSettings, Cdt cdt,
            Dictionary<EdgeGeometry, Set<Polyline>> edgeLooseEnterable, Dictionary<EdgeGeometry, Set<Polyline>> edgeTightEnterable, Func<Port, Polyline> loosePolylineOfPort) {
            //Debug.Assert(cdt != null);
            this.regularEdges = regularEdges;
            if (cdt != null)
                Cdt = cdt;
            else
                Cdt = BundleRouter.CreateConstrainedDelaunayTriangulation(looseTree);

            EdgeLooseEnterable = edgeLooseEnterable;
            EdgeTightEnterable = edgeTightEnterable;
            LoosePolylineOfPort = loosePolylineOfPort;

            looseIntersections = new Intersections(this, bundlingSettings, looseTree, station => station.EnterableLoosePolylines);
            tightIntersections = new Intersections(this, bundlingSettings, tightTree, station => station.EnterableTightPolylines);
            cdtIntersections = new CdtIntersections(this, bundlingSettings);

            Initialize(false);
        }
 static void TestTriangulationOnSmallGraph(ArgsParser.ArgsParser parser) {
     var polyline = new Polyline(
         new Point(20.8211097717285, 40.9088821411133),
         new Point(21.4894065856934, 46.6845321655273),
         new Point(22.9755554199219, 41.3355484008789),
         new Point(20.8211097717285, 40.9088821411133));
     var polylines = new List<Polyline>();
     polylines.Add(polyline);
     var points = new List<Point>();
     var centroid = new Point(21.7620239257813, 42.9763209025065);
     points.Add(centroid);
     var testCdt = new Cdt(points, polylines, null);
     testCdt.Run();
 }
        static void Triangulation(bool reverseX) {
#if DEBUG
            DisplayGeometryGraph.SetShowFunctions();
#endif
            int r = reverseX ? -1 : 1;
            IEnumerable<Point> points = Points().Select(p => new Point(r*p.X, p.Y));

            var poly = (Polyline) RussiaPolyline.GetTestPolyline().ScaleFromOrigin(1, 1);
            var cdt = new Cdt(null, new[] {poly}, null);
            cdt.Run();
#if DEBUG
            CdtSweeper.ShowFront(cdt.GetTriangles(), null, null, null);
#endif
        }
        private CdtEdge FindEdge(PolylinePoint a, PolylinePoint b, Cdt cdt) {
            int aIsAboveB = Cdt.Above(a.Point, b.Point);
            System.Diagnostics.Debug.Assert(aIsAboveB != 0);
            if (aIsAboveB > 0) {
                foreach (var e in cdt.FindSite(a.Point).Edges)
                    if (e.lowerSite.Point == b.Point)
                        return e;
            } else {
                foreach (var e in cdt.FindSite(b.Point).Edges)
                    if (e.lowerSite.Point == a.Point)
                        return e;           
            }

            throw new InvalidOperationException("cannot find an edge of a polyline in the tessellation");

        }
        static void TestTriangulationOnPolys() {
            FileStream stream = File.Open("polys", FileMode.Open);
            var bformatter = new BinaryFormatter();

            var polys = (Polyline[]) bformatter.Deserialize(stream);
            stream.Close();
            var cdt = new Cdt(null, polys, null);
            cdt.Run();
        }
        private void CleanUpExternalTriangles(Shape shape, ref Set<CdtTriangle> triangles, Cdt cdt) {
            Set<CdtTriangle> removedTriangles = new Set<CdtTriangle>();
            var poly = (Polyline)shape.BoundaryCurve;
            for (var p = poly.StartPoint; p.Next != null; p = p.Next)
                FillRemovedForExternalTriangle(p, p.Next, removedTriangles, cdt);

            FillRemovedForExternalTriangle(poly.EndPoint, poly.StartPoint, removedTriangles, cdt);
            //var l = new List<DebugCurve>();
            //l.Add(new DebugCurve(100, 1, "black", poly));
            //l.AddRange(removedTriangles.Select(t => new DebugCurve(100, 0.1, "red", new Polyline(t.Sites.Select(s => s.Point).ToArray()) { Closed = true })));
            //LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(l);
            triangles -= removedTriangles;
        }
        private void FillRemovedForExternalTriangle(PolylinePoint a, PolylinePoint b, Set<CdtTriangle> removedTriangles, Cdt cdt) {
            CdtEdge e = FindEdge(a, b, cdt);
            if (e.CcwTriangle == null || e.CwTriangle == null) return;

            bool aligned = a.Point == e.upperSite.Point;
            if (aligned) {               
//                LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(100, 0.1, "black", a.Polyline), new DebugCurve(100, 0.1, "red", new Polyline(e.CcwTriangle.Sites.Select(s => s.Point).ToArray()) { Closed = true }));
                FillRemovedConnectedRegion(e.CcwTriangle, removedTriangles);
            } else {
  //              LayoutAlgorithmSettings.ShowDebugCurves(new DebugCurve(100, 0.1, "black", a.Polyline), new DebugCurve(100,0.1,"red", new Polyline(e.CwTriangle.Sites.Select(s => s.Point).ToArray()) { Closed = true }));
                FillRemovedConnectedRegion(e.CwTriangle, removedTriangles);
            }

        }
        public void SmallTriangulation() {
#if DEBUG&& TEST_MSAGL
            GraphViewerGdi.DisplayGeometryGraph.SetShowFunctions();
#endif
            var cdt = new Cdt(Points(), null, new []{new SymmetricTuple<Point>(new Point(109,202),new Point(506,135) ),
            new SymmetricTuple<Point>(new Point(139,96),new Point(452,96) )}.ToList());
            cdt.Run();
        }
        bool DoSingleIteration(int currentIteration, ref bool scanlinePhase) {
            List<Tuple<Point, object>> sites =
                nodePositions.Select((p, index) => new Tuple<Point, object>(p, index)).ToList();
            var triangulation = new Cdt(sites);
            triangulation.Run();

            List<Tuple<int, int, double, double>> proximityEdgesWithDistance;
            int numCrossings = GetProximityEdgesWithDistance(_nodes, triangulation, nodeSizes,
                                                             out proximityEdgesWithDistance);

            if (scanlinePhase || numCrossings == 0) {
                scanlinePhase = true;
                numCrossings = CompleteProximityGraphWithRTree(ref numCrossings, proximityEdgesWithDistance);
            }
#if DEBUG
            int realCrossings = CountCrossingsWithRTree(nodeSizes);
            crossingsOverTime.Add(realCrossings);
            if (currentIteration%10 == 0)
                Console.WriteLine("Scanline: {0}, Crossings: {1}", scanlinePhase, numCrossings);
#endif

            if (numCrossings == 0) return true;

            AddStressFromProximityEdges(StressSolver, proximityEdgesWithDistance);
            List<Point> newPositions = StressSolver.IterateAll();

            ShowCurrentMovementVectors(currentIteration, nodeSizes, nodePositions, newPositions,
                                       proximityEdgesWithDistance,
                                       null);

            UpdatePointsAndBoxes(newPositions);
            //clear the data structures
            StressSolver.ClearVotings();
#if DEBUG
            for (int i = 0; i < nodePositions.Length; i++) {
                trajectories[i].AddPoint(newPositions[i]);
            }
#endif
            return false;
        }
        void Triangulate(int n, double size) {
            var random = new Random(n);
            var w = n * size;
            var cdt = new Cdt(PointsForCdt(random, n, w), null, SegmentsForCdt(w).ToList());
            cdt.Run();
#if DEBUG&&TEST_MSAGL
            CdtSweeper.ShowFront(cdt.GetTriangles(), null, null,null);
#endif
        }
        public void InitCdt() {

            InitSegmentTree();

            for (int i = 0; i < fixedRectangles.Length; i++) {
                Point p = Round( fixedRectangles[i].Center );
                var node = new TreeNode { isFixed = true, rectId = i, rect = fixedRectangles[i], sitePoint = p, type = SiteType.RectFixed };
                if (nodeLabelsFixed != null)
                {
                    node.label = nodeLabelsFixed[i];
                }
                pointToTreeNode[p] = node;
                _rectNodesRtree.Add(node.rect, node);
                _fixedRectanglesTree.Add(fixedRectangles[i], node);
            }

            for (int i = 0; i < moveableRectangles.Length; i++)
            {
                Point p = Round(moveableRectangles[i].Center);
                var node = new TreeNode { isFixed = false, rectId = i, rect = moveableRectangles[i], sitePoint = p, type = SiteType.RectMoveable };
                if (nodeLabelsMoveable != null)
                {
                    node.label = nodeLabelsMoveable[i];
                }

                pointToTreeNode[p] = node;
                _rectNodesRtree.Add(node.rect, node);
                _moveableRectanglesTree.Add(moveableRectangles[i], node);
            }

            var sites = pointToTreeNode.Keys.ToList();

            //AddSitesForBoxSegmentOverlaps(sites);            

            cdt = new Cdt(sites, null, null);
            cdt.Run();
        }
 static Cdt GetConstrainedDelaunayTriangulation(IEnumerable<Polyline> obstacles) {
     var constrainedDelaunayTriangulation = new Cdt(null, obstacles, null);
     constrainedDelaunayTriangulation.Run();
     return constrainedDelaunayTriangulation;
 }
 internal FlipCollapser(MetroGraphData metroGraphData, BundlingSettings bundlingSettings, Cdt cdt) {
     this.metroGraphData = metroGraphData;
     this.bundlingSettings = bundlingSettings;
     this.cdt = cdt;
 }
 internal SdShortestPath(Func<EdgeGeometry, List<Shape>> makeTransparentShapesOfEdgeGeometryAndGetTheShapes, Cdt cdt, Set<CdtEdge> gates) {
     MakeTransparentShapesOfEdgeGeometry = makeTransparentShapesOfEdgeGeometryAndGetTheShapes;
     Cdt = cdt;
     Gates = gates;
 }
        Set<CdtEdge> FindCdtGates(Cdt cdt) {
            Dictionary<ICurve, Shape> loosePolylinesToLooseParentShapeMap = new Dictionary<ICurve, Shape>();
        
            CreateTheMapToParentLooseShapes(root, loosePolylinesToLooseParentShapeMap);
            //looking for Cdt edges connecting two siblings; only those we define as gates
            var gates = new Set<CdtEdge>();
            foreach (var cdtSite in cdt.PointsToSites.Values) {
                foreach (var cdtEdge in cdtSite.Edges) {
                    
                    if(cdtEdge.CwTriangle==null && cdtEdge.CcwTriangle==null)
                        continue;

                    var a = (Polyline)cdtSite.Owner;
                    var b = (Polyline)cdtEdge.lowerSite.Owner;
                    if (a == b) continue;
                    Shape aParent;
                    Shape bParent;
                    if(loosePolylinesToLooseParentShapeMap.TryGetValue(a, out aParent) 
                        && loosePolylinesToLooseParentShapeMap.TryGetValue(b, out bParent) && aParent==bParent)
                        gates.Insert(cdtEdge);
                }
            }
           //CdtSweeper.ShowFront(cdt.GetTriangles(), null,
             //                    gates.Select(g => new LineSegment(g.upperSite.Point, g.lowerSite.Point)), null);
            return gates;
        }
        public void TestRepeatedSite() {
            //in this method the triangulation is such that a repeated site appears in EdgeEvent
            var stream = File.Open("polys", FileMode.Open);
            var bformatter = new BinaryFormatter();

            var polys = (Polyline[])bformatter.Deserialize(stream);
            stream.Close();
            var cdt = new Cdt(null, polys, null);
            cdt.Run();
            TestTriangles(cdt.GetTriangles());
        }
        /// <summary>
        /// 
        /// </summary>
        public static void Test()
        {
#if DEBUG && !SILVERLIGHT && !SHARPKIT
            int count = 100;
            var random = new Random(3);
            var points = new List<Point>();
            for (int i = 0; i < count; i++)
                points.Add(20 * new Point(random.NextDouble(), random.NextDouble()));

            var cdt = new Cdt(points, null, null);
            cdt.Run();
            var ret = GetMstOnCdt(cdt, e => (e.lowerSite.Point - e.upperSite.Point).Length);
            var l = new List<DebugCurve>();
            foreach(var s in cdt.PointsToSites.Values)
                foreach (var e in s.Edges)
                {
                    l.Add(new DebugCurve(100, 0.1, "black", new LineSegment(e.lowerSite.Point, e.upperSite.Point)));
                }
            foreach (var e in ret)
            {
                l.Add(new DebugCurve(100, 0.12, "red", new LineSegment(e.lowerSite.Point, e.upperSite.Point)));
            }
            LayoutAlgorithmSettings.ShowDebugCurvesEnumeration(l);
#endif
        }
        private void TesselateUnderShape(Shape shape) {
            var polys=new List<Polyline>(shape.Children.Select(sh=>(Polyline)sh.BoundaryCurve));
            polys.Add(shape.BoundaryCurve as Polyline);
            var cdt=new Cdt(shapesToInnerPoints[shape], polys,null);
            cdt.Run();
            Set<CdtTriangle> triangles=cdt.GetTriangles();
            cdt.SetInEdges();
            CleanUpTriangles(shape, ref triangles,cdt);
            foreach(var t in triangles){
                AddTriangleToCanvas(t);
            }

        }
Example #22
0
        static CdtEdge Flip(CdtSite pi, CdtEdge edge)
        {
            Debug.Assert(!edge.IsAdjacent(pi));
            Debug.Assert(edge.CcwTriangle.Contains(pi) || edge.CwTriangle.Contains(pi));
            //get surrounding data
            CdtTriangle t, ot;

            if (edge.CcwTriangle.Contains(pi))
            {
                t  = edge.CcwTriangle;
                ot = edge.CwTriangle;
            }
            else
            {
                t  = edge.CwTriangle;
                ot = edge.CcwTriangle;
            }
            Debug.Assert(t.Contains(pi));
            var eIndex      = t.Edges.Index(edge);
            var eOtherIndex = ot.Edges.Index(edge);

            Debug.Assert(eIndex > -1 && eOtherIndex > -1);
            var pl          = ot.Sites[eOtherIndex + 2];
            var edgeBeforPi = t.Edges[eIndex + 1];
            var edgeBeforPl = ot.Edges[eOtherIndex + 1];

            //changing t
            var newEdge = Cdt.GetOrCreateEdge(pi, pl);

            t.Sites[eIndex + 1] = pl;
            t.Edges[eIndex]     = edgeBeforPl;
            t.Edges[eIndex + 1] = newEdge;
            //changing ot
            ot.Sites[eOtherIndex + 1] = pi;
            ot.Edges[eOtherIndex]     = edgeBeforPi;
            ot.Edges[eOtherIndex + 1] = newEdge;
            //orient the new edge and the two edges that move from one triangle to another
            if (edgeBeforPl.lowerSite == pl)
            {
                edgeBeforPl.CcwTriangle = t;
            }
            else
            {
                edgeBeforPl.CwTriangle = t;
            }

            if (edgeBeforPi.lowerSite == pi)
            {
                edgeBeforPi.CcwTriangle = ot;
            }
            else
            {
                edgeBeforPi.CwTriangle = ot;
            }

            if (newEdge.upperSite == pi)
            {
                newEdge.CcwTriangle = ot;
                newEdge.CwTriangle  = t;
            }
            else
            {
                newEdge.CcwTriangle = t;
                newEdge.CwTriangle  = ot;
            }
            Debug.Assert(CheckTriangle(t));
            Debug.Assert(CheckTriangle(t));
            //ShowFlip(pi, t, ot);
            edge.upperSite.Edges.Remove(edge); //forget the edge
            return(newEdge);
        }
 private void CleanUpTriangles(Shape shape, ref Set<CdtTriangle> triangles, Cdt cdt) {
     CleanUpExternalTriangles(shape, ref triangles, cdt);
     foreach (var sh in shape.Children)
         CleanUpInternalTriangles(sh, ref triangles, cdt);
 }
        /// <summary>
        /// Does one iterations in which a miniminum spanning tree is 
        /// determined on the delaunay triangulation and finally the tree is exanded to resolve the overlaps.
        /// </summary>
        /// <param name="nodePositions"></param>
        /// <param name="nodeSizes"></param>
        /// <param name="scanlinePhase"></param>
        /// <returns></returns>
        bool OneIteration(Point[] nodePositions, Size[] nodeSizes, bool scanlinePhase) {
            var cdt = new Cdt(nodePositions.Select((p, index) => Tuple.Create(p, (object) index)));
            cdt.Run();
            var siteIndex = new Dictionary<CdtSite, int>();
            for (int i = 0; i < nodePositions.Length; i++)
                siteIndex[cdt.PointsToSites[nodePositions[i]]] = i;

            int numCrossings = 0;
            List<Tuple<int, int, double, double, double>> proximityEdges =
                new List<Tuple<int, int, double, double, double>>();
            foreach (var site in cdt.PointsToSites.Values)
                foreach (var edge in site.Edges) {

                    Point point1 = edge.upperSite.Point;
                    Point point2 = edge.lowerSite.Point;
                    var nodeId1 = siteIndex[edge.upperSite];
                    var nodeId2 = siteIndex[edge.lowerSite];
                    Debug.Assert(ApproximateComparer.Close(point1, nodePositions[nodeId1]));
                    Debug.Assert(ApproximateComparer.Close(point2, nodePositions[nodeId2]));
                    var tuple = GetIdealEdgeLength(nodeId1, nodeId2, point1, point2, nodeSizes, _overlapForLayers);
                    proximityEdges.Add(tuple);
                    if (tuple.Item3 > 1) numCrossings++;
                }


            if (numCrossings == 0 || scanlinePhase) {
                int additionalCrossings = FindProximityEdgesWithSweepLine(proximityEdges, nodeSizes, nodePositions);
                if (numCrossings == 0 && additionalCrossings == 0) {
//                    if(nodeSizes.Length>100)
//                    ShowAndMoveBoxesRemoveLater(null, proximityEdges, nodeSizes, nodePositions, -1);
                    return false;
                }

                if (numCrossings == 0 && !scanlinePhase) return false;
            }
            var treeEdges = MstOnDelaunayTriangulation.GetMstOnTuple(proximityEdges, nodePositions.Length);

            int rootId = treeEdges.First().Item1;

//            if (nodeSizes.Length > 100)
//                ShowAndMoveBoxesRemoveLater(treeEdges, proximityEdges, nodeSizes, nodePositions, rootId);

            MoveNodePositions(treeEdges, nodePositions, rootId);

            return true;
        }
        /// <summary>
        /// Determines the edges of the triangulation together with their desired length (distance between nodes).
        /// </summary>
        /// <param name="originalGraph"></param>
        /// <param name="cdt"></param>
        /// <param name="targetSizes"></param>
        /// <param name="desiredEdgeDistances"></param>
        /// <returns></returns>
        public static int GetProximityEdgesWithDistance(Node[] originalGraph, Cdt cdt,
                                                        Size[] targetSizes,
                                                        out List<Tuple<int, int, double, double>> desiredEdgeDistances) {
            desiredEdgeDistances = new List<Tuple<int, int, double, double>>();
            int numberOverlappingPairs = 0;
            var edgeSet = new HashSet<CdtEdge>();
            //add edges
            foreach (CdtTriangle triangle in cdt.GetTriangles()) {
                foreach (CdtEdge triangleEdge in triangle.Edges) {
                    CdtSite site1 = triangleEdge.upperSite;
                    CdtSite site2 = triangleEdge.lowerSite;
                    var nodeId1 = (int) site1.Owner;
                    var nodeId2 = (int) site2.Owner;
                    if (edgeSet.Contains(triangleEdge)) continue; //edge already included 
                    edgeSet.Add(triangleEdge);

                    Point point1 = site1.Point;
                    Point point2 = site2.Point;

                    double t;
                    double distance = GetIdealDistanceBetweenNodes(nodeId1, nodeId2, point1, point2, targetSizes,
                                                                   out t);
                    if (t > 1)
                        numberOverlappingPairs++;
                    int nodeIdSmall = nodeId1;
                    int nodeIdBig = nodeId2;
                    if (nodeId1 > nodeId2) {
                        nodeIdSmall = nodeId2;
                        nodeIdBig = nodeId1;
                    }
                    var tuple = new Tuple<int, int, double, double>(nodeIdSmall, nodeIdBig, distance, t);
                    desiredEdgeDistances.Add(tuple);
                }
            }
            return numberOverlappingPairs;
        }