/// <summary> /// An edge can define a cluster as logical head. /// This is used to fake edges to and from clusters by clipping the edge on the borders of the logical head. /// </summary> public void SetLogicalHead(SubGraph lhead) { if (!lhead.IsCluster()) { throw new InvalidOperationException("ltail must be a cluster"); } if (!MyRootGraph.IsCompound()) { throw new InvalidOperationException("rootgraph must be compound for lheads/ltails to be used"); } string lheadname = lhead.GetName(); SafeSetAttribute("lhead", lheadname, ""); }
/// <summary> /// FIXME: use an actual subg equivalent to agsubedge and agsubnode /// https://github.com/ellson/graphviz/issues/1206 /// This might cause a new subgraph creation. /// </summary> public void AddExisting(SubGraph subgraph) { Agsubg(_ptr, subgraph.GetName(), 1); }
public SubGraph OppositeLogicalEndpoint(SubGraph s) { Debug.Assert(s == LogicalTail() || s == LogicalHead()); return(s == LogicalTail() ? LogicalHead() : LogicalTail()); }
public void CloneInto(RootGraph target) { // Copy all nodes and edges foreach (var node in Nodes()) { string nodename = node.GetName(); Node newnode = target.GetOrAddNode(nodename); foreach (var edge in node.EdgesOut(this)) { Node head = edge.Head(); Debug.Assert(Contains(head)); Node tail = edge.Tail(); Debug.Assert(node.Equals(tail)); string headname = head.GetName(); Node newhead = target.GetOrAddNode(headname); string tailname = tail.GetName(); Node newtail = target.GetNode(tailname); string edgename = edge.GetName(); Edge newedge = target.GetOrAddEdge(newtail, newhead, edgename); edge.CopyAttributesTo(newedge); } node.CopyAttributesTo(newnode); } // Copy all subgraphs foreach (var subgraph in Descendants()) { string subgraphname = subgraph.GetName(); Graph parent = subgraph.Parent(); Graph newparent; if (parent.Equals(this)) { newparent = target; } else { string parentname = parent.GetName(); newparent = target.GetDescendantByName(parentname); Debug.Assert(newparent != null); } SubGraph newsubgraph = newparent.GetOrAddSubgraph(subgraphname); subgraph.CopyAttributesTo(newsubgraph); // Add the (already created) nodes and edges to newly created subgraph foreach (var node in subgraph.Nodes()) { string nodename = node.GetName(); Node newnode = target.GetNode(nodename); Debug.Assert(newnode != null); newsubgraph.AddExisting(newnode); foreach (var edge in node.EdgesOut(subgraph)) { Node head = edge.Head(); Node tail = edge.Tail(); Debug.Assert(node.Equals(tail)); string headname = head.GetName(); Node newhead = target.GetNode(headname); string tailname = tail.GetName(); Node newtail = target.GetNode(tailname); string edgename = edge.GetName(); Edge newedge = target.GetEdge(newtail, newhead, edgename); newsubgraph.AddExisting(newedge); } node.CopyAttributesTo(newnode); } } }
/// <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); }
public SubGraph GetSubgraph(string name) { return(SubGraph.Get(this, name)); }
public SubGraph GetOrAddSubgraph(string name) { return(SubGraph.GetOrCreate(this, name)); }