static IEnumerable<Node> Children(Cluster parent) {
#if SILVERLIGHT
            return parent.Clusters.Cast<Node>().Concat(parent.Nodes);
#else
            return parent.Clusters.Concat(parent.Nodes);
#endif
        }
コード例 #2
0
 HashSet<Node> CreateOrGetAddedChildrenOfParent(Cluster parent) {
     HashSet<Node> addedChildren;
     addedNodesByCluster.TryGetValue(parent, out addedChildren);
     if (addedChildren == null)
         addedNodesByCluster[parent] = addedChildren = new HashSet<Node>();
     return addedChildren;
 }
コード例 #3
0
        public void IsDescendantOf_BasicTest()
        {
            Cluster cluster = new Cluster();
            Node node = new Node();
            Node node2 = new Node();
            cluster.AddChild(node);

            Assert.IsTrue(node.IsDescendantOf(cluster), "Node is a descendant of cluster but IsDescendantOf returns false.");
            Assert.IsFalse(node2.IsDescendantOf(cluster), "Node2 is not a descendant of cluster but IsDescendantOf returns true.");
            Assert.IsFalse(cluster.IsDescendantOf(cluster), "A cluster should not be considered a descendant of itself.");
        }
 static void ProcessAncestorDescendantCouple(Cluster ancestor, Node node, Dictionary<Node, Shape> 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);
 }
コード例 #5
0
        public void IsDescendantOf_ManyParents()
        {
            Cluster grandMother = new Cluster();
            Cluster grandFather = new Cluster();
            Cluster parent = new Cluster();
            Cluster uncle = new Cluster();
            grandMother.AddChild(parent);
            grandMother.AddChild(uncle);
            grandFather.AddChild(parent);
            grandFather.AddChild(uncle);

            Node child = new Node();
            parent.AddChild(child);

            Assert.IsTrue(child.IsDescendantOf(parent), "The child node should be considered a descendant of its parent.");
            Assert.IsTrue(child.IsDescendantOf(grandMother), "The child node should be considered a descendant of its grandmother.");
            Assert.IsTrue(child.IsDescendantOf(grandFather), "The child node should be considered a descendant of its grandfather.");
            Assert.IsFalse(child.IsDescendantOf(uncle), "The child node should not be considered a descendant of its uncle.");
        }
コード例 #6
0
        /// <summary>
        /// Copy the cluster's child Nodes and Clusters as nodes and return a mapping of original to copy.
        /// The reverse mapping (copy to original) is available via the copy's UserData
        /// </summary>
        /// <param name="cluster">Cluster whose contents will be copied</param>
        /// <returns>the mapping from original to copy</returns>
        internal static Dictionary<Node, Node> ShallowNodeCopyDictionary(Cluster cluster) {
            var originalNodeToCopy = new Dictionary<Node, Node>();

            foreach (var v in cluster.Nodes)
                originalNodeToCopy[v] = new Node(v.BoundaryCurve.Clone()) {UserData = v};

            foreach (var cl in cluster.Clusters) {
                if (cl.IsCollapsed)
                    originalNodeToCopy[cl] = new Node(cl.CollapsedBoundary.Clone()) {UserData = cl};
                else {
                    if (cl.BoundaryCurve == null)
                        cl.BoundaryCurve = cl.RectangularBoundary.RectangularHull();

                    originalNodeToCopy[cl] = new Node(cl.BoundaryCurve.Clone()) {UserData = cl};
                }
            }

            return originalNodeToCopy;
        }
