示例#1
0
文件: rank.c 项目: jeci-sarl/graphviz
static int 
rank_set_class(graph_t * g)
{
    static char *name[] = { "same", "min", "source", "max", "sink", NULL };
    static int class[] =
	{ SAMERANK, MINRANK, SOURCERANK, MAXRANK, SINKRANK, 0 };
    int val;

    if (is_cluster(g))
	return CLUSTER;
    val = maptoken(agget(g, "rank"), name, class);
    GD_set_type(g) = val;
    return val;
}

static int 
make_new_cluster(graph_t * g, graph_t * subg)
{
    int cno;
    cno = ++(GD_n_cluster(g));
    GD_clust(g) = ZALLOC(cno + 1, GD_clust(g), graph_t *, GD_n_cluster(g));
    GD_clust(g)[cno] = subg;
    do_graph_label(subg);
    return cno;
}
示例#2
0
static void 
dot_cleanup_graph(graph_t * g)
{
    int i, c;
    graph_t *clust;

    for (c = 1; c <= GD_n_cluster(g); c++) {
	clust = GD_clust(g)[c];
	GD_cluster_was_collapsed(clust) = FALSE;
	dot_cleanup(clust);
    }
    if (GD_clust(g)) free (GD_clust(g));
    if (GD_rankleader(g)) free (GD_rankleader(g));

    free_list(GD_comp(g));
    if (GD_rank(g)) {
	for (i = GD_minrank(g); i <= GD_maxrank(g); i++)
	    free(GD_rank(g)[i].av);
	if (GD_minrank(g) == -1)
	    free(GD_rank(g)-1);
	else
	    free(GD_rank(g));
    }
    if (g != agroot(g)) 
#ifndef WITH_CGRAPH
	memset(&(g->u), 0, sizeof(Agraphinfo_t));
#else /* WITH_CGRAPH */
	agclean(g,AGRAPH,"Agraphinfo_t");
#endif /* WITH_CGRAPH */
}
示例#3
0
/* place_graph_label:
 * Put cluster labels recursively in the non-flip case.
 * The adjustments to the bounding boxes should no longer
 * be necessary, since we now guarantee the label fits in
 * the cluster.
 */
void place_graph_label(graph_t * g)
{
    int c;
    pointf p, d;

    if ((g != agroot(g)) && (GD_label(g)) && !GD_label(g)->set) {
	if (GD_label_pos(g) & LABEL_AT_TOP) {
	    d = GD_border(g)[TOP_IX];
	    p.y = GD_bb(g).UR.y - d.y / 2;
	} else {
	    d = GD_border(g)[BOTTOM_IX];
	    p.y = GD_bb(g).LL.y + d.y / 2;
	}

	if (GD_label_pos(g) & LABEL_AT_RIGHT) {
	    p.x = GD_bb(g).UR.x - d.x / 2;
	} else if (GD_label_pos(g) & LABEL_AT_LEFT) {
	    p.x = GD_bb(g).LL.x + d.x / 2;
	} else {
	    p.x = (GD_bb(g).LL.x + GD_bb(g).UR.x) / 2;
	}
	GD_label(g)->pos = p;
	GD_label(g)->set = TRUE;
    }

    for (c = 1; c <= GD_n_cluster(g); c++)
	place_graph_label(GD_clust(g)[c]);
}
示例#4
0
文件: layout.c 项目: zionyx/graphviz
/* evalPositions:
 * The input is laid out, but node coordinates
 * are relative to smallest containing cluster.
 * Walk through all nodes and clusters, translating
 * the positions to absolute coordinates.
 * Assume that when called, g's bounding box is
 * in absolute coordinates and that box of root graph
 * has LL at origin.
 */
