示例#1
0
static void figptarray(GVJ_t *job, pointf * A, int n, int close)
{
    int i;
    point p;

    for (i = 0; i < n; i++) {
	PF2P(A[i],p);
        gvprintf(job, " %d %d", p.x, p.y);
    }
    if (close) {
	PF2P(A[0],p);
        gvprintf(job, " %d %d", p.x, p.y);
    }
    gvputs(job, "\n");
}
示例#2
0
point dotneato_closest(splines * spl, point p)
{
    int i, j, k, besti, bestj;
    double bestdist2, d2, dlow2, dhigh2; /* squares of distances */
    double low, high, t;
    pointf c[4], pt2, pt;
    point rv;
    bezier bz;

    besti = bestj = -1;
    bestdist2 = 1e+38;
    P2PF(p, pt);
    for (i = 0; i < spl->size; i++) {
	bz = spl->list[i];
	for (j = 0; j < bz.size; j++) {
	    pointf b;

	    b.x = bz.list[j].x;
	    b.y = bz.list[j].y;
	    d2 = DIST2(b, pt);
	    if ((bestj == -1) || (d2 < bestdist2)) {
		besti = i;
		bestj = j;
		bestdist2 = d2;
	    }
	}
    }

    bz = spl->list[besti];
    j = bestj / 3;
    if (j >= spl->size)
	j--;
    for (k = 0; k < 4; k++) {
	c[k].x = bz.list[j + k].x;
	c[k].y = bz.list[j + k].y;
    }
    low = 0.0;
    high = 1.0;
    dlow2 = DIST2(c[0], pt);
    dhigh2 = DIST2(c[3], pt);
    do {
	t = (low + high) / 2.0;
	pt2 = Bezier(c, 3, t, NULL, NULL);
	if (fabs(dlow2 - dhigh2) < 1.0)
	    break;
	if (fabs(high - low) < .00001)
	    break;
	if (dlow2 < dhigh2) {
	    high = t;
	    dhigh2 = DIST2(pt2, pt);
	} else {
	    low = t;
	    dlow2 = DIST2(pt2, pt);
	}
    } while (1);
    PF2P(pt2, rv);
    return rv;
}
示例#3
0
/* Ensures that a new canvas item is created for this node and moved to right
 * position, or just moves an existing canvas item if already created.
 */
static void
cls_node_ensure_draw (gpointer klass_id, ClsNode *cls_node, ClsBox *bounding_box) 
{
	gdouble x, y;
	point node_pos;
#ifndef ND_coord_i
	pointf node_posf;
#endif
	
	/* get some infos from the node */
#ifdef ND_coord_i
	node_pos = ND_coord_i (cls_node->agnode);
#else
	node_posf = ND_coord (cls_node->agnode);
	PF2P (node_posf, node_pos);
#endif

	/* Determine node coords and size *in* canvas world coordinate system */
	cls_node->width = INCH_TO_PIXELS (ND_width (cls_node->agnode));
	cls_node->height = INCH_TO_PIXELS (ND_height (cls_node->agnode));
	cls_node->x1 = node_pos.x - cls_node->width/2;
	cls_node->y1 = GRAPH_TO_CANVAS_Y ((node_pos.y + cls_node->height/2));
	cls_node->x2 = node_pos.x + cls_node->width/2;
	cls_node->y2 = GRAPH_TO_CANVAS_Y ((node_pos.y - cls_node->height/2));

	if (cls_node->x1 < bounding_box->x1) bounding_box->x1 = cls_node->x1;
	if (cls_node->y1 < bounding_box->y1) bounding_box->y1 = cls_node->y1;
	if (cls_node->x2 > bounding_box->x2) bounding_box->x2 = cls_node->x2;
	if (cls_node->y2 > bounding_box->y2) bounding_box->y2 = cls_node->y2;

	if (cls_node->canvas_group == NULL ||
	    cls_node->drawn_expansion_status != cls_node->expansion_status)
	{
		if (cls_node->expansion_status == CLS_NODE_COLLAPSED)
			cls_node_draw_collapsed (cls_node);
		else
			cls_node_draw_expanded (cls_node);
	}
	/* Move the canvas item to right place */
	x = cls_node->x1;
	y = cls_node->y1;
	foo_canvas_item_set (cls_node->canvas_group, "x", x, "y", y, NULL);
	g_hash_table_foreach (cls_node->edges_to, (GHFunc) cls_node_draw_edge, cls_node);
}
示例#4
0
static void map_output_shape (GVJ_t *job, map_shape_t map_shape, pointf * AF, int nump,
                char* url, char *tooltip, char *target)
{
    int i;

    static point *A;
    static int size_A;

    if (!AF || !nump)
	return;

    if (size_A < nump) {
	size_A = nump + 10;
	A = realloc(A, size_A * sizeof(point));
    }
    for (i = 0; i < nump; i++)
	PF2P(AF[i], A[i]);

    if (job->render.id == FORMAT_IMAP && url && url[0]) {
        switch (map_shape) {
        case MAP_RECTANGLE:
	    /* Y_GOES_DOWN so need UL to LR */
            core_printf(job, "rect %s %d,%d %d,%d\n", url,
                A[0].x, A[1].y, A[1].x, A[0].y);
            break;
        case MAP_CIRCLE:
            core_printf(job, "circle %s %d,%d,%d\n", url,
                A[0].x, A[0].y, A[1].x-A[0].x);
            break;
        case MAP_POLYGON:
            core_printf(job, "poly %s", url);
            for (i = 0; i < nump; i++)
                core_printf(job, " %d,%d", A[i].x, A[i].y);
            core_fputs(job, "\n");
            break;
        default:
            assert(0);
            break;
        }

    } else if (job->render.id == FORMAT_ISMAP && url && url[0]) {
        switch (map_shape) {
        case MAP_RECTANGLE:
	    /* Y_GOES_DOWN so need UL to LR */
            core_printf(job, "rectangle (%d,%d) (%d,%d) %s %s\n",
                A[0].x, A[1].y, A[1].x, A[0].y, url, tooltip);
	    break;
        default:
            assert(0);
            break;
        }

    } else if (job->render.id == FORMAT_CMAP || job->render.id == FORMAT_CMAPX) {
        switch (map_shape) {
        case MAP_CIRCLE:
            core_fputs(job, "<area shape=\"circle\"");
            break;
        case MAP_RECTANGLE:
            core_fputs(job, "<area shape=\"rect\"");
            break;
        case MAP_POLYGON:
            core_fputs(job, "<area shape=\"poly\"");
            break;
        default:
            assert(0);
            break;
        }
        if (url && url[0]) {
            core_fputs(job, " href=\"");
	    core_fputs(job, xml_string(url));
	    core_fputs(job, "\"");
	}
        if (target && target[0]) {
            core_fputs(job, " target=\"");
	    core_fputs(job, xml_string(target));
	    core_fputs(job, "\"");
	}
        if (tooltip && tooltip[0]) {
            core_fputs(job, " title=\"");
	    core_fputs(job, xml_string(tooltip));
	    core_fputs(job, "\"");
	}
        /*
	 * alt text is intended for the visually impaired, but such
	 * folk are not likely to be clicking around on a graph anyway.
	 * IE on the PC platform (but not on Macs) incorrectly
	 * uses (non-empty) alt strings instead of title strings for tooltips.
	 * To make tooltips work and avoid this IE issue,
	 * while still satisfying usability guidelines
	 * that require that there is always an alt string,
	 * we generate just an empty alt string.
	 */
        core_fputs(job, " alt=\"\"");

        core_fputs(job, " coords=\"");
        switch (map_shape) {
        case MAP_CIRCLE:
            core_printf(job, "%d,%d,%d", A[0].x, A[0].y, A[1].x);
            break;
        case MAP_RECTANGLE:
	    /* Y_GOES_DOWN so need UL to LR */
            core_printf(job, "%d,%d,%d,%d", A[0].x, A[1].y, A[1].x, A[0].y);  
            break;
        case MAP_POLYGON:
            core_printf(job, "%d,%d", A[0].x, A[0].y);
            for (i = 1; i < nump; i++)
                core_printf(job, " %d,%d", A[i].x, A[i].y);
            break;
        default:
            break;
        }
        if (job->render.id == FORMAT_CMAPX)
            core_fputs(job, "\"/>\n");
	else
            core_fputs(job, "\">\n");
    }
}
示例#5
0
static void vrml_ellipse(GVJ_t * job, pointf * A, int filled)
{
    FILE *out = job->output_file;
    obj_state_t *obj = job->obj;
    node_t *n;
    edge_t *e;
    double z = obj->z;
    double rx, ry;
    int dx, dy;
    pointf npf, nqf;
    point np;
    int pen;
    gdImagePtr brush = NULL;

    rx = A[1].x - A[0].x;
    ry = A[1].y - A[0].y;

    switch (obj->type) {
    case ROOTGRAPH_OBJTYPE:
    case CLUSTER_OBJTYPE:
	break;
    case NODE_OBJTYPE:
	n = obj->u.n;
	if (shapeOf(n) == SH_POINT) {
	    doSphere (job, n, A[0], z, rx, ry);
	    return;
	}
	pen = set_penstyle(job, im, brush);

	npf = vrml_node_point(job, n, A[0]);
	nqf = vrml_node_point(job, n, A[1]);

	dx = ROUND(2 * (nqf.x - npf.x));
	dy = ROUND(2 * (nqf.y - npf.y));

	PF2P(npf, np);

	if (filled)
	    gdImageFilledEllipse(im, np.x, np.y, dx, dy, color_index(im, obj->fillcolor));
	gdImageArc(im, np.x, np.y, dx, dy, 0, 360, pen);

	if (brush)
	    gdImageDestroy(brush);

	fprintf(out, "Transform {\n");
	fprintf(out, "  translation %.3f %.3f %.3f\n", A[0].x, A[0].y, z);
	fprintf(out, "  scale %.3f %.3f 1\n", rx, ry);
	fprintf(out, "  children [\n");
	fprintf(out, "    Transform {\n");
	fprintf(out, "      rotation 1 0 0   1.57\n");
	fprintf(out, "      children [\n");
	fprintf(out, "        Shape {\n");
	fprintf(out, "          geometry Cylinder { side FALSE }\n");
	fprintf(out, "          appearance Appearance {\n");
	fprintf(out, "            material Material {\n");
	fprintf(out, "              ambientIntensity 0.33\n");
	fprintf(out, "              diffuseColor 1 1 1\n");
	fprintf(out, "            }\n");
	fprintf(out, "            texture ImageTexture { url \"node%d.png\" }\n", n->id);
	fprintf(out, "          }\n");
	fprintf(out, "        }\n");
	fprintf(out, "      ]\n");
	fprintf(out, "    }\n");
	fprintf(out, "  ]\n");
	fprintf(out, "}\n");
	break;
    case EDGE_OBJTYPE:
	e = obj->u.e;
	/* this is gruesome, but how else can we get z coord */
	if (DIST2(A[0], ND_coord_i(e->tail)) < DIST2(A[0], ND_coord_i(e->head)))
	    z = obj->tail_z;
	else
	    z = obj->head_z;

	fprintf(out, "Transform {\n");
	fprintf(out, "  translation %.3f %.3f %.3f\n", A[0].x, A[0].y, z);
	fprintf(out, "  children [\n");
	fprintf(out, "    Shape {\n");
	fprintf(out, "      geometry Sphere {radius %.3f }\n", (double) rx);
	fprintf(out, "      appearance USE E%d\n", e->id);
	fprintf(out, "    }\n");
	fprintf(out, "  ]\n");
	fprintf(out, "}\n");
    }
}
示例#6
0
文件: input.c 项目: ekoontz/graphviz
/* do_graph_label:
 * Set characteristics of graph label if it exists.
 * 
 */
