|
Graphviz
2.29.20120523.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 00015 /* dbg.c: 00016 * Written by Emden R. Gansner 00017 * 00018 * Simple debugging infrastructure 00019 */ 00020 #ifdef DEBUG 00021 00022 #define FDP_PRIVATE 00023 00024 #include <dbg.h> 00025 #include <neatoprocs.h> 00026 #include <fdp.h> 00027 #include <math.h> 00028 00029 static int indent = -1; 00030 00031 void incInd() 00032 { 00033 indent++; 00034 } 00035 00036 void decInd() 00037 { 00038 if (indent >= 0) 00039 indent--; 00040 } 00041 00042 void prIndent(void) 00043 { 00044 int i; 00045 for (i = 0; i < indent; i++) 00046 fputs(" ", stderr); 00047 } 00048 00049 static void dumpBB(graph_t * g) 00050 { 00051 boxf bb; 00052 boxf b; 00053 00054 bb = BB(g); 00055 b = GD_bb(g); 00056 prIndent(); 00057 fprintf(stderr, " LL (%f,%f) UR (%f,%f)\n", bb.LL.x, bb.LL.y, 00058 bb.UR.x, bb.UR.y); 00059 prIndent(); 00060 fprintf(stderr, " LL (%f,%f) UR (%f,%f)\n", b.LL.x, b.LL.y, 00061 b.UR.x, b.UR.y); 00062 } 00063 00064 static void dumpSG(graph_t * g) 00065 { 00066 graph_t *subg; 00067 int i; 00068 00069 if (GD_n_cluster(g) == 0) 00070 return; 00071 prIndent(); 00072 fprintf(stderr, " {\n"); 00073 for (i = 1; i <= GD_n_cluster(g); i++) { 00074 subg = (GD_clust(g))[i]; 00075 prIndent(); 00076 fprintf(stderr, " subgraph %s : %d nodes\n", subg->name, 00077 agnnodes(subg)); 00078 dumpBB(subg); 00079 incInd (); 00080 dumpSG(subg); 00081 decInd (); 00082 } 00083 prIndent(); 00084 fprintf(stderr, " }\n"); 00085 } 00086 00087 /* dumpE: 00088 */ 00089 void dumpE(graph_t * g, int derived) 00090 { 00091 Agnode_t *n; 00092 Agedge_t *e; 00093 Agedge_t **ep; 00094 Agedge_t *el; 00095 int i; 00096 int deg; 00097 00098 prIndent(); 00099 fprintf(stderr, "Graph %s : %d nodes %d edges\n", g->name, agnnodes(g), 00100 agnedges(g)); 00101 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00102 deg = 0; 00103 for (e = agfstout(g, n); e; e = agnxtout(g, e)) { 00104 deg++; 00105 prIndent(); 00106 fprintf(stderr, " %s -- %s\n", e->tail->name, e->head->name); 00107 if (derived) { 00108 for (i = 0, ep = (Agedge_t **) ED_to_virt(e); 00109 i < ED_count(e); i++, ep++) { 00110 el = *ep; 00111 prIndent(); 00112 fprintf(stderr, " %s -- %s\n", el->tail->name, 00113 el->head->name); 00114 } 00115 } 00116 } 00117 if (deg == 0) { /* no out edges */ 00118 if (!agfstin(g, n)) /* no in edges */ 00119 fprintf(stderr, " %s\n", n->name); 00120 } 00121 } 00122 if (!derived) { 00123 bport_t *pp; 00124 if ((pp = PORTS(g))) { 00125 int sz = NPORTS(g); 00126 fprintf(stderr, " %d ports\n", sz); 00127 while (pp->e) { 00128 fprintf(stderr, " %s : %s -- %s\n", pp->n->name, 00129 pp->e->tail->name, pp->e->head->name); 00130 pp++; 00131 } 00132 } 00133 } 00134 } 00135 00136 /* dump: 00137 */ 00138 void dump(graph_t * g, int level, int doBB) 00139 { 00140 node_t *n; 00141 boxf bb; 00142 double w, h; 00143 pointf pos; 00144 00145 if (Verbose < level) 00146 return; 00147 prIndent(); 00148 fprintf(stderr, "Graph %s : %d nodes\n", g->name, agnnodes(g)); 00149 dumpBB(g); 00150 if (Verbose > level) { 00151 incInd(); 00152 dumpSG(g); 00153 decInd(); 00154 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00155 pos.x = ND_pos(n)[0]; 00156 pos.y = ND_pos(n)[1]; 00157 prIndent(); 00158 w = ND_width(n); 00159 h = ND_height(n); 00160 if (doBB) { 00161 bb.LL.x = pos.x - w / 2.0; 00162 bb.LL.y = pos.y - h / 2.0; 00163 bb.UR.x = bb.LL.x + w; 00164 bb.UR.y = bb.LL.y + h; 00165 fprintf(stderr, "%s: (%f,%f) ((%f,%f) , (%f,%f))\n", 00166 n->name, pos.x, pos.y, bb.LL.x, bb.LL.y, bb.UR.x, 00167 bb.UR.y); 00168 } else { 00169 fprintf(stderr, "%s: (%f,%f) (%f,%f) \n", 00170 n->name, pos.x, pos.y, w, h); 00171 } 00172 } 00173 } 00174 } 00175 00176 void dumpG(graph_t * g, char *fname, int expMode) 00177 { 00178 FILE *fp; 00179 00180 fp = fopen(fname, "w"); 00181 if (!fp) { 00182 fprintf(stderr, "Couldn not open %s \n", fname); 00183 exit(1); 00184 } 00185 outputGraph(g, fp, expMode); 00186 fclose(fp); 00187 } 00188 00189 /* #define BOX */ 00190 00191 /* static char* pos_name = "pos"; */ 00192 /* static char* lp_name = "lp"; */ 00193 00194 double Scale = 0.0; 00195 double ArrowScale = 1.0; 00196 00197 #define ARROW_LENGTH 10 00198 #define ARROW_WIDTH 5 00199 /* #define DEGREES(rad) ((rad)/M_PI * 180.0) */ 00200 00201 static char *plog = "%%!PS-Adobe-2.0\n\n\ 00202 /Times-Roman findfont 14 scalefont setfont\n\ 00203 /lLabel {\n\ 00204 \tmoveto\n\ 00205 \tgsave\n\ 00206 \tshow\n\ 00207 \tgrestore\n\ 00208 } def\n\ 00209 /inch {\n\ 00210 \t72 mul\n\ 00211 } def\n\ 00212 /doBox {\n\ 00213 \tnewpath\n\ 00214 \tmoveto\n\ 00215 \t/ht exch def\n\ 00216 \t/wd exch def\n\ 00217 \t0 ht rlineto\n\ 00218 \twd 0 rlineto\n\ 00219 \t0 0 ht sub rlineto\n\ 00220 \tclosepath\n\ 00221 \tgsave\n\ 00222 \t\t.9 setgray\n\ 00223 \t\tfill\n\ 00224 \tgrestore\n\ 00225 \tstroke\n\ 00226 } def\n\ 00227 /drawCircle {\n\ 00228 \t/r exch def\n\ 00229 \t/y exch def\n\ 00230 \t/x exch def\n\ 00231 \tnewpath\n\ 00232 \tx y r 0 360 arc\n\ 00233 \tstroke\n\ 00234 } def\n\ 00235 /fillCircle {\n\ 00236 \t/r exch def\n\ 00237 \t/y exch def\n\ 00238 \t/x exch def\n\ 00239 \tnewpath\n\ 00240 \tx y r 0 360 arc\n\ 00241 \tfill\n\ 00242 } def\n"; 00243 00244 static char *elog = "showpage\n"; 00245 00246 /* 00247 static char* arrow = "/doArrow {\n\ 00248 \t/arrowwidth exch def\n\ 00249 \t/arrowlength exch def\n\ 00250 \tgsave\n\ 00251 \t\t3 1 roll\n\ 00252 \t\ttranslate\n\ 00253 \t\t\trotate\n\ 00254 \t\t\tnewpath\n\ 00255 \t\t\tarrowlength arrowwidth 2 div moveto\n\ 00256 \t\t\t0 0 lineto\n\ 00257 \t\t\tarrowlength arrowwidth -2 div lineto\n\ 00258 \t\tclosepath fill\n\ 00259 \t\tstroke\n\ 00260 \tgrestore\n\ 00261 } def\n"; 00262 */ 00263 00264 static double PSWidth = 550.0; 00265 static double PSHeight = 756.0; 00266 00267 static void pswrite(Agraph_t * g, FILE * fp, int expMode) 00268 { 00269 Agnode_t *n; 00270 Agnode_t *h; 00271 Agedge_t *e; 00272 Agnodeinfo_t *data; 00273 Agnodeinfo_t *hdata; 00274 double minx, miny, maxx, maxy; 00275 double scale, width, height; 00276 int do_arrow; 00277 int angle; 00278 char *p; 00279 double theta; 00280 double arrow_w, arrow_l; 00281 int portColor; 00282 00283 fprintf(fp, plog); 00284 00285 /* 00286 if (agisdirected (g) && DoArrow) { 00287 do_arrow = 1; 00288 fprintf(fp,arrow); 00289 } 00290 else 00291 */ 00292 do_arrow = 0; 00293 00294 n = agfstnode(g); 00295 data = &(n->u); 00296 minx = data->pos[0]; 00297 miny = data->pos[1]; 00298 maxx = data->pos[0]; 00299 maxy = data->pos[1]; 00300 n = agnxtnode(g, n); 00301 for (; n; n = agnxtnode(g, n)) { 00302 data = &(n->u); 00303 if (data->pos[0] < minx) 00304 minx = data->pos[0]; 00305 if (data->pos[1] < miny) 00306 miny = data->pos[1]; 00307 if (data->pos[0] > maxx) 00308 maxx = data->pos[0]; 00309 if (data->pos[1] > maxy) 00310 maxy = data->pos[1]; 00311 } 00312 00313 /* Convert to points 00314 */ 00315 minx *= POINTS_PER_INCH; 00316 miny *= POINTS_PER_INCH; 00317 maxx *= POINTS_PER_INCH; 00318 maxy *= POINTS_PER_INCH; 00319 00320 /* Check for rotation 00321 */ 00322 if ((p = agget(g, "rotate")) && (*p != '\0') 00323 && ((angle = atoi(p)) != 0)) { 00324 fprintf(fp, "306 396 translate\n"); 00325 fprintf(fp, "%d rotate\n", angle); 00326 fprintf(fp, "-306 -396 translate\n"); 00327 } 00328 00329 /* If user gives scale factor, use it. 00330 * Else if figure too large for standard PS page, scale it to fit. 00331 */ 00332 if (Scale > 0.0) 00333 scale = Scale; 00334 else { 00335 width = maxx - minx + 20; 00336 height = maxy - miny + 20; 00337 if (width > PSWidth) { 00338 if (height > PSHeight) { 00339 scale = 00340 (PSWidth / width < 00341 PSHeight / height ? PSWidth / width : PSHeight / 00342 height); 00343 } else 00344 scale = PSWidth / width; 00345 } else if (height > PSHeight) { 00346 scale = PSHeight / height; 00347 } else 00348 scale = 1.0; 00349 } 00350 00351 fprintf(fp, "%f %f translate\n", 00352 (PSWidth - scale * (minx + maxx)) / 2.0, 00353 (PSHeight - scale * (miny + maxy)) / 2.0); 00354 fprintf(fp, "%f %f scale\n", scale, scale); 00355 00356 /* 00357 if (Verbose) 00358 fprintf (stderr, "Region (%f,%f) (%f,%f), scale %f\n", 00359 minx, miny, maxx, maxy, scale); 00360 */ 00361 00362 if (do_arrow) { 00363 arrow_w = ArrowScale * ARROW_WIDTH / scale; 00364 arrow_l = ArrowScale * ARROW_LENGTH / scale; 00365 } 00366 00367 fprintf(fp, "0.0 setlinewidth\n"); 00368 #ifdef SHOW_GRID 00369 if (UseGrid) { 00370 int i; 00371 fprintf(fp, "%f %f 5 fillCircle\n", 0.0, 0.0); 00372 for (i = 0; i < maxx; i += CellW) { 00373 fprintf(fp, "%f 0.0 moveto %f %f lineto stroke\n", 00374 (float) i, (float) i, maxy); 00375 } 00376 for (i = 0; i < maxy; i += CellH) { 00377 fprintf(fp, "0.0 %f moveto %f %f lineto stroke\n", 00378 (float) i, maxx, (float) i); 00379 } 00380 } 00381 #endif 00382 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00383 if (IS_PORT(n)) { 00384 double r; 00385 data = &(n->u); 00386 r = sqrt(data->pos[0] * data->pos[0] + 00387 data->pos[1] * data->pos[1]); 00388 fprintf(fp, "0 0 %f inch drawCircle\n", r); 00389 break; 00390 } 00391 } 00392 00393 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00394 data = &(n->u); 00395 for (e = agfstout(g, n); e; e = agnxtout(g, e)) { 00396 h = e->head; 00397 hdata = &(h->u); 00398 fprintf(fp, "%f inch %f inch moveto %f inch %f inch lineto\n", 00399 data->pos[0], data->pos[1], hdata->pos[0], 00400 hdata->pos[1]); 00401 fprintf(fp, "stroke\n"); 00402 if (do_arrow) { 00403 theta = 00404 atan2(data->pos[1] - hdata->pos[1], 00405 data->pos[0] - hdata->pos[0]); 00406 fprintf(fp, "%f %f %.2f %.2f %.2f doArrow\n", 00407 hdata->pos[0], hdata->pos[1], DEGREES(theta), 00408 arrow_l, arrow_w); 00409 } 00410 00411 } 00412 } 00413 00414 #ifdef BOX 00415 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00416 float wd, ht; 00417 00418 data = getData(n); 00419 wd = data->wd; 00420 ht = data->ht; 00421 fprintf(fp, "%f %f %f %f doBox\n", wd, ht, 00422 data->pos.x - (wd / 2), data->pos.y - (ht / 2)); 00423 } 00424 #else 00425 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00426 data = &(n->u); 00427 fprintf(fp, "%% %s\n", n->name); 00428 if (expMode) { 00429 double wd, ht; 00430 double r; 00431 wd = data->width; 00432 ht = data->height; 00433 r = sqrt((wd * wd / 4) + ht * ht / 4); 00434 fprintf(fp, "%f inch %f inch %f inch %f inch doBox\n", wd, ht, 00435 data->pos[0] - (wd / 2), data->pos[1] - (ht / 2)); 00436 fprintf(fp, "%f inch %f inch %f inch drawCircle\n", 00437 data->pos[0], data->pos[1], r); 00438 } else { 00439 if (IS_PORT(n)) { 00440 if (!portColor) { 00441 fprintf(fp, "0.667 1.000 1.000 sethsbcolor\n"); 00442 portColor = 1; 00443 } 00444 } else { 00445 if (portColor) { 00446 fprintf(fp, "0.0 0.000 0.000 sethsbcolor\n"); 00447 portColor = 0; 00448 } 00449 } 00450 } 00451 fprintf(fp, "%f inch %f inch %f fillCircle\n", data->pos[0], 00452 data->pos[1], 3 / scale); 00453 } 00454 #endif 00455 00456 fprintf(fp, "0.667 1.000 1.000 sethsbcolor\n"); 00457 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00458 data = &(n->u); 00459 for (e = agfstout(g, n); e; e = agnxtout(g, e)) { 00460 h = e->head; 00461 hdata = &(h->u); 00462 fprintf(fp, "%f inch %f inch moveto %f inch %f inch lineto\n", 00463 data->pos[0], data->pos[1], hdata->pos[0], 00464 hdata->pos[1]); 00465 fprintf(fp, "stroke\n"); 00466 if (do_arrow) { 00467 theta = 00468 atan2(data->pos[1] - hdata->pos[1], 00469 data->pos[0] - hdata->pos[0]); 00470 fprintf(fp, "%f %f %.2f %.2f %.2f doArrow\n", 00471 hdata->pos[0], hdata->pos[1], DEGREES(theta), 00472 arrow_l, arrow_w); 00473 } 00474 00475 } 00476 } 00477 00478 fprintf(fp, elog); 00479 } 00480 00481 void outputGraph(Agraph_t * g, FILE * fp, int expMode) 00482 { 00483 pswrite(g, fp, expMode); 00484 } 00485 00486 #endif /* DEBUG */
1.7.5