static void evalPositions(graph_t * g, graph_t* rootg)
{
    int i;
    graph_t *subg;
    node_t *n;
    boxf bb;
    boxf sbb;

    bb = BB(g);

    /* translate nodes in g */
    if (g != rootg) {
	for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	    if (PARENT(n) != g)
		continue;
	    ND_pos(n)[0] += bb.LL.x;
	    ND_pos(n)[1] += bb.LL.y;
	}
    }

    /* translate top-level clusters and recurse */
    for (i = 1; i <= GD_n_cluster(g); i++) {
	subg = GD_clust(g)[i];
	if (g != rootg) {
	    sbb = BB(subg);
	    sbb.LL.x += bb.LL.x;
	    sbb.LL.y += bb.LL.y;
	    sbb.UR.x += bb.LL.x;
	    sbb.UR.y += bb.LL.y;
	    BB(subg) = sbb;
	}
	evalPositions(subg, rootg);
    }
}
示例#5
0
文件: rank.c 项目: jeci-sarl/graphviz
static void 
node_induce(graph_t * par, graph_t * g)
{
    node_t *n, *nn;
    edge_t *e;
    int i;

    /* enforce that a node is in at most one cluster at this level */
    for (n = agfstnode(g); n; n = nn) {
	nn = agnxtnode(g, n);
	if (ND_ranktype(n)) {
	    agdelete(g, n);
	    continue;
	}
	for (i = 1; i < GD_n_cluster(par); i++)
	    if (agcontains(GD_clust(par)[i], n))
		break;
	if (i < GD_n_cluster(par))
	    agdelete(g, n);
	ND_clust(n) = NULL;
    }

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	for (e = agfstout(dot_root(g), n); e; e = agnxtout(dot_root(g), e)) {
	    if (agcontains(g, aghead(e)))
		agsubedge(g,e,1);
	}
    }
}
示例#6
0
/* place_graph_label:
 * Put cluster labels recursively in the non-flip case.
 * The adjustments to the bounding boxes should no longer
 * be necessary, since we now guarantee the label fits in
 * the cluster.
 */