コード例 #7
0
        /// <summary>
        /// Creates a shallow copy of the root cluster and divides into GeometryGraphs each of which is a connected component with
        /// respect to edges internal to root.
        /// </summary>
        /// <param name="cluster">cluster to break into components</param>
        /// <returns>GeometryGraphs that are each a connected component</returns>
        static IEnumerable<GeometryGraph> GetComponents(Cluster cluster) {
            Dictionary<Node, Node> originalToCopyNodeMap = ShallowNodeCopyDictionary(cluster);
            var copiedEdges = new List<Edge>();
            foreach (var target in originalToCopyNodeMap.Keys) {
                foreach (var e in target.InEdges) {
                    var sourceAncestorUnderRoot = Ancestor(e.Source, cluster);
                    if (sourceAncestorUnderRoot == e.Source)
                        //it is a flat edge and we are only interested in flat edges
                        copiedEdges.Add(CopyEdge(originalToCopyNodeMap, e, sourceAncestorUnderRoot, target));
                }
                copiedEdges.AddRange(target.SelfEdges.Select(e => CopyEdge(originalToCopyNodeMap, e)));
            }

            return GraphConnectedComponents.CreateComponents(originalToCopyNodeMap.Values.ToArray(), copiedEdges);
        }
コード例 #8
0
 /// <summary>
 /// Check if root is an ancestor of node
 /// </summary>
 /// <param name="node"></param>
 /// <param name="root"></param>
 /// <returns>true if the node is a descendant of root</returns>
 static bool IsDescendant(Node node, Cluster root) {
     return Ancestor(node, root) != null;
 }
コード例 #9
0
        /// <summary>
        /// Apply the appropriate layout to the specified cluster and its children (bottom up)
        /// </summary>
        /// <param name="cluster">the root of the cluster hierarchy to lay out</param>
        /// <returns>list of edges external to the cluster</returns>
        void LayoutCluster(Cluster cluster) {
            if (cluster.IsCollapsed)
                return;

            LayoutAlgorithmSettings settings = clusterSettings(cluster);
            cluster.UnsetInitialLayoutState();
            if (runInParallel && cluster.Clusters.Count() > 1)
                Parallel.ForEach(cluster.Clusters, parallelOptions, LayoutCluster);
            else
                foreach (var cl in cluster.Clusters)
                    LayoutCluster(cl);

            List<GeometryGraph> components = (List<GeometryGraph>) GetComponents(cluster);

            //currentComponentFraction = (1.0 / clusterCount) / components.Count;

//            if (runInParallel)
//                Parallel.ForEach(components, parallelOptions, comp => LayoutComponent(settings, comp));
//            else // debug!!!!!!
                components.ForEach(c => LayoutComponent(settings, c));

            var bounds = MdsGraphLayout.PackGraphs(components, settings);

            foreach (var g in components)
                FixOriginalGraph(g, true);

            cluster.UpdateBoundary(bounds);

            cluster.SetInitialLayoutState(settings.ClusterMargin);
            cluster.RaiseLayoutDoneEvent();

//            var l = new List<DebugCurve>();
//            foreach (var node in cluster.Nodes) {
//                l.Add(new DebugCurve(node.BoundaryCurve));
//            }
//            foreach (var cl in cluster.AllClustersDepthFirstExcludingSelf()) {
//                l.Add(new DebugCurve(cl.BoundaryCurve));
//                l.AddRange(cl.Nodes.Select(n=>new DebugCurve(n.BoundaryCurve)));
//            }
//            LayoutAlgorithmSettings.ShowDebugCurves(l.ToArray());
        }
コード例 #10
0
        static void FixClusterBoundariesWithNoRectBoundaries(Cluster cluster, double padding) {
            foreach (Cluster cl in cluster.Clusters)
                FixClusterBoundariesWithNoRectBoundaries(cl, padding);

            var box = Rectangle.CreateAnEmptyBox();

            var clusterPoints =
                    cluster.Clusters.SelectMany(c => ClusterPoints(c)).Concat(
                        cluster.Nodes.SelectMany(n => NodePerimeterPoints(n)));
            foreach (var clusterPoint in clusterPoints)
                box.Add(clusterPoint);

            box.Pad(padding);
            cluster.BoundaryCurve = box.Perimeter();
            cluster.RectangularBoundary = new RectangularClusterBoundary();
        }
