コード例 #1
0
ファイル: utils.c プロジェクト: BestSean2016/graphviz
static void undoCompound(edge_t * e, graph_t * clg)
{
    node_t *t = agtail(e);
    node_t *h = aghead(e);
    node_t *ntail;
    node_t *nhead;
    edge_t* ce;

    if (!(IS_CLUST_NODE(t) || IS_CLUST_NODE(h)))
	return;
    ntail = mapN(t, clg);
    nhead = mapN(h, clg);
    ce = cloneEdge(e, ntail, nhead);

    /* transfer drawing information */
    ED_spl(ce) = ED_spl(e);
    ED_spl(e) = NULL;
    ED_label(ce) = ED_label(e);
    ED_label(e) = NULL;
    ED_xlabel(ce) = ED_xlabel(e);
    ED_xlabel(e) = NULL;
    ED_head_label(ce) = ED_head_label(e);
    ED_head_label(e) = NULL;
    ED_tail_label(ce) = ED_tail_label(e);
    ED_tail_label(e) = NULL;
    gv_cleanup_edge(e);
}
コード例 #2
0
ファイル: postproc.c プロジェクト: AhmedAMohamed/graphviz
static void map_edge(edge_t * e)
{
    int j, k;
    bezier bz;

    if (ED_spl(e) == NULL) {
	if ((Concentrate == FALSE) && (ED_edge_type(e) != IGNORED))
	    agerr(AGERR, "lost %s %s edge\n", agnameof(agtail(e)),
		  agnameof(aghead(e)));
	return;
    }
    for (j = 0; j < ED_spl(e)->size; j++) {
	bz = ED_spl(e)->list[j];
	for (k = 0; k < bz.size; k++)
	    bz.list[k] = map_point(bz.list[k]);
	if (bz.sflag)
	    ED_spl(e)->list[j].sp = map_point(ED_spl(e)->list[j].sp);
	if (bz.eflag)
	    ED_spl(e)->list[j].ep = map_point(ED_spl(e)->list[j].ep);
    }
    if (ED_label(e))
	ED_label(e)->pos = map_point(ED_label(e)->pos);
    if (ED_xlabel(e))
	ED_xlabel(e)->pos = map_point(ED_xlabel(e)->pos);
    /* vladimir */
    if (ED_head_label(e))
	ED_head_label(e)->pos = map_point(ED_head_label(e)->pos);
    if (ED_tail_label(e))
	ED_tail_label(e)->pos = map_point(ED_tail_label(e)->pos);
}
コード例 #3
0
ファイル: utils.c プロジェクト: Goettsch/game-editor
/* 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;
}
コード例 #4
0
ファイル: neatoinit.c プロジェクト: Chaduke/bah.mod
void neato_free_splines(edge_t * e)
{
    int i;
    if (ED_spl(e)) {
	for (i = 0; i < ED_spl(e)->size; i++)
	    free(ED_spl(e)->list[i].list);
	free(ED_spl(e)->list);
	free(ED_spl(e));
    }
    ED_spl(e) = NULL;
}
コード例 #5
0
ファイル: QGVEdge.cpp プロジェクト: mylxiaoyi/gazebo
void QGVEdge::updateLayout()
{
    prepareGeometryChange();

    qreal gheight = QGVCore::graphHeight(_scene->_graph->graph());

    const splines* spl = ED_spl(_edge->edge());
    _path = QGVCore::toPath(spl, gheight);


    //Edge arrows
    if((spl->list != 0) && (spl->list->size%3 == 1))
    {
        if(spl->list->sflag)
        {
            _tail_arrow = toArrow(
                QLineF(QGVCore::toPoint(spl->list->list[0], gheight),
                QGVCore::toPoint(spl->list->sp, gheight)));
        }

        if(spl->list->eflag)
        {
            _head_arrow = toArrow(
                QLineF(QGVCore::toPoint(spl->list->list[spl->list->size-1],
                gheight), QGVCore::toPoint(spl->list->ep, gheight)));
        }
    }

    _pen.setWidth(1);

    _pen.setColor(this->edgeColor);
    _pen.setStyle(QGVCore::toPenStyle(getAttribute("style")));

    // Edge label
    textlabel_t *xlabel = ED_xlabel(_edge->edge());
    if(xlabel)
    {
        _label = xlabel->text;
        _label_rect.setSize(QSize(xlabel->dimen.x, xlabel->dimen.y));
        _label_rect.moveCenter(QGVCore::toPoint(xlabel->pos,
            QGVCore::graphHeight(_scene->_graph->graph())));
    }

    setToolTip(getAttribute("tooltip"));
}
コード例 #6
0
ファイル: gvitems.cpp プロジェクト: ABRG-Models/SpineCreator
QPointF GVEdge::getGVEdgeSplinesEndPoint()
{
    QPointF spline = QPointF(ED_spl(this->gv_edge)->list->ep.x,
                             GD_bb(this->layout->getGVGraph()).UR.y - ED_spl(this->gv_edge)->list->ep.y);
    return spline;
}
コード例 #7
0
ファイル: gvitems.cpp プロジェクト: ABRG-Models/SpineCreator
int GVEdge::getGVEdgeSplinesCount()
{
    return ED_spl(this->gv_edge)->list->size;
}
コード例 #8
0
ファイル: output.c プロジェクト: Chaduke/bah.mod
/* _write_plain:
 */