void place_graph_label(graph_t * g)
{
    int c;
#ifdef OLD
    int minx, maxx;
#endif
    point p, d;

    if ((g != g->root) && (GD_label(g)) && !GD_label(g)->set) {
	if (GD_label_pos(g) & LABEL_AT_TOP) {
	    d = GD_border(g)[TOP_IX];
	    p.y = GD_bb(g).UR.y - d.y / 2;
	} else {
	    d = GD_border(g)[BOTTOM_IX];
	    p.y = GD_bb(g).LL.y + d.y / 2;
	}

	if (GD_label_pos(g) & LABEL_AT_RIGHT) {
	    p.x = GD_bb(g).UR.x - d.x / 2;
#ifdef OLD
	    minx = p.x - d.x / 2;
	    if (GD_bb(g).LL.x > minx)
		GD_bb(g).LL.x = minx;
	    if (GD_bb(g->root).LL.x > minx)
		GD_bb(g->root).LL.x = minx;
#endif
	} else if (GD_label_pos(g) & LABEL_AT_LEFT) {
	    p.x = GD_bb(g).LL.x + d.x / 2;
#ifdef OLD
	    maxx = p.x + d.x / 2;
	    if (GD_bb(g).UR.x < maxx)
		GD_bb(g).UR.x = maxx;
	    if (GD_bb(g->root).UR.x < maxx)
		GD_bb(g->root).UR.x = maxx;
#endif
	} else {
	    p.x = (GD_bb(g).LL.x + GD_bb(g).UR.x) / 2;
#ifdef OLD
	    maxx = p.x + d.x / 2;
	    minx = p.x - d.x / 2;
	    if (GD_bb(g).UR.x < maxx)
		GD_bb(g).UR.x = maxx;
	    if (GD_bb(g).LL.x > minx)
		GD_bb(g).LL.x = minx;
	    if (GD_bb(g->root).UR.x < maxx)
		GD_bb(g->root).UR.x = maxx;
	    if (GD_bb(g->root).LL.x > minx)
		GD_bb(g->root).LL.x = minx;
#endif
	}
	GD_label(g)->p = p;
	GD_label(g)->set = TRUE;
    }

    for (c = 1; c <= GD_n_cluster(g); c++)
	place_graph_label(GD_clust(g)[c]);
}
示例#7
0
void mark_lowclusters(Agraph_t * root)
{
    Agnode_t *n, *vn;
    Agedge_t *orig, *e;

    /* first, zap any previous cluster labelings */
    for (n = agfstnode(root); n; n = agnxtnode(root, n)) {
	ND_clust(n) = NULL;
	for (orig = agfstout(root, n); orig; orig = agnxtout(root, orig)) {
	    if ((e = ED_to_virt(orig))) {
#ifndef WITH_CGRAPH
		while (e && (vn = e->head)->u.node_type == VIRTUAL) {
#else /* WITH_CGRAPH */
		while (e && (ND_node_type(vn = aghead(e))) == VIRTUAL) {
#endif /* WITH_CGRAPH */
		    ND_clust(vn) = NULL;
		    e = ND_out(aghead(e)).list[0];
		}
	    }
	}
    }

    /* do the recursion */
    mark_lowcluster_basic(root);
}

static void mark_lowcluster_basic(Agraph_t * g)
{
    Agraph_t *clust;
    Agnode_t *n, *vn;
    Agedge_t *orig, *e;
    int c;

    for (c = 1; c <= GD_n_cluster(g); c++) {
	clust = GD_clust(g)[c];
	mark_lowcluster_basic(clust);
    }
    /* see what belongs to this graph that wasn't already marked */
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (ND_clust(n) == NULL)
	    ND_clust(n) = g;
	for (orig = agfstout(g, n); orig; orig = agnxtout(g, orig)) {
	    if ((e = ED_to_virt(orig))) {
#ifndef WITH_CGRAPH
		while (e && (vn = e->head)->u.node_type == VIRTUAL) {
#else /* WITH_CGRAPH */
		while (e && (ND_node_type(vn = aghead(e))) == VIRTUAL) {
#endif /* WITH_CGRAPH */
		    if (ND_clust(vn) == NULL)
			ND_clust(vn) = g;
		    e = ND_out(aghead(e)).list[0];
		}
	    }
	}
    }
}
示例#8
0
static int
countClusterLabels (Agraph_t* g)
{
    int c, i = 0;
    if ((g != agroot(g)) && (GD_label(g)) && GD_label(g)->set)
	i++;
    for (c = 1; c <= GD_n_cluster(g); c++)
	i += countClusterLabels (GD_clust(g)[c]);
    return i;
}
示例#9
0
文件: rank.c 项目: jeci-sarl/graphviz
static void 
set_minmax(graph_t * g)
{
    int c;

    GD_minrank(g) += ND_rank(GD_leader(g));
    GD_maxrank(g) += ND_rank(GD_leader(g));
    for (c = 1; c <= GD_n_cluster(g); c++)
	set_minmax(GD_clust(g)[c]);
}
示例#10
0
文件: conc.c 项目: Chaduke/bah.mod
static void rebuild_vlists(graph_t * g)
{
    int c, i, r, maxi;
    node_t *n, *lead;
    edge_t *e, *rep;

    for (r = GD_minrank(g); r <= GD_maxrank(g); r++)
	GD_rankleader(g)[r] = NULL;

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	infuse(g, n);
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
	    for (rep = e; ED_to_virt(rep); rep = ED_to_virt(rep));
	    while (ND_rank(rep->head) < ND_rank(e->head)) {
		infuse(g, rep->head);
		rep = ND_out(rep->head).list[0];
	    }
	}
    }

    for (r = GD_minrank(g); r <= GD_maxrank(g); r++) {
	lead = GD_rankleader(g)[r];
	if (ND_rank(g->root)[r].v[ND_order(lead)] != lead)
	    abort();
	GD_rank(g)[r].v =
	    ND_rank(g->root)[r].v + GD_rankleader(g)[r]->u.order;
	maxi = -1;
	for (i = 0; i < GD_rank(g)[r].n; i++) {
	    if ((n = GD_rank(g)[r].v[i]) == NULL)
		break;
	    if (ND_node_type(n) == NORMAL) {
		if (agcontains(g, n))
		    maxi = i;
		else
		    break;
	    } else {
		edge_t *e;
		for (e = ND_in(n).list[0]; e && ED_to_orig(e);
		     e = ED_to_orig(e));
		if (e && (agcontains(g, e->tail))
		    && agcontains(g, e->head))
		    maxi = i;
	    }
	}
	if (maxi == -1)
	    agerr(AGWARN, "degenerate concentrated rank %s,%d\n", g->name,
		  r);
	GD_rank(g)[r].n = maxi + 1;
    }

    for (c = 1; c <= GD_n_cluster(g); c++)
	rebuild_vlists(GD_clust(g)[c]);
}
示例#11
0
static void 
dot_cleanup_graph(graph_t * g)
{
    int i;
    graph_t *subg;
    for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
	dot_cleanup_graph(subg);
    }
    if (GD_clust(g)) free (GD_clust(g));
    if (GD_rankleader(g)) free (GD_rankleader(g));

    free_list(GD_comp(g));
    if (GD_rank(g)) {
	for (i = GD_minrank(g); i <= GD_maxrank(g); i++)
	    free(GD_rank(g)[i].av);
	if (GD_minrank(g) == -1)
	    free(GD_rank(g)-1);
	else
	    free(GD_rank(g));
    }
    if (g != agroot(g)) 
	agdelrec(g,"Agraphinfo_t");
}
示例#12
0
static cinfo_t
addClusterObj (Agraph_t* g, cinfo_t info)
{
    int c;

    for (c = 1; c <= GD_n_cluster(g); c++)
	info = addClusterObj (GD_clust(g)[c], info);
    if ((g != agroot(g)) && (GD_label(g)) && GD_label(g)->set) {
	object_t* objp = info.objp;
	info.bb = addLabelObj (GD_label(g), objp, info.bb);
	info.objp++;
    }

    return info;
}
示例#13
0
文件: output.c 项目: Chaduke/bah.mod
static void rec_attach_bb(graph_t * g)
{
    int c;
    char buf[BUFSIZ];
    point pt;

    sprintf(buf, "%d,%d,%d,%d", GD_bb(g).LL.x, GD_bb(g).LL.y,
	    GD_bb(g).UR.x, GD_bb(g).UR.y);
    agset(g, "bb", buf);
    if (GD_label(g) && GD_label(g)->text[0]) {
	pt = GD_label(g)->p;
	sprintf(buf, "%d,%d", pt.x, YDIR(pt.y));
	agset(g, "lp", buf);
    }
    for (c = 1; c <= GD_n_cluster(g); c++)
	rec_attach_bb(GD_clust(g)[c]);
}
示例#14
0
文件: conc.c 项目: Chaduke/bah.mod
void dot_concentrate(graph_t * g)
{
    int c, r, leftpos, rightpos;
    node_t *left, *right;

    if (GD_maxrank(g) - GD_minrank(g) <= 1)
	return;
    /* this is the downward looking pass. r is a candidate rank. */
    for (r = 1; GD_rank(g)[r + 1].n; r++) {
	for (leftpos = 0; leftpos < GD_rank(g)[r].n; leftpos++) {
	    left = GD_rank(g)[r].v[leftpos];
	    if (downcandidate(left) == FALSE)
		continue;
	    for (rightpos = leftpos + 1; rightpos < GD_rank(g)[r].n;
		 rightpos++) {
		right = GD_rank(g)[r].v[rightpos];
		if (bothdowncandidates(left, right) == FALSE)
		    break;
	    }
	    if (rightpos - leftpos > 1)
		mergevirtual(g, r, leftpos, rightpos - 1, DOWN);
	}
    }
    /* this is the corresponding upward pass */
    while (r > 0) {
	for (leftpos = 0; leftpos < GD_rank(g)[r].n; leftpos++) {
	    left = GD_rank(g)[r].v[leftpos];
	    if (upcandidate(left) == FALSE)
		continue;
	    for (rightpos = leftpos + 1; rightpos < GD_rank(g)[r].n;
		 rightpos++) {
		right = GD_rank(g)[r].v[rightpos];
		if (bothupcandidates(left, right) == FALSE)
		    break;
	    }
	    if (rightpos - leftpos > 1)
		mergevirtual(g, r, leftpos, rightpos - 1, UP);
	}
	r--;
    }
    for (c = 1; c <= GD_n_cluster(g); c++)
	rebuild_vlists(GD_clust(g)[c]);
}
示例#15
0
void translate_bb(graph_t * g, int rankdir)
{
    int c;
    boxf bb, new_bb;

    bb = GD_bb(g);
    if (rankdir == RANKDIR_LR || rankdir == RANKDIR_BT) {
	new_bb.LL = map_point(pointfof(bb.LL.x, bb.UR.y));
	new_bb.UR = map_point(pointfof(bb.UR.x, bb.LL.y));
    } else {
	new_bb.LL = map_point(pointfof(bb.LL.x, bb.LL.y));
	new_bb.UR = map_point(pointfof(bb.UR.x, bb.UR.y));
    }
    GD_bb(g) = new_bb;
    if (GD_label(g)) {
	GD_label(g)->pos = map_point(GD_label(g)->pos);
    }
    for (c = 1; c <= GD_n_cluster(g); c++)
	translate_bb(GD_clust(g)[c], rankdir);
}
示例#16
0
static void 
dot_cleanup_graph(graph_t * g)
{
    int i, c;
    graph_t *clust;

    for (c = 1; c <= GD_n_cluster(g); c++) {
	clust = GD_clust(g)[c];
	GD_cluster_was_collapsed(clust) = FALSE;
	dot_cleanup(clust);
    }

    free_list(GD_comp(g));
    if ((g == g->root) && GD_rank(g)) {
	for (i = GD_minrank(g); i <= GD_maxrank(g); i++)
	    free(GD_rank(g)[i].v);
	free(GD_rank(g));
    }
    if (g != g->root) memset(&(g->u), 0, sizeof(Agraphinfo_t));
}
示例#17
0
文件: dbg.c 项目: ekoontz/graphviz
static void dumpSG(graph_t * g)
{
    graph_t *subg;
    int i;

    if (GD_n_cluster(g) == 0)
	return;
    prIndent();
    fprintf(stderr, "  {\n");
    for (i = 1; i <= GD_n_cluster(g); i++) {
	subg = (GD_clust(g))[i];
	prIndent();
	fprintf(stderr, "  subgraph %s : %d nodes\n", subg->name,
		agnnodes(subg));
	dumpBB(subg);
	incInd ();
	dumpSG(subg);
	decInd ();
    }
    prIndent();
    fprintf(stderr, "  }\n");
}
示例#18
0
static void rec_attach_bb(graph_t * g, Agsym_t* bbsym)
{
    int c;
    char buf[BUFSIZ];
    pointf pt;

    sprintf(buf, "%.5g,%.5g,%.5g,%.5g", GD_bb(g).LL.x, YDIR(GD_bb(g).LL.y),
	    GD_bb(g).UR.x, YDIR(GD_bb(g).UR.y));
    agxset(g, bbsym, buf);
    if (GD_label(g) && GD_label(g)->text[0]) {
	pt = GD_label(g)->pos;
	sprintf(buf, "%.5g,%.5g", pt.x, YDIR(pt.y));
	agset(g, "lp", buf);
	pt = GD_label(g)->dimen;
	sprintf(buf, "%.2f", PS2INCH(pt.x));
	agset (g, "lwidth", buf);
	sprintf(buf, "%.2f", PS2INCH(pt.y));
	agset (g, "lheight", buf);
    }
    for (c = 1; c <= GD_n_cluster(g); c++)
	rec_attach_bb(GD_clust(g)[c], bbsym);
}
示例#19
0
/* compute_bb:
 * Compute bounding box of g using nodes, splines, and clusters.
 * Assumes bb of clusters already computed.
 * store in GD_bb.
 */
