00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "dot.h"
00019
00020
00021 static node_t *make_vn_slot(graph_t * g, int r, int pos)
00022 {
00023 int i;
00024 node_t **v, *n;
00025
00026 v = GD_rank(g)[r].v =
00027 ALLOC(GD_rank(g)[r].n + 2, GD_rank(g)[r].v, node_t *);
00028 for (i = GD_rank(g)[r].n; i > pos; i--) {
00029 v[i] = v[i - 1];
00030 v[i]->u.order++;
00031 }
00032 n = v[pos] = virtual_node(g);
00033 ND_order(n) = pos;
00034 ND_rank(n) = r;
00035 v[++(GD_rank(g)[r].n)] = NULL;
00036 return v[pos];
00037 }
00038
00039 #define HLB 0
00040 #define HRB 1
00041 #define SLB 2
00042 #define SRB 3
00043
00044 static void findlr(node_t * u, node_t * v, int *lp, int *rp)
00045 {
00046 int l, r;
00047 l = ND_order(u);
00048 r = ND_order(v);
00049 if (l > r) {
00050 int t = l;
00051 l = r;
00052 r = t;
00053 }
00054 *lp = l;
00055 *rp = r;
00056 }
00057
00058 static void setbounds(node_t * v, int *bounds, int lpos, int rpos)
00059 {
00060 int i, l, r, ord;
00061 edge_t *f;
00062
00063 if (ND_node_type(v) == VIRTUAL) {
00064 ord = ND_order(v);
00065 if (ND_in(v).size == 0) {
00066 assert(ND_out(v).size == 2);
00067 findlr(ND_out(v).list[0]->head, ND_out(v).list[1]->head, &l,
00068 &r);
00069
00070 if (r <= lpos)
00071 bounds[SLB] = bounds[HLB] = ord;
00072 else if (l >= rpos)
00073 bounds[SRB] = bounds[HRB] = ord;
00074
00075 else if ((l < lpos) && (r > rpos));
00076
00077 else {
00078 if ((l < lpos) || ((l == lpos) && (r < rpos)))
00079 bounds[SLB] = ord;
00080 if ((r > rpos) || ((r == rpos) && (l > lpos)))
00081 bounds[SRB] = ord;
00082 }
00083 } else {
00084 boolean onleft, onright;
00085 onleft = onright = FALSE;
00086 for (i = 0; (f = ND_out(v).list[i]); i++) {
00087 if (ND_order(f->head) <= lpos) {
00088 onleft = TRUE;
00089 continue;
00090 }
00091 if (ND_order(f->head) >= rpos) {
00092 onright = TRUE;
00093 continue;
00094 }
00095 }
00096 if (onleft && (onright == FALSE))
00097 bounds[HLB] = ord + 1;
00098 if (onright && (onleft == FALSE))
00099 bounds[HRB] = ord - 1;
00100 }
00101 }
00102 }
00103
00104 static int flat_limits(graph_t * g, edge_t * e)
00105 {
00106 int lnode, rnode, r, bounds[4], lpos, rpos, pos;
00107 node_t **rank;
00108
00109 r = ND_rank(e->tail) - 1;
00110 rank = GD_rank(g)[r].v;
00111 lnode = 0;
00112 rnode = GD_rank(g)[r].n - 1;
00113 bounds[HLB] = bounds[SLB] = lnode - 1;
00114 bounds[HRB] = bounds[SRB] = rnode + 1;
00115 findlr(e->tail, e->head, &lpos, &rpos);
00116 while (lnode <= rnode) {
00117 setbounds(rank[lnode], bounds, lpos, rpos);
00118 if (lnode != rnode)
00119 setbounds(rank[rnode], bounds, lpos, rpos);
00120 lnode++;
00121 rnode--;
00122 if (bounds[HRB] - bounds[HLB] <= 1)
00123 break;
00124 }
00125 if (bounds[HLB] <= bounds[HRB])
00126 pos = (bounds[HLB] + bounds[HRB] + 1) / 2;
00127 else
00128 pos = (bounds[SLB] + bounds[SRB] + 1) / 2;
00129 return pos;
00130 }
00131
00132
00133
00134
00135
00136
00137
00138 static void
00139 flat_node(edge_t * e)
00140 {
00141 int r, place, ypos, h2;
00142 graph_t *g;
00143 node_t *n, *vn;
00144 edge_t *ve;
00145 pointf dimen;
00146
00147 if (ED_label(e) == NULL)
00148 return;
00149 g = e->tail->graph;
00150 r = ND_rank(e->tail);
00151
00152 place = flat_limits(g, e);
00153
00154 if ((n = GD_rank(g)[r - 1].v[0]))
00155 ypos = ND_coord_i(n).y - GD_rank(g)[r - 1].ht1;
00156 else {
00157 n = GD_rank(g)[r].v[0];
00158 ypos = ND_coord_i(n).y + GD_rank(g)[r].ht2 + GD_ranksep(g);
00159 }
00160 vn = make_vn_slot(g, r - 1, place);
00161 dimen = ED_label(e)->dimen;
00162 if (GD_flip(g)) {
00163 double f = dimen.x;
00164 dimen.x = dimen.y;
00165 dimen.y = f;
00166 }
00167 ND_ht_i(vn) = dimen.y;
00168 h2 = ND_ht_i(vn) / 2;
00169 ND_lw_i(vn) = ND_rw_i(vn) = dimen.x / 2;
00170 ND_label(vn) = ED_label(e);
00171 ND_coord_i(vn).y = ypos + h2;
00172 ve = virtual_edge(vn, e->tail, e);
00173 ED_tail_port(ve).p.x = -ND_lw_i(vn);
00174 ED_head_port(ve).p.x = ND_rw_i(e->tail);
00175 ED_edge_type(ve) = FLATORDER;
00176 ve = virtual_edge(vn, e->head, e);
00177 ED_tail_port(ve).p.x = ND_rw_i(vn);
00178 ED_head_port(ve).p.x = ND_lw_i(e->head);
00179 ED_edge_type(ve) = FLATORDER;
00180
00181 if (GD_rank(g)[r - 1].ht1 < h2)
00182 GD_rank(g)[r - 1].ht1 = h2;
00183 if (GD_rank(g)[r - 1].ht2 < h2)
00184 GD_rank(g)[r - 1].ht2 = h2;
00185 ND_alg(vn) = e;
00186 }
00187
00188 static void abomination(graph_t * g)
00189 {
00190 int r;
00191 rank_t *rptr;
00192
00193 assert(GD_minrank(g) == 0);
00194
00195 r = GD_maxrank(g) + 3;
00196 rptr = ALLOC(r, GD_rank(g), rank_t);
00197 GD_rank(g) = rptr + 1;
00198 for (r = GD_maxrank(g); r >= 0; r--)
00199 GD_rank(g)[r] = GD_rank(g)[r - 1];
00200 GD_rank(g)[r].n = GD_rank(g)[0].an = 0;
00201 GD_rank(g)[r].v = GD_rank(g)[0].av = N_NEW(2, node_t *);
00202 GD_rank(g)[r].flat = NULL;
00203 GD_rank(g)[r].ht1 = GD_rank(g)[r].ht2 = 1;
00204 GD_rank(g)[r].pht1 = GD_rank(g)[r].pht2 = 1;
00205 GD_minrank(g)--;
00206 }
00207
00208
00209
00210
00211
00212 static int
00213 flatAdjacent (edge_t* e)
00214 {
00215 node_t* tn = e->tail;
00216 node_t* hn = e->head;
00217 int i, lo, hi;
00218 node_t* n;
00219 rank_t *rank;
00220
00221 if (ND_order(tn) < ND_order(hn)) {
00222 lo = ND_order(tn);
00223 hi = ND_order(hn);
00224 }
00225 else {
00226 lo = ND_order(hn);
00227 hi = ND_order(tn);
00228 }
00229 rank = &(GD_rank(tn->graph)[ND_rank(tn)]);
00230 for (i = lo + 1; i < hi; i++) {
00231 n = rank->v[i];
00232 if ((ND_node_type(n) == VIRTUAL && ND_label(n)) ||
00233 ND_node_type(n) == NORMAL)
00234 break;
00235 }
00236 return (i == hi);
00237 }
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 int
00257 flat_edges(graph_t * g)
00258 {
00259 int i, j, reset = FALSE;
00260 node_t *n;
00261 edge_t *e;
00262 int found = FALSE;
00263
00264 for (n = GD_nlist(g); n; n = ND_next(n)) {
00265 if (!ND_flat_out(n).list) continue;
00266 for (j = 0; (e = ND_flat_out(n).list[j]); j++) {
00267 if (flatAdjacent (e)) ED_adjacent(e) = 1;
00268 }
00269 }
00270
00271 if ((GD_rank(g)[0].flat) || (GD_n_cluster(g) > 0)) {
00272 for (i = 0; (n = GD_rank(g)[0].v[i]); i++) {
00273 for (j = 0; (e = ND_flat_in(n).list[j]); j++) {
00274 if ((ED_label(e)) && !ED_adjacent(e)) {
00275 abomination(g);
00276 found = TRUE;
00277 break;
00278 }
00279 }
00280 if (found)
00281 break;
00282 }
00283 }
00284
00285 rec_save_vlists(g);
00286 for (n = GD_nlist(g); n; n = ND_next(n)) {
00287
00288 if (ND_flat_out(n).list) {
00289 for (i = 0; (e = ND_flat_out(n).list[i]); i++) {
00290 if (ED_label(e)) {
00291 if (ED_adjacent(e)) {
00292 if (GD_flip(g)) ED_dist(e) = ED_label(e)->dimen.y;
00293 else ED_dist(e) = ED_label(e)->dimen.x;
00294 }
00295 else {
00296 reset = TRUE;
00297 flat_node(e);
00298 }
00299 }
00300 }
00301
00302 for (j = 0; j < ND_other(n).size; j++) {
00303 edge_t* le;
00304 e = ND_other(n).list[j];
00305 if (ND_rank(e->tail) != ND_rank(e->head)) continue;
00306 if (e->tail == e->head) continue;
00307 le = e;
00308 while (ED_to_virt(le)) le = ED_to_virt(le);
00309 ED_adjacent(e) = ED_adjacent(le);
00310 if (ED_label(e)) {
00311 if (ED_adjacent(e)) {
00312 double lw;
00313 if (GD_flip(g)) lw = ED_label(e)->dimen.y;
00314 else lw = ED_label(e)->dimen.x;
00315 ED_dist(le) = MAX(lw,ED_dist(le));
00316 }
00317 else {
00318 reset = TRUE;
00319 flat_node(e);
00320 }
00321 }
00322 }
00323 }
00324 }
00325 if (reset)
00326 rec_reset_vlists(g);
00327 return reset;
00328 }