void do_graph_label(graph_t * sg)
{
    char *p, *pos, *just;
    int pos_ix;

    /* it would be nice to allow multiple graph labels in the future */
    if ((p = agget(sg, "label"))) {
	char pos_flag;
	int lbl_kind = LT_NONE;
	point dpt;
	pointf dimen;

	if (aghtmlstr(p)) lbl_kind = LT_HTML;
	GD_has_labels(sg->root) |= GRAPH_LABEL;
        if (lbl_kind) p = strdup (p);
	else p = strdup_and_subst_obj(p, (void*)sg);
	GD_label(sg) = make_label(sg->root, lbl_kind, p,
				  late_double(sg,
					      agfindattr(sg, "fontsize"),
					      DEFAULT_FONTSIZE, MIN_FONTSIZE),
				  late_nnstring(sg,
						agfindattr(sg, "fontname"),
						DEFAULT_FONTNAME),
				  late_nnstring(sg,
						agfindattr(sg, "fontcolor"),
						DEFAULT_COLOR));
	if (lbl_kind) {
	    if (make_html_label(sg->root, GD_label(sg), sg) == 1)
		agerr(AGPREV, "in label of graph %s\n", sg->name);
	}

	/* set label position */
	pos = agget(sg, "labelloc");
	if (sg != sg->root) {
	    if (pos && (pos[0] == 'b'))
		pos_flag = LABEL_AT_BOTTOM;
	    else
		pos_flag = LABEL_AT_TOP;
	} else {
	    if (pos && (pos[0] == 't'))
		pos_flag = LABEL_AT_TOP;
	    else
		pos_flag = LABEL_AT_BOTTOM;
	}
	just = agget(sg, "labeljust");
	if (just) {
	    if (just[0] == 'l')
		pos_flag |= LABEL_AT_LEFT;
	    else if (just[0] == 'r')
		pos_flag |= LABEL_AT_RIGHT;
	}
	GD_label_pos(sg) = pos_flag;

	if (sg == sg->root)
	    return;

	/* Set border information for cluster labels to allow space
	 */
	dimen = GD_label(sg)->dimen;
	PAD(dimen);
	PF2P(dimen, dpt);
	if (!GD_flip(sg->root)) {
	    if (GD_label_pos(sg) & LABEL_AT_TOP)
		pos_ix = TOP_IX;
	    else
		pos_ix = BOTTOM_IX;
	    GD_border(sg)[pos_ix] = dpt;
	} else {
	    /* when rotated, the labels will be restored to TOP or BOTTOM  */
	    if (GD_label_pos(sg) & LABEL_AT_TOP)
		pos_ix = RIGHT_IX;
	    else
		pos_ix = LEFT_IX;
	    GD_border(sg)[pos_ix].x = dpt.y;
	    GD_border(sg)[pos_ix].y = dpt.x;
	}
    }
}
示例#7
0
/* dotneato_postprocess:
 * Set graph and cluster label positions.
 * Add space for root graph label and translate graph accordingly.
 * Set final nodesize using ns.
 * Assumes the boxes of all clusters have been computed.
 * When done, the bounding box of g has LL at origin.
 */