void compute_bb(graph_t * g)
{
    node_t *n;
    edge_t *e;
    box b, bb;
    point pt, s2;
    int i, j;

    bb.LL = pointof(MAXINT, MAXINT);
    bb.UR = pointof(-MAXINT, -MAXINT);
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	pt = coord(n);
	s2.x = ND_xsize(n) / 2 + 1;
	s2.y = ND_ysize(n) / 2 + 1;
	b.LL = sub_points(pt, s2);
	b.UR = add_points(pt, s2);

	EXPANDBB(bb,b);
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
	    if (ED_spl(e) == 0)
		continue;
	    for (i = 0; i < ED_spl(e)->size; i++) {
		for (j = 0; j < ED_spl(e)->list[i].size; j++) {
		    pt = ED_spl(e)->list[i].list[j];
		    EXPANDBP(bb,pt);
		}
	    }
	    if (ED_label(e) && ED_label(e)->set)
		bb = addLabelBB(bb, ED_label(e), GD_flip(g));
	}
    }

    for (i = 1; i <= GD_n_cluster(g); i++) {
	EXPANDBB(bb,GD_clust(g)[i]->u.bb);
    }

    GD_bb(g) = bb;
}
示例#20
0
文件: rank.c 项目: jeci-sarl/graphviz
/* 
 * Assigns ranks of non-leader nodes.
 * Expands same, min, max rank sets.
 * Leaf sets and clusters remain merged.
 * Sets minrank and maxrank appropriately.
 */
