|
Graphviz
2.29.20120524.0446
|
00001 /* $Id$ $Revision$ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /************************************************************************* 00005 * Copyright (c) 2011 AT&T Intellectual Property 00006 * All rights reserved. This program and the accompanying materials 00007 * are made available under the terms of the Eclipse Public License v1.0 00008 * which accompanies this distribution, and is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * 00011 * Contributors: See CVS logs. Details at http://www.graphviz.org/ 00012 *************************************************************************/ 00013 00014 #include <assert.h> 00015 #include "render.h" 00016 #include "neatoprocs.h" 00017 #include "pack.h" 00018 00019 /* Test driver for libpack library. 00020 * Input consists of graphs in dot format. 00021 * If -c is not specified, the graphs must have pos information, 00022 * typically the output of one of the layout programs using -Tdot. 00023 * -c computes connected components of input graphs 00024 * Otherwise, ptest packs the input graphs. 00025 * -s causes all the input graphs to be combined 00026 * into a single output graph, ready to be sent to neato -s -n2. 00027 * Otherwise, each graph is output separately, but with the 00028 * appropriately adjusted coordinates. 00029 * -e causes the packing to not use edge splines, if any. 00030 * If any input graph does not have spline info, -e goes into 00031 * effect automatically. 00032 * -m <i> specifies the margin, in points, about each graph. 00033 */ 00034 char *Info[] = { 00035 "ptest", /* Program */ 00036 "1.0", /* Version */ 00037 DATE /* Build Date */ 00038 }; 00039 00040 static int margin = 8; 00041 static int doEdges = 1; 00042 static int doComps = 0; 00043 static int verbose = 0; 00044 static char **Files = 0; 00045 static int nFiles = 0; 00046 static int single = 0; 00047 00048 static char *useString = "Usage: ptest [-cesv?] [-m <margine>] <files>\n\ 00049 -c - components\n\ 00050 -e - no edges\n\ 00051 -m n - set margine\n\ 00052 -v - verbose\n\ 00053 -s - single graph\n\ 00054 -? - print usage\n\ 00055 If no files are specified, stdin is used\n"; 00056 00057 static void usage(int v) 00058 { 00059 printf(useString); 00060 exit(v); 00061 } 00062 00063 static void init(int argc, char *argv[]) 00064 { 00065 int c; 00066 00067 aginit(); 00068 while ((c = getopt(argc, argv, ":escvm:?")) != -1) { 00069 switch (c) { 00070 case 'e': 00071 doEdges = 0; 00072 break; 00073 case 'c': 00074 doComps = 1; 00075 break; 00076 case 'm': 00077 margin = atoi(optarg); 00078 break; 00079 case 's': 00080 single = 1; 00081 break; 00082 case 'v': 00083 verbose = 1; 00084 Verbose = 1; 00085 break; 00086 case '?': 00087 if (optopt == '?') 00088 usage(0); 00089 else 00090 fprintf(stderr, 00091 "ptest: option -%c unrecognized - ignored\n", c); 00092 break; 00093 } 00094 } 00095 argv += optind; 00096 argc -= optind; 00097 00098 if (argc) { 00099 Files = argv; 00100 nFiles = argc; 00101 } 00102 00103 } 00104 00105 static int numFields(char *pos) 00106 { 00107 int cnt = 0; 00108 char c; 00109 00110 while (isspace(*pos)) 00111 pos++; 00112 while (*pos) { 00113 cnt++; 00114 while ((c = *pos) && !isspace(c)) 00115 pos++; /* skip token */ 00116 while (isspace(*pos)) 00117 pos++; 00118 } 00119 return cnt; 00120 } 00121 00122 static point *user_spline(attrsym_t * symptr, edge_t * e, int *np) 00123 { 00124 char *pos; 00125 int i, n, nc; 00126 point *ps = 0; 00127 point *pp; 00128 double x, y; 00129 00130 if (symptr == NULL) 00131 return 0; 00132 pos = agxget(e, symptr->index); 00133 if (*pos == '\0') 00134 return 0; 00135 n = numFields(pos); 00136 *np = n; 00137 if (n > 1) { 00138 ps = ALLOC(n, 0, point); 00139 pp = ps; 00140 while (n) { 00141 i = sscanf(pos, "%lf,%lf%n", &x, &y, &nc); 00142 if (i < 2) { 00143 free(ps); 00144 ps = 0; 00145 break; 00146 } 00147 pos = pos + nc; 00148 pp->x = (int) x; 00149 pp->y = (int) y; 00150 pp++; 00151 n--; 00152 } 00153 } 00154 return ps; 00155 } 00156 00157 static void initPos(Agraph_t * g) 00158 { 00159 Agnode_t *n; 00160 Agedge_t *e; 00161 double *pvec; 00162 char *p; 00163 point *sp; 00164 int pn; 00165 attrsym_t *N_pos = agfindnodeattr(g, "pos"); 00166 attrsym_t *E_pos = agfindedgeattr(g, "pos"); 00167 00168 assert(N_pos); 00169 if (!E_pos) { 00170 if (doEdges) 00171 fprintf(stderr, "Warning: turning off doEdges, graph %s\n", 00172 g->name); 00173 doEdges = 0; 00174 } 00175 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00176 pvec = ND_pos(n); 00177 p = agxget(n, N_pos->index); 00178 if (p[0] && (sscanf(p, "%lf,%lf", pvec, pvec + 1) == 2)) { 00179 int i; 00180 for (i = 0; i < NDIM; i++) 00181 pvec[i] = pvec[i] / PSinputscale; 00182 } else { 00183 fprintf(stderr, "could not find pos for node %s in graph %s\n", 00184 n->name, g->name); 00185 exit(1); 00186 } 00187 ND_coord_i(n).x = POINTS(ND_pos(n)[0]); 00188 ND_coord_i(n).y = POINTS(ND_pos(n)[1]); 00189 } 00190 00191 if (doEdges) { 00192 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00193 for (e = agfstout(g, n); e; e = agnxtout(g, e)) { 00194 if ((sp = user_spline(E_pos, e, &pn)) != 0) { 00195 clip_and_install(e, sp, pn); 00196 free(sp); 00197 } else { 00198 fprintf(stderr, 00199 "Missing edge pos for edge %s - %s in graph %s\n", 00200 n->name, e->head->name, g->name); 00201 exit(1); 00202 } 00203 } 00204 } 00205 } 00206 } 00207 00208 static void ptest_nodesize(node_t * n, boolean flip) 00209 { 00210 int w; 00211 00212 w = ND_xsize(n) = POINTS(ND_width(n)); 00213 ND_lw(n) = ND_rw(n) = w / 2; 00214 ND_ht(n) = ND_ysize(n) = POINTS(ND_height(n)); 00215 } 00216 00217 00218 static void ptest_initNode(node_t * n) 00219 { 00220 char *str; 00221 ND_width(n) = 00222 late_double(n, N_width, DEFAULT_NODEWIDTH, MIN_NODEWIDTH); 00223 ND_height(n) = 00224 late_double(n, N_height, DEFAULT_NODEHEIGHT, MIN_NODEWIDTH); 00225 if (N_label == NULL) 00226 str = NODENAME_ESC; 00227 else 00228 str = agxget(n, N_label->index); 00229 str = strdup_and_subst(str, NODENAME_ESC, n->name); 00230 ND_label(n) = make_label(str, 00231 late_double(n, N_fontsize, DEFAULT_FONTSIZE, 00232 MIN_FONTSIZE), late_nnstring(n, 00233 N_fontname, 00234 DEFAULT_FONTNAME), 00235 late_nnstring(n, N_fontcolor, DEFAULT_COLOR), 00236 n->graph); 00237 ND_shape(n) = bind_shape(late_nnstring(n, N_shape, DEFAULT_NODESHAPE)); 00238 ND_shape(n)->initfn(n); /* ### need to quantize ? */ 00239 ptest_nodesize(n, n->GD_flip(graph)); 00240 00241 00242 } 00243 00244 static void ptest_initGraph(graph_t * g) 00245 { 00246 node_t *n; 00247 /* edge_t *e; */ 00248 00249 for (n = agfstnode(g); n; n = agnxtnode(g, n)) 00250 ptest_initNode(n); 00251 /* 00252 for (n = agfstnode(g); n; n = agnxtnode(g,n)) { 00253 for (e = agfstout(g,n); e; e = agnxtout(g,e)) ptest_initEdge(e); 00254 } 00255 */ 00256 } 00257 00258 static void dumpG(graph_t * g) 00259 { 00260 node_t *n; 00261 /* point p; */ 00262 edge_t *e; 00263 00264 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00265 fprintf(stderr, " node %s \n", n->name); 00266 00267 for (e = agfstout(g, n); e; e = agnxtout(g, e)) { 00268 fprintf(stderr, " %s - %s \n", e->tail->name, e->head->name); 00269 } 00270 #ifdef OLD 00271 p = coord(n); 00272 fprintf(stderr, " %s pos (%f,%f) (%d,%d)\n", 00273 n->name, ND_pos(n)[0], ND_pos(n)[1], p.x, p.y); 00274 fprintf(stderr, " width %f height %f xsize %d ysize %d\n", 00275 ND_width(n), ND_height(n), ND_xsize(n), ND_ysize(n)); 00276 #endif 00277 } 00278 } 00279 00280 static void copyPos(Agraph_t * g) 00281 { 00282 Agnode_t *n; 00283 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00284 ND_coord_i(n).x = POINTS(ND_pos(n)[0]); 00285 ND_coord_i(n).y = POINTS(ND_pos(n)[1]); 00286 } 00287 } 00288 00289 main(int argc, char *argv[]) 00290 { 00291 Agraph_t **gs; 00292 Agraph_t **ccs; 00293 Agraph_t *g; 00294 Agraph_t *gp; 00295 char *fname; 00296 FILE *fp; 00297 int cnt; 00298 int i; 00299 00300 init(argc, argv); 00301 if (!Files) { 00302 fprintf(stderr, "No input files given\n"); 00303 exit(1); 00304 } 00305 00306 PSinputscale = POINTS_PER_INCH; 00307 if (doComps) { 00308 if (verbose) 00309 fprintf(stderr, "do Comps\n"); 00310 while (fname = *Files++) { 00311 fp = fopen(fname, "r"); 00312 if (!fp) { 00313 fprintf(stderr, "Could not open %s\n", fname); 00314 continue; 00315 } 00316 g = agread(fp); 00317 fclose(fp); 00318 if (!g) { 00319 fprintf(stderr, "Could not read graph\n"); 00320 continue; 00321 } 00322 printf("%s %d nodes %d edges %sconnected\n", 00323 g->name, agnnodes(g), agnedges(g), 00324 (isConnected(g) ? "" : "not ")); 00325 gs = ccomps(g, &cnt, "abc"); 00326 for (i = 0; i < cnt; i++) { 00327 gp = gs[i]; 00328 printf(" %s %d nodes %d edges\n", gp->name, agnnodes(gp), 00329 agnedges(gp)); 00330 } 00331 } 00332 } else { 00333 gs = N_GNEW(nFiles, Agraph_t *); 00334 cnt = 0; 00335 while (fname = Files[cnt]) { 00336 fp = fopen(fname, "r"); 00337 if (!fp) { 00338 fprintf(stderr, "Could not open %s\n", fname); 00339 exit(1); 00340 } 00341 g = agread(fp); 00342 fclose(fp); 00343 if (!g) { 00344 fprintf(stderr, "Could not read graph\n"); 00345 exit(1); 00346 } 00347 if (!single) { 00348 graph_init(g); 00349 ptest_initGraph(g); 00350 } 00351 initPos(g); 00352 /* if (Verbose) dumpG (g); */ 00353 gs[cnt++] = g; 00354 } 00355 if (single) { 00356 Agraph_t *root; 00357 Agnode_t *n; 00358 Agnode_t *np; 00359 Agnode_t *tp; 00360 Agnode_t *hp; 00361 Agedge_t *e; 00362 Agedge_t *ep; 00363 root = agopen("root", 0); 00364 agedgeattr(root, "pos", ""); 00365 for (i = 0; i < cnt; i++) { 00366 g = gs[i]; 00367 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00368 if (agfindnode(root, n->name)) { 00369 fprintf(stderr, 00370 "Error: node %s in graph %d (%s) previously added\n", 00371 n->name, i, Files[i]); 00372 exit(1); 00373 } 00374 np = agnode(root, n->name); 00375 ND_pos(np)[0] = ND_pos(n)[0]; 00376 ND_pos(np)[1] = ND_pos(n)[1]; 00377 ND_coord_i(np).x = ND_coord_i(n).x; 00378 ND_coord_i(np).y = ND_coord_i(n).y; 00379 } 00380 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00381 tp = agfindnode(root, n->name); 00382 for (e = agfstout(g, n); e; e = agnxtout(g, e)) { 00383 hp = agfindnode(root, e->head->name); 00384 ep = agedge(root, tp, hp); 00385 ED_spl(ep) = ED_spl(e); 00386 } 00387 } 00388 } 00389 graph_init(root); 00390 ptest_initGraph(root); 00391 ccs = ccomps(root, &cnt, 0); 00392 packGraphs(cnt, ccs, root, margin, doEdges); 00393 if (!doEdges) 00394 copyPos(root); 00395 else 00396 State = GVSPLINES; 00397 attach_attrs(root); 00398 for (i = 0; i < cnt; i++) { 00399 agdelete(root, ccs[i]); 00400 } 00401 agwrite(root, stdout); 00402 } else { 00403 packGraphs(cnt, gs, 0, margin, doEdges); 00404 if (doEdges) 00405 State = GVSPLINES; 00406 for (i = 0; i < cnt; i++) { 00407 if (!doEdges) 00408 copyPos(gs[i]); 00409 attach_attrs(gs[i]); 00410 agwrite(gs[i], stdout); 00411 } 00412 } 00413 } 00414 }
1.7.5