/// <summary> /// Sugiyama step 3: Node Ordering /// This method uses Median heuristic to determine the vertical node /// order for each layer. /// </summary> public void OrderNodes() { // Assign temporary vertical indices for further processing foreach (List<Node> layer in Layers.Skip(1)) { foreach (Node node in layer) node.Y = Infinite; } foreach (List<Node> layer in Layers.Skip(1)) { double prevY = -10; bool layerUpdated = false; foreach (Node n in layer) { // Get the vertical coordinates of each node's right edge // and get the median from these values List<Edge> neighborEdges = n.RightEdges .Where(x => x.EndNode.Y < Infinite).OrderBy(x => x.EndY).ToList(); if (neighborEdges.Count > 1 && neighborEdges.Count % 2 == 0) { Edge median1 = neighborEdges[(neighborEdges.Count - 1) / 2]; Edge median2 = neighborEdges[(neighborEdges.Count) / 2]; n.Y = (median1.EndY + median2.EndY - median1.StartOffsetY - median2.StartOffsetY) / 2; prevY = n.Y; layerUpdated = true; } else if (neighborEdges.Count > 0) { Edge median = neighborEdges[(neighborEdges.Count - 1) / 2]; n.Y = median.EndY - median.StartOffsetY; prevY = n.Y; layerUpdated = true; } else if (n.LeftEdges.Count > 0 && AnchorRightEdges.Count == 0) { n.Y = prevY; prevY = n.Y; layerUpdated = true; } } if (layerUpdated) { AssignCoordinates(layer); } } // Assign left-anchored nodes foreach (List<Node> layer in Layers.Skip(1).Reverse()) { bool layerUpdated = false; foreach (Node n in layer) { if (n.Y >= Infinite) { List<Edge> neighborEdges = n.LeftEdges .Where(x => x.StartNode.Y < Infinite).OrderBy(x => x.EndY).ToList(); if (neighborEdges.Count > 1 && neighborEdges.Count % 2 == 0) { Edge median1 = neighborEdges[(neighborEdges.Count - 1) / 2]; Edge median2 = neighborEdges[(neighborEdges.Count) / 2]; n.Y = (median1.StartNode.Y + median1.StartOffsetY + median2.StartNode.Y + median2.StartOffsetY - median1.EndOffsetY - median2.EndOffsetY) / 2; layerUpdated = true; } else if (neighborEdges.Count > 0) { Edge median = neighborEdges[(neighborEdges.Count - 1) / 2]; n.Y = median.StartNode.Y + median.StartOffsetY - median.EndOffsetY; layerUpdated = true; } } } if (layerUpdated) { AssignCoordinates(layer); } } }
/// <summary> /// Adds a new edge to the graph object. /// </summary> /// <param name="startId">The guid of the starting node.</param> /// <param name="endId">The guid of the ending node.</param> /// <param name="startX">The x coordinate of the connector's left end point.</param> /// <param name="startY">The y coordinate of the connector's left end point.</param> /// <param name="endX">The x coordinate of the connector's right end point.</param> /// <param name="endY">The y coordinate of the connector's right end point.</param> public void AddEdge(Guid startId, Guid endId, double startX, double startY, double endX, double endY) { var edge = new Edge(startId, endId, startX, startY, endX, endY, this); Edges.Add(edge); }