示例#1
0
文件: blockpath.c 项目: aosm/graphviz
/* clone_graph:
 * Create two copies of the argument graph
 * One is a subgraph, the other is an actual copy since we will be
 * adding edges to it.
 */
static Agraph_t*
clone_graph(Agraph_t* ing, Agraph_t** xg)
{
	Agraph_t*  clone;
	Agraph_t*  xclone;
	Agnode_t*  n;
	Agnode_t*  xn;
	Agnode_t*  xh;
	Agedge_t*  e;
	Agedge_t*  xe;
	char       gname[SMALLBUF];
	static int id = 0;

	sprintf (gname, "_clone_%d", id++);
	clone = agsubg(ing, gname);
	sprintf (gname, "_clone_%d", id++);
	xclone = agopen(gname, ing->kind);

	for(n = agfstnode(ing); n; n = agnxtnode(ing, n)) {
		aginsert (clone, n);
		xn = agnode (xclone, n->name);
		CLONE(n) = xn;
	}

	for(n = agfstnode(ing); n; n = agnxtnode(ing, n)) {
		xn = CLONE(n);
		for(e = agfstout(ing, n); e; e = agnxtout(ing, e)) {
			aginsert (clone, e);
			xh = CLONE(e->head); 
			xe = agedge (xclone, xn, xh);
			ORIGE(xe) = e;
			DEGREE(xn) += 1;
			DEGREE(xh) += 1;
		}
	}
	*xg = xclone;
#ifdef OLD
	clone = agopen("clone", root->kind);

	for(n = agfstnode(root); n; n = agnxtnode(root, n)) {
		cn = agnode(clone, n->name);		
		ND_alg(cn) = DATA(n);
		BCDONE(cn) = 0;
	}

	for(n = agfstnode(root); n; n = agnxtnode(root, n)) {
		Agnode_t *t = agnode(clone, n);
		for(e = agfstout(root, n); e; e = agnxtout(root, e)) {
			Agnode_t *h = agnode(clone, e->head->name);
			agedge(clone, t, h);
		}
	}
#endif
	return clone;
}
示例#2
0
/* dfs:
 *
 * Current scheme adds articulation point to first non-trivial child
 * block. If none exists, it will be added to its parent's block, if
 * non-trivial, or else given its own block.
 *
 * FIX:
 * This should be modified to:
 *  - allow user to specify which block gets a node, perhaps on per-node basis.
 *  - if an articulation point is not used in one of its non-trivial blocks,
 *    dummy edges should be added to preserve biconnectivity
 *  - turn on user-supplied blocks.
 *
 */
static void dfs(Agraph_t * g, Agnode_t * n, circ_state * state, int isRoot)
{
    Agedge_t *e;
    Agnode_t *curtop;

    LOWVAL(n) = VAL(n) = state->orderCount++;

    stackPush(state->bcstack, n);

    for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
	Agnode_t *neighbor = e->head;
	if (neighbor == n)
	    neighbor = e->tail;

	if (neighbor == PARENT(n))
	    continue;

	if (VAL(neighbor)) {
	    LOWVAL(n) = min_value(LOWVAL(n), VAL(neighbor));
	    continue;
	}
	if (!stackCheck(state->bcstack, n)) {
	    stackPush(state->bcstack, n);
	}

	PARENT(neighbor) = n;
	curtop = top(state->bcstack);
	dfs(g, neighbor, state, 0);

	LOWVAL(n) = min_value(LOWVAL(n), LOWVAL(neighbor));
	if (LOWVAL(neighbor) >= VAL(n)) {
	    block_t *block = NULL;
	    Agnode_t *np;
	    if (top(state->bcstack) != curtop)
		do {
		    np = stackPop(state->bcstack);
		    if (!BCDONE(np)) {
			if (!block)
			    block = makeBlock(g, state);
			addNode(block, np);
		    }
		} while (np != n);
	    if (block) {	/* If block != NULL, it's not empty */
		if (isRoot && (BLOCK(n) == block))
		    insertBlock(&state->bl, block);
		else
		    appendBlock(&state->bl, block);
	    }
	    if ((LOWVAL(n) < VAL(n)) && (!stackCheck(state->bcstack, n))) {
		stackPush(state->bcstack, n);
	    }
	}
    }
    if ((LOWVAL(n) == VAL(n)) && !BCDONE(n)) {
	block_t *block = makeBlock(g, state);
	stackPop(state->bcstack);
	addNode(block, n);
	if (isRoot)
	    insertBlock(&state->bl, block);
	else
	    appendBlock(&state->bl, block);
    }
}
示例#3
0
/* find_blocks:
 */
static void find_blocks(Agraph_t * g, circ_state * state)
{
    Agnode_t *n;
    Agnode_t *root = NULL;
    block_t *rootBlock = NULL;
    blocklist_t ublks;
#ifdef USER_BLOCKS
    graph_t *clust_subg;
    graph_t *mg;
    edge_t *me;
    node_t *mm;
    int isRoot;
#endif

    initBlocklist(&ublks);

    /*      check to see if there is a node which is set to be the root
     */
    if (state->rootname) {
	root = agfindnode(g, state->rootname);
    }
    if (!root && state->N_root) {
	for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	    if (late_bool(ORIGN(n), state->N_root, 0)) {
		root = n;
		break;
	    }
	}
    }
#ifdef USER_BLOCKS
    /* process clusters first */
    /* by construction, all subgraphs are blocks and are non-empty */
    mm = g->meta_node;
    mg = mm->graph;
    for (me = agfstout(mg, mm); me; me = agnxtout(mg, me)) {
	block_t *block;

	clust_subg = agusergraph(me->head);

	isRoot = 0;
	block = mkBlock(clust_subg);
	/* block = makeBlock(g, state); */
	for (n = agfstnode(clust_subg); n; n = agnxtnode(clust_subg, n)) {
	    if (!BCDONE(n)) {	/* test not necessary if blocks disjoint */
		SET_BCDONE(n);
		BLOCK(n) = block;
		if (n == root)
		    isRoot = 1;
	    }
	}
	if (isRoot) {
	    /* Assume blocks are disjoint, so don't check if rootBlock is
	     * already assigned.
	     */
	    rootBlock = block;
	    insertBlock(&state->bl, block);
	} else {
	    appendBlock(&state->bl, block);
	}
    }
    ublks.first = state->bl.first;
    ublks.last = state->bl.last;
#endif

    if (!root)
	root = agfstnode(g);
    dfs(g, root, state, !rootBlock);

#ifdef USER_BLOCKS
    /* If g has user-supplied blocks, it may be disconnected.
     * We then fall into the following ugly loop.
     * We are guaranteed !VISITED(n) and PARENT(n) has been
     * set to a visited node.
     */
    if (ublks.first) {
	while (n = findUnvisited(&ublks)) {
	    dfs(g, n, state, 0);
	}
    }
#endif
}