int _ged_scale_extrude(struct ged *gedp, struct rt_extrude_internal *extrude, const char *attribute, fastf_t sf, int rflag) { vect_t hvec; RT_EXTRUDE_CK_MAGIC(extrude); switch (attribute[0]) { case 'h': case 'H': if (!rflag) sf /= MAGNITUDE(extrude->h); VSCALE(hvec, extrude->h, sf); /* Make sure hvec is not zero length */ if (MAGNITUDE(hvec) > SQRT_SMALL_FASTF) { VMOVE(extrude->h, hvec); } break; default: bu_vls_printf(gedp->ged_result_str, "bad extrude attribute - %s", attribute); return GED_ERROR; } return GED_OK; }
int _ged_scale_rpc(struct ged *gedp, struct rt_rpc_internal *rpc, const char *attribute, fastf_t sf, int rflag) { RT_RPC_CK_MAGIC(rpc); switch (attribute[0]) { case 'b': case 'B': if (!rflag) sf /= MAGNITUDE(rpc->rpc_B); VSCALE(rpc->rpc_B, rpc->rpc_B, sf); break; case 'h': case 'H': if (!rflag) sf /= MAGNITUDE(rpc->rpc_H); VSCALE(rpc->rpc_H, rpc->rpc_H, sf); break; case 'r': case 'R': if (rflag) rpc->rpc_r *= sf; else rpc->rpc_r = sf; break; default: bu_vls_printf(gedp->ged_result_str, "bad rpc attribute - %s", attribute); return GED_ERROR; } return GED_OK; }
struct hyp_specific * hyp_internal_to_specific(struct rt_hyp_internal *hyp_in) { struct hyp_specific *hyp; BU_GET(hyp, struct hyp_specific); hyp->hyp_r1 = hyp_in->hyp_bnr * MAGNITUDE(hyp_in->hyp_A); hyp->hyp_r2 = hyp_in->hyp_bnr * hyp_in->hyp_b; hyp->hyp_c = sqrt(4 * MAGSQ(hyp_in->hyp_A) / MAGSQ(hyp_in->hyp_Hi) * (1 - hyp_in->hyp_bnr * hyp_in->hyp_bnr)); VSCALE(hyp->hyp_H, hyp_in->hyp_Hi, 0.5); VADD2(hyp->hyp_V, hyp_in->hyp_Vi, hyp->hyp_H); VMOVE(hyp->hyp_Au, hyp_in->hyp_A); VUNITIZE(hyp->hyp_Au); hyp->hyp_rx = 1.0 / (hyp->hyp_r1 * hyp->hyp_r1); hyp->hyp_ry = 1.0 / (hyp->hyp_r2 * hyp->hyp_r2); hyp->hyp_rz = (hyp->hyp_c * hyp->hyp_c) / (hyp->hyp_r1 * hyp->hyp_r1); /* calculate height to use for top/bottom intersection planes */ hyp->hyp_Hmag = MAGNITUDE(hyp->hyp_H); hyp->hyp_bounds = hyp->hyp_rz*hyp->hyp_Hmag*hyp->hyp_Hmag + 1.0; /* setup unit vectors for hyp_specific */ VMOVE(hyp->hyp_Hunit, hyp->hyp_H); VMOVE(hyp->hyp_Aunit, hyp->hyp_Au); VCROSS(hyp->hyp_Bunit, hyp->hyp_Hunit, hyp->hyp_Aunit); VUNITIZE(hyp->hyp_Aunit); VUNITIZE(hyp->hyp_Bunit); VUNITIZE(hyp->hyp_Hunit); return hyp; }
void top(fastf_t *vec1, fastf_t *vec2, fastf_t *t) { fastf_t tooch, mag; vect_t del, tvec; int i, j; tooch = t[2] * .25; del[0] = vec2[0] - vec1[0]; del[1] = 0.0; del[2] = vec2[2] - vec1[2]; mag = MAGNITUDE( del ); VSCALE(tvec, del, tooch/mag); VSUB2(&sol.s_values[0], vec1, tvec); VADD2(del, del, tvec); VADD2(&sol.s_values[3], del, tvec); tvec[0] = tvec[2] = 0.0; tvec[1] = t[1] - t[0]; VCROSS(del, tvec, &sol.s_values[3]); mag = MAGNITUDE( del ); if (del[2] < 0) mag *= -1.0; VSCALE(&sol.s_values[9], del, t[2]/mag); VADD2(&sol.s_values[6], &sol.s_values[3], &sol.s_values[9]); VMOVE(&sol.s_values[12], tvec); for (i=3; i<=9; i+=3) { j = i + 12; VADD2(&sol.s_values[j], &sol.s_values[i], tvec); } }
EXPR *ExprFindCommensurate( EXPR *expr ) { unsigned int i, j ; EXPR *tmp, *tmp2 ; for( i = 0 ; i < U(UnitList)->used ; i++ ) { if( U(UN(i))->used != U(expr)->used ) continue ; for( j = 1 ; j < U(expr)->used ; j++ ) { if( !BooleanValue( (BOOL*) OP3( "?=", U(UN(i))->list[j], U(expr)->list[j] ) ) ) break ; } if( j == U(expr)->used ) /* found one */ { tmp = OP3( "/", U(expr)->list[0], U(UN(i))->list[0] ) ; tmp2 = Real( MAGNITUDE( tmp ), i ) ; delete tmp ; delete expr ; return tmp2 ; } } for( i = 1 ; i < U(expr)->used ; i++ ) { if( IS_ZERO( U(expr)->list[i] ) ) continue ; if( MAGNITUDE( U(expr)->list[i] ) == 1.0 ) tmp = U(UN(i))->Ehead->Copy() ; else { tmp = Operator( OPER_POW ) ; D(tmp)->Eleft = U(UN(i))->Ehead->Copy() ; D(tmp)->Eright = U(expr)->list[i]->Copy() ; } if( U(expr)->Eeval ) { tmp2 = Operator( OPER_MULTIPLY ) ; D(tmp2)->Eleft = U(expr)->Eeval ; D(tmp2)->Eright = tmp ; U(expr)->Eeval = tmp2 ; } else U(expr)->Eeval = tmp ; } tmp = Real( MAGNITUDE( U(expr)->list[0] ), U(UnitList)->used ) ; delete U(expr)->list[0] ; U(expr)->list[0] = Real(1,0) ; ListAppend( UnitList, expr ) ; return tmp ; }
void rt_superell_surf_area(fastf_t *area, const struct rt_db_internal *ip) { struct rt_superell_internal *sip; vect_t mags; RT_CK_DB_INTERNAL(ip); sip = (struct rt_superell_internal *)ip->idb_ptr; mags[0] = MAGNITUDE(sip->a); mags[1] = MAGNITUDE(sip->b); mags[2] = MAGNITUDE(sip->c); /* The parametric representation does not work correctly at n = e * = 0, so this uses a special calculation for boxes. */ if ((NEAR_EQUAL(sip->e, 0, BN_TOL_DIST)) && NEAR_EQUAL(sip->n, 0, BN_TOL_DIST)) { *area = superell_surf_area_box(mags); } else { /* This number specifies the initial precision used. The * precision is roughly the number of chunks that the uv-space * is divided into during the approximation; the larger the * number the higher the accuracy and the lower the * performance. */ int precision = 1024; fastf_t previous_area = 0; fastf_t current_area = superell_surf_area_general(sip, mags, M_PI / precision); while (!(NEAR_EQUAL(current_area, previous_area, BN_TOL_DIST))) { /* The precision is multiplied by a constant on each round * through the loop to make sure that the precision * continues to increase until a satisfactory value is * found. If this value is very small, this approximation * will likely converge fairly quickly and with lower * accuracy: the smaller the distance between the inputs * the more likely that the outputs will be within * BN_TOL_DIST. A large value will result in slow * convergence, but in high accuracy: when the values are * finally within BN_TOL_DIST of each other the * approximation must be very good, because a large * increase in input precision resulted in a small * increase in accuracy. */ precision *= 2; previous_area = current_area; current_area = superell_surf_area_general(sip, mags, M_PI / precision); } *area = current_area; } }
HIDDEN int rt_pattern_rect_orthogrid(fastf_t **rays, size_t *ray_cnt, const point_t center_pt, const vect_t dir, const vect_t a_vec, const vect_t b_vec, const fastf_t da, const fastf_t db) { int count = 0; point_t pt; vect_t a_dir; vect_t b_dir; fastf_t x, y; fastf_t a_length = MAGNITUDE(a_vec); fastf_t b_length = MAGNITUDE(b_vec); if (!rays || !ray_cnt) return -1; VMOVE(a_dir, a_vec); VUNITIZE(a_dir); VMOVE(b_dir, b_vec); VUNITIZE(b_dir); /* Find out how much memory we'll need and get it */ for (y = -b_length; y <= b_length; y += db) { for (x = -a_length; x <= a_length; x += da) { count++; } } *(rays) = (fastf_t *)bu_calloc(sizeof(fastf_t) * 6, count + 1, "rays"); /* Now that we have memory, reset count so it can * be used to index into the array */ count = 0; /* Build the rays */ for (y = -b_length; y <= b_length; y += db) { for (x = -a_length; x <= a_length; x += da) { VJOIN2(pt, center_pt, x, a_dir, y, b_dir); (*rays)[6*count] = pt[0]; (*rays)[6*count+1] = pt[1]; (*rays)[6*count+2] = pt[2]; (*rays)[6*count+3] = dir[0]; (*rays)[6*count+4] = dir[1]; (*rays)[6*count+5] = dir[2]; count++; } } *(ray_cnt) = count; return count; }
static int hit_headon(struct application *ap, struct partition *PartHeadp) { register char diff_solid; vect_t diff; register fastf_t len; if (PartHeadp->pt_forw->pt_forw != PartHeadp) Tcl_AppendResult(interp, "hit_headon: multiple partitions\n", (char *)NULL); VJOIN1(PartHeadp->pt_forw->pt_inhit->hit_point, ap->a_ray.r_pt, PartHeadp->pt_forw->pt_inhit->hit_dist, ap->a_ray.r_dir); VSUB2(diff, PartHeadp->pt_forw->pt_inhit->hit_point, aim_point); diff_solid = (FIRST_SOLID(sp) != PartHeadp->pt_forw->pt_inseg->seg_stp->st_dp); len = MAGNITUDE(diff); if ( NEAR_ZERO(len, epsilon) || ( diff_solid && VDOT(diff, ap->a_ray.r_dir) > 0 ) ) return(1); else return(0); }
/** * For a hit on the surface of an METABALL, return the (u, v) * coordinates of the hit point, 0 <= u, v <= 1. * * u = azimuth * v = elevation */ void rt_metaball_uv(struct application *ap, struct soltab *stp, struct hit *hitp, struct uvcoord *uvp) { struct rt_metaball_internal *metaball = (struct rt_metaball_internal *)stp->st_specific; vect_t work, pprime; fastf_t r; if (ap) RT_CK_APPLICATION(ap); if (stp) RT_CK_SOLTAB(stp); if (hitp) RT_CK_HIT(hitp); if (!uvp) return; if (!metaball) return; /* stuff stolen from sph */ VSUB2(work, hitp->hit_point, stp->st_center); VSCALE(pprime, work, 1.0/MAGNITUDE(work)); /* Assert that pprime has unit length */ /* U is azimuth, atan() range: -pi to +pi */ uvp->uv_u = bn_atan2(pprime[Y], pprime[X]) * M_1_2PI; if (uvp->uv_u < 0) uvp->uv_u += 1.0; /* * V is elevation, atan() range: -pi/2 to +pi/2, because sqrt() * ensures that X parameter is always >0 */ uvp->uv_v = bn_atan2(pprime[Z], sqrt(pprime[X] * pprime[X] + pprime[Y] * pprime[Y])) * M_1_2PI; /* approximation: r / (circumference, 2 * pi * aradius) */ r = ap->a_rbeam + ap->a_diverge * hitp->hit_dist; uvp->uv_du = uvp->uv_dv = M_1_2PI * r / stp->st_aradius; return; }
int _ged_scale_part(struct ged *gedp, struct rt_part_internal *part, const char *attribute, fastf_t sf, int rflag) { RT_PART_CK_MAGIC(part); switch (attribute[0]) { case 'H': if (!rflag) sf /= MAGNITUDE(part->part_H); VSCALE(part->part_H, part->part_H, sf); break; case 'v': if (rflag) part->part_vrad *= sf; else part->part_vrad = sf; break; case 'h': if (rflag) part->part_hrad *= sf; else part->part_hrad = sf; break; default: bu_vls_printf(gedp->ged_result_str, "bad part attribute - %s", attribute); return GED_ERROR; } return GED_OK; }
double ExprCommensurate( int U1, int U2 ) { unsigned int i ; double scale ; EXPR *tmp ; return 1.0 ; // EVIL HACK if( U1 == U2 ) return 1.0 ; if( U(UN(U1))->used != U(UN(U2))->used ) return 0.0 ; for( i = 1 ; i < U(UN(U1))->used ; i++ ) { if( !BooleanValue( (BOOL*) OP3( "?=", U(UN(U1))->list[i], U(UN(U2))->list[i] ) ) ) return 0.0 ; } tmp = OP3( "/", U(UN(U2))->list[0], U(UN(U1))->list[0] ) ; scale = MAGNITUDE( tmp ) ; delete tmp ; return scale ; }
void tancir(register fastf_t *cir1, register fastf_t *cir2) { static fastf_t mag; vect_t work; fastf_t f; static fastf_t temp, tempp, ang, angc; work[0] = cir2[0] - cir1[0]; work[2] = cir2[1] - cir1[1]; work[1] = 0.0; mag = MAGNITUDE( work ); if ( mag > 1.0e-20 || mag < -1.0e-20 ) { f = 1.0/mag; } else { Tcl_AppendResult(interp, "tancir(): 0-length vector!\n", (char *)NULL); return; } VSCALE(work, work, f); temp = acos( work[0] ); if ( work[2] < 0.0 ) temp = 6.28318512717958646 - temp; tempp = acos( (cir1[2] - cir2[2]) * f ); ang = temp + tempp; angc = temp - tempp; if ( (cir1[1] + cir1[2] * sin(ang)) > (cir1[1] + cir1[2] * sin(angc)) ) ang = angc; plano[0] = cir1[0] + cir1[2] * cos(ang); plano[1] = cir1[1] + cir1[2] * sin(ang); plant[0] = cir2[0] + cir2[2] * cos(ang); plant[1] = cir2[1] + cir2[2] * sin(ang); return; }
int coplanar_3d_to_2d(point2d_t **points_2d, const point_t *origin_pnt, const vect_t *u_axis, const vect_t *v_axis, const point_t *points_3d, int n) { int i = 0; for (i = 0; i < n; i++) { vect_t temp, c, d; fastf_t u, v; VSUB2(temp, points_3d[i], *origin_pnt); VPROJECT(temp, *u_axis, c, d); u = (VDOT(c, *u_axis) > 0.0) ? (MAGNITUDE(c)) : (-1.0 * MAGNITUDE(c)); v = (VDOT(d, *v_axis) > 0.0) ? (MAGNITUDE(d)) : (-1.0 * MAGNITUDE(d)); V2SET((*points_2d)[i], u, v); } return 0; }
int rt_gen_elliptical_grid(struct xrays *rays, const struct xray *center_ray, const fastf_t *avec, const fastf_t *bvec, fastf_t gridsize) { register struct xrays *xrayp; int count = 0; point_t C; vect_t dir; vect_t a_dir; vect_t b_dir; fastf_t a = MAGNITUDE(avec); fastf_t b = MAGNITUDE(bvec); fastf_t x, y; int acpr = a / gridsize; int bcpr = b / gridsize; VMOVE(a_dir, avec); VUNITIZE(a_dir); VMOVE(b_dir, bvec); VUNITIZE(b_dir); VMOVE(C, center_ray->r_pt); VMOVE(dir, center_ray->r_dir); /* make sure avec perpendicular to bvec perpendicular to ray direction */ BU_ASSERT(NEAR_ZERO(VDOT(avec, bvec), VUNITIZE_TOL)); BU_ASSERT(NEAR_ZERO(VDOT(avec, dir), VUNITIZE_TOL)); for (y=gridsize * (-bcpr); y <= b; y=y+gridsize) { for (x= gridsize * (-acpr); x <= a; x=x+gridsize) { if (((x*x)/(a*a) + (y*y)/(b*b)) < 1) { BU_ALLOC(xrayp, struct xrays); VJOIN2(xrayp->ray.r_pt, C, x, a_dir, y, b_dir); VMOVE(xrayp->ray.r_dir, dir); xrayp->ray.index = count++; xrayp->ray.magic = RT_RAY_MAGIC; BU_LIST_APPEND(&rays->l, &xrayp->l); } } } return count; }
int rt_gen_rect(struct xrays *rays, const struct xray *center_ray, const vect_t a_vec, const vect_t b_vec, const fastf_t da, const fastf_t db) { int count = 0; point_t orig_start; vect_t dir; fastf_t x, y; fastf_t a_length = MAGNITUDE(a_vec); fastf_t b_length = MAGNITUDE(b_vec); vect_t a_dir; vect_t b_dir; register struct xrays *xrayp; VMOVE(orig_start, center_ray->r_pt); VMOVE(dir, center_ray->r_dir); VMOVE(a_dir, a_vec); VUNITIZE(a_dir); VMOVE(b_dir, b_vec); VUNITIZE(b_dir); for (y = -b_length; y <= b_length; y += db) { for (x = -a_length; x <= a_length; x += da) { BU_ALLOC(xrayp, struct xrays); VJOIN2(xrayp->ray.r_pt, orig_start, x, a_dir, y, b_dir); VMOVE(xrayp->ray.r_dir, dir); xrayp->ray.index = count++; xrayp->ray.magic = RT_RAY_MAGIC; BU_LIST_APPEND(&rays->l, &xrayp->l); } } return count; }
/** * Classify a point vs a vertex (touching/missed) */ static int nmg_class_pt_vu(struct fpi *fpi, struct vertexuse *vu) { vect_t delta; struct ve_dist *ved; NMG_CK_VERTEXUSE(vu); /* see if we've classified this vertex WRT the point already */ for (BU_LIST_FOR(ved, ve_dist, &fpi->ve_dh)) { NMG_CK_VED(ved); if (ved->magic_p == &vu->v_p->magic) { goto found; } } /* if we get here, we didn't find the vertex in the list of * previously classified geometry. Create an entry in the * face's list of processed geometry. */ VSUB2(delta, vu->v_p->vg_p->coord, fpi->pt); BU_ALLOC(ved, struct ve_dist); ved->magic_p = &vu->v_p->magic; ved->dist = MAGNITUDE(delta); if (ved->dist < fpi->tol->dist_sq) { ved->status = NMG_FPI_TOUCHED; if (fpi->hits == NMG_FPI_PERGEOM) { /* need to cast vu_func pointer for actual use as a function */ void (*cfp)(struct vertexuse *, point_t, const char*); cfp = (void (*)(struct vertexuse *, point_t, const char *))fpi->vu_func; cfp(vu, fpi->pt, fpi->priv); } } else ved->status = NMG_FPI_MISSED; ved->v1 = ved->v2 = vu->v_p; BU_LIST_MAGIC_SET(&ved->l, NMG_VE_DIST_MAGIC); BU_LIST_APPEND(&fpi->ve_dh, &ved->l); found: if (fpi->vu_func && ved->status == NMG_FPI_TOUCHED && fpi->hits == NMG_FPI_PERUSE) { /* need to cast vu_func pointer for actual use as a function */ void (*cfp)(struct vertexuse *, point_t, const char*); cfp = (void (*)(struct vertexuse *, point_t, const char *))fpi->vu_func; cfp(vu, fpi->pt, fpi->priv); } return ved->status; }
/** * R T _ P G F A C E * * This function is called with pointers to 3 points, * and is used to prepare PG faces. * ap, bp, cp point to vect_t points. * * Return - * 0 if the 3 points didn't form a plane (e.g., colinear, etc.). * # pts (3) if a valid plane resulted. */ HIDDEN int rt_pgface(struct soltab *stp, fastf_t *ap, fastf_t *bp, fastf_t *cp, const struct bn_tol *tol) { struct tri_specific *trip; vect_t work; fastf_t m1, m2, m3, m4; BU_GET(trip, struct tri_specific); VMOVE(trip->tri_A, ap); VSUB2(trip->tri_BA, bp, ap); VSUB2(trip->tri_CA, cp, ap); VCROSS(trip->tri_wn, trip->tri_BA, trip->tri_CA); /* Check to see if this plane is a line or pnt */ m1 = MAGNITUDE(trip->tri_BA); m2 = MAGNITUDE(trip->tri_CA); VSUB2(work, bp, cp); m3 = MAGNITUDE(work); m4 = MAGNITUDE(trip->tri_wn); if (m1 < tol->dist || m2 < tol->dist || m3 < tol->dist || m4 < tol->dist) { BU_PUT(trip, struct tri_specific); if (RT_G_DEBUG & DEBUG_ARB8) bu_log("pg(%s): degenerate facet\n", stp->st_name); return 0; /* BAD */ } /* wn is a normal of not necessarily unit length. * N is an outward pointing unit normal. * We depend on the points being given in CCW order here. */ VMOVE(trip->tri_N, trip->tri_wn); VUNITIZE(trip->tri_N); /* Add this face onto the linked list for this solid */ trip->tri_forw = (struct tri_specific *)stp->st_specific; stp->st_specific = (genptr_t)trip; return 3; /* OK */ }
/** *@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); }
void quat_log(fastf_t *out, const fastf_t *in) { fastf_t theta; fastf_t scale; if ( (scale = MAGNITUDE(in)) > VDIVIDE_TOL ) { theta = atan2( scale, in[W] ); scale = theta/scale; } VSCALE( out, in, scale ); out[W] = 0.0; }
void quat_exp(fastf_t *out, const fastf_t *in) { fastf_t theta; fastf_t scale; if ( (theta = MAGNITUDE( in )) > VDIVIDE_TOL ) scale = sin(theta)/theta; else scale = 1.0; VSCALE( out, in, scale ); out[W] = cos(theta); }
/** * Computes the volume of a superellipsoid * * Volume equation from http://lrv.fri.uni-lj.si/~franc/SRSbook/geometry.pdf * which also includes a derivation on page 32. */ void rt_superell_volume(fastf_t *volume, const struct rt_db_internal *ip) { #ifdef HAVE_TGAMMA struct rt_superell_internal *sip; double mag_a, mag_b, mag_c; #endif if (volume == NULL || ip == NULL) { return; } #ifdef HAVE_TGAMMA RT_CK_DB_INTERNAL(ip); sip = (struct rt_superell_internal *)ip->idb_ptr; RT_SUPERELL_CK_MAGIC(sip); mag_a = MAGNITUDE(sip->a); mag_b = MAGNITUDE(sip->b); mag_c = MAGNITUDE(sip->c); *volume = 2.0 * mag_a * mag_b * mag_c * sip->e * sip->n * (tgamma(sip->n/2.0 + 1.0) * tgamma(sip->n) / tgamma(3.0 * sip->n/2.0 + 1.0)) * (tgamma(sip->e / 2.0) * tgamma(sip->e / 2.0) / tgamma(sip->e)); #endif }
/* * Replica of STEP function: * FUNCTION first_proj_axis() */ void Axis2Placement3D::FirstProjAxis(double *proj,double *zaxis, double *refdir) { double z[3] = VINIT_ZERO; double v[3] = VINIT_ZERO; double TOL = 1e-9; if (zaxis == NULL) return; VMOVE(z,zaxis); VUNITIZE(z); if (refdir == NULL) { double xplus[3]= {1.0,0.0,0.0}; double xminus[3]= {-1.0,0.0,0.0}; if (!VNEAR_EQUAL(z, xplus, TOL) && !VNEAR_EQUAL(z, xminus, TOL)) { VSET(v,1.0,0.0,0.0); } else { VSET(v,0.0,1.0,0.0); } } else { double cross[3]; double mag; VCROSS(cross, refdir, z); mag = MAGNITUDE(cross); if (NEAR_ZERO(mag,TOL)) { return; } else { VMOVE(v,refdir); VUNITIZE(v); } } double x_vec[3]; double aproj[3]; double dot = VDOT(v,z); ScalarTimesVector(x_vec, dot, z); VectorDifference(aproj,v,x_vec); VSCALE(x_vec,z,dot); VSUB2(aproj,v, x_vec); VUNITIZE(aproj); VMOVE(proj,aproj); return; }
/** * Given ONE ray distance, return the normal and entry/exit point. */ void rt_superell_norm(struct hit *hitp, struct soltab *stp, struct xray *rp) { struct superell_specific *superell = (struct superell_specific *)stp->st_specific; vect_t xlated; fastf_t scale; VJOIN1(hitp->hit_point, rp->r_pt, hitp->hit_dist, rp->r_dir); VSUB2(xlated, hitp->hit_point, superell->superell_V); MAT4X3VEC(hitp->hit_normal, superell->superell_invRSSR, xlated); scale = 1.0 / MAGNITUDE(hitp->hit_normal); VSCALE(hitp->hit_normal, hitp->hit_normal, scale); return; }
/* * Convert an ascii nmg description into a BRL-CAD data base. */ static int ascii_to_brlcad(FILE *fpin, struct rt_wdb *fpout, char *reg_name, char *grp_name) { struct model *m; struct nmgregion *r; struct bn_tol tol; struct shell *s; vect_t Ext; struct faceuse *fu; plane_t pl; VSETALL(Ext, 0.); m = nmg_mm(); /* Make nmg model. */ r = nmg_mrsv(m); /* Make region, empty shell, vertex */ s = BU_LIST_FIRST(shell, &r->s_hd); descr_to_nmg(s, fpin, Ext); /* Convert ascii description to nmg. */ /* Copied from proc-db/nmgmodel.c */ tol.magic = BN_TOL_MAGIC; tol.dist = 0.01; tol.dist_sq = tol.dist * tol.dist; tol.perp = 0.001; tol.para = 0.999; /* Associate the face geometry. */ fu = BU_LIST_FIRST( faceuse, &s->fu_hd ); if (nmg_loop_plane_area(BU_LIST_FIRST(loopuse, &fu->lu_hd), pl) < 0.0) return -1; else nmg_face_g( fu, pl ); if (!NEAR_ZERO(MAGNITUDE(Ext), 0.001)) nmg_extrude_face(BU_LIST_FIRST(faceuse, &s->fu_hd), Ext, &tol); nmg_region_a(r, &tol); /* Calculate geometry for region and shell. */ nmg_fix_normals( s, &tol ); /* insure that faces have outward pointing normals */ create_brlcad_db(fpout, m, reg_name, grp_name); return 0; }
int coplanar_2d_to_3d(point_t **points_3d, const point_t *origin_pnt, const vect_t *u_axis, const vect_t *v_axis, const point2d_t *points_2d, int n) { int i; vect_t u_x_component, u_y_component, u_z_component; vect_t v_x_component, v_y_component, v_z_component; vect_t x_axis, y_axis, z_axis; vect_t temp; fastf_t mag_u_x, mag_u_y, mag_u_z; fastf_t mag_v_x, mag_v_y, mag_v_z; VSET(x_axis, 1.0, 0.0, 0.0); VSET(y_axis, 0.0, 1.0, 0.0); VSET(z_axis, 0.0, 0.0, 1.0); /* Step 1 - find the 3d X, Y and Z components of u_axis and v_axis */ VPROJECT(*u_axis, x_axis, u_x_component, temp); VPROJECT(temp, y_axis, u_y_component, u_z_component); VPROJECT(*v_axis, x_axis, v_x_component, temp); VPROJECT(temp, y_axis, v_y_component, v_z_component); mag_u_x = (VDOT(u_x_component, x_axis) > 0.0) ? (MAGNITUDE(u_x_component)) : (-1.0 * MAGNITUDE(u_x_component)); mag_u_y = (VDOT(u_y_component, y_axis) > 0.0) ? (MAGNITUDE(u_y_component)) : (-1.0 * MAGNITUDE(u_y_component)); mag_u_z = (VDOT(u_z_component, z_axis) > 0.0) ? (MAGNITUDE(u_z_component)) : (-1.0 * MAGNITUDE(u_z_component)); mag_v_x = (VDOT(v_x_component, x_axis) > 0.0) ? (MAGNITUDE(v_x_component)) : (-1.0 * MAGNITUDE(v_x_component)); mag_v_y = (VDOT(v_y_component, y_axis) > 0.0) ? (MAGNITUDE(v_y_component)) : (-1.0 * MAGNITUDE(v_y_component)); mag_v_z = (VDOT(v_z_component, z_axis) > 0.0) ? (MAGNITUDE(v_z_component)) : (-1.0 * MAGNITUDE(v_z_component)); /* Step 2 - for each 2D point, calculate the (x,y,z) coordinates as follows: * (http://math.stackexchange.com/questions/525829/how-to-find-the-3d-coordinate-of-a-2d-point-on-a-known-plane) */ for (i = 0; i < n; i++) { vect_t temp_2d; VSET(temp_2d, points_2d[i][0]*mag_u_x + (points_2d)[i][1]*mag_v_x, (points_2d)[i][0]*mag_u_y + (points_2d)[i][1]*mag_v_y, (points_2d)[i][0]*mag_u_z + (points_2d)[i][1]*mag_v_z); VADD2((*points_3d)[i], (*origin_pnt), temp_2d); } return 0; }
static void render_camera_prep_persp_dof(render_camera_t *camera) { vect_t look, up, side, dof_look, dof_up, dof_side, dof_topl, dof_topr, dof_botl, temp, step_x, step_y, topl, topr, botl; tfloat angle, mag, sfov, cfov, sdof, cdof; uint32_t i, n; /* Generate unitized lookector */ VSUB2(dof_look, camera->focus, camera->pos); VUNITIZE(dof_look); /* Generate standard up vector */ dof_up[0] = 0; dof_up[1] = 0; dof_up[2] = 1; /* Make unitized up vector perpendicular to lookector */ VMOVE(temp, dof_look); angle = VDOT(dof_up, temp); VSCALE(temp, temp, angle); VSUB2(dof_up, dof_up, temp); VUNITIZE(dof_up); /* Generate a temporary side vector */ VCROSS(dof_side, dof_up, dof_look); /* Apply tilt to up vector - negate angle to make positive angles clockwise */ sdof = sin(-camera->tilt * DEG2RAD); cdof = cos(-camera->tilt * DEG2RAD); VSCALE(dof_up, dof_up, cdof); VSCALE(dof_side, dof_side, sdof); VADD2(dof_up, dof_up, dof_side); /* Create final side vector */ VCROSS(dof_side, dof_up, dof_look); /* * Generate a camera position, top left vector, and step vectors for each DOF sample */ /* Obtain magnitude of reverse lookector */ VSUB2(dof_look, camera->pos, camera->focus); mag = MAGNITUDE(dof_look); VUNITIZE(dof_look); /* Compute sine and cosine terms for field of view */ sdof = sin(camera->dof*DEG2RAD); cdof = cos(camera->dof*DEG2RAD); /* Up, Look, and Side vectors are complete, generate Top Left reference vector */ dof_topl[0] = sdof*dof_up[0] + sdof*dof_side[0] + cdof*dof_look[0]; dof_topl[1] = sdof*dof_up[1] + sdof*dof_side[1] + cdof*dof_look[1]; dof_topl[2] = sdof*dof_up[2] + sdof*dof_side[2] + cdof*dof_look[2]; dof_topr[0] = sdof*dof_up[0] - sdof*dof_side[0] + cdof*dof_look[0]; dof_topr[1] = sdof*dof_up[1] - sdof*dof_side[1] + cdof*dof_look[1]; dof_topr[2] = sdof*dof_up[2] - sdof*dof_side[2] + cdof*dof_look[2]; dof_botl[0] = -sdof*dof_up[0] + sdof*dof_side[0] + cdof*dof_look[0]; dof_botl[1] = -sdof*dof_up[1] + sdof*dof_side[1] + cdof*dof_look[1]; dof_botl[2] = -sdof*dof_up[2] + sdof*dof_side[2] + cdof*dof_look[2]; VUNITIZE(dof_topl); VUNITIZE(dof_botl); VUNITIZE(dof_topr); VSUB2(step_x, dof_topr, dof_topl); VSUB2(step_y, dof_botl, dof_topl); for (i = 0; i < RENDER_CAMERA_DOF_SAMPLES; i++) { for (n = 0; n < RENDER_CAMERA_DOF_SAMPLES; n++) { /* Generate virtual camera position for this depth of field sample */ VSCALE(temp, step_x, ((tfloat)i/(tfloat)(RENDER_CAMERA_DOF_SAMPLES-1))); VADD2(camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].pos, dof_topl, temp); VSCALE(temp, step_y, ((tfloat)n/(tfloat)(RENDER_CAMERA_DOF_SAMPLES-1))); VADD2(camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].pos, camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].pos, temp); VUNITIZE(camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].pos); VSCALE(camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].pos, camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].pos, mag); VADD2(camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].pos, camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].pos, camera->focus); /* Generate unitized lookector */ VSUB2(look, camera->focus, camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].pos); VUNITIZE(look); /* Generate standard up vector */ up[0] = 0; up[1] = 0; up[2] = 1; /* Make unitized up vector perpendicular to lookector */ VMOVE(temp, look); angle = VDOT(up, temp); VSCALE(temp, temp, angle); VSUB2(up, up, temp); VUNITIZE(up); /* Generate a temporary side vector */ VCROSS(side, up, look); /* Apply tilt to up vector - negate angle to make positive angles clockwise */ sfov = sin(-camera->tilt * DEG2RAD); cfov = cos(-camera->tilt * DEG2RAD); VSCALE(up, up, cfov); VSCALE(side, side, sfov); VADD2(up, up, side); /* Create final side vector */ VCROSS(side, up, look); /* Compute sine and cosine terms for field of view */ sfov = sin(camera->fov*DEG2RAD); cfov = cos(camera->fov*DEG2RAD); /* Up, Look, and Side vectors are complete, generate Top Left reference vector */ topl[0] = sfov*up[0] + camera->aspect*sfov*side[0] + cfov*look[0]; topl[1] = sfov*up[1] + camera->aspect*sfov*side[1] + cfov*look[1]; topl[2] = sfov*up[2] + camera->aspect*sfov*side[2] + cfov*look[2]; topr[0] = sfov*up[0] - camera->aspect*sfov*side[0] + cfov*look[0]; topr[1] = sfov*up[1] - camera->aspect*sfov*side[1] + cfov*look[1]; topr[2] = sfov*up[2] - camera->aspect*sfov*side[2] + cfov*look[2]; botl[0] = -sfov*up[0] + camera->aspect*sfov*side[0] + cfov*look[0]; botl[1] = -sfov*up[1] + camera->aspect*sfov*side[1] + cfov*look[1]; botl[2] = -sfov*up[2] + camera->aspect*sfov*side[2] + cfov*look[2]; VUNITIZE(topl); VUNITIZE(botl); VUNITIZE(topr); /* Store the top left vector */ VMOVE(camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].top_l, topl); /* Generate stepx and stepy vectors for sampling each pixel */ VSUB2(camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].step_x, topr, topl); VSUB2(camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].step_y, botl, topl); /* Divide stepx and stepy by the number of pixels */ VSCALE(camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].step_x, camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].step_x, 1.0 / camera->w); VSCALE(camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].step_y, camera->view_list[i*RENDER_CAMERA_DOF_SAMPLES+n].step_y, 1.0 / camera->h); } } }
extern "C" void rt_nmg_brep(ON_Brep **b, const struct rt_db_internal *ip, const struct bn_tol *tol) { struct model *m; struct nmgregion *r; struct shell *s; struct faceuse *fu; struct loopuse *lu; struct edgeuse *eu; int edge_index; long* brepi; RT_CK_DB_INTERNAL(ip); m = (struct model *)ip->idb_ptr; NMG_CK_MODEL(m); brepi = static_cast<long*>(bu_malloc(m->maxindex * sizeof(long), "rt_nmg_brep: brepi[]")); for (int i = 0; i < m->maxindex; i++) brepi[i] = -INT_MAX; for (BU_LIST_FOR(r, nmgregion, &m->r_hd)) { for (BU_LIST_FOR(s, shell, &r->s_hd)) { for (BU_LIST_FOR(fu, faceuse, &s->fu_hd)) { NMG_CK_FACEUSE(fu); if (fu->orientation != OT_SAME) continue; // Need to create ON_NurbsSurface based on plane of // face in order to have UV space in which to define // trimming loops. Bounding points are NOT on the // face plane, so another approach must be used. // // General approach: For all loops in the faceuse, // collect all the vertices. Find the center point of // all the vertices, and search for the point with the // greatest distance from that center point. Once // found, cross the vector between the center point // and furthest point with the normal of the face and // scale the resulting vector to have the same length // as the vector to the furthest point. Add the two // resulting vectors to find the first corner point. // Mirror the first corner point across the center to // find the second corner point. Cross the two // vectors created by the first two corner points with // the face normal to get the vectors of the other two // corners, and scale the resulting vectors to the // same magnitude as the first two. These four points // bound all vertices on the plane and form a suitable // staring point for a UV space, since all points on // all the edges are equal to or further than the // distance between the furthest vertex and the center // point. // ............. ............. // . .* . . // . . . . . // . . . . . // . . . * . // . . . . . // . . . . . // . . . . . // . * * . . // . . . . // . . . . // . . . . // . *. . . // . ... ...* . // . .... .... . // . * . // ........................... // const struct face_g_plane *fg = fu->f_p->g.plane_p; struct bu_ptbl vert_table; nmg_tabulate_face_g_verts(&vert_table, fg); point_t tmppt, center, max_pt; struct vertex **pt; VSET(tmppt, 0, 0, 0); VSET(max_pt, 0, 0, 0); int ptcnt = 0; for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) { tmppt[0] += (*pt)->vg_p->coord[0]; tmppt[1] += (*pt)->vg_p->coord[1]; tmppt[2] += (*pt)->vg_p->coord[2]; ptcnt++; 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; } } VSET(center, tmppt[0]/ptcnt, tmppt[1]/ptcnt, tmppt[2]/ptcnt); fastf_t max_dist = 0.0; fastf_t curr_dist; for (BU_PTBL_FOR(pt, (struct vertex **), &vert_table)) { tmppt[0] = (*pt)->vg_p->coord[0]; tmppt[1] = (*pt)->vg_p->coord[1]; tmppt[2] = (*pt)->vg_p->coord[2]; curr_dist = DIST_PT_PT(center, tmppt); if (curr_dist > max_dist) { max_dist = curr_dist; VMOVE(max_pt, tmppt); } } bu_ptbl_free(&vert_table); int ccw = 0; vect_t vtmp, uv1, uv2, uv3, uv4, vnormal; // If an outer loop is found in the nmg with a cw // orientation, use a flipped normal to form the NURBS // surface 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]); } VSUB2(uv1, max_pt, center); VCROSS(vtmp, uv1, vnormal); VADD2(uv1, uv1, vtmp); VCROSS(uv2, uv1, vnormal); VREVERSE(uv3, uv1); VCROSS(uv4, uv3, vnormal); VADD2(uv1, uv1, center); VADD2(uv2, uv2, center); VADD2(uv3, uv3, center); VADD2(uv4, uv4, center); ON_3dPoint p1 = ON_3dPoint(uv1); ON_3dPoint p2 = ON_3dPoint(uv2); ON_3dPoint p3 = ON_3dPoint(uv3); ON_3dPoint p4 = ON_3dPoint(uv4); (*b)->m_S.Append(sideSurface(p1, p4, p3, p2)); ON_Surface *surf = (*(*b)->m_S.Last()); int surfindex = (*b)->m_S.Count(); // Now that we have the surface, define the face 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. vect_t u_axis, v_axis; VSUB2(u_axis, uv2, uv1); VSUB2(v_axis, uv4, uv1); fastf_t u_axis_dist = MAGNITUDE(u_axis); fastf_t v_axis_dist = MAGNITUDE(v_axis); // Now that the surface context is set up, add the loops. for (BU_LIST_FOR(lu, loopuse, &fu->lu_hd)) { int edges=0; if (BU_LIST_FIRST_MAGIC(&lu->down_hd) != NMG_EDGEUSE_MAGIC) continue; // loop is a single vertex ON_BrepLoop::TYPE looptype; // Check if this is an inner or outer loop if (lu->orientation == OT_SAME) { looptype = ON_BrepLoop::outer; } else { looptype = ON_BrepLoop::inner; } ON_BrepLoop& loop = (*b)->NewLoop(looptype, face); for (BU_LIST_FOR(eu, edgeuse, &lu->down_hd)) { ++edges; vect_t ev1, ev2; struct vertex_g *vg1, *vg2; vg1 = eu->vu_p->v_p->vg_p; NMG_CK_VERTEX_G(vg1); int vert1 = brepi[vg1->index]; VMOVE(ev1, vg1->coord); vg2 = eu->eumate_p->vu_p->v_p->vg_p; NMG_CK_VERTEX_G(vg2); int vert2 = brepi[vg2->index]; 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 */ if (vg1->index > vg2->index) { int tmpvert = vert1; vert1 = vert2; vert2 = tmpvert; } // 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 vect_t u_component, v_component; ON_3dPoint vg1pt(vg1->coord); int orientation = 0; edge_index = brepi[eu->e_p->index]; if (vg1pt != (*b)->m_V[(*b)->m_E[edge_index].m_vi[0]].Point()) { orientation = 1; } // Now, make 2d trimming curves vect_t vect1, vect2; VSUB2(vect1, ev1, uv1); VSUB2(vect2, ev2, uv1); ON_2dPoint from_uv, to_uv; double u0, u1, v0, v1; 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_3dPoint S1, S2; ON_3dVector Su, Sv; surf->Ev1Der(from_uv.x, from_uv.y, S1, Su, Sv); surf->Ev1Der(to_uv.x, to_uv.y, S2, Su, Sv); 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); edge_index = brepi[eu->e_p->index]; ON_BrepTrim& trim = (*b)->NewTrim((*b)->m_E[edge_index], orientation, loop, c2i); trim.m_type = ON_BrepTrim::mated; trim.m_tolerance[0] = 0.0; trim.m_tolerance[1] = 0.0; } } } (*b)->SetTrimIsoFlags(); } } bu_free(brepi, "rt_nmg_brep: brepi[]"); }
/* * F _ H I D E L I N E */ int f_hideline(ClientData clientData, Tcl_Interp *interp, int argc, char **argv) { FILE *plotfp; char visible; int i, numobjs; char *objname[MAXOBJECTS], title[1]; fastf_t len, u, step; float ratio; vect_t last_move; struct rt_i *rtip; struct resource resource; struct application a; vect_t temp; vect_t last, dir; register struct bn_vlist *vp; CHECK_DBI_NULL; if (argc < 2 || 4 < argc) { struct bu_vls vls; bu_vls_init(&vls); bu_vls_printf(&vls, "help H"); Tcl_Eval(interp, bu_vls_addr(&vls)); bu_vls_free(&vls); return TCL_ERROR; } if ((plotfp = fopen(argv[1], "w")) == NULL) { Tcl_AppendResult(interp, "f_hideline: unable to open \"", argv[1], "\" for writing.\n", (char *)NULL); return TCL_ERROR; } pl_space(plotfp, (int)GED_MIN, (int)GED_MIN, (int)GED_MAX, (int)GED_MAX); /* Build list of objects being viewed */ numobjs = 0; FOR_ALL_SOLIDS(sp) { for (i = 0; i < numobjs; i++) { if ( objname[i] == FIRST_SOLID(sp)->d_namep ) break; } if (i == numobjs) objname[numobjs++] = FIRST_SOLID(sp)->d_namep; } Tcl_AppendResult(interp, "Generating hidden-line drawing of the following regions:\n", (char *)NULL); for (i = 0; i < numobjs; i++) Tcl_AppendResult(interp, "\t", objname[i], "\n", (char *)NULL); /* Initialization for librt */ if ((rtip = rt_dirbuild(dbip->dbi_filename, title, 0)) == RTI_NULL) { Tcl_AppendResult(interp, "f_hideline: unable to open model file \"", dbip->dbi_filename, "\"\n", (char *)NULL); return TCL_ERROR; } a.a_hit = hit_headon; a.a_miss = hit_tangent; a.a_overlap = hit_overlap; a.a_rt_i = rtip; a.a_resource = &resource; a.a_level = 0; a.a_onehit = 1; a.a_diverge = 0; a.a_rbeam = 0; if (argc > 2) { sscanf(argv[2], "%f", &step); step = view_state->vs_Viewscale/step; sscanf(argv[3], "%f", &epsilon); epsilon *= view_state->vs_Viewscale/100; } else { step = view_state->vs_Viewscale/256; epsilon = 0.1*view_state->vs_Viewscale; } for (i = 0; i < numobjs; i++) if (rt_gettree(rtip, objname[i]) == -1) Tcl_AppendResult(interp, "f_hideline: rt_gettree failed on \"", objname[i], "\"\n", (char *)NULL); /* Crawl along the vectors raytracing as we go */ VSET(temp, 0.0, 0.0, -1.0); /* looking at model */ MAT4X3VEC(a.a_ray.r_dir, view_state->vs_view2model, temp); VUNITIZE(a.a_ray.r_dir); FOR_ALL_SOLIDS(sp) { ratio = sp->s_size / VIEWSIZE; /* ignore if small or big */ if (ratio >= dmp->dmr_bound || ratio < 0.001) continue; Tcl_AppendResult(interp, "Primitive\n", (char *)NULL); for ( BU_LIST_FOR( vp, bn_vlist, &(sp->s_vlist) ) ) { register int i; register int nused = vp->nused; register int *cmd = vp->cmd; register point_t *pt = vp->pt; for ( i = 0; i < nused; i++, cmd++, pt++ ) { Tcl_AppendResult(interp, "\tVector\n", (char *)NULL); switch ( *cmd ) { case BN_VLIST_POLY_START: case BN_VLIST_POLY_VERTNORM: break; case BN_VLIST_POLY_MOVE: case BN_VLIST_LINE_MOVE: /* move */ VMOVE(last, *pt); MOVE(last); break; case BN_VLIST_POLY_DRAW: case BN_VLIST_POLY_END: case BN_VLIST_LINE_DRAW: /* setup direction && length */ VSUB2(dir, *pt, last); len = MAGNITUDE(dir); VUNITIZE(dir); visible = FALSE; { struct bu_vls tmp_vls; bu_vls_init(&tmp_vls); bu_vls_printf(&tmp_vls, "\t\tDraw 0 -> %g, step %g\n", len, step); Tcl_AppendResult(interp, bu_vls_addr(&tmp_vls), (char *)NULL); bu_vls_free(&tmp_vls); } for (u = 0; u <= len; u += step) { VJOIN1(aim_point, last, u, dir); MAT4X3PNT(temp, view_state->vs_model2view, aim_point); temp[Z] = 100; /* parallel project */ MAT4X3PNT(a.a_ray.r_pt, view_state->vs_view2model, temp); if (rt_shootray(&a)) { if (!visible) { visible = TRUE; MOVE(aim_point); } } else { if (visible) { visible = FALSE; DRAW(aim_point); } } } if (visible) DRAW(aim_point); VMOVE(last, *pt); /* new last vertex */ } } } } fclose(plotfp); return TCL_OK; }
/** * Given a pointer to an internal GED database object, mirror the * object's values about the given transformation matrix. */ int rt_half_mirror(struct rt_db_internal *ip, register const plane_t plane) { struct rt_half_internal *half; mat_t mirmat; mat_t rmat; mat_t temp; vect_t nvec; vect_t xvec; vect_t mirror_dir; point_t mirror_pt; fastf_t ang; vect_t n1; vect_t n2; static fastf_t tol_dist_sq = 0.0005 * 0.0005; static point_t origin = {0.0, 0.0, 0.0}; RT_CK_DB_INTERNAL(ip); half = (struct rt_half_internal *)ip->idb_ptr; RT_HALF_CK_MAGIC(half); MAT_IDN(mirmat); VMOVE(mirror_dir, plane); VSCALE(mirror_pt, plane, plane[W]); /* Build mirror transform matrix, for those who need it. */ /* First, perform a mirror down the X axis */ mirmat[0] = -1.0; /* Create the rotation matrix */ VSET(xvec, 1, 0, 0); VCROSS(nvec, xvec, mirror_dir); VUNITIZE(nvec); ang = -acos(VDOT(xvec, mirror_dir)); bn_mat_arb_rot(rmat, origin, nvec, ang*2.0); /* Add the rotation to mirmat */ MAT_COPY(temp, mirmat); bn_mat_mul(mirmat, temp, rmat); /* Add the translation to mirmat */ mirmat[3 + X*4] += mirror_pt[X] * mirror_dir[X]; mirmat[3 + Y*4] += mirror_pt[Y] * mirror_dir[Y]; mirmat[3 + Z*4] += mirror_pt[Z] * mirror_dir[Z]; /* FIXME: this is not using the mirmat we just computed, not clear * it's even right given it's only taking the mirror direction * into account and not the mirror point. */ VMOVE(n1, half->eqn); VCROSS(n2, mirror_dir, n1); VUNITIZE(n2); ang = M_PI_2 - acos(VDOT(n1, mirror_dir)); bn_mat_arb_rot(rmat, origin, n2, ang*2); MAT4X3VEC(half->eqn, rmat, n1); if (!NEAR_EQUAL(VDOT(n1, half->eqn), 1.0, tol_dist_sq)) { point_t ptA; point_t ptB; point_t ptC; vect_t h; fastf_t mag; fastf_t cosa; VSCALE(ptA, n1, half->eqn[H]); VADD2(ptB, ptA, mirror_dir); VSUB2(h, ptB, ptA); mag = MAGNITUDE(h); VUNITIZE(h); cosa = VDOT(h, mirror_dir); VSCALE(ptC, half->eqn, -mag * cosa); VADD2(ptC, ptC, ptA); half->eqn[H] = VDOT(half->eqn, ptC); } return 0; }
/** * R T _ P G _ T O _ B O T * * Convert in-memory form of a polysolid (pg) to a bag of triangles (BoT) * There is no record in the V5 database for a polysolid. * * Depends on the "max_npts" parameter having been set. * * Returns - * -1 FAIL * 0 OK */ int rt_pg_to_bot(struct rt_db_internal *ip, const struct bn_tol *tol, struct resource *resp) { struct rt_pg_internal *ip_pg; struct rt_bot_internal *ip_bot; size_t max_pts; size_t max_tri; size_t p; size_t i; RT_CK_DB_INTERNAL(ip); BN_CK_TOL(tol); RT_CK_RESOURCE(resp); if (ip->idb_type != ID_POLY) { bu_log("ERROR: rt_pt_to_bot() called with a non-polysolid!!!\n"); return -1; } ip_pg = (struct rt_pg_internal *)ip->idb_ptr; RT_PG_CK_MAGIC(ip_pg); BU_ALLOC(ip_bot, struct rt_bot_internal); ip_bot->magic = RT_BOT_INTERNAL_MAGIC; ip_bot->mode = RT_BOT_SOLID; ip_bot->orientation = RT_BOT_CCW; ip_bot->bot_flags = 0; /* maximum possible vertices */ max_pts = ip_pg->npoly * ip_pg->max_npts; BU_ASSERT_SIZE_T(max_pts, >, 0); /* maximum possible triangular faces */ max_tri = ip_pg->npoly * 3; BU_ASSERT_SIZE_T(max_tri, >, 0); ip_bot->num_vertices = 0; ip_bot->num_faces = 0; ip_bot->thickness = (fastf_t *)NULL; ip_bot->face_mode = (struct bu_bitv *)NULL; ip_bot->vertices = (fastf_t *)bu_calloc(max_pts * 3, sizeof(fastf_t), "BOT vertices"); ip_bot->faces = (int *)bu_calloc(max_tri * 3, sizeof(int), "BOT faces"); for (p=0; p<ip_pg->npoly; p++) { vect_t work[3], tmp; struct tri_specific trip; fastf_t m1, m2, m3, m4; size_t v0=0, v2=0; int first; first = 1; VMOVE(work[0], &ip_pg->poly[p].verts[0*3]); VMOVE(work[1], &ip_pg->poly[p].verts[1*3]); for (i=2; i < ip_pg->poly[p].npts; i++) { VMOVE(work[2], &ip_pg->poly[p].verts[i*3]); VSUB2(trip.tri_BA, work[1], work[0]); VSUB2(trip.tri_CA, work[2], work[0]); VCROSS(trip.tri_wn, trip.tri_BA, trip.tri_CA); /* Check to see if this plane is a line or pnt */ m1 = MAGNITUDE(trip.tri_BA); m2 = MAGNITUDE(trip.tri_CA); VSUB2(tmp, work[1], work[2]); m3 = MAGNITUDE(tmp); m4 = MAGNITUDE(trip.tri_wn); if (m1 >= tol->dist && m2 >= tol->dist && m3 >= tol->dist && m4 >= tol->dist) { /* add this triangle to the BOT */ if (first) { ip_bot->faces[ip_bot->num_faces * 3] = ip_bot->num_vertices; VMOVE(&ip_bot->vertices[ip_bot->num_vertices * 3], work[0]); v0 = ip_bot->num_vertices; ip_bot->num_vertices++; ip_bot->faces[ip_bot->num_faces * 3 + 1] = ip_bot->num_vertices; VMOVE(&ip_bot->vertices[ip_bot->num_vertices * 3], work[1]); ip_bot->num_vertices++; first = 0; } else { ip_bot->faces[ip_bot->num_faces * 3] = v0; ip_bot->faces[ip_bot->num_faces * 3 + 1] = v2; } VMOVE(&ip_bot->vertices[ip_bot->num_vertices * 3], work[2]); ip_bot->faces[ip_bot->num_faces * 3 + 2] = ip_bot->num_vertices; v2 = ip_bot->num_vertices; ip_bot->num_vertices++; ip_bot->num_faces++; } /* Chop off a triangle, and continue */ VMOVE(work[1], work[2]); } } rt_bot_vertex_fuse(ip_bot, tol); rt_bot_face_fuse(ip_bot); rt_db_free_internal(ip); ip->idb_major_type = DB5_MAJORTYPE_BRLCAD; ip->idb_type = ID_BOT; ip->idb_meth = &rt_functab[ID_BOT]; ip->idb_ptr = ip_bot; return 0; }