void write_plain(GVJ_t * job, graph_t * g, FILE * f, bool extend)
{
    int i, j, splinePoints;
    char *tport, *hport;
    node_t *n;
    edge_t *e;
    bezier bz;
    point pt;
    char *lbl;

//    setup_graph(job, g);
    setYInvert(g);
    pt = GD_bb(g).UR;
    fprintf(f, "graph %.3f %.3f %.3f\n", job->zoom, PS2INCH(pt.x), PS2INCH(pt.y));
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (IS_CLUST_NODE(n))
	    continue;
	fprintf(f, "node %s ", agcanonical(n->name));
	printptf(f, ND_coord_i(n));
	if (ND_label(n)->html)   /* if html, get original text */
	    lbl = agxget(n, N_label->index);
	else
	    lbl = ND_label(n)->text;
	if (lbl)
	    lbl = agcanonical(lbl);
	else
	    lbl = "\"\"";
	fprintf(f, " %.3f %.3f %s %s %s %s %s\n",
		ND_width(n), ND_height(n), lbl,
		late_nnstring(n, N_style, "solid"),
		ND_shape(n)->name,
		late_nnstring(n, N_color, DEFAULT_COLOR),
		late_nnstring(n, N_fillcolor, DEFAULT_FILL));
    }
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
	    if (extend && e->attr) {
		tport = e->attr[TAILX];
		hport = e->attr[HEADX];
	    } 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;
		}
		fprintf(f, "edge ");
		writenodeandport(f, e->tail, tport);
		fprintf(f, " ");
		writenodeandport(f, e->head, hport);
		fprintf(f, " %d", splinePoints);
		for (i = 0; i < ED_spl(e)->size; i++) {
		    bz = ED_spl(e)->list[i];
		    for (j = 0; j < bz.size; j++)
			printptf(f, bz.list[j]);
		}
	    }
	    if (ED_label(e)) {
		fprintf(f, " %s", agcanonical(ED_label(e)->text));
		printptf(f, ED_label(e)->p);
	    }
	    fprintf(f, " %s %s\n", late_nnstring(e, E_style, "solid"),
		    late_nnstring(e, E_color, DEFAULT_COLOR));
	}
    }
    fprintf(f, "stop\n");
}
コード例 #9
0
ファイル: output.c プロジェクト: Chaduke/bah.mod
void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep)
{
    int e_arrows;		/* graph has edges with end arrows */
    int s_arrows;		/* graph has edges with start arrows */
    int i, j, sides;
    char buf[BUFSIZ];		/* Used only for small strings */
    unsigned char xbuffer[BUFSIZ];	/* Initial buffer for xb */
    agxbuf xb;
    node_t *n;
    edge_t *e;
    point pt;

    e_arrows = s_arrows = 0;
    setYInvert(g);
    agxbinit(&xb, BUFSIZ, xbuffer);
    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 (GD_has_labels(g) & EDGE_LABEL)
	safe_dcl(g, g->proto->e, "lp", "", agedgeattr);
    if (GD_has_labels(g) & HEAD_LABEL)
	safe_dcl(g, g->proto->e, "head_lp", "", agedgeattr);
    if (GD_has_labels(g) & TAIL_LABEL)
	safe_dcl(g, g->proto->e, "tail_lp", "", agedgeattr);
    if (GD_label(g)) {
	safe_dcl(g, g, "lp", "", agraphattr);
	if (GD_label(g)->text[0]) {
	    pt = GD_label(g)->p;
	    sprintf(buf, "%d,%d", pt.x, YDIR(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", ND_coord_i(n).x, YDIR(ND_coord_i(n).y));
	agset(n, "pos", buf);
	sprintf(buf, "%.2f", PS2INCH(ND_ht_i(n)));
	agxset(n, N_height->index, buf);
	sprintf(buf, "%.2f", PS2INCH(ND_lw_i(n) + ND_rw_i(n)));
	agxset(n, N_width->index, buf);
	if (strcmp(ND_shape(n)->name, "record") == 0) {
	    set_record_rects(n, ND_shape_info(n), &xb);
	    agxbpop(&xb);	/* get rid of last space */
	    agset(n, "rects", agxbuse(&xb));
	} else {
	    polygon_t *poly;
	    int i;
	    if (N_vertices && isPolygon(n)) {
		poly = (polygon_t *) ND_shape_info(n);
		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)
			agxbputc(&xb, ' ');
		    if (poly->sides >= 3)
			sprintf(buf, "%.3f %.3f",
				PS2INCH(poly->vertices[i].x),
				YFDIR(PS2INCH(poly->vertices[i].y)));
		    else
			sprintf(buf, "%.3f %.3f",
				ND_width(n) / 2.0 * cos(i /
							(double) sides *
							PI * 2.0),
				YFDIR(ND_height(n) / 2.0 *
				   sin(i / (double) sides * PI * 2.0)));
		    agxbput(&xb, buf);
		}
		agxset(n, N_vertices->index, agxbuse(&xb));
	    }
	}
	if (State >= GVSPLINES) {
	    for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
		if (ED_edge_type(e) == IGNORED)
		    continue;
		if (ED_spl(e) == NULL)
		    continue;	/* reported in postproc */
		for (i = 0; i < ED_spl(e)->size; i++) {
		    if (i > 0)
			agxbputc(&xb, ';');
		    if (ED_spl(e)->list[i].sflag) {
			s_arrows = 1;
			sprintf(buf, "s,%d,%d ",
				ED_spl(e)->list[i].sp.x,
				YDIR(ED_spl(e)->list[i].sp.y));
			agxbput(&xb, buf);
		    }
		    if (ED_spl(e)->list[i].eflag) {
			e_arrows = 1;
			sprintf(buf, "e,%d,%d ",
				ED_spl(e)->list[i].ep.x,
				YDIR(ED_spl(e)->list[i].ep.y));
			agxbput(&xb, buf);
		    }
		    for (j = 0; j < ED_spl(e)->list[i].size; j++) {
			if (j > 0)
			    agxbputc(&xb, ' ');
			pt = ED_spl(e)->list[i].list[j];
			sprintf(buf, "%d,%d", pt.x, YDIR(pt.y));
			agxbput(&xb, buf);
		    }
		}
		agset(e, "pos", agxbuse(&xb));
		if (ED_label(e)) {
		    pt = ED_label(e)->p;
		    sprintf(buf, "%d,%d", pt.x, YDIR(pt.y));
		    agset(e, "lp", buf);
		}
		if (ED_head_label(e)) {
		    pt = ED_head_label(e)->p;
		    sprintf(buf, "%d,%d", pt.x, YDIR(pt.y));
		    agset(e, "head_lp", buf);
		}
		if (ED_tail_label(e)) {
		    pt = ED_tail_label(e)->p;
		    sprintf(buf, "%d,%d", pt.x, YDIR(pt.y));
		    agset(e, "tail_lp", buf);
		}
	    }
	}
    }
    rec_attach_bb(g);
    agxbfree(&xb);

    if (HAS_CLUST_EDGE(g))
	undoClusterEdges(g);
    
    *sp = s_arrows;
    *ep = e_arrows;
}
コード例 #10
0
ファイル: ortho.c プロジェクト: TidyHuang/vizgems
/* 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
    if (doLbls) {
	agerr(AGWARN, "Orthogonal edges do not currently handle edge labels. Try using xlabels.\n");
	doLbls = 0;
    }
    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);
	    }
       	    if (shortPath (sg, dn, sn)) goto orthofinish;
	}
	    
       	route_list[i] = convertSPtoRoute(sg, sn, dn);
       	reset (sg);
    }
    PQfree ();

    mp->hchans = extractHChans (mp);
    mp->vchans = extractVChans (mp);
    assignSegs (n_edges, route_list, mp);
    if (setjmp(jbuf))
	goto orthofinish;
    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);

orthofinish:
    if (Concentrate)
	freePS (ps);

    for (i=0; i < n_edges; i++)
	free (route_list[i].segs);
    free (route_list);
    freeMaze (mp);
}
コード例 #11
0
ファイル: output.c プロジェクト: wrigleyster/graphviz
void attach_attrs_and_arrows(graph_t* g, int* sp, int* ep)
{
    int e_arrows;		/* graph has edges with end arrows */
    int s_arrows;		/* graph has edges with start arrows */
    int i, j, sides;
    char buf[BUFSIZ];		/* Used only for small strings */
    unsigned char xbuffer[BUFSIZ];	/* Initial buffer for xb */
    agxbuf xb;
    node_t *n;
    edge_t *e;
    pointf ptf;
    int dim3 = (GD_odim(g) >= 3);
    Agsym_t* bbsym;

    gv_fixLocale (1);
    e_arrows = s_arrows = 0;
    setYInvert(g);
    agxbinit(&xb, BUFSIZ, xbuffer);
    safe_dcl(g, AGNODE, "pos", "");
    safe_dcl(g, AGNODE, "rects", "");
    N_width = safe_dcl(g, AGNODE, "width", "");
    N_height = safe_dcl(g, AGNODE, "height", "");
    safe_dcl(g, AGEDGE, "pos", "");
    if (GD_has_labels(g) & NODE_XLABEL)
	safe_dcl(g, AGNODE, "xlp", "");
    if (GD_has_labels(g) & EDGE_LABEL)
	safe_dcl(g, AGEDGE, "lp", "");
    if (GD_has_labels(g) & EDGE_XLABEL)
	safe_dcl(g, AGEDGE, "xlp", "");
    if (GD_has_labels(g) & HEAD_LABEL)
	safe_dcl(g, AGEDGE, "head_lp", "");
    if (GD_has_labels(g) & TAIL_LABEL)
	safe_dcl(g, AGEDGE, "tail_lp", "");
    if (GD_label(g)) {
	safe_dcl(g, AGRAPH, "lp", "");
	safe_dcl(g, AGRAPH, "lwidth", "");
	safe_dcl(g, AGRAPH, "lheight", "");
	if (GD_label(g)->text[0]) {
	    ptf = GD_label(g)->pos;
	    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
	    agset(g, "lp", buf);
	    ptf = GD_label(g)->dimen;
	    sprintf(buf, "%.2f", PS2INCH(ptf.x));
	    agset(g, "lwidth", buf);
	    sprintf(buf, "%.2f", PS2INCH(ptf.y));
	    agset(g, "lheight", buf);
	}
    }
    bbsym = safe_dcl(g, AGRAPH, "bb", "");
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (dim3) {
	    int k;

	    sprintf(buf, "%.5g,%.5g,%.5g", ND_coord(n).x, YDIR(ND_coord(n).y), POINTS_PER_INCH*(ND_pos(n)[2]));
	    agxbput (&xb, buf);
	    for (k = 3; k < GD_odim(g); k++) {
		sprintf(buf, ",%.5g", POINTS_PER_INCH*(ND_pos(n)[k]));
		agxbput (&xb, buf);
	    }
	    agset(n, "pos", agxbuse(&xb));
	} else {
	    sprintf(buf, "%.5g,%.5g", ND_coord(n).x, YDIR(ND_coord(n).y));
	    agset(n, "pos", buf);
	}
	sprintf(buf, "%.5g", PS2INCH(ND_ht(n)));
	agxset(n, N_height, buf);
	sprintf(buf, "%.5g", PS2INCH(ND_lw(n) + ND_rw(n)));
	agxset(n, N_width, buf);
	if (ND_xlabel(n) && ND_xlabel(n)->set) {
	    ptf = ND_xlabel(n)->pos;
	    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
	    agset(n, "xlp", buf);
	}
	if (strcmp(ND_shape(n)->name, "record") == 0) {
	    set_record_rects(n, ND_shape_info(n), &xb);
	    agxbpop(&xb);	/* get rid of last space */
	    agset(n, "rects", agxbuse(&xb));
	} else {
	    polygon_t *poly;
	    int i;
	    if (N_vertices && isPolygon(n)) {
		poly = (polygon_t *) ND_shape_info(n);
		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)
			agxbputc(&xb, ' ');
		    if (poly->sides >= 3)
			sprintf(buf, "%.5g %.5g",
				PS2INCH(poly->vertices[i].x),
				YFDIR(PS2INCH(poly->vertices[i].y)));
		    else
			sprintf(buf, "%.5g %.5g",
				ND_width(n) / 2.0 * cos(i / (double) sides * M_PI * 2.0),
				YFDIR(ND_height(n) / 2.0 * sin(i / (double) sides * M_PI * 2.0)));
		    agxbput(&xb, buf);
		}
		agxset(n, N_vertices, agxbuse(&xb));
	    }
	}
	if (State >= GVSPLINES) {
	    for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
		if (ED_edge_type(e) == IGNORED)
		    continue;
		if (ED_spl(e) == NULL)
		    continue;	/* reported in postproc */
		for (i = 0; i < ED_spl(e)->size; i++) {
		    if (i > 0)
			agxbputc(&xb, ';');
		    if (ED_spl(e)->list[i].sflag) {
			s_arrows = 1;
			sprintf(buf, "s,%.5g,%.5g ",
				ED_spl(e)->list[i].sp.x,
				YDIR(ED_spl(e)->list[i].sp.y));
			agxbput(&xb, buf);
		    }
		    if (ED_spl(e)->list[i].eflag) {
			e_arrows = 1;
			sprintf(buf, "e,%.5g,%.5g ",
				ED_spl(e)->list[i].ep.x,
				YDIR(ED_spl(e)->list[i].ep.y));
			agxbput(&xb, buf);
		    }
		    for (j = 0; j < ED_spl(e)->list[i].size; j++) {
			if (j > 0)
			    agxbputc(&xb, ' ');
			ptf = ED_spl(e)->list[i].list[j];
			sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
			agxbput(&xb, buf);
		    }
		}
		agset(e, "pos", agxbuse(&xb));
		if (ED_label(e)) {
		    ptf = ED_label(e)->pos;
		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
		    agset(e, "lp", buf);
		}
		if (ED_xlabel(e) && ED_xlabel(e)->set) {
		    ptf = ED_xlabel(e)->pos;
		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
		    agset(e, "xlp", buf);
		}
		if (ED_head_label(e)) {
		    ptf = ED_head_label(e)->pos;
		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
		    agset(e, "head_lp", buf);
		}
		if (ED_tail_label(e)) {
		    ptf = ED_tail_label(e)->pos;
		    sprintf(buf, "%.5g,%.5g", ptf.x, YDIR(ptf.y));
		    agset(e, "tail_lp", buf);
		}
	    }
	}
    }
    rec_attach_bb(g, bbsym);
    agxbfree(&xb);

    if (HAS_CLUST_EDGE(g))
	undoClusterEdges(g);
    
    *sp = s_arrows;
    *ep = e_arrows;
    gv_fixLocale (0);
}
コード例 #12
0
ファイル: output.c プロジェクト: wrigleyster/graphviz
/* _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);
}
コード例 #13
0
ファイル: compound.c プロジェクト: emdenrg/graphviz
static void makeCompoundEdge(graph_t * g, edge_t * e)
#endif
{
    graph_t *lh;		/* cluster containing head */
    graph_t *lt;		/* cluster containing tail */
    bezier *bez;		/* original Bezier for e */
    bezier *nbez;		/* new Bezier  for e */
    int starti = 0, endi = 0;	/* index of first and last control point */
    node_t *head;
    node_t *tail;
    boxf *bb;
    int i, j;
    int size;
    pointf pts[4];
    pointf p;
    int fixed;

    /* find head and tail target clusters, if defined */