void dotneato_postprocess(Agraph_t * g)
{
    int diff;
    pointf dimen;
    point d = { 0, 0 };

    Rankdir = GD_rankdir(g);
    Flip = GD_flip(g);
    if (Flip)
	place_flip_graph_label(g);
    else
	place_graph_label(g);

    if (GD_label(g) && !GD_label(g)->set) {
	dimen = GD_label(g)->dimen;
	PAD(dimen);
	PF2P(dimen, d);
	if (Flip) {
	    if (GD_label_pos(g) & LABEL_AT_TOP) {
		GD_bb(g).UR.x += d.y;
	    } else {
		GD_bb(g).LL.x -= d.y;
	    }

	    if (d.x > GD_bb(g).UR.y - GD_bb(g).LL.y) {
		diff = d.x - (GD_bb(g).UR.y - GD_bb(g).LL.y);
		diff = diff / 2;
		GD_bb(g).LL.y -= diff;
		GD_bb(g).UR.y += diff;
	    }
	} else {
	    if (GD_label_pos(g) & LABEL_AT_TOP) {
		if (Rankdir == RANKDIR_TB)
		    GD_bb(g).UR.y += d.y;
		else
		    GD_bb(g).LL.y -= d.y;
	    } else {
		if (Rankdir == RANKDIR_TB)
		    GD_bb(g).LL.y -= d.y;
		else
		    GD_bb(g).UR.y += d.y;
	    }

	    if (d.x > GD_bb(g).UR.x - GD_bb(g).LL.x) {
		diff = d.x - (GD_bb(g).UR.x - GD_bb(g).LL.x);
		diff = diff / 2;
		GD_bb(g).LL.x -= diff;
		GD_bb(g).UR.x += diff;
	    }
	}
    }
    switch (Rankdir) {
    case RANKDIR_TB:
	Offset = GD_bb(g).LL;
	break;
    case RANKDIR_LR:
	Offset = pointof(-GD_bb(g).UR.y, GD_bb(g).LL.x);
	break;
    case RANKDIR_BT:
	Offset = pointof(GD_bb(g).LL.x, -GD_bb(g).UR.y);
	break;
    case RANKDIR_RL:
	Offset = pointof(GD_bb(g).LL.y, GD_bb(g).LL.x);
	break;
    }
    translate_drawing(g);
    if (GD_label(g) && !GD_label(g)->set)
	place_root_label(g, d);

    if (Show_boxes) {
	char buf[BUFSIZ];
	if (Flip)
	    sprintf(buf, M2, Offset.x, Offset.y, Offset.x, Offset.y);
	else
	    sprintf(buf, M1, Offset.y, Offset.x, Offset.y, Offset.x, 
                 -Offset.x, -Offset.y);
	Show_boxes[0] = strdup(buf);
    }
}
示例#8
0
文件: layout.c 项目: zionyx/graphviz
/* finalCC:
 * Set graph bounding box given list of connected
 * components, each with its bounding box set.
 * If c_cnt > 1, then pts != NULL and gives translations for components.
 * Add margin about whole graph unless isRoot is true.
 * Reposition nodes based on final position of
 * node's connected component.
 * Also, entire layout is translated to origin.
 */
