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