コード例 #1
0
ファイル: actions.c プロジェクト: Goettsch/game-editor
/* copy:
 * Create new object of type AGTYPE(obj) with all of its
 * attributes.
 * If obj is an edge, only create end nodes if necessary.
 * If obj is a graph, if g is null, create a top-level
 * graph. Otherwise, create a subgraph of g.
 * Assume obj != NULL.
 */
Agobj_t *copy(Agraph_t * g, Agobj_t * obj)
{
    Agobj_t *nobj = 0;
    Agedge_t *e;
    Agnode_t *h;
    Agnode_t *t;
    int kind = AGTYPE(obj);
    char *name = agnameof(obj);

    if ((kind != AGRAPH) && !g) {
	error(ERROR_FATAL, "NULL graph with non-graph object in copy()");
	return 0;
    }

    switch (kind) {
    case AGNODE:
	nobj = (Agobj_t *) openNode(g, name);
	break;
    case AGRAPH:
	if (g)
	    nobj = (Agobj_t *) openSubg(g, name);
	else
	    nobj = (Agobj_t *) openG(name, ((Agraph_t *) obj)->desc);
	break;
    case AGEDGE:
	e = (Agedge_t *) obj;
	t = openNode(g, agnameof(agtail(e)));
	h = openNode(g, agnameof(aghead(e)));
	nobj = (Agobj_t *) openEdge(t, h, name);
	break;
    }
    if (nobj)
	copyAttr(obj, nobj);

    return nobj;
}
コード例 #2
0
ファイル: minc2.c プロジェクト: AhmedAMohamed/graphviz
static void add_node(Agraph_t * g, Agedge_t * e, int labels)
{
    /*find out how the ranks increase ,it may not always be from tail to head! */

    int rankDiff;
    int i;
    Agnode_t *tmpN;
    Agedge_t *tmpE;
    Agnode_t *tail;
    Agnode_t *head;
    Agraph_t *cluster = NULL;
    Agraph_t *tempC1 = NULL;
    Agraph_t *tempC2 = NULL;

    int type = INTNODE;

    head = aghead(e);
    tail = agtail(e);
#if 0
    if ((strcmp(agnameof(head), "T1") == 0)
	&& (strcmp(agnameof(tail), "23") == 0))
	fprintf(stderr, "found \n");
    if ((strcmp(agnameof(head), "23") == 0)
	&& (strcmp(agnameof(tail), "T1") == 0))
	fprintf(stderr, "found \n");
#endif

    /*check whether edge is a cluster */
    tempC1 = MND_highCluster(head);
    tempC2 = MND_highCluster(tail);

    if (tempC1 == tempC2)
	cluster = tempC1;

    rankDiff = MND_rank(head) - MND_rank(tail);
    if ((rankDiff == 1) || (rankDiff == -1))
	return;
    if (rankDiff == 0)
	return;

    if (rankDiff > 0)		/*expected */
	for (i = MND_rank(tail) + 1; i < MND_rank(head); i++) {

	    if (labels) {
		if (type == LBLNODE)
		    type = INTNODE;
		else
		    type = LBLNODE;
	    } else
		type = INTNODE;
	    tmpN = mkMCNode (g, type, (char *) 0);

	    MND_rank(tmpN) = i;
	    MND_type(tmpN) = type;
	    MND_highCluster(tmpN) = cluster;
	    MND_orderr(tmpN) = MND_orderr(tail);
	    /*create internal edge */
	    tmpE = mkMCEdge (g, tail, tmpN, 0, VIRTUAL, MED_orig(e));
	    tail = tmpN;
    } else
	for (i = MND_rank(tail) - 1; i > MND_rank(head); i--) {
	    if (labels) {
		if (type == LBLNODE)
		    type = INTNODE;
		else
		    type = LBLNODE;
	    } else
		type = INTNODE;
	    tmpN = mkMCNode (g, type, (char *) 0);

	    MND_rank(tmpN) = i;
	    MND_type(tmpN) = type;
	    MND_highCluster(tmpN) = cluster;
	    /*create internal edge */
	    tmpE = mkMCEdge (g, tail, tmpN, 0, VIRTUAL, MED_orig(e));
	    tail = tmpN;
	}
    tmpE = mkMCEdge (g, tail, head, 0, VIRTUAL, MED_orig(e));
    /*mark the long edge for deletion */
    MED_deleteFlag(e) = 1;
}
コード例 #3
0
ファイル: routespl.c プロジェクト: CharlieSa/livizjs
static pointf *_routesplines(path * pp, int *npoints, int polyline)
{
    Ppoly_t poly;
    Ppolyline_t pl, spl;
    int splinepi;
    Ppoint_t eps[2];
    Pvector_t evs[2];
    int edgei, prev, next;
    pointf sp[4];
    int pi, bi, si;
    double t;
    boxf *boxes;
    int boxn;
    edge_t* realedge;
    int flip;
    int delta = 10;

    nedges++;
    nboxes += pp->nbox;

    for (realedge = (edge_t *) pp->data;
#ifdef NOTNOW
	 origedge = realedge;
#endif
	 realedge && ED_edge_type(realedge) != NORMAL;
	 realedge = ED_to_orig(realedge));
    if (!realedge) {
	agerr(AGERR, "in routesplines, cannot find NORMAL edge\n");
	abort();
    }

    boxes = pp->boxes;
    boxn = pp->nbox;

    checkpath(boxn, boxes, pp);

#ifdef DEBUG
    if (debugleveln(realedge, 1))
	printboxes(boxn, boxes);
    if (debugleveln(realedge, 3)) {
	psprintinit(1);
	psprintboxes(boxn, boxes);
    }
#endif

    if (boxn * 8 > polypointn) {
	polypoints = ALLOC(boxn * 8, polypoints, Ppoint_t);
	polypointn = boxn * 8;
    }

    if ((boxn > 1) && (boxes[0].LL.y > boxes[1].LL.y)) {
        flip = 1;
	for (bi = 0; bi < boxn; bi++) {
	    double v = boxes[bi].UR.y;
	    boxes[bi].UR.y = -1*boxes[bi].LL.y;
	    boxes[bi].LL.y = -v;
	}
    }
    else flip = 0;

    if (agtail(realedge) != aghead(realedge)) {
	/* I assume that the path goes either down only or
	   up - right - down */
	for (bi = 0, pi = 0; bi < boxn; bi++) {
	    next = prev = 0;
	    if (bi > 0)
		prev = (boxes[bi].LL.y > boxes[bi - 1].LL.y) ? -1 : 1;
	    if (bi < boxn - 1)
		next = (boxes[bi + 1].LL.y > boxes[bi].LL.y) ? 1 : -1;
	    if (prev != next) {
		if (next == -1 || prev == 1) {
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		} else {
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		}
	    }
	    else if (prev == 0) { /* single box */
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].UR.y;
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].LL.y;
	    } 
	    else {
		if (!(prev == -1 && next == -1))
		    abort();
	    }
	}
	for (bi = boxn - 1; bi >= 0; bi--) {
	    next = prev = 0;
	    if (bi < boxn - 1)
		prev = (boxes[bi].LL.y > boxes[bi + 1].LL.y) ? -1 : 1;
	    if (bi > 0)
		next = (boxes[bi - 1].LL.y > boxes[bi].LL.y) ? 1 : -1;
	    if (prev != next) {
		if (next == -1 || prev == 1 ) {
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		} else {
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		}
	    } 
	    else if (prev == 0) { /* single box */
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].LL.y;
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].UR.y;
	    }
	    else {
		if (!(prev == -1 && next == -1)) {
		    /* it went badly, e.g. degenerate box in boxlist */
		    *npoints = 0;
		    abort();	/* for correctness sake, it's best to just stop */
		    return ps;	/* could also be reported as a lost edge (no spline) */
		}
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].LL.y;
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].UR.y;
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].UR.y;
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].LL.y;
	    }
	}
    }
    else {
	abort();
    }

    if (flip) {
	int i;
	for (bi = 0; bi < boxn; bi++) {
	    int v = boxes[bi].UR.y;
	    boxes[bi].UR.y = -1*boxes[bi].LL.y;
	    boxes[bi].LL.y = -v;
	}
	for (i = 0; i < pi; i++)
	    polypoints[i].y *= -1;
    }

    for (bi = 0; bi < boxn; bi++)
	boxes[bi].LL.x = INT_MAX, boxes[bi].UR.x = INT_MIN;
    poly.ps = polypoints, poly.pn = pi;
    eps[0].x = pp->start.p.x, eps[0].y = pp->start.p.y;
    eps[1].x = pp->end.p.x, eps[1].y = pp->end.p.y;
    if (Pshortestpath(&poly, eps, &pl) == -1)
	abort();
