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