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