Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>To control a pydot digraph's node position and edge length properly so that edges are parallel to each other when pointing in the same direction, no edges point straight down, and all nodes drawn to their appropriate level - invisible nodes must be used.</p> <p>In the previous SO Q/A session on this topic "how to control line angles..." I learned that invisible nodes are used to fill out missing leaf nodes. This works for some trees but there were several side effects.</p> <p>Now, I have learned to add a third invisible node to each node with both left and right nodes. The invisible nodes are not added to the tree, mind you, but are just drawn into the graph. So the tree can still be used for searching, insertion, deletion, and other methods.</p> <p>Here is a graphviz example demonstrating the solution:</p> <pre><code>digraph { nodesep=0.35 ordering=out node[style="filled", fillcolor="grey"] edge[color="blue", arrowhead="vee"] { node[shape=point style=invis] m5 m2 m8 m6 m4 } 5 -&gt; 2 5 -&gt; m5 [weight=100 style=invis] 5 -&gt; 8 2 -&gt; 1 2 -&gt; m2 [weight=100 style=invis] 2 -&gt; 4 8 -&gt; 6 8 -&gt; m8 [weight=100 style=invis] 4 -&gt; 3 4 -&gt; m4 [weight=100 style=invis] 6 -&gt; m6 [weight=100 style=invis] 6 -&gt; 7 } </code></pre> <p>Here is a snippet of my updated python code to automate this process with a typical tree class:</p> <pre><code> vT = visualizeTree(0, fileDir, 'bst_graph','.png',1) # instantiate the visualizeTree Object graph = pydot.Dot(graph_type='digraph', nodesep=.5, pad=.3, size="19.2, 10.1") graph.set_node_defaults(style="filled", fillcolor="grey") graph.set_edge_defaults(color="blue", arrowhead="vee") vT.searchTree(root, sketchTree) vT.updateGraph() class visualizeTree(object): # more code and comments located at project home def __init__(self, fileCount, fileDir, fileName, fileExt, vidFrames): def sketchTree(node, stack, find=None, draw=None): if node.getLeftBranch(): draw(str(node), str(node.getLeftBranch())) stack.append(node.getLeftBranch()) if node.getRightBranch(): # insert invisible third node in-between left and right nodes draw(str(node), ":"+str(node), style_type="invisible") elif node.getRightBranch(): # draw any missing left branches as invisible nodes/edges with dummy unique labels draw(str(node), ":"+str(node), style_type="invisible") if node.getRightBranch(): draw(str(node), str(node.getRightBranch())) stack.append(node.getRightBranch()) elif node.getLeftBranch(): # draw any missing right branches as invisible nodes/edges with dummy unique labels draw(str(node), ";"+str(node), style_type="invisible") def draw(self, parent_name, child_name, fill_color="grey", style_type='filled'): if style_type=="invisible": # save original edge defaults weight_ = "100" saveEdgeDefaults = graph.get_edge_defaults()[0] graph.set_edge_defaults(style=style_type, color="white", arrowhead="none") else: weight_ = "3" edge = pydot.Edge(parent_name, child_name, style=style_type, weight=weight_) graph.add_edge(edge) if style_type=="invisible": graph.set_edge_defaults(**saveEdgeDefaults) if not self.nodeNames: self.nodeNames[parent_name] = pydot.Node(parent_name, label=parent_name, fillcolor=fill_color, style=style_type) graph.add_node(self.nodeNames[parent_name]) if (parent_name not in self.nodeNames): self.nodeNames[parent_name] = pydot.Node(parent_name, label=parent_name, fillcolor=fill_color, style=style_type) graph.add_node(self.nodeNames[parent_name]) if child_name not in self.nodeNames: self.nodeNames[child_name] = pydot.Node(child_name, label=child_name, fillcolor=fill_color, style=style_type) graph.add_node(self.nodeNames[child_name]) </code></pre> <p><strong>Full source code can be found at the project's home:</strong> <a href="http://www.embeddedcomponents.com/blogs/2013/12/visualizing-software-tree-structures/" rel="nofollow noreferrer">http://www.embeddedcomponents.com/blogs/2013/12/visualizing-software-tree-structures/</a></p> <p><strong>Typical small images now draw as I wanted in the first place:</strong> <img src="https://i.stack.imgur.com/wPaZo.png" alt="binary search tree"></p> <p><strong>Even large trees can be drawn with similar geometry:</strong> <img src="https://i.stack.imgur.com/AylSQ.png" alt="larger binary search tree with ordered search trail"></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload