예제 #1
0
파일: class1.c 프로젝트: emdenrg/graphviz
void class1(graph_t * g)
{
    node_t *n, *t, *h;
    edge_t *e, *rep;

    mark_clusters(g);
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	for (e = agfstout(g, n); e; e = agnxtout(g, e)) {

	    /* skip edges already processed */
	    if (ED_to_virt(e))
		continue;

	    /* skip edges that we want to ignore in this phase */
	    if (nonconstraint_edge(e))
		continue;

	    t = UF_find(agtail(e));
	    h = UF_find(aghead(e));

	    /* skip self, flat, and intra-cluster edges */
	    if (t == h)
		continue;


	    /* inter-cluster edges require special treatment */
	    if (ND_clust(t) || ND_clust(h)) {
		interclust1(g, agtail(e), aghead(e), e);
		continue;
	    }

	    if ((rep = find_fast_edge(t, h)))
		merge_oneway(e, rep);
	    else
		virtual_edge(t, h, e);

#ifdef NOTDEF
	    if ((t == agtail(e)) && (h == aghead(e))) {
		if (rep = find_fast_edge(t, h))
		    merge_oneway(e, rep);
		else
		    virtual_edge(t, h, e);
	    } else {
		f = agfindedge(g, t, h);
		if (f && (ED_to_virt(f) == NULL))
		    rep = virtual_edge(t, h, f);
		else
		    rep = find_fast_edge(t, h);
		if (rep)
		    merge_oneway(e, rep);
		else
		    virtual_edge(t, h, e);
	    }
#endif
	}
    }
}
예제 #2
0
파일: rank.c 프로젝트: jeci-sarl/graphviz
static void 
node_induce(graph_t * par, graph_t * g)
{
    node_t *n, *nn;
    edge_t *e;
    int i;

    /* enforce that a node is in at most one cluster at this level */
    for (n = agfstnode(g); n; n = nn) {
	nn = agnxtnode(g, n);
	if (ND_ranktype(n)) {
	    agdelete(g, n);
	    continue;
	}
	for (i = 1; i < GD_n_cluster(par); i++)
	    if (agcontains(GD_clust(par)[i], n))
		break;
	if (i < GD_n_cluster(par))
	    agdelete(g, n);
	ND_clust(n) = NULL;
    }

    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	for (e = agfstout(dot_root(g), n); e; e = agnxtout(dot_root(g), e)) {
	    if (agcontains(g, aghead(e)))
		agsubedge(g,e,1);
	}
    }
}
예제 #3
0
파일: class1.c 프로젝트: emdenrg/graphviz
int nonconstraint_edge(edge_t * e)
{
    char *constr;

#ifndef WITH_CGRAPH
    if (E_constr && (constr = agxget(e, E_constr->index))) {
#else /* WITH_CGRAPH */
    if (E_constr && (constr = agxget(e, E_constr))) {
#endif /* WITH_CGRAPH */
	if (constr[0] && mapbool(constr) == FALSE)
	    return TRUE;
    }
    return FALSE;
}

static void 
interclust1(graph_t * g, node_t * t, node_t * h, edge_t * e)
{
    node_t *v, *t0, *h0;
    int offset, t_len, h_len, t_rank, h_rank;
    edge_t *rt, *rh;

    if (ND_clust(agtail(e)))
	t_rank = ND_rank(agtail(e)) - ND_rank(GD_leader(ND_clust(agtail(e))));
    else
	t_rank = 0;
    if (ND_clust(aghead(e)))
	h_rank = ND_rank(aghead(e)) - ND_rank(GD_leader(ND_clust(aghead(e))));
    else
	h_rank = 0;
    offset = ED_minlen(e) + t_rank - h_rank;
    if (offset > 0) {
	t_len = 0;
	h_len = offset;
    } else {
	t_len = -offset;
	h_len = 0;
    }

    v = virtual_node(g);
    ND_node_type(v) = SLACKNODE;
    t0 = UF_find(t);
    h0 = UF_find(h);
    rt = make_aux_edge(v, t0, t_len, CL_BACK * ED_weight(e));
    rh = make_aux_edge(v, h0, h_len, ED_weight(e));
    ED_to_orig(rt) = ED_to_orig(rh) = e;
}
예제 #4
0
파일: cluster.c 프로젝트: emdenrg/graphviz
void install_cluster(graph_t * g, node_t * n, int pass, nodequeue * q)
{
    int r;
    graph_t *clust;

    clust = ND_clust(n);
    if (GD_installed(clust) != pass + 1) {
	for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
	    install_in_rank(g, GD_rankleader(clust)[r]);
	for (r = GD_minrank(clust); r <= GD_maxrank(clust); r++)
	    enqueue_neighbors(q, GD_rankleader(clust)[r], pass);
	GD_installed(clust) = pass + 1;
    }
}
예제 #5
0
파일: cluster.c 프로젝트: emdenrg/graphviz
void mark_lowclusters(Agraph_t * root)
{
    Agnode_t *n, *vn;
    Agedge_t *orig, *e;

    /* first, zap any previous cluster labelings */
    for (n = agfstnode(root); n; n = agnxtnode(root, n)) {
	ND_clust(n) = NULL;
	for (orig = agfstout(root, n); orig; orig = agnxtout(root, 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) = NULL;
		    e = ND_out(aghead(e)).list[0];
		}
	    }
	}
    }

    /* do the recursion */
    mark_lowcluster_basic(root);
}

static void mark_lowcluster_basic(Agraph_t * g)
{
    Agraph_t *clust;
    Agnode_t *n, *vn;
    Agedge_t *orig, *e;
    int c;

    for (c = 1; c <= GD_n_cluster(g); c++) {
	clust = GD_clust(g)[c];
	mark_lowcluster_basic(clust);
    }
    /* see what belongs to this graph that wasn't already marked */
    for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	if (ND_clust(n) == NULL)
	    ND_clust(n) = g;
	for (orig = agfstout(g, n); orig; orig = agnxtout(g, 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 */
		    if (ND_clust(vn) == NULL)
			ND_clust(vn) = g;
		    e = ND_out(aghead(e)).list[0];
		}
	    }
	}
    }
}
예제 #6
0
파일: cluster.c 프로젝트: emdenrg/graphviz
static node_t*
map_interclust_node(node_t * n)
{
    node_t *rv;

#ifndef WITH_CGRAPH
    if ((ND_clust(n) == NULL) || (ND_clust(n)->u.expanded))
#else /* WITH_CGRAPH */
    if ((ND_clust(n) == NULL) || (  GD_expanded(ND_clust(n))) )
#endif /* WITH_CGRAPH */
	rv = n;
    else
#ifndef WITH_CGRAPH
	rv = ND_clust(n)->u.rankleader[ND_rank(n)];
#else /* WITH_CGRAPH */
	rv = GD_rankleader(ND_clust(n))[ND_rank(n)];
#endif /* WITH_CGRAPH */
    return rv;
}
예제 #7
0
파일: poly.c 프로젝트: TidyHuang/vizgems
int makePoly(Poly * pp, Agnode_t * n, float xmargin, float ymargin)
{
    int i;
    int sides;
    Point *verts;
    polygon_t *poly;
    boxf b;

    if (ND_clust(n)) {
	Point b;
	sides = 4;
	b.x = ND_width(n) / 2.0;
	b.y = ND_height(n) / 2.0;
	pp->kind = BOX;
	verts = N_GNEW(sides, Point);
	PUTPT(verts[0], b.x, b.y);
	PUTPT(verts[1], -b.x, b.y);
	PUTPT(verts[2], -b.x, -b.y);
	PUTPT(verts[3], b.x, -b.y);
    } else
	switch (shapeOf(n)) {
	case SH_POLY:
	    poly = (polygon_t *) ND_shape_info(n);
	    sides = poly->sides;
	    if (sides >= 3) {	/* real polygon */
		verts = N_GNEW(sides, Point);
		for (i = 0; i < sides; i++) {
		    verts[i].x = PS2INCH(poly->vertices[i].x);
		    verts[i].y = PS2INCH(poly->vertices[i].y);
		}
	    } else
		verts = genRound(n, &sides, 0, 0);

	    if (streq(ND_shape(n)->name, "box"))
		pp->kind = BOX;
	    else if (streq(ND_shape(n)->name, "polygon")
		     && isBox(verts, sides))
		pp->kind = BOX;
	    else if ((poly->sides < 3) && poly->regular)
		pp->kind = CIRCLE;
	    else
		pp->kind = 0;

	    break;
	case SH_RECORD:
	    sides = 4;
	    verts = N_GNEW(sides, Point);
	    b = ((field_t *) ND_shape_info(n))->b;
	    verts[0] = makeScaledPoint(b.LL.x, b.LL.y);
	    verts[1] = makeScaledPoint(b.UR.x, b.LL.y);
	    verts[2] = makeScaledPoint(b.UR.x, b.UR.y);
	    verts[3] = makeScaledPoint(b.LL.x, b.UR.y);
	    pp->kind = BOX;
	    break;
	case SH_POINT:
	    pp->kind = CIRCLE;
	    verts = genRound(n, &sides, 0, 0);
	    break;
	default:
	    agerr(AGERR, "makePoly: unknown shape type %s\n",
		  ND_shape(n)->name);
	    return 1;
	}

#ifdef OLD
    if (margin != 0.0)
	inflatePts(verts, sides, margin);
#else
    if ((xmargin != 1.0) || (ymargin != 1.0))
	inflatePts(verts, sides, xmargin, ymargin);
#endif

    pp->verts = verts;
    pp->nverts = sides;
    bbox(verts, sides, &pp->origin, &pp->corner);

    if (sides > maxcnt)
	maxcnt = sides;
    return 0;
}
예제 #8
0
파일: poly.c 프로젝트: TidyHuang/vizgems
int makeAddPoly(Poly * pp, Agnode_t * n, float xmargin, float ymargin)
{
    int i;
    int sides;
    Point *verts;
    polygon_t *poly;
    boxf b;

    if (ND_clust(n)) {
	Point b;
	sides = 4;
	b.x = ND_width(n) / 2.0 + xmargin;
	b.y = ND_height(n) / 2.0 + ymargin;
	pp->kind = BOX;
	verts = N_GNEW(sides, Point);
	PUTPT(verts[0], b.x, b.y);
	PUTPT(verts[1], -b.x, b.y);
	PUTPT(verts[2], -b.x, -b.y);
	PUTPT(verts[3], b.x, -b.y);
    } else
	switch (shapeOf(n)) {
	case SH_POLY:
	    poly = (polygon_t *) ND_shape_info(n);
	    sides = poly->sides;

	    if (streq(ND_shape(n)->name, "box"))
		pp->kind = BOX;
	    else if (streq(ND_shape(n)->name, "polygon")
		     && isBox(poly->vertices, sides))
		pp->kind = BOX;
	    else if ((poly->sides < 3) && poly->regular)
		pp->kind = CIRCLE;
	    else
		pp->kind = 0;

	    if (sides >= 3) {	/* real polygon */
		verts = N_GNEW(sides, Point);
		if (pp->kind == BOX) {
			/* To do an additive margin, we rely on knowing that
			 * the vertices are CCW starting from the UR
			 */
		    verts[0].x = PS2INCH(poly->vertices[0].x) + xmargin;
		    verts[0].y = PS2INCH(poly->vertices[0].y) + ymargin;
		    verts[1].x = PS2INCH(poly->vertices[1].x) - xmargin;
		    verts[1].y = PS2INCH(poly->vertices[1].y) + ymargin;
		    verts[2].x = PS2INCH(poly->vertices[2].x) - xmargin;
		    verts[2].y = PS2INCH(poly->vertices[2].y) - ymargin;
		    verts[3].x = PS2INCH(poly->vertices[3].x) + xmargin;
		    verts[3].y = PS2INCH(poly->vertices[3].y) - ymargin;
 
		}
		else {
		    for (i = 0; i < sides; i++) {
                        double h = LEN(poly->vertices[i].x,poly->vertices[i].y);
		        verts[i].x = poly->vertices[i].x * (1.0 + xmargin/h);
		        verts[i].y = poly->vertices[i].y * (1.0 + ymargin/h);
		        verts[i].x = PS2INCH(verts[i].x);
		        verts[i].y = PS2INCH(verts[i].y);
		    }
		}
	    } else
		verts = genRound(n, &sides, xmargin, ymargin);
	    break;
	case SH_RECORD:
	    sides = 4;
	    verts = N_GNEW(sides, Point);
	    b = ((field_t *) ND_shape_info(n))->b;
	    verts[0] = makeScaledTransPoint(b.LL.x, b.LL.y, -xmargin, -ymargin);
	    verts[1] = makeScaledTransPoint(b.UR.x, b.LL.y, xmargin, -ymargin);
	    verts[2] = makeScaledTransPoint(b.UR.x, b.UR.y, xmargin, ymargin);
	    verts[3] = makeScaledTransPoint(b.LL.x, b.UR.y, -xmargin, ymargin);
	    pp->kind = BOX;
	    break;
	case SH_POINT:
	    pp->kind = CIRCLE;
	    verts = genRound(n, &sides, xmargin, ymargin);
	    break;
	default:
	    agerr(AGERR, "makeAddPoly: unknown shape type %s\n",
		  ND_shape(n)->name);
	    return 1;
	}

    pp->verts = verts;
    pp->nverts = sides;
    bbox(verts, sides, &pp->origin, &pp->corner);

    if (sides > maxcnt)
	maxcnt = sides;
    return 0;
}
예제 #9
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)--;
    }
}