public static void ProcessUpwardRays()

in GraphLayout/MSAGL/GraphmapsWithMesh/MeshCreator.cs [638:790]


        public static void ProcessUpwardRays(Tiling g, int maxX, int maxY, Dictionary<Point, int> locationtoNode)
        {
            int a;

            //sort all horizontal segments according to the y coordinates
            List<double> Y = new List<double>();
            List<OrthogonalEdge> E = new List<OrthogonalEdge>();

            foreach (var hEdges in VHEdges.Values)
            {
                foreach (var edge in hEdges)
                {
                    if (edge.a == null) continue;
                    E.Add(edge);                    
                    Y.Add(edge.a.YLoc);
                }
            }
            double[] ArrayOfY = Y.ToArray();
            OrthogonalEdge[] SortedHorizontalEdges = E.ToArray();
            Array.Sort(ArrayOfY, SortedHorizontalEdges);
            //done sorting


            //sort the points according to Y
            double[] PointYArray = new double[g.N];
            int[] PointIdArray = new int[g.N];
            for (int i = 0; i < g.N; i++)
            {
                PointYArray[i] = g.VList[i].YLoc;
                PointIdArray[i] = i;
            }
            Array.Sort(PointYArray, PointIdArray);
            //done sorting


            //keep the points in a RB tree - compared accorfing to y coordinates
            RbTree<Vertex> PointTreeSortedByX = new RbTree<Vertex>(new xCoordinateComparator());



            //for each horizontal edge check what are the points below it, and whether any of these can be extended
            OrthogonalEdge CurrentEdge;
            int index = 0;
            //for each hEdge om sprted order
            for (int i = 0; i < SortedHorizontalEdges.Length; i++)
            {
                CurrentEdge = SortedHorizontalEdges[i];
                var CurrentY = CurrentEdge.a.YLoc;
                var leftEnd = CurrentEdge.a.XLoc;
                var rightEnd = CurrentEdge.b.XLoc;



                //insert the points below CurrentY according to the y-coordinates 
                while (index < PointIdArray.Length && g.VList[PointIdArray[index]].YLoc < CurrentY)
                    PointTreeSortedByX.Insert(g.VList[PointIdArray[index++]]);

                //do a search to find the intersecting points
                var node1 = PointTreeSortedByX.FindLast(v => v.XLoc >= leftEnd);
                var node2 = PointTreeSortedByX.FindFirst(v => v.XLoc <= rightEnd);
                if (node1 != null && node1.Item.XLoc > rightEnd) node1 = null;
                if (node2 != null && node2.Item.XLoc < leftEnd) node2 = null;
                if (node1 == null || node2 == null) continue;


                //collect all the candidate vertices
                var node = node2;
                List<Vertex> nodesToCheck = new List<Vertex>();

                if (node1.Item.Id == node2.Item.Id) nodesToCheck.Add(node.Item);
                else
                {
                    while (node.Item.Id != node1.Item.Id)
                    {
                        nodesToCheck.Add(node.Item);
                        node = PointTreeSortedByX.Next(node);
                    }
                    nodesToCheck.Add(node.Item);
                }


                List<Vertex> addedVertices = new List<Vertex>();
                List<Vertex> nodesToRemove = new List<Vertex>();
                //filter out the nodes that must be connecte to the hEdge
                foreach (var w in nodesToCheck)
                {
                    //find the topmost neighbor of w
                    int CurrentVertexId = w.Id;
                    int topNeighborId;
                    do
                    {
                        topNeighborId = CurrentVertexId;
                        for (int j = 0; j < g.DegList[CurrentVertexId]; j++)
                        {
                            Vertex Candidate = g.VList[g.EList[CurrentVertexId, j].NodeId];
                            if (Candidate.YLoc > g.VList[CurrentVertexId].YLoc)
                            {
                                CurrentVertexId = Candidate.Id;
                                break;
                            }
                        }
                    } while (topNeighborId != CurrentVertexId);
                    if (g.VList[topNeighborId].YLoc >= CurrentY) continue;

                    //add a subdivision
                    a = g.InsertVertexWithDuplicateCheck(g.VList[topNeighborId].XLoc, CurrentY, locationtoNode);
                    addedVertices.Add(g.VList[a]);


                    g.AddEdge(topNeighborId, a);
                    if (!HVEdges.ContainsKey(g.VList[topNeighborId].XLoc))
                        HVEdges[g.VList[topNeighborId].XLoc] = new List<OrthogonalEdge>();
                    HVEdges[g.VList[topNeighborId].XLoc].Add(new OrthogonalEdge(g.VList[topNeighborId], g.VList[a]));

                    nodesToRemove.Add(w);

                }


                foreach (var newnode in addedVertices)
                {


                    bool e1 = g.AddEdge(CurrentEdge.a.Id, newnode.Id);
                    if (!VHEdges.ContainsKey(newnode.YLoc))
                        VHEdges[newnode.YLoc] = new List<OrthogonalEdge>();
                    VHEdges[newnode.YLoc].Add(new OrthogonalEdge(CurrentEdge.a, newnode));

                    bool e2 = g.AddEdge(CurrentEdge.b.Id, newnode.Id);
                    if (!VHEdges.ContainsKey(newnode.YLoc))
                        VHEdges[newnode.YLoc] = new List<OrthogonalEdge>();
                    VHEdges[newnode.YLoc].Add(new OrthogonalEdge(CurrentEdge.b, newnode));


                    if (e1 && e2)
                    {
                        g.RemoveEdge(CurrentEdge.a.Id, CurrentEdge.b.Id);
                        if (VHEdges.ContainsKey(CurrentEdge.b.YLoc))
                            VHEdges[CurrentEdge.b.YLoc].Remove(CurrentEdge);

                    }


                    CurrentEdge = new OrthogonalEdge(newnode, CurrentEdge.a);


                }

                foreach (var w in nodesToRemove)
                    PointTreeSortedByX.Remove(w);

            }
        }