示例#1
0
static void 
remove_rankleaders(graph_t * g)
{
    int r;
    node_t *v;
    edge_t *e;

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

	/* remove the entire chain */
	while ((e = ND_out(v).list[0]))
	    delete_fast_edge(e);
	while ((e = ND_in(v).list[0]))
	    delete_fast_edge(e);
	delete_fast_node(agroot(g), v);
	GD_rankleader(g)[r] = NULL;
    }
}
示例#2
0
文件: rank.c 项目: CharlieSa/livizjs
static void 
cleanup1(graph_t * g)
{
    node_t *n;
    edge_t *e, *f;
    int c;

    for (c = 0; c < GD_comp(g).size; c++) {
	GD_nlist(g) = GD_comp(g).list[c];
	for (n = GD_nlist(g); n; n = ND_next(n)) {
	    renewlist(&ND_in(n));
	    renewlist(&ND_out(n));
	    ND_mark(n) = FALSE;
	}
    }
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
	    f = ED_to_virt(e);
	    /* Null out any other references to f to make sure we don't 
	     * handle it a second time. For example, parallel multiedges 
	     * share a virtual edge.
	     */
	    if (f && (e == ED_to_orig(f))) {
		edge_t *e1, *f1;
		for (e1 = agfstout(g, n); e1; e1 = agnxtout(g, e1)) {
		    if (e != e1) {
			f1 = ED_to_virt(e1);
			if (f1 && (f == f1)) {
			    ED_to_virt(e1) = NULL;
			}
		    }
		}
		free(f);
	    }
	    ED_to_virt(e) = NULL;
	}
    }
    free(GD_comp(g).list);
    GD_comp(g).list = NULL;
    GD_comp(g).size = 0;
}
示例#3
0
static void checkChain(graph_t * g)
{
    node_t *t;
    node_t *h;
    edge_t *e;
    t = GD_nlist(g);
    for (h = ND_next(t); h; h = ND_next(h)) {
	if (!agfindedge(g, t, h)) {
#ifdef WITH_CGRAPH
            e = agedge(g, t, h, NULL, 1);
	    agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE);
#else
	    e = agedge(g, t, h);
#endif
	    ED_minlen(e) = 0;
	    elist_append(e, ND_out(t));
	    elist_append(e, ND_in(h));
	}
	t = h;
    }
}
示例#4
0
文件: rank.c 项目: CharlieSa/livizjs
static int 
minmax_edges2(graph_t * g, point slen)
{
    node_t *n;
    edge_t *e = 0;

    if ((GD_maxset(g)) || (GD_minset(g))) {
	for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	    if (n != UF_find(n))
		continue;
	    if ((ND_out(n).size == 0) && GD_maxset(g) && (n != GD_maxset(g))) {
		e = virtual_edge(n, GD_maxset(g), NULL);
		ED_minlen(e) = slen.y;
	    }
	    if ((ND_in(n).size == 0) && GD_minset(g) && (n != GD_minset(g))) {
		e = virtual_edge(GD_minset(g), n, NULL);
		ED_minlen(e) = slen.x;
	    }
	}
    }
    return (e != 0);
}
示例#5
0
文件: conc.c 项目: Chaduke/bah.mod
static bool upcandidate(node_t * v)
{
    return ((ND_node_type(v) == VIRTUAL) && (ND_out(v).size == 1)
	    && (ND_in(v).size == 1) && (ND_label(v) == NULL));
}
示例#6
0
文件: fastgr.c 项目: Chaduke/bah.mod
edge_t *find_fast_edge(node_t * u, node_t * v)
{
    return ffe(u, ND_out(u), v, ND_in(v));
}
示例#7
0
文件: fastgr.c 项目: Chaduke/bah.mod
/* disconnects e from graph */
void delete_fast_edge(edge_t * e)
{
    assert(e != NULL);
    zapinlist(&(ND_out(e->tail)), e);
    zapinlist(&(ND_in(e->head)), e);
}
示例#8
0
/* makeGraphs:
 * Generate dags modeling the row and column constraints.
 * If the table has cc columns, we create the graph
 *  0 -> 1 -> 2 -> ... -> cc
 * and if a cell starts in column c with span cspan, with
 * width w, we add the edge c -> c+cspan [minlen = w].
 *
 * We might simplify the graph by removing multiedges,
 * using the max minlen, but will affect the balancing?
 */
void makeGraphs(htmltbl_t * tbl, graph_t * rowg, graph_t * colg)
{
    htmlcell_t *cp;
    htmlcell_t **cells;
    node_t *t;
    node_t *lastn;
    node_t *h;
    edge_t *e;
    int i;
    int* minc;
    int* minr;

    lastn = NULL;
    for (i = 0; i <= tbl->cc; i++) {
	t = agnode(colg, nToName(i));
	alloc_elist(tbl->rc, ND_in(t));
	alloc_elist(tbl->rc, ND_out(t));
	if (lastn) {
	    ND_next(lastn) = t;
	    lastn = t;
	} else {
	    lastn = GD_nlist(colg) = t;
	}
    }
    lastn = NULL;
    for (i = 0; i <= tbl->rc; i++) {
	t = agnode(rowg, nToName(i));
	alloc_elist(tbl->cc, ND_in(t));
	alloc_elist(tbl->cc, ND_out(t));
	if (lastn) {
	    ND_next(lastn) = t;
	    lastn = t;
	} else {
	    lastn = GD_nlist(rowg) = t;
	}
    }
    minr = N_NEW(tbl->rc, int);
    minc = N_NEW(tbl->cc, int);
    for (cells = tbl->u.n.cells; *cells; cells++) {
        int x, y, c, r;
	cp = *cells;
        x = (cp->data.box.UR.x + (cp->cspan-1))/cp->cspan;
        for (c = 0; c < cp->cspan; c++)
          minc[cp->col + c] = MAX(minc[cp->col + c],x);
        y = (cp->data.box.UR.y + (cp->rspan-1))/cp->rspan;
        for (r = 0; r < cp->rspan; r++)
          minr[cp->row + r] = MAX(minr[cp->row + r],y);
    }
    for (cells = tbl->u.n.cells; *cells; cells++) {
        int x, y, c, r;
	cp = *cells;
	t = agfindnode(colg, nToName(cp->col));
	h = agfindnode(colg, nToName(cp->col + cp->cspan));
	e = agedge(colg, t, h);
        x = 0;
        for (c = 0; c < cp->cspan; c++)
            x += minc[cp->col + c];
	ED_minlen(e) = x;
	/* ED_minlen(e) = cp->data.box.UR.x; */
#ifdef DEBUG
	fprintf(stderr, "col edge %s -> %s %d\n", t->name, h->name,
		ED_minlen(e));
#endif
	elist_append(e, ND_out(t));
	elist_append(e, ND_in(h));

	t = agfindnode(rowg, nToName(cp->row));
	h = agfindnode(rowg, nToName(cp->row + cp->rspan));
	e = agedge(rowg, t, h);
        y = 0;
        for (r = 0; r < cp->rspan; r++)
            y += minr[cp->row + r];
	ED_minlen(e) = y;
	/* ED_minlen(e) = cp->data.box.UR.y; */
#ifdef DEBUG
	fprintf(stderr, "row edge %s -> %s %d\n", t->name, h->name,
		ED_minlen(e));
#endif
	elist_append(e, ND_out(t));
	elist_append(e, ND_in(h));
    }

    /* Make sure that 0 <= 1 <= 2 ...k. This implies graph connected. */
    checkChain(colg);
    checkChain(rowg);

    free (minc);
    free (minr);
}
示例#9
0
/* mkConstraintG:
 */
static graph_t *mkConstraintG(graph_t * g, Dt_t * list,
			      intersectfn intersect, distfn dist)
{
    nitem *p;
    nitem *nxt = NULL;
    nitem *nxp;
    graph_t *vg;
    node_t *prev = NULL;
    node_t *root = NULL;
    node_t *n = NULL;
    edge_t *e;
    int lcnt, cnt;
    int oldval = -INT_MAX;
#ifdef OLD
    double root_val;
#endif
    node_t *lastn = NULL;
#ifndef WITH_CGRAPH
    graph_t *cg = agopen("cg", AGDIGRAPHSTRICT);
#else
    graph_t *cg = agopen("cg", Agstrictdirected, NIL(Agdisc_t *));
    agbindrec(cg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE);  // graph custom data
#endif

    /* count distinct nodes */
    cnt = 0;
    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
	if (oldval != p->val) {
	    oldval = p->val;
	    cnt++;
	}
    }

    /* construct basic chain to enforce left to right order */
    oldval = -INT_MAX;
    lcnt = 0;
    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
	if (oldval != p->val) {
	    oldval = p->val;
	    /* n = newNode (cg); */
#ifndef WITH_CGRAPH
	    n = agnode(cg, agnameof(p->np));	/* FIX */
#else
	    n = agnode(cg, agnameof(p->np), 1);	/* FIX */
	    agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data
#endif
	    ND_alg(n) = p;
	    if (root) {
		ND_next(lastn) = n;
		lastn = n;
	    } else {
		root = n;
#ifdef OLD
		root_val = p->val;
#endif
		lastn = GD_nlist(cg) = n;
	    }
	    alloc_elist(lcnt, ND_in(n));
	    if (prev) {
		if (prev == root)
		    alloc_elist(2 * (cnt - 1), ND_out(prev));
		else
		    alloc_elist(cnt - lcnt - 1, ND_out(prev));
#ifndef WITH_CGRAPH
		e = agedge(cg, prev, n);
#else
		e = agedge(cg, prev, n, NULL, 1);
		agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE);   // edge custom data
#endif
		ED_minlen(e) = SCALE;
		ED_weight(e) = 1;
		elist_append(e, ND_out(prev));
		elist_append(e, ND_in(n));
	    }
	    lcnt++;
	    prev = n;
	}
	p->cnode = n;
    }
    alloc_elist(0, ND_out(prev));

    /* add immediate right neighbor constraints
     * Construct visibility graph, then perform transitive reduction.
     * Remaining outedges are immediate right neighbors.
     * FIX: Incremental algorithm to construct trans. reduction?
     */
#ifndef WITH_CGRAPH
    vg = agopen("vg", AGDIGRAPHSTRICT);
#else
    vg = agopen("vg", Agstrictdirected, NIL(Agdisc_t *));
#endif
    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
#ifndef WITH_CGRAPH
	n = agnode(vg, agnameof(p->np));     /* FIX */
#else
	n = agnode(vg, agnameof(p->np), 1);  /* FIX */
	agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE);  //node custom data
#endif
	p->vnode = n;
	ND_alg(n) = p;
    }
    oldval = -INT_MAX;
    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
	if (oldval != p->val) {	/* new pos: reset nxt */
	    oldval = p->val;
	    for (nxt = (nitem *) dtlink(link, (Dtlink_t *) p); nxt;
		 nxt = (nitem *) dtlink(list, (Dtlink_t *) nxt)) {
		if (nxt->val != oldval)
		    break;
	    }
	    if (!nxt)
		break;
	}
	for (nxp = nxt; nxp;
	     nxp = (nitem *) dtlink(list, (Dtlink_t *) nxp)) {
	    if (intersect(p, nxp))
#ifndef WITH_CGRAPH
		agedge(vg, p->vnode, nxp->vnode);
#else
		agedge(vg, p->vnode, nxp->vnode, NULL, 1);
#endif
	}
    }

    /* Remove redundant constraints here. However, the cost of doing this
     * may be a good deal more than the time saved in network simplex. Also,
     * if the graph is changed, the ND_in and ND_out data has to be updated.
     */
    mapGraphs(vg, cg, dist);
    agclose(vg);

    /* add dummy constraints for absolute values and initial positions */