#ifdef DEBUG
    if (debugleveln(realedge, 3)) {
	psprintpoly(poly);
	psprintline(pl);
    }
#endif

    if (polyline) {
	make_polyline (pl, &spl);
    }
    else {
	if (poly.pn > edgen) {
	    edges = ALLOC(poly.pn, edges, Pedge_t);
	    edgen = poly.pn;
	}
	for (edgei = 0; edgei < poly.pn; edgei++) {
	    edges[edgei].a = polypoints[edgei];
	    edges[edgei].b = polypoints[(edgei + 1) % poly.pn];
	}
	if (pp->start.constrained) {
	    evs[0].x = cos(pp->start.theta);
	    evs[0].y = sin(pp->start.theta);
	} else
	    evs[0].x = evs[0].y = 0;
	if (pp->end.constrained) {
	    evs[1].x = -cos(pp->end.theta);
	    evs[1].y = -sin(pp->end.theta);
	} else
	    evs[1].x = evs[1].y = 0;

	if (Proutespline(edges, poly.pn, pl, evs, &spl) == -1)
	    abort();
#ifdef DEBUG
	if (debugleveln(realedge, 3)) {
	    psprintspline(spl);
	    psprintinit(0);
	}
#endif
    }
    mkspacep(spl.pn);
    for (bi = 0; bi < boxn; bi++) {
	boxes[bi].LL.x = INT_MAX;
	boxes[bi].UR.x = INT_MIN;
    }
    for (splinepi = 0; splinepi < spl.pn; splinepi++) {
	ps[splinepi] = spl.ps[splinepi];
    }
REDO:
    for (splinepi = 0; splinepi + 3 < spl.pn; splinepi += 3) {
	int num_div = delta * boxn;
	for (si = 0; si <= num_div; si++) {
	    t = si / (double)num_div;
	    sp[0] = ps[splinepi];
	    sp[1] = ps[splinepi + 1];
	    sp[2] = ps[splinepi + 2];
	    sp[3] = ps[splinepi + 3];
	    sp[0].x = sp[0].x + t * (sp[1].x - sp[0].x);
	    sp[0].y = sp[0].y + t * (sp[1].y - sp[0].y);
	    sp[1].x = sp[1].x + t * (sp[2].x - sp[1].x);
	    sp[1].y = sp[1].y + t * (sp[2].y - sp[1].y);
	    sp[2].x = sp[2].x + t * (sp[3].x - sp[2].x);
	    sp[2].y = sp[2].y + t * (sp[3].y - sp[2].y);
	    sp[0].x = sp[0].x + t * (sp[1].x - sp[0].x);
	    sp[0].y = sp[0].y + t * (sp[1].y - sp[0].y);
	    sp[1].x = sp[1].x + t * (sp[2].x - sp[1].x);
	    sp[1].y = sp[1].y + t * (sp[2].y - sp[1].y);
	    sp[0].x = sp[0].x + t * (sp[1].x - sp[0].x);
	    sp[0].y = sp[0].y + t * (sp[1].y - sp[0].y);
	    for (bi = 0; bi < boxn; bi++) {
/* this tested ok on 64bit machines, but on 32bit we need this FUDGE
 *     or graphs/directed/records.gv fails */
#define FUDGE .0001
		if (sp[0].y <= boxes[bi].UR.y+FUDGE && sp[0].y >= boxes[bi].LL.y-FUDGE) {
		    if (boxes[bi].LL.x > sp[0].x)
			boxes[bi].LL.x = sp[0].x;
		    if (boxes[bi].UR.x < sp[0].x)
			boxes[bi].UR.x = sp[0].x;
		}
	    }
	}
    }
    /* The following check is necessary because if a box is not very 
     * high, it is possible that the sampling above might miss it.
     * Therefore, we make the sample finer until all boxes have
     * valid values. cf. bug 456. Would making sp[] pointfs help?
     */
    for (bi = 0; bi < boxn; bi++) {
	/* these fp equality tests are used only to detect if the
	 * values have been changed since initialization - ok */
	if ((boxes[bi].LL.x == INT_MAX) || (boxes[bi].UR.x == INT_MIN)) {
	    delta *= 2;
	    goto REDO;
	}
    }
    *npoints = spl.pn;

#ifdef DEBUG
    if (GD_showboxes(realedge->head->graph) == 2 ||
	GD_showboxes(realedge->tail->graph) == 2 ||
	ED_showboxes(realedge) == 2 ||
	ND_showboxes(realedge->head) == 2 ||
	ND_showboxes(realedge->tail) == 2)
	printboxes(boxn, boxes);
#endif

    return ps;
}
コード例 #4
0
/* routesplines:
 * Route a path using the path info in pp. This includes start and end points
 * plus a collection of contiguous boxes contain the terminal points. The boxes
 * are converted into a containing polygon. A shortest path is constructed within
 * the polygon from between the terminal points. If polyline is true, this path
 * is converted to a spline representation. Otherwise, we call the path planner to
 * convert the polyline into a smooth spline staying within the polygon. In both
 * cases, the function returns an array of the computed control points. The number
 * of these points is given in npoints.
 *
 * Note that the returned points are stored in a single array, so the points must be
 * used before another call to this function.
 *
 * During cleanup, the function determines the x-extent of the spline in the box, so
 * the box can be shrunk to the minimum width. The extra space can then be used by other
 * edges. 
 *
 * If a catastrophic error, return NULL.
 */
static pointf *_routesplines(path * pp, int *npoints, int polyline)
{
    Ppoly_t poly;
    Ppolyline_t pl, spl;
    int splinepi;
    Ppoint_t eps[2];
    Pvector_t evs[2];
    int edgei, prev, next;
    int pi, bi;
    boxf *boxes;
    int boxn;
    edge_t* realedge;
    int flip;
    int loopcnt, delta = INIT_DELTA;
    boolean unbounded;

    nedges++;
    nboxes += pp->nbox;

    for (realedge = (edge_t *) pp->data;
#ifdef NOTNOW
	 origedge = realedge;
#endif
	 realedge && ED_edge_type(realedge) != NORMAL;
	 realedge = ED_to_orig(realedge));
    if (!realedge) {
	agerr(AGERR, "in routesplines, cannot find NORMAL edge\n");
	return NULL;
    }

    boxes = pp->boxes;
    boxn = pp->nbox;

    if (checkpath(boxn, boxes, pp))
	return NULL;

#ifdef DEBUG
    if (debugleveln(realedge, 1))
	printboxes(boxn, boxes);
    if (debugleveln(realedge, 3)) {
	psprintinit(1);
	psprintboxes(boxn, boxes);
    }
#endif

    if (boxn * 8 > polypointn) {
	polypoints = ALLOC(boxn * 8, polypoints, Ppoint_t);
	polypointn = boxn * 8;
    }

    if ((boxn > 1) && (boxes[0].LL.y > boxes[1].LL.y)) {
        flip = 1;
	for (bi = 0; bi < boxn; bi++) {
	    double v = boxes[bi].UR.y;
	    boxes[bi].UR.y = -1*boxes[bi].LL.y;
	    boxes[bi].LL.y = -v;
	}
    }
    else flip = 0;

    if (agtail(realedge) != aghead(realedge)) {
	/* I assume that the path goes either down only or
	   up - right - down */
	for (bi = 0, pi = 0; bi < boxn; bi++) {
	    next = prev = 0;
	    if (bi > 0)
		prev = (boxes[bi].LL.y > boxes[bi - 1].LL.y) ? -1 : 1;
	    if (bi < boxn - 1)
		next = (boxes[bi + 1].LL.y > boxes[bi].LL.y) ? 1 : -1;
	    if (prev != next) {
		if (next == -1 || prev == 1) {
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		} else {
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		}
	    }
	    else if (prev == 0) { /* single box */
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].UR.y;
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].LL.y;
	    } 
	    else {
		if (!(prev == -1 && next == -1)) {
		    agerr(AGERR, "in routesplines, illegal values of prev %d and next %d, line %d\n", prev, next, __LINE__);
		    return NULL;
		}
	    }
	}
	for (bi = boxn - 1; bi >= 0; bi--) {
	    next = prev = 0;
	    if (bi < boxn - 1)
		prev = (boxes[bi].LL.y > boxes[bi + 1].LL.y) ? -1 : 1;
	    if (bi > 0)
		next = (boxes[bi - 1].LL.y > boxes[bi].LL.y) ? 1 : -1;
	    if (prev != next) {
		if (next == -1 || prev == 1 ) {
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		    polypoints[pi].x = boxes[bi].LL.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		} else {
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].LL.y;
		    polypoints[pi].x = boxes[bi].UR.x;
		    polypoints[pi++].y = boxes[bi].UR.y;
		}
	    } 
	    else if (prev == 0) { /* single box */
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].LL.y;
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].UR.y;
	    }
	    else {
		if (!(prev == -1 && next == -1)) {
		    /* it went badly, e.g. degenerate box in boxlist */
		    agerr(AGERR, "in routesplines, illegal values of prev %d and next %d, line %d\n", prev, next, __LINE__);
		    return NULL; /* for correctness sake, it's best to just stop */
		}
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].LL.y;
		polypoints[pi].x = boxes[bi].UR.x;
		polypoints[pi++].y = boxes[bi].UR.y;
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].UR.y;
		polypoints[pi].x = boxes[bi].LL.x;
		polypoints[pi++].y = boxes[bi].LL.y;
	    }
	}
    }
    else {
	agerr(AGERR, "in routesplines, edge is a loop at %s\n", agnameof(aghead(realedge)));
	return NULL;
    }

    if (flip) {
	int i;
	for (bi = 0; bi < boxn; bi++) {
	    int v = boxes[bi].UR.y;
	    boxes[bi].UR.y = -1*boxes[bi].LL.y;
	    boxes[bi].LL.y = -v;
	}
	for (i = 0; i < pi; i++)
	    polypoints[i].y *= -1;
    }

    for (bi = 0; bi < boxn; bi++)
	boxes[bi].LL.x = INT_MAX, boxes[bi].UR.x = INT_MIN;
    poly.ps = polypoints, poly.pn = pi;
    eps[0].x = pp->start.p.x, eps[0].y = pp->start.p.y;
    eps[1].x = pp->end.p.x, eps[1].y = pp->end.p.y;
    if (Pshortestpath(&poly, eps, &pl) < 0) {
	agerr(AGERR, "in routesplines, Pshortestpath failed\n");
	return NULL;
    }
