00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "circular.h"
00032 #include "adjust.h"
00033 #include "pack.h"
00034 #include "neatoprocs.h"
00035 #include <string.h>
00036
00037 static void circular_init_node(node_t * n)
00038 {
00039 common_init_node(n);
00040
00041 neato_nodesize(n, GD_flip(n->graph));
00042 ND_pos(n) = N_NEW(GD_ndim(n->graph), double);
00043 }
00044
00045 static void circular_init_edge(edge_t * e)
00046 {
00047 common_init_edge(e);
00048
00049 ED_factor(e) = late_double(e, E_weight, 1.0, 0.0);
00050 }
00051
00052
00053 static void circular_init_node_edge(graph_t * g)
00054 {
00055 node_t *n;
00056 edge_t *e;
00057 int i = 0;
00058 ndata* alg = N_NEW(agnnodes(g), ndata);
00059
00060 GD_neato_nlist(g) = N_NEW(agnnodes(g) + 1, node_t *);
00061 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00062 ND_alg(n) = alg + i;
00063 GD_neato_nlist(g)[i++] = n;
00064 circular_init_node(n);
00065 }
00066 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00067 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
00068 circular_init_edge(e);
00069 }
00070 }
00071 }
00072
00073
00074 void circo_init_graph(graph_t * g)
00075 {
00076 setEdgeType (g, ET_LINE);
00077
00078 Ndim = GD_ndim(g) = 2;
00079 circular_init_node_edge(g);
00080 }
00081
00082
00083
00084
00085
00086
00087
00088 static node_t *makeDerivedNode(graph_t * dg, char *name, int isNode,
00089 void *orig)
00090 {
00091 node_t *n = agnode(dg, name);
00092 ND_alg(n) = (void *) NEW(cdata);
00093 if (isNode) {
00094 ND_pos(n) = N_NEW(Ndim, double);
00095 ND_xsize(n) = ND_xsize((node_t *) orig);
00096 ND_ysize(n) = ND_ysize((node_t *) orig);
00097 ORIGN(n) = (node_t *) orig;
00098 } else
00099 ORIGG(n) = (graph_t *) orig;
00100 return n;
00101 }
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 Agraph_t **circomps(Agraph_t * g, int *cnt)
00112 {
00113 int c_cnt;
00114 Agraph_t **ccs;
00115 Agraph_t *dg;
00116 Agnode_t *n, *v, *dt, *dh;
00117 Agedge_t *e;
00118 Agraph_t *sg;
00119 int i;
00120 Agedge_t *ep;
00121 Agnode_t *p;
00122 #ifdef USER_BLOCKS
00123 Agraph_t *ssg, *ssgl, *subg;
00124 Agnode_t *t;
00125 Agedge_t *me;
00126 #endif
00127
00128 dg = agopen("derived", AGFLAG_STRICT);
00129 GD_alg(g) = dg;
00130 #ifdef USER_BLOCKS
00131 sg = g->meta_node->graph;
00132 for (me = agfstout(sg, g->meta_node); me; me = agnxtout(sg, me)) {
00133 subg = agusergraph(me->head);
00134
00135 if (strncmp(subg->name, "block", 5) != 0)
00136 continue;
00137
00138 if (agnnodes(subg) == 0)
00139 continue;
00140
00141 n = makeDerivedNode(dg, subg->name, 0, subg);
00142 for (v = agfstnode(subg); v; v = agnxtnode(subg, v)) {
00143 DNODE(v) = n;
00144 }
00145 }
00146 #endif
00147
00148 for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
00149 if (DNODE(v))
00150 continue;
00151 n = makeDerivedNode(dg, v->name, 1, v);
00152 DNODE(v) = n;
00153 }
00154
00155 for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
00156 for (e = agfstout(g, v); e; e = agnxtout(g, e)) {
00157 dt = DNODE(e->tail);
00158 dh = DNODE(e->head);
00159 if (dt != dh)
00160 agedge(dg, dt, dh);
00161 }
00162 }
00163
00164 ccs = ccomps(dg, &c_cnt, 0);
00165
00166
00167 for (i = 0; i < c_cnt; i++) {
00168 sg = ccs[i];
00169
00170 #ifdef USER_BLOCKS
00171 for (n = agfstnode(sg); n; n = agnxtnode(sg, n)) {
00172
00173 if (agobjkind(ORIGN(n)) != AGNODE) {
00174 ssg = ORIGG(n);
00175 free(ND_alg(n));
00176 agdelete(n->graph, n);
00177 ssgl = agsubg(sg, ssg->name);
00178 for (t = agfstnode(ssg); t; t = agnxtnode(ssg, t)) {
00179 p = makeDerivedNode(dg, t->name, 1, t);
00180 DNODE(t) = p;
00181 aginsert(ssgl, p);
00182 }
00183 }
00184 }
00185 #endif
00186
00187
00188
00189
00190 for (n = agfstnode(sg); n; n = agnxtnode(sg, n)) {
00191 p = ORIGN(n);
00192 for (e = agfstout(g, p); e; e = agnxtout(g, e)) {
00193
00194 dh = DNODE(e->head);
00195 if (n != dh) {
00196 ep = agedge(dg, n, dh);
00197 aginsert(sg, ep);
00198 }
00199 }
00200 }
00201 }
00202
00203
00204 for (n = agfstnode(dg); n; n = agnxtnode(dg, n)) {
00205 for (e = agfstout(dg, n); e; e = agnxtout(dg, e)) {
00206 ED_alg(e) = NEW(edata);
00207 }
00208 }
00209
00210 *cnt = c_cnt;
00211 return ccs;
00212 }
00213
00214
00215
00216 static void closeDerivedGraph(graph_t * g)
00217 {
00218 node_t *n;
00219 edge_t *e;
00220
00221 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00222 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
00223 free(ED_alg(e));
00224 }
00225 free(ND_alg(n));
00226 free(ND_pos(n));
00227 }
00228 agclose(g);
00229 }
00230
00231
00232
00233
00234
00235
00236 static void copyPosns(graph_t * g)
00237 {
00238 node_t *n;
00239 node_t *v;
00240
00241 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
00242 v = ORIGN(n);
00243 ND_pos(v)[0] = ND_pos(n)[0];
00244 ND_pos(v)[1] = ND_pos(n)[1];
00245 }
00246 }
00247
00248
00249
00250 void circoLayout(Agraph_t * g)
00251 {
00252 Agraph_t **ccs;
00253 Agraph_t *sg;
00254 int ncc;
00255 int i;
00256
00257 if (agnnodes(g)) {
00258 ccs = circomps(g, &ncc);
00259
00260 if (ncc == 1) {
00261 circularLayout(ccs[0]);
00262 copyPosns(ccs[0]);
00263 adjustNodes(g);
00264 } else {
00265 Agraph_t *dg = ccs[0]->root;
00266 pack_info pinfo;
00267 pack_mode pmode = getPackMode(g, l_node);
00268
00269 for (i = 0; i < ncc; i++) {
00270 sg = ccs[i];
00271 circularLayout(sg);
00272 adjustNodes(sg);
00273 }
00274 pinfo.margin = getPack(g, CL_OFFSET, CL_OFFSET);
00275
00276
00277
00278
00279 pinfo.doSplines = 1;
00280 pinfo.mode = pmode;
00281 pinfo.fixed = 0;
00282 packSubgraphs(ncc, ccs, dg, &pinfo);
00283 for (i = 0; i < ncc; i++)
00284 copyPosns(ccs[i]);
00285 }
00286 for (i = 0; i < ncc; i++) {
00287 agdelete(g, ccs[i]);
00288 }
00289 free(ccs);
00290 }
00291 }
00292
00293
00294
00295 void circo_layout(Agraph_t * g)
00296 {
00297 if (agnnodes(g) == 0) return;
00298 circo_init_graph(g);
00299 circoLayout(g);
00300
00301 free(ND_alg(agfstnode(g)));
00302 spline_edges(g);
00303 dotneato_postprocess(g);
00304 }
00305
00306 static void circular_cleanup_node(node_t * n)
00307 {
00308 free(ND_pos(n));
00309 if (ND_shape(n))
00310 ND_shape(n)->fns->freefn(n);
00311 free_label(ND_label(n));
00312 memset(&(n->u), 0, sizeof(Agnodeinfo_t));
00313 }
00314
00315 static void circular_free_splines(edge_t * e)
00316 {
00317 int i;
00318 if (ED_spl(e)) {
00319 for (i = 0; i < ED_spl(e)->size; i++)
00320 free(ED_spl(e)->list[i].list);
00321 free(ED_spl(e)->list);
00322 free(ED_spl(e));
00323 }
00324 ED_spl(e) = NULL;
00325 }
00326
00327 static void circular_cleanup_edge(edge_t * e)
00328 {
00329 circular_free_splines(e);
00330 free_label(ED_label(e));
00331 memset(&(e->u), 0, sizeof(Agedgeinfo_t));
00332 }
00333
00334 void circo_cleanup(graph_t * g)
00335 {
00336 node_t *n;
00337 edge_t *e;
00338
00339 n = agfstnode(g);
00340 if (n == NULL)
00341 return;
00342
00343 closeDerivedGraph((graph_t*)GD_alg(g));
00344
00345 for (; n; n = agnxtnode(g, n)) {
00346 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
00347 circular_cleanup_edge(e);
00348 }
00349 circular_cleanup_node(n);
00350 }
00351 free(GD_neato_nlist(g));
00352 if (g != g->root) memset(&(g->u), 0, sizeof(Agraphinfo_t));
00353 }