static void
finalCC(graph_t * g, int c_cnt, graph_t ** cc, point * pts, graph_t * rg,
	layout_info* infop)
{
    attrsym_t * G_width = infop->G_width;
    attrsym_t * G_height = infop->G_height;
    graph_t *cg;
    box b, bb;
    boxf bbf;
    point pt;
    int margin;
    graph_t **cp = cc;
    point *pp = pts;
    int isRoot = (rg == infop->rootg);
    int isEmpty = 0;

    /* compute graph bounding box in points */
    if (c_cnt) {
	cg = *cp++;
	BF2B(GD_bb(cg), bb);
	if (c_cnt > 1) {
	    pt = *pp++;
	    bb.LL.x += pt.x;
	    bb.LL.y += pt.y;
	    bb.UR.x += pt.x;
	    bb.UR.y += pt.y;
	    while ((cg = *cp++)) {
		BF2B(GD_bb(cg), b);
		pt = *pp++;
		b.LL.x += pt.x;
		b.LL.y += pt.y;
		b.UR.x += pt.x;
		b.UR.y += pt.y;
		bb.LL.x = MIN(bb.LL.x, b.LL.x);
		bb.LL.y = MIN(bb.LL.y, b.LL.y);
		bb.UR.x = MAX(bb.UR.x, b.UR.x);
		bb.UR.y = MAX(bb.UR.y, b.UR.y);
	    }
	}
    } else {			/* empty graph */
	bb.LL.x = 0;
	bb.LL.y = 0;
	bb.UR.x = late_int(rg, G_width, POINTS(DEFAULT_NODEWIDTH), 3);
	bb.UR.y = late_int(rg, G_height, POINTS(DEFAULT_NODEHEIGHT), 3);
	isEmpty = 1;
    }

    if (GD_label(rg)) {
	point p;
	int d;

	isEmpty = 0;
	PF2P(GD_label(rg)->dimen, p);
	d = p.x - (bb.UR.x - bb.LL.x);
	if (d > 0) {		/* height of label added below */
	    d /= 2;
	    bb.LL.x -= d;
	    bb.UR.x += d;
	}
    }

    if (isRoot || isEmpty)
	margin = 0;
    else
	margin = late_int (g, G_margin, CL_OFFSET, 0);
    pt.x = -bb.LL.x + margin;
    pt.y = -bb.LL.y + margin + GD_border(rg)[BOTTOM_IX].y;
    bb.LL.x = 0;
    bb.LL.y = 0;
    bb.UR.x += pt.x + margin;
    bb.UR.y += pt.y + margin + GD_border(rg)[TOP_IX].y;

    /* translate nodes */
    if (c_cnt) {
	cp = cc;
	pp = pts;
	while ((cg = *cp++)) {
	    point p;
	    node_t *n;
	    pointf del;

	    if (pp) {
		p = *pp++;
		p.x += pt.x;
		p.y += pt.y;
	    } else {
		p = pt;
	    }
	    del.x = PS2INCH(p.x);
	    del.y = PS2INCH(p.y);
	    for (n = agfstnode(cg); n; n = agnxtnode(cg, n)) {
		ND_pos(n)[0] += del.x;
		ND_pos(n)[1] += del.y;
	    }
	}
    }

    bbf.LL.x = PS2INCH(bb.LL.x);
    bbf.LL.y = PS2INCH(bb.LL.y);
    bbf.UR.x = PS2INCH(bb.UR.x);
    bbf.UR.y = PS2INCH(bb.UR.y);
    BB(g) = bbf;

}