コード例 #11
0
 /// <summary>
 /// Add the parent cluster to this node's list of parents
 /// </summary>
 /// <param name="parent"></param>
 public void AddClusterParent(Cluster parent)
 {
     ValidateArg.IsNotNull(parent, "parent");
     Debug.Assert(parent != this);
     clusterParents.Add(parent);
 }
コード例 #12
0
 Cluster ProcessSubGraphs(Subgraph subgraph) {
     var geomCluster = new Cluster(subgraph.Nodes.Select(n => nodeMapping[n]),
                                   subgraph.Subgraphs.Select(ProcessSubGraphs));
     foreach (Cluster sub in geomCluster.Clusters)
         sub.GeometryParent = geomCluster;
     subgraph.GeometryNode = geomCluster;
     geomCluster.UserData = subgraph;
     nodeMapping[subgraph] = geomCluster;
     return geomCluster;
 }
コード例 #13
0
 void WriteCluster(Cluster cluster, string clusterId) {
     WriteStartElement(GeometryToken.Cluster);
     WriteAttribute(GeometryToken.Id, clusterId);
     WriteAttribute(GeometryToken.Barycenter, cluster.Barycenter);
     WriteChildClusters(cluster);
     WriteChildNodes(cluster);
     if (cluster.BoundaryCurve != null)
         WriteICurve(cluster.BoundaryCurve);
     WriteClusterRectBoundary(cluster.RectangularBoundary);            
     WriteEndElement();
 }
コード例 #14
0
 static IEnumerable<Point> ClusterPoints(Cluster cluster) {
     return cluster.BoundaryCurve as Polyline;
 }
コード例 #15
0
        private void AddOlapClusters(ConstraintGenerator generator, OverlapRemovalCluster olapParentCluster, Cluster incClus, InitialCenterDelegateType nodeCenter)
        {
            LayoutAlgorithmSettings settings = clusterSettings(incClus);
            double nodeSeparationH = settings.NodeSeparation;
            double nodeSeparationV = settings.NodeSeparation + 1e-4;
            double innerPaddingH = settings.ClusterMargin;
            double innerPaddingV = settings.ClusterMargin + 1e-4;

            // Creates the OverlapRemoval (Olap) Cluster/Node objects for our FastIncrementalLayout (FIL) objects.
            // If !isHorizontal this overwrites the Olap members of the Incremental.Clusters and Msagl.Nodes.

            // First create the olapCluster for the current incCluster.  If olapParentCluster is null, then
            // incCluster is the root of a new hierarchy.
            RectangularClusterBoundary rb = incClus.RectangularBoundary;
            if (IsHorizontal)
            {
                rb.olapCluster = generator.AddCluster(
                    olapParentCluster,
                    incClus /* userData */,
                    rb.MinWidth,
                    rb.MinHeight,
                    rb.LeftBorderInfo,
                    rb.RightBorderInfo,
                    rb.BottomBorderInfo,
                    rb.TopBorderInfo);
                rb.olapCluster.NodePadding = nodeSeparationH;
                rb.olapCluster.NodePaddingP = nodeSeparationV;
                rb.olapCluster.ClusterPadding = innerPaddingH;
                rb.olapCluster.ClusterPaddingP = innerPaddingV;
            }
            else
            {
                var postXLeftBorderInfo = new BorderInfo(rb.LeftBorderInfo.InnerMargin, rb.Rect.Left, rb.LeftBorderInfo.Weight);
                var postXRightBorderInfo = new BorderInfo(rb.RightBorderInfo.InnerMargin, rb.Rect.Right, rb.RightBorderInfo.Weight);
                rb.olapCluster = generator.AddCluster(
                    olapParentCluster,
                    incClus /* userData */,
                    rb.MinHeight,
                    rb.MinWidth,
                    rb.BottomBorderInfo,
                    rb.TopBorderInfo,
                    postXLeftBorderInfo,
                    postXRightBorderInfo);
                rb.olapCluster.NodePadding = nodeSeparationV;
                rb.olapCluster.NodePaddingP = nodeSeparationH;
                rb.olapCluster.ClusterPadding = innerPaddingV;
                rb.olapCluster.ClusterPaddingP = innerPaddingH;
            }
            rb.olapCluster.TranslateChildren = rb.GenerateFixedConstraints;
            // Note: Incremental.Cluster always creates child List<Cluster|Node> so we don't have to check for null here.
            // Add our child nodes.
            foreach (var filNode in incClus.Nodes)
            {
                AddOlapNode(generator, rb.olapCluster, (FiNode)filNode.AlgorithmData, nodeCenter);
            }

            // Now recurse through all child clusters.
            foreach (var incChildClus in incClus.Clusters)
            {
                AddOlapClusters(generator, rb.olapCluster, incChildClus, nodeCenter);
            }
        }
