コード例 #1
0
ファイル: rank.c プロジェクト: aosm/graphviz
/* Merge the nodes of a min, max, or same rank set. */
void collapse_rankset(graph_t *g, graph_t *subg, int kind)
{
	node_t	*u,*v;

	u = v = agfstnode(subg);
	if (u) {
		ND_ranktype(u) = kind;
		while ((v = agnxtnode(subg,v))) {
			UF_union(u,v);
			ND_ranktype(v) = ND_ranktype(u);
		}
		switch (kind) {
		case MINRANK: case SOURCERANK:
			if (GD_minset(g) == NULL) GD_minset(g) = u;
			else GD_minset(g) = UF_union(GD_minset(g),u);
			break;
		case MAXRANK: case SINKRANK:
			if (GD_maxset(g) == NULL) GD_maxset(g) = u;
			else GD_maxset(g) = UF_union(GD_maxset(g),u);
			break;
		}
		switch (kind) {
			case SOURCERANK: GD_minset(g)->u.ranktype = kind; break;
			case SINKRANK: GD_maxset(g)->u.ranktype = kind; break;
		}
	}
}
コード例 #2
0
ファイル: rank.c プロジェクト: jeci-sarl/graphviz
/* To ensure that min and max rank nodes always have the intended rank
 * assignment, reverse any incompatible edges.
 */
static point 
minmax_edges(graph_t * g)
{
    node_t *n;
    edge_t *e;
    point  slen;

    slen.x = slen.y = 0;
    if ((GD_maxset(g) == NULL) && (GD_minset(g) == NULL))
	return slen;
    if (GD_minset(g) != NULL)
	GD_minset(g) = UF_find(GD_minset(g));
    if (GD_maxset(g) != NULL)
	GD_maxset(g) = UF_find(GD_maxset(g));

    if ((n = GD_maxset(g))) {
	slen.y = (ND_ranktype(GD_maxset(g)) == SINKRANK);
	while ((e = ND_out(n).list[0])) {
	    assert(aghead(e) == UF_find(aghead(e)));
	    reverse_edge(e);
	}
    }
    if ((n = GD_minset(g))) {
	slen.x = (ND_ranktype(GD_minset(g)) == SOURCERANK);
	while ((e = ND_in(n).list[0])) {
	    assert(agtail(e) == UF_find(agtail(e)));
	    reverse_edge(e);
	}
    }
    return slen;
}
コード例 #3
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);
	}
    }
}
コード例 #4
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;
    }
}
コード例 #5
0
ファイル: rank.c プロジェクト: jeci-sarl/graphviz
static void
cluster_leader(graph_t * clust)
{
    node_t *leader, *n;
    int maxrank = 0;

    /* find number of ranks and select a leader */
    leader = NULL;
    for (n = GD_nlist(clust); n; n = ND_next(n)) {
	if ((ND_rank(n) == 0) && (ND_node_type(n) == NORMAL))
	    leader = n;
	if (maxrank < ND_rank(n))
	    maxrank = ND_rank(n);
    }
    assert(leader != NULL);
    GD_leader(clust) = leader;

    for (n = agfstnode(clust); n; n = agnxtnode(clust, n)) {
	assert((ND_UF_size(n) <= 1) || (n == leader));
	UF_union(n, leader);
	ND_ranktype(n) = CLUSTER;
    }
}
コード例 #6
0
ファイル: cluster.c プロジェクト: emdenrg/graphviz
/* 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)--;
    }
}
コード例 #7
0
ファイル: utils.c プロジェクト: Goettsch/game-editor
void UF_singleton(node_t * u)
{
    ND_UF_size(u) = 1;
    ND_UF_parent(u) = NULL;
    ND_ranktype(u) = NORMAL;
}