#ifdef DEBUG
    if (debugleveln(realedge, 3)) {
	psprintpoly(poly);
	psprintline(pl);
    }
#endif

    if (polyline) {
	make_polyline (pl, &spl);
    }
    else {
	if (poly.pn > edgen) {
	    edges = ALLOC(poly.pn, edges, Pedge_t);
	    edgen = poly.pn;
	}
	for (edgei = 0; edgei < poly.pn; edgei++) {
	    edges[edgei].a = polypoints[edgei];
	    edges[edgei].b = polypoints[(edgei + 1) % poly.pn];
	}
	if (pp->start.constrained) {
	    evs[0].x = cos(pp->start.theta);
	    evs[0].y = sin(pp->start.theta);
	} else
	    evs[0].x = evs[0].y = 0;
	if (pp->end.constrained) {
	    evs[1].x = -cos(pp->end.theta);
	    evs[1].y = -sin(pp->end.theta);
	} else
	    evs[1].x = evs[1].y = 0;

	if (Proutespline(edges, poly.pn, pl, evs, &spl) < 0) {
	    agerr(AGERR, "in routesplines, Proutespline failed\n");
	    return NULL;
	}
#ifdef DEBUG
	if (debugleveln(realedge, 3)) {
	    psprintspline(spl);
	    psprintinit(0);
	}
#endif
    }
    if (mkspacep(spl.pn))
	return NULL;  /* Bailout if no memory left */

    for (bi = 0; bi < boxn; bi++) {
	boxes[bi].LL.x = INT_MAX;
	boxes[bi].UR.x = INT_MIN;
    }
    unbounded = TRUE;
    for (splinepi = 0; splinepi < spl.pn; splinepi++) {
	ps[splinepi] = spl.ps[splinepi];
    }

    for (loopcnt = 0; unbounded && (loopcnt < LOOP_TRIES); loopcnt++) {
	limitBoxes (boxes, boxn, ps, spl.pn, delta);

    /* The following check is necessary because if a box is not very 
     * high, it is possible that the sampling above might miss it.
     * Therefore, we make the sample finer until all boxes have
     * valid values. cf. bug 456. Would making sp[] pointfs help?
     */
	for (bi = 0; bi < boxn; bi++) {
	/* these fp equality tests are used only to detect if the
	 * values have been changed since initialization - ok */
	    if ((boxes[bi].LL.x == INT_MAX) || (boxes[bi].UR.x == INT_MIN)) {
		delta *= 2; /* try again with a finer interval */
		if (delta > INT_MAX/boxn) /* in limitBoxes, boxn*delta must fit in an int, so give up */
		    loopcnt = LOOP_TRIES;
		break;
	    }
	}
	if (bi == boxn)
	    unbounded = FALSE;
    }
    if (unbounded) {  
	/* Either an extremely short, even degenerate, box, or some failure with the path
         * planner causing the spline to miss some boxes. In any case, use the shortest path 
	 * to bound the boxes. This will probably mean a bad edge, but we avoid an infinite
	 * loop and we can see the bad edge, and even use the showboxes scaffolding.
	 */
	Ppolyline_t polyspl;
	agerr(AGWARN, "Unable to reclaim box space in spline routing for edge \"%s\" -> \"%s\". Something is probably seriously wrong.\n", agnameof(agtail(realedge)), agnameof(aghead(realedge)));
	make_polyline (pl, &polyspl);
	limitBoxes (boxes, boxn, polyspl.ps, polyspl.pn, INIT_DELTA);
	free (polyspl.ps);
    }

    *npoints = spl.pn;

#ifdef DEBUG
    if (GD_showboxes(agraphof(aghead(realedge))) == 2 ||
	GD_showboxes(agraphof(agtail(realedge))) == 2 ||
	ED_showboxes(realedge) == 2 ||
	ND_showboxes(aghead(realedge)) == 2 ||
	ND_showboxes(agtail(realedge)) == 2)
	printboxes(boxn, boxes);
#endif

    return ps;
}
コード例 #5
0
ファイル: cluster.c プロジェクト: emdenrg/graphviz
/* 
 * attach and install edges between clusters.
 * essentially, class2() for interclust edges.
 */
void interclexp(graph_t * subg)
{
    graph_t *g;
    node_t *n;
    edge_t *e, *prev, *next;

    g = agroot(subg);
    for (n = agfstnode(subg); n; n = agnxtnode(subg, n)) {

	/* N.B. n may be in a sub-cluster of subg */
	prev = NULL;
	for (e = agfstedge(agroot(subg), n); e; e = next) {
	    next = agnxtedge(agroot(subg), e, n);
	    if (agcontains(subg, e))
		continue;

#ifdef WITH_CGRAPH
		/* canonicalize edge */
	    e = AGMKOUT(e);
#endif
	    /* short/flat multi edges */
	    if (mergeable(prev, e)) {
		if (ND_rank(agtail(e)) == ND_rank(aghead(e)))
		    ED_to_virt(e) = prev;
		else
		    ED_to_virt(e) = NULL;
		if (ED_to_virt(prev) == NULL)
		    continue;	/* internal edge */
		merge_chain(subg, e, ED_to_virt(prev), FALSE);
		safe_other_edge(e);
		continue;
	    }

	    /* flat edges */
	    if (ND_rank(agtail(e)) == ND_rank(aghead(e))) {
		edge_t* fe;
		if ((fe = find_flat_edge(agtail(e), aghead(e))) == NULL) {
		    flat_edge(g, e);
		    prev = e;
		} else if (e != fe) {
		    safe_other_edge(e);
		    if (!ED_to_virt(e)) merge_oneway(e, fe);
		}
		continue;
	    }

/* This assertion is still valid if the new ranking is not used */
#ifndef WITH_CGRAPH
	    assert(ED_to_virt(e) != NULL);
#endif

	    /* forward edges */
	    if (ND_rank(aghead(e)) > ND_rank(agtail(e))) {
		make_interclust_chain(g, agtail(e), aghead(e), e);
		prev = e;
		continue;
	    }

	    /* backward edges */
	    else {
/*
I think that make_interclust_chain should create call other_edge(e) anyway 
				if (agcontains(subg,agtail(e))
					&& agfindedge(subg->root,aghead(e),agtail(e))) other_edge(e);
*/
		make_interclust_chain(g, aghead(e), agtail(e), e);
		prev = e;
	    }
	}
    }
}
コード例 #6
0
/* make_label:
 * Assume str is freshly allocated for this instance, so it
 * can be freed in free_label.
 */
