Пример #1
0
/*
 * Close a graph or subgraph, freeing its storage.
 */
int agclose(Agraph_t * g)
{
    Agraph_t *subg, *next_subg, *par;
    Agnode_t *n, *next_n;

    par = agparent(g);
    if ((par == NILgraph) && (AGDISC(g, mem)->close)) {
	/* free entire heap */
	agmethod_delete(g, g);	/* invoke user callbacks */
	agfreeid(g, AGRAPH, AGID(g));
	AGDISC(g, mem)->close(AGCLOS(g, mem));	/* whoosh */
	return SUCCESS;
    }

    for (subg = agfstsubg(g); subg; subg = next_subg) {
	next_subg = agnxtsubg(subg);
	agclose(subg);
    }

    for (n = agfstnode(g); n; n = next_n) {
	next_n = agnxtnode(g, n);
	agdelnode(g, n);
    }

    aginternalmapclose(g);
    agmethod_delete(g, g);

    assert(dtsize(g->n_id) == 0);
    agdtclose(g, g->n_id);
    assert(dtsize(g->n_seq) == 0);
    agdtclose(g, g->n_seq);

    assert(dtsize(g->e_id) == 0);
    agdtclose(g, g->e_id);
    assert(dtsize(g->e_seq) == 0);
    agdtclose(g, g->e_seq);

    assert(dtsize(g->g_dict) == 0);
    agdtclose(g, g->g_dict);

    if (g->desc.has_attrs)
	agraphattr_delete(g);
    agrecclose((Agobj_t *) g);
    agfreeid(g, AGRAPH, AGID(g));

    if (par) {
	agdelsubg(par, g);
	agfree(par, g);
    } else {
	Agmemdisc_t *memdisc;
	void *memclos, *clos;
	while (g->clos->cb)
	    agpopdisc(g, g->clos->cb->f);
	AGDISC(g, id)->close(AGCLOS(g, id));
	agstrclose(g);
	memdisc = AGDISC(g, mem);
	memclos = AGCLOS(g, mem);
	clos = g->clos;
	(memdisc->free) (memclos, g);
	(memdisc->free) (memclos, clos);
    }
    return SUCCESS;
}
Пример #2
0
/* scAdjust:
 * Scale the layout.
 * equal > 0  => scale uniformly in x and y to remove overlaps
 * equal = 0  => scale separately in x and y to remove overlaps
 * equal < 0  => scale down uniformly in x and y to remove excess space
 * The last assumes there are no overlaps at present.
 * Based on Marriott, Stuckey, Tam and He,
 * "Removing Node Overlapping in Graph Layout Using Constrained Optimization",
 * Constraints,8(2):143--172, 2003.
 */
int scAdjust(graph_t * g, int equal)
{
    int nnodes = agnnodes(g);
    info *nlist = N_GNEW(nnodes, info);
    info *p = nlist;
    node_t *n;
    pointf s;
    int i;
    double margin;
    pointf *aarr;
    int m;

    margin = expFactor (g);

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	double w2 = margin * ND_width(n) / 2.0;
	double h2 = margin * ND_height(n) / 2.0;
	p->pos.x = ND_pos(n)[0];
	p->pos.y = ND_pos(n)[1];
	p->bb.LL.x = p->pos.x - w2;
	p->bb.LL.y = p->pos.y - h2;
	p->bb.UR.x = p->pos.x + w2;
	p->bb.UR.y = p->pos.y + h2;
	p->wd2 = w2;
	p->ht2 = h2;
	p->np = n;
	p++;
    }

    if (equal < 0) {
	s.x = s.y = compress(nlist, nnodes);
	if (s.x == 0) {		/* overlaps exist */
	    free(nlist);
	    return 0;
	}
	fprintf(stderr, "compress %g \n", s.x);
    } else {
	aarr = mkOverlapSet(nlist, nnodes, &m);

	if (m == 0) {		/* no overlaps */
	    free(aarr);
	    free(nlist);
	    return 0;
	}

	if (equal) {
	    s.x = s.y = computeScale(aarr, m);
	} else {
	    s = computeScaleXY(aarr, m);
	}
	free(aarr);
    }

    p = nlist;
    for (i = 0; i < nnodes; i++) {
	ND_pos(p->np)[0] = s.x * p->pos.x;
	ND_pos(p->np)[1] = s.y * p->pos.y;
	p++;
    }

    free(nlist);
    return 1;
}
Пример #3
0
static void sfdpLayout(graph_t * g, spring_electrical_control ctrl,
		       int hops, pointf pad)
{
    real *sizes;
    real *pos;
    Agnode_t *n;
    int flag, i;
    int n_edge_label_nodes = 0, *edge_label_nodes = NULL;
    SparseMatrix D = NULL;
    SparseMatrix A;

    if (ctrl->method == METHOD_SPRING_MAXENT) /* maxent can work with distance matrix */
	A = makeMatrix(g, Ndim, &D);
    else
	A = makeMatrix(g, Ndim, NULL);

    if (ctrl->overlap >= 0) {
	if (ctrl->edge_labeling_scheme > 0)
	    sizes = getSizes(g, pad, &n_edge_label_nodes, &edge_label_nodes);
	else
	    sizes = getSizes(g, pad, NULL, NULL);
    }
    else
	sizes = NULL;
    pos = getPos(g, ctrl);

    switch (ctrl->method) {
    case METHOD_SPRING_ELECTRICAL:
    case METHOD_SPRING_MAXENT:
	multilevel_spring_electrical_embedding(Ndim, A, D, ctrl, NULL, sizes, pos, n_edge_label_nodes, edge_label_nodes, &flag);
	break;
    case METHOD_UNIFORM_STRESS:
	uniform_stress(Ndim, A, pos, &flag);
	break;
    case METHOD_STRESS:{
	int maxit = 200;
	real tol = 0.001;
	int weighted = TRUE;

	if (!D){
	    D = SparseMatrix_get_real_adjacency_matrix_symmetrized(A);/* all distance 1 */
	    weighted = FALSE;
	} else {
	    D = SparseMatrix_symmetrize_nodiag(D, FALSE);
	    weighted = TRUE;
	}
	if (hops > 0){
	    SparseMatrix DD;
	    DD = SparseMatrix_distance_matrix_khops(hops, D, weighted);
	    if (Verbose){
		fprintf(stderr,"extracted a %d-neighborhood graph of %d edges from a graph of %d edges\n",
		    hops, (DD->nz)/2, (D->nz/2));
	    }
	    SparseMatrix_delete(D);
	    D = DD;
	}

	stress_model(Ndim, A, D, &pos, TRUE, maxit, tol, &flag);
	}
	break;
    }

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	real *npos = pos + (Ndim * ND_id(n));
	for (i = 0; i < Ndim; i++) {
	    ND_pos(n)[i] = npos[i];
	}
    }

    free(sizes);
    free(pos);
    SparseMatrix_delete (A);
    if (D) SparseMatrix_delete (D);
    if (edge_label_nodes) FREE(edge_label_nodes);
}
Пример #4
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 *cg = agopen("cg", AGDIGRAPHSTRICT);
    graph_t *vg;
    node_t *prev = NULL;
    node_t *root = NULL;
    node_t *n = NULL;
    edge_t *e;
    int lcnt, cnt;
    int oldval = -MAXINT;
