Draw Arc between Edge Labels

Hello everyone,

I try to accomplish something like the left graph

and I got pretty far (right one). The only thing that drives me crazy are those dotted arcs between the edge labels. Is there any way to achieve this using graphviz?

Here’s the code of what I got so far:

digraph {
    compound=true dpi=150
    node [color=grey70 shape=circle style=filled]
    edge [arrowhead=normal]
    subgraph cluster_global {
	    style=invis
	    global_void [label="" style=invis]
    }
    subgraph cluster_lts_1 {
	    label=lts_p
	    color=grey95 style="filled,rounded"
	    cluster_lts_1_p1 [label=p1]
	    cluster_lts_1_p2 [label=p2]
	    cluster_lts_1_p3 [label=p3]
	    cluster_lts_1_p4 [label=p4]
	    global_void -> cluster_lts_1_p1
	    cluster_lts_1_p1 -> cluster_lts_1_p2 [label="A'"]
	    cluster_lts_1_p2 -> cluster_lts_1_p4 [label="B'"]
	    cluster_lts_1_p2 -> cluster_lts_1_p3 [label="C'"]
	    cluster_lts_1_p3 -> cluster_lts_1_p4 [label=Z]
    }
    subgraph cluster_lts_2 {
	    label=lts_q
	    color=grey95 style="filled,rounded"
	    cluster_lts_2_q1 [label=q1]
	    cluster_lts_2_q2 [label=q2]
	    cluster_lts_2_q3 [label=q3]
	    cluster_lts_2_q4 [label=q4]
	    cluster_lts_2_q5 [label=q5]
	    global_void -> cluster_lts_2_q1
	    cluster_lts_2_q1 -> cluster_lts_2_q2 [label=X]
	    cluster_lts_2_q2 -> cluster_lts_2_q3 [label=A]
	    cluster_lts_2_q3 -> cluster_lts_2_q4 [label=B]
	    cluster_lts_2_q3 -> cluster_lts_2_q4 [label=C]
	    cluster_lts_2_q4 -> cluster_lts_2_q5 [label=Y]
    }
}

Some dirty hack like placing an invisible node on an edge label would be perfectly fine. Thanks in advance!

Here is an example of what you are attempting. An edge cannot connect to another edge, but you can split the edge using invisible nodes, and then connect the invisible nodes with the dotted edges.

Create a node with color="invis" (shape="point" is good for this). Connect your tail node to the invisible node with edge attributes arrowhead="none" headclip="true". Next connect your invisible node to your head node with edge attributes tailclip="true". At this point it should appear that there is a directed edge from your tail node to your head node.

Repeat the process for another edge. Now you can connect the invisible nodes with an edge having style="dotted".

Additional techniques/tricks used

To replicated your desired graph I applied a couple other tricks. I used an invisible circle of fixedsize="true" width="0.3" diameter for the invisible nodes. This small circle gives the appearance of a gap between the arrow head of the dotted edge from the solid edge. Because the invisible circle node has a size, you have to use the headclip= and tailclip= attributes as mentioned previously to ensure the edges go all the way to the center of the circle, otherwise it will appear that your edge has a gap in it.

To get the labels near the arrowheads of the dotted line I used the headlabel= or taillabel= attributes. The label attribute will put the label in the center of the edge, but since we split the edge in half you have to shift the label down to the end of the edge.

The weight= attribute was used to straighten out some of the vertical edges.

Ranking was used to align the visible circle nodes. The graph option newrank="true" was specified to use the algorithm which ranks nodes while ignoring clusters.

The dotted edges are created after the clusters are complete. You must include the attribute constraint="false" on these edges, otherwise the ranking is ignored and the circle nodes do not align horizontally.

Here is the complete code for the diagram above:

digraph "main"
{
    newrank="true";
    rankdir="TB";
    splines="spline";
    
    graph[ fontname="consolas" fontsize="10" ];
    node[ shape="circle" color="grey70" style="filled" fontname="consolas" fontsize="10" ];
    edge[ fontname="consolas" fontsize="10" ];

    subgraph "cluster_1" {  color="grey95" style="filled,rounded" label="lts_q"
        "invisible_Q2A"[ shape="circle" width=".3" fixedsize="true" color="invis" label="" ];
        "invisible_Q3B"[ shape="circle" width=".3" fixedsize="true" color="invis" label="" ];
        "invisible_Q4C"[ shape="circle" width=".3" fixedsize="true" color="invis" label="" ];
        "q1" -> "q2"[ label="1/X" ];
        "q2" -> "invisible_Q2A"[ arrowhead="none" headclip="false" ];
        "invisible_Q2A" -> "q3"[ weight="100" tailclip="false" taillabel="2/A" ];
        "q3" -> "invisible_Q3B"[ arrowhead="none" headclip="false" ];
        "invisible_Q3B" -> "q4"[ tailclip="false" taillabel="3/B" ];
        "q3" -> "invisible_Q4C"[ arrowhead="none" headclip="false" ];
        "invisible_Q4C" -> "q4"[ tailclip="false" taillabel="4/C" ];
        "q4" -> "q5"[ label="Y" ];
    }

    subgraph "cluster_2" {  color="grey95" style="filled,rounded" label="lts_p"
        "invisible_P1A"[ shape="circle" width=".3" fixedsize="true" color="invis" label="" ];
        "invisible_P3C"[ shape="circle" width=".3" fixedsize="true" color="invis" label="" ];
        "invisible_P2B"[ shape="circle" width=".3" fixedsize="true" color="invis" label="" ];
        "p1" -> "invisible_P1A"[ arrowhead="none" headclip="false" ];
        "invisible_P1A" -> "p2"[ weight="100" tailclip="false" taillabel="1/A" ];
        "p2" -> "invisible_P2B"[ arrowhead="none" headclip="false" ];
        "invisible_P2B" -> "p4"[ tailclip="false" taillabel="2/B'" ];
        "p2" -> "invisible_P3C"[ arrowhead="none"  headclip="false" weight="100" ];
        "invisible_P3C" -> "p3"[ weight="100" tailclip="false" taillabel="3/C" ];
        "p3" -> "p4"[ weight="100" label="4/Z" ];
    }

    "invisible_P1A" -> "invisible_Q2A"[ style="dotted" dir="both" arrowhead="vee" arrowtail="vee" constraint="false" ];
    "invisible_P2B" -> "invisible_Q3B"[ style="dotted" dir="both" arrowhead="vee" arrowtail="vee" constraint="false" ];
    "invisible_P3C" -> "invisible_Q4C"[ style="dotted" dir="both" arrowhead="vee" arrowtail="vee" constraint="false" ];
 
    { rank="same"; "p1"; "q1"; }
    { rank="same"; "p2"; "q2"; }
    { rank="same"; "p3"; "q3"; }
    { rank="same"; "p4"; "q4"; }
}

This dot code was created using “Excel for Graphviz” as the IDE. You can download a free copy from SourceForge here.

Well, that’s the kind of dirty hack I was expecting :smiley:

In the mean time I had a similar idea but discarded it since I was expecting it to blow up the layout. So I ended up using colors for highlighting the relation. However, I think I give it a shot now. Thank you so much!