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