コード例 #16
0
        public DCluster AddCluster(DCluster parent, string id)
        {
            if (parent == null)
            {
                Graph.LayoutAlgorithmSettings = new FastIncrementalLayoutSettings();
                Graph.LayoutAlgorithmSettings.EdgeRoutingSettings.KeepOriginalSpline = true;
                var settings = Graph.LayoutAlgorithmSettings as FastIncrementalLayoutSettings;
                settings.AvoidOverlaps = true;
                settings.NodeSeparation = 30;
                settings.RouteEdges = true;
            }

            Subgraph cluster = new Subgraph(id == null ? GetNewNodeID() : id);
            Cluster geometryCluster = new Cluster() { GeometryParent = parent == null ? Graph.GeometryGraph : (GeometryObject)parent.GeometryNode };
            cluster.GeometryNode = geometryCluster;
            geometryCluster.UserData = cluster;

            DCluster ret = new DCluster((DObject)parent ?? this, cluster);
            cluster.LabelText = null;
            SetNodeBoundaryCurve(Graph, cluster);

            if (parent == null)
                m_RootCluster = ret;
            else
                parent.AddCluster(ret);

            if (UpdateGraphBoundingBoxPreservingCenter())
                Invalidate();

            AddCluster(ret, false);

            return ret;
        }
コード例 #17
0
 void AddRootCluster(GeometryGraph graph) {
     var c = new Cluster(graph.Nodes);
     graph.RootCluster = c;
 }
コード例 #18
0
        static bool Ancestor(Cluster root, Node node)
        {
            if (node.ClusterParents.Contains(root))
                return true;
            var parents = new Queue<Cluster>(node.ClusterParents);
            while (parents.Count > 0)
            {
                Cluster parent = parents.Dequeue();

                if (root.Clusters.Contains(parent))
                    return true;

                foreach (Cluster grandParent in parent.ClusterParents)
                    parents.Enqueue(grandParent);
            }

            return false;
        }
