Example #1
0
        /// <summary>
        /// Add a plain subgraph with given name to self, containing the nodes that occur both in origin
        /// and the filter. In other words, filter the origin subgraph by the filter subgraph on node-level.
        /// Attributes are copied from origin to the result.
        ///
        /// Side effect: adds the returned subgraph to self.
        /// </summary>
        public SubGraph AddSubgraphFilteredByNodes(string name, SubGraph origin, IEnumerable <Node> filter)
        {
            SubGraph result = GetOrAddSubgraph(name);

            foreach (var node in origin.Nodes().Where(filter.Contains))
            {
                result.AddExisting(node);
            }

            origin.CopyAttributesTo(result);
            return(result);
        }
Example #2
0
        /// <summary>
        /// Create a subgraph consisting of nodes from the given nodes.
        /// Edges are added to the result if both endpoints are among the nodes.
        /// Subgraphs are added to the result if they have nodes in the given nodelist.
        /// The names of the Subgraphs are of the form "name:subgraphname".
        ///
        /// Side effect: adds the returned subgraph (and its children) to self.
        /// </summary>
        public SubGraph AddSubgraphFromNodes(string name, IEnumerable <Node> nodes)
        {
            // Freeze the list of descendants,
            // since we are going to add subgraphs while iterating over existing subgraphs
            List <SubGraph> descendants = Descendants().ToList();

            SubGraph result = GetOrAddSubgraph(name);

            foreach (var node in nodes)
            {
                result.AddExisting(node);
            }

            Debug.Assert(result.Nodes().Count() == nodes.Count());

            // All that remains to do is to patch up the result by adding edges and subgraphs
            foreach (var node in result.Nodes())
            {
                foreach (var edge in node.EdgesOut(this))
                {
                    if (result.Contains(edge.Head()))
                    {
                        result.AddExisting(edge);
                    }
                }
            }

            Debug.Assert(result.Nodes().Count() == nodes.Count());

            // Iterate over the (frozen) existing subgraphs and add new filtered subgraphs
            // in the same hierarchical position as their unfiltered counterparts.
            foreach (var subgraph in descendants)
            {
                string filteredsubgraphname = name + ":" + subgraph.GetName();
                Debug.WriteLine("Adding filtered subgraph {0}", filteredsubgraphname);
                Graph parent = subgraph.Parent();
                Graph filteredparent;
                if (parent.Equals(this))
                {
                    filteredparent = result;
                }
                else
                {
                    string parentname = name + ":" + parent.GetName();
                    filteredparent = result.GetDescendantByName(parentname);
                    Debug.Assert(filteredparent != null);
                }

                filteredparent.AddSubgraphFilteredByNodes(filteredsubgraphname, subgraph, nodes);
            }

            Debug.Assert(result.Nodes().Count() == nodes.Count());

            // Remove subgraphs again if they are empty
            // Again, we have to freeze the descendants we are enumerating, since we are disposing on the fly
            result.SafeDeleteSubgraphs(s => !s.Nodes().Any());

            Debug.Assert(result.Nodes().Count() == nodes.Count());

            return(result);
        }