using System; using System.Collections; using System.Collections.Generic; using Netron.Diagramming.Core.Analysis; namespace Netron.Diagramming.Core { public partial class Model : IGraph, ITree { #region Fields private bool mIsDirected; private ITree mSpanningTree; #endregion /// /// Get the in-degree of a node, the number of edges for which the node /// is the target. /// /// /// int IGraph.InDegree(INode node) { return (node as INode).InDegree; } /// /// Get the out-degree of a node, the number of edges for which the node /// is the source. /// /// /// int IGraph.OutDegree(INode node) { return (node as INode).OutDegree; } /// /// Get the degree of a node, the number of edges for which a node /// is either the source or the target. /// /// /// int IGraph.Degree(INode node) { return (node as INode).Degree; } /// /// Indicates if the edges of this graph are directed or undirected. /// /// bool IGraph.IsDirected { get { return mIsDirected; } } /// /// Returns the nodes for the current page. This is the same as the property except that the return type is /// here rather than type. /// /// CollectionBase IGraph.Nodes { get { CollectionBase nodes = new CollectionBase(); foreach (IShape shape in this.CurrentPage.Shapes) { nodes.Add(shape as INode); } return nodes; } } /// /// Gets the edges. /// /// The edges. CollectionBase IGraph.Edges { get { CollectionBase edges = new CollectionBase(); foreach (IConnection cn in this.CurrentPage.Connections) { edges.Add(cn as IEdge); } return edges; } } /// /// Get the source Node for the given Edge instance. /// /// /// INode IGraph.FromNode(IEdge edge) { return edge.SourceNode; } INode IGraph.ToNode(IEdge edge) { return edge.TargetNode; } /// /// Given an Edge and an incident Node, return the other Node /// connected to the edge. /// /// /// /// INode IGraph.AdjacentNode(IEdge edge, INode node) { if (edge.SourceNode == node) return edge.TargetNode; else if (edge.TargetNode == node) return edge.SourceNode; else throw new InconsistencyException("The node is not a target or source node of the given edge."); } /// /// Gets the collection of all adjacent nodes connected to the given node by an /// incoming edge (i.e., all nodes that "point" at this one). /// /// /// CollectionBase IGraph.InNeighbors(INode node) { return node.InNeighbors; } /// /// Gets the collection of adjacent nodes connected to the given node by an /// outgoing edge (i.e., all nodes "pointed" to by this one). /// /// /// CollectionBase IGraph.OutNeighbors(INode node) { return node.OutNeighbors; } /// /// Get an iterator over all nodes connected to the given node. /// /// /// CollectionBase IGraph.Neighbors(INode node) { return node.Neighbors; } /// /// Edgeses the specified node. /// /// The node. /// CollectionBase IGraph.EdgesOf(INode node) { return node.Edges; } /// /// Ins the edges. /// /// The node. /// CollectionBase IGraph.InEdges(INode node) { return node.InEdges; } /// /// Outs the edges. /// /// The node. /// CollectionBase IGraph.OutEdges(INode node) { return node.OutEdges; } /// /// Gets the spanning tree. /// /// The spanning tree. ITree IGraph.SpanningTree { get { return mSpanningTree; } } /// /// Makes the spanning tree. /// /// The node. /// void IGraph.MakeSpanningTree(INode node) { // build unweighted spanning tree by BFS LinkedList q = new LinkedList(); BitArray visit = new BitArray(this.CurrentPage.Shapes.Count); q.AddFirst(node); visit[this.CurrentPage.Shapes.IndexOf(node as IShape)] = true; INode n; while (q.Count > 0) { INode p = q.First.Value; q.RemoveFirst(); if (p.Children == null) p.Children = new CollectionBase(); if (visit[this.CurrentPage.Shapes.IndexOf(p as IShape)]) p.Children.Clear(); foreach (IEdge edge in p.Edges) { n = edge.AdjacentNode(p); if (n == null) continue; try { if (!visit[this.CurrentPage.Shapes.IndexOf(n as IShape)]) { q.AddLast(n); visit[this.CurrentPage.Shapes.IndexOf(n as IShape)] = true; n.ParentNode = p; n.ParentEdge = edge; p.Children.Add(n); } } catch (ArgumentOutOfRangeException) { continue; } } } mSpanningTree = this as ITree; } void ITree.ForEach(Action action, INode startNode) { (action as Action).Invoke(startNode); if (startNode.Children == null) return; foreach (INode node in startNode.Children) { //(action as Action).Invoke(node); (this as ITree).ForEach((action as Action), node); } } /// /// Clears the spanning tree. /// void IGraph.ClearSpanningTree() { mSpanningTree = null; } IEdge ITree.ParentEdge(INode node) { if (mSpanningTree == null) return null; return mSpanningTree.ParentEdge(node); } /// /// Indicates if the edges of this graph are directed or undirected. /// /// bool ITree.IsDirected { get { return mIsDirected; } set { mIsDirected = value; } } INode ITree.Root { get { return mLayoutRoot as INode; } set { mLayoutRoot = value as IShape; } } CollectionBase ITree.Children(INode node) { if (mSpanningTree == null) return null; return mSpanningTree.Children(node); } CollectionBase ITree.ChildEdges(INode node) { if (mSpanningTree == null) return null; return mSpanningTree.ChildEdges(node); } INode ITree.NextSibling(INode node) { if (mSpanningTree == null) return null; return mSpanningTree.NextSibling(node); } INode ITree.PreviousSibling(INode node) { if (mSpanningTree == null) return null; return mSpanningTree.PreviousSibling(node); } INode ITree.LastChild(INode node) { if (mSpanningTree == null) return null; return mSpanningTree.LastChild(node); } INode ITree.FirstChild(INode node) { if (mSpanningTree == null) return null; return mSpanningTree.FirstChild(node); } int ITree.ChildCount(INode node) { if (mSpanningTree == null) return 0; return mSpanningTree.ChildCount(node); } int ITree.Depth(INode node) { if (mSpanningTree == null) return 0; return mSpanningTree.Depth(node); } } }