Created
June 5, 2023 02:21
-
-
Save steveroush/b45d4c2b79019128d64e7292da955436 to your computer and use it in GitHub Desktop.
A GVPR program to improve Graphviz edge labels
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*********************************************** | |
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 | |
} | |
*************************************************/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment