Glory to Russia
Glory to Russia

Reputation: 18712

How to create an edge from a node to a subgraph in Graphviz Dot?

I want to create a graph that looks like this, i. e. where an edge goes from the node Manufacturer of means of production to the subgraph with the same name.

Expected result

I wrote the following code for this:

digraph G {
    rankdir=LR;
    compound=true;

    graph [fontname="Liberation Mono"];
    node [fontname="Liberation Mono"];
    edge [fontname="Liberation Mono"];

    subgraph cluster0 {
        label="System components";
        mmp [label="Manufacturer of means of production", shape=box];
    }

    subgraph cluster1 {
        t1start [label="Start of tact 1", shape=point]
        t1end [label="End of tact 1", shape=point ]
        subgraph cluster1_mmp {
            label="Manufacturer of means of production"

            cluster1_1 [label="Node 1", color=white]


            subgraph cluster1_1_1 {
                label="Technological cycle 1"

                cluster1_1_1 [label="Node 2", color=white]
            }
            subgraph cluster1_1_2 {
                label="Technological cycle 2"

                cluster1_1_2 [label="Node 2", color=white]
            }
        }
    }

    subgraph cluster2 {
        label="Такт 2"
        t2start [label="Start of tact 2", shape=point]
        t2end [label="End of tact 2", shape=point]

    }
    t1end -> t2start
    mmp -> cluster1_1 [ltail=cluster1_mmp]; 
}

If I try to compile this code ("C:\Program Files (x86)\Graphviz2.38\bin\"dot.exe -Tpng -ograph.png graph.dot ), I get the warning Warning: mmp -> cluster1_1: tail not inside tail cluster cluster1_mmp.

How can I fix it and make the edge go to the subgraph?

Update 1:

Below you can find the image of the expected result -- an edge that goes from a node to a subgraph (subgraph, not a node inside the subgraph). This edge is red in the image below.

Expected result

Update 2: Changed the code like shown below.

digraph G {
    rankdir=LR;
    compound=true;

    graph [fontname="Liberation Mono"];
    node [fontname="Liberation Mono"];
    edge [fontname="Liberation Mono"];

    subgraph cluster0 {
        label="System components";
        mmp [label="Manufacturer of means of production", shape=box];
    }

    subgraph cluster1 {
        t1start [label="Start of tact 1", shape=point]
        t1end [label="End of tact 1", shape=point ]
        subgraph cluster1_mmp {
            label="Manufacturer of means of production"

            testNode [label="Node 1", color=white]

            subgraph cluster1_1_1 {
                label="Technological cycle 1"

                cluster1_1_1 [label="Node 2", color=white]
            }
            subgraph cluster1_1_2 {
                label="Technological cycle 2"

                cluster1_1_2 [label="Node 2", color=white]
            }
        }
    }

    subgraph cluster2 {
        label="Такт 2"
        t2start [label="Start of tact 2", shape=point]
        t2end [label="End of tact 2", shape=point]

    }
    t1end -> t2start
    mmp -> cluster1 [ltail=cluster0, lhead=cluster1, label="           "];

}

Second attempt

Upvotes: 7

Views: 4527

Answers (2)

Tarun Lalwani
Tarun Lalwani

Reputation: 146510

You need to change your last line

mmp -> cluster1_1 [ltail=cluster1_mmp];

to

mmp -> cluster1_1 [lhead=cluster1 label="           "]

And then the graph comes as expected

Issue fixed

Also if you want the edge to start from outside the box then you would do

mmp -> cluster1_1 [ltail=cluster0 lhead=cluster1 label="           "];

Box outside

Edit

The final code used

digraph G {
    rankdir=LR;
    compound=true;

    graph [fontname="Liberation Mono"];
    node [fontname="Liberation Mono"];
    edge [fontname="Liberation Mono"];

    subgraph cluster0 {
        label="System components";
        mmp [label="Manufacturer of means of production", shape=box];
    }

    subgraph cluster1 {
        t1start [label="Start of tact 1", shape=point]
        t1end [label="End of tact 1", shape=point ]
        subgraph cluster1_mmp {
            label="Manufacturer of means of production"

            cluster1_1 [label="Node 1", color=white]


            subgraph cluster1_1_1 {
                label="Technological cycle 1"

                cluster1_1_1 [label="Node 2", color=white]
            }
            subgraph cluster1_1_2 {
                label="Technological cycle 2"

                cluster1_1_2 [label="Node 2", color=white]
            }
        }
    }

    subgraph cluster2 {
        label="Такт 2"
        t2start [label="Start of tact 2", shape=point]
        t2end [label="End of tact 2", shape=point]

    }
    t1end -> t2start
    mmp -> cluster1_1 [lhead=cluster1 label="           "]
}

The fiddle link for the same

Fiddle

Upvotes: 6

PertinentDetail
PertinentDetail

Reputation: 141

Urm, did you just mean "lhead=cluster1_mmp" rather than ltail?

Your edge is specified as:

mmp -> cluster1_1 [ltail=cluster1_mmp]; 

The error message you have is "Warning: mmp -> cluster1_1: tail not inside tail cluster cluster1_mmp"

This says that your tail is not inside the tail cluster. The tail cluster is cluster1_mmp. cluster1_1, which is what you're trying to connect to is definitely inside cluster1_mmp. This explains your confusion.

Only after much investigation with a GraphvizFiddle did I eventually remember that with an arrow the pointy end is the head (that is, the syntax is tail -> head).

So, cluster1_1, the node you're trying to says is in cluster1_mmp is the head of the arrow. That's why your ltail specification isn't working. Changing it to lhead gets rid of the error message and generates a graph that looks like your picture. The arrow goes to the subgraph, exactly what you asked for in your question.

Here's are two GraphvizFiddles, one of the original code generating the original error and one with ltail changed to lhead which matches your picture.

(I'm sure I've spent ages debugging the same problem in my own graphs. Perhaps Graphviz could get an update to check if the the ltail parameter would make sense for the arrow head and vice versa and spit out a more helpful error message.)

Upvotes: 0

Related Questions