Graphviz  2.29.20120523.0446
lib/fdpgen/dbg.c
Go to the documentation of this file.
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 */