/**
 *@brief
 * Draw a vector between points "from" and "to", with the option of
 * having an arrowhead on either or both ends.
 *
 * The fromheadfract and toheadfract values indicate the length of the
 * arrowheads relative to the length of the vector to-from.  A typical
 * value is 0.1, making the head 10% of the size of the vector.  The
 * sign of the "fract" values indicates the pointing direction.
 * Positive points towards the "to" point, negative points towards
 * "from".  Upon return, the virtual pen is left at the "to" position.
 */
void
tp_3vector(FILE *plotfp, fastf_t *from, fastf_t *to, double fromheadfract, double toheadfract)
{
    register fastf_t len;
    register fastf_t hooklen;
    vect_t diff;
    vect_t c1, c2;
    vect_t h1, h2;
    vect_t backup;
    point_t tip;

    pdv_3line(plotfp, from, to);
    /* "pen" is left at "to" position */

    VSUB2(diff, to, from);
    if ((len = MAGNITUDE(diff)) < SMALL)  return;
    VSCALE(diff, diff, 1/len);
    bn_vec_ortho(c1, diff);
    VCROSS(c2, c1, diff);

    if (!ZERO(fromheadfract)) {
	hooklen = fromheadfract*len;
	VSCALE(backup, diff, -hooklen);

	VSCALE(h1, c1, hooklen);
	VADD3(tip, from, h1, backup);
	pdv_3move(plotfp, from);
	pdv_3cont(plotfp, tip);

	VSCALE(h2, c2, hooklen);
	VADD3(tip, from, h2, backup);
	pdv_3move(plotfp, tip);
    }
    if (!ZERO(toheadfract)) {
	hooklen = toheadfract*len;
	VSCALE(backup, diff, -hooklen);

	VSCALE(h1, c1, hooklen);
	VADD3(tip, to, h1, backup);
	pdv_3move(plotfp, to);
	pdv_3cont(plotfp, tip);

	VSCALE(h2, c2, hooklen);
	VADD3(tip, to, h2, backup);
	pdv_3move(plotfp, tip);
    }
    /* Be certain "pen" is left at "to" position */
    if (!ZERO(fromheadfract) || !ZERO(toheadfract))
	pdv_3cont(plotfp, to);

}
Esempio n. 2
0
File: hyp.c Progetto: kanzure/brlcad
/**
 * Create a bounding RPP for an hyp
 */
int
rt_hyp_bbox(struct rt_db_internal *ip, point_t *min, point_t *max, const struct bn_tol *UNUSED(tol)) {
    struct rt_hyp_internal *xip;
    vect_t hyp_Au, hyp_B, hyp_An, hyp_Bn, hyp_H;
    vect_t pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8;
    RT_CK_DB_INTERNAL(ip);
    xip = (struct rt_hyp_internal *)ip->idb_ptr;
    RT_HYP_CK_MAGIC(xip);

    VMOVE(hyp_H, xip->hyp_Hi);
    VUNITIZE(hyp_H);
    VMOVE(hyp_Au, xip->hyp_A);
    VUNITIZE(hyp_Au);
    VCROSS(hyp_B, hyp_Au, hyp_H);

    VSETALL((*min), INFINITY);
    VSETALL((*max), -INFINITY);

    VSCALE(hyp_B, hyp_B, xip->hyp_b);
    VREVERSE(hyp_An, xip->hyp_A);
    VREVERSE(hyp_Bn, hyp_B);

    VADD3(pt1, xip->hyp_Vi, xip->hyp_A, hyp_B);
    VADD3(pt2, xip->hyp_Vi, xip->hyp_A, hyp_Bn);
    VADD3(pt3, xip->hyp_Vi, hyp_An, hyp_B);
    VADD3(pt4, xip->hyp_Vi, hyp_An, hyp_Bn);
    VADD4(pt5, xip->hyp_Vi, xip->hyp_A, hyp_B, xip->hyp_Hi);
    VADD4(pt6, xip->hyp_Vi, xip->hyp_A, hyp_Bn, xip->hyp_Hi);
    VADD4(pt7, xip->hyp_Vi, hyp_An, hyp_B, xip->hyp_Hi);
    VADD4(pt8, xip->hyp_Vi, hyp_An, hyp_Bn, xip->hyp_Hi);

    /* Find the RPP of the rotated axis-aligned hyp bbox - that is,
     * the bounding box the given hyp would have if its height
     * vector were in the positive Z direction. This does not give
     * us an optimal bbox except in the case where the hyp is
     * actually axis aligned to start with, but it's usually
     * at least a bit better than the bounding sphere RPP. */
    VMINMAX((*min), (*max), pt1);
    VMINMAX((*min), (*max), pt2);
    VMINMAX((*min), (*max), pt3);
    VMINMAX((*min), (*max), pt4);
    VMINMAX((*min), (*max), pt5);
    VMINMAX((*min), (*max), pt6);
    VMINMAX((*min), (*max), pt7);
    VMINMAX((*min), (*max), pt8);

    return 0;
}
Esempio n. 3
0
void
DHPt3PerpBisect(point4 p0, point4 p1, point4 result, int metric)
{
    switch (metric)	{
      case  DG_EUCLIDEAN:
	{
	point4 tmp;
	VSUB3(p1, p0, result)
	VADD3(p0, p1, tmp)
	VSCALE3(tmp, .5, tmp)
	result[3] = -(VDOT3(tmp, result));
	}
	break;

      case DG_HYPERBOLIC:
	NORMALIZE31(p0);
	NORMALIZE31(p1);
	VSUB4(p0, p1, result)
	if (INPRO31(p0, result) > 0.0)	VSCALE4(result, -1, result)
	break;

      case DG_SPHERICAL:
	NORMALIZE4(p0);
	NORMALIZE4(p1);
	VSUB4(p0, p1, result)
	if (INPRO4(p0, result) > 0.0)	VSCALE4(result, -1, result)
	break;

    }
}
Esempio n. 4
0
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;
}
Esempio n. 5
0
File: hyp.c Progetto: 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;
}
Esempio n. 6
0
/*
 *			G E T S O L I D
 *
 *  Returns -
 *	-1	error
 *	 0	conversion OK
 *	 1	EOF
 */
