using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Msagl.Core.GraphAlgorithms;
using Microsoft.Msagl.Core.Layout;
namespace Microsoft.Msagl.Layout.Layered {
///
/// a class representing a graph where every edge goes down only one layer
///
internal class ProperLayeredGraph {
///
/// the underlying basic graph
///
internal BasicGraph BaseGraph;
LayerEdge[] virtualNodesToInEdges;
LayerEdge[] virtualNodesToOutEdges;
int totalNumberOfNodes;
int firstVirtualNode;
private int FirstVirtualNode {
get {
return firstVirtualNode;
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
internal ProperLayeredGraph(BasicGraph intGraph) {
Initialize(intGraph);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
internal void Initialize(BasicGraph intGraph)
{
BaseGraph = intGraph;
if (BaseGraph.Edges.Count > 0) {
var edgesGoingDown = from edge in BaseGraph.Edges
where edge.LayerEdges != null
select edge;
if(edgesGoingDown.Any() )
totalNumberOfNodes= (from edge in edgesGoingDown from layerEdge in edge.LayerEdges
select Math.Max(layerEdge.Source, layerEdge.Target) + 1).Max();
else totalNumberOfNodes = intGraph.NodeCount;
} else
totalNumberOfNodes = intGraph.NodeCount;
if (ExistVirtualNodes(BaseGraph.Edges)) {
firstVirtualNode = (from edge in BaseGraph.Edges
where edge.LayerEdges != null && edge.LayerEdges.Count > 1
let source = edge.Source
from layerEdge in edge.LayerEdges
let layerEdgeSource = layerEdge.Source
where layerEdge.Source != source
select layerEdgeSource).Min();
} else {
firstVirtualNode = BaseGraph.NodeCount;
totalNumberOfNodes = BaseGraph.NodeCount;
}
virtualNodesToInEdges = new LayerEdge[totalNumberOfNodes - FirstVirtualNode];
virtualNodesToOutEdges = new LayerEdge[totalNumberOfNodes - FirstVirtualNode];
foreach (IntEdge e in BaseGraph.Edges)
if (e.LayerSpan > 0)
foreach (LayerEdge le in e.LayerEdges) {
if (le.Target != e.Target)
virtualNodesToInEdges[le.Target - FirstVirtualNode] = le;
if (le.Source != e.Source)
virtualNodesToOutEdges[le.Source - FirstVirtualNode] = le;
}
}
static bool ExistVirtualNodes(ICollection iCollection) {
foreach (var edge in iCollection)
if (edge.LayerEdges != null && edge.LayerEdges.Count > 1)
return true;
return false;
}
//internal ProperLayeredGraph(BasicGraph intGraph, int[]layering) {
// this.baseGraph = intGraph;
// this.totalNumberOfNodes = intGraph.Nodes.Count + VirtualNodeCount(layering);
// virtualNodesToInEdges = new LayerEdge[totalNumberOfNodes - this.baseGraph.Nodes.Count];
// virtualNodesToOutEdges = new LayerEdge[totalNumberOfNodes - this.baseGraph.Nodes.Count];
// int currentVirtNode = intGraph.Nodes.Count;
// foreach (IntEdge e in baseGraph.Edges) {
// CreateLayerEdgesPath(e, layering, ref currentVirtNode);
// if (e.LayerSpan > 1)
// foreach (LayerEdge le in e.LayerEdges) {
// if (le.Target != e.Target)
// virtualNodesToInEdges[le.Target - NumOfOriginalNodes] = le;
// if (le.Source != e.Source)
// virtualNodesToOutEdges[le.Source - NumOfOriginalNodes] = le;
// }
// }
//}
///
/// enumerates over the graph edges
///
public IEnumerable Edges {
get {
foreach (IntEdge ie in BaseGraph.Edges) {
if (ie.LayerSpan > 0)
foreach (LayerEdge le in ie.LayerEdges)
yield return le;
}
}
}
///
/// enumerates over edges of a node
///
///
///
public IEnumerable InEdges(int node) {
if (node < BaseGraph.NodeCount)//original node
foreach (IntEdge e in BaseGraph.InEdges(node)) {
if (e.Source != e.Target && e.LayerEdges != null)
yield return LastEdge(e);
}
else if (node >= firstVirtualNode)
yield return InEdgeOfVirtualNode(node);
}
private static LayerEdge LastEdge(IntEdge e) {
return e.LayerEdges[e.LayerEdges.Count - 1];
}
internal LayerEdge InEdgeOfVirtualNode(int node) {
return virtualNodesToInEdges[node - FirstVirtualNode];
}
///
/// enumerates over the node outcoming edges
///
///
///
public IEnumerable OutEdges(int node) {
if (node < BaseGraph.NodeCount)//original node
foreach (IntEdge e in BaseGraph.OutEdges(node)) {
if (e.Source != e.Target && e.LayerEdges!=null)
yield return FirstEdge(e);
}
else if (node >= FirstVirtualNode)
yield return OutEdgeOfVirtualNode(node);
}
public bool OutDegreeIsMoreThanOne(int node) {
if (node < BaseGraph.NodeCount)//original node
return BaseGraph.OutEdges(node).Count() > 1;
else
return false;
}
public bool InDegreeIsMoreThanOne(int node) {
if (node < BaseGraph.NodeCount)//original node
return BaseGraph.InEdges(node).Count() > 1;
else
return false;
}
internal LayerEdge OutEdgeOfVirtualNode(int node) {
return virtualNodesToOutEdges[node - FirstVirtualNode];
}
private static LayerEdge FirstEdge(IntEdge e) {
return e.LayerEdges[0];
}
///
/// returns the number of incoming edges for an edge
///
///
///
public int InEdgesCount(int node) {
return RealInEdgesCount(node);
}
private int RealInEdgesCount(int node) {
return node < this.BaseGraph.NodeCount ? BaseGraph.InEdges(node).Count(e=>e.LayerEdges!=null): 1;
}
///
/// returns the number of outcoming edges for an edge
///
///
///
public int OutEdgesCount(int node) {
return RealOutEdgesCount(node);
}
private int RealOutEdgesCount(int node) {
return node < this.BaseGraph.NodeCount ? BaseGraph.OutEdges(node).Count(l=>l.LayerEdges!=null): 1;
}
///
/// returns the node count
///
public int NodeCount {
get { return this.totalNumberOfNodes; }
}
public bool IsRealNode(int node) {
return (node < this.BaseGraph.NodeCount);
}
public bool IsVirtualNode(int node) {
return !IsRealNode(node);
}
internal ProperLayeredGraph ReversedClone() {
List reversedEdges = CreateReversedEdges();
return new ProperLayeredGraph(new BasicGraph(reversedEdges, this.BaseGraph.NodeCount));
}
private List CreateReversedEdges() {
List ret = new List();
foreach (IntEdge e in BaseGraph.Edges)
if(!e.SelfEdge())
ret.Add(e.ReversedClone());
return ret;
}
internal IEnumerable Succ(int node) {
foreach (LayerEdge le in this.OutEdges(node))
yield return le.Target;
}
internal IEnumerable Pred(int node) {
foreach (LayerEdge le in this.InEdges(node))
yield return le.Source;
}
}
}