dbg.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. /* dbg.c:
  11. * Written by Emden R. Gansner
  12. *
  13. * Simple debugging infrastructure
  14. */
  15. #ifdef DEBUG
  16. #define FDP_PRIVATE
  17. #include <fdpgen/dbg.h>
  18. #include <neatogen/neatoprocs.h>
  19. #include <fdpgen/fdp.h>
  20. #include <math.h>
  21. #include <util/exit.h>
  22. static int indent = -1;
  23. void incInd()
  24. {
  25. indent++;
  26. }
  27. void decInd()
  28. {
  29. if (indent >= 0)
  30. indent--;
  31. }
  32. void prIndent(void)
  33. {
  34. int i;
  35. for (i = 0; i < indent; i++)
  36. fputs(" ", stderr);
  37. }
  38. void prEdge(edge_t *e,char *s)
  39. {
  40. fprintf(stderr,"%s --", agnameof(agtail(e)));
  41. fprintf(stderr,"%s%s", agnameof(aghead(e)),s);
  42. }
  43. static void dumpBB(graph_t * g)
  44. {
  45. boxf bb;
  46. boxf b;
  47. bb = BB(g);
  48. b = GD_bb(g);
  49. prIndent();
  50. fprintf(stderr, " LL (%f,%f) UR (%f,%f)\n", bb.LL.x, bb.LL.y,
  51. bb.UR.x, bb.UR.y);
  52. prIndent();
  53. fprintf(stderr, " LL (%f,%f) UR (%f,%f)\n", b.LL.x, b.LL.y,
  54. b.UR.x, b.UR.y);
  55. }
  56. static void dumpSG(graph_t * g)
  57. {
  58. graph_t *subg;
  59. int i;
  60. if (GD_n_cluster(g) == 0)
  61. return;
  62. prIndent();
  63. fprintf(stderr, " {\n");
  64. for (i = 1; i <= GD_n_cluster(g); i++) {
  65. subg = (GD_clust(g))[i];
  66. prIndent();
  67. fprintf(stderr, " subgraph %s : %d nodes\n", agnameof(subg),
  68. agnnodes(subg));
  69. dumpBB(subg);
  70. incInd ();
  71. dumpSG(subg);
  72. decInd ();
  73. }
  74. prIndent();
  75. fprintf(stderr, " }\n");
  76. }
  77. /* dump:
  78. */
  79. void dump(graph_t *g, int level) {
  80. node_t *n;
  81. boxf bb;
  82. double w, h;
  83. pointf pos;
  84. if (Verbose < level)
  85. return;
  86. prIndent();
  87. fprintf(stderr, "Graph %s : %d nodes\n", agnameof(g), agnnodes(g));
  88. dumpBB(g);
  89. if (Verbose > level) {
  90. incInd();
  91. dumpSG(g);
  92. decInd();
  93. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  94. pos.x = ND_pos(n)[0];
  95. pos.y = ND_pos(n)[1];
  96. prIndent();
  97. w = ND_width(n);
  98. h = ND_height(n);
  99. fprintf(stderr, "%s: (%f,%f) (%f,%f) \n",
  100. agnameof(n), pos.x, pos.y, w, h);
  101. }
  102. }
  103. }
  104. void dumpG(graph_t * g, char *fname, int expMode)
  105. {
  106. FILE *fp;
  107. fp = fopen(fname, "w");
  108. if (!fp) {
  109. fprintf(stderr, "Couldn not open %s \n", fname);
  110. graphviz_exit(1);
  111. }
  112. outputGraph(g, fp, expMode);
  113. fclose(fp);
  114. }
  115. static const double ArrowScale = 1.0;
  116. #define ARROW_LENGTH 10
  117. #define ARROW_WIDTH 5
  118. static char *plog = "%!PS-Adobe-2.0\n\n\
  119. /Times-Roman findfont 14 scalefont setfont\n\
  120. /lLabel {\n\
  121. \tmoveto\n\
  122. \tgsave\n\
  123. \tshow\n\
  124. \tgrestore\n\
  125. } def\n\
  126. /inch {\n\
  127. \t72 mul\n\
  128. } def\n\
  129. /doBox {\n\
  130. \tnewpath\n\
  131. \tmoveto\n\
  132. \t/ht exch def\n\
  133. \t/wd exch def\n\
  134. \t0 ht rlineto\n\
  135. \twd 0 rlineto\n\
  136. \t0 0 ht sub rlineto\n\
  137. \tclosepath\n\
  138. \tgsave\n\
  139. \t\t.9 setgray\n\
  140. \t\tfill\n\
  141. \tgrestore\n\
  142. \tstroke\n\
  143. } def\n\
  144. /drawCircle {\n\
  145. \t/r exch def\n\
  146. \t/y exch def\n\
  147. \t/x exch def\n\
  148. \tnewpath\n\
  149. \tx y r 0 360 arc\n\
  150. \tstroke\n\
  151. } def\n\
  152. /fillCircle {\n\
  153. \t/r exch def\n\
  154. \t/y exch def\n\
  155. \t/x exch def\n\
  156. \tnewpath\n\
  157. \tx y r 0 360 arc\n\
  158. \tfill\n\
  159. } def\n";
  160. static char *elog = "showpage\n";
  161. static double PSWidth = 550.0;
  162. static double PSHeight = 756.0;
  163. static void pswrite(Agraph_t * g, FILE * fp, int expMode)
  164. {
  165. Agnode_t *n;
  166. Agnode_t *h;
  167. Agedge_t *e;
  168. double minx, miny, maxx, maxy;
  169. double scale, width, height;
  170. int do_arrow;
  171. int angle;
  172. char *p;
  173. double theta;
  174. double arrow_w, arrow_l;
  175. int portColor;
  176. fprintf(fp, "%s", plog);
  177. do_arrow = 0;
  178. n = agfstnode(g);
  179. minx = ND_pos(n)[0];
  180. miny = ND_pos(n)[1];
  181. maxx = ND_pos(n)[0];
  182. maxy = ND_pos(n)[1];
  183. n = agnxtnode(g, n);
  184. for (; n; n = agnxtnode(g, n)) {
  185. minx = fmin(minx, ND_pos(n)[0]);
  186. miny = fmin(miny, ND_pos(n)[1]);
  187. maxx = fmax(maxx, ND_pos(n)[0]);
  188. maxy = fmax(maxy, ND_pos(n)[1]);
  189. }
  190. /* Convert to points
  191. */
  192. minx *= POINTS_PER_INCH;
  193. miny *= POINTS_PER_INCH;
  194. maxx *= POINTS_PER_INCH;
  195. maxy *= POINTS_PER_INCH;
  196. /* Check for rotation
  197. */
  198. if ((p = agget(g, "rotate")) && *p != '\0' && (angle = atoi(p)) != 0) {
  199. fprintf(fp, "306 396 translate\n");
  200. fprintf(fp, "%d rotate\n", angle);
  201. fprintf(fp, "-306 -396 translate\n");
  202. }
  203. /* If user gives scale factor, use it.
  204. * Else if figure too large for standard PS page, scale it to fit.
  205. */
  206. width = maxx - minx + 20;
  207. height = maxy - miny + 20;
  208. if (width > PSWidth) {
  209. if (height > PSHeight) {
  210. scale = fmin(PSWidth / width, PSHeight / height);
  211. } else
  212. scale = PSWidth / width;
  213. } else if (height > PSHeight) {
  214. scale = PSHeight / height;
  215. } else
  216. scale = 1.0;
  217. fprintf(fp, "%f %f translate\n",
  218. (PSWidth - scale * (minx + maxx)) / 2.0,
  219. (PSHeight - scale * (miny + maxy)) / 2.0);
  220. fprintf(fp, "%f %f scale\n", scale, scale);
  221. /*
  222. if (Verbose)
  223. fprintf (stderr, "Region (%f,%f) (%f,%f), scale %f\n",
  224. minx, miny, maxx, maxy, scale);
  225. */
  226. if (do_arrow) {
  227. arrow_w = ArrowScale * ARROW_WIDTH / scale;
  228. arrow_l = ArrowScale * ARROW_LENGTH / scale;
  229. }
  230. fprintf(fp, "0.0 setlinewidth\n");
  231. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  232. if (IS_PORT(n)) {
  233. double r;
  234. r = sqrt(ND_pos(n)[0] * ND_pos(n)[0] +
  235. ND_pos(n)[1] * ND_pos(n)[1]);
  236. fprintf(fp, "0 0 %f inch drawCircle\n", r);
  237. break;
  238. }
  239. }
  240. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  241. for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
  242. h = aghead(e);
  243. fprintf(fp, "%f inch %f inch moveto %f inch %f inch lineto\n",
  244. ND_pos(n)[0], ND_pos(n)[1], ND_pos(h)[0],
  245. ND_pos(h)[1]);
  246. fprintf(fp, "stroke\n");
  247. if (do_arrow) {
  248. theta =
  249. atan2(ND_pos(n)[1] - ND_pos(h)[1],
  250. ND_pos(n)[0] - ND_pos(h)[0]);
  251. fprintf(fp, "%f %f %.2f %.2f %.2f doArrow\n",
  252. ND_pos(h)[0], ND_pos(h)[1], DEGREES(theta),
  253. arrow_l, arrow_w);
  254. }
  255. }
  256. }
  257. #ifdef BOX
  258. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  259. float wd, ht;
  260. data = getData(n);
  261. wd = data->wd;
  262. ht = data->ht;
  263. fprintf(fp, "%f %f %f %f doBox\n", wd, ht,
  264. data->pos.x - wd / 2, data->pos.y - ht / 2);
  265. }
  266. #else
  267. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  268. fprintf(fp, "%% %s\n", agnameof(n));
  269. if (expMode) {
  270. double wd, ht;
  271. double r;
  272. wd = ND_width(n);
  273. ht = ND_height(n);
  274. r = sqrt(wd * wd / 4 + ht * ht / 4);
  275. fprintf(fp, "%f inch %f inch %f inch %f inch doBox\n", wd, ht,
  276. ND_pos(n)[0] - wd / 2, ND_pos(n)[1] - ht / 2);
  277. fprintf(fp, "%f inch %f inch %f inch drawCircle\n",
  278. ND_pos(n)[0], ND_pos(n)[1], r);
  279. } else {
  280. if (IS_PORT(n)) {
  281. if (!portColor) {
  282. fprintf(fp, "0.667 1.000 1.000 sethsbcolor\n");
  283. portColor = 1;
  284. }
  285. } else {
  286. if (portColor) {
  287. fprintf(fp, "0.0 0.000 0.000 sethsbcolor\n");
  288. portColor = 0;
  289. }
  290. }
  291. }
  292. fprintf(fp, "%f inch %f inch %f fillCircle\n", ND_pos(n)[0],
  293. ND_pos(n)[1], 3 / scale);
  294. }
  295. #endif
  296. fprintf(fp, "0.667 1.000 1.000 sethsbcolor\n");
  297. for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
  298. for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
  299. h = aghead(e);
  300. fprintf(fp, "%f inch %f inch moveto %f inch %f inch lineto\n",
  301. ND_pos(n)[0], ND_pos(n)[1], ND_pos(h)[0],
  302. ND_pos(h)[1]);
  303. fprintf(fp, "stroke\n");
  304. if (do_arrow) {
  305. theta =
  306. atan2(ND_pos(n)[1] - ND_pos(h)[1],
  307. ND_pos(n)[0] - ND_pos(h)[0]);
  308. fprintf(fp, "%f %f %.2f %.2f %.2f doArrow\n",
  309. ND_pos(h)[0], ND_pos(h)[1], DEGREES(theta),
  310. arrow_l, arrow_w);
  311. }
  312. }
  313. }
  314. fprintf(fp, "%s", elog);
  315. }
  316. void outputGraph(Agraph_t * g, FILE * fp, int expMode)
  317. {
  318. pswrite(g, fp, expMode);
  319. }
  320. #endif /* DEBUG */