#ifdef OLD
    double root_val;
#endif
    node_t *lastn = NULL;

    /* 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 = -MAXINT;
    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); */
	    n = agnode(cg, p->np->name);	/* FIX */
	    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));
		e = agedge(cg, prev, n);
		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?
     */
    vg = agopen("vg", AGDIGRAPHSTRICT);
    for (p = (nitem *) dtflatten(list); p;
	 p = (nitem *) dtlink(list, (Dtlink_t *) p)) {
	n = agnode(vg, p->np->name);
	p->vnode = n;
	ND_alg(n) = p;
    }
    oldval = -MAXINT;
    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))
		agedge(vg, p->vnode, nxp->vnode);
	}
    }

    /* 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));

	e = agedge(cg, root, an);
	ED_minlen(e) = p->val - root_val;
	elist_append(e, ND_out(root));
	elist_append(e, ND_in(an));

	e = agedge(cg, an, vn);
	elist_append(e, ND_out(an));
	elist_append(e, ND_in(vn));

	e = agedge(cg, n, vn);
	elist_append(e, ND_out(n));
	elist_append(e, ND_in(vn));
    }
#endif

    return cg;
}
Пример #5
0
/* cAdjust:
 * Use optimization to remove overlaps.
 * Modifications;
 *  - do y;x then x;y and use the better one
 *  - for all overlaps (or if overlap with leftmost nodes), add a constraint;
 *     constraint could move both x and y away, or the smallest, or some
 *     mixture.
 *  - follow by a scale down using actual shapes
 * We use an optimization based on Marriott, Stuckey, Tam and He,
 * "Removing Node Overlapping in Graph Layout Using Constrained Optimization",
 * Constraints,8(2):143--172, 2003.
 * We solve 2 constraint problem, one in X, one in Y. In each dimension,
 * we require relative positions to remain the same. That is, if two nodes
 * have the same x originally, they have the same x at the end, and if one
 * node is to the left of another, it remains to the left. In addition, if
 * two nodes could overlap by moving their X coordinates, we insert a constraint * to keep the two nodes sufficiently apart. Similarly, for Y.
 * 
 * mode = AM_ORTHOXY => first X, then Y
 * mode = AM_ORTHOYX => first Y, then X
 * mode = AM_ORTHO   => first X, then Y
 * mode = AM_ORTHO_YX   => first Y, then X
 * In the last 2 cases, relax the constraints as follows: during the X pass,
 * if two nodes actually intersect and a smaller move in the Y direction
 * will remove the overlap, we don't force the nodes apart in the X direction,
 * but leave it for the Y pass to remove any remaining overlaps. Without this,
 * the X pass will remove all overlaps, and the Y pass only compresses in the
 * Y direction, causing a skewing of the aspect ratio.
 * 
 * mode = AM_ORTHOXY => first X, then Y
 * mode = AM_ORTHOYX => first Y, then X
 * mode = AM_ORTHO   => first X, then Y
 * mode = AM_ORTHO_YX   => first Y, then X
 */
int cAdjust(graph_t * g, int mode)
{
    double margin;
    int ret, i, nnodes = agnnodes(g);
    nitem *nlist = N_GNEW(nnodes, nitem);
    nitem *p = nlist;
    node_t *n;

    margin = expFactor (g);

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	initItem(n, p, margin);
	p++;
    }

    if (overlaps(nlist, nnodes)) {
	point pt;

	switch ((adjust_mode)mode) {
	case AM_ORTHOXY:
	    constrainX(g, nlist, nnodes, intersectY, 1);
	    constrainY(g, nlist, nnodes, intersectX, 1);
	    break;
	case AM_ORTHOYX:
	    constrainY(g, nlist, nnodes, intersectX, 1);
	    constrainX(g, nlist, nnodes, intersectY, 1);
	    break;
	case AM_ORTHO :
	    constrainX(g, nlist, nnodes, intersectY0, 1);
	    constrainY(g, nlist, nnodes, intersectX, 1);
	case AM_ORTHO_YX :
	    constrainY(g, nlist, nnodes, intersectX0, 1);
	    constrainX(g, nlist, nnodes, intersectY, 1);
	case AM_PORTHOXY:
	    constrainX(g, nlist, nnodes, intersectY, 0);
	    constrainY(g, nlist, nnodes, intersectX, 0);
	    break;
	case AM_PORTHOYX:
	    constrainY(g, nlist, nnodes, intersectX, 0);
	    constrainX(g, nlist, nnodes, intersectY, 0);
	    break;
	case AM_PORTHO_YX :
	    constrainY(g, nlist, nnodes, intersectX0, 0);
	    constrainX(g, nlist, nnodes, intersectY, 0);
	    break;
	case AM_PORTHO :
	default :
	    constrainX(g, nlist, nnodes, intersectY0, 0);
	    constrainY(g, nlist, nnodes, intersectX, 0);
	    break;
	}
	p = nlist;
	for (i = 0; i < nnodes; i++) {
	    n = p->np;
	    pt = p->pos;
	    ND_pos(n)[0] = PS2INCH(pt.x) / SCALE;
	    ND_pos(n)[1] = PS2INCH(pt.y) / SCALE;
	    p++;
	}
	ret = 1;
    }
    else ret = 0;
    free(nlist);
    return ret;
}
Пример #6
0
static void color(Agraph_t * g)
{
    int nn, i, j, cnt;
    Agnode_t *n, *v, **nlist;
    Agedge_t *e;
    char *p;
    double x, y, maxrank = 0.0;
    double sum[NC], d, lowsat, highsat;

    if (agattr(g, AGNODE, "pos", 0) == NULL) {
	fprintf(stderr,
		"graph must be run through 'dot' before 'gvcolor'\n");
	exit(1);
    }
    aginit(g, AGNODE, "nodeinfo", sizeof(Agnodeinfo_t), TRUE);
    if (agattr(g, AGNODE, "style", 0) == NULL)
	agattr(g, AGNODE, "style", "filled");
    if ((p = agget(g, "Defcolor")))
	setcolor(p, Defcolor);

    if ((p = agget(g, "rankdir")) && (p[0] == 'L'))
	LR = 1;
    if ((p = agget(g, "flow")) && (p[0] == 'b'))
	Forward = 0;
    if ((p = agget(g, "saturation"))) {
	if (sscanf(p, "%lf,%lf", &lowsat, &highsat) == 2) {
	    MinRankSaturation = lowsat;
	    MaxRankSaturation = highsat;
	    AdjustSaturation = 1;
	}
    }

    /* assemble the sorted list of nodes and store the initial colors */
    nn = agnnodes(g);
    nlist = (Agnode_t **) malloc(nn * sizeof(Agnode_t *));
    i = 0;
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	nlist[i++] = n;
	if ((p = agget(n, "color")))
	    setcolor(p, ND_x(n));
	p = agget(n, "pos");
	sscanf(p, "%lf,%lf", &x, &y);
	ND_relrank(n) = (LR ? x : y);
	if (maxrank < ND_relrank(n))
	    maxrank = ND_relrank(n);
    }
    if (LR != Forward)
	for (i = 0; i < nn; i++) {
	    n = nlist[i];
	    ND_relrank(n) = maxrank - ND_relrank(n);
	}
    qsort((void *) nlist, (size_t) nn, sizeof(Agnode_t *),
	  (int (*)(const void *, const void *)) cmpf);

    /* this is the pass that pushes the colors through the edges */
    for (i = 0; i < nn; i++) {
	n = nlist[i];

	/* skip nodes that were manually colored */
	cnt = 0;
	for (j = 0; j < NC; j++)
	    if (ND_x(n)[j] != 0.0)
		cnt++;
	if (cnt > 0)
	    continue;

	for (j = 0; j < NC; j++)
	    sum[j] = 0.0;
	cnt = 0;
	for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
	    v = aghead(e);
	    if (v == n)
		v = agtail(e);
	    d = ND_relrank(v) - ND_relrank(n) - 0.01;
	    if (d < 0) {
		double t = 0.0;
		for (j = 0; j < NC; j++) {
		    t += ND_x(v)[j];
		    sum[j] += ND_x(v)[j];
		}
		if (t > 0.0)
		    cnt++;
	    }
	}
	if (cnt)
	    for (j = 0; j < NC; j++)
		ND_x(n)[j] = sum[j] / cnt;
    }

    /* apply saturation adjustment and convert color to string */
    for (i = 0; i < nn; i++) {
	double h, s, b, t;
	char buf[64];

	n = nlist[i];

	t = 0.0;
	for (j = 0; j < NC; j++)
	    t += ND_x(n)[j];
	if (t > 0.0) {
	    h = ND_x(n)[0];
	    if (AdjustSaturation) {
		s = ND_relrank(n) / maxrank;
		if (!Forward)
		    s = 1.0 - s;
		s = MinRankSaturation
		    + s * (MaxRankSaturation - MinRankSaturation);
	    } else
		s = 1.0;
	    s = s * ND_x(n)[1];
	    b = ND_x(n)[2];
	} else {
	    h = Defcolor[0];
	    s = Defcolor[1];
	    b = Defcolor[2];
	}
	sprintf(buf, "%f %f %f", h, s, b);
	agset(n, "color", buf);
    }
}
Пример #7
0
/* orthoEdges:
 * For edges without position information, construct an orthogonal routing.
 * If doLbls is true, use edge label info when available to guide routing, 
 * and set label pos for those edges for which this info is not available.
 */
