/// <summary> /// Adds all nodes and edges reachable from this node to the subgraph. /// Uses an explicit stack to avoid a large depth of recursion. /// </summary> /// <param name="startNode"></param> /// <param name="subgraph"></param> private void AddReachable(Node startNode, Subgraph subgraph) { Stack nodeStack = new Stack(); nodeStack.Push(startNode); while (!(nodeStack.Count == 0)) { Node node = (Node)nodeStack.Pop(); AddEdges(node, nodeStack, subgraph); } }
/// <summary> /// Adds the argument node and all its out edges to the subgraph. /// </summary> /// <param name="node"></param> /// <param name="nodeStack"></param> /// <param name="subgraph"></param> private void AddEdges(Node node, Stack nodeStack, Subgraph subgraph) { node.Visited = true; IEnumerator i = ((DirectedEdgeStar)node.OutEdges).GetEnumerator(); while(i.MoveNext()) { DirectedEdge de = (DirectedEdge)i.Current; subgraph.Add(de.Edge); Node toNode = de.ToNode; if (!toNode.IsVisited) nodeStack.Push(toNode); } }
/// <summary> /// /// </summary> /// <param name="graph"></param> /// <returns></returns> private static Node FindLowestDegreeNode(Subgraph graph) { int minDegree = Int32.MaxValue; Node minDegreeNode = null; IEnumerator i = graph.GetNodeEnumerator(); while (i.MoveNext()) { Node node = (Node) i.Current; if (minDegreeNode == null || node.Degree < minDegree) { minDegree = node.Degree; minDegreeNode = node; } } return minDegreeNode; }
/// <summary> /// /// </summary> /// <param name="graph"></param> /// <returns></returns> private IList FindSequence(Subgraph graph) { GraphComponent.SetVisited(graph.GetEdgeEnumerator(), false); Node startNode = FindLowestDegreeNode(graph); // HACK: we need to reverse manually the order: maybe sorting error? ArrayList list = (ArrayList) startNode.OutEdges.Edges; list.Reverse(); IEnumerator ie = list.GetEnumerator(); ie.MoveNext(); DirectedEdge startDE = (DirectedEdge) ie.Current; DirectedEdge startDESym = startDE.Sym; LinkedList<DirectedEdge> seq = new LinkedList<DirectedEdge>(); LinkedListNode<DirectedEdge> pos = AddReverseSubpath(startDESym, null, seq, false); while (pos != null) { DirectedEdge prev = pos.Value; DirectedEdge unvisitedOutDE = FindUnvisitedBestOrientedDE(prev.FromNode); if (unvisitedOutDE != null) { DirectedEdge toInsert = unvisitedOutDE.Sym; pos = AddReverseSubpath(toInsert, pos, seq, true); } else pos = pos.Previous; } /* * At this point, we have a valid sequence of graph DirectedEdges, but it * is not necessarily appropriately oriented relative to the underlying geometry. */ IList orientedSeq = Orient(new ArrayList(seq)); return orientedSeq; }
/// <summary> /// Tests whether a complete unique path exists in a graph /// using Euler's Theorem. /// </summary> /// <param name="graph">The <see cref="Subgraph" /> containing the edges.</param> /// <returns><c>true</c> if a sequence exists.</returns> private bool HasSequence(Subgraph graph) { int oddDegreeCount = 0; IEnumerator i = graph.GetNodeEnumerator(); while(i.MoveNext()) { Node node = (Node) i.Current; if (node.Degree % 2 == 1) oddDegreeCount++; } return oddDegreeCount <= 2; }
private Subgraph FindSubgraph(Node node) { Subgraph subgraph = new Subgraph(graph); AddReachable(node, subgraph); return subgraph; }