#ifdef OLD
    for (n = agfstnode(cg); n; n = agnxtnode(cg, n)) {
	node_t *vn;		/* slack node for absolute value */
	node_t *an;		/* node representing original position */

	p = (nitem *) ND_alg(n);
	if ((n == root) || (!p))
	    continue;
	vn = newNode(cg);
	ND_next(lastn) = vn;
	lastn = vn;
	alloc_elist(0, ND_out(vn));
	alloc_elist(2, ND_in(vn));
	an = newNode(cg);
	ND_next(lastn) = an;
	lastn = an;
	alloc_elist(1, ND_in(an));
	alloc_elist(1, ND_out(an));

#ifndef WITH_CGRAPH
	e = agedge(cg, root, an);
#else
	e = agedge(cg, root, an, 1);
#endif
	ED_minlen(e) = p->val - root_val;
	elist_append(e, ND_out(root));
	elist_append(e, ND_in(an));

#ifndef WITH_CGRAPH
	e = agedge(cg, an, vn);
#else
	e = agedge(cg, an, vn, 1);
#endif
	elist_append(e, ND_out(an));
	elist_append(e, ND_in(vn));

#ifndef WITH_CGRAPH
	e = agedge(cg, n, vn);
#else
	e = agedge(cg, n, vn, 1);
#endif
	elist_append(e, ND_out(n));
	elist_append(e, ND_in(vn));
    }
#endif  /* OLD */

    return cg;
}
示例#10
0
/* mkNConstraintG:
 * Similar to mkConstraintG, except it doesn't enforce orthogonal
 * ordering. If there is overlap, as defined by intersect, the
 * nodes will kept/pushed apart in the current order. If not, no
 * constraint is enforced. If a constraint edge is added, and it
 * corresponds to a real edge, we increase the weight in an attempt
 * to keep the resulting shift short. 
 */
static graph_t *mkNConstraintG(graph_t * g, Dt_t * list,
			      intersectfn intersect, distfn dist)
{
    nitem *p;
    nitem *nxp;
    node_t *n;
    edge_t *e;
    node_t *lastn = NULL;
#ifndef WITH_CGRAPH
    graph_t *cg = agopen("cg", AGDIGRAPHSTRICT);
#else
    graph_t *cg = agopen("cg", Agstrictdirected, NIL(Agdisc_t *));
    agbindrec(cg, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE);  // graph custom data
#endif

    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
#ifndef WITH_CGRAPH
	n = agnode(cg, agnameof(p->np));	/* FIX */
#else
	n = agnode(cg, agnameof(p->np), 1);      /* FIX */
	agbindrec(n, "Agnodeinfo_t", sizeof(Agnodeinfo_t), TRUE); //node custom data
#endif
	ND_alg(n) = p;
	p->cnode = n;
	alloc_elist(0, ND_in(n));
	alloc_elist(0, ND_out(n));
	if (lastn) {
	    ND_next(lastn) = n;
	    lastn = n;
	} else {
	    lastn = GD_nlist(cg) = n;
	}
    }
    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
	for (nxp = (nitem *) dtlink(link, (Dtlink_t *) p); nxp;
	     nxp = (nitem *) dtlink(list, (Dtlink_t *) nxp)) {
	    e = NULL;
	    if (intersect(p, nxp)) {
	        double delta = dist(&p->bb, &nxp->bb);
#ifndef WITH_CGRAPH
	        e = agedge(cg, p->cnode, nxp->cnode);
#else
	        e = agedge(cg, p->cnode, nxp->cnode, NULL, 1);
		agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE);   // edge custom data
#endif
		assert (delta <= 0xFFFF);
		ED_minlen(e) = delta;
		ED_weight(e) = 1;
	    }
	    if (e && agfindedge(g,p->np, nxp->np)) {
		ED_weight(e) = 100;
            }
#if 0
	    if (agfindedge(g,p->np, nxp->np)) {
		if (e == NULL)
	            e = agedge(cg, p->cnode, nxp->cnode);
		ED_weight(e) = 100;
                /* If minlen < SCALE, the nodes can't conflict or there's
                 * an overlap but it will be removed in the orthogonal pass.
                 * So we just keep the node's basically where they are.
                 */
		if (SCALE > ED_minlen(e))
		    ED_minlen(e) = SCALE;
	    }
#endif
	}
    }
   
    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
	n = p->cnode;
	for (e = agfstout(cg,n); e; e = agnxtout(cg,e)) {
	    elist_append(e, ND_out(n));
	    elist_append(e, ND_in(aghead(e)));
	}
    }

    /* We could remove redundant constraints here. However, the cost of doing 
     * this may be a good deal more than the time saved in network simplex. 
     * Also, if the graph is changed, the ND_in and ND_out data has to be 
     * updated.
     */
    return cg;
}