void
orthoEdges (Agraph_t* g, int doLbls)
{
    sgraph* sg;
    maze* mp;
    int n_edges;
    route* route_list;
    int i, gstart;
    Agnode_t* n;
    Agedge_t* e;
    snode* sn;
    snode* dn;
    epair_t* es = N_GNEW(agnedges(g), epair_t);
    cell* start;
    cell* dest;
    PointSet* ps;
    textlabel_t* lbl;

    if (Concentrate) 
	ps = newPS();

#ifdef DEBUG
    {
	char* s = agget(g, "odb");
        char c;
	odb_flags = 0;
	if (s && (*s != '\0')) {
	    while ((c = *s++)) {
		switch (c) {
		case 'c' :
		    odb_flags |= ODB_CHANG;     // emit channel graph 
		    break;
		case 'i' :
		    odb_flags |= (ODB_SGRAPH|ODB_IGRAPH);  // emit search graphs
		    break;
		case 'm' :
		    odb_flags |= ODB_MAZE;      // emit maze
		    break;
		case 'r' :
		    odb_flags |= ODB_ROUTE;     // emit routes in maze
		    break;
		case 's' :
		    odb_flags |= ODB_SGRAPH;    // emit search graph 
		    break;
		}
	    }
	}
    }
#endif
    mp = mkMaze (g, doLbls);
    sg = mp->sg;
#ifdef DEBUG
    if (odb_flags & ODB_SGRAPH) emitSearchGraph (stderr, sg);
#endif

    /* store edges to be routed in es, along with their lengths */
    n_edges = 0;
    for (n = agfstnode (g); n; n = agnxtnode(g, n)) {
        for (e = agfstout(g, n); e; e = agnxtout(g,e)) {
	    if ((Nop == 2) && ED_spl(e)) continue;
	    if (Concentrate) {
		int ti = AGID(agtail(e));
		int hi = AGID(aghead(e));
		if (ti <= hi) {
		    if (isInPS (ps,ti,hi)) continue;
		    else addPS (ps,ti,hi);
		}
		else {
		    if (isInPS (ps,hi,ti)) continue;
		    else addPS (ps,hi,ti);
		}
	    }
	    es[n_edges].e = e;
	    es[n_edges].d = edgeLen (e);
	    n_edges++;
	}
    }

    route_list = N_NEW (n_edges, route);

    qsort((char *)es, n_edges, sizeof(epair_t), (qsort_cmpf) edgecmp);

    gstart = sg->nnodes;
    PQgen (sg->nnodes+2);
    sn = &sg->nodes[gstart];
    dn = &sg->nodes[gstart+1];
    for (i = 0; i < n_edges; i++) {
#ifdef DEBUG
	if ((i > 0) && (odb_flags & ODB_IGRAPH)) emitSearchGraph (stderr, sg);
#endif
	e = es[i].e;
        start = CELL(agtail(e));
        dest = CELL(aghead(e));

	if (doLbls && (lbl = ED_label(e)) && lbl->set) {
	}
	else {
	    if (start == dest)
		addLoop (sg, start, dn, sn);
	    else {
       		addNodeEdges (sg, dest, dn);
		addNodeEdges (sg, start, sn);
	    }
       	    shortPath (sg, dn, sn);
	}
	    
       	route_list[i] = convertSPtoRoute(sg, sn, dn);
       	reset (sg);
    }
    PQfree ();

    mp->hchans = extractHChans (mp);
    mp->vchans = extractVChans (mp);
    assignSegs (n_edges, route_list, mp);
    assignTracks (n_edges, route_list, mp);
#ifdef DEBUG
    if (odb_flags & ODB_ROUTE) emitGraph (stderr, mp, n_edges, route_list, es);
#endif
    attachOrthoEdges (g, mp, n_edges, route_list, &sinfo, es, doLbls);

    if (Concentrate)
	freePS (ps);

    for (i=0; i < n_edges; i++)
	free (route_list[i].segs);
    free (route_list);
    freeMaze (mp);
}
Пример #8
0
void write_plainstr(graph_t* g, std::string *str)
{
	int			i;
	node_t		*n;
	edge_t		*e;
	bezier		bz;
	char		buf[SMALLBUF],buf1[SMALLBUF];

	char tmpbuf[1000];

	setup_graph(g);

	sprintf(tmpbuf, "graph %.3f", g->u.drawing->scale);
	str->append(tmpbuf);
	printptf(str, g->u.bb.UR);
	str->append("\n");

	for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
	    str->append("node ");
	    str->append(agstrcanon(n->name,buf));
	    printptf(str,n->u.coord);
	    sprintf(tmpbuf, " %.3f", n->u.width);
	    str->append(tmpbuf);
	    sprintf(tmpbuf, " %.3f ", n->u.height);
	    str->append(tmpbuf);
	    str->append(agstrcanon(n->u.label->text,buf));
	    str->append(" ");
	    str->append(late_nnstring(n,N_style,"solid"));
	    str->append(" ");
	    str->append(n->u.shape->name);
	    str->append(" ");
	    str->append(late_nnstring(n,N_color,DEFAULT_COLOR));
	    str->append(" ");
	    str->append(late_nnstring(n,N_fillcolor,DEFAULT_FILL));
	    str->append("\n");
	}
	for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
		for (e = agfstout(g,n); e; e = agnxtout(g,e)) {
			bz = e->u.spl->list[0];
			str->append("edge ");
			str->append(agstrcanon(e->tail->name,buf));
			str->append(" ");
			str->append(agstrcanon(e->head->name,buf1));
			str->append(" ");
			sprintf(tmpbuf, " %d", bz.size);
			str->append(tmpbuf);

			for (i = 0; i < bz.size; i++) printptf(str,bz.list[i]);
			if (e->u.label) {
			    str->append(" ");
			    str->append(agstrcanon(e->u.label->text,buf));
			    printptf(str,e->u.label->p);
			}
			str->append(" ");
			str->append(late_nnstring(e,E_style,"solid"));
			str->append(" ");
			str->append(late_nnstring(e,E_color,DEFAULT_COLOR));
			str->append("\n");
		}
	}
	str->append("stop\n");
}
Пример #9
0
static void
write_subg(Agraph_t * g, FILE * fp, Agraph_t * par, int indent,
	   printdict_t * state)
{
    Agraph_t *subg, *meta;
    Agnode_t *n, *pn;
    Agedge_t *e, *pe;
    Dt_t *save_e, *save_n;

    if (indent) {
	tabover(fp, indent++);
	if (dtsearch(state->subgleft, g->meta_node)) {
	    if (strncmp(g->name, "_anonymous", 10)) {
		agputs("subgraph ", fp);
		agputs(agcanonical(g->name), fp);
		agputs(" {\n", fp);
	    }
	    else {
		agputs("{\n", fp);	/* no name printed for anonymous subg */
	    }
	    write_diffattr(fp, indent, g, par, g->univ->globattr);
	    /* The root node and edge environment use the dictionaries,
	     * not the proto node or edge, so the next level down must
	     * record differences with the dictionaries.
	     */
	    if (par == g->root) {
		pn = NULL;
		pe = NULL;
	    } else {
		pn = par->proto->n;
		pe = par->proto->e;
	    }
	    write_diffattr(fp, indent, g->proto->n, pn, g->univ->nodeattr);
	    write_diffattr(fp, indent, g->proto->e, pe, g->univ->edgeattr);
	    dtdelete(state->subgleft, g->meta_node);
	} else {
	    agputs("subgraph ", fp);
	    agputs(agcanonical(g->name), fp);
	    agputs(";\n", fp);
	    return;
	}
    } else
	write_diffattr(fp, ++indent, g, NULL, g->univ->globattr);

    save_n = state->n_insubg;
    save_e = state->e_insubg;
    meta = g->meta_node->graph;
    state->n_insubg = dtopen(&agNamedisc, Dtoset);
    state->e_insubg = dtopen(&agOutdisc, Dtoset);
    for (e = agfstout(meta, g->meta_node); e; e = agnxtout(meta, e)) {
	subg = agusergraph(e->head);
	write_subg(subg, fp, g, indent, state);
    }
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (dtsearch(state->nodesleft, n)) {
	    agwrnode(g, fp, n, TRUE, indent);
	    dtdelete(state->nodesleft, n);
	} else {
	    if (dtsearch(state->n_insubg, n) == NULL) {
		agwrnode(g, fp, n, FALSE, indent);
	    }
	}
	dtinsert(save_n, n);
    }

    dtdisc(g->outedges, &agEdgedisc, 0);	/* sort by id */
    for (e = (Agedge_t *) dtfirst(g->outedges); e;
	 e = (Agedge_t *) dtnext(g->outedges, e)) {
	if (dtsearch(state->edgesleft, e)) {
	    tabover(fp, indent);
	    agwredge(g, fp, e, TRUE);
	    dtdelete(state->edgesleft, e);
	} else {
	    if (dtsearch(state->e_insubg, e) == NULL) {
		tabover(fp, indent);
		agwredge(g, fp, e, FALSE);
	    }
	}
	dtinsert(save_e, e);
    }
    dtdisc(g->outedges, &agOutdisc, 0);	/* sort by name */
    dtclose(state->n_insubg);
    state->n_insubg = save_n;
    dtclose(state->e_insubg);
    state->e_insubg = save_e;

    if (indent > 1) {
	tabover(fp, indent - 1);
	agputs("}\n", fp);
    }
}
Пример #10
0
main(int argc, char *argv[])
{
    Agraph_t **gs;
    Agraph_t **ccs;
    Agraph_t *g;
    Agraph_t *gp;
    char *fname;
    FILE *fp;
    int cnt;
    int i;

    init(argc, argv);
    if (!Files) {
	fprintf(stderr, "No input files given\n");
	exit(1);
    }

    PSinputscale = POINTS_PER_INCH;
    if (doComps) {
	if (verbose)
	    fprintf(stderr, "do Comps\n");
	while (fname = *Files++) {
	    fp = fopen(fname, "r");
	    if (!fp) {
		fprintf(stderr, "Could not open %s\n", fname);
		continue;
	    }
	    g = agread(fp);
	    fclose(fp);
	    if (!g) {
		fprintf(stderr, "Could not read graph\n");
		continue;
	    }
	    printf("%s %d nodes %d edges %sconnected\n",
		   g->name, agnnodes(g), agnedges(g),
		   (isConnected(g) ? "" : "not "));
	    gs = ccomps(g, &cnt, "abc");
	    for (i = 0; i < cnt; i++) {
		gp = gs[i];
		printf(" %s %d nodes %d edges\n", gp->name, agnnodes(gp),
		       agnedges(gp));
	    }
	}
    } else {
	gs = N_GNEW(nFiles, Agraph_t *);
	cnt = 0;
	while (fname = Files[cnt]) {
	    fp = fopen(fname, "r");
	    if (!fp) {
		fprintf(stderr, "Could not open %s\n", fname);
		exit(1);
	    }
	    g = agread(fp);
	    fclose(fp);
	    if (!g) {
		fprintf(stderr, "Could not read graph\n");
		exit(1);
	    }
	    if (!single) {
		graph_init(g);
		ptest_initGraph(g);
	    }
	    initPos(g);
	    /* if (Verbose) dumpG (g); */
	    gs[cnt++] = g;
	}
	if (single) {
	    Agraph_t *root;
	    Agnode_t *n;
	    Agnode_t *np;
	    Agnode_t *tp;
	    Agnode_t *hp;
	    Agedge_t *e;
	    Agedge_t *ep;
	    root = agopen("root", 0);
	    agedgeattr(root, "pos", "");
	    for (i = 0; i < cnt; i++) {
		g = gs[i];
		for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
		    if (agfindnode(root, n->name)) {
			fprintf(stderr,
				"Error: node %s in graph %d (%s) previously added\n",
				n->name, i, Files[i]);
			exit(1);
		    }
		    np = agnode(root, n->name);
		    ND_pos(np)[0] = ND_pos(n)[0];
		    ND_pos(np)[1] = ND_pos(n)[1];
		    ND_coord_i(np).x = ND_coord_i(n).x;
		    ND_coord_i(np).y = ND_coord_i(n).y;
		}
		for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
		    tp = agfindnode(root, n->name);
		    for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
			hp = agfindnode(root, e->head->name);
			ep = agedge(root, tp, hp);
			ED_spl(ep) = ED_spl(e);
		    }
		}
	    }
	    graph_init(root);
	    ptest_initGraph(root);
	    ccs = ccomps(root, &cnt, 0);
	    packGraphs(cnt, ccs, root, margin, doEdges);
	    if (!doEdges)
		copyPos(root);
	    else
		State = GVSPLINES;
	    attach_attrs(root);
	    for (i = 0; i < cnt; i++) {
		agdelete(root, ccs[i]);
	    }
	    agwrite(root, stdout);
	} else {
	    packGraphs(cnt, gs, 0, margin, doEdges);
	    if (doEdges)
		State = GVSPLINES;
	    for (i = 0; i < cnt; i++) {
		if (!doEdges)
		    copyPos(gs[i]);
		attach_attrs(gs[i]);
		agwrite(gs[i], stdout);
	    }
	}
    }
}
Пример #11
0
void attach_attrs(graph_t* g)
{
	int		i,j,sides;
	char	buf[BUFSIZ],*p;
	node_t	*n;
	edge_t	*e;
	point	pt;

	safe_dcl(g,g->proto->n,"pos","",agnodeattr);
	safe_dcl(g,g->proto->n,"rects","",agnodeattr);
	N_width = safe_dcl(g,g->proto->n,"width","",agnodeattr);
	N_height = safe_dcl(g,g->proto->n,"height","",agnodeattr);
	safe_dcl(g,g->proto->e,"pos","",agedgeattr);
	if (g->u.has_edge_labels) safe_dcl(g,g->proto->e,"lp","",agedgeattr);
	if (g->u.label) {
		safe_dcl(g,g,"lp","",agraphattr);
		pt = g->u.label->p;
		sprintf(buf,"%d,%d",pt.x,pt.y);
		agset(g,"lp",buf);
	}
	safe_dcl(g,g,"bb","",agraphattr);
	for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
		sprintf(buf,"%d,%d",n->u.coord.x,n->u.coord.y);
		agset(n,"pos",buf);
		sprintf(buf,"%.2f",PS2INCH(n->u.ht));
		agxset(n,N_height->index,buf);
		sprintf(buf,"%.2f",PS2INCH(n->u.lw + n->u.rw));
		agxset(n,N_width->index,buf);
		if (strcmp (n->u.shape->name, "record") == 0) {
			buf[0] = '\000', rectbufp = &buf[0];
			set_record_rects (n, (field_t *)(n->u.shape_info));
			if (rectbufp > &buf[0]) /* get rid of last space */
				*(--rectbufp) = '\000';
			agset(n,"rects",buf);
		}
		else {
			extern void	poly_init(node_t *);
			polygon_t *poly;
			int i;
			if (N_vertices && (n->u.shape->initfn == poly_init)) {
				poly = (polygon_t*) n->u.shape_info;
				p = buf; 
				sides = poly->sides;
				if (sides < 3) {
					char *p = agget(n,"samplepoints");
					if (p) sides = atoi(p);
					else sides = 8;
					if (sides < 3) sides = 8;
				}
				for (i = 0; i < sides; i++) {
					if (i > 0) {*p++ = ' ';}
					if (poly->sides >= 3)
						sprintf(p,"%.3lf %.3lf",
							poly->vertices[i].x,poly->vertices[i].y);
					else
						sprintf(p,"%.3lf %.3lf",
							n->u.width/2.0 * cos(i/(double)sides * PI * 2.0),
							n->u.height/2.0 * sin(i/(double)sides * PI * 2.0));
					while (*p) p++;
				}
				agxset(n,N_vertices->index,buf);
			}
		}
		for (e = agfstout(g,n); e; e = agnxtout(g,e)) {
			p = buf;
if (e->u.spl == NULL)
	{fprintf(stderr,"lost spline of %s %s\n",e->tail->name,e->head->name); continue;}
			for (i = 0; i < e->u.spl->size; i++) {
				if (i > 0) *p++ = ';';
				if (e->u.spl->list[i].sflag) {
					sprintf (p, "s,%d,%d ",e->u.spl->list[i].sp.x,e->u.spl->list[i].sp.y);
					while (*p) p++;
				}
				if (e->u.spl->list[i].eflag) {
					sprintf (p, "e,%d,%d ",e->u.spl->list[i].ep.x,e->u.spl->list[i].ep.y);
					while (*p) p++;
				}
				for (j = 0; j < e->u.spl->list[i].size; j++) {
					if (j > 0) *p++ = ' ';
					pt = e->u.spl->list[i].list[j];
					sprintf(p,"%d,%d",pt.x,pt.y);
					while (*p) p++;
				}
				*p = '\0';
			}
			agset(e,"pos",buf);
			if (e->u.label) {
				pt = e->u.label->p;
				sprintf(buf,"%d,%d",pt.x,pt.y);
				agset(e,"lp",buf);
			}
		}
	}
	rec_attach_bb(g);
}
Пример #12
0
SEXP getEdgeLocs(Agraph_t *g) {
    SEXP outList, curCP, curEP, pntList, pntSet, curXY, curLab;
    SEXP epClass, cpClass, xyClass, labClass;
    Agnode_t *node, *head;
    Agedge_t *edge;
    char *tmpString;
    bezier bez;
    int nodes;
    int i,k,l,pntLstEl;
    int curEle = 0;

    epClass = MAKE_CLASS("AgEdge");
    cpClass = MAKE_CLASS("BezierCurve");
    xyClass = MAKE_CLASS("xyPoint");
    labClass = MAKE_CLASS("AgTextLabel");

    /* tmpString is used to convert a char to a char* w/ labels */
    tmpString = (char *)R_alloc(2, sizeof(char));
    if (tmpString == NULL) error("Allocation error in getEdgeLocs");

    PROTECT(outList = allocVector(VECSXP, agnedges(g)));

    nodes = agnnodes(g);
    node = agfstnode(g);

    for (i = 0; i < nodes; i++) {
        edge = agfstout(g, node);
        while (edge != NULL && edge->u.spl != NULL) {
            PROTECT(curEP = NEW_OBJECT(epClass));
            bez = edge->u.spl->list[0];
            PROTECT(pntList = allocVector(VECSXP, ((bez.size-1)/3)));
            pntLstEl = 0;

            /* There are really (bez.size-1)/3 sets of control */
            /* points, with the first set containing teh first 4 */
            /* points, and then every other set starting with the */
            /* last point from the previous set and then the next 3 */
            for (k = 1; k < bez.size; k += 3) {
                PROTECT(curCP = NEW_OBJECT(cpClass));
                PROTECT(pntSet = allocVector(VECSXP, 4));
                for (l = -1; l < 3; l++) {
                    PROTECT(curXY = NEW_OBJECT(xyClass));
                    SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(bez.list[k+l].x));
                    SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(bez.list[k+l].y));
                    SET_ELEMENT(pntSet, l+1, curXY);
                    UNPROTECT(1);
                }
                SET_SLOT(curCP, Rf_install("cPoints"), pntSet);
                SET_ELEMENT(pntList, pntLstEl++, curCP);
                UNPROTECT(2);
            }
            SET_SLOT(curEP, Rf_install("splines"), pntList);
            /* get the sp and ep */
            PROTECT(curXY = NEW_OBJECT(xyClass));
            SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(bez.sp.x));
            SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(bez.sp.y));
            SET_SLOT(curEP, Rf_install("sp"), curXY);
            UNPROTECT(1);
            PROTECT(curXY = NEW_OBJECT(xyClass));
            SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(bez.ep.x));
            SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(bez.ep.y));
            SET_SLOT(curEP, Rf_install("ep"), curXY);
            UNPROTECT(1);

            SET_SLOT(curEP, Rf_install("tail"), Rgraphviz_ScalarStringOrNull(node->name));
            head = edge->head;
            SET_SLOT(curEP, Rf_install("head"), Rgraphviz_ScalarStringOrNull(head->name));

            /* TODO: clean up the use of attrs: dir, arrowhead, arrowtail.
             * the following are for interactive plotting in R-env, not needed 
             * for output to files.  The existing codes set "dir"-attr, but use
             * "arrowhead"/"arrowtail" instead.  Quite confusing.  
             */
            SET_SLOT(curEP, Rf_install("dir"), Rgraphviz_ScalarStringOrNull(agget(edge, "dir")));
            SET_SLOT(curEP, Rf_install("arrowhead"), Rgraphviz_ScalarStringOrNull(agget(edge, "arrowhead")));
            SET_SLOT(curEP, Rf_install("arrowtail"), Rgraphviz_ScalarStringOrNull(agget(edge, "arrowtail")));
            SET_SLOT(curEP, Rf_install("arrowsize"), Rgraphviz_ScalarStringOrNull(agget(edge, "arrowsize")));

            SET_SLOT(curEP, Rf_install("color"), Rgraphviz_ScalarStringOrNull(agget(edge, "color")));

            /* get lty/lwd info */
            if ( agget(edge, "lty") )
               SET_SLOT(curEP, Rf_install("lty"), Rgraphviz_ScalarStringOrNull(agget(edge, "lty")));

            if ( agget(edge, "lwd") )
               SET_SLOT(curEP, Rf_install("lwd"), Rgraphviz_ScalarStringOrNull(agget(edge, "lwd")));

            /* Get the label information */
            if (edge->u.label != NULL) {
                PROTECT(curLab = NEW_OBJECT(labClass));
                SET_SLOT(curLab, Rf_install("labelText"),
                         Rgraphviz_ScalarStringOrNull(ED_label(edge)->u.txt.para->str));
                /* Get the X/Y location of the label */
                PROTECT(curXY = NEW_OBJECT(xyClass));
#if GRAPHVIZ_MAJOR == 2 && GRAPHVIZ_MINOR > 20
                SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(ED_label(edge)->pos.x));
                SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(ED_label(edge)->pos.y));