static void expand_ranksets(graph_t * g, aspect_t* asp)
{
    int c;
    node_t *n, *leader;

    if ((n = agfstnode(g))) {
	GD_minrank(g) = MAXSHORT;
	GD_maxrank(g) = -1;
	while (n) {
	    leader = UF_find(n);
	    /* The following works because ND_rank(n) == 0 if n is not in a
	     * cluster, and ND_rank(n) = the local rank offset if n is in
	     * a cluster. */
	    if ((leader != n) && (!asp || (ND_rank(n) == 0)))
		ND_rank(n) += ND_rank(leader);

	    if (GD_maxrank(g) < ND_rank(n))
		GD_maxrank(g) = ND_rank(n);
	    if (GD_minrank(g) > ND_rank(n))
		GD_minrank(g) = ND_rank(n);

	    if (ND_ranktype(n) && (ND_ranktype(n) != LEAFSET))
		UF_singleton(n);
	    n = agnxtnode(g, n);
	}
	if (g == dot_root(g)) {
	    if (CL_type == LOCAL) {
		for (c = 1; c <= GD_n_cluster(g); c++)
		    set_minmax(GD_clust(g)[c]);
	    } else {
		find_clusters(g);
	    }
	}
    } else {
	GD_minrank(g) = GD_maxrank(g) = 0;
    }
}
示例#21
0
/* compute_bb:
 * Compute bounding box of g using nodes, splines, and clusters.
 * Assumes bb of clusters already computed.
 * store in GD_bb.
 */
