Aetheria/Assets/Plugins/MSAGL/Layout/Layered/ProperLayeredGraph.cs

239 lines
9 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Msagl.Core.GraphAlgorithms;
using Microsoft.Msagl.Core.Layout;
namespace Microsoft.Msagl.Layout.Layered {
/// <summary>
/// a class representing a graph where every edge goes down only one layer
/// </summary>
internal class ProperLayeredGraph {
/// <summary>
/// the underlying basic graph
/// </summary>
internal BasicGraph<Node, IntEdge> 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<Node, IntEdge> intGraph) {
Initialize(intGraph);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")]
internal void Initialize(BasicGraph<Node, IntEdge> 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<IntEdge> iCollection) {
foreach (var edge in iCollection)
if (edge.LayerEdges != null && edge.LayerEdges.Count > 1)
return true;
return false;
}
//internal ProperLayeredGraph(BasicGraph<IntEdge> 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;
// }
// }
//}
/// <summary>
/// enumerates over the graph edges
/// </summary>
public IEnumerable<LayerEdge> Edges {
get {
foreach (IntEdge ie in BaseGraph.Edges) {
if (ie.LayerSpan > 0)
foreach (LayerEdge le in ie.LayerEdges)
yield return le;
}
}
}
/// <summary>
/// enumerates over edges of a node
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
public IEnumerable<LayerEdge> 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];
}
/// <summary>
/// enumerates over the node outcoming edges
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
public IEnumerable<LayerEdge> 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];
}
/// <summary>
/// returns the number of incoming edges for an edge
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
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;
}
/// <summary>
/// returns the number of outcoming edges for an edge
/// </summary>
/// <param name="node"></param>
/// <returns></returns>
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;
}
/// <summary>
/// returns the node count
/// </summary>
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<IntEdge> reversedEdges = CreateReversedEdges();
return new ProperLayeredGraph(new BasicGraph<Node, IntEdge>(reversedEdges, this.BaseGraph.NodeCount));
}
private List<IntEdge> CreateReversedEdges() {
List<IntEdge> ret = new List<IntEdge>();
foreach (IntEdge e in BaseGraph.Edges)
if(!e.SelfEdge())
ret.Add(e.ReversedClone());
return ret;
}
internal IEnumerable<int> Succ(int node) {
foreach (LayerEdge le in this.OutEdges(node))
yield return le.Target;
}
internal IEnumerable<int> Pred(int node) {
foreach (LayerEdge le in this.InEdges(node))
yield return le.Source;
}
}
}