using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Msagl.Core.DataStructures;
using Microsoft.Msagl.Core.Layout;
namespace Microsoft.Msagl.Routing {
///
/// written in assumption of a single parent
///
internal static class ShapeCreatorForRoutingToParents {
public static IEnumerable GetShapes(IEnumerable inParentEdges, List outParentEdges) {
var nodesToShapes = new Dictionary();
foreach (var edge in inParentEdges) {
ProcessAncestorDescendantCouple((Cluster)edge.Target, edge.Source, nodesToShapes);
InsertEdgePortsToShapes(nodesToShapes, edge);
}
foreach (var edge in outParentEdges) {
ProcessAncestorDescendantCouple((Cluster)edge.Source, edge.Target, nodesToShapes);
InsertEdgePortsToShapes(nodesToShapes, edge);
}
BindShapes(nodesToShapes);
return nodesToShapes.Values;
}
private static void InsertEdgePortsToShapes(Dictionary nodesToShapes, Edge edge) {
nodesToShapes[edge.Target].Ports.Insert(edge.TargetPort);
nodesToShapes[edge.Source].Ports.Insert(edge.SourcePort);
}
static void BindShapes(Dictionary nodesToShapes) {
foreach (var nodeShape in nodesToShapes) {
var cluster = nodeShape.Key as Cluster;
if(cluster==null) continue;
var shape=nodeShape.Value;
foreach (var child in Children(cluster) ) {
Shape childShape;
if(nodesToShapes.TryGetValue(child, out childShape))
shape.AddChild(childShape);
}
}
}
static void ProcessAncestorDescendantCouple(Cluster ancestor, Node node, Dictionary nodesToShapes) {
Cluster parent=Parent(node);
do {
foreach (var n in Children(parent))
CreateShapeIfNeeeded(n, nodesToShapes);
if (parent == ancestor)
break;
parent = Parent(parent);
} while (true);
CreateShapeIfNeeeded(parent, nodesToShapes);
}
static void CreateShapeIfNeeeded(Node n, Dictionary nodesToShapes) {
if (nodesToShapes.ContainsKey(n)) return;
nodesToShapes[n] = new RelativeShape(() => n.BoundaryCurve)
#if DEBUG
{
UserData = n.ToString()
}
#endif
;
}
static IEnumerable Children(Cluster parent) {
return parent.Clusters.Concat(parent.Nodes);
}
static Cluster Parent(Node node) {
return node.ClusterParents.First();
}
internal static bool NumberOfActiveNodesIsUnderThreshold(List inParentEdges, List outParentEdges, int threshold) {
var usedNodeSet = new Set();
foreach (var edge in inParentEdges)
if(SetOfActiveNodesIsLargerThanThreshold((Cluster)edge.Target, edge.Source, usedNodeSet, threshold))
return false;
foreach (var edge in outParentEdges)
if(SetOfActiveNodesIsLargerThanThreshold((Cluster)edge.Source, edge.Target, usedNodeSet, threshold))
return false;
return true;
}
private static bool SetOfActiveNodesIsLargerThanThreshold(Cluster ancestor, Node node, Set usedNodeSet, int threshold) {
Cluster parent = Parent(node);
do {
foreach (var n in Children(parent)) {
usedNodeSet.Insert(n);
if (usedNodeSet.Count > threshold)
return true;
}
if (parent == ancestor)
break;
parent = Parent(parent);
} while (true);
usedNodeSet.Insert(parent);
return usedNodeSet.Count > threshold;
}
}
}