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