#ifdef WITH_CGRAPH
    lh = getCluster(g, agget(e, "lhead"), clustMap);
    lt = getCluster(g, agget(e, "ltail"), clustMap);
#else
    lh = getCluster(g, agget(e, "lhead"));
    lt = getCluster(g, agget(e, "ltail"));
#endif
    if (!lt && !lh)
	return;
    if (!ED_spl(e)) return;

    /* at present, we only handle single spline case */
    if (ED_spl(e)->size > 1) {
	agerr(AGWARN, "%s -> %s: spline size > 1 not supported\n",
	      agnameof(agtail(e)), agnameof(aghead(e)));
	return;
    }
    bez = ED_spl(e)->list;
    size = bez->size;

    head = aghead(e);
    tail = agtail(e);

    /* allocate new Bezier */
    nbez = GNEW(bezier);
    nbez->eflag = bez->eflag;
    nbez->sflag = bez->sflag;

    /* if Bezier has four points, almost collinear,
     * make line - unimplemented optimization?
     */

    /* If head cluster defined, find first Bezier
     * crossing head cluster, and truncate spline to
     * box edge.
     * Otherwise, leave end alone.
     */
    fixed = 0;
    if (lh) {
	bb = &(GD_bb(lh));
	if (!inBoxf(ND_coord(head), bb)) {
	    agerr(AGWARN, "%s -> %s: head not inside head cluster %s\n",
		  agnameof(agtail(e)), agnameof(aghead(e)), agget(e, "lhead"));
	} else {
	    /* If first control point is in bb, degenerate case. Spline
	     * reduces to four points between the arrow head and the point 
	     * where the segment between the first control point and arrow head 
	     * crosses box.
	     */
	    if (inBoxf(bez->list[0], bb)) {
		if (inBoxf(ND_coord(tail), bb)) {
		    agerr(AGWARN,
			  "%s -> %s: tail is inside head cluster %s\n",
			  agnameof(agtail(e)), agnameof(aghead(e)), agget(e, "lhead"));
		} else {
		    assert(bez->sflag);	/* must be arrowhead on tail */
		    p = boxIntersectf(bez->list[0], bez->sp, bb);
		    bez->list[3] = p;
		    bez->list[1] = mid_pointf(p, bez->sp);
		    bez->list[0] = mid_pointf(bez->list[1], bez->sp);
		    bez->list[2] = mid_pointf(bez->list[1], p);
		    if (bez->eflag)
			endi = arrowEndClip(e, bez->list,
					 starti, 0, nbez, bez->eflag);
		    endi += 3;
		    fixed = 1;
		}
	    } else {
		for (endi = 0; endi < size - 1; endi += 3) {
		    if (splineIntersectf(&(bez->list[endi]), bb))
			break;
		}
		if (endi == size - 1) {	/* no intersection */
		    assert(bez->eflag);
		    nbez->ep = boxIntersectf(bez->ep, bez->list[endi], bb);
		} else {
		    if (bez->eflag)
			endi =
			    arrowEndClip(e, bez->list,
					 starti, endi, nbez, bez->eflag);
		    endi += 3;
		}
		fixed = 1;
	    }
	}
    }
    if (fixed == 0) {		/* if no lh, or something went wrong, use original head */
	endi = size - 1;
	if (bez->eflag)
	    nbez->ep = bez->ep;
    }

    /* If tail cluster defined, find last Bezier
     * crossing tail cluster, and truncate spline to
     * box edge.
     * Otherwise, leave end alone.
     */
    fixed = 0;
    if (lt) {
	bb = &(GD_bb(lt));
	if (!inBoxf(ND_coord(tail), bb)) {
	    agerr(AGWARN, "%s -> %s: tail not inside tail cluster %s\n",
		agnameof(agtail(e)), agnameof(aghead(e)), agget(e, "ltail"));
	} else {
	    /* If last control point is in bb, degenerate case. Spline
	     * reduces to four points between arrow head, and the point
	     * where the segment between the last control point and the 
	     * arrow head crosses box.
	     */
	    if (inBoxf(bez->list[endi], bb)) {
		if (inBoxf(ND_coord(head), bb)) {
		    agerr(AGWARN,
			"%s -> %s: head is inside tail cluster %s\n",
		  	agnameof(agtail(e)), agnameof(aghead(e)), agget(e, "ltail"));
		} else {
		    assert(bez->eflag);	/* must be arrowhead on head */
		    p = boxIntersectf(bez->list[endi], nbez->ep, bb);
		    starti = endi - 3;
		    bez->list[starti] = p;
		    bez->list[starti + 2] = mid_pointf(p, nbez->ep);
		    bez->list[starti + 3] = mid_pointf(bez->list[starti + 2], nbez->ep);
		    bez->list[starti + 1] = mid_pointf(bez->list[starti + 2], p);
		    if (bez->sflag)
			starti = arrowStartClip(e, bez->list, starti,
				endi - 3, nbez, bez->sflag);
		    fixed = 1;
		}
	    } else {
		for (starti = endi; starti > 0; starti -= 3) {
		    for (i = 0; i < 4; i++)
			pts[i] = bez->list[starti - i];
		    if (splineIntersectf(pts, bb)) {
			for (i = 0; i < 4; i++)
			    bez->list[starti - i] = pts[i];
			break;
		    }
		}
		if (starti == 0) {
		    assert(bez->sflag);
		    nbez->sp =
			boxIntersectf(bez->sp, bez->list[starti], bb);
		} else {
		    starti -= 3;
		    if (bez->sflag)
			starti = arrowStartClip(e, bez->list, starti,
				endi - 3, nbez, bez->sflag);
		}
		fixed = 1;
	    }
	}
    }
    if (fixed == 0) {		/* if no lt, or something went wrong, use original tail */
	/* Note: starti == 0 */
	if (bez->sflag)
	    nbez->sp = bez->sp;
    }

    /* complete Bezier, free garbage and attach new Bezier to edge 
     */
    nbez->size = endi - starti + 1;
    nbez->list = N_GNEW(nbez->size, pointf);
    for (i = 0, j = starti; i < nbez->size; i++, j++)
	nbez->list[i] = bez->list[j];
    free(bez->list);
    free(bez);
    ED_spl(e)->list = nbez;
}
コード例 #14
0
ファイル: class-inherit.c プロジェクト: rosedu/anjuta
static void
cls_node_draw_edge (ClsNode *cls_node_to, ClsNodeEdge *cls_edge, ClsNode *cls_node_from)
{
	Agedge_t *edge;
	FooCanvasPoints *points;
	gint i, num_points;
	
	edge = cls_edge->agedge;
	num_points = ED_spl(edge)->list->size;
	points = foo_canvas_points_new(num_points + 1);
	
	for (i = 0; i < num_points; i++)
	{
		points->coords[2 * i] = ((ED_spl(edge))->list->list[i]).x;
		points->coords[2 * i + 1] = GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[i]).y);
	}

    /* Draw arrow destination point */
	
	/* Arrow end position */
	/* Sometimes, last 2 points overlap, resulting in failure to determine
	 * next point, track back until there is a usable pair of points.
	 */
	do
	{
		num_points--;
		
		/* starting point */
		points->coords[2 * i] = ((ED_spl(edge))->list->list[num_points]).x;
		points->coords[2 * i + 1] =
			GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[num_points]).y);
	
	}
	while (num_points > 0 &&
	       !create_canvas_edge_arrow_ending (((ED_spl(edge))->list->list[num_points - 1]).x,
			                                 GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[num_points - 1]).y),
			                                 ((ED_spl(edge))->list->list[num_points]).x,
			                                 GRAPH_TO_CANVAS_Y (((ED_spl(edge))->list->list[num_points]).y),
			                                 &points->coords[2 * i], &points->coords[2 * i + 1]));
	/* draw the line */
	if (cls_edge->canvas_line)
	{
		foo_canvas_item_set (cls_edge->canvas_line, "points", points, NULL);
	}
	else
	{
		cls_edge->canvas_line =
			foo_canvas_item_new (foo_canvas_root
			                     (FOO_CANVAS (cls_node_from->canvas)), 
			                     foo_canvas_line_get_type(),
			                     "smooth", TRUE,
			                     "last_arrowhead", TRUE,
			                     "arrow_shape_a", (gdouble) 8.0,
			                     "arrow_shape_b", (gdouble) 10.0,
			                     "arrow_shape_c", (gdouble) 3.0,
			                     "fill_color_gdk",
			                     &cls_node_from->plugin->style[STYLE_FG],
			                     "points", points,
			                     NULL);
		foo_canvas_item_lower_to_bottom (cls_edge->canvas_line);
	}
	foo_canvas_points_unref (points);
}
コード例 #15
0
ファイル: utils.c プロジェクト: jho1965us/graphviz
/* 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;
}
コード例 #16
0
ファイル: xdgen.c プロジェクト: Goettsch/game-editor
/* 
 * John M. suggests:
 * You might want to add four more:
 *
 * _ohdraw_ (optional head-end arrow for edges)
 * _ohldraw_ (optional head-end label for edges)
 * _otdraw_ (optional tail-end arrow for edges)
 * _otldraw_ (optional tail-end label for edges)
 * 
 * that would be generated when an additional option is supplied to 
 * dot, etc. and 
 * these would be the arrow/label positions to use if a user want to flip the 
 * direction of an edge (as sometimes is there want).
 * 
 * N.B. John M. asks:
 *   By the way, I don't know if you ever plan to add other letters for 
 * the xdot spec, but could you reserve "a" and also "A" (for  attribute), 
 * "n" and also "N" (for numeric), "w" (for sWitch),  "s" (for string) 
 * and "t" (for tooltip) and "x" (for position). We use  those letters in 
 * our drawing spec (and also "<" and ">"), so if you  start generating 
 * output with them, it could break what we have. 
 */
