Need to control edge length in directed dot graph

Is there a way to use pydot to generate a directed tree graph (using python) that looks like "normal tree graphs" where every node of the same depth displays at the same depth, and every edge is at some angle (not straight down)?

When I use these defaults:

graph = pydot.Dot(graph_type='digraph', nodesep=.75)
graph.set_node_defaults(style="filled", fillcolor="grey")
graph.set_edge_defaults(color="blue", arrowhead="vee", weight="0")
The length of the edge between nodes 2 and 1 is too long. See link to image here: http://www.embeddedcomponents.com/blogs/wp-content/uploads/2013/12/bst_g...

I can correct the length of the node using an edge weight of "1" like:

graph.set_edge_defaults(color="blue", arrowhead="vee", weight="1")

But now two of the edges are pointing straight down between 2 and 3, and 7 and 6. See the link to image here: http://www.embeddedcomponents.com/blogs/wp-content/uploads/2013/12/bst_g...

Edges pointing straight down turns out to be a real problem. If both left and right siblings are not drawn, then it is not clear which node (left or right) is drawn.

PS: Here is a link to the home page for my automated graph animation project (full source, and sample animations):
http://www.embeddedcomponents.com/blogs/2013/12/visualizing-software-tre...

First, you probably don't

First, you probably don't want to set edge weights to 0 globally. This basically tells dot not to optimize the edge lengths at all, so they may end up much larger than you want. Second, the response you got on stackoverflow is basically the correct answer. Dot is designed for real-world graphs, where it is important to save space and where symmetry rarely arises, so you need to use invisible artifacts to guide the layout. It seems from your code that you are already doing this.

If you want to fine-tune the layout more, I would suggest attaching invisible, verticle node-edge pairs to all nodes having children. This wil guarantee left and right children really appear to the left or right. And, for nodes with only one child, this node can serve as the necessary invisible auxiliary node. I have attached a typical dot description below, which translates into the obvious pydot commands.

By the way, the appearance of arrowheads on invisible edges was a bug that was fixed a while ago.

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 ->  2
  5 ->  m5 [weight=100 style=invis]
  5 ->  8
  2 -> 1
  2 -> m2 [weight=100 style=invis]
  2 -> 4
  8 -> 6
  8 -> m8 [weight=100 style=invis]
  4 -> 3
  4 -> m4 [weight=100 style=invis]
  6 -> m6 [weight=100 style=invis]
  6 ->  7
}

 

Thank you so much "erg".

Thank you so much "erg".
Your reply made perfect sense to me.  I had to add only three lines of code to my automated tree image and search animation project to

  • insert a third "invisible" node into each node with both left/right nodes, and to
  • change the edge weight strategy to "100" to connect "invisible" nodes, and "3" to connect "visible" nodes.

I appreciate your sharing the ".gv" script so I could learn to think more clearly about the pydot interface.  Also, I noticed that you took some time to review my code and answer with information that was very pertinent to my needs.

Thank you again.  My code is now updated and available at the same link: http://www.embeddedcomponents.com/blogs/2013/12/visualizing-software-tree-structures/

 

Here are a few examples of automated sketches:

Unbalanced Tree:

 

 

Balanced Tree

 

Big Trees

Recent comments