int
getsolid(void)
{
    char	given_solid_num[16];
    char	solid_type[16];
    int	i;
    double	r1, r2;
    vect_t	work;
    double	m1, m2;		/* Magnitude temporaries */
    char	*name=NULL;
    double	dd[4*6];	/* 4 cards of 6 nums each */
    point_t	tmp[8];		/* 8 vectors of 3 nums each */
    int	ret;
#define D(_i)	(&(dd[_i*3]))
#define T(_i)	(&(tmp[_i][0]))

    if ( (i = get_line( scard, sizeof(scard), "solid card" )) == EOF )  {
        printf("getsolid: unexpected EOF\n");
        return( 1 );
    }

    switch ( version )  {
    case 5:
        bu_strlcpy( given_solid_num, scard+0, sizeof(given_solid_num) );
        given_solid_num[5] = '\0';
        bu_strlcpy( solid_type, scard+5, sizeof(solid_type) );
        solid_type[5] = '\0';
        break;
    case 4:
        bu_strlcpy( given_solid_num, scard+0, sizeof(given_solid_num) );
        given_solid_num[3] = '\0';
        bu_strlcpy( solid_type, scard+3, sizeof(solid_type) );
        solid_type[7] = '\0';
        break;
    case 1:
        /* DoE/MORSE version, believed to be original MAGIC format */
        bu_strlcpy( given_solid_num, scard+5, sizeof(given_solid_num) );
        given_solid_num[4] = '\0';
        bu_strlcpy( solid_type, scard+2, sizeof(solid_type) );
        break;
    default:
        fprintf(stderr, "getsolid() version %d unimplemented\n", version);
        bu_exit(1, NULL);
        break;
    }
    /* Trim trailing spaces */
    trim_trail_spaces( given_solid_num );
    trim_trail_spaces( solid_type );

    /* another solid - increment solid counter
     * rather than using number from the card, which may go into
     * pseudo-hex format in version 4 models (due to 3 column limit).
     */
    sol_work++;
    if ( version == 5 )  {
        if ( (i = getint( scard, 0, 5 )) != sol_work )  {
            printf("expected solid card %d, got %d, abort\n",
                   sol_work, i );
            return(1);
        }
    }

    /* Reduce solid type to lower case */
    {
        register char	*cp;
        register char	c;

        cp = solid_type;
        while ( (c = *cp) != '\0' )  {
            if ( !isascii(c) )  {
                *cp++ = '?';
            } else if ( isupper(c) )  {
                *cp++ = tolower(c);
            } else {
                cp++;
            }
        }
    }

    namecvt( sol_work, &name, 's' );
    if (verbose) col_pr( name );

    if ( strcmp( solid_type, "end" ) == 0 )  {
        /* DoE/MORSE version 1 format */
        bu_free( name, "name" );
        return(1);		/* END */
    }

    if ( strcmp( solid_type, "ars" ) == 0 )  {
        int		ncurves;
        int		pts_per_curve;
        double		**curve;

        ncurves = getint( scard, 10, 10 );
        pts_per_curve = getint( scard, 20, 10 );

        /* Allocate curves pointer array */
        curve = (double **)bu_malloc((ncurves+1)*sizeof(double *), "curve");

        /* Allocate space for a curve, and read it in */
        for ( i=0; i<ncurves; i++ )  {
            curve[i] = (double *)bu_malloc((pts_per_curve+1)*3*sizeof(double), "curve[i]" );

            /* Get data for this curve */
            if ( getxsoldata( curve[i], pts_per_curve*3, sol_work ) < 0 )  {
                printf("ARS %d: getxsoldata failed, curve %d\n",
                       sol_work, i);
                return(-1);
            }
        }
        if ( (ret = mk_ars( outfp, name, ncurves, pts_per_curve, curve )) < 0 )  {
            printf("mk_ars(%s) failed\n", name );
            /* Need to free memory; 'ret' is returned below */
        }

        for ( i=0; i<ncurves; i++ )  {
            bu_free( (char *)curve[i], "curve[i]" );
        }
        bu_free( (char *)curve, "curve" );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "rpp" ) == 0 )  {
        double	min[3], max[3];

        if ( getsoldata( dd, 2*3, sol_work ) < 0 )
            return(-1);
        VSET( min, dd[0], dd[2], dd[4] );
        VSET( max, dd[1], dd[3], dd[5] );
        ret = mk_rpp( outfp, name, min, max );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "box" ) == 0 )  {
        if ( getsoldata( dd, 4*3, sol_work ) < 0 )
            return(-1);
        VMOVE( T(0), D(0) );
        VADD2( T(1), D(0), D(2) );
        VADD3( T(2), D(0), D(2), D(1) );
        VADD2( T(3), D(0), D(1) );

        VADD2( T(4), D(0), D(3) );
        VADD3( T(5), D(0), D(3), D(2) );
        VADD4( T(6), D(0), D(3), D(2), D(1) );
        VADD3( T(7), D(0), D(3), D(1) );
        ret = mk_arb8( outfp, name, &tmp[0][X] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "raw" ) == 0 ||
            strcmp( solid_type, "wed" ) == 0		/* DoE name */
       )  {
        if ( getsoldata( dd, 4*3, sol_work ) < 0 )
            return(-1);
        VMOVE( T(0), D(0) );
        VADD2( T(1), D(0), D(2) );
        VMOVE( T(2), T(1) );
        VADD2( T(3), D(0), D(1) );

        VADD2( T(4), D(0), D(3) );
        VADD3( T(5), D(0), D(3), D(2) );
        VMOVE( T(6), T(5) );
        VADD3( T(7), D(0), D(3), D(1) );
        ret = mk_arb8( outfp, name, &tmp[0][X] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "rvw" ) == 0 )  {
        /* Right Vertical Wedge (Origin: DoE/MORSE) */
        double	a2, theta, phi, h2;
        double	a2theta;
        double	angle1, angle2;
        vect_t	a, b, c;

        if ( getsoldata( dd, 1*3+4, sol_work ) < 0 )
            return(-1);
        a2 = dd[3];		/* XY side length */
        theta = dd[4];
        phi = dd[5];
        h2 = dd[6];		/* height in +Z */

        angle1 = (phi+theta-90) * bn_degtorad;
        angle2 = (phi+theta) * bn_degtorad;
        a2theta = a2 * tan(theta * bn_degtorad);

        VSET( a, a2theta*cos(angle1), a2theta*sin(angle1), 0 );
        VSET( b, -a2*cos(angle2), -a2*sin(angle2), 0 );
        VSET( c, 0, 0, h2 );

        VSUB2( T(0), D(0), b );
        VMOVE( T(1), D(0) );
        VMOVE( T(2), D(0) );
        VADD2( T(3), T(0), a );

        VADD2( T(4), T(0), c );
        VADD2( T(5), T(1), c );
        VMOVE( T(6), T(5) );
        VADD2( T(7), T(3), c );
        ret = mk_arb8( outfp, name, &tmp[0][X] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "arw" ) == 0) {
        /* ARbitrary Wedge --- ERIM */
        if ( getsoldata( dd, 4*3, sol_work ) < 0)
            return(-1);
        VMOVE( T(0), D(0) );
        VADD2( T(1), D(0), D(2) );
        VADD3( T(2), D(0), D(2), D(3) );
        VADD2( T(3), D(0), D(3) );

        VADD2( T(4), D(0), D(1) );
        VMOVE( T(5), T(4) );

        VADD3( T(6), D(0), D(1), D(3) );
        VMOVE( T(7), T(6) );
        ret = mk_arb8( outfp, name, &tmp[0][X]);
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "arb8" ) == 0 )  {
        if ( getsoldata( dd, 8*3, sol_work ) < 0 )
            return(-1);
        ret = mk_arb8( outfp, name, dd );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "arb7" ) == 0 )  {
        if ( getsoldata( dd, 7*3, sol_work ) < 0 )
            return(-1);
        VMOVE( D(7), D(4) );
        ret = mk_arb8( outfp, name, dd );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "arb6" ) == 0 )  {
        if ( getsoldata( dd, 6*3, sol_work ) < 0 )
            return(-1);
        /* Note that the ordering is important, as data is in D(4), D(5) */
        VMOVE( D(7), D(5) );
        VMOVE( D(6), D(5) );
        VMOVE( D(5), D(4) );
        ret = mk_arb8( outfp, name, dd );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "arb5" ) == 0 )  {
        if ( getsoldata( dd, 5*3, sol_work ) < 0 )
            return(-1);
        VMOVE( D(5), D(4) );
        VMOVE( D(6), D(4) );
        VMOVE( D(7), D(4) );
        ret = mk_arb8( outfp, name, dd );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "arb4" ) == 0 )  {
        if ( getsoldata( dd, 4*3, sol_work ) < 0 )
            return(-1);
        ret = mk_arb4( outfp, name, dd );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "rcc" ) == 0 )  {
        /* V, H, r */
        if ( getsoldata( dd, 2*3+1, sol_work ) < 0 )
            return(-1);
        ret = mk_rcc( outfp, name, D(0), D(1), dd[6] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "rec" ) == 0 )  {
        /* V, H, A, B */
        if ( getsoldata( dd, 4*3, sol_work ) < 0 )
            return(-1);
        ret = mk_tgc( outfp, name, D(0), D(1),
                      D(2), D(3), D(2), D(3) );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "trc" ) == 0 )  {
        /* V, H, r1, r2 */
        if ( getsoldata( dd, 2*3+2, sol_work ) < 0 )
            return(-1);
        ret = mk_trc_h( outfp, name, D(0), D(1), dd[6], dd[7] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "tec" ) == 0 )  {
        /* V, H, A, B, p */
        if ( getsoldata( dd, 4*3+1, sol_work ) < 0 )
            return(-1);
        r1 = 1.0/dd[12];	/* P */
        VSCALE( D(4), D(2), r1 );
        VSCALE( D(5), D(3), r1 );
        ret = mk_tgc( outfp, name, D(0), D(1),
                      D(2), D(3), D(4), D(5) );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "tgc" ) == 0 )  {
        /* V, H, A, B, r1, r2 */
        if ( getsoldata( dd, 4*3+2, sol_work ) < 0 )
            return(-1);
        r1 = dd[12] / MAGNITUDE( D(2) );	/* A/|A| * C */
        r2 = dd[13] / MAGNITUDE( D(3) );	/* B/|B| * D */
        VSCALE( D(4), D(2), r1 );
        VSCALE( D(5), D(3), r2 );
        ret = mk_tgc( outfp, name, D(0), D(1),
                      D(2), D(3), D(4), D(5) );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "sph" ) == 0 )  {
        /* V, radius */
        if ( getsoldata( dd, 1*3+1, sol_work ) < 0 )
            return(-1);
        ret = mk_sph( outfp, name, D(0), dd[3] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strncmp( solid_type, "wir", 3 ) == 0 )  {
        int			numpts;		/* points per wire */
        int			num;
        int			i;
        double			dia;
        double			*pts;		/* 3 entries per pt */
        struct	wdb_pipept	*ps;
        struct	bu_list		head;		/* allow a whole struct for head */

        /* This might be getint( solid_type, 3, 2 ); for non-V5 */
        numpts = getint( scard, 8, 2 );
        num = numpts * 3 + 1;			/* 3 entries per pt */

        /* allocate space for the points array */
        pts = ( double *)bu_malloc(num * sizeof( double), "pts" );

        if ( getsoldata( pts, num, sol_work ) < 0 )  {
            return(-1);
        }
        dia = pts[num-1] * 2.0;	/* radius X 2.0 == diameter */

        /* allocate nodes on a list and store all information in
         * the appropriate location.
         */
        BU_LIST_INIT( &head );
        for ( i = 0; i < numpts; i++ )  {
            /* malloc a new structure */
            ps = (struct wdb_pipept *)bu_malloc(sizeof( struct wdb_pipept), "ps");

            ps->l.magic = WDB_PIPESEG_MAGIC;
            VMOVE( ps->pp_coord, &pts[i*3]);	/* 3 pts at a time */
            ps->pp_id = 0;				/* solid */
            ps->pp_od = dia;
            ps->pp_bendradius = dia;
            BU_LIST_INSERT( &head, &ps->l );
        }

        if ( mk_pipe( outfp, name, &head ) < 0 )
            return(-1);
        mk_pipe_free( &head );
        bu_free( name, "name" );
        return(0);		/* OK */
    }

    if ( strcmp( solid_type, "rpc" ) == 0 )  {
        /* V, H, B, r */
        if ( getsoldata( dd, 3*3+1, sol_work ) < 0 )
            return(-1);
        ret = mk_rpc( outfp, name, D(0), D(1),
                      D(2), dd[9] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "rhc" ) == 0 )  {
        /* V, H, B, r, c */
        if ( getsoldata( dd, 3*3+2, sol_work ) < 0 )
            return(-1);
        ret = mk_rhc( outfp, name, D(0), D(1),
                      D(2), dd[9], dd[10] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "epa" ) == 0 )  {
        /* V, H, Au, r1, r2 */
        if ( getsoldata( dd, 3*3+2, sol_work ) < 0 )
            return(-1);
        ret = mk_epa( outfp, name, D(0), D(1),
                      D(2), dd[9], dd[10] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "ehy" ) == 0 )  {
        /* V, H, Au, r1, r2, c */
        if ( getsoldata( dd, 3*3+3, sol_work ) < 0 )
            return(-1);
        ret = mk_ehy( outfp, name, D(0), D(1),
                      D(2), dd[9], dd[10], dd[11] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "eto" ) == 0 )  {
        /* V, N, C, r, rd */
        if ( getsoldata( dd, 3*3+2, sol_work ) < 0 )
            return(-1);
        ret = mk_eto( outfp, name, D(0), D(1),
                      D(2), dd[9], dd[10] );
        bu_free( name, "name" );
        return(ret);
    }


    if ( version <= 4 && strcmp( solid_type, "ell" ) == 0 )  {
        /* Foci F1, F2, major axis length L */
        vect_t	v;

        /*
         * For simplicity, we convert ELL to ELL1, then
         * fall through to ELL1 code.
         * Format of ELL is F1, F2, len
         * ELL1 format is V, A, r
         */
        if ( getsoldata( dd, 2*3+1, sol_work ) < 0 )
            return(-1);
        VADD2SCALE( v, D(0), D(1), 0.5 ); /* V is midpoint */

        VSUB2( work, D(1), D(0) );	/* work holds F2 -  F1 */
        m1 = MAGNITUDE( work );
        r2 = 0.5 * dd[6] / m1;
        VSCALE( D(1), work, r2 );	/* A */

        dd[6] = sqrt( MAGSQ( D(1) ) -
                      (m1 * 0.5)*(m1 * 0.5) );	/* r */
        VMOVE( D(0), v );
        goto ell1;
    }

    if ( (version == 5 && strcmp( solid_type, "ell" ) == 0)  ||
            strcmp( solid_type, "ell1" ) == 0 )  {
        /* V, A, r */
        /* GIFT4 name is "ell1", GIFT5 name is "ell" */
        if ( getsoldata( dd, 2*3+1, sol_work ) < 0 )
            return(-1);

ell1:
        r1 = dd[6];		/* R */
        VMOVE( work, D(0) );
        work[0] += bn_pi;
        work[1] += bn_pi;
        work[2] += bn_pi;
        VCROSS( D(2), work, D(1) );
        m1 = r1/MAGNITUDE( D(2) );
        VSCALE( D(2), D(2), m1 );

        VCROSS( D(3), D(1), D(2) );
        m2 = r1/MAGNITUDE( D(3) );
        VSCALE( D(3), D(3), m2 );

        /* Now we have V, A, B, C */
        ret = mk_ell( outfp, name, D(0), D(1), D(2), D(3) );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "ellg" ) == 0 )  {
        /* V, A, B, C */
        if ( getsoldata( dd, 4*3, sol_work ) < 0 )
            return(-1);
        ret = mk_ell( outfp, name, D(0), D(1), D(2), D(3) );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "tor" ) == 0 )  {
        /* V, N, r1, r2 */
        if ( getsoldata( dd, 2*3+2, sol_work ) < 0 )
            return(-1);
        ret = mk_tor( outfp, name, D(0), D(1), dd[6], dd[7] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "haf" ) == 0 )  {
        /* N, d */
        if ( getsoldata( dd, 1*3+1, sol_work ) < 0 )
            return(-1);
        ret = mk_half( outfp, name, D(0), -dd[3] );
        bu_free( name, "name" );
        return(ret);
    }

    if ( strcmp( solid_type, "arbn" ) == 0 )  {
        ret = read_arbn( name );
        bu_free( name, "name" );
    }

    /*
     *  The solid type string is defective,
     *  or that solid is not currently supported.
     */
    printf("getsolid:  no support for solid type '%s'\n", solid_type );
    return(-1);
}
Esempio n. 7
0
int
main(int argc, const char **argv)
{
    int i = 0;
    int retval = 0;

    int do_plotting = 0;

    if (argc == 2 && BU_STR_EQUAL(argv[1], "-p")) do_plotting = 1;

    /* 2D input */
    {
	point2d_t center;
	vect2d_t u, v;
	point2d_t pnts[4+1] = {{0}};
	point2d_t expected[4+1] = {{0}};
	point2d_t output_pnts[4+1] = {{0}};
	point_t output_3d_pnts[4+1] = {{0}};
	int n = 4;

	V2SET(pnts[0], 1.5, 1.5);
	V2SET(pnts[1], 3.0, 2.0);
	V2SET(pnts[2], 2.0, 2.5);
	V2SET(pnts[3], 1.0, 2.0);

	V2SET(expected[0], 1.2, 1.4);
	V2SET(expected[1], 3.0, 2.0);
	V2SET(expected[2], 2.75, 2.75);
	V2SET(expected[3], 0.95, 2.15);


	retval = bn_2d_obr(&center, &u, &v, (const point2d_t *)pnts, n);
	if (retval) return -1;
	V2ADD3(output_pnts[2], center, u, v);
	V2SCALE(u, u, -1);
	V2ADD3(output_pnts[3], center, u, v);
	V2SCALE(v, v, -1);
	V2ADD3(output_pnts[0], center, u, v);
	V2SCALE(u, u, -1);
	V2ADD3(output_pnts[1], center, u, v);
	bu_log("Test #001:  polyline_2d_hull - 4 point test:\n");
	bu_log("bn_2d_obr: center (%f, %f)\n", V2ARGS(center));
	bu_log("           u      (%f, %f)\n", V2ARGS(u));
	bu_log("           v      (%f, %f)\n", V2ARGS(v));

	for (i = 0; i < 4; i++) {
	    bu_log("    expected[%d]: (%f, %f)\n", i, V2ARGS(expected[i]));
	    bu_log("      actual[%d]: (%f, %f)\n", i, V2ARGS(output_pnts[i]));
	    if (!NEAR_ZERO(output_pnts[i][0] - expected[i][0], VUNITIZE_TOL) ||
		    !NEAR_ZERO(output_pnts[i][1] - expected[i][1], VUNITIZE_TOL)) {
		retval += 1;
	    }
	}
	if (retval) {return -1;} else {bu_log("Test #001 Passed!\n");}
	if (do_plotting) {
	    VSET(output_3d_pnts[0], output_pnts[0][0], output_pnts[0][1], 0);
	    VSET(output_3d_pnts[1], output_pnts[1][0], output_pnts[1][1], 0);
	    VSET(output_3d_pnts[2], output_pnts[2][0], output_pnts[2][1], 0);
	    VSET(output_3d_pnts[3], output_pnts[3][0], output_pnts[3][1], 0);
	    if (do_plotting) {
		plot_obr(1, (const point_t *)output_3d_pnts, 4);
	    }
	}
    }

    /* Triangle input */
    {
	point2d_t center;
	vect2d_t u, v;
	point2d_t pnts[3+1] = {{0}};
	point2d_t expected[4+1] = {{0}};
	point2d_t output_pnts[4+1] = {{0}};
	point_t output_3d_pnts[4+1] = {{0}};
	int n = 3;

	V2SET(pnts[0], 1.0, 0.0);
	V2SET(pnts[1], 3.0, 0.0);
	V2SET(pnts[2], 2.0, 4.0);

	V2SET(expected[0], 1.0, 0.0);
	V2SET(expected[1], 3.0, 0.0);
	V2SET(expected[2], 3.0, 4.0);
	V2SET(expected[3], 1.0, 4.0);


	retval = bn_2d_obr(&center, &u, &v, (const point2d_t *)pnts, n);
	if (retval) return -1;
	V2ADD3(output_pnts[2], center, u, v);
	V2SCALE(u, u, -1);
	V2ADD3(output_pnts[3], center, u, v);
	V2SCALE(v, v, -1);
	V2ADD3(output_pnts[0], center, u, v);
	V2SCALE(u, u, -1);
	V2ADD3(output_pnts[1], center, u, v);
	bu_log("Test #001:  polyline_2d_hull - triangle test:\n");
	bu_log("bn_2d_obr: center (%f, %f)\n", V2ARGS(center));
	bu_log("           u      (%f, %f)\n", V2ARGS(u));
	bu_log("           v      (%f, %f)\n", V2ARGS(v));

	for (i = 0; i < 4; i++) {
	    bu_log("    expected[%d]: (%f, %f)\n", i, V2ARGS(expected[i]));
	    bu_log("      actual[%d]: (%f, %f)\n", i, V2ARGS(output_pnts[i]));
	    if (!NEAR_ZERO(output_pnts[i][0] - expected[i][0], SMALL_FASTF) ||
		    !NEAR_ZERO(output_pnts[i][1] - expected[i][1], SMALL_FASTF)) {
		retval += 1;
	    }
	}
	if (do_plotting) {
	    VSET(output_3d_pnts[0], output_pnts[0][0], output_pnts[0][1], 0);
	    VSET(output_3d_pnts[1], output_pnts[1][0], output_pnts[1][1], 0);
	    VSET(output_3d_pnts[2], output_pnts[2][0], output_pnts[2][1], 0);
	    VSET(output_3d_pnts[3], output_pnts[3][0], output_pnts[3][1], 0);
	    if (do_plotting) {
		plot_obr(8, (const point_t *)output_3d_pnts, 4);
	    }
	}
	if (retval) {return -1;} else {bu_log("Triangle Test Passed!\n");}
    }


    /* 3D input */
    {
	point_t center;
	vect_t u, v;
	point_t output_pnts[4+1] = {{0}};
	point_t test2_points[17+1] = {{0}};
	point_t expected[4+1] = {{0}};
	VSET(test2_points[0], -0.5, 0.5, 0.5);
	VSET(test2_points[1], 0.5, -0.5, 0.5);
	VSET(test2_points[2], 0.5, 0.5, 0.5);
	VSET(test2_points[3], -0.5, -0.5, 0.5);
	VSET(test2_points[4], 0.5, 0.5, 0.5);
	VSET(test2_points[5], -0.5, -0.5, 0.5);
	VSET(test2_points[6], -0.5, 0.5, 0.5);
	VSET(test2_points[7], 0.5, -0.5, 0.5);
	VSET(test2_points[8], 0.1666666666666666574148081, 0.1666666666666666574148081, 0.5);
	VSET(test2_points[9], -0.1666666666666666574148081, -0.1666666666666666574148081, 0.5);
	VSET(test2_points[10], -0.3888888888888888950567946, -0.05555555555555555247160271, 0.5);
	VSET(test2_points[11], -0.3518518518518518600757261, 0.09259259259259258745267118, 0.5);
	VSET(test2_points[12], -0.4629629629629629095077803, -0.01851851851851851749053424, 0.5);
	VSET(test2_points[13], 0.05555555555555555247160271, 0.3888888888888888950567946, 0.5);
	VSET(test2_points[14], 0.3888888888888888950567946, 0.05555555555555555247160271, 0.5);
	VSET(test2_points[15], 0.3518518518518518600757261, 0.2407407407407407273769451, 0.5);
	VSET(test2_points[16], -0.05555555555555555247160271, -0.05555555555555555247160271, 0.5);
	VSET(expected[0], 0.5, 0.5, 0.5);
	VSET(expected[1], 0.5, -0.5, 0.5);
	VSET(expected[2], -0.5, -0.5, 0.5);
	VSET(expected[3], -0.5, 0.5, 0.5);
	retval = bn_3d_coplanar_obr(&center, &u, &v, (const point_t *)test2_points, 17);
	if (retval) return -1;
	VADD3(output_pnts[2], center, u, v);
	VSCALE(u, u, -1);
	VADD3(output_pnts[3], center, u, v);
	VSCALE(v, v, -1);
	VADD3(output_pnts[0], center, u, v);
	VSCALE(u, u, -1);
	VADD3(output_pnts[1], center, u, v);
	bu_log("Test #002:  3d obr - points in XY plane at Z=0.5, duplicate points:\n");
	for (i = 0; i < 4; i++) {
	    bu_log("    expected[%d]: (%f, %f, %f)\n", i, V3ARGS(expected[i]));
	    bu_log("      actual[%d]: (%f, %f, %f)\n", i, V3ARGS(output_pnts[i]));
	    if (!NEAR_ZERO(output_pnts[i][0] - expected[i][0], VUNITIZE_TOL) ||
		!NEAR_ZERO(output_pnts[i][1] - expected[i][1], VUNITIZE_TOL) ||
		!NEAR_ZERO(output_pnts[i][2] - expected[i][2], VUNITIZE_TOL)) {
		retval += 1;
	    }
	}
	if (retval) {return -1;} else {bu_log("Test #002 Passed!\n");}
	if (do_plotting) {
	    plot_obr(2, (const point_t *)output_pnts, 4);
	}

    }

    {
	point_t center;
	vect_t u, v;
	point_t output_pnts[4+1] = {{0}};
	point_t test3_points[17+1] = {{0}};
	point_t expected[4+1] = {{0}};

	VSET(test3_points[0],-0.2615997126297299746333636,0.9692719821506950994560725,1.113297221058902053414386);
	VSET(test3_points[1],-0.6960082873702697625617475,-0.3376479821506951362053428,0.791972778941099408989146);
	VSET(test3_points[2],0.08930731496876459507561208,0.2282231541335035251982788,0.5408368359872989250547448);
	VSET(test3_points[3],-1.046915314968769772363544,0.4034008458664972707197194,1.364433164012702537348787);
	VSET(test3_points[4],0.08930731496876459507561208,0.2282231541335035251982788,0.5408368359872989250547448);
	VSET(test3_points[5],-1.046915314968769772363544,0.4034008458664972707197194,1.364433164012702537348787);
	VSET(test3_points[6],-0.2615997126297299746333636,0.9692719821506950994560725,1.113297221058902053414386);
	VSET(test3_points[7],-0.6960082873702697625617475,-0.3376479821506951362053428,0.791972778941099408989146);
	VSET(test3_points[8],-0.2894335616770786212548217,0.2866157180445003671565019,0.8153689453291005362345345);
	VSET(test3_points[9],-0.6681744383229220041187091,0.3450082819554983748489008,1.089901054670902258436627);
	VSET(test3_points[10],-0.6588964886404735654679143,0.5725603699908965449338893,1.189210479914168061554847);
	VSET(test3_points[11],-0.5295568798643752739252477,0.628946878032363931865234,1.13080291854799019901634);
	VSET(test3_points[12],-0.6558038387463227536500199,0.6484110660026961570068238,1.222313621661925475692101);
	VSET(test3_points[13],-0.1539086531126804824332055,0.4947036181095669227225642,0.823167667458433838234555);
	VSET(test3_points[14],-0.2987115113595283921732459,0.05906363000910182931013637,0.7160595200858336228932899);
	VSET(test3_points[15],-0.1662792526892814537475829,0.1913008340623683078973727,0.6907551004674108430236856);
	VSET(test3_points[16],-0.5419274794409739692824246,0.3255440939851655945957987,0.9983903515569694242515197);
	VSET(expected[0], 0.089307314968765, 0.228223154133504, 0.540836835987299);
	VSET(expected[1], -0.696008287370264, -0.337647982150691, 0.791972778941097);
	VSET(expected[2], -1.046915314968751, 0.403400845866492, 1.364433164012691);
	VSET(expected[3], -0.261599712629723, 0.969271982150686, 1.113297221058893);

	retval = bn_3d_coplanar_obr(&center, &u, &v, (const point_t *)test3_points, 17);
	if (retval) return -1;
	VADD3(output_pnts[2], center, u, v);
	VSCALE(u, u, -1);
	VADD3(output_pnts[3], center, u, v);
	VSCALE(v, v, -1);
	VADD3(output_pnts[0], center, u, v);
	VSCALE(u, u, -1);
	VADD3(output_pnts[1], center, u, v);
	bu_log("Test #003:  3d obr - points in tilted plane, duplicate points:\n");
	for (i = 0; i < 4; i++) {
	    bu_log("    expected[%d]: (%.15f, %.15f, %.15f)\n", i, V3ARGS(expected[i]));
	    bu_log("      actual[%d]: (%.15f, %.15f, %.15f)\n", i, V3ARGS(output_pnts[i]));
	    if (!NEAR_ZERO(output_pnts[i][0] - expected[i][0], VUNITIZE_TOL) ||
		!NEAR_ZERO(output_pnts[i][1] - expected[i][1], VUNITIZE_TOL) ||
		!NEAR_ZERO(output_pnts[i][2] - expected[i][2], VUNITIZE_TOL)) {
		retval += 1;
	    }
	}
	if (retval) {return -1;} else {bu_log("Test #003 Passed!\n");}
	if (do_plotting) {
	    plot_obr(3, (const point_t *)output_pnts, 4);
	}


    }

    {
	point_t center;
	vect_t u, v;
	point_t output_pnts[4+1] = {{0}};
	point_t test4_points[9+1] = {{0}};
	point_t expected[4+1] = {{0}};

	VSET(test4_points[0],-0.2894335616770786212548217,0.2866157180445003671565019,0.8153689453291005362345345);
	VSET(test4_points[1],-0.6681744383229220041187091,0.3450082819554983748489008,1.089901054670902258436627);
	VSET(test4_points[2],-0.6588964886404735654679143,0.5725603699908965449338893,1.189210479914168061554847);
	VSET(test4_points[3],-0.5295568798643752739252477,0.628946878032363931865234,1.13080291854799019901634);
	VSET(test4_points[4],-0.6558038387463227536500199,0.6484110660026961570068238,1.222313621661925475692101);
	VSET(test4_points[5],-0.1539086531126804824332055,0.4947036181095669227225642,0.823167667458433838234555);
	VSET(test4_points[6],-0.2987115113595283921732459,0.05906363000910182931013637,0.7160595200858336228932899);
	VSET(test4_points[7],-0.1662792526892814537475829,0.1913008340623683078973727,0.6907551004674108430236856);
	VSET(test4_points[8],-0.5419274794409739692824246,0.3255440939851655945957987,0.9983903515569694242515197);
	VSET(expected[0], -0.804068848240491, 0.450183326349575, 1.227405986932079);
	VSET(expected[1], -0.277478009809908, 0.042630029322528, 0.694574374420025);
	VSET(expected[2], -0.018014243195113, 0.389528573715492, 0.685662735197256);
	VSET(expected[3], -0.544605081625695, 0.797081870742539, 1.218494347709310);

	retval = bn_3d_coplanar_obr(&center, &u, &v, (const point_t *)test4_points, 9);
	if (retval) return -1;
	VADD3(output_pnts[2], center, u, v);
	VSCALE(u, u, -1);
	VADD3(output_pnts[3], center, u, v);
	VSCALE(v, v, -1);
	VADD3(output_pnts[0], center, u, v);
	VSCALE(u, u, -1);
	VADD3(output_pnts[1], center, u, v);
	bu_log("Test #004:  3d obr - points from test 4 sans square corners, no duplicate points:\n");
	for (i = 0; i < 4; i++) {
	    bu_log("    expected[%d]: (%.15f, %.15f, %.15f)\n", i, V3ARGS(expected[i]));
	    bu_log("      actual[%d]: (%.15f, %.15f, %.15f)\n", i, V3ARGS(output_pnts[i]));
	    if (!NEAR_ZERO(output_pnts[i][0] - expected[i][0], VUNITIZE_TOL) ||
		!NEAR_ZERO(output_pnts[i][1] - expected[i][1], VUNITIZE_TOL) ||
		!NEAR_ZERO(output_pnts[i][2] - expected[i][2], VUNITIZE_TOL)) {
		retval += 1;
	    }
	}
	if (retval) {return -1;} else {bu_log("Test #004 Passed!\n");}
	if (do_plotting) {
	    plot_obr(4, (const point_t *)output_pnts, 4);
	}

    }


    return 0;
}
int
block(int entityno)
{

    fastf_t xscale = 0.0;
    fastf_t yscale = 0.0;
    fastf_t zscale = 0.0;
    fastf_t x_1, y_1, z_1;		/* First vertex components */
    fastf_t x_2, y_2, z_2;		/* xdir vector components */
    fastf_t x_3, y_3, z_3;		/* zdir vector components */
    point_t v;			/* the first vertex */
    vect_t xdir;			/* a unit vector */
    vect_t xvec;			/* vector along x-axis */
    vect_t ydir;			/* a unit vector */
    vect_t yvec;			/* vector along y-axis */
    vect_t zdir;			/* a unit vector */
    vect_t zvec;			/* vector along z-axis */
    point_t pts[9];			/* array of points */
    int sol_num;		/* IGES solid type number */

    /* Default values */
    x_1 = 0.0;
    y_1 = 0.0;
    z_1 = 0.0;
    x_2 = 1.0;
    y_2 = 0.0;
    z_2 = 0.0;
    x_3 = 0.0;
    y_3 = 0.0;
    z_3 = 1.0;


    /* Acquiring Data */

    if (dir[entityno]->param <= pstart) {
	bu_log("Illegal parameter pointer for entity D%07d (%s)\n" ,
	       dir[entityno]->direct, dir[entityno]->name);
	return 0;
    }

    Readrec(dir[entityno]->param);
    Readint(&sol_num, "");
    Readcnv(&xscale, "");
    Readcnv(&yscale, "");
    Readcnv(&zscale, "");
    Readcnv(&x_1, "");
    Readcnv(&y_1, "");
    Readcnv(&z_1, "");
    Readflt(&x_2, "");
    Readflt(&y_2, "");
    Readflt(&z_2, "");
    Readflt(&x_3, "");
    Readflt(&y_3, "");
    Readflt(&z_3, "");

    if (xscale <= 0.0 || yscale <= 0.0 || zscale <= 0.0) {
	bu_log("Illegal parameters for entity D%07d (%s)\n" ,
	       dir[entityno]->direct, dir[entityno]->name);
	return 0;
    }

    /*
     * Making the necessaries. First an id is made for the new entity.
     * Then the vertices for the bottom and top faces are found.  Point
     * is located in the lower left corner of the solid, and the vertices are
     * counted in the counter-clockwise direction, around the bottom face.
     * Next these vertices are extruded to form the top face.  The points
     * thus made are loaded into an array of points and handed off to mk_arb8().
     * Make and unitize necessary vectors.
     */

    VSET(xdir, x_2, y_2, z_2);			/* Makes x-dir vector */
    VUNITIZE(xdir);
    VSET(zdir, x_3, y_3, z_3);			/* Make z-dir vector */
    VUNITIZE(zdir);
    VCROSS(ydir, zdir, xdir);		/* Make y-dir vector */

    /* Scale all vectors */

    VSCALE(xvec, xdir, xscale);
    VSCALE(zvec, zdir, zscale);
    VSCALE(yvec, ydir, yscale);

    /* Make the bottom face. */

    VSET(v, x_1, y_1, z_1);			/* Yields first vertex */
    VMOVE(pts[0], v);			/* put first vertex into array */
    VADD2(pts[1], v, xvec);			/* Finds second vertex */
    VADD3(pts[2], v, xvec, yvec);		/* Finds third vertex */
    VADD2(pts[3], v, yvec);			/* Finds fourth vertex */

    /* Now extrude the bottom face to make the top.
     */

    VADD2(pts[4], v, zvec);			/* Finds fifth vertex */
    VADD2(pts[5], pts[1], zvec);		/* Finds sixth vertex */
    VADD2(pts[6], pts[2], zvec);		/* Finds seventh vertex */
    VADD2(pts[7], pts[3], zvec);		/* Find eighth vertex */


    /* Now the information is handed off to mk_arb8(). */

    mk_arb8(fdout, dir[entityno]->name, &pts[0][X]);

    return 1;


}
HIDDEN int
nmg_brep_face(ON_Brep **b, const struct faceuse *fu, const struct bn_tol *tol, long *brepi) {
    const struct face_g_plane *fg = fu->f_p->g.plane_p;
    struct bu_ptbl vert_table;
    struct vertex **pt;
    int ret = 0;
    int pnt_cnt = 0;
    int pnt_index = 0;
    vect_t u_axis, v_axis;
    point_t obr_center;
    point_t *points_3d = NULL;
    point_t *points_obr = NULL;
    struct loopuse *lu;
    struct edgeuse *eu;

    /* Find out how many points we have, set up any uninitialized ON_Brep vertex
     * structures, and prepare a map of NMG index values to the point array indices */
    nmg_tabulate_face_g_verts(&vert_table, fg);

    for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) {
	if (brepi[(*pt)->vg_p->index] == -INT_MAX) {
	    ON_BrepVertex& vert = (*b)->NewVertex((*pt)->vg_p->coord, SMALL_FASTF);
	    brepi[(*pt)->vg_p->index] = vert.m_vertex_index;
	}
	pnt_cnt++;
    }

    /* Prepare the 3D obr input array */
    points_3d = (point_t *)bu_calloc(pnt_cnt + 1, sizeof(point_t), "nmg points");
    for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) {
	VSET(points_3d[pnt_index], (*pt)->vg_p->coord[0],(*pt)->vg_p->coord[1],(*pt)->vg_p->coord[2]);
	pnt_index++;
    }
    bu_ptbl_free(&vert_table);


    /* Calculate the 3D coplanar oriented bounding rectangle (obr) */
    ret += bg_3d_coplanar_obr(&obr_center, &u_axis, &v_axis, (const point_t *)points_3d, pnt_cnt);
    if (ret) {
	bu_log("Failed to get oriented bounding rectangle for NMG faceuse #%lu\n", fu->index);
	return -1;
    }
    bu_free(points_3d, "done with obr 3d point inputs");

    /* Use the obr to define the 3D corner points of the NURBS surface */
    points_obr = (point_t *)bu_calloc(3 + 1, sizeof(point_t), "points_3d");
    VADD3(points_obr[2], obr_center, u_axis, v_axis);
    VSCALE(u_axis, u_axis, -1);
    VADD3(points_obr[3], obr_center, u_axis, v_axis);
    VSCALE(v_axis, v_axis, -1);
    VADD3(points_obr[0], obr_center, u_axis, v_axis);
    VSCALE(u_axis, u_axis, -1);
    VADD3(points_obr[1], obr_center, u_axis, v_axis);

    /* We need to orient our surface correctly according to the NMG - using
     * the openNURBS FlipFace function later does not seem to work very
     * well. If an outer loop is found in the NMG with a cw orientation,
     * factor that in in addition to the fu->f_p->flip flag. */
    int ccw = 0;
    vect_t vtmp, uv1, uv2, vnormal;
    point_t center;
    VADD2(center, points_obr[0], points_obr[1]);
    VADD2(center, center, points_obr[2]);
    VADD2(center, center, points_obr[3]);
    VSCALE(center, center, 0.25);
    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
	if (lu->orientation == OT_SAME && nmg_loop_is_ccw(lu, fg->N, tol) == -1) ccw = -1;
    }
    if (ccw != -1) {
	VSET(vnormal, fg->N[0], fg->N[1], fg->N[2]);
    } else {
	VSET(vnormal, -fg->N[0], -fg->N[1], -fg->N[2]);
    }
    if (fu->f_p->flip)
	VSET(vnormal, -vnormal[0], -vnormal[1], -vnormal[2]);
    VSUB2(uv1, points_obr[0], center);
    VSUB2(uv2, points_obr[1], center);
    VCROSS(vtmp, uv1, uv2);
    if (VDOT(vtmp, vnormal) < 0) {
	VMOVE(vtmp, points_obr[0]);
	VMOVE(points_obr[0], points_obr[1]);
	VMOVE(points_obr[1], vtmp);
	VMOVE(vtmp, points_obr[3]);
	VMOVE(points_obr[3], points_obr[2]);
	VMOVE(points_obr[2], vtmp);
    }

    /* Now that we've got our points correctly oriented for
     * the NURBS surface, proceed to create it. */
    ON_3dPoint p1 = ON_3dPoint(points_obr[0]);
    ON_3dPoint p2 = ON_3dPoint(points_obr[1]);
    ON_3dPoint p3 = ON_3dPoint(points_obr[2]);
    ON_3dPoint p4 = ON_3dPoint(points_obr[3]);

    (*b)->m_S.Append(sideSurface(p1, p2, p3, p4));
    ON_Surface *surf = (*(*b)->m_S.Last());
    int surfindex = (*b)->m_S.Count();
    ON_BrepFace& face = (*b)->NewFace(surfindex - 1);

    // With the surface and the face defined, make
    // trimming loops and create faces.  To generate UV
    // coordinates for each from and to for the
    // edgecurves, the UV origin is defined to be v1,
    // v1->v2 is defined as the U domain, and v1->v4 is
    // defined as the V domain.
    VSUB2(u_axis, points_obr[2], points_obr[1]);
    VSUB2(v_axis, points_obr[0], points_obr[1]);
    fastf_t u_axis_dist = MAGNITUDE(u_axis);
    fastf_t v_axis_dist = MAGNITUDE(v_axis);

    /* Now that we have the surface and the face, add the loops */
    for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) {
	if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; // loop is a single vertex
	// Check if this is an inner or outer loop
	ON_BrepLoop::TYPE looptype = (lu->orientation == OT_SAME) ? ON_BrepLoop::outer : ON_BrepLoop::inner;
	ON_BrepLoop& loop = (*b)->NewLoop(looptype, face);
	for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) {
	    vect_t ev1, ev2;
	    struct vertex_g *vg1 = eu->vu_p->v_p->vg_p;
	    struct vertex_g *vg2 = eu->eumate_p->vu_p->v_p->vg_p;
	    NMG_CK_VERTEX_G(vg1);
	    NMG_CK_VERTEX_G(vg2);
	    VMOVE(ev1, vg1->coord);
	    VMOVE(ev2, vg2->coord);
	    // Add edge if not already added
	    if (brepi[eu->e_p->index] == -INT_MAX) {
		/* always add edges with the small vertex index as from */
		int vert1 = (vg1->index <= vg2->index) ? brepi[vg1->index] : brepi[vg2->index];
		int vert2 = (vg1->index > vg2->index) ? brepi[vg1->index] : brepi[vg2->index];
		// Create and add 3D curve
		ON_Curve* c3d = new ON_LineCurve((*b)->m_V[vert1].Point(), (*b)->m_V[vert2].Point());
		c3d->SetDomain(0.0, 1.0);
		(*b)->m_C3.Append(c3d);
		// Create and add 3D edge
		ON_BrepEdge& e = (*b)->NewEdge((*b)->m_V[vert1], (*b)->m_V[vert2] , (*b)->m_C3.Count() - 1);
		e.m_tolerance = 0.0;
		brepi[eu->e_p->index] = e.m_edge_index;
	    }
	    // Regardless of whether the edge existed as an object, it needs to be added to the trimming loop
	    ON_3dPoint vg1pt(vg1->coord);
	    int orientation = ((vg1pt != (*b)->m_V[(*b)->m_E[(int)brepi[eu->e_p->index]].m_vi[0]].Point())) ? 1 : 0;
	    // Make a 2d trimming curve, create a trim, and add the trim to the loop
	    vect_t vect1, vect2, u_component, v_component;
	    double u0, u1, v0, v1;
	    ON_2dPoint from_uv, to_uv;
	    VSUB2(vect1, ev1, points_obr[0]);
	    VSUB2(vect2, ev2, points_obr[0]);
	    surf->GetDomain(0, &u0, &u1);
	    surf->GetDomain(1, &v0, &v1);
	    VPROJECT(vect1, u_axis, u_component, v_component);
	    from_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0);
	    from_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0);
	    VPROJECT(vect2, u_axis, u_component, v_component);
	    to_uv.y = u0 + MAGNITUDE(u_component)/u_axis_dist*(u1-u0);
	    to_uv.x = v0 + MAGNITUDE(v_component)/v_axis_dist*(v1-v0);
	    ON_Curve* c2d =  new ON_LineCurve(from_uv, to_uv);
	    c2d->SetDomain(0.0, 1.0);
	    int c2i = (*b)->m_C2.Count();
	    (*b)->m_C2.Append(c2d);
	    ON_BrepTrim& trim = (*b)->NewTrim((*b)->m_E[(int)brepi[eu->e_p->index]], orientation, loop, c2i);
	    trim.m_type = ON_BrepTrim::mated;
	    trim.m_tolerance[0] = 0.0;
	    trim.m_tolerance[1] = 0.0;
	}
    }

    bu_free(points_obr, "Done with obr");

    return 0;
}
Esempio n. 10
0
int
ged_bot_face_split(struct ged *gedp, int argc, const char *argv[])
{
    static const char *usage = "bot face";
    struct directory *dp;
    static fastf_t sf = 1.0 / 3.0;
    struct rt_db_internal intern;
    struct rt_bot_internal *botip;
    mat_t mat;
    char *last;
    size_t face_i;
    size_t last_vi;
    size_t save_vi;
    point_t new_pt;

    GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR);
    GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR);

    /* initialize result */
    bu_vls_trunc(gedp->ged_result_str, 0);

    /* must be wanting help */
    if (argc == 1) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_HELP;
    }

    if (argc != 3) {
	bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
	return GED_ERROR;
    }

    if ((last = strrchr(argv[1], '/')) == NULL)
	last = (char *)argv[1];
    else
	++last;

    if (last[0] == '\0') {
	bu_vls_printf(gedp->ged_result_str, "%s: illegal input - %s", argv[0], argv[1]);
	return GED_ERROR;
    }

    dp = db_lookup(gedp->ged_wdbp->dbip, last, LOOKUP_QUIET);
    if (dp == RT_DIR_NULL) {
	bu_vls_printf(gedp->ged_result_str, "%s: failed to find %s", argv[0], argv[1]);
	return GED_ERROR;
    }

    if (bu_sscanf(argv[2], "%zu", &face_i) != 1) {
	bu_vls_printf(gedp->ged_result_str, "%s: bad bot vertex index - %s", argv[0], argv[2]);
	return GED_ERROR;
    }

    if (wdb_import_from_path2(gedp->ged_result_str, &intern, last, gedp->ged_wdbp, mat) == GED_ERROR) {
	bu_vls_printf(gedp->ged_result_str, "%s: failed to find %s", argv[0], argv[1]);
	return GED_ERROR;
    }

    if (intern.idb_major_type != DB5_MAJORTYPE_BRLCAD ||
	intern.idb_minor_type != DB5_MINORTYPE_BRLCAD_BOT) {
	bu_vls_printf(gedp->ged_result_str, "Object is not a BOT");
	rt_db_free_internal(&intern);

	return GED_ERROR;
    }

    botip = (struct rt_bot_internal *)intern.idb_ptr;
    last_vi = botip->num_vertices;

    if (face_i >= botip->num_faces) {
	bu_vls_printf(gedp->ged_result_str, "%s: bad bot face index - %s", argv[0], argv[2]);
	rt_db_free_internal(&intern);
	return GED_ERROR;
    }

    /* Create the new point, modify face_i and hook in the two extra faces */
    /* First, create some space */
    botip->num_vertices++;
    botip->num_faces += 2;
    botip->vertices = (fastf_t *)bu_realloc((void *)botip->vertices, botip->num_vertices*3*sizeof(fastf_t), "realloc bot vertices");
    botip->faces = (int *)bu_realloc((void *)botip->faces, botip->num_faces*3*sizeof(int), "realloc bot faces");

    /* Create the new point. For the moment, we're using the average of the face_i's points */
    VADD3(new_pt,
	  &botip->vertices[botip->faces[face_i*3]*3],
	  &botip->vertices[botip->faces[face_i*3+1]*3],
	  &botip->vertices[botip->faces[face_i*3+2]*3]);
    VSCALE(new_pt, new_pt, sf);

    /* Add the new point to the last position in the list of vertices. */
    VMOVE(&botip->vertices[last_vi*3], new_pt);

    /* Update face_i */
    save_vi = botip->faces[face_i*3+2];
    botip->faces[face_i*3+2] = last_vi;

    /* Initialize the two new faces */
    botip->faces[(botip->num_faces-2)*3] = botip->faces[face_i*3+1];
    botip->faces[(botip->num_faces-2)*3+1] = save_vi;
    botip->faces[(botip->num_faces-2)*3+2] = last_vi;
    botip->faces[(botip->num_faces-1)*3] = save_vi;
    botip->faces[(botip->num_faces-1)*3+1] = botip->faces[face_i*3];
    botip->faces[(botip->num_faces-1)*3+2] = last_vi;

    bu_vls_printf(gedp->ged_result_str, "%zu", last_vi);

    GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR);
    rt_db_free_internal(&intern);
    return GED_OK;
}