#else
                SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(edge->u.label->p.x));
                SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(edge->u.label->p.y));
#endif
                SET_SLOT(curLab, Rf_install("labelLoc"), curXY);
                UNPROTECT(1);

                snprintf(tmpString, 2, "%c",ED_label(edge)->u.txt.para->just);
                SET_SLOT(curLab, Rf_install("labelJust"),
                         Rgraphviz_ScalarStringOrNull(tmpString));

                SET_SLOT(curLab, Rf_install("labelWidth"),
                         Rf_ScalarInteger(ED_label(edge)->u.txt.para->width));

                SET_SLOT(curLab, Rf_install("labelColor"),
                         Rgraphviz_ScalarStringOrNull(edge->u.label->fontcolor));

                SET_SLOT(curLab, Rf_install("labelFontsize"), Rf_ScalarReal(edge->u.label->fontsize));

                SET_SLOT(curEP, Rf_install("txtLabel"), curLab);
                UNPROTECT(1);
            }

            SET_ELEMENT(outList, curEle++, curEP);
            UNPROTECT(2);
            edge = agnxtout(g, edge);
        }
        node = agnxtnode(g, node);
    }
    UNPROTECT(1);

    return(outList);
}
Пример #13
0
SEXP getNodeLayouts(Agraph_t *g) {
    Agnode_t *node;
    SEXP outLst, nlClass, xyClass, curXY, curNL;
    SEXP curLab, labClass;
    int i, nodes;
    char *tmpString;

    if (g == NULL) error("getNodeLayouts passed a NULL graph");

    nlClass = MAKE_CLASS("AgNode");
    xyClass = MAKE_CLASS("xyPoint");
    labClass = MAKE_CLASS("AgTextLabel");

    /* tmpString is used to convert a char to a char* w/ labels */
    tmpString = (char *)R_alloc(2, sizeof(char));
    if (tmpString == NULL) error("Allocation error in getNodeLayouts");

    nodes = agnnodes(g);
    node = agfstnode(g);

    PROTECT(outLst = allocVector(VECSXP, nodes));

    for (i = 0; i < nodes; i++) {
        PROTECT(curNL = NEW_OBJECT(nlClass));
        PROTECT(curXY = NEW_OBJECT(xyClass));
        SET_SLOT(curXY,Rf_install("x"),Rf_ScalarInteger(node->u.coord.x));
        SET_SLOT(curXY,Rf_install("y"),Rf_ScalarInteger(node->u.coord.y));
        SET_SLOT(curNL,Rf_install("center"),curXY);
        SET_SLOT(curNL,Rf_install("height"),Rf_ScalarInteger(node->u.ht));
        SET_SLOT(curNL,Rf_install("rWidth"),Rf_ScalarInteger(node->u.rw));
        SET_SLOT(curNL,Rf_install("lWidth"),Rf_ScalarInteger(node->u.lw));
        SET_SLOT(curNL,Rf_install("name"), Rgraphviz_ScalarStringOrNull(node->name));

        SET_SLOT(curNL, Rf_install("color"), Rgraphviz_ScalarStringOrNull(agget(node, "color")));
        SET_SLOT(curNL, Rf_install("fillcolor"), Rgraphviz_ScalarStringOrNull(agget(node, "fillcolor")));
        SET_SLOT(curNL, Rf_install("shape"), Rgraphviz_ScalarStringOrNull(agget(node, "shape")));
        SET_SLOT(curNL, Rf_install("style"), Rgraphviz_ScalarStringOrNull(agget(node, "style")));

        PROTECT(curLab = NEW_OBJECT(labClass));

	if (ND_label(node)  == NULL) {
	} else if (ND_label(node)->u.txt.para != NULL) {
            SET_SLOT(curLab, Rf_install("labelText"),
                     Rgraphviz_ScalarStringOrNull(ND_label(node)->u.txt.para->str));
            snprintf(tmpString, 2, "%c",ND_label(node)->u.txt.para->just);
            SET_SLOT(curLab, Rf_install("labelJust"), Rgraphviz_ScalarStringOrNull(tmpString));

            SET_SLOT(curLab, Rf_install("labelWidth"),
                     Rf_ScalarInteger(ND_label(node)->u.txt.para->width));
            /* Get the X/Y location of the label */
            PROTECT(curXY = NEW_OBJECT(xyClass));
#if GRAPHVIZ_MAJOR == 2 && GRAPHVIZ_MINOR > 20
	    SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(ND_label(node)->pos.x));
	    SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(ND_label(node)->pos.y));
#else
            SET_SLOT(curXY, Rf_install("x"), Rf_ScalarInteger(node->u.label->p.x));
            SET_SLOT(curXY, Rf_install("y"), Rf_ScalarInteger(node->u.label->p.y));
#endif
            SET_SLOT(curLab, Rf_install("labelLoc"), curXY);
            UNPROTECT(1);

            SET_SLOT(curLab, Rf_install("labelColor"), Rgraphviz_ScalarStringOrNull(node->u.label->fontcolor));

            SET_SLOT(curLab, Rf_install("labelFontsize"), Rf_ScalarReal(node->u.label->fontsize));

        }

        SET_SLOT(curNL, Rf_install("txtLabel"), curLab);

        SET_ELEMENT(outLst, i, curNL);
        node = agnxtnode(g,node);

        UNPROTECT(3);
    }
    UNPROTECT(1);
    return(outLst);
}
Пример #14
0
static void end_edgestmt(void)
{
	objstack_t	*old_SP;
	objlist_t	*tailptr,*headptr,*freeptr;
	Agraph_t		*t_graph,*h_graph;
	Agnode_t	*t_node,*h_node,*t_first,*h_first;
	Agedge_t	*e;
	char		*tport,*hport;

	for (tailptr = SP->list; tailptr->link; tailptr = tailptr->link) {
		headptr = tailptr->link;
		tport = tailptr->data.port;
		hport = headptr->data.port;
		if (TAG_OF(tailptr->data.obj) == TAG_NODE) {
			t_graph = NULL;
			t_first = (Agnode_t*)(tailptr->data.obj);
		}
		else {
			t_graph = (Agraph_t*)(tailptr->data.obj);
			t_first = agfstnode(t_graph);
		}
		if (TAG_OF(headptr->data.obj) == TAG_NODE) {
			h_graph = NULL;
			h_first = (Agnode_t*)(headptr->data.obj);
		}
		else {
			h_graph = (Agraph_t*)(headptr->data.obj);
			h_first = agfstnode(h_graph);
		}

		for (t_node = t_first; t_node; t_node = t_graph ?
		  agnxtnode(t_graph,t_node) : NULL) {
			for (h_node = h_first; h_node; h_node = h_graph ?
			  agnxtnode(h_graph,h_node) : NULL ) {
				e = agedge(G,t_node,h_node);
				if (e) {
					char	*tp = tport;
					char 	*hp = hport;
					if ((e->tail != e->head) && (e->head == t_node)) {
						/* could happen with an undirected edge */
						char 	*temp;
						temp = tp; tp = hp; hp = temp;
					}
					if (tp && tp[0]) agxset(e,TAILX,tp);
					if (hp && hp[0]) agxset(e,HEADX,hp);
				}
			}
		}
	}
	tailptr = SP->list; 
	while (tailptr) {
		freeptr = tailptr;
		tailptr = tailptr->link;
		if (TAG_OF(freeptr->data.obj) == TAG_NODE)
		free(freeptr->data.port);
		free(freeptr);
	}
	if (G != SP->subg) abort();
	agpopproto(G);
	In_edge_stmt = SP->in_edge_stmt;
	old_SP = SP;
	SP = SP->link;
	In_decl = FALSE;
	free(old_SP);
	Current_class = TAG_GRAPH;
}
Пример #15
0
xbt_dynar_t SD_dotload_generic(const char * filename, seq_par_t seq_or_par, bool schedule){
  xbt_assert(filename, "Unable to use a null file descriptor\n");
  FILE *in_file = fopen(filename, "r");
  xbt_assert(in_file != nullptr, "Failed to open file: %s", filename);

  unsigned int i;
  SD_task_t root;
  SD_task_t end;
  SD_task_t task;
  xbt_dict_t computers;
  xbt_dynar_t computer = nullptr;
  xbt_dict_cursor_t dict_cursor;
  bool schedule_success = true;

  xbt_dict_t jobs = xbt_dict_new_homogeneous(nullptr);
  xbt_dynar_t result = xbt_dynar_new(sizeof(SD_task_t), dot_task_p_free);

  Agraph_t * dag_dot = agread(in_file, NIL(Agdisc_t *));

  if (schedule)
    computers = xbt_dict_new_homogeneous(nullptr);

  /* Create all the nodes */
  Agnode_t *node = nullptr;
  for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) {
    char *name = agnameof(node);
    double amount = atof(agget(node, (char*)"size"));
    task = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, name));
    if (task == nullptr) {
      if (seq_or_par == sequential){
        XBT_DEBUG("See <job id=%s amount =%.0f>", name, amount);
        task = SD_task_create_comp_seq(name, nullptr , amount);
      } else {
        double alpha = atof(agget(node, (char *) "alpha"));
        XBT_DEBUG("See <job id=%s amount =%.0f alpha = %.3f>", name, amount, alpha);
        task = SD_task_create_comp_par_amdahl(name, nullptr , amount, alpha);
      }

      xbt_dict_set(jobs, name, task, nullptr);

      if (strcmp(name,"root") && strcmp(name,"end"))
        xbt_dynar_push(result, &task);

      if((seq_or_par == sequential) &&
        ((schedule && schedule_success) || XBT_LOG_ISENABLED(sd_dotparse, xbt_log_priority_verbose))){
        /* try to take the information to schedule the task only if all is right*/
        char *char_performer = agget(node, (char *) "performer");
        char *char_order = agget(node, (char *) "order");
        /* Tasks will execute on in a given "order" on a given set of "performer" hosts */
        int performer = ((!char_performer || !strcmp(char_performer,"")) ? -1:atoi(char_performer));
        int order = ((!char_order || !strcmp(char_order, ""))? -1:atoi(char_order));

        if((performer != -1 && order != -1) && performer < (int) sg_host_count()){
          /* required parameters are given and less performers than hosts are required */
          XBT_DEBUG ("Task '%s' is scheduled on workstation '%d' in position '%d'", task->name, performer, order);
          if(!(computer = (xbt_dynar_t) xbt_dict_get_or_null(computers, char_performer))){
            computer = xbt_dynar_new(sizeof(SD_task_t), nullptr);
            xbt_dict_set(computers, char_performer, computer, nullptr);
          }

          if((unsigned int)order < xbt_dynar_length(computer)){
            SD_task_t *task_test = (SD_task_t *)xbt_dynar_get_ptr(computer,order);
            if(*task_test && *task_test != task){
              /* the user gave the same order to several tasks */
              schedule_success = false;
              XBT_VERB("Task '%s' wants to start on performer '%s' at the same position '%s' as task '%s'",
                       (*task_test)->name, char_performer, char_order, task->name);
              continue;
            }
          }
          /* the parameter seems to be ok */
          xbt_dynar_set_as(computer, order, SD_task_t, task);
        } else {
          /* one of required parameters is not given */
          schedule_success = false;
          XBT_VERB("The schedule is ignored, task '%s' can not be scheduled on %d hosts", task->name, performer);
        }
      }
    } else {
      XBT_WARN("Task '%s' is defined more than once", name);
    }
  }

  /*Check if 'root' and 'end' nodes have been explicitly declared.  If not, create them. */
  if (!(root = (SD_task_t)xbt_dict_get_or_null(jobs, "root")))
    root = (seq_or_par == sequential?SD_task_create_comp_seq("root", nullptr, 0):
                                     SD_task_create_comp_par_amdahl("root", nullptr, 0, 0));

  SD_task_set_state(root, SD_SCHEDULABLE);   /* by design the root task is always SCHEDULABLE */
  xbt_dynar_insert_at(result, 0, &root);     /* Put it at the beginning of the dynar */

  if (!(end = (SD_task_t)xbt_dict_get_or_null(jobs, "end")))
    end = (seq_or_par == sequential?SD_task_create_comp_seq("end", nullptr, 0):
                                    SD_task_create_comp_par_amdahl("end", nullptr, 0, 0));

  /* Create edges */
  xbt_dynar_t edges = xbt_dynar_new(sizeof(Agedge_t*), nullptr);
  for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) {
    Agedge_t * edge;
    xbt_dynar_reset(edges);
    for (edge = agfstout(dag_dot, node); edge; edge = agnxtout(dag_dot, edge))
      xbt_dynar_push_as(edges, Agedge_t *, edge);

    /* Be sure edges are sorted */
    xbt_dynar_sort(edges, edge_compare);

    xbt_dynar_foreach(edges, i, edge) {
      char *src_name=agnameof(agtail(edge)), *dst_name=agnameof(aghead(edge));
      double size = atof(agget(edge, (char *) "size"));

      SD_task_t src = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, src_name));
      SD_task_t dst = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, dst_name));

      if (size > 0) {
        char *name = bprintf("%s->%s", src_name, dst_name);
        XBT_DEBUG("See <transfer id=%s amount = %.0f>", name, size);
        task = static_cast<SD_task_t>(xbt_dict_get_or_null(jobs, name));
        if (task == nullptr) {
          if (seq_or_par == sequential)
            task = SD_task_create_comm_e2e(name, nullptr , size);
          else
            task = SD_task_create_comm_par_mxn_1d_block(name, nullptr , size);
          SD_task_dependency_add(nullptr, nullptr, src, task);
          SD_task_dependency_add(nullptr, nullptr, task, dst);
          xbt_dict_set(jobs, name, task, nullptr);
          xbt_dynar_push(result, &task);
        } else {
          XBT_WARN("Task '%s' is defined more than once", name);
        }
        xbt_free(name);
      } else {
        SD_task_dependency_add(nullptr, nullptr, src, dst);
      }
    }
  }
