예제 #1
0
파일: poly.c 프로젝트: cogitokat/brlcad
/**
 * R T _ P G _ P L O T
 */
int
rt_pg_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    size_t i;
    size_t p;	/* current polygon number */
    struct rt_pg_internal *pgp;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    pgp = (struct rt_pg_internal *)ip->idb_ptr;
    RT_PG_CK_MAGIC(pgp);

    for (p = 0; p < pgp->npoly; p++) {
	struct rt_pg_face_internal *pp;

	pp = &pgp->poly[p];
	RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)],
		     BN_VLIST_LINE_MOVE);
	for (i=0; i < pp->npts; i++) {
	    RT_ADD_VLIST(vhead, &pp->verts[3*i],
			 BN_VLIST_LINE_DRAW);
	}
    }
    return 0;		/* OK */
}
예제 #2
0
파일: poly.c 프로젝트: cogitokat/brlcad
/**
 * R T _ P G _ P L O T _ P O L Y
 *
 * Convert to vlist, draw as polygons.
 */
int
rt_pg_plot_poly(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol))
{
    size_t i;
    size_t p;	/* current polygon number */
    struct rt_pg_internal *pgp;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    pgp = (struct rt_pg_internal *)ip->idb_ptr;
    RT_PG_CK_MAGIC(pgp);

    for (p = 0; p < pgp->npoly; p++) {
	struct rt_pg_face_internal *pp;
	vect_t aa, bb, norm;

	pp = &pgp->poly[p];
	if (pp->npts < 3)
	    continue;
	VSUB2(aa, &pp->verts[3*(0)], &pp->verts[3*(1)]);
	VSUB2(bb, &pp->verts[3*(0)], &pp->verts[3*(2)]);
	VCROSS(norm, aa, bb);
	VUNITIZE(norm);
	RT_ADD_VLIST(vhead, norm, BN_VLIST_POLY_START);

	RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_POLY_MOVE);
	for (i=0; i < pp->npts-1; i++) {
	    RT_ADD_VLIST(vhead, &pp->verts[3*i], BN_VLIST_POLY_DRAW);
	}
	RT_ADD_VLIST(vhead, &pp->verts[3*(pp->npts-1)], BN_VLIST_POLY_END);
    }
    return 0;		/* OK */
}
void
plot_ellipse(
	struct bu_list *vhead,
	const vect_t center,
	const vect_t axis_a,
	const vect_t axis_b,
	int num_points)
{
    int i;
    point_t p;
    fastf_t radian, radian_step;

    radian_step = M_2PI / num_points;

    ellipse_point_at_radian(p, center, axis_a, axis_b,
	    radian_step * (num_points - 1));
    RT_ADD_VLIST(vhead, p, BN_VLIST_LINE_MOVE);

    radian = 0;
    for (i = 0; i < num_points; ++i) {
	ellipse_point_at_radian(p, center, axis_a, axis_b, radian);
	RT_ADD_VLIST(vhead, p, BN_VLIST_LINE_DRAW);

	radian += radian_step;
    }
}
예제 #4
0
파일: superell.c 프로젝트: kanzure/brlcad
int
rt_superell_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    int i;
    struct rt_superell_internal *eip;
    fastf_t top[16*3];
    fastf_t middle[16*3];
    fastf_t bottom[16*3];

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    eip = (struct rt_superell_internal *)ip->idb_ptr;
    RT_SUPERELL_CK_MAGIC(eip);

    rt_superell_16pts(top, eip->v, eip->a, eip->b);
    rt_superell_16pts(bottom, eip->v, eip->b, eip->c);
    rt_superell_16pts(middle, eip->v, eip->a, eip->c);

    RT_ADD_VLIST(vhead, &top[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i=0; i<16; i++) {
        RT_ADD_VLIST(vhead, &top[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
    }

    RT_ADD_VLIST(vhead, &bottom[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i=0; i<16; i++) {
        RT_ADD_VLIST(vhead, &bottom[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
    }

    RT_ADD_VLIST(vhead, &middle[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i=0; i<16; i++) {
        RT_ADD_VLIST(vhead, &middle[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
    }
    return 0;
}
void
rt_metaball_plot_sph(struct bu_list *vhead, point_t *center, fastf_t radius)
{
    fastf_t top[16*3], middle[16*3], bottom[16*3];
    point_t a, b, c;
    int i;

    BU_CK_LIST_HEAD(vhead);

    VSET(a, radius, 0, 0);
    VSET(b, 0, radius, 0);
    VSET(c, 0, 0, radius);
    rt_ell_16pts(top, *center, a, b);
    rt_ell_16pts(bottom, *center, b, c);
    rt_ell_16pts(middle, *center, a, c);

    RT_ADD_VLIST(vhead, &top[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i = 0; i < 16; i++) RT_ADD_VLIST(vhead, &top[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
    RT_ADD_VLIST(vhead, &bottom[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i = 0; i < 16; i++) RT_ADD_VLIST(vhead, &bottom[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
    RT_ADD_VLIST(vhead, &middle[15*ELEMENTS_PER_VECT], BN_VLIST_LINE_MOVE);
    for (i = 0; i < 16; i++) RT_ADD_VLIST(vhead, &middle[i*ELEMENTS_PER_VECT], BN_VLIST_LINE_DRAW);
}
예제 #6
0
파일: revolve.c 프로젝트: kanzure/brlcad
int
rt_revolve_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *ttol, const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    struct rt_revolve_internal *rip;

    size_t nvert, narc, nadd, nseg, i, j, k;
    point2d_t *verts;
    struct rt_curve *crv;

    vect_t ell[16], cir[16], ucir[16], height, xdir, ydir, ux, uy, uz, rEnd, xEnd, yEnd;
    fastf_t cos22_5 = 0.9238795325112867385;
    fastf_t cos67_5 = 0.3826834323650898373;
    int *endcount = NULL;
    point_t add, add2, add3;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    rip = (struct rt_revolve_internal *)ip->idb_ptr;
    RT_REVOLVE_CK_MAGIC(rip);

    nvert = rip->skt->vert_count;
    verts = rip->skt->verts;
    crv = &rip->skt->curve;

    if (rip->ang < M_2PI) {
	narc = ceil(rip->ang * 8 * M_1_PI);
    } else {
	narc = 16;
    }
    VSCALE(xEnd, rip->r, cos(rip->ang));
    VCROSS(rEnd, rip->axis3d, rip->r);	/* using rEnd for temp storage */
    VSCALE(yEnd, rEnd, sin(rip->ang));
    VADD2(rEnd, xEnd, yEnd);

    VMOVE(uz, rip->axis3d);
    VMOVE(ux, rip->r);
    VCROSS(uy, uz, ux);

    VUNITIZE(ux);
    VUNITIZE(uy);
    VUNITIZE(uz);

    /* setup unit circle to be scaled */
    VMOVE(ucir[ 0], ux);
    VREVERSE(ucir[ 8], ucir[0]);

    VSCALE(xdir, ux, cos22_5);
    VSCALE(ydir, uy, cos67_5);
    VADD2(ucir[ 1], xdir, ydir);
    VREVERSE(ucir[ 9], ucir[1]);
    VREVERSE(xdir, xdir);
    VADD2(ucir[ 7], xdir, ydir);
    VREVERSE(ucir[15], ucir[7]);

    VSCALE(xdir, ux, M_SQRT1_2);
    VSCALE(ydir, uy, M_SQRT1_2);
    VADD2(ucir[ 2], xdir, ydir);
    VREVERSE(ucir[10], ucir[2]);
    VREVERSE(xdir, xdir);
    VADD2(ucir[ 6], xdir, ydir);
    VREVERSE(ucir[14], ucir[6]);


    VSCALE(xdir, ux, cos67_5);
    VSCALE(ydir, uy, cos22_5);
    VADD2(ucir[ 3], xdir, ydir);
    VREVERSE(ucir[11], ucir[3]);
    VREVERSE(xdir, xdir);
    VADD2(ucir[ 5], xdir, ydir);
    VREVERSE(ucir[13], ucir[5]);

    VMOVE(ucir[ 4], uy);
    VREVERSE(ucir[12], ucir[4]);

    /* find open endpoints, and determine which points are used */
    if (nvert)
	endcount = (int *)bu_calloc(nvert, sizeof(int), "endcount");

    nseg = rip->skt->curve.count;

    for (i=0; i<nseg; i++) {
	uint32_t *lng;
	struct line_seg *lsg;
	struct carc_seg *csg;
	struct nurb_seg *nsg;
	struct bezier_seg *bsg;

	lng = (uint32_t *)rip->skt->curve.segment[i];

	switch (*lng) {
	    case CURVE_LSEG_MAGIC:
		lsg = (struct line_seg *)lng;
		endcount[lsg->start]++;
		endcount[lsg->end]++;
		break;
	    case CURVE_CARC_MAGIC:
		csg = (struct carc_seg *)lng;
		if (csg->radius <= 0.0) break;
		endcount[csg->start]++;
		endcount[csg->end]++;
		break;
	    case CURVE_BEZIER_MAGIC:
		bsg = (struct bezier_seg *)lng;
		endcount[bsg->ctl_points[0]]++;
		endcount[bsg->ctl_points[bsg->degree]]++;
		break;
	    case CURVE_NURB_MAGIC:
		nsg = (struct nurb_seg *)lng;
		endcount[nsg->ctl_points[0]]++;
		endcount[nsg->ctl_points[nsg->c_size-1]]++;
		break;
	    default:
		bu_log("rt_revolve_prep: ERROR: unrecognized segment type!\n");
		break;
	}
    }

    /* draw circles */
    for (i=0; i<nvert; i++) {
	if (endcount[i] == 0) continue;
	VSCALE(height, uz, verts[i][Y]);
	for (j=0; j<narc; j++) {
	    VSCALE(cir[j], ucir[j], verts[i][X]);
	    VADD3(ell[j], rip->v3d, cir[j], height);
	}
	RT_ADD_VLIST(vhead, ell[0], BN_VLIST_LINE_MOVE);
	for (j=1; j<narc; j++) {
	    RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW);
	}
	if (narc < 16) {
	    VSCALE(cir[narc], rEnd, verts[i][X]);
	    VADD3(ell[narc], rip->v3d, cir[narc], height);
	    RT_ADD_VLIST(vhead, ell[narc], BN_VLIST_LINE_DRAW);
	} else {
	    RT_ADD_VLIST(vhead, ell[0], BN_VLIST_LINE_DRAW);
	}
    }

    /* convert endcounts to store which endpoints are odd */
    for (i=0, j=0; i<rip->skt->vert_count; i++) {
	if (endcount[i] % 2 != 0) {
	    /* add 'i' to list, insertion sort by vert[i][Y] */
	    for (k=j; k>0; k--) {
		if ((ZERO(verts[i][Y] - verts[endcount[k-1]][Y])
		     && verts[i][X] > verts[endcount[k-1]][X])
		    || (!ZERO(verts[i][Y] - verts[endcount[k-1]][Y])
			&& verts[i][Y] < verts[endcount[k-1]][Y])) {
		    endcount[k] = endcount[k-1];
		} else {
		    break;
		}
	    }
	    endcount[k] = i;
	    j++;
	}
    }
    nadd = j;
    while (j < rip->skt->vert_count) {
	endcount[j++] = -1;
    }

    /* draw sketch outlines */
    for (i=0; i<narc; i++) {
	curve_to_vlist(vhead, ttol, rip->v3d, ucir[i], uz, rip->skt, crv);
	for (j=0; j<nadd; j++) {
	    if (j+1 < nadd &&
		ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], ucir[i]);
		VJOIN1(add3, add, verts[endcount[j+1]][X], ucir[i]);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add3, BN_VLIST_LINE_DRAW);
		j++;
	    } else {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], ucir[i]);
		RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
	    }
	}
    }
    if (narc < 16) {
	curve_to_vlist(vhead, ttol, rip->v3d, rEnd, uz, rip->skt, crv);
	for (j=0; j<nadd; j++) {
	    if (j+1 < nadd &&
		ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], rEnd);
		VJOIN1(add3, add, verts[endcount[j+1]][X], rEnd);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add3, BN_VLIST_LINE_DRAW);
		j++;
	    } else {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, add, verts[endcount[j]][X], rEnd);
		RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
	    }
	}
	for (j=0; j<nadd; j+=2) {
	    if (!ZERO(verts[endcount[j]][Y] - verts[endcount[j+1]][Y])) {
		VJOIN1(add, rip->v3d, verts[endcount[j]][Y], rip->axis3d);
		VJOIN1(add2, rip->v3d, verts[endcount[j+1]][Y], rip->axis3d);
		RT_ADD_VLIST(vhead, add, BN_VLIST_LINE_MOVE);
		RT_ADD_VLIST(vhead, add2, BN_VLIST_LINE_DRAW);
	    }
	}
    }

    if (nvert)
	bu_free(endcount, "endcount");
    return 0;
}
예제 #7
0
파일: hyp.c 프로젝트: kanzure/brlcad
int
rt_hyp_plot(struct bu_list *vhead, struct rt_db_internal *incoming, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *UNUSED(tol), const struct rt_view_info *UNUSED(info))
{
    int i, j;		/* loop indices */
    struct rt_hyp_internal *hyp_in;
    struct hyp_specific *hyp;
    vect_t majorAxis[8],	/* vector offsets along major axis */
	minorAxis[8],		/* vector offsets along minor axis */
	heightAxis[7],		/* vector offsets for layers */
	Bunit;			/* unit vector along semi-minor axis */
    vect_t ell[16];		/* stores 16 points to draw ellipses */
    vect_t ribs[16][7];		/* assume 7 layers for now */
    fastf_t scale;		/* used to calculate semi-major/minor axes for top/bottom */
    fastf_t cos22_5 = 0.9238795325112867385;
    fastf_t cos67_5 = 0.3826834323650898373;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(incoming);
    hyp_in = (struct rt_hyp_internal *)incoming->idb_ptr;
    RT_HYP_CK_MAGIC(hyp_in);

    hyp = hyp_internal_to_specific(hyp_in);

    VCROSS(Bunit, hyp->hyp_H, hyp->hyp_Au);
    VUNITIZE(Bunit);

    VMOVE(heightAxis[0], hyp->hyp_H);
    VSCALE(heightAxis[1], heightAxis[0], 0.5);
    VSCALE(heightAxis[2], heightAxis[0], 0.25);
    VSETALL(heightAxis[3], 0);
    VREVERSE(heightAxis[4], heightAxis[2]);
    VREVERSE(heightAxis[5], heightAxis[1]);
    VREVERSE(heightAxis[6], heightAxis[0]);

    for (i = 0; i < 7; i++) {
	/* determine Z height depending on i */
	scale = sqrt(MAGSQ(heightAxis[i])*(hyp->hyp_c * hyp->hyp_c)/(hyp->hyp_r1 * hyp->hyp_r1) + 1);

	/* calculate vectors for offset */
	VSCALE(majorAxis[0], hyp->hyp_Au, hyp->hyp_r1 * scale);
	VSCALE(majorAxis[1], majorAxis[0], cos22_5);
	VSCALE(majorAxis[2], majorAxis[0], M_SQRT1_2);
	VSCALE(majorAxis[3], majorAxis[0], cos67_5);
	VREVERSE(majorAxis[4], majorAxis[3]);
	VREVERSE(majorAxis[5], majorAxis[2]);
	VREVERSE(majorAxis[6], majorAxis[1]);
	VREVERSE(majorAxis[7], majorAxis[0]);

	VSCALE(minorAxis[0], Bunit, hyp->hyp_r2 * scale);
	VSCALE(minorAxis[1], minorAxis[0], cos22_5);
	VSCALE(minorAxis[2], minorAxis[0], M_SQRT1_2);
	VSCALE(minorAxis[3], minorAxis[0], cos67_5);
	VREVERSE(minorAxis[4], minorAxis[3]);
	VREVERSE(minorAxis[5], minorAxis[2]);
	VREVERSE(minorAxis[6], minorAxis[1]);
	VREVERSE(minorAxis[7], minorAxis[0]);

	/* calculate ellipse */
	VADD3(ell[ 0], hyp->hyp_V, heightAxis[i], majorAxis[0]);
	VADD4(ell[ 1], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[3]);
	VADD4(ell[ 2], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[2]);
	VADD4(ell[ 3], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[1]);
	VADD3(ell[ 4], hyp->hyp_V, heightAxis[i], minorAxis[0]);
	VADD4(ell[ 5], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[1]);
	VADD4(ell[ 6], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[2]);
	VADD4(ell[ 7], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[3]);
	VADD3(ell[ 8], hyp->hyp_V, heightAxis[i], majorAxis[7]);
	VADD4(ell[ 9], hyp->hyp_V, heightAxis[i], majorAxis[6], minorAxis[4]);
	VADD4(ell[10], hyp->hyp_V, heightAxis[i], majorAxis[5], minorAxis[5]);
	VADD4(ell[11], hyp->hyp_V, heightAxis[i], majorAxis[4], minorAxis[6]);
	VADD3(ell[12], hyp->hyp_V, heightAxis[i], minorAxis[7]);
	VADD4(ell[13], hyp->hyp_V, heightAxis[i], majorAxis[3], minorAxis[6]);
	VADD4(ell[14], hyp->hyp_V, heightAxis[i], majorAxis[2], minorAxis[5]);
	VADD4(ell[15], hyp->hyp_V, heightAxis[i], majorAxis[1], minorAxis[4]);

	/* draw ellipse */
	RT_ADD_VLIST(vhead, ell[15], BN_VLIST_LINE_MOVE);
	for (j = 0; j < 16; j++) {
	    RT_ADD_VLIST(vhead, ell[j], BN_VLIST_LINE_DRAW);
	}

	/* add ellipse's points to ribs */
	for (j = 0; j < 16; j++) {
	    VMOVE(ribs[j][i], ell[j]);
	}
    }

    /* draw ribs */
    for (i = 0; i < 16; i++) {
	RT_ADD_VLIST(vhead, ribs[i][0], BN_VLIST_LINE_MOVE);
	for (j = 1; j < 7; j++) {
	    RT_ADD_VLIST(vhead, ribs[i][j], BN_VLIST_LINE_DRAW);
	}

    }

    BU_PUT(hyp, struct hyp_specific);

    return 0;
}
/**********************************************************
 *   Code for identifying semi-flat patches in bots
 *   and creating wireframe edges
 **********************************************************/
extern "C" int
rt_bot_adaptive_plot(struct rt_db_internal *ip, const struct rt_view_info *info)
{
    struct rt_bot_internal *bot;
    RT_CK_DB_INTERNAL(ip);
    BU_CK_LIST_HEAD(info->vhead);
    bot = (struct rt_bot_internal *)ip->idb_ptr;
    RT_BOT_CK_MAGIC(bot);
    vect_t gvects[6];
    VSET(gvects[0], -1,0,0);
    VSET(gvects[1], 0,-1,0);
    VSET(gvects[2], 0,0,-1);
    VSET(gvects[3], 1,0,0);
    VSET(gvects[4], 0,1,0);
    VSET(gvects[5], 0,0,1);

    if (bot->num_vertices <= 0 || !bot->vertices || bot->num_faces <= 0 || !bot->faces)
        return 0;

    /* Declare key containers */
    double *face_normals= (double *)bu_calloc(bot->num_faces * 3, sizeof(double), "normals");
    /* Stash all the initial categorization test results - can be re-used later */
//    unsigned int *categorization_results = (unsigned int *)bu_calloc(sizeof(unsigned int) * bot->num_faces * 6, "categorization results");
    /* Initial group assignments */
    unsigned int *groups = (unsigned int *)bu_calloc(bot->num_faces, sizeof(unsigned int), "groups");
    /* Initially, patch breakdown is made in a faces -> patch_id map */
    unsigned int *patches= (unsigned int *)bu_calloc(bot->num_faces, sizeof(unsigned int), "patch_id_numbers");
    /* Don't know yet how big these needs to be */
    unsigned int *vert_to_face = NULL;

    /* Sanity check vertex indices in face definitions */
    for (unsigned int i = 0; i < bot->num_faces; ++i) {
        if ((unsigned int)bot->faces[i*3+0] > (unsigned int)(bot->num_vertices)) return 0;
        if ((unsigned int)bot->faces[i*3+1] > (unsigned int)(bot->num_vertices)) return 0;
        if ((unsigned int)bot->faces[i*3+2] > (unsigned int)(bot->num_vertices)) return 0;
    }

    /* Pre-compute face normals once */
    for (unsigned int i = 0; i < bot->num_faces; i++) {
	vect_t a, b, norm_dir;
	VSUB2(a, &bot->vertices[bot->faces[i*3+1]*3], &bot->vertices[bot->faces[i*3]*3]);
	VSUB2(b, &bot->vertices[bot->faces[i*3+2]*3], &bot->vertices[bot->faces[i*3]*3]);
	VCROSS(norm_dir, a, b);
	VUNITIZE(norm_dir);
	face_normals[i*3]=norm_dir[0];
	face_normals[i*3+1]=norm_dir[1];
	face_normals[i*3+2]=norm_dir[2];
    }

    /* Calculate categorization results and assign groups */
    for (unsigned int i = 0; i < bot->num_faces; i++) {
	int result_max = 0;
	double result = 0.0;
	double vdot = 0.0;
	vect_t norm_dir;
	VSET(norm_dir, face_normals[i*3], face_normals[i*3+1], face_normals[i*3+2]);
	for (unsigned int j=0; j < 6; j++) {
	    vdot = VDOT(gvects[j],norm_dir);
	    //categorization_results[i*j] = vdot;
	    if (vdot > result) {
		result_max = j;
		result = vdot;
	    }
	}
        groups[i] = result_max;
    }
    bu_free(face_normals, "face_normals");

    /* Determine the maximum number of faces associated with any one vertex */
    unsigned int *vert_face_cnt = (unsigned int *)bu_calloc(bot->num_vertices, sizeof(unsigned int), "vert face cnt");
    for (unsigned int i = 0; i < bot->num_faces; i++) {
        vert_face_cnt[bot->faces[i*3+0]]++;
        vert_face_cnt[bot->faces[i*3+1]]++;
        vert_face_cnt[bot->faces[i*3+2]]++;
    }
    unsigned int max_face_cnt = 0;
    for (unsigned int i = 0; i < bot->num_vertices; i++) {
	if (vert_face_cnt[i] > max_face_cnt)
	    max_face_cnt = vert_face_cnt[i];
    }
    /* Now, allocate a 2D array that can hold the full vert->face map
     * and populate it */
    vert_to_face = (unsigned int *)bu_calloc(bot->num_vertices * max_face_cnt, sizeof(unsigned int), "map");
    unsigned int *vert_sizes = (unsigned int *)bu_calloc(bot->num_vertices, sizeof(unsigned int), "map");
    for (unsigned int i = 0; i < bot->num_faces; i++) {
	for (unsigned int j = 0; j < 3; j++) {
	    unsigned int vert = bot->faces[i*3+j];
            unsigned int k = vert_sizes[vert];
            /* rows are vertex indexes, columns hold the faces */
            /* Need to increment face index by one so we can reference
	     * the first face and still use the true/false test that 0 allows */
	    vert_to_face[max_face_cnt * vert + k] = i + 1;
            vert_sizes[vert]++;
            //bu_log("vert_to_face(%d,%d)[%d] = %d\n", vert, k, max_face_cnt * vert + k, i + 1);
	}
    }


    /* Order the groups by number of bots */
    /* Note - needed only when group boarders are not enforced in patch building */
//    unsigned int group_cnt[6] = {0};
    unsigned int ordered_groups[6] = {0,1,2,3,4,5};
/*    for (unsigned int i = 0; i < bot->num_faces; i++) {
        group_cnt[groups[i]]++;
    }
    for (unsigned int i = 0; i < 6; i++) {
        unsigned int more = 0;
	for (unsigned int j = 0; j < 6; j++) {
            if (group_cnt[j] > group_cnt[i]) more++;
	}
        ordered_groups[more] = i;
    }
*/


    // All faces must belong to some patch - continue until all faces are processed
    unsigned int patch_cnt = 0;
    for (unsigned int i = 0; i < 6; i++) {
	int unused = 0;
	while (unused != -1) {
            unsigned int face_stp = 0;
	    // Start a new patch
	    unused = -1;
	    patch_cnt++;
	    // Find remaining face in group
	    while (unused == -1 && face_stp < bot->num_faces) {
		if (ordered_groups[i] == groups[face_stp] && !patches[face_stp]) {
                   unused = face_stp;
		}
                face_stp++;
            }
	    if (unused != -1) {
		std::queue<unsigned int> face_queue;
		face_queue.push(unused);
		patches[unused] = patch_cnt;
		while (!face_queue.empty()) {
		    unsigned int face_num = face_queue.front();
		    face_queue.pop();
		    for (unsigned int k = 0; k < 3; k++) {
			unsigned int vert_id = bot->faces[face_num*3+k];
			for (unsigned int l = 0; l < vert_face_cnt[vert_id]; l++) {
			    unsigned int new_face = vert_to_face[max_face_cnt * vert_id  + l] - 1;
			    if (groups[new_face] == ordered_groups[i] && !patches[new_face]) {
				face_queue.push(new_face);
				patches[new_face] = patch_cnt;
			    }
			}
		    }
		}
	    }
	}
    }
    bu_free(groups, "groups");
    bu_free(vert_to_face, "vert_to_face");

    unsigned int *patch_vert_cnt = vert_sizes;
    memset(patch_vert_cnt, 0, bot->num_vertices * sizeof(unsigned int));
    unsigned int *vert_edge_status = (unsigned int *)bu_calloc(bot->num_vertices, sizeof(unsigned int), "vert status");
    for (unsigned int i = 0; i < patch_cnt; i++) {
        memset(patch_vert_cnt, 0, bot->num_vertices * sizeof(unsigned int));
	for (unsigned int j = 0; j < bot->num_faces; j++) {
	    if (patches[j] == i+1) {
		patch_vert_cnt[bot->faces[j*3+0]]++;
		patch_vert_cnt[bot->faces[j*3+1]]++;
		patch_vert_cnt[bot->faces[j*3+2]]++;
	    }
	}
	for (unsigned int j = 0; j < bot->num_vertices; j++) {
	    if (patch_vert_cnt[j] && patch_vert_cnt[j] != vert_face_cnt[j]) {
		vert_edge_status[j]++;
	    }
	}
    }
    bu_free(patches, "patches");
    bu_free(patch_vert_cnt, "patch_vert_cnt");
    bu_free(vert_face_cnt, "vert_face_cnt");

    for (unsigned int j = 0; j < bot->num_faces; j++) {
	if (vert_edge_status[bot->faces[j*3+0]] &&  vert_edge_status[bot->faces[j*3+1]]) {
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+0]*3]), BN_VLIST_LINE_MOVE);
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+1]*3]), BN_VLIST_LINE_DRAW);
	}
        if (vert_edge_status[bot->faces[j*3+1]] &&  vert_edge_status[bot->faces[j*3+2]]) {
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+1]*3]), BN_VLIST_LINE_MOVE);
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+2]*3]), BN_VLIST_LINE_DRAW);
	}
	if (vert_edge_status[bot->faces[j*3+2]] &&  vert_edge_status[bot->faces[j*3+0]]) {
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+2]*3]), BN_VLIST_LINE_MOVE);
	    RT_ADD_VLIST(info->vhead, &(bot->vertices[bot->faces[j*3+0]*3]), BN_VLIST_LINE_DRAW);
	}
    }

    bu_free(vert_edge_status, "vert status");

    return 0;
}
예제 #9
0
파일: arbn.c 프로젝트: kanzure/brlcad
/**
 * Brute force through all possible plane intersections.
 * Generate all edge lines, then intersect the line with all
 * the other faces to find the vertices on that line.
 * If the geometry is correct, there will be no more than two.
 * While not the fastest strategy, this will produce an accurate
 * plot without requiring extra bookkeeping.
 * Note that the vectors will be drawn in no special order.
 */
