|  |  | @@ -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 | 
    
    |  |  | } | 
    
    |  |  | *************************************************/ |