public void Update(Node aNode) { if (aNode.Descendants.Count != 0) { return; } // This node is a head, create a new lane for it Node h = aNode; if (h.Ancestors.Count != 0) { foreach (Junction j in h.Ancestors) { var detail = new LaneJunctionDetail(j); laneNodes.Add(detail); } } else { // This is a single entry with no parents or children. var detail = new LaneJunctionDetail(h); laneNodes.Add(detail); } }
public void Clear() { laneRows.Clear(); laneNodes.Clear(); currentRow.Clear(); foreach (Node aNode in sourceGraph.GetHeads()) { if (aNode.Descendants.Count == 0) { // This node is a head, create a new lane for it Node h = aNode; if (h.Ancestors.Count == 0) { // This is a single entry with no parents or children. var detail = new LaneJunctionDetail(h); laneNodes.Add(detail); } else { foreach (Junction j in h.Ancestors) { var detail = new LaneJunctionDetail(j); laneNodes.Add(detail); } } } } }
/// <summary> /// Advance the lane to the next element /// </summary> /// <param name="curLane">Index of the lane to advance</param> /// <returns>True if there will still be nodes in this lane</returns> private int AdvanceLane(int curLane) { LaneJunctionDetail lane = laneNodes[curLane]; int minLane = curLane; // Advance the lane lane.Next(); // See if we can pull up ancestors if (lane.Count == 0 && lane.Junction == null) { // Handle a single node branch. currentRow.Collapse(curLane); laneNodes.RemoveAt(curLane); } else if (lane.Count == 0) { Node node = lane.Junction.Oldest; foreach (Junction parent in node.Ancestors) { if (parent.CurrentState != Junction.State.Unprocessed) { // This item is already in the lane list, no action needed continue; } var addedLane = new LaneJunctionDetail(parent); addedLane.Next(); int addedLaneLane = int.MaxValue; // Check to see if this junction already points to one of the // existing lanes. If so, we'll just add the lane line and not // add it to the laneNodes. if (addedLane.Count == 1) { for (int i = 0; i < laneNodes.Count; i++) { if (laneNodes[i].Current == addedLane.Current) { // We still advance the lane so it gets // marked as processed. addedLane.Next(); addedLaneLane = i; break; } } } // Add to the lane nodes if (addedLaneLane == int.MaxValue) { if (lane.Count == 0) { lane = addedLane; laneNodes[curLane] = lane; addedLaneLane = curLane; } else { addedLaneLane = curLane + 1; laneNodes.Insert(addedLaneLane, addedLane); currentRow.Expand(addedLaneLane); } } currentRow.Add(curLane, new Graph.LaneInfo(addedLaneLane, parent)); } // If the lane count after processing is still 0 // this is a root node of the graph if (lane.Count == 0) { currentRow.Collapse(curLane); laneNodes.RemoveAt(curLane); } } else if (lane.Count == 1) { // If any other lanes have this node on top, merge them together for (int i = 0; i < laneNodes.Count; i++) { if (i == curLane || curLane >= laneNodes.Count) { continue; } if (laneNodes[i].Current == laneNodes[curLane].Current) { int left; int right; Junction junction = laneNodes[curLane].Junction; if (i > curLane) { left = curLane; right = i; } else { left = i; right = curLane; curLane = i; } currentRow.Replace(right, left); currentRow.Collapse(right); laneNodes[right].Clear(); laneNodes.RemoveAt(right); currentRow.Add(currentRow.NodeLane, new Graph.LaneInfo(left, junction)); minLane = Math.Min(minLane, left); } } // If the current lane is still active, add it. It might not be active // if it got merged above. if (!lane.IsClear) { currentRow.Add(currentRow.NodeLane, new Graph.LaneInfo(curLane, lane.Junction)); } } else // lane.Count > 1 { currentRow.Add(currentRow.NodeLane, new Graph.LaneInfo(curLane, lane.Junction)); } return(curLane); }
private bool MoveNext() { // If there are no lanes, there is nothing more to draw if (laneNodes.Count == 0 || sourceGraph.Count <= laneRows.Count) { return(false); } // Find the new current row's node (newest item in the row) #region Find current node & index currentRow.Node = null; for (int curLane = 0; curLane < laneNodes.Count; curLane++) { LaneJunctionDetail lane = laneNodes[curLane]; if (lane.Count == 0) { continue; } // NOTE: We could also compare with sourceGraph sourceGraph.AddedNodes[sourceGraph.processedNodes], // since it should always be the same value if (currentRow.Node == null || currentRow.Node.Data == null || (lane.Current.Data != null && lane.Current.Index < currentRow.Node.Index)) { currentRow.Node = lane.Current; currentRow.NodeLane = curLane; //break; } } if (currentRow.Node == null) { // DEBUG: The check above didn't find anything, but should have if (Debugger.IsAttached) { Debugger.Break(); } //Node[] topo = this.sourceGraph.TopoSortedNodes(); return(false); } // If this row doesn't contain data, we're to the end of the valid entries. if (currentRow.Node.Data == null) { return(false); } sourceGraph.ProcessNode(currentRow.Node); #endregion // Check for multiple junctions with this node at the top. Remove the // node from that junction as well. This will happen when there is a branch #region Check for branches currentRow.Clear(currentRow.NodeLane); for (int curLane = 0; curLane < laneNodes.Count; curLane++) { LaneJunctionDetail lane = laneNodes[curLane]; if (lane.Count == 0) { continue; } if (currentRow.Node != lane.Current) { // We're only interested in columns that have the same node // at the top of the junction as the current row's node continue; } // Remove the item from the lane, since it is being drawn now. // We need to draw the graph line for this lane. If there are no items // left in the lane we don't draw it. int intoLane = AdvanceLane(curLane); if (intoLane < curLane) { // AdvanceLane could have removed lanes so we need to start from // the merged into lane (otherwise we could skip a lane, causing // us to try to insert a node into the graph twice) curLane = intoLane; } // Re-process the lane to make sure there are no actions left. curLane--; } #endregion // Look for lanes that cross and reorder to straighten them out if possible, // and keep the lanes that merge next to each other. #region Straighten out lanes // Look for crossing lanes // but only when there are not too many lanes taking up too much performance if (currentRow.Count < 10) { for (int lane = 0; lane < currentRow.Count; lane++) { for (int item = 0; item < currentRow.LaneInfoCount(lane); item++) { Graph.LaneInfo laneInfo = currentRow[lane, item]; if (laneInfo.ConnectLane <= lane) { continue; } // Lane is moving to the right, check to see if it intersects // with any lanes moving to the left. for (int otherLane = lane + 1; otherLane <= laneInfo.ConnectLane; otherLane++) { if (currentRow.LaneInfoCount(otherLane) != 1) { continue; } Graph.LaneInfo otherLaneInfo = currentRow[otherLane, 0]; if (otherLaneInfo.ConnectLane < otherLane) { currentRow.Swap(otherLaneInfo.ConnectLane, otherLane); LaneJunctionDetail temp = laneNodes[otherLane]; laneNodes[otherLane] = laneNodes[otherLaneInfo.ConnectLane]; laneNodes[otherLaneInfo.ConnectLane] = temp; } } } } } //// Keep the merge lanes next to each other //int mergeFromCount = currentRow.LaneInfoCount(currentRow.NodeLane); //if (mergeFromCount > 1) //{ // for (int i = 0; i < mergeFromCount; i++) // { // Graph.LaneInfo laneInfo = currentRow[currentRow.NodeLane, i]; // // Check to see if the lane is currently next to us // if (laneInfo.ConnectLane - currentRow.NodeLane > mergeFromCount) // { // // Only move the lane if it isn't already being drawn. // if (currentRow.LaneInfoCount(laneInfo.ConnectLane) == 0) // { // // Remove the row laneInfo.ConnectLane and insert // // it at currentRow.NodeLane+1. // // Then start over searching for others if i != mergeFromCount-1? // int adjacentLane = currentRow.NodeLane + 1; // if (adjacentLane >= laneNodes.Count) Debugger.Break(); // currentRow.Expand(adjacentLane); // currentRow.Replace(laneInfo.ConnectLane + 1, adjacentLane); // LaneJunctionDetail temp = laneNodes[laneInfo.ConnectLane]; // laneNodes.RemoveAt(laneInfo.ConnectLane); // laneNodes.Insert(adjacentLane, temp); // } // } // } //} #endregion if (currentRow.Node != null) { Graph.ILaneRow row = currentRow.Advance(); // This means there is a node that got put in the graph twice... if (row.Node.InLane != int.MaxValue) { if (Debugger.IsAttached) { Debugger.Break(); } } row.Node.InLane = laneRows.Count; laneRows.Add(row); return(true); } // Return that there are more items left return(false); }