void compute_bb(graph_t * g)
{
    node_t *n;
    edge_t *e;
    boxf b, bb;
    boxf BF;
    pointf ptf, s2;
    int i, j;

    if ((agnnodes(g) == 0) && (GD_n_cluster(g) ==0)) {
	bb.LL = pointfof(0, 0);
	bb.UR = pointfof(0, 0);
	return;
    }

    bb.LL = pointfof(INT_MAX, INT_MAX);
    bb.UR = pointfof(-INT_MAX, -INT_MAX);
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	ptf = coord(n);
	s2.x = ND_xsize(n) / 2.0;
	s2.y = ND_ysize(n) / 2.0;
	b.LL = sub_pointf(ptf, s2);
	b.UR = add_pointf(ptf, s2);

	EXPANDBB(bb,b);
	if (ND_xlabel(n) && ND_xlabel(n)->set) {
	    bb = addLabelBB(bb, ND_xlabel(n), GD_flip(g));
	}
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
	    if (ED_spl(e) == 0)
		continue;
	    for (i = 0; i < ED_spl(e)->size; i++) {
		for (j = 0; j < (((Agedgeinfo_t*)AGDATA(e))->spl)->list[i].size; j++) {
		    ptf = ED_spl(e)->list[i].list[j];
		    EXPANDBP(bb,ptf);
		}
	    }
	    if (ED_label(e) && ED_label(e)->set) {
		bb = addLabelBB(bb, ED_label(e), GD_flip(g));
	    }
	    if (ED_head_label(e) && ED_head_label(e)->set) {
		bb = addLabelBB(bb, ED_head_label(e), GD_flip(g));
	    }
	    if (ED_tail_label(e) && ED_tail_label(e)->set) {
		bb = addLabelBB(bb, ED_tail_label(e), GD_flip(g));
	    }
	    if (ED_xlabel(e) && ED_xlabel(e)->set) {
		bb = addLabelBB(bb, ED_xlabel(e), GD_flip(g));
	    }
	}
    }

    for (i = 1; i <= GD_n_cluster(g); i++) {
	B2BF(GD_bb(GD_clust(g)[i]), BF);
	EXPANDBB(bb,BF);
    }
    if (GD_label(g) && GD_label(g)->set) {
	bb = addLabelBB(bb, GD_label(g), GD_flip(g));
    }

    GD_bb(g) = bb;
}
示例#22
0
/* this function marks every node in <g> with its top-level cluster under <g> */
void mark_clusters(graph_t * g)
{
    int c;
    node_t *n, *nn, *vn;
    edge_t *orig, *e;
    graph_t *clust;

    /* remove sub-clusters below this level */
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (ND_ranktype(n) == CLUSTER)
	    UF_singleton(n);
	ND_clust(n) = NULL;
    }

    for (c = 1; c <= GD_n_cluster(g); c++) {
	clust = GD_clust(g)[c];
	for (n = agfstnode(clust); n; n = nn) {
		nn = agnxtnode(clust,n);
	    if (ND_ranktype(n) != NORMAL) {
		agerr(AGWARN,
		      "%s was already in a rankset, deleted from cluster %s\n",
		      agnameof(n), agnameof(g));
		agdelete(clust,n);
		continue;
	    }
	    UF_setname(n, GD_leader(clust));
	    ND_clust(n) = clust;
	    ND_ranktype(n) = CLUSTER;

	    /* here we mark the vnodes of edges in the cluster */
	    for (orig = agfstout(clust, n); orig;
		 orig = agnxtout(clust, orig)) {
		if ((e = ED_to_virt(orig))) {
#ifndef WITH_CGRAPH
		    while (e && (vn = e->head)->u.node_type == VIRTUAL) {
#else /* WITH_CGRAPH */
		    while (e && ND_node_type(vn =aghead(e)) == VIRTUAL) {
#endif /* WITH_CGRAPH */
			ND_clust(vn) = clust;
			e = ND_out(aghead(e)).list[0];
			/* trouble if concentrators and clusters are mixed */
		    }
		}
	    }
	}
    }
}