void extend_attrs(GVJ_t * job, graph_t *g, int s_arrows, int e_arrows)
{
    node_t *n;
    edge_t *e;
    attrsym_t *n_draw = NULL;
    attrsym_t *n_l_draw = NULL;
    attrsym_t *e_draw = NULL;
    attrsym_t *h_draw = NULL;
    attrsym_t *t_draw = NULL;
    attrsym_t *e_l_draw = NULL;
    attrsym_t *hl_draw = NULL;
    attrsym_t *tl_draw = NULL;
    unsigned char buf0[BUFSIZ];
    unsigned char buf1[BUFSIZ];
    unsigned char buf2[BUFSIZ];
    unsigned char buf3[BUFSIZ];
    unsigned char buf4[BUFSIZ];
    unsigned char buf5[BUFSIZ];

    gvc = job->gvc;

    agsafeset (g, "xdotversion", XDOTVERSION, "");
    if (GD_has_labels(g) & GRAPH_LABEL)
	g_l_draw = safe_dcl(g, g, "_ldraw_", "", agraphattr);
    else
	g_l_draw = NULL;
    if (GD_n_cluster(g))
	g_draw = safe_dcl(g, g, "_draw_", "", agraphattr);
    else
	g_draw = NULL;

    n_draw = safe_dcl(g, g->proto->n, "_draw_", "", agnodeattr);
    n_l_draw = safe_dcl(g, g->proto->n, "_ldraw_", "", agnodeattr);

    e_draw = safe_dcl(g, g->proto->e, "_draw_", "", agedgeattr);
    if (e_arrows)
	h_draw = safe_dcl(g, g->proto->e, "_hdraw_", "", agedgeattr);
    if (s_arrows)
	t_draw = safe_dcl(g, g->proto->e, "_tdraw_", "", agedgeattr);
    if (GD_has_labels(g) & EDGE_LABEL)
	e_l_draw = safe_dcl(g, g->proto->e, "_ldraw_", "", agedgeattr);
    if (GD_has_labels(g) & HEAD_LABEL)
	hl_draw = safe_dcl(g, g->proto->e, "_hldraw_", "", agedgeattr);
    if (GD_has_labels(g) & TAIL_LABEL)
	tl_draw = safe_dcl(g, g->proto->e, "_tldraw_", "", agedgeattr);

    agxbinit(&xbuf0, BUFSIZ, buf0);
    agxbinit(&xbuf1, BUFSIZ, buf1);
    agxbinit(&xbuf2, BUFSIZ, buf2);
    agxbinit(&xbuf3, BUFSIZ, buf3);
    agxbinit(&xbuf4, BUFSIZ, buf4);
    agxbinit(&xbuf5, BUFSIZ, buf5);

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (ND_shape(n) && !isInvis(late_string(n, N_style, ""))) {
	    ND_shape(n)->fns->codefn(job, n);
	    agxset(n, n_draw->index, agxbuse(xbufs[EMIT_NDRAW]));
	    agxset(n, n_l_draw->index, agxbuse(xbufs[EMIT_NLABEL]));
	}
	if (State < GVSPLINES)
	    continue;
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {
	    if (ED_edge_type(e) == IGNORED)
		continue;
	    if (isInvis(late_string(e, E_style, "")))
		continue;
	    if (ED_spl(e) == NULL)
		continue;

	    emit_edge_graphics (job, e);
	    agxset(e, e_draw->index, agxbuse(xbufs[EMIT_EDRAW]));
	    if (t_draw) agxset(e, t_draw->index, agxbuse(xbufs[EMIT_TDRAW]));
	    if (h_draw) agxset(e, h_draw->index, agxbuse(xbufs[EMIT_HDRAW]));
	    if (e_l_draw) agxset(e, e_l_draw->index,agxbuse(xbufs[EMIT_ELABEL]));
	    if (tl_draw) agxset(e, tl_draw->index, agxbuse(xbufs[EMIT_TLABEL]));
	    if (hl_draw) agxset(e, hl_draw->index, agxbuse(xbufs[EMIT_HLABEL]));
	}
    }
  
    emit_background(job, g);
    if (agxblen(xbufs[EMIT_GDRAW])) {
	if (!g_draw)
	    g_draw = safe_dcl(g, g, "_draw_", "", agraphattr);
	agxset(g, g_draw->index, agxbuse(xbufs[EMIT_GDRAW]));
    }
    if (GD_label(g)) {
	emit_label(job, EMIT_GLABEL, GD_label(g), (void *) g);
	agxset(g, g_l_draw->index, agxbuse(xbufs[EMIT_GLABEL]));
    }
    emit_clusters(job, g, 0);
    agxbfree(&xbuf0);
    agxbfree(&xbuf1);
    agxbfree(&xbuf2);
    agxbfree(&xbuf3);
    agxbfree(&xbuf4);
    agxbfree(&xbuf5);
}
コード例 #17
0
ファイル: ptest.c プロジェクト: AhmedAMohamed/graphviz
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);
	    }
	}
    }
}