26 static int nsiter2(
graph_t * g);
27 static void create_aux_edges(
graph_t * g);
28 static void remove_aux_edges(
graph_t * g);
29 static void set_xcoords(
graph_t * g);
30 static void set_ycoords(
graph_t * g);
32 static void expand_leaves(
graph_t * g);
33 static void make_lrvn(
graph_t * g);
34 static void contain_nodes(
graph_t * g);
35 static boolean idealsize(
graph_t * g,
double);
48 for (i = 0; i < el.
size; i++) {
60 largeMinlen (
double l)
62 agerr (
AGERR,
"Edge length %f larger than maximum %u allowed.\nCheck for overwide node(s).\n", l, USHRT_MAX);
63 return (
double)USHRT_MAX;
86 for (i = 0; i < rp->
n; i++) {
98 for (j = 0; (e =
ND_save_in(tp).list[j]); j++) {
107 if (found || !tp)
continue;
110 else hp = (rp-1)->v[0];
132 if (
rank(g, 2, nsiter2(g))) {
134 const int rank_result =
rank(g, 2, nsiter2(g));
144 static int nsiter2(
graph_t * g)
149 if ((s =
agget(g,
"nslimit")))
161 for (i = 0; (e =
ND_out(u).list[i]); i++) {
186 len = largeMinlen (len);
193 static void allocate_aux_edges(
graph_t * g)
202 for (i = 0;
ND_out(n).list[i]; i++);
203 for (j = 0;
ND_in(n).list[j]; j++);
213 make_LR_constraints(
graph_t * g)
236 last =
ND_rank(rank[i].v[0]) = 0;
237 nodesep = sep[i & 1];
238 for (j = 0; j < rank[i].
n; j++) {
251 for (k = 0; (e =
ND_other(u).list[k]); k++) {
258 v = rank[i].
v[j + 1];
262 last = (
ND_rank(v) = last + width);
307 m0 = largeMinlen (m0);
327 static void make_edge_pairs(
graph_t * g)
364 static void contain_clustnodes(
graph_t * g)
404 static void keepout_othernodes(
graph_t * g)
416 for (i =
ND_order(v) - 1; i >= 0; i--) {
444 static void contain_subclust(
graph_t * g)
458 contain_subclust(subg);
468 static void separate_subclust(
graph_t * g)
507 static void pos_clusters(
graph_t * g)
510 contain_clustnodes(g);
511 keepout_othernodes(g);
513 separate_subclust(g);
517 static void compress_graph(
graph_t * g)
537 x =
MIN(x,USHRT_MAX);
541 static void create_aux_edges(
graph_t * g)
543 allocate_aux_edges(g);
544 make_LR_constraints(g);
550 static void remove_aux_edges(
graph_t * g)
553 node_t *n, *nnext, *nprev;
557 for (i = 0; (e =
ND_out(n).list[i]); i++) {
568 for (n =
GD_nlist(g); n; n = nnext) {
594 for (j = 0; j < rank[i].
n; j++) {
613 static void adjustSimple(
graph_t * g,
int delta,
int margin_total)
615 int r, bottom, deltop, delbottom;
621 bottom = (delta+1) / 2;
622 delbottom =
GD_ht1(g) + bottom - (rank[maxr].
ht1 - margin_total);
624 for (r = maxr; r >= minr; r--) {
626 ND_coord(rank[r].v[0]).y += delbottom;
628 deltop =
GD_ht2(g) + (delta-bottom) + delbottom - (rank[minr].ht2 - margin_total);
631 deltop =
GD_ht2(g) + (delta-bottom) - (rank[minr].ht2 - margin_total);
633 for (r = minr-1; r >=
GD_minrank(root); r--) {
638 GD_ht2(g) += (delta - bottom);
648 static void adjustRanks(
graph_t * g,
int margin_total)
652 int maxr, minr, margin;
654 double delta, ht1, ht2;
667 adjustRanks(subg, margin+margin_total);
682 delta = lht - (rht + ht1 + ht2);
684 adjustSimple(g, delta, margin_total);
707 int margin, haveClustLabel = 0;
720 haveClustLabel |= clust_ht(subg);
745 return haveClustLabel;
749 static void set_ycoords(
graph_t * g)
752 double ht2, maxht, delta, d0, d1;
763 for (i = 0; i < rank[r].
n; i++) {
772 for (j = 0; (e =
ND_other(n).list[j]); j++) {
780 if (rank[r].pht2 < ht2)
781 rank[r].
pht2 = rank[r].
ht2 = ht2;
782 if (rank[r].pht1 < ht2)
783 rank[r].
pht1 = rank[r].
ht1 = ht2;
802 (
ND_coord(rank[r].v[0])).y = rank[r].ht1;
811 fprintf(stderr,
"dot set_ycoords: rank %d is empty\n",
814 maxht =
MAX(maxht, delta);
831 maxht =
MAX(maxht, delta);
842 (
ND_coord(rank[r + 1].v[0])).y + maxht;
910 dot_compute_bb(g, root);
917 static void scale_bb(
graph_t * g,
graph_t * root,
double xf,
double yf)
922 scale_bb(
GD_clust(g)[c], root, xf, yf);
935 fprintf(stderr,
"AR=%0.4lf\t Area= %0.4lf\t", AR, (
double)(
GD_bb(g).UR.
x -
GD_bb(g).LL.
x)*(
GD_bb(g).UR.
y -
GD_bb(g).LL.
y)/10000.0);
941 else if (AR <= 0.8 * asp->targetAR) {
944 fprintf(stderr,
"Going to apply another expansion.\n");
950 fprintf(stderr,
"next#iter=%d\n", asp->
nextIter);
960 double xf = 0.0, yf = 0.0, actual, desired;
962 boolean scale_it, filled;
976 filled = idealsize(g, .5);
984 xf = (double)
GD_drawing(g)->size.x / (double) sz.
x;
985 yf = (
double)
GD_drawing(g)->size.y / (double) sz.
y;
986 if ((xf < 1.0) || (yf < 1.0)) {
1001 (double)
GD_bb(g).UR.x;
1003 (double)
GD_bb(g).UR.y;
1004 if ((xf > 1.0) && (yf > 1.0)) {
1005 double scale =
MIN(xf, yf);
1012 actual = ((double) sz.
y) / ((double) sz.
x);
1013 if (actual < desired) {
1014 yf = desired / actual;
1017 xf = actual / desired;
1032 scale_bb(g, g, xf, yf);
1036 if (asp) adjustAspectRatio (g, asp);
1059 return resize_leaf(leaf, lbound);
1063 static void make_leafslots(
graph_t * g)
1070 for (i = 0; i <
GD_rank(g)[r].n; i++) {
1081 for (i =
GD_rank(g)[r].n - 1; i >= 0; i--) {
1101 lbound = resize_leaf(leader, lbound);
1102 if (
ND_out(leader).size > 0) {
1108 lbound = place_leaf(g,
agtail(e1), lbound, j++);
1118 lbound = place_leaf(g,
aghead(e), lbound, j++);
1138 static void expand_leaves(
graph_t * g)
1151 for (i = 0; (e =
ND_other(n).list[i]); i++) {
1180 static void make_lrvn(
graph_t * g)
1204 static void contain_nodes(
graph_t * g)
1218 agerr(
AGERR,
"contain_nodes clust %s rank %d missing node\n",
1234 static boolean idealsize(
graph_t * g,
double minallowed)
1236 double xf, yf, f, R;
1237 pointf b, relpage, margin;
1241 if (relpage.
x < 0.001 || relpage.
y < 0.001)
1244 relpage = sub_pointf(relpage, margin);
1245 relpage = sub_pointf(relpage, margin);
1248 xf = relpage.
x / b.
x;
1249 yf = relpage.
y / b.
y;
1250 if ((xf >= 1.0) && (yf >= 1.0))
1254 xf = yf =
MAX(f, minallowed);
1256 R = ceil((xf * b.
x) / relpage.
x);
1257 xf = ((R * relpage.
x) / b.
x);
1258 R = ceil((yf * b.
y) / relpage.
y);
1259 yf = ((R * relpage.
y) / b.
y);
#define elist_append(item, L)
void fast_nodeapp(Agnode_t *, Agnode_t *)
Agedge_t * find_fast_edge(Agnode_t *, Agnode_t *)
CGRAPH_API Agedge_t * agfstin(Agraph_t *g, Agnode_t *n)
#define ALLOC(size, ptr, type)
Agnode_t * virtual_node(Agraph_t *)
EXTERN Agsym_t * G_margin
void unmerge_oneway(Agedge_t *)
#define alloc_elist(n, L)
int agerr(agerrlevel_t level, const char *fmt,...)
CGRAPH_API int agcontains(Agraph_t *, void *)
CGRAPH_API Agraph_t * agroot(void *obj)
CGRAPH_API Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
void dot_concentrate(graph_t *g)
char * agget(void *obj, char *name)
node_t * UF_find(node_t *n)
CGRAPH_API Agraph_t * agraphof(void *obj)
CGRAPH_API Agnode_t * agtail(Agedge_t *e)
int rank(graph_t *g, int balance, int maxiter)
CGRAPH_API Agnode_t * aghead(Agedge_t *e)
int selfRightSpace(edge_t *e)
CGRAPH_API char * agnameof(void *)
void mark_lowclusters(Agraph_t *root)
int late_int(void *obj, attrsym_t *attr, int def, int low)
Agraph_t * dot_root(void *p)
if(aagss+aagstacksize-1<=aagssp)
#define GD_exact_ranksep(g)
EXTERN unsigned char Concentrate
EXTERN unsigned char Verbose
void zapinlist(elist *, Agedge_t *)
CGRAPH_API int agnnodes(Agraph_t *g)
CGRAPH_API Agedge_t * agnxtin(Agraph_t *g, Agedge_t *e)
void gv_nodesize(node_t *n, boolean flip)
int countDummyNodes(graph_t *g)
Agedge_t * make_aux_edge(Agnode_t *, Agnode_t *, double, int)
int flat_edges(Agraph_t *)
CGRAPH_API Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
void dot_position(Agraph_t *, aspect_t *)
char * el(GVJ_t *job, char *template,...)
int ports_eq(edge_t *, edge_t *)
Agedge_t * fast_edge(Agedge_t *)