Пример #16
0
Agnode_t *firstnode(Agraph_t *g)
{
    if (!g)
        return NULL;
    return agfstnode(g);
}
Пример #17
0
/* _write_plain:
 */
void write_plain(GVJ_t * job, graph_t * g, FILE * f, boolean extend)
{
    int i, j, splinePoints;
    char *tport, *hport;
    node_t *n;
    edge_t *e;
    bezier bz;
    pointf pt;
    char *lbl;
    char* fillcolor;

    putstr = g->clos->disc.io->putstr;
//    setup_graph(job, g);
    setYInvert(g);
    pt = GD_bb(g).UR;
    printdouble(f, "graph ", job->zoom);
    printdouble(f, " ", PS2INCH(pt.x));
    printdouble(f, " ", PS2INCH(pt.y));
    agputc('\n', f);
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
        if (IS_CLUST_NODE(n))
            continue;
        printstring(f, "node ", agcanonStr(agnameof(n)));
        printpoint(f, ND_coord(n));
        if (ND_label(n)->html)   /* if html, get original text */
            lbl = agcanonStr (agxget(n, N_label));
        else
            lbl = canon(agraphof(n),ND_label(n)->text);
        printdouble(f, " ", ND_width(n));
        printdouble(f, " ", ND_height(n));
        printstring(f, " ", lbl);
        printstring(f, " ", late_nnstring(n, N_style, "solid"));
        printstring(f, " ", ND_shape(n)->name);
        printstring(f, " ", late_nnstring(n, N_color, DEFAULT_COLOR));
        fillcolor = late_nnstring(n, N_fillcolor, "");
        if (fillcolor[0] == '\0')
            fillcolor = late_nnstring(n, N_color, DEFAULT_FILL);
        printstring(f, " ", fillcolor);
        agputc('\n', f);
    }
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
        for (e = agfstout(g, n); e; e = agnxtout(g, e)) {

            if (extend) {		//assuming these two attrs have already been created by cgraph
                if (!(tport = agget(e,"tailport")))
                    tport = "";
                if (!(hport = agget(e,"headport")))
                    hport = "";
            }
            else
                tport = hport = "";
            if (ED_spl(e)) {
                splinePoints = 0;
                for (i = 0; i < ED_spl(e)->size; i++) {
                    bz = ED_spl(e)->list[i];
                    splinePoints += bz.size;
                }
                printstring(f, NULL, "edge");
                writenodeandport(f, agtail(e), tport);
                writenodeandport(f, aghead(e), hport);
                printint(f, " ", splinePoints);
                for (i = 0; i < ED_spl(e)->size; i++) {
                    bz = ED_spl(e)->list[i];
                    for (j = 0; j < bz.size; j++)
                        printpoint(f, bz.list[j]);
                }
            }
            if (ED_label(e)) {
                printstring(f, " ", canon(agraphof(agtail(e)),ED_label(e)->text));
                printpoint(f, ED_label(e)->pos);
            }
            printstring(f, " ", late_nnstring(e, E_style, "solid"));
            printstring(f, " ", late_nnstring(e, E_color, DEFAULT_COLOR));
            agputc('\n', f);
        }
    }
    agputs("stop\n", f);
}
Пример #18
0
/* 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]);
}