textlabel_t *make_label(void *obj, char *str, int kind, double fontsize, char *fontname, char *fontcolor)
{
    textlabel_t *rv = NEW(textlabel_t);
    graph_t *g = NULL, *sg = NULL;
    node_t *n = NULL;
    edge_t *e = NULL;
        char *s;

    switch (agobjkind(obj)) {
    case AGRAPH:
        sg = (graph_t*)obj;
	g = sg->root;
	break;
    case AGNODE:
        n = (node_t*)obj;
	g = agroot(agraphof(n));
	break;
    case AGEDGE:
        e = (edge_t*)obj;
	g = agroot(agraphof(aghead(e)));
	break;
    }
    rv->fontname = fontname;
    rv->fontcolor = fontcolor;
    rv->fontsize = fontsize;
    rv->charset = GD_charset(g);
    if (kind & LT_RECD) {
	rv->text = strdup(str);
        if (kind & LT_HTML) {
	    rv->html = TRUE;
	}
    }
    else if (kind == LT_HTML) {
	rv->text = strdup(str);
	rv->html = TRUE;
	if (make_html_label(obj, rv)) {
	    switch (agobjkind(obj)) {
	    case AGRAPH:
	        agerr(AGPREV, "in label of graph %s\n",agnameof(sg));
		break;
	    case AGNODE:
	        agerr(AGPREV, "in label of node %s\n", agnameof(n));
		break;
	    case AGEDGE:
		agerr(AGPREV, "in label of edge %s %s %s\n",
		        agnameof(agtail(e)), agisdirected(g)?"->":"--", agnameof(aghead(e)));
		break;
	    }
	}
    }
    else {
        assert(kind == LT_NONE);
	/* This call just processes the graph object based escape sequences. The formatting escape
         * sequences (\n, \l, \r) are processed in make_simple_label. That call also replaces \\ with \.
         */
	rv->text = strdup_and_subst_obj0(str, obj, 0);
        switch (rv->charset) {
	case CHAR_LATIN1:
	    s = latin1ToUTF8(rv->text);
	    break;
	default: /* UTF8 */
	    s = htmlEntityUTF8(rv->text, g);
	    break;
	}
        free(rv->text);
        rv->text = s;
	make_simple_label(GD_gvc(g), rv);
    }
    return rv;
}
コード例 #7
0
ファイル: utils.c プロジェクト: jho1965us/graphviz
/* return true if edge has label */
int common_init_edge(edge_t * e)
{
    char *str;
    int r = 0;
    struct fontinfo fi;
    struct fontinfo lfi;
    graph_t *sg = agraphof(agtail(e));

    fi.fontname = NULL;
    lfi.fontname = NULL;
    if (E_label && (str = agxget(e, E_label)) && (str[0])) {
	r = 1;
	initFontEdgeAttr(e, &fi);
	ED_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
				fi.fontsize, fi.fontname, fi.fontcolor);
	GD_has_labels(sg) |= EDGE_LABEL;
	ED_label_ontop(e) =
	    mapbool(late_string(e, E_label_float, "false"));
    }

    if (E_xlabel && (str = agxget(e, E_xlabel)) && (str[0])) {
	if (!fi.fontname)
	    initFontEdgeAttr(e, &fi);
	ED_xlabel(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
				fi.fontsize, fi.fontname, fi.fontcolor);
	GD_has_labels(sg) |= EDGE_XLABEL;
    }


    /* vladimir */
    if (E_headlabel && (str = agxget(e, E_headlabel)) && (str[0])) {
	initFontLabelEdgeAttr(e, &fi, &lfi);
	ED_head_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
				lfi.fontsize, lfi.fontname, lfi.fontcolor);
	GD_has_labels(sg) |= HEAD_LABEL;
    }
    if (E_taillabel && (str = agxget(e, E_taillabel)) && (str[0])) {
	if (!lfi.fontname)
	    initFontLabelEdgeAttr(e, &fi, &lfi);
	ED_tail_label(e) = make_label((void*)e, str, (aghtmlstr(str) ? LT_HTML : LT_NONE),
				lfi.fontsize, lfi.fontname, lfi.fontcolor);
	GD_has_labels(sg) |= TAIL_LABEL;
    }
    /* end vladimir */

    /* We still accept ports beginning with colons but this is deprecated 
     * That is, we allow tailport = ":abc" as well as the preferred 
     * tailport = "abc".
     */
    str = agget(e, TAIL_ID);
    /* libgraph always defines tailport/headport; libcgraph doesn't */
    if (!str) str = "";
    if (str && str[0])
	ND_has_port(agtail(e)) = TRUE;
    ED_tail_port(e) = chkPort (ND_shape(agtail(e))->fns->portfn, agtail(e), str);
    if (noClip(e, E_tailclip))
	ED_tail_port(e).clip = FALSE;
    str = agget(e, HEAD_ID);
    /* libgraph always defines tailport/headport; libcgraph doesn't */
    if (!str) str = "";
    if (str && str[0])
	ND_has_port(aghead(e)) = TRUE;
    ED_head_port(e) = chkPort(ND_shape(aghead(e))->fns->portfn, aghead(e), str);
    if (noClip(e, E_headclip))
	ED_head_port(e).clip = FALSE;

    return r;
}
コード例 #8
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);
}
コード例 #9
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);
      }
    }
  }
コード例 #10
0
ファイル: utils.c プロジェクト: jho1965us/graphviz
static void
checkCompound(edge_t * e, graph_t * clg, agxbuf * xb, Dt_t * map, Dt_t* cmap)
{
    graph_t *tg;
    graph_t *hg;
    node_t *cn;
    node_t *cn1;
    node_t *t = agtail(e);
    node_t *h = aghead(e);
    edge_t *ce;
    item *ip;

    if (IS_CLUST_NODE(h)) return;
    tg = MAPC(t);
    hg = MAPC(h);
    if (!tg && !hg)
	return;
    if (tg == hg) {
	agerr(AGWARN, "cluster cycle %s -- %s not supported\n", agnameof(t),
	      agnameof(t));
	return;
    }
    ip = mapEdge(map, e);
    if (ip) {
	cloneEdge(e, ip->t, ip->h);
	return;
    }

    if (hg) {
	if (tg) {
	    if (agcontains(hg, tg)) {
		agerr(AGWARN, "tail cluster %s inside head cluster %s\n",
		      agnameof(tg), agnameof(hg));
		return;
	    }
	    if (agcontains(tg, hg)) {
		agerr(AGWARN, "head cluster %s inside tail cluster %s\n",
		      agnameof(hg),agnameof(tg));
		return;
	    }
	    cn = clustNode(t, tg, xb, clg);
	    cn1 = clustNode(h, hg, xb, clg);
	    ce = cloneEdge(e, cn, cn1);
	    insertEdge(map, t, h, ce);
	} else {
	    if (agcontains(hg, t)) {
		agerr(AGWARN, "tail node %s inside head cluster %s\n",
		      agnameof(t), agnameof(hg));
		return;
	    }
	    cn = clustNode(h, hg, xb, clg);
	    ce = cloneEdge(e, t, cn);
	    insertEdge(map, t, h, ce);
	}
    } else {
	if (agcontains(tg, h)) {
	    agerr(AGWARN, "head node %s inside tail cluster %s\n", agnameof(h),
		  agnameof(tg));
	    return;
	}
	cn = clustNode(t, tg, xb, clg);
	ce = cloneEdge(e, cn, h);
	insertEdge(map, t, h, ce);
    }
}
コード例 #11
0
/* genroute:
 * Generate splines for e and cohorts.
 * Edges go from s to t.
 * Return 0 on success.
 */
