Skip to content

Instantly share code, notes, and snippets.

@miku
Forked from steveroush/improveEdgeLabels.gvpr
Created January 28, 2025 16:15
Show Gist options
  • Save miku/67d25cd0080e27213a5191ba887d8ccf to your computer and use it in GitHub Desktop.
Save miku/67d25cd0080e27213a5191ba887d8ccf to your computer and use it in GitHub Desktop.

Revisions

  1. @steveroush steveroush created this gist Jun 5, 2023.
    196 changes: 196 additions & 0 deletions improveEdgeLabels.gvpr
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,196 @@
    /***********************************************
    1. save this file as improveEdgeLabels.gvpr
    2. what it does: it allows you to re-position Graphviz edge labels
    3. command line example (works with any Graphviz engine):
    dot myfile.gv |gvpr -cf improveEdgeLabels.gvpr |neato -n2 -Tpng >myfile.png
    4. how to use:
    improveEdgeLabels adds 3 new edge attributes to Graphviz:
    - labelOverlay, labelAdjust, label2Node
    - they can be used separately or in combination
    - if labelOverlay=true
    overlay label/xlabel on-top-of edge - centered
    - if labelOverlay=n% (n is integer)
    overlay label/xlabel on-top-of edge - n% of the way from tail-to-head
    - if labelAdjust (X,Y)
    adjust edge.lp by X,Y (either/both can be negative)
    - if label2Node = true
    delete the edge label
    replace the edge label with a node, where pos=edge.lp
    set node attributes
    #### future:
    - set/change various attributes of the new node
    *************************************************/
    BEGIN{
    int i, cnt, LN=0;
    string tStr, tok[int];
    graph_t Root;

    // do NOT call with direct output from sprintf - there is a bug - string will be empty
    void doError(string eString) {
    printf(2, "Error:: %s\n", eString);
    }
    ////////////////////////////////////////////////////////////////////
    int istrue(string checkme, int rc) {
    checkme = tolower(checkme);
    if (checkme == "@(1|yes|true)") // ksh syntax
    rc=1;
    else
    rc=0;
    return(rc);
    }
    /////////////////////////////////////////////////////////////////
    string overlayPos(string Pos, string cmd) {
    string p1, p2, pnew;
    float x1, y1, x2, y2, dx, dy, percent;
    p1="";
    if (cmd=="(+([0-9])\%)") {
    percent=.01 * (float)sub(cmd,"%");
    } else {
    percent=.5;
    }
    cnt=tokens(Pos, tok);
    for (i=0; i<cnt; i++) {
    if (tok[i]=="[es]*")
    continue;
    if (p1=="") {
    p1=tok[i];
    }
    if (i==cnt-1)
    p2=tok[i];
    }
    //print("// cmd: ", cmd, " p1: ", p1," p2: ",p2);
    //print("// PERCENT: ", percent );
    x1=(float)xOf(p1);
    x2=(float)xOf(p2);
    y1=(float)yOf(p1);
    y2=(float)yOf(p2);
    dx=x2-x1;
    dy=y2-y1;
    return (string)(x1 + percent*dx) + ", " + (string)(y1 + percent*dy);
    }
    ///////////////////////////////////////////////////////////////////
    string adjustPos(string Pos, string adj) {
    string newPt;
    newPt=(string)((float)xOf(Pos) + (float)xOf(adj)) + ", " + (string)((float)yOf(Pos) + (float)yOf(adj));
    return newPt;
    }
    }
    BEG_G{
    Root=$G;
    $G.notranslate="true"; // fighting pos changes for created nodes
    if (!(hasAttr(Root, "splines") && Root.splines!=""))
    Root.splines="true";
    }
    N{
    $.REALLY_USE_THIS_pos=$.pos;
    }
    E{
    if (hasAttr($, "labelOverlay")) {
    if (istrue($.labelOverlay) || $.labelOverlay=="(+([0-9])\%)") {
    if (hasAttr($, "lp") && $.lp!="") {
    $.preOverlaylp=$.lp;
    $.lp=overlayPos($.pos, $.labelOverlay);
    }
    } else {
    doError("For edge " + $.name + ", invalid value (" + $.labelOverlay + ") for labelOverlay attribute");
    }
    }
    if (hasAttr($, "labelAdjust") && ($.labelAdjust!="")) {
    if (hasAttr($, "lp") && $.lp!="") {
    $.preAdjustlp=$.lp;
    $.lp=adjustPos($.lp, $.labelAdjust);
    }
    }
    if (hasAttr($, "label2node") && istrue($.label2node)) {
    node_t aNode;
    string lbl, rep, s1, s2;
    if (hasAttr($, "lp") && $.lp!="") {
    $.preL2Nlp=$.lp;
    $.preL2Nlabel=$.label;
    //// create node
    tStr="__labelNODE__" + (string)++LN;
    aNode=node($G, tStr);
    lbl=$.label;
    rep=$.tail.name;
    /********** problem w/ gsub, so roll our own ***********/
    print ("// escape stuff >", lbl);
    while (i=index(lbl,"\\T"), i!=-1) {
    //print ("// x ", lbl, " ",i);
    if (i>0)
    s1=substr(lbl,0,i-1);
    else
    s1="";
    if (i<(length(lbl)-2))
    s2=substr(lbl,i+1);
    else
    s2="";
    lbl=s1 + rep + s2;
    }
    print("// lbl:", lbl);
    while (i=index(lbl,"\H"), i!=-1) {
    //print ("// y ", lbl, " ",i);
    lbl=substr(lbl,0,i-1) + rep + substr(lbl,i+1);
    }
    //print("// lbl:", lbl);
    while (i=index(lbl,"\E"), i!=-1) {
    //print ("// z ", lbl, " ",i);
    lbl=substr(lbl,0,i-1) + rep + substr(lbl,i+1);
    }
    //print("// lbl:", lbl);
    aNode.label=lbl;
    aNode.shape="plaintext";
    aNode.style="filled";
    aNode.width=".05";
    aNode.height=".05";
    aNode.margin="0.01,0.01";
    aNode.fillcolor="white";
    aNode.pos=$.lp;
    // clean-up edge attributes
    $.label="";
    $.lp="";
    $._comment="edge label replaced by " + tStr;
    }
    }
    }

    /******************* test graph **************************

    graph straight {
    splines=false
    edge [label="\T" labelOverlay=true color=purple]
    node [shape=rect style=filled fillcolor=lightblue]

    a1 -- b1
    c1 -- d1 [labelOverlay="15%" label=high]
    e1 -- f1 [label2node=true labelOverlay="75%" label=low]
    g1:sw -- h1:nw
    g1:s -- h1:n [labelOverlay="20%"]
    g1:se -- h1:ne
    j1 -- k1 [ label2node=true]

    node[shape=square style=filled fillcolor=lightgreen]
    {rank=sink
    edge [fontcolor=red]
    Aaa -- B3 [labelOverlay="33%"]
    C98 -- D3 [labelOverlay="80%" label2node=true]
    Eee -- F6 [label="adjust me" labelAdjust="45,-25"]
    G12 -- H3 [label2node=true]
    node [shape=plain fontcolor=blue style=""]
    Lxx -- M123
    Noo -- Ooo [label2node=true]
    node [shape=oval fontcolor=blue style=""]
    P -- Q
    }

    node[shape=circle style=filled fillcolor=pink]
    edge [label2node=true label="aeiou" labelOverlay="78%"]
    10 -- {11 12}
    10 -- 13 [labelOverlay="38%"]
    10 -- 14 [labelOverlay="62%"]
    edge [label="three"]
    node [shape=Mrecord]
    13 -- 21
    edge [labelOverlay="55%" label="T\nh\nr\ne\ne\n \n33"] 13 -- 22
    edge [labelOverlay="60%"] 13 -- 23
    }
    *************************************************/