Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set node direction on graphviz

Suppose this code using neato:

graph sample {
  layout=neato
  overlap=false
  splines=true
  tailclip=false
  headclip=false
  A -- I
  A -- J
  A -- B
  A -- H
  A -- E
  A -- K
  B -- D
  B -- C
  B -- L
  C -- M
  C -- N
  C -- O
  D -- P
  D -- Q
  E -- R
  F -- A
  G -- F
  H -- J
}

This gives us this diagram:

neato diagram

What I need is to place a node X, always fixed in a position south from his parent node. i.e. If I put another relation A -- X, X should be always placed south from A. And I don't really care where everything else ends up.

I've looked into the pos attribute, but it doesn't seems to be the solution since X is not really in a fixed position, but on a position relative to his relation.

Also tailport and headport, but they only define from where the edge will come out/in, but don't really affect the direction of the node.

Update

An additional image to make things clearer:

x should be south from his parent

I don't require neato, but I don't want the graph to look like a UD or LR dot tree, I don't want it to be linearly ordered. circo, fdp, sfdp, twopi are alright too.

like image 232
pablasso Avatar asked Jan 10 '12 19:01

pablasso


2 Answers

The neato program supports multiple modes, one of which can probably give you what you want. In particular, if you set mode=ipsep, you can specify dot-like constraints that are honored during the layout. For example, I take your graph and use the graph attributes

mode=ipsep
diredgeconstraints=true
levelsgap=0.5

The first turns on ipsep mode, the second tells the model to support directed edges as in dot, and the last specifies how strong the separation should be. I then set the edge dir attribute to none

edge[dir=none]

and add an edge A -- X [dir=1]

The dir=1 indicates this edge should induce a directional constraint. If I then run neato, I get the appended picture.

neato layout

The Graphviz attribute documentation http://www.graphviz.org/content/attrs provides more information about these attributes.

like image 193
Emden R. Gansner Avatar answered Jan 01 '23 14:01

Emden R. Gansner


In response to the updated constraints, one solution is to pin A and X, and then lay out the graph around them:

graph sample {
overlap=false;
splines=true;
tailclip=false;
headclip=false;

A [pin=true,pos="0,.2"]
X [pin=true,pos="0,.1"]
A -- I
A -- J
A -- B
A -- H
A -- E
A -- K
B -- D
B -- C
B -- L
C -- M
C -- N
C -- O
D -- P
D -- Q
E -- R
F -- A
G -- F
H -- J
A -- X

graph output

I tried layout with both neato and fdp, and it seems to produce a graph like what you want. Naturally, if you want to impose such a constraint on arbitrary pairs of nodes in the same graph, this solution may not work.

--- Earlier answer ---

If you're committed to using neato, I'm not certain there is a way to solve the problem without modifying the graph in a post-processing step. If neato is just a convenient default, then you should be able to solve your problem by using dot as your layout engine instead, and using "rankdir=UD", plus a couple of additional kludges if X needs to be due south.

In the event that you only need the constraint to apply for a single node X, then putting X and A together in a cluster should do the job:

graph sample {
  rankdir=UD 
  layout=dot
  overlap=false
  // .. as before
  A -- X
  subgraph clusterone {
   style=invisible
   A
   X
  }
}

If you need a strictly-south constraint to apply to arbitrary children of A, then that kind of clustering followed by the trick described in:

How to force all nodes in the same column in graphviz?

might do the trick. The attribute clusterrank=local might also be useful in that case, but I'm not certain. Hope this helps.

like image 32
Chris Avatar answered Jan 01 '23 13:01

Chris