static int 
genroute(graph_t* g, tripoly_t * trip, int s, int t, edge_t * e, int doPolyline)
{
    pointf eps[2];
    Pvector_t evs[2];
    pointf **cpts;		/* lists of control points */
    Ppoly_t poly;
    Ppolyline_t pl, spl;
    int i, j;
    Ppolyline_t mmpl;
    Pedge_t *medges = N_GNEW(trip->poly.pn, Pedge_t);
    int pn;
    int mult = ED_count(e);
    node_t* head = aghead(e);

    eps[0].x = trip->poly.ps[s].x, eps[0].y = trip->poly.ps[s].y;
    eps[1].x = trip->poly.ps[t].x, eps[1].y = trip->poly.ps[t].y;
    Pshortestpath(&(trip->poly), eps, &pl);

    if (pl.pn == 2) {
	makeStraightEdge(agraphof(head), e, doPolyline);
	return 0;
    }

    evs[0].x = evs[0].y = 0;
    evs[1].x = evs[1].y = 0;

    if ((mult == 1) || Concentrate) {
	poly = trip->poly;
	for (j = 0; j < poly.pn; j++) {
	    medges[j].a = poly.ps[j];
	    medges[j].b = poly.ps[(j + 1) % poly.pn];
	}
	tweakPath (poly, s, t, pl);
	Proutespline(medges, poly.pn, pl, evs, &spl);
	finishEdge (g, e, spl, aghead(e) != head, eps[0], eps[1]);
	free(medges);

	return 0;
    }
    
    pn = 2 * (pl.pn - 1);

    cpts = N_NEW(pl.pn - 2, pointf *);
    for (i = 0; i < pl.pn - 2; i++) {
	cpts[i] =
	    mkCtrlPts(t, mult+1, pl.ps[i], pl.ps[i + 1], pl.ps[i + 2], trip);
	if (!cpts[i]) {
	    agerr(AGWARN, "Could not create control points for multiple spline for edge (%s,%s)\n", agnameof(agtail(e)), agnameof(aghead(e)));
	    return 1;
	}
    }

    poly.ps = N_GNEW(pn, pointf);
    poly.pn = pn;

    for (i = 0; i < mult; i++) {
	poly.ps[0] = eps[0];
	for (j = 1; j < pl.pn - 1; j++) {
	    poly.ps[j] = cpts[j - 1][i];
	}
	poly.ps[pl.pn - 1] = eps[1];
	for (j = 1; j < pl.pn - 1; j++) {
	    poly.ps[pn - j] = cpts[j - 1][i + 1];
	}
	Pshortestpath(&poly, eps, &mmpl);

	if (doPolyline) {
	    make_polyline (mmpl, &spl);
	}
	else {
	    for (j = 0; j < poly.pn; j++) {
		medges[j].a = poly.ps[j];
		medges[j].b = poly.ps[(j + 1) % poly.pn];
	    }
	    tweakPath (poly, 0, pl.pn-1, mmpl);
	    Proutespline(medges, poly.pn, mmpl, evs, &spl);
	}
	finishEdge (g, e, spl, aghead(e) != head, eps[0], eps[1]);

	e = ED_to_virt(e);
    }

    for (i = 0; i < pl.pn - 2; i++)
	free(cpts[i]);
    free(cpts);
    free(medges);
    free(poly.ps);
    return 0;
}
コード例 #12
0
Agnode_t *nextnode(Agedge_t *e, Agnode_t *n)
{
    if (!e || n != agtail(e))
        return NULL;
    return aghead(e);
}
コード例 #13
0
Agnode_t *firstnode(Agedge_t *e)
{
    if (!e)
        return NULL;
    return agtail(e);
}
コード例 #14
0
ファイル: sd_dotloader.cpp プロジェクト: simgrid/simgrid
xbt_dynar_t SD_dotload_generic(const char* filename, bool sequential, 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);

  SD_task_t root;
  SD_task_t end;
  SD_task_t task;
  std::vector<SD_task_t>* computer;
  std::unordered_map<std::string, std::vector<SD_task_t>*> computers;
  bool schedule_success = true;

  std::unordered_map<std::string, SD_task_t> jobs;
  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 *));

  /* 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"));
    if (jobs.find(name) == jobs.end()) {
      if (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);
      }

      jobs.insert({std::string(name), task});

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

      if ((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 = ((not char_performer || not strcmp(char_performer, "")) ? -1 : atoi(char_performer));
        int order     = ((not char_order || not strcmp(char_order, "")) ? -1 : atoi(char_order));

        if ((performer != -1 && order != -1) && performer < static_cast<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);
          auto comp = computers.find(char_performer);
          if (comp != computers.end()) {
            computer = comp->second;
          } else {
            computer = new std::vector<SD_task_t>;
            computers.insert({char_performer, computer});
          }
          if (static_cast<unsigned int>(order) < computer->size()) {
            SD_task_t task_test = computer->at(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;
            }
          } else
            computer->resize(order);

          computer->insert(computer->begin() + order, 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 (jobs.find("root") == jobs.end())
    root = (sequential ? SD_task_create_comp_seq("root", nullptr, 0)
                       : SD_task_create_comp_par_amdahl("root", nullptr, 0, 0));
  else
    root = jobs.at("root");

  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 (jobs.find("end") == jobs.end())
    end = (sequential ? SD_task_create_comp_seq("end", nullptr, 0)
                      : SD_task_create_comp_par_amdahl("end", nullptr, 0, 0));
  else
    end = jobs.at("end");

  /* Create edges */
  std::vector<Agedge_t*> edges;
  for (node = agfstnode(dag_dot); node; node = agnxtnode(dag_dot, node)) {
    edges.clear();
    for (Agedge_t* edge = agfstout(dag_dot, node); edge; edge = agnxtout(dag_dot, edge))
      edges.push_back(edge);

    /* Be sure edges are sorted */
    std::sort(edges.begin(), edges.end(), [](const Agedge_t* a, const Agedge_t* b) { return AGSEQ(a) < AGSEQ(b); });

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

      SD_task_t src = jobs.at(src_name);
      SD_task_t dst = jobs.at(dst_name);

      if (size > 0) {
        std::string name = std::string(src_name) + "->" + dst_name;
        XBT_DEBUG("See <transfer id=%s amount = %.0f>", name.c_str(), size);
        if (jobs.find(name) == jobs.end()) {
          if (sequential)
            task = SD_task_create_comm_e2e(name.c_str(), nullptr, size);
          else
            task = SD_task_create_comm_par_mxn_1d_block(name.c_str(), nullptr, size);
          SD_task_dependency_add(src, task);
          SD_task_dependency_add(task, dst);
          jobs.insert({name, task});
          xbt_dynar_push(result, &task);
        } else {
          XBT_WARN("Task '%s' is defined more than once", name.c_str());
        }
      } else {
        SD_task_dependency_add(src, dst);
      }
    }
  }

  XBT_DEBUG("All tasks have been created, put %s at the end of the dynar", end->name);
  xbt_dynar_push(result, &end);

  /* Connect entry tasks to 'root', and exit tasks to 'end'*/
  unsigned i;
  xbt_dynar_foreach (result, i, task){
    if (task->predecessors->empty() && task->inputs->empty() && task != root) {
      XBT_DEBUG("Task '%s' has no source. Add dependency from 'root'", task->name);
      SD_task_dependency_add(root, task);
    }

    if (task->successors->empty() && task->outputs->empty() && task != end) {
      XBT_DEBUG("Task '%s' has no destination. Add dependency to 'end'", task->name);
      SD_task_dependency_add(task, end);
    }
  }

  agclose(dag_dot);
  fclose(in_file);

  if(schedule){
    if (schedule_success) {
      std::vector<simgrid::s4u::Host*> hosts = simgrid::s4u::Engine::get_instance()->get_all_hosts();

      for (auto const& elm : computers) {
        SD_task_t previous_task = nullptr;
        for (auto const& cur_task : *elm.second) {
          /* add dependency between the previous and the task to avoid parallel execution */
          if (cur_task) {
            if (previous_task && not SD_task_dependency_exists(previous_task, cur_task))
              SD_task_dependency_add(previous_task, cur_task);

            SD_task_schedulel(cur_task, 1, hosts[std::stod(elm.first)]);
            previous_task = cur_task;
          }
        }
        delete elm.second;
      }
    } else {
      XBT_WARN("The scheduling is ignored");
      for (auto const& elm : computers)
        delete elm.second;
      xbt_dynar_free(&result);
      result = nullptr;
    }
  }

  if (result && not acyclic_graph_detail(result)) {
    std::string base = simgrid::xbt::Path(filename).get_base_name();
    XBT_ERROR("The DOT described in %s is not a DAG. It contains a cycle.", base.c_str());
    xbt_dynar_free(&result);
    result = nullptr;
  }
  return result;
}
コード例 #15
0
ファイル: draw.c プロジェクト: AhmedAMohamed/graphviz
static void relocate_spline(sdot_op * sop, int param)
{
    Agedge_t *e;
    Agnode_t *tn;		//tail node
    Agnode_t *hn;		//head node
    int i = 0;
    xdot_op *op = &sop->op;
    if (AGTYPE(sop->obj) == AGEDGE)
	{
		e = sop->obj;
		tn = agtail(e);
		hn = aghead(e);
		if ((OD_Selected(hn) == 1) && (OD_Selected(tn) == 0))
		{
			set_options(sop, 1);
			for (i = 1; i < op->u.bezier.cnt - 1; i = i + 1)
			{
				if ((dx != 0) || (dy != 0)) 
				{
					op->u.bezier.pts[i].x =
							op->u.bezier.pts[i].x -
								(int) (dx * (float) i /
									(float) (op->u.bezier.cnt));
					op->u.bezier.pts[i].y =
								op->u.bezier.pts[i].y -
									(int) (dy * (float) i /
								       (float) (op->u.bezier.cnt));
				}
		    }
			if ((dx != 0) || (dy != 0)) 
			{
				op->u.bezier.pts[op->u.bezier.cnt - 1].x =
						op->u.bezier.pts[op->u.bezier.cnt - 1].x - (int) dx;
				op->u.bezier.pts[op->u.bezier.cnt - 1].y =
						op->u.bezier.pts[op->u.bezier.cnt - 1].y - (int) dy;
			}
		}
		else if ((OD_Selected(hn) == 0) && (OD_Selected(tn) == 1))
		{
			set_options(sop, 1);
			for (i = op->u.bezier.cnt - 1; i > 0; i = i - 1) 
			{
				if ((dx != 0) || (dy != 0)) 
				{
					op->u.bezier.pts[i].x =
						op->u.bezier.pts[i].x -
							(int) (dx * (float) (op->u.bezier.cnt - i) /
											(float) (op->u.bezier.cnt));
				op->u.bezier.pts[i].y =
						op->u.bezier.pts[i].y -
							(int) (dy * (float) (op->u.bezier.cnt - i) /
								(float) (op->u.bezier.cnt));
				}
			}
			if ((dx != 0) || (dy != 0)) 
			{
				op->u.bezier.pts[0].x = op->u.bezier.pts[0].x - (int) dx;
				op->u.bezier.pts[0].y = op->u.bezier.pts[0].y - (int) dy;
			}
		}
		else if ((OD_Selected(hn) == 1) && (OD_Selected(tn) == 1)) 
		{
		    set_options(sop, 1);
			for (i = 0; i < op->u.bezier.cnt; i = i + 1) 
			{
				if ((dx != 0) || (dy != 0)) 
				{
					op->u.bezier.pts[i].x =
							op->u.bezier.pts[i].x - (int) dx;
					op->u.bezier.pts[i].y =
							op->u.bezier.pts[i].y - (int) dy;
				}
			}
		}
	}
}
コード例 #16
0
ファイル: ortho.c プロジェクト: TidyHuang/vizgems
static void
attachOrthoEdges (Agraph_t* g, maze* mp, int n_edges, route* route_list, splineInfo *sinfo, epair_t es[], int doLbls)
{
    int irte = 0;
    int i, ipt, npts;
    pointf* ispline = 0;
    int splsz = 0;
    pointf p, p1, q1;
    route rte;
    segment* seg;
    Agedge_t* e;
    textlabel_t* lbl;

    for (; irte < n_edges; irte++) {
	e = es[irte].e;
	p1 = addPoints(ND_coord(agtail(e)), ED_tail_port(e).p);
	q1 = addPoints(ND_coord(aghead(e)), ED_head_port(e).p);

	rte = route_list[irte];
	npts = 1 + 3*rte.n;
	if (npts > splsz) {
		if (ispline) free (ispline);
		ispline = N_GNEW(npts, pointf);
		splsz = npts;
	}
	    
	seg = rte.segs;
	if (seg->isVert) {
		p.x = vtrack(seg, mp);
		p.y = p1.y;
	}
	else {
		p.y = htrack(seg, mp);
		p.x = p1.x;
	}
	ispline[0] = ispline[1] = p;
	ipt = 2;

	for (i = 1;i<rte.n;i++) {
		seg = rte.segs+i;
		if (seg->isVert)
		    p.x = vtrack(seg, mp);
		else
		    p.y = htrack(seg, mp);
		ispline[ipt+2] = ispline[ipt+1] = ispline[ipt] = p;
		ipt += 3;
	}

	if (seg->isVert) {
		p.x = vtrack(seg, mp);
		p.y = q1.y;
	}
	else {
		p.y = htrack(seg, mp);
		p.x = q1.x;
	}
	ispline[ipt] = ispline[ipt+1] = p;
	if (Verbose > 1)
	    fprintf(stderr, "ortho %s %s\n", agnameof(agtail(e)),agnameof(aghead(e)));
	clip_and_install(e, aghead(e), ispline, npts, sinfo);
	if (doLbls && (lbl = ED_label(e)) && !lbl->set)
	    addEdgeLabels(g, e, p1, q1);
    }
    free(ispline);
}
コード例 #17
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;
}
コード例 #18
0
ファイル: cluster.c プロジェクト: emdenrg/graphviz
static void 
map_path(node_t * from, node_t * to, edge_t * orig, edge_t * ve, int type)
{
    int r;
    node_t *u, *v;
    edge_t *e;

    assert(ND_rank(from) < ND_rank(to));

    if ((agtail(ve) == from) && (aghead(ve) == to))
	return;

    if (ED_count(ve) > 1) {
	ED_to_virt(orig) = NULL;
	if (ND_rank(to) - ND_rank(from) == 1) {
	    if ((e = find_fast_edge(from, to)) && (ports_eq(orig, e))) {
		merge_oneway(orig, e);
		if ((ND_node_type(from) == NORMAL)
		    && (ND_node_type(to) == NORMAL))
		    other_edge(orig);
		return;
	    }
	}
	u = from;
	for (r = ND_rank(from); r < ND_rank(to); r++) {
	    if (r < ND_rank(to) - 1)
		v = clone_vn(agraphof(from), aghead(ve));
	    else
		v = to;
	    e = virtual_edge(u, v, orig);
	    ED_edge_type(e) = type;
	    u = v;
	    ED_count(ve)--;
	    ve = ND_out(aghead(ve)).list[0];
	}
    } else {
	if (ND_rank(to) - ND_rank(from) == 1) {
	    if ((ve = find_fast_edge(from, to)) && (ports_eq(orig, ve))) {
		/*ED_to_orig(ve) = orig; */
		ED_to_virt(orig) = ve;
		ED_edge_type(ve) = type;
		ED_count(ve)++;
		if ((ND_node_type(from) == NORMAL)
		    && (ND_node_type(to) == NORMAL))
		    other_edge(orig);
	    } else {
		ED_to_virt(orig) = NULL;
		ve = virtual_edge(from, to, orig);
		ED_edge_type(ve) = type;
	    }
	}
	if (ND_rank(to) - ND_rank(from) > 1) {
	    e = ve;
	    if (agtail(ve) != from) {
		ED_to_virt(orig) = NULL;
		e = ED_to_virt(orig) = virtual_edge(from, aghead(ve), orig);
		delete_fast_edge(ve);
	    } else
		e = ve;
	    while (ND_rank(aghead(e)) != ND_rank(to))
		e = ND_out(aghead(e)).list[0];
	    if (aghead(e) != to) {
		ve = e;
		e = virtual_edge(agtail(e), to, orig);
		ED_edge_type(e) = type;
		delete_fast_edge(ve);
	    }
	}
    }
}
コード例 #19
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);
}
コード例 #20
0
ファイル: cluster.c プロジェクト: emdenrg/graphviz
/* this function marks every node in <g> with its top-level cluster under <g> */
void mark_clusters(graph_t * g)
{
    int c;
    node_t *n, *nn, *vn;
    edge_t *orig, *e;
    graph_t *clust;

    /* remove sub-clusters below this level */
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (ND_ranktype(n) == CLUSTER)
	    UF_singleton(n);
	ND_clust(n) = NULL;
    }

    for (c = 1; c <= GD_n_cluster(g); c++) {
	clust = GD_clust(g)[c];
	for (n = agfstnode(clust); n; n = nn) {
		nn = agnxtnode(clust,n);
	    if (ND_ranktype(n) != NORMAL) {
		agerr(AGWARN,
		      "%s was already in a rankset, deleted from cluster %s\n",
		      agnameof(n), agnameof(g));
		agdelete(clust,n);
		continue;
	    }
	    UF_setname(n, GD_leader(clust));
	    ND_clust(n) = clust;
	    ND_ranktype(n) = CLUSTER;

	    /* here we mark the vnodes of edges in the cluster */
	    for (orig = agfstout(clust, n); orig;
		 orig = agnxtout(clust, orig)) {
		if ((e = ED_to_virt(orig))) {
#ifndef WITH_CGRAPH
		    while (e && (vn = e->head)->u.node_type == VIRTUAL) {
#else /* WITH_CGRAPH */
		    while (e && ND_node_type(vn =aghead(e)) == VIRTUAL) {
#endif /* WITH_CGRAPH */
			ND_clust(vn) = clust;
			e = ND_out(aghead(e)).list[0];
			/* trouble if concentrators and clusters are mixed */
		    }
		}
	    }
	}
    }
}