コード例 #19
0
        static GeometryGraph GenerateGraphWithGroups(Random random, int multiplier)
        {
            int clusterCount = (2 + random.Next(5))*multiplier;
            int nodeCount = (clusterCount + random.Next(20))*multiplier;
            int edgeCount = (10 + random.Next(20))*multiplier;

            //tree of clusters
            var parent = GenerateClusterTree(clusterCount, random);
            GeometryGraph graph = new GeometryGraph();

            //create nodes
            for (int i = 0; i < nodeCount; i++) {
                Node node = GraphGenerator.CreateNode(i);
                graph.Nodes.Add(node);
            }

            //create clusters
            var clusters = new Cluster[clusterCount];
            for (int i = 0; i < clusterCount; i++) {
                clusters[i] = new Cluster();
                clusters[i].BoundaryCurve = CurveFactory.CreateRectangle(30, 30, new Point(15, 15));
                clusters[i].RectangularBoundary = new RectangularClusterBoundary { LeftMargin = 5, RightMargin = 5, BottomMargin = 5, TopMargin = 5 };
            }

            //set cluster hiearchy
            graph.RootCluster = clusters[0];
            for (int i = 1; i < clusterCount; i++) {
                clusters[parent[i]].AddChild(clusters[i]);
            }

            //put nodes to clusters
            for (int i = 0; i < nodeCount; i++) {
                clusters[random.Next(clusterCount)].AddChild(graph.Nodes[i]);
            }

            for (int i = 0; i < clusterCount; i++) {
                if (clusters[i].Nodes.Count() == 0 && clusters[i].Clusters.Count() == 0) {
                    Node node = GraphGenerator.CreateNode(i);
                    graph.Nodes.Add(node);
                    clusters[i].AddChild(node);
                    nodeCount++;
                }
            }

            //adding edges
            for (int i = 0; i < edgeCount; i++) {
                int s = random.Next(nodeCount + clusterCount - 1);
                Node snode = (s < nodeCount ? graph.Nodes[s] : clusters[s - nodeCount + 1]);
                int t = random.Next(nodeCount + clusterCount - 1);
                Node tnode = (t < nodeCount ? graph.Nodes[t] : clusters[t - nodeCount + 1]);

                if (EdgeIsValid(snode, tnode)) {
                    var edge = new Edge(snode, tnode);
                    edge.LineWidth = 0.5 + 3 * random.NextDouble();
                    graph.Edges.Add(edge);
                }
                else
                    i--;
            }

            SetupPorts(graph);
            return graph;
        }
コード例 #20
0
        /// <summary>
        /// find ancestor of node that is immediate child of root, or node itself if node is a direct child of root
        /// null if none
        /// </summary>
        /// <param name="node"></param>
        /// <param name="root"></param>
        /// <returns>returns highest ancestor of node (or node itself) that is a direct child of root, null if not 
        /// a descendent of root</returns>
        internal static Node Ancestor(Node node, Cluster root) {
            if (node.ClusterParents.Contains(root)) return node;
            var parents = new Queue<Cluster>(node.ClusterParents);
            while (parents.Count > 0) {
                Cluster parent = parents.Dequeue();

                if (root.Clusters.Contains(parent))
                    return parent;

                foreach (Cluster grandParent in parent.ClusterParents)
                    parents.Enqueue(grandParent);
            }

            return null;
        }