int
rt_arbn_plot(struct bu_list *vhead, struct rt_db_internal *ip, const struct rt_tess_tol *UNUSED(ttol), const struct bn_tol *tol, const struct rt_view_info *UNUSED(info))
{
    struct rt_arbn_internal *aip;
    size_t i;
    size_t j;
    size_t k;

    BU_CK_LIST_HEAD(vhead);
    RT_CK_DB_INTERNAL(ip);
    aip = (struct rt_arbn_internal *)ip->idb_ptr;
    RT_ARBN_CK_MAGIC(aip);

    for (i = 0; i < aip->neqn - 1; i++) {
	for (j = i + 1; j < aip->neqn; j++) {
	    double dot;
	    int point_count;	/* # points on this line */
	    point_t a, b;		/* start and end points */
	    vect_t dist;

	    VSETALL(a, 0);
	    VSETALL(b, 0);

	    /* If normals are parallel, no intersection */
	    dot = VDOT(aip->eqn[i], aip->eqn[j]);
	    if (BN_VECT_ARE_PARALLEL(dot, tol)) continue;

	    /* Have an edge line, isect with all other planes */
	    point_count = 0;
	    for (k = 0; k < aip->neqn; k++) {
		size_t m;
		point_t pt;
		size_t next_k;

		next_k = 0;

		if (k == i || k == j) continue;
		if (bn_mkpoint_3planes(pt, aip->eqn[i], aip->eqn[j], aip->eqn[k]) < 0) continue;

		/* See if point is outside arb */
		for (m = 0; m < aip->neqn; m++) {
		    if (i == m || j == m || k == m) continue;
		    if (VDOT(pt, aip->eqn[m])-aip->eqn[m][3] > tol->dist) {
			next_k = 1;
			break;
		    }
		}

		if (next_k != 0) continue;

		if (point_count <= 0) {
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_MOVE);
		    VMOVE(a, pt);
		} else if (point_count == 1) {
		    VSUB2(dist, pt, a);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);
		    VMOVE(b, pt);
		} else {
		    VSUB2(dist, pt, a);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    VSUB2(dist, pt, b);
		    if (MAGSQ(dist) < tol->dist_sq) continue;
		    bu_log("rt_arbn_plot() error, point_count=%d (>2) on edge %zu/%zu, non-convex\n",
			   point_count+1,
			   i, j);
		    VPRINT(" a", a);
		    VPRINT(" b", b);
		    VPRINT("pt", pt);
		    RT_ADD_VLIST(vhead, pt, BN_VLIST_LINE_DRAW);	/* draw it */
		}
		point_count++;
	    }
	    /* Point counts of 1 are (generally) not harmful,
	     * occurring on pyramid peaks and the like.
	     */
	}
    }
    return 0;
}