/** *@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); }
/** * 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; }
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; } }
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; }
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; }
/* * 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); }
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(¢er, &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(¢er, &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(¢er, &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(¢er, &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(¢er, &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; }
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; }