コード例 #21
0
        private void DebugVerifyClusters(ConstraintGenerator generator, Cluster incCluster, Cluster root) {
            double dblEpsilon = 0.0001;

            // First verify that all nodes are within the cluster.
            Rectangle clusRect = incCluster.RectangularBoundary.rectangle;
            foreach (var v in incCluster.Nodes) {
                FiNode iiFilNode = (FiNode)v.AlgorithmData;
                Rectangle iiNodeRect = iiFilNode.mNode.BoundaryCurve.BoundingBox;

                if (IsHorizontal) {
                    // Don't check containment for the root ClusterHierarchy as there is no border for it.
                    if (incCluster != root) {
                        // This is horizontal so we've not yet calculated the Y-axis stuff.  The only thing we
                        // can do is verify we're within cluster X bounds.  If *Space is negative, there's overlap.
                        // Generator primary axis is horizontal so use its Padding.
                        double dblLboundSpace = iiNodeRect.Left - clusRect.Left - generator.Padding;
                        double dblRboundSpace = clusRect.Right - iiNodeRect.Right - generator.Padding;
                        Debug.Assert((dblLboundSpace >= -dblEpsilon) && (dblRboundSpace >= -dblEpsilon)
                                    , "Node is not within parent Cluster");
                    }
                } else {
                    // Don't check containment for the root ClusterHierarchy as there is no border for it.
                    if (incCluster != root) {
                        // This is vertical so we've calculated the Y-axis stuff and horizontal is Perpendicular.
                        DebugVerifyRectContains(clusRect, iiNodeRect
                                                , generator.PaddingP, generator.Padding, dblEpsilon);
                    }
                    // Make sure the node doesn't intersect any following nodes, or any clusters.
                    foreach (var u in incCluster.Nodes) {
                        if (u == v) continue;
                        FiNode jjFilNode = (FiNode)u.AlgorithmData;
                        Rectangle jjNodeRect = jjFilNode.mNode.BoundaryCurve.BoundingBox;

                        // We've already added the padding for the node so don't add it for the jjNode/Cluster.
                        DebugVerifyRectsDisjoint(iiNodeRect, jjNodeRect
                                                , generator.PaddingP, generator.Padding, dblEpsilon);
                    }
                    foreach (Cluster incClusComp in incCluster.Clusters)
                    {
                        DebugVerifyRectsDisjoint(iiNodeRect, incClusComp.RectangularBoundary.rectangle
                                            , generator.PaddingP, generator.Padding, dblEpsilon);
                    }
                } // endif isHorizontal
            } // endfor iiNode

            // Now verify the clusters are contained and don't overlap.
            foreach (var iiIncClus in incCluster.Clusters) {
                Rectangle iiClusRect = iiIncClus.RectangularBoundary.rectangle;

                if (IsHorizontal) {
                    // Don't check containment for the root ClusterHierarchy as there is no border for it.
                    if (incCluster != root) {
                        // This is horizontal so we've not yet calculated the Y-axis stuff.  The only thing we
                        // can do is verify we're within cluster X bounds.  If *Space is negative, there's overlap.
                        // Generator primary axis is horizontal so use its Padding.
                        double dblLboundSpace = iiClusRect.Left - clusRect.Left - generator.Padding;
                        double dblRboundSpace = clusRect.Right - iiClusRect.Right - generator.Padding;
                        Debug.Assert((dblLboundSpace >= -dblEpsilon) && (dblRboundSpace >= -dblEpsilon)
                                    , "Cluster is not within parent Cluster");
                    }
                } else {
                    // Don't check containment for the root ClusterHierarchy as there is no border for it.
                    if (incCluster != root) {
                        // This is vertical so we've calculated the Y-axis stuff and horizontal is Perpendicular.
                        DebugVerifyRectContains(clusRect, iiClusRect
                                                , generator.PaddingP, generator.Padding, dblEpsilon);
                    }
                    // Make sure the cluster doesn't intersect any following clusters.
                    foreach (var jjIncClus in incCluster.Clusters) {
                        if (jjIncClus == iiIncClus) continue;
                        Rectangle jjClusRect = jjIncClus.RectangularBoundary.rectangle;
                        DebugVerifyRectsDisjoint(iiClusRect, jjClusRect
                                                , generator.PaddingP, generator.Padding, dblEpsilon);
                    }
                } // endif isHorizontal

                // Now recurse.
                DebugVerifyClusters(generator, iiIncClus, root);
            } // endfor iiCluster
        }
コード例 #22
0
 void WriteChildClusters(Cluster cluster) {
     WriteAttribute(GeometryToken.ChildClusters,
     String.Join(" ", cluster.Clusters.Select(child => NodeToIds[child])));            
 }
 private static bool SetOfActiveNodesIsLargerThanThreshold(Cluster ancestor, Node node, Set<Node> 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;
 }
コード例 #24
0
        void ProcessCluster(Cluster cluster) {
            if (cluster.IsCollapsed)
                return;
            Rectangle oldBounds = cluster.BoundingBox;
            cluster.UnsetInitialLayoutStateIncludingAncestors();
            LayoutCluster(cluster);

            if (cluster != graph.RootCluster) {
                Rectangle newBounds = cluster.BoundingBox;
                cluster.DeepTranslation(oldBounds.Center - newBounds.Center, true);
            }
#if DEBUG
              //  ValidateLayout(cluster);
#endif
        }
コード例 #25
0
 void WriteChildNodes(Cluster cluster) {
     WriteAttribute(GeometryToken.ChildNodes,
         string.Join(" ",
         cluster.nodes.Select(child => nodeIds[child].ToString(CultureInfo.InvariantCulture))));
 }
