Graphviz 12.1.1~dev.20240814.0213
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 <cgraph/exit.h>
22#include <fdpgen/dbg.h>
23#include <neatogen/neatoprocs.h>
24#include <fdpgen/fdp.h>
25#include <math.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 boxf bb;
96 double w, h;
97 pointf pos;
98
99 if (Verbose < level)
100 return;
101 prIndent();
102 fprintf(stderr, "Graph %s : %d nodes\n", agnameof(g), agnnodes(g));
103 dumpBB(g);
104 if (Verbose > level) {
105 incInd();
106 dumpSG(g);
107 decInd();
108 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
109 pos.x = ND_pos(n)[0];
110 pos.y = ND_pos(n)[1];
111 prIndent();
112 w = ND_width(n);
113 h = ND_height(n);
114 fprintf(stderr, "%s: (%f,%f) (%f,%f) \n",
115 agnameof(n), pos.x, pos.y, w, h);
116 }
117 }
118}
119
120void dumpG(graph_t * g, char *fname, int expMode)
121{
122 FILE *fp;
123
124 fp = fopen(fname, "w");
125 if (!fp) {
126 fprintf(stderr, "Couldn not open %s \n", fname);
127 graphviz_exit(1);
128 }
129 outputGraph(g, fp, expMode);
130 fclose(fp);
131}
132
133static const double ArrowScale = 1.0;
134
135#define ARROW_LENGTH 10
136#define ARROW_WIDTH 5
137
138static char *plog = "%!PS-Adobe-2.0\n\n\
139/Times-Roman findfont 14 scalefont setfont\n\
140/lLabel {\n\
141\tmoveto\n\
142\tgsave\n\
143\tshow\n\
144\tgrestore\n\
145} def\n\
146/inch {\n\
147\t72 mul\n\
148} def\n\
149/doBox {\n\
150\tnewpath\n\
151\tmoveto\n\
152\t/ht exch def\n\
153\t/wd exch def\n\
154\t0 ht rlineto\n\
155\twd 0 rlineto\n\
156\t0 0 ht sub rlineto\n\
157\tclosepath\n\
158\tgsave\n\
159\t\t.9 setgray\n\
160\t\tfill\n\
161\tgrestore\n\
162\tstroke\n\
163} def\n\
164/drawCircle {\n\
165\t/r exch def\n\
166\t/y exch def\n\
167\t/x exch def\n\
168\tnewpath\n\
169\tx y r 0 360 arc\n\
170\tstroke\n\
171} def\n\
172/fillCircle {\n\
173\t/r exch def\n\
174\t/y exch def\n\
175\t/x exch def\n\
176\tnewpath\n\
177\tx y r 0 360 arc\n\
178\tfill\n\
179} def\n";
180
181static char *elog = "showpage\n";
182
183static double PSWidth = 550.0;
184static double PSHeight = 756.0;
185
186static void pswrite(Agraph_t * g, FILE * fp, int expMode)
187{
188 Agnode_t *n;
189 Agnode_t *h;
190 Agedge_t *e;
191 double minx, miny, maxx, maxy;
192 double scale, width, height;
193 int do_arrow;
194 int angle;
195 char *p;
196 double theta;
197 double arrow_w, arrow_l;
198 int portColor;
199
200 fprintf(fp, "%s", plog);
201
202 do_arrow = 0;
203
204 n = agfstnode(g);
205 minx = ND_pos(n)[0];
206 miny = ND_pos(n)[1];
207 maxx = ND_pos(n)[0];
208 maxy = ND_pos(n)[1];
209 n = agnxtnode(g, n);
210 for (; n; n = agnxtnode(g, n)) {
211 minx = fmin(minx, ND_pos(n)[0]);
212 miny = fmin(miny, ND_pos(n)[1]);
213 maxx = fmax(maxx, ND_pos(n)[0]);
214 maxy = fmax(maxy, ND_pos(n)[1]);
215 }
216
217 /* Convert to points
218 */
219 minx *= POINTS_PER_INCH;
220 miny *= POINTS_PER_INCH;
221 maxx *= POINTS_PER_INCH;
222 maxy *= POINTS_PER_INCH;
223
224 /* Check for rotation
225 */
226 if ((p = agget(g, "rotate")) && *p != '\0' && (angle = atoi(p)) != 0) {
227 fprintf(fp, "306 396 translate\n");
228 fprintf(fp, "%d rotate\n", angle);
229 fprintf(fp, "-306 -396 translate\n");
230 }
231
232 /* If user gives scale factor, use it.
233 * Else if figure too large for standard PS page, scale it to fit.
234 */
235 width = maxx - minx + 20;
236 height = maxy - miny + 20;
237 if (width > PSWidth) {
238 if (height > PSHeight) {
239 scale = fmin(PSWidth / width, PSHeight / height);
240 } else
241 scale = PSWidth / width;
242 } else if (height > PSHeight) {
243 scale = PSHeight / height;
244 } else
245 scale = 1.0;
246
247 fprintf(fp, "%f %f translate\n",
248 (PSWidth - scale * (minx + maxx)) / 2.0,
249 (PSHeight - scale * (miny + maxy)) / 2.0);
250 fprintf(fp, "%f %f scale\n", scale, scale);
251
252/*
253 if (Verbose)
254 fprintf (stderr, "Region (%f,%f) (%f,%f), scale %f\n",
255 minx, miny, maxx, maxy, scale);
256*/
257
258 if (do_arrow) {
259 arrow_w = ArrowScale * ARROW_WIDTH / scale;
260 arrow_l = ArrowScale * ARROW_LENGTH / scale;
261 }
262
263 fprintf(fp, "0.0 setlinewidth\n");
264 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
265 if (IS_PORT(n)) {
266 double r;
267 r = sqrt(ND_pos(n)[0] * ND_pos(n)[0] +
268 ND_pos(n)[1] * ND_pos(n)[1]);
269 fprintf(fp, "0 0 %f inch drawCircle\n", r);
270 break;
271 }
272 }
273
274 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
275 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
276 h = aghead(e);
277 fprintf(fp, "%f inch %f inch moveto %f inch %f inch lineto\n",
278 ND_pos(n)[0], ND_pos(n)[1], ND_pos(h)[0],
279 ND_pos(h)[1]);
280 fprintf(fp, "stroke\n");
281 if (do_arrow) {
282 theta =
283 atan2(ND_pos(n)[1] - ND_pos(h)[1],
284 ND_pos(n)[0] - ND_pos(h)[0]);
285 fprintf(fp, "%f %f %.2f %.2f %.2f doArrow\n",
286 ND_pos(h)[0], ND_pos(h)[1], DEGREES(theta),
287 arrow_l, arrow_w);
288 }
289
290 }
291 }
292
293#ifdef BOX
294 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
295 float wd, ht;
296
297 data = getData(n);
298 wd = data->wd;
299 ht = data->ht;
300 fprintf(fp, "%f %f %f %f doBox\n", wd, ht,
301 data->pos.x - wd / 2, data->pos.y - ht / 2);
302 }
303#else
304 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
305 fprintf(fp, "%% %s\n", agnameof(n));
306 if (expMode) {
307 double wd, ht;
308 double r;
309 wd = ND_width(n);
310 ht = ND_height(n);
311 r = sqrt(wd * wd / 4 + ht * ht / 4);
312 fprintf(fp, "%f inch %f inch %f inch %f inch doBox\n", wd, ht,
313 ND_pos(n)[0] - wd / 2, ND_pos(n)[1] - ht / 2);
314 fprintf(fp, "%f inch %f inch %f inch drawCircle\n",
315 ND_pos(n)[0], ND_pos(n)[1], r);
316 } else {
317 if (IS_PORT(n)) {
318 if (!portColor) {
319 fprintf(fp, "0.667 1.000 1.000 sethsbcolor\n");
320 portColor = 1;
321 }
322 } else {
323 if (portColor) {
324 fprintf(fp, "0.0 0.000 0.000 sethsbcolor\n");
325 portColor = 0;
326 }
327 }
328 }
329 fprintf(fp, "%f inch %f inch %f fillCircle\n", ND_pos(n)[0],
330 ND_pos(n)[1], 3 / scale);
331 }
332#endif
333
334 fprintf(fp, "0.667 1.000 1.000 sethsbcolor\n");
335 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
336 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
337 h = aghead(e);
338 fprintf(fp, "%f inch %f inch moveto %f inch %f inch lineto\n",
339 ND_pos(n)[0], ND_pos(n)[1], ND_pos(h)[0],
340 ND_pos(h)[1]);
341 fprintf(fp, "stroke\n");
342 if (do_arrow) {
343 theta =
344 atan2(ND_pos(n)[1] - ND_pos(h)[1],
345 ND_pos(n)[0] - ND_pos(h)[0]);
346 fprintf(fp, "%f %f %.2f %.2f %.2f doArrow\n",
347 ND_pos(h)[0], ND_pos(h)[1], DEGREES(theta),
348 arrow_l, arrow_w);
349 }
350
351 }
352 }
353
354 fprintf(fp, "%s", elog);
355}
356
357void outputGraph(Agraph_t * g, FILE * fp, int expMode)
358{
359 pswrite(g, fp, expMode);
360}
361
362#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:64
static pointf scale(double c, pointf p)
Definition geomprocs.h:130
static int Verbose
Definition gml2gv.c:22
int agnnodes(Agraph_t *g)
Definition graph.c:158
char * agget(void *obj, char *name)
Definition attr.c:442
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:23
#define agtail(e)
Definition cgraph.h:889
#define aghead(e)
Definition cgraph.h:890
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:38
#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:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
#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:158
static void indent(int ix)
Definition gv2gml.c:96
graph or subgraph
Definition cgraph.h:425
Definition geom.h:41
pointf UR
Definition geom.h:41
pointf LL
Definition geom.h:41
Definition legal.c:50
double x
Definition geom.h:29
double y
Definition geom.h:29
Definition grammar.c:94