void build_skeleton(graph_t * g, graph_t * subg)
{
    int r;
    node_t *v, *prev, *rl;
    edge_t *e;

    prev = NULL;
    GD_rankleader(subg) = N_NEW(GD_maxrank(subg) + 2, node_t *);
    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
	v = GD_rankleader(subg)[r] = virtual_node(g);
	ND_rank(v) = r;
	ND_ranktype(v) = CLUSTER;
	ND_clust(v) = subg;
	if (prev) {
	    e = virtual_edge(prev, v, NULL);
	    ED_xpenalty(e) *= CL_CROSS;
	}
	prev = v;
    }

    /* set the counts on virtual edges of the cluster skeleton */
    for (v = agfstnode(subg); v; v = agnxtnode(subg, v)) {
	rl = GD_rankleader(subg)[ND_rank(v)];
	ND_UF_size(rl)++;
	for (e = agfstout(subg, v); e; e = agnxtout(subg, e)) {
	    for (r = ND_rank(agtail(e)); r < ND_rank(aghead(e)); r++) {
		ED_count(ND_out(rl).list[0])++;
	    }
	}
    }
    for (r = GD_minrank(subg); r <= GD_maxrank(subg); r++) {
	rl = GD_rankleader(subg)[r];
	if (ND_UF_size(rl) > 1)
	    ND_UF_size(rl)--;
    }
}
コード例 #21
0
ファイル: grafo.c プロジェクト: alex-co/trabalho_grafos
grafo le_grafo(FILE *input) {

    Agraph_t *ag = agread(input, 0);
    if(!(ag && agisstrict(ag)))
        return NULL;

//	struct grafo *g = malloc(sizeof(struct grafo));
	grafo g = malloc(sizeof(struct grafo));
    if( !g ) return NULL;

	g->vertices = constroi_lista();
    g->nome     = malloc(sizeof(char) * strlen(agnameof(ag)+1));
    strcpy(g->nome, agnameof(ag));
    g->direcionado = agisdirected(ag);
    g->n_vertices  = (unsigned int)agnnodes(ag);
    g->n_arestas   = (unsigned int)agnedges(ag);
    g->ponderado   = 0;

	for( Agnode_t *v = agfstnode(ag); v; v = agnxtnode(ag,v) ){

		vertice vt = malloc(sizeof(struct vertice));
		vt->nome   = malloc(sizeof(char) * strlen(agnameof(v))+1);
		strcpy( vt->nome, agnameof(v) );
		vt->visitado = 0;
		vt->coberto  = 0;
		vt->arestas_saida   = constroi_lista();
		vt->arestas_entrada = constroi_lista();

		insere_lista(vt, g->vertices);
	}

	for( Agnode_t *v = agfstnode(ag); v; v = agnxtnode(ag,v) ){

		vertice vt = busca_vertice(g->vertices, agnameof(v));

		if( g-> direcionado ){
			for( Agedge_t *e = agfstout(ag,v); e; e = agnxtout(ag,e) ){
				aresta at = cria_aresta(g->vertices, e);
				if( at->peso != 0 ) g->ponderado = 1;
				insere_lista(at, vt->arestas_saida);
			}
			for( Agedge_t *e = agfstin(ag,v); e; e = agnxtin(ag,e) ){
				aresta at = cria_aresta(g->vertices, e);
				if( at->peso != 0 ) g->ponderado = 1;
				insere_lista(at, vt->arestas_entrada);
			}
		}
		else {

			for( Agedge_t *e = agfstedge(ag,v); e; e = agnxtedge(ag,e,v) ){
				if( agtail(e) != v ) continue;
				aresta at = cria_aresta(g->vertices, e);
				if( at->peso != 0 ) g->ponderado = 1;
				insere_lista(at, at->origem->arestas_saida);
				insere_lista(at, at->destino->arestas_saida);
			}
		}
	}

	if( agclose(ag) )
		return NULL;
	return g;
}
コード例 #22
0
/* strdup_and_subst_obj0:
 * Replace various escape sequences with the name of the associated
 * graph object. A double backslash \\ can be used to avoid a replacement.
 * If escBackslash is true, convert \\ to \; else leave alone. All other dyads 
 * of the form \. are passed through unchanged.
 */