コード例 #26
0
 static void RouteSimplHooksAndFillTheLists(Cluster rootCluster, List<Edge> inParentEdges,
     List<Edge> outParentEdges, EdgeRoutingSettings edgeRoutingSettings) {
     var padding = edgeRoutingSettings.Padding + edgeRoutingSettings.PolylinePadding;
     foreach (var cluster in rootCluster.AllClustersWidthFirstExcludingSelfAvoidingChildrenOfCollapsed().Where(c=>!c.IsCollapsed)) {
         RouteClusterParentInEdges(inParentEdges, edgeRoutingSettings, cluster, padding);
         RouteClusterParentOutEdges(outParentEdges, edgeRoutingSettings, cluster, padding);
     }
 }
コード例 #27
0
 void MapClustersToIds(Cluster cluster) {
     string id;
     var setOfIds = new Set<string>(nodeIds.Values);
     foreach (Cluster child in cluster.AllClustersDepthFirst()) {
         if (!nodeIds.TryGetValue(child, out id)) {
             id = FindNewId(setOfIds);
             nodeIds[child] = id;
             setOfIds.Insert(id);
         }
     }
 }
コード例 #28
0
 static void RouteClusterParentInEdges(List<Edge> inParentEdges, EdgeRoutingSettings edgeRoutingSettings, Cluster cluster,
     double padding) {
     foreach (var e in cluster.InEdges.Where(e => IsDescendant(e.Source, cluster))) {
         double ePadding = Math.Max(padding, 1.5*ArrowlengthAtTarget(e));
         var hookPort = e.TargetPort as HookUpAnywhereFromInsidePort;
         if (hookPort == null)
             e.TargetPort = hookPort = new HookUpAnywhereFromInsidePort(() => cluster.BoundaryCurve);
         hookPort.HookSize = ePadding;
         e.Curve = StraightLineEdges.CreateLoop(e.Source.BoundingBox, cluster.BoundingBox, ePadding, false);
         Arrowheads.TrimSplineAndCalculateArrowheads(e, e.Curve, false,
             edgeRoutingSettings.KeepOriginalSpline);
         inParentEdges.Add(e);
     }
 }
コード例 #29
0
        /// <summary>
        /// Determines if this node is a descendant of the given cluster.
        /// </summary>
        /// <returns>True if the node is a descendant of the cluster.  False otherwise.</returns>
        public bool IsDescendantOf(Cluster cluster)
        {
            Queue<Cluster> parents = new Queue<Cluster>(this.ClusterParents);

            while (parents.Count > 0)
            {
                Cluster parent = parents.Dequeue();

                if (parent == cluster)
                {
                    return true;
                }

                foreach (Cluster grandParent in parent.ClusterParents)
                {
                    parents.Enqueue(grandParent);
                }
            }

            return false;
        }
コード例 #30
0
    //        void CheckEdges() {
    //            foreach (var edge in graph.Edges)
    //                CheckEdge(edge);
    //        }
    //
    //        static void CheckEdge(Edge edge) {
    //            var s = edge.Source;
    //            var t = edge.Target;
    //            var sParents = new Set<Node>(s.ClusterParents);
    //            var tParents = new Set<Node>(t.ClusterParents);
    //            if (sParents == tParents) // the edge is between of the nodes of the same cluster, in a simple case
    //                return;
    //            var cluster = t as Cluster;
    //            if (cluster != null && IsDescendant(s, cluster))
    //                return;
    //            cluster = s as Cluster;
    //            if (cluster != null && IsDescendant(t, cluster))
    //                return;
    //            Debug.Assert(false, "an edge can be flat or connecting with an ancestor");
    //        }

    /// <summary>
    /// Ensures that containment is preserved
    /// </summary>
    /// <param name="cluster">check is applied to specified cluster and below</param>
        static void ValidateLayout(Cluster cluster) {
            foreach (var c in cluster.AllClustersDepthFirst())
                foreach (var v in c.nodes.Concat(c.Clusters.Cast<Node>()))
                    Debug.Assert(c.BoundingBox.Contains(v.BoundingBox));
        }