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