Keith Thompson
Keith Thompson

Reputation: 263267

Horizontally partitioning nodes in a graph

I'm using the dot command to generate a graph of, in this case, a series of software releases, showing the relationship among the releases.

Assumptions:

I can generate a graph that clearly shows the relationships among the releases, but I also want to put all the "alt" releases on the right side of the vertical graph, and all the non-"alt" releases on the left side -- while maintaining all the relationship information (which means arrows going from the left side of the graph to the right, and vice versa).

I've tried putting the "alt" nodes into a subgraph/cluster, but that loses the dependencies (arrows) between nodes in the cluster and nodes outside it.

I've also tried creating an invisible node in the "middle" and defining dependencies from every node to the "middle" node while specifying the direction, but I was unable to mix vertical and horizontal dependencies in the same graph.

Here's the demo.dot file I have so far, which does not do the partitioning I want:

digraph releases {
// Use a box shape for all nodes
    node [shape=box];

// Define labels for nodes
    v106 [style=bold];
    v105 [label="v105 alt" style=dashed];
    v104;
    v103;
    v102 [label="v102 alt" style=dashed];
    v101 [style=bold];

// Define dependencies
    v106 -> v104;
    v106 -> v105 [style=dashed];
    v105 -> v102;
    v104 -> v101;
    v103 -> v101;
    v102 -> v101;

// Use [style=invisible dir=none] to ensure that a later node appears above
// an earlier one even if there's no dependency.
    v106 -> v105 [style=invisible dir=none];
    v105 -> v104 [style=invisible dir=none];
    v104 -> v103 [style=invisible dir=none];
    v103 -> v102 [style=invisible dir=none];
    v102 -> v101 [style=invisible dir=none];

}

And here's the image file, generated with dot -Tpng demo.dot -o demo.png

demo.png

What I want is to have all the "alt" nodes to the right of an invisible vertical line and all the other nodes to the left of it, with all the arrows still in place (distorted as necessary).

Is there a way to do this with dot? Or is there another tool (usable on Linux, specifically Debian) that can do the same thing?

Upvotes: 3

Views: 734

Answers (2)

stefan
stefan

Reputation: 3759

This is a very late answer but may help others.

Graphviz tries to keep edges straight if both nodes belog to the same group.

digraph releases { nodesep=0.5
    // Use a box shape for all nodes
    node [shape=box];

    // Define regular nodes
    {
        node [group=regular];
        v106 [style=bold];
        v104;
        v103;
        v101 [style=bold];
    }

    // Define alt nodes
    {
        node [group=alt style=dashed];
        v102 [label="v102 alt"];
        v105 [label="v105 alt"];
    }

    // Define dependencies
    v106 -> v104;
    v106 -> v105 [style=dashed];
    v105 -> v102;
    v104 -> v101;
    v103 -> v101;
    v102 -> v101;

    // Use [style=invisible dir=none] to ensure that a later node appears above
    // an earlier one even if there's no dependency.
    edge [style=invisible dir=none];
    v106 -> v105;
    v105 -> v104;
    v104 -> v103;
    v103 -> v102;
    v102 -> v101;

}

gives

enter image description here

Upvotes: 2

andersoj
andersoj

Reputation: 22884

Trying to do something similar. Adding this to your code gets close:

subgraph cluster_alt {
    graph [style= invisible];
    edge [style = invisible, arrowhead=none];
    weight = 10;
    v102 -> v105;
}

subgraph cluster_main {
    graph [style= invisible];
    edge [style = invisible, arrowhead=none];
    weight = 10;
    v106 -> v105-> v104->v103->v102->v101;
}

Gives me: enter image description here

The "weight" attribute pushes the edges in these invisible subgraphs towards being more vertical than the other edges (the visible ones you've already defined).

Upvotes: 0

Related Questions