1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| // from Emden Gansner // https://mailman.research.att.com/pipermail/graphviz-interest/2010q2/007101.html // requires GraphViz 2.28.0 (fails with 2.26.3 at least) BEGIN { double tw[node_t]; // width of tree rooted at node double nw[node_t]; // width of node double xoff[node_t]; // x offset of root from left side of its tree double sp = 36; // extra space between left and right subtrees double wd, w, w1, w2; double x, y, z; edge_t e1, e2; node_t n; } BEG_G { $.bb = ""; $tvtype=TV_postfwd; // visit root after all children visited } N { sscanf ($.width, "%f", &w); w *= 72; // convert inches to points nw[$] = w; if ($.outdegree == 0) { tw[$] = w; xoff[$] = w/2.0; } else if ($.outdegree == 1) { e1 = fstout($); w1 = tw[e1.head]; tw[$] = w1 + (sp+w)/2.0; if (e1.side == "left") xoff[$] = tw[$] - w/2.0; else xoff[$] = w/2.0; } else { e1 = fstout($); w1 = tw[e1.head]; e2 = nxtout(e1); w2 = tw[e2.head]; wd = w1 + w2 + sp; if (w > wd) wd = w; tw[$] = wd; xoff[$] = w1 + sp/2.0; } } BEG_G { $tvtype=TV_fwd; // visit root first, then children } N { if ($.indegree == 0) { sscanf ($.pos, "%f,%f", &x, &y); $.pos = sprintf("0,%f", y); } if ($.outdegree == 0) return; sscanf ($.pos, "%f,%f", &x, &y); wd = tw[$]; e1 = fstout($); n = e1.head; sscanf (n.pos, "%f,%f", &z, &y); if ($.outdegree == 1) { if (e1.side == "left") n.pos = sprintf("%f,%f", x - tw[n] - sp/2.0 + xoff[n], y); else n.pos = sprintf("%f,%f", x + sp/2.0 + xoff[n], y); } else { n.pos = sprintf("%f,%f", x - tw[n] - sp/2.0 + xoff[n], y); e2 = nxtout(e1); n = e2.head; sscanf (n.pos, "%f,%f", &z, &y); n.pos = sprintf("%f,%f", x + sp/2.0 + xoff[n], y); } }
|