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