void build_skeleton(graph_t * g, graph_t * subg)
{
    int r;
    node_t *v, *prev, *rl;
    edge_t *e;

    prev = NULL;
    GD_rankleader(subg) = N_NEW(GD_maxrank(subg) + 2, node_t *);
    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
	v = GD_rankleader(subg)[r] = virtual_node(g);
	ND_rank(v) = r;
	ND_ranktype(v) = CLUSTER;
	ND_clust(v) = subg;
	if (prev) {
	    e = virtual_edge(prev, v, NULL);
	    ED_xpenalty(e) *= CL_CROSS;
	}
	prev = v;
    }

    /* set the counts on virtual edges of the cluster skeleton */
    for (v = agfstnode(subg); v; v = agnxtnode(subg, v)) {
	rl = GD_rankleader(subg)[ND_rank(v)];
	ND_UF_size(rl)++;
	for (e = agfstout(subg, v); e; e = agnxtout(subg, e)) {
	    for (r = ND_rank(agtail(e)); r < ND_rank(aghead(e)); r++) {
		ED_count(ND_out(rl).list[0])++;
	    }
	}
    }
    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
	rl = GD_rankleader(subg)[r];
	if (ND_UF_size(rl) > 1)
	    ND_UF_size(rl)--;
    }
}
示例#23
0
文件: rank.c 项目: emdenrg/graphviz
/* Execute union commands for "same rank" subgraphs and clusters. */
static void 
collapse_sets(graph_t *rg, graph_t *g)
{
    int c;
    graph_t  *subg;
#ifdef OBSOLETE
    node_t *n;
#endif

#ifndef WITH_CGRAPH
    graph_t *mg;
    node_t *mn;
    edge_t *me;
    mg = g->meta_node->graph;
    for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) {
	mn = aghead(me);
	subg = agusergraph(mn);
#else /* WITH_CGRAPH */
    for (subg = agfstsubg(g); subg; subg = agnxtsubg(subg)) {
#endif /* WITH_CGRAPH */
	c = rank_set_class(subg);
	if (c) {
	    if ((c == CLUSTER) && CL_type == LOCAL)
		collapse_cluster(rg, subg);
	    else
		collapse_rankset(rg, subg, c);
	}
	else collapse_sets(rg, subg);

#ifdef OBSOLETE
 Collapsing leaves is currently obsolete

	/* mark nodes with ordered edges so their leaves are not collapsed */
	if (agget(subg, "ordering"))
	    for (n = agfstnode(subg); n; n = agnxtnode(subg, n))
		ND_order(n) = 1;
#endif
    }
}

