Graphviz 14.1.2~dev.20251224.0902
Loading...
Searching...
No Matches
tlayout.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/* tlayout.c:
12 * Written by Emden R. Gansner
13 *
14 * Module for initial layout, using point nodes and ports.
15 *
16 * Note: If interior nodes are not connected, they tend to fly apart,
17 * despite being tied to port nodes. This occurs because, as initially
18 * coded, as the nodes tend to straighten into a line, the radius
19 * grows causing more expansion. Is the problem really here and not
20 * with disconnected nodes in xlayout? If here, we can either forbid
21 * expansion or eliminate repulsion between nodes only connected
22 * via port nodes.
23 */
24
25#include "config.h"
26
27/* uses PRIVATE interface */
28#define FDP_PRIVATE 1
29
30#include <fdpgen/dbg.h>
31#include <fdpgen/grid.h>
32#include <math.h>
33#include <neatogen/neato.h>
34#include <stdbool.h>
35#include <stdlib.h>
36#include <sys/types.h>
37#include <time.h>
38
39#ifndef HAVE_SRAND48
40#define srand48 srand
41#endif
42
43#include <common/globals.h>
44#include <fdpgen/tlayout.h>
45
46#define D_useGrid (fdp_parms->useGrid)
47#define D_useNew (fdp_parms->useNew)
48#define D_numIters (fdp_parms->numIters)
49#define D_unscaled (fdp_parms->unscaled)
50#define D_C (fdp_parms->C)
51#define D_Tfact (fdp_parms->Tfact)
52#define D_K (fdp_parms->K)
53#define D_T0 (fdp_parms->T0)
54
55/* Actual parameters used; initialized using fdp_parms, then possibly
56 * updated with graph-specific values.
57 */
58typedef struct {
59 int useGrid; /* use grid for speed up */
60 int useNew; /* encode x-K into attractive force */
61 long seed; /* seed for position RNG */
62 int numIters; /* actual iterations in layout */
63 int maxIters; /* max iterations in layout */
64 int unscaled; /* % of iterations used in pass 1 */
65 double C; /* Repulsion factor in xLayout */
66 double Tfact; /* scale temp from default expression */
67 double K; /* spring constant; ideal distance */
68 double T0; /* initial temperature */
69 int smode; /* seed mode */
70 double Cell; /* grid cell size */
71 double Wd; /* half-width of boundary */
72 double Ht; /* half-height of boundary */
73 int pass1; /* iterations used in pass 1 */
74 int loopcnt; /* actual iterations in this pass */
75} parms_t;
76
78
79#define T_useGrid (parms.useGrid)
80#define T_useNew (parms.useNew)
81#define T_seed (parms.seed)
82#define T_numIters (parms.numIters)
83#define T_maxIters (parms.maxIters)
84#define T_unscaled (parms.unscaled)
85#define T_C (parms.C)
86#define T_Tfact (parms.Tfact)
87#define T_K (parms.K)
88#define T_T0 (parms.T0)
89#define T_smode (parms.smode)
90#define T_Cell (parms.Cell)
91#define T_Wd (parms.Wd)
92#define T_Ht (parms.Ht)
93#define T_pass1 (parms.pass1)
94#define T_loopcnt (parms.loopcnt)
95
96#define EXPFACTOR 1.2
97#define DFLT_maxIters 600
98#define DFLT_K 0.3
99#define DFLT_Cell 0.0
100#define DFLT_seed 1
101#define DFLT_smode INIT_RANDOM
102
103static double cool(int t) { return T_T0 * (T_maxIters - t) / T_maxIters; }
104
105static void reset_params(void) { T_T0 = -1.0; }
106
107/* Set parameters for expansion phase based on initial
108 * layout parameters. If T0 is not set, we set it here
109 * based on the size of the graph. In this case, we
110 * return true, so that fdp_tLayout can unset T0, to be
111 * reset by a recursive call to fdp_tLayout.
112 *
113 * @return Does `reset` need to be called later?
114 */
115static bool init_params(graph_t *g, xparams *xpms) {
116 bool ret = false;
117
118 if (T_T0 == -1.0) {
119 int nnodes = agnnodes(g);
120
121 T_T0 = T_Tfact * T_K * sqrt(nnodes) / 5;
122#ifdef DEBUG
123 if (Verbose) {
124 prIndent();
125 fprintf(stderr, "tlayout %s", agnameof(g));
126 fprintf(stderr, "(%s) : T0 %f\n", agnameof(GORIG(g->root)), T_T0);
127 }
128#endif
129 ret = true;
130 }
131
132 xpms->T0 = cool(T_pass1);
133 xpms->K = T_K;
134 xpms->C = T_C;
135 xpms->numIters = T_maxIters - T_pass1;
136
137 if (T_numIters >= 0) {
138 if (T_numIters <= T_pass1) {
140 xpms->loopcnt = 0;
141 } else if (T_numIters <= T_maxIters) {
143 xpms->loopcnt = T_numIters - T_pass1;
144 }
145 } else {
147 xpms->loopcnt = xpms->numIters;
148 }
149 return ret;
150}
151
159 T_C = D_C;
161 T_maxIters =
162 late_int(g, agattr_text(g, AGRAPH, "maxiter", NULL), DFLT_maxIters, 0);
163 D_K = T_K = late_double(g, agattr_text(g, AGRAPH, "K", NULL), DFLT_K, 0.0);
164 if (D_T0 == -1.0) {
165 T_T0 = late_double(g, agattr_text(g, AGRAPH, "T0", NULL), -1.0, 0.0);
166 } else
167 T_T0 = D_T0;
170 if (T_smode == INIT_SELF) {
171 agwarningf("fdp does not support start=self - ignoring\n");
173 }
174
175 T_pass1 = T_unscaled * T_maxIters / 100;
176
177 if (T_useGrid) {
178 if (T_Cell <= 0.0)
179 T_Cell = 3 * T_K;
180 }
181#ifdef DEBUG
182 if (Verbose) {
183 prIndent();
184 fprintf(stderr, "Params %s : K %f T0 %f Tfact %f maxIters %d unscaled %d\n",
186 }
187#endif
188}
189
190static void doRep(node_t *p, node_t *q, double xdelta, double ydelta,
191 double dist2) {
192 double force;
193 double dist;
194
195 while (dist2 == 0.0) {
196 xdelta = 5 - rand() % 10;
197 ydelta = 5 - rand() % 10;
198 dist2 = xdelta * xdelta + ydelta * ydelta;
199 }
200 if (T_useNew) {
201 dist = sqrt(dist2);
202 force = T_K * T_K / (dist * dist2);
203 } else
204 force = T_K * T_K / dist2;
205 if (IS_PORT(p) && IS_PORT(q))
206 force *= 10.0;
207 DISP(q)[0] += xdelta * force;
208 DISP(q)[1] += ydelta * force;
209 DISP(p)[0] -= xdelta * force;
210 DISP(p)[1] -= ydelta * force;
211}
212
214static void applyRep(Agnode_t *p, Agnode_t *q) {
215 double xdelta, ydelta;
216
217 xdelta = ND_pos(q)[0] - ND_pos(p)[0];
218 ydelta = ND_pos(q)[1] - ND_pos(p)[1];
219 doRep(p, q, xdelta, ydelta, xdelta * xdelta + ydelta * ydelta);
220}
221
222static void doNeighbor(Grid *grid, int i, int j, node_list *nodes) {
223 cell *cellp = findGrid(grid, i, j);
224 node_list *qs;
225 Agnode_t *p;
226 Agnode_t *q;
227 double xdelta, ydelta;
228 double dist2;
229
230 if (cellp) {
231#ifdef DEBUG
232 if (Verbose >= 3) {
233 prIndent();
234 fprintf(stderr, " doNeighbor (%d,%d) : %d\n", i, j, gLength(cellp));
235 }
236#endif
237 for (; nodes != 0; nodes = nodes->next) {
238 p = nodes->node;
239 for (qs = cellp->nodes; qs != 0; qs = qs->next) {
240 q = qs->node;
241 xdelta = (ND_pos(q))[0] - (ND_pos(p))[0];
242 ydelta = (ND_pos(q))[1] - (ND_pos(p))[1];
243 dist2 = xdelta * xdelta + ydelta * ydelta;
244 if (dist2 < T_Cell * T_Cell)
245 doRep(p, q, xdelta, ydelta, dist2);
246 }
247 }
248 }
249}
250
251static int gridRepulse(void *c, void *g) {
252 cell *const cellp = c;
253 Grid *const grid = g;
254 node_list *nodes = cellp->nodes;
255 int i = cellp->p.i;
256 int j = cellp->p.j;
257 node_list *p;
258 node_list *q;
259
260#ifdef DEBUG
261 if (Verbose >= 3) {
262 prIndent();
263 fprintf(stderr, "gridRepulse (%d,%d) : %d\n", i, j, gLength(cellp));
264 }
265#endif
266 for (p = nodes; p != 0; p = p->next) {
267 for (q = nodes; q != 0; q = q->next)
268 if (p != q)
269 applyRep(p->node, q->node);
270 }
271
272 doNeighbor(grid, i - 1, j - 1, nodes);
273 doNeighbor(grid, i - 1, j, nodes);
274 doNeighbor(grid, i - 1, j + 1, nodes);
275 doNeighbor(grid, i, j - 1, nodes);
276 doNeighbor(grid, i, j + 1, nodes);
277 doNeighbor(grid, i + 1, j - 1, nodes);
278 doNeighbor(grid, i + 1, j, nodes);
279 doNeighbor(grid, i + 1, j + 1, nodes);
280
281 return 0;
282}
283
284/* Attractive force = weight × (d × d) ÷ K
285 * or force = (d - L(e)) × weight(e)
286 */
287static void applyAttr(Agnode_t *p, Agnode_t *q, Agedge_t *e) {
288 double xdelta, ydelta;
289 double force;
290 double dist;
291 double dist2;
292
293 xdelta = ND_pos(q)[0] - ND_pos(p)[0];
294 ydelta = ND_pos(q)[1] - ND_pos(p)[1];
295 dist2 = xdelta * xdelta + ydelta * ydelta;
296 while (dist2 == 0.0) {
297 xdelta = 5 - rand() % 10;
298 ydelta = 5 - rand() % 10;
299 dist2 = xdelta * xdelta + ydelta * ydelta;
300 }
301 dist = sqrt(dist2);
302 if (T_useNew)
303 force = ED_factor(e) * (dist - ED_dist(e)) / dist;
304 else
305 force = ED_factor(e) * dist / ED_dist(e);
306 DISP(q)[0] -= xdelta * force;
307 DISP(q)[1] -= ydelta * force;
308 DISP(p)[0] += xdelta * force;
309 DISP(p)[1] += ydelta * force;
310}
311
312static void updatePos(Agraph_t *g, double temp, bport_t *pp) {
313 Agnode_t *n;
314 double temp2;
315 double len2;
316 double x, y, d;
317 double dx, dy;
318
319 temp2 = temp * temp;
320 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
321 if (ND_pinned(n) & P_FIX)
322 continue;
323 dx = DISP(n)[0];
324 dy = DISP(n)[1];
325 len2 = dx * dx + dy * dy;
326
327 /* limit by temperature */
328 if (len2 < temp2) {
329 x = ND_pos(n)[0] + dx;
330 y = ND_pos(n)[1] + dy;
331 } else {
332 double fact = temp / sqrt(len2);
333 x = ND_pos(n)[0] + dx * fact;
334 y = ND_pos(n)[1] + dy * fact;
335 }
336
337 /* if ports, limit by boundary */
338 if (pp) {
339 d = sqrt(x * x / (T_Wd * T_Wd) + y * y / (T_Ht * T_Ht));
340 if (IS_PORT(n)) {
341 ND_pos(n)[0] = x / d;
342 ND_pos(n)[1] = y / d;
343 } else if (d >= 1.0) {
344 ND_pos(n)[0] = 0.95 * x / d;
345 ND_pos(n)[1] = 0.95 * y / d;
346 } else {
347 ND_pos(n)[0] = x;
348 ND_pos(n)[1] = y;
349 }
350 } else {
351 ND_pos(n)[0] = x;
352 ND_pos(n)[1] = y;
353 }
354 }
355}
356
357#define FLOOR(d) ((int)floor(d))
358
359static void gAdjust(Agraph_t *g, double temp, bport_t *pp, Grid *grid) {
360 Agnode_t *n;
361 Agedge_t *e;
362
363 if (temp <= 0.0)
364 return;
365
367
368 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
369 DISP(n)[0] = DISP(n)[1] = 0;
370 addGrid(grid, FLOOR((ND_pos(n))[0] / T_Cell),
371 FLOOR((ND_pos(n))[1] / T_Cell), n);
372 }
373
374 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
375 for (e = agfstout(g, n); e; e = agnxtout(g, e))
376 if (n != aghead(e))
377 applyAttr(n, aghead(e), e);
378 }
380
381 updatePos(g, temp, pp);
382}
383
384static void adjust(Agraph_t *g, double temp, bport_t *pp) {
385 Agnode_t *n;
386 Agnode_t *n1;
387 Agedge_t *e;
388
389 if (temp <= 0.0)
390 return;
391
392 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
393 DISP(n)[0] = DISP(n)[1] = 0;
394 }
395
396 for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
397 for (n1 = agnxtnode(g, n); n1; n1 = agnxtnode(g, n1)) {
398 applyRep(n, n1);
399 }
400 for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
401 if (n != aghead(e))
402 applyAttr(n, aghead(e), e);
403 }
404 }
405
406 updatePos(g, temp, pp);
407}
408
409/* Create initial layout of nodes
410 * TODO :
411 * Position nodes near neighbors with positions.
412 * Use bbox to reset K.
413 */
414static pointf initPositions(graph_t *g, bport_t *pp) {
415 int nG = agnnodes(g) - NPORTS(g);
416 double size;
417 Agnode_t *np;
418 int n_pos = 0; /* no. of nodes with position info */
419 boxf bb = {{0, 0}, {0, 0}};
420 pointf ctr; /* center of boundary ellipse */
421 long local_seed;
422 double PItimes2 = M_PI * 2.0;
423
424 for (np = agfstnode(g); np; np = agnxtnode(g, np)) {
425 if (ND_pinned(np)) {
426 if (n_pos) {
427 bb.LL.x = MIN(ND_pos(np)[0], bb.LL.x);
428 bb.LL.y = MIN(ND_pos(np)[1], bb.LL.y);
429 bb.UR.x = MAX(ND_pos(np)[0], bb.UR.x);
430 bb.UR.y = MAX(ND_pos(np)[1], bb.UR.y);
431 } else {
432 bb.UR.x = bb.LL.x = ND_pos(np)[0];
433 bb.UR.y = bb.LL.y = ND_pos(np)[1];
434 }
435 n_pos++;
436 }
437 }
438
439 size = T_K * (sqrt((double)nG) + 1.0);
440 T_Wd = T_Ht = EXPFACTOR * (size / 2.0);
441 if (n_pos == 1) {
442 ctr.x = bb.LL.x;
443 ctr.y = bb.LL.y;
444 } else if (n_pos > 1) {
445 double alpha, area, width, height, quot;
446 ctr.x = (bb.LL.x + bb.UR.x) / 2.0;
447 ctr.y = (bb.LL.y + bb.UR.y) / 2.0;
448 width = EXPFACTOR * (bb.UR.x - bb.LL.x);
449 height = EXPFACTOR * (bb.UR.y - bb.LL.y);
450 area = 4.0 * T_Wd * T_Ht;
451 quot = width * height / area;
452 if (quot >= 1.0) { /* If bbox has large enough area, use it */
453 T_Wd = width / 2.0;
454 T_Ht = height / 2.0;
455 } else if (quot > 0.0) { /* else scale up to have enough area */
456 quot = 2.0 * sqrt(quot);
457 T_Wd = width / quot;
458 T_Ht = height / quot;
459 } else { /* either width or height is 0 */
460 if (width > 0) {
461 height = area / width;
462 T_Wd = width / 2.0;
463 T_Ht = height / 2.0;
464 } else if (height > 0) {
465 width = area / height;
466 T_Wd = width / 2.0;
467 T_Ht = height / 2.0;
468 }
469 /* If width = height = 0, use Wd and Ht as defined above for
470 * the case the n_pos == 0.
471 */
472 }
473
474 /* Construct enclosing ellipse */
475 alpha = atan2(T_Ht, T_Wd);
476 T_Wd = T_Wd / cos(alpha);
477 T_Ht = T_Ht / sin(alpha);
478 } else {
479 ctr.x = ctr.y = 0;
480 }
481
482 /* Set seed value */
483 if (T_smode == INIT_RANDOM)
484 local_seed = T_seed;
485 else {
486 local_seed = (long)time(NULL);
487 }
488 srand48(local_seed);
489
490 /* If ports, place ports on and nodes within an ellipse centered at origin
491 * with halfwidth Wd and halfheight Ht.
492 * If no ports, place nodes within a rectangle centered at origin
493 * with halfwidth Wd and halfheight Ht. Nodes with a given position
494 * are translated. Wd and Ht are set to contain all positioned points.
495 * The reverse translation will be applied to all
496 * nodes at the end of the layout.
497 * TODO: place unfixed points using adjacent ports or fixed pts.
498 */
499 if (pp) {
500 while (pp->e) { /* position ports on ellipse */
501 np = pp->n;
502 ND_pos(np)[0] = T_Wd * cos(pp->alpha) + ctr.x;
503 ND_pos(np)[1] = T_Ht * sin(pp->alpha) + ctr.y;
504 ND_pinned(np) = P_SET;
505 pp++;
506 }
507 for (np = agfstnode(g); np; np = agnxtnode(g, np)) {
508 if (IS_PORT(np))
509 continue;
510 if (ND_pinned(np)) {
511 ND_pos(np)[0] -= ctr.x;
512 ND_pos(np)[1] -= ctr.y;
513 } else {
514 pointf p = {0.0, 0.0};
515 int cnt = 0;
516 node_t *op;
517 edge_t *ep;
518 for (ep = agfstedge(g, np); ep; ep = agnxtedge(g, ep, np)) {
519 if (aghead(ep) == agtail(ep))
520 continue;
521 op = aghead(ep) == np ? agtail(ep) : aghead(ep);
522 if (!hasPos(op))
523 continue;
524 if (cnt) {
525 p.x = (p.x * cnt + ND_pos(op)[0]) / (cnt + 1);
526 p.y = (p.y * cnt + ND_pos(op)[1]) / (cnt + 1);
527 } else {
528 p.x = ND_pos(op)[0];
529 p.y = ND_pos(op)[1];
530 }
531 cnt++;
532 }
533 if (cnt > 1) {
534 ND_pos(np)[0] = p.x;
535 ND_pos(np)[1] = p.y;
536 } else if (cnt == 1) {
537 ND_pos(np)[0] = 0.98 * p.x + 0.1 * ctr.x;
538 ND_pos(np)[1] = 0.9 * p.y + 0.1 * ctr.y;
539 } else {
540 double angle = PItimes2 * drand48();
541 double radius = 0.9 * drand48();
542 ND_pos(np)[0] = radius * T_Wd * cos(angle);
543 ND_pos(np)[1] = radius * T_Ht * sin(angle);
544 }
545 ND_pinned(np) = P_SET;
546 }
547 }
548 } else {
549 if (n_pos) { /* If positioned nodes */
550 for (np = agfstnode(g); np; np = agnxtnode(g, np)) {
551 if (ND_pinned(np)) {
552 ND_pos(np)[0] -= ctr.x;
553 ND_pos(np)[1] -= ctr.y;
554 } else {
555 ND_pos(np)[0] = T_Wd * (2.0 * drand48() - 1.0);
556 ND_pos(np)[1] = T_Ht * (2.0 * drand48() - 1.0);
557 }
558 }
559 } else { /* No ports or positions; place randomly */
560 for (np = agfstnode(g); np; np = agnxtnode(g, np)) {
561 ND_pos(np)[0] = T_Wd * (2.0 * drand48() - 1.0);
562 ND_pos(np)[1] = T_Ht * (2.0 * drand48() - 1.0);
563 }
564 }
565 }
566
567 return ctr;
568}
569
570/* Given graph g with ports nodes, layout g respecting ports.
571 * If some node have position information, it may be useful to
572 * reset temperature and other parameters to reflect this.
573 */
574void fdp_tLayout(graph_t *g, xparams *xpms) {
575 bport_t *const pp = PORTS(g);
576 const bool reset = init_params(g, xpms);
577 const pointf ctr = initPositions(g, pp);
578
579 if (T_useGrid) {
580 Grid *const grid = mkGrid(agnnodes(g));
582 for (int i = 0; i < T_loopcnt; i++) {
583 const double temp = cool(i);
584 gAdjust(g, temp, pp, grid);
585 }
586 delGrid(grid);
587 } else {
588 for (int i = 0; i < T_loopcnt; i++) {
589 const double temp = cool(i);
590 adjust(g, temp, pp);
591 }
592 }
593
594 if (ctr.x != 0.0 || ctr.y != 0.0) {
595 for (Agnode_t *n = agfstnode(g); n; n = agnxtnode(g, n)) {
596 ND_pos(n)[0] += ctr.x;
597 ND_pos(n)[1] += ctr.y;
598 }
599 }
600 if (reset)
601 reset_params();
602}
#define MIN(a, b)
Definition arith.h:28
#define M_PI
Definition arith.h:41
#define MAX(a, b)
Definition arith.h:33
int late_int(void *obj, attrsym_t *attr, int defaultValue, int minimum)
Definition utils.c:36
double late_double(void *obj, attrsym_t *attr, double defaultValue, double minimum)
Definition utils.c:51
double drand48(void)
Definition utils.c:1547
#define P_SET
Definition const.h:247
#define P_FIX
Definition const.h:248
static float dy
Definition draw.c:40
static float dx
Definition draw.c:39
static const char adjust[]
Definition emit.c:3080
static double dist(int dim, double *x, double *y)
static bool Verbose
Definition gml2gv.c:24
node NULL
Definition grammar.y:181
static int cnt(Dict_t *d, Dtlink_t **set)
Definition graph.c:196
void adjustGrid(Grid *g, int nnodes)
Definition grid.c:169
int gLength(cell *p)
return the number of nodes in a cell
Definition grid.c:237
void delGrid(Grid *g)
close and free all grid resources
Definition grid.c:194
void walkGrid(Grid *g, int(*walkf)(void *, void *))
Definition grid.c:220
void addGrid(Grid *g, int i, int j, Agnode_t *n)
add node n to cell (i,j) in grid g
Definition grid.c:202
cell * findGrid(Grid *g, int i, int j)
Definition grid.c:227
Grid * mkGrid(int cellHint)
Definition grid.c:155
int agnnodes(Agraph_t *g)
Definition graph.c:155
Agsym_t * agattr_text(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up text attributes of a graph
Definition attr.c:334
#define ED_dist(e)
Definition types.h:602
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:26
#define agtail(e)
Definition cgraph.h:977
Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Definition edge.c:96
#define ED_factor(e)
Definition types.h:585
#define aghead(e)
Definition cgraph.h:978
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:41
Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
Definition edge.c:87
void agwarningf(const char *fmt,...)
Definition agerror.c:173
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_pinned(n)
Definition types.h:519
#define ND_pos(n)
Definition types.h:520
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:143
@ AGRAPH
Definition cgraph.h:207
@ grid
Definition gvgen.c:34
#define hasPos(n)
Definition macros.h:18
#define INIT_SELF
Definition neato.h:28
#define INIT_RANDOM
Definition neato.h:30
int setSeed(graph_t *G, int dflt, long *seedp)
Definition neatoinit.c:920
PATHUTIL_API COORD dist2(Ppoint_t, Ppoint_t)
Definition visibility.c:120
void reset(sgraph *G)
Definition sgraph.c:29
#define alpha
Definition shapes.c:4056
static const double cool
graph or subgraph
Definition cgraph.h:424
Agraph_t * root
subgraphs - ancestors
Definition cgraph.h:433
Definition grid.c:64
Agnode_t * node
Definition grid.h:25
struct _node_list * next
Definition grid.h:26
Definition geom.h:41
pointf UR
Definition geom.h:41
pointf LL
Definition geom.h:41
result of partitioning available space, part of maze
Definition grid.h:33
node_list * nodes
Definition grid.h:35
gridpt p
Definition grid.h:34
int j
Definition grid.h:30
int i
Definition grid.h:30
double Tfact
Definition tlayout.c:66
int numIters
Definition tlayout.c:62
int useGrid
Definition tlayout.c:59
double T0
Definition tlayout.c:68
double Ht
Definition tlayout.c:72
int unscaled
Definition tlayout.c:64
double Cell
Definition tlayout.c:70
int pass1
Definition tlayout.c:73
int loopcnt
Definition tlayout.c:74
double C
Definition tlayout.c:65
double K
Definition tlayout.c:67
long seed
Definition tlayout.c:61
int smode
Definition tlayout.c:69
int useNew
Definition tlayout.c:60
int maxIters
Definition tlayout.c:63
double Wd
Definition tlayout.c:71
double x
Definition geom.h:29
double y
Definition geom.h:29
int loopcnt
Definition xlayout.h:24
int numIters
Definition xlayout.h:20
double T0
Definition xlayout.h:21
double C
Definition xlayout.h:23
double K
Definition xlayout.h:22
static bool init_params(graph_t *g, xparams *xpms)
Definition tlayout.c:115
#define D_unscaled
Definition tlayout.c:49
#define DFLT_maxIters
Definition tlayout.c:97
#define D_C
Definition tlayout.c:50
#define T_C
Definition tlayout.c:85
#define srand48
Definition tlayout.c:40
#define FLOOR(d)
Definition tlayout.c:357
#define T_Wd
Definition tlayout.c:91
static int gridRepulse(void *c, void *g)
Definition tlayout.c:251
#define T_unscaled
Definition tlayout.c:84
#define T_seed
Definition tlayout.c:81
#define T_smode
Definition tlayout.c:89
#define DFLT_smode
Definition tlayout.c:101
void fdp_initParams(graph_t *g)
initialize parameters based on root graph attributes
Definition tlayout.c:153
static void applyAttr(Agnode_t *p, Agnode_t *q, Agedge_t *e)
Definition tlayout.c:287
#define T_maxIters
Definition tlayout.c:83
#define T_pass1
Definition tlayout.c:93
static pointf initPositions(graph_t *g, bport_t *pp)
Definition tlayout.c:414
static void applyRep(Agnode_t *p, Agnode_t *q)
repulsive force = K × K ÷ d or K × K ÷ d × d
Definition tlayout.c:214
static void doRep(node_t *p, node_t *q, double xdelta, double ydelta, double dist2)
Definition tlayout.c:190
#define DFLT_K
Definition tlayout.c:98
static void updatePos(Agraph_t *g, double temp, bport_t *pp)
Definition tlayout.c:312
#define D_useGrid
Definition tlayout.c:46
#define D_K
Definition tlayout.c:52
#define T_Tfact
Definition tlayout.c:86
#define D_T0
Definition tlayout.c:53
#define EXPFACTOR
Definition tlayout.c:96
#define D_numIters
Definition tlayout.c:48
static void doNeighbor(Grid *grid, int i, int j, node_list *nodes)
Definition tlayout.c:222
#define DFLT_seed
Definition tlayout.c:100
#define DFLT_Cell
Definition tlayout.c:99
#define T_Cell
Definition tlayout.c:90
#define T_K
Definition tlayout.c:87
#define T_Ht
Definition tlayout.c:92
#define T_useGrid
Definition tlayout.c:79
#define D_Tfact
Definition tlayout.c:51
void fdp_tLayout(graph_t *g, xparams *xpms)
Definition tlayout.c:574
static parms_t parms
Definition tlayout.c:77
#define T_numIters
Definition tlayout.c:82
#define T_T0
Definition tlayout.c:88
#define T_useNew
Definition tlayout.c:80
#define T_loopcnt
Definition tlayout.c:94
#define D_useNew
Definition tlayout.c:47
static void reset_params(void)
Definition tlayout.c:105
static void gAdjust(Agraph_t *g, double temp, bport_t *pp, Grid *grid)
Definition tlayout.c:359
static void clearGrid(grid_t *g)
Definition tvnodes.c:309