static char *strdup_and_subst_obj0 (char *str, void *obj, int escBackslash)
{
    char c, *s, *p, *t, *newstr;
    char *tp_str = "", *hp_str = "";
    char *g_str = "\\G", *n_str = "\\N", *e_str = "\\E",
	*h_str = "\\H", *t_str = "\\T", *l_str = "\\L";
    int g_len = 2, n_len = 2, e_len = 2,
	h_len = 2, t_len = 2, l_len = 2,
	tp_len = 0, hp_len = 0;
    int newlen = 0;
    int isEdge = 0;
    textlabel_t *tl;
    port pt;

    /* prepare substitution strings */
    switch (agobjkind(obj)) {
	case AGRAPH:
	    g_str = agnameof((graph_t *)obj);
	    g_len = strlen(g_str);
	    tl = GD_label((graph_t *)obj);
	    if (tl) {
		l_str = tl->text;
	    	if (str) l_len = strlen(l_str);
	    }
	    break;
	case AGNODE:
	    g_str = agnameof(agraphof((node_t *)obj));
	    g_len = strlen(g_str);
	    n_str = agnameof((node_t *)obj);
	    n_len = strlen(n_str);
	    tl = ND_label((node_t *)obj);
	    if (tl) {
		l_str = tl->text;
	    	if (str) l_len = strlen(l_str);
	    }
	    break;
	case AGEDGE:
	    isEdge = 1;
	    g_str = agnameof(agroot(agraphof(agtail(((edge_t *)obj)))));
	    g_len = strlen(g_str);
	    t_str = agnameof(agtail(((edge_t *)obj)));
	    t_len = strlen(t_str);
	    pt = ED_tail_port((edge_t *)obj);
	    if ((tp_str = pt.name))
	        tp_len = strlen(tp_str);
	    h_str = agnameof(aghead(((edge_t *)obj)));
	    h_len = strlen(h_str);
	    pt = ED_head_port((edge_t *)obj);
	    if ((hp_str = pt.name))
		hp_len = strlen(hp_str);
	    h_len = strlen(h_str);
	    tl = ED_label((edge_t *)obj);
	    if (tl) {
		l_str = tl->text;
	    	if (str) l_len = strlen(l_str);
	    }
	    if (agisdirected(agroot(agraphof(agtail(((edge_t*)obj))))))
		e_str = "->";
	    else
		e_str = "--";
	    e_len = t_len + (tp_len?tp_len+1:0) + 2 + h_len + (hp_len?hp_len+1:0);
	    break;
    }

    /* two passes over str.
     *
     * first pass prepares substitution strings and computes 
     * total length for newstring required from malloc.
     */
    for (s = str; (c = *s++);) {
	if (c == '\\') {
	    switch (c = *s++) {
	    case 'G':
		newlen += g_len;
		break;
	    case 'N':
		newlen += n_len;
		break;
	    case 'E':
		newlen += e_len;
		break;
	    case 'H':
		newlen += h_len;
		break;
	    case 'T':
		newlen += t_len;
		break; 
	    case 'L':
		newlen += l_len;
		break; 
	    case '\\':
		if (escBackslash) {
		    newlen += 1;
		    break; 
		}
		/* Fall through */
	    default:  /* leave other escape sequences unmodified, e.g. \n \l \r */
		newlen += 2;
	    }
	} else {
	    newlen++;
	}
    }
    /* allocate new string */
    newstr = gmalloc(newlen + 1);

    /* second pass over str assembles new string */
    for (s = str, p = newstr; (c = *s++);) {
	if (c == '\\') {
	    switch (c = *s++) {
	    case 'G':
		for (t = g_str; (*p = *t++); p++);
		break;
	    case 'N':
		for (t = n_str; (*p = *t++); p++);
		break;
	    case 'E':
		if (isEdge) {
		    for (t = t_str; (*p = *t++); p++);
		    if (tp_len) {
			*p++ = ':';
			for (t = tp_str; (*p = *t++); p++);
		    }
		    for (t = e_str; (*p = *t++); p++);
		    for (t = h_str; (*p = *t++); p++);
		    if (hp_len) {
			*p++ = ':';
			for (t = hp_str; (*p = *t++); p++);
		    }
		}
		break;
	    case 'T':
		for (t = t_str; (*p = *t++); p++);
		break;
	    case 'H':
		for (t = h_str; (*p = *t++); p++);
		break;
	    case 'L':
		for (t = l_str; (*p = *t++); p++);
		break;
	    case '\\':
		if (escBackslash) {
		    *p++ = '\\';
		    break; 
		}
		/* Fall through */
	    default:  /* leave other escape sequences unmodified, e.g. \n \l \r */
		*p++ = '\\';
		*p++ = c;
		break;
	    }
	} else {
	    *p++ = c;
	}
    }
    *p++ = '\0';
    return newstr;
}
コード例 #23
0
ファイル: gvevent.c プロジェクト: Wuvist/jsPlumb_Liviz.js
static void gv_graph_state(GVJ_t *job, graph_t *g)
{
#ifndef WITH_CGRAPH
    int i;
#endif
    int j;
    Agsym_t *a;
    gv_argvlist_t *list;

    list = &(job->selected_obj_type_name);
    j = 0;
    if (g == agroot(g)) {
        if (agisdirected(g))
            gv_argvlist_set_item(list, j++, s_digraph);
        else
            gv_argvlist_set_item(list, j++, s_graph);
    }
    else {
        gv_argvlist_set_item(list, j++, s_subgraph);
    }
    gv_argvlist_set_item(list, j++, agnameof(g));
    list->argc = j;

    list = &(job->selected_obj_attributes);
#ifndef WITH_CGRAPH
    for (i = 0, j = 0; i < dtsize(g->univ->globattr->dict); i++) {
        a = g->univ->globattr->list[i];
#else
    a = NULL;
    while ((a = agnxtattr(g, AGRAPH, a))) {
#endif
        gv_argvlist_set_item(list, j++, a->name);
#ifndef WITH_CGRAPH
        gv_argvlist_set_item(list, j++, agxget(g, a->index));
#else
        gv_argvlist_set_item(list, j++, agxget(g, a));
#endif
        gv_argvlist_set_item(list, j++, (char*)GVATTR_STRING);
    }
    list->argc = j;

    a = agfindgraphattr(g, s_href);
    if (!a)
        a = agfindgraphattr(g, s_URL);
    if (a)
#ifndef WITH_CGRAPH
        job->selected_href = strdup_and_subst_obj(agxget(g, a->index), (void*)g);
#else
        job->selected_href = strdup_and_subst_obj(agxget(g, a), (void*)g);
#endif
}

static void gv_node_state(GVJ_t *job, node_t *n)
{
#ifndef WITH_CGRAPH
    int i;
#endif
    int j;
    Agsym_t *a;
    Agraph_t *g;
    gv_argvlist_t *list;

    list = &(job->selected_obj_type_name);
    j = 0;
    gv_argvlist_set_item(list, j++, s_node);
    gv_argvlist_set_item(list, j++, agnameof(n));
    list->argc = j;

    list = &(job->selected_obj_attributes);
    g = agroot(agraphof(n));
#ifndef WITH_CGRAPH
    for (i = 0, j = 0; i < dtsize(g->univ->nodeattr->dict); i++) {
        a = g->univ->nodeattr->list[i];
#else
    a = NULL;
    while ((a = agnxtattr(g, AGNODE, a))) {
#endif
        gv_argvlist_set_item(list, j++, a->name);
#ifndef WITH_CGRAPH
        gv_argvlist_set_item(list, j++, agxget(n, a->index));
#else
        gv_argvlist_set_item(list, j++, agxget(n, a));
#endif
    }
    list->argc = j;

    a = agfindnodeattr(agraphof(n), s_href);
    if (!a)
        a = agfindnodeattr(agraphof(n), s_URL);
    if (a)
#ifndef WITH_CGRAPH
        job->selected_href = strdup_and_subst_obj(agxget(n, a->index), (void*)n);
#else
        job->selected_href = strdup_and_subst_obj(agxget(n, a), (void*)n);
#endif
}

static void gv_edge_state(GVJ_t *job, edge_t *e)
{
#ifndef WITH_CGRAPH
    int i;
#endif
    int j;
    Agsym_t *a;
    Agraph_t *g;
    gv_argvlist_t *nlist, *alist;

    nlist = &(job->selected_obj_type_name);

    /* only tail, head, and key are strictly identifying properties,
     * but we commonly alse use edge kind (e.g. "->") and tailport,headport
     * in edge names */
    j = 0;
    gv_argvlist_set_item(nlist, j++, s_edge);
    gv_argvlist_set_item(nlist, j++, agnameof(agtail(e)));
    j++; /* skip tailport slot for now */
    gv_argvlist_set_item(nlist, j++, agisdirected(agraphof(agtail(e)))?"->":"--");
    gv_argvlist_set_item(nlist, j++, agnameof(aghead(e)));
    j++; /* skip headport slot for now */
    j++; /* skip key slot for now */
    nlist->argc = j;

    alist = &(job->selected_obj_attributes);
    g = agroot(agraphof(aghead(e)));
#ifndef WITH_CGRAPH
    for (i = 0, j = 0; i < dtsize(g->univ->edgeattr->dict); i++) {
        a = g->univ->edgeattr->list[i];
#else
    a = NULL;
    while ((a = agnxtattr(g, AGEDGE, a))) {
#endif

        /* tailport and headport can be shown as part of the name, but they
         * are not identifying properties of the edge so we
         * also list them as modifyable attributes. */
        if (strcmp(a->name,s_tailport) == 0)
#ifndef WITH_CGRAPH
            gv_argvlist_set_item(nlist, 2, agxget(e, a->index));
#else
            gv_argvlist_set_item(nlist, 2, agxget(e, a));
#endif
        else if (strcmp(a->name,s_headport) == 0)
#ifndef WITH_CGRAPH
            gv_argvlist_set_item(nlist, 5, agxget(e, a->index));
#else
            gv_argvlist_set_item(nlist, 5, agxget(e, a));
#endif

        /* key is strictly an identifying property to distinguish multiple
         * edges between the same node pair.   Its non-writable, so
         * no need to list it as an attribute as well. */
        else if (strcmp(a->name,s_key) == 0) {
#ifndef WITH_CGRAPH
            gv_argvlist_set_item(nlist, 6, agxget(e, a->index));
#else
            gv_argvlist_set_item(nlist, 6, agxget(e, a));
#endif
            continue;
        }

        gv_argvlist_set_item(alist, j++, a->name);
#ifndef WITH_CGRAPH
        gv_argvlist_set_item(alist, j++, agxget(e, a->index));
#else
        gv_argvlist_set_item(alist, j++, agxget(e, a));
#endif
    }
コード例 #24
0
/* makeStraightEdge:
 *
 * FIX: handle ports on boundary?
 */
void 
makeStraightEdge(graph_t * g, edge_t * e, int et, splineInfo* sinfo)
{
    pointf dumb[4];
    node_t *n = agtail(e);
    node_t *head = aghead(e);
    int e_cnt = ED_count(e);
    int curved = (et == ET_CURVED);
    pointf perp;
    pointf del;
    edge_t *e0;
    int i, j, xstep, dx;
    double l_perp;
    pointf dumber[4];
    pointf p, q;

    p = dumb[1] = dumb[0] = add_pointf(ND_coord(n), ED_tail_port(e).p);
    q = dumb[2] = dumb[3] = add_pointf(ND_coord(head), ED_head_port(e).p);
    if ((e_cnt == 1) || Concentrate) {
	if (curved) bend(dumb,get_centroid(g));
	clip_and_install(e, aghead(e), dumb, 4, sinfo);
	addEdgeLabels(g, e, p, q);
	return;
    }

    e0 = e;
    if (APPROXEQPT(dumb[0], dumb[3], MILLIPOINT)) {
	/* degenerate case */
	dumb[1] = dumb[0];
	dumb[2] = dumb[3];
	del.x = 0;
	del.y = 0;
    }
    else {
        perp.x = dumb[0].y - dumb[3].y;
        perp.y = dumb[3].x - dumb[0].x;
	l_perp = LEN(perp.x, perp.y);
	xstep = GD_nodesep(g->root);
	dx = xstep * (e_cnt - 1) / 2;
	dumb[1].x = dumb[0].x + (dx * perp.x) / l_perp;
	dumb[1].y = dumb[0].y + (dx * perp.y) / l_perp;
	dumb[2].x = dumb[3].x + (dx * perp.x) / l_perp;
	dumb[2].y = dumb[3].y + (dx * perp.y) / l_perp;
	del.x = -xstep * perp.x / l_perp;
	del.y = -xstep * perp.y / l_perp;
    }

    for (i = 0; i < e_cnt; i++) {
	if (aghead(e0) == head) {
	    p = dumb[0];
	    q = dumb[3];
	    for (j = 0; j < 4; j++) {
		dumber[j] = dumb[j];
	    }
	} else {
	    p = dumb[3];
	    q = dumb[0];
	    for (j = 0; j < 4; j++) {
		dumber[3 - j] = dumb[j];
	    }
	}
	if (et == ET_PLINE) {
	    Ppoint_t pts[4];
	    Ppolyline_t spl, line;

	    line.pn = 4;
	    line.ps = pts;
	    for (j=0; j < 4; j++) {
		pts[j] = dumber[j];
	    }
	    make_polyline (line, &spl);
	    clip_and_install(e0, aghead(e0), spl.ps, spl.pn, sinfo);
	}
	else
	    clip_and_install(e0, aghead(e0), dumber, 4, sinfo);

	addEdgeLabels(g, e0, p, q);
	e0 = ED_to_virt(e0);
	dumb[1].x += del.x;
	dumb[1].y += del.y;
	dumb[2].x += del.x;
	dumb[2].y += del.y;
    }
}
コード例 #25
0
ファイル: gvcolor.c プロジェクト: AhmedAMohamed/graphviz
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);
    }
}