static void 
find_clusters(graph_t * g)
{
    graph_t *subg;
#ifndef WITH_CGRAPH
    graph_t *mg;
    node_t *mn;
    edge_t *me;

    mg = g->meta_node->graph;
    for (me = agfstout(mg, g->meta_node); me; me = agnxtout(mg, me)) {
	mn = me->head;
	subg = agusergraph(mn);
#else /* WITH_CGRAPH */
    for (subg = agfstsubg(agroot(g)); subg; subg = agnxtsubg(subg)) {
#endif /* WITH_CGRAPH */
	if (GD_set_type(subg) == CLUSTER)
	    collapse_cluster(g, subg);
    }
}

static void 
set_minmax(graph_t * g)
{
    int c;

    GD_minrank(g) += ND_rank(GD_leader(g));
    GD_maxrank(g) += ND_rank(GD_leader(g));
    for (c = 1; c <= GD_n_cluster(g); c++)
	set_minmax(GD_clust(g)[c]);
}
示例#24
0
/* place_flip_graph_label:
 * Put cluster labels recursively in the flip case.
 */
static void place_flip_graph_label(graph_t * g)
{
    int c;
    point p, d;
#ifdef OLD
    int maxx, minx;
    int maxy, miny;
    pointf dimen;
#endif

    if ((g != g->root) && (GD_label(g)) && !GD_label(g)->set) {

	if (GD_label_pos(g) & LABEL_AT_TOP) {
	    d = GD_border(g)[RIGHT_IX];
	    p.x = GD_bb(g).UR.x - d.x / 2;
#ifdef OLD
	    maxx = GD_bb(g).UR.x + d.y;
	    GD_bb(g).UR.x = maxx;
	    if (GD_bb(g->root).UR.x < maxx)
		GD_bb(g->root).UR.x = maxx;
#endif
	} else {
	    d = GD_border(g)[LEFT_IX];
	    p.x = GD_bb(g).LL.x + d.x / 2;
#ifdef OLD
	    minx = GD_bb(g).LL.x - d.y;
	    GD_bb(g).LL.x = minx;
	    if (GD_bb(g->root).LL.x > minx)
		GD_bb(g->root).LL.x = minx;
#endif
	}

	if (GD_label_pos(g) & LABEL_AT_RIGHT) {
	    p.y = GD_bb(g).LL.y + d.y / 2;
#ifdef OLD
	    maxy = p.y + d.x / 2;
	    if (GD_bb(g->root).UR.y < maxy)
		GD_bb(g->root).UR.y = maxy;
#endif
	} else if (GD_label_pos(g) & LABEL_AT_LEFT) {
	    p.y = GD_bb(g).UR.y - d.y / 2;
#ifdef OLD
	    miny = p.y - d.x / 2;
	    if (GD_bb(g->root).LL.y > miny)
		GD_bb(g->root).LL.y = miny;
#endif
	} else {
	    p.y = (GD_bb(g).LL.y + GD_bb(g).UR.y) / 2;
#ifdef OLD
	    maxy = p.y + d.x / 2;
	    miny = p.y - d.x / 2;
#endif
	}

	GD_label(g)->p = p;
	GD_label(g)->set = TRUE;
    }

    for (c = 1; c <= GD_n_cluster(g); c++)
	place_flip_graph_label(GD_clust(g)[c]);
}