/** * R E C _ C U R V E * * Return the "curvature" of the cylinder. If an endplate, * pick a principle direction orthogonal to the normal, and * indicate no curvature. Otherwise, compute curvature. * Normal must have been computed before calling this routine. */ void rt_rec_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp) { struct rec_specific *rec = (struct rec_specific *)stp->st_specific; vect_t uu; fastf_t ax, bx, q; switch (hitp->hit_surfno) { case REC_NORM_BODY: /* This could almost certainly be simpler if we used * inverse A rather than inverse A squared, right Ed? */ VMOVE(cvp->crv_pdir, rec->rec_Hunit); VSUB2(uu, hitp->hit_point, rec->rec_V); cvp->crv_c1 = 0; ax = VDOT(uu, rec->rec_A) * rec->rec_iAsq; bx = VDOT(uu, rec->rec_B) * rec->rec_iBsq; q = sqrt(ax * ax * rec->rec_iAsq + bx * bx * rec->rec_iBsq); cvp->crv_c2 = - rec->rec_iAsq * rec->rec_iBsq / (q*q*q); break; case REC_NORM_TOP: case REC_NORM_BOT: bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal); cvp->crv_c1 = cvp->crv_c2 = 0; break; default: bu_log("rt_rec_curve: bad surfno %d\n", hitp->hit_surfno); break; } }
/** * Return the "curvature" of the ARB face. * Pick a principle direction orthogonal to normal, and * indicate no curvature. */ void rt_arbn_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp) { struct rt_arbn_internal *arbn = (struct rt_arbn_internal *)stp->st_specific; RT_ARBN_CK_MAGIC(arbn); bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal); cvp->crv_c1 = cvp->crv_c2 = 0; }
/** * R T _ P G _ C U R V E */ void rt_pg_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp) { if (!cvp || !hitp) return; RT_CK_HIT(hitp); if (stp) RT_CK_SOLTAB(stp); bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal); cvp->crv_c1 = cvp->crv_c2 = 0; }
/** * Return the curvature of the revolve. */ void rt_revolve_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp) { if (!cvp || !hitp) return; RT_CK_HIT(hitp); if (stp) RT_CK_SOLTAB(stp); cvp->crv_c1 = cvp->crv_c2 = 0; /* any tangent direction */ bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal); }
/** *@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); }
/** * Return the curvature of the xxx. */ void rt_xxx_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp) { struct xxx_specific *xxx; if (!stp) return; xxx = (struct xxx_specific *)stp->st_specific; if (!xxx) return; RT_CK_SOLTAB(stp); cvp->crv_c1 = cvp->crv_c2 = 0; /* any tangent direction */ bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal); }
HIDDEN int rt_pattern_circ_spiral(fastf_t **rays, size_t *ray_cnt, const point_t center_pt, const vect_t dir, const double radius, const int rays_per_ring, const int nring, const double delta) { int ring; double fraction = 1.0; double theta; double radial_scale; vect_t avec, bvec; int ray_index = 0; bn_vec_ortho(avec, dir); VCROSS(bvec, dir, avec); VUNITIZE(bvec); if (!rays || !ray_cnt) return -1; *(rays) = (fastf_t *)bu_calloc(sizeof(fastf_t) * 6, (rays_per_ring * nring) + 1, "rays"); for (ring = 0; ring < nring; ring++) { register int i; theta = 0; fraction = ((double)(ring+1)) / nring; theta = delta * fraction; /* spiral skew */ radial_scale = radius * fraction; for (i=0; i < rays_per_ring; i++) { register double ct, st; point_t pt; /* pt = V + cos(theta) * A + sin(theta) * B */ ct = cos(theta) * radial_scale; st = sin(theta) * radial_scale; VJOIN2(pt, center_pt, ct, avec, st, bvec); (*rays)[6*ray_index] = pt[0]; (*rays)[6*ray_index+1] = pt[1]; (*rays)[6*ray_index+2] = pt[2]; (*rays)[6*ray_index+3] = dir[0]; (*rays)[6*ray_index+4] = dir[1]; (*rays)[6*ray_index+5] = dir[2]; theta += delta; ray_index++; } } *(ray_cnt) = ray_index; return ray_index; }
/* * M A I N */ int main(int argc, char **argv) { struct application ap; static struct rt_i *rtip; char *title_file; char idbuf[RT_BUFSIZE] = {0}; /* First ID record info */ char *ptr; int attr_count=0, i; char **attrs = (char **)NULL; if ( argc < 3 ) { bu_exit(1, usage); } RT_APPLICATION_INIT(&ap); argc--; argv++; while ( argv[0][0] == '-' ) switch ( argv[0][1] ) { case 'R': bundle_radius = atof( argv[1] ); argc -= 2; argv += 2; break; case 'n': num_rings = atoi( argv[1] ); argc -= 2; argv += 2; break; case 'c': rays_per_ring = atoi( argv[1] ); argc -= 2; argv += 2; break; case 'v': /* count the number of attribute names provided */ ptr = argv[1]; while ( *ptr ) { while ( *ptr && isspace( *ptr ) ) ptr++; if ( *ptr ) attr_count++; while ( *ptr && !isspace( *ptr ) ) ptr++; } if ( attr_count == 0 ) { bu_log( "missing list of attribute names!\n" ); bu_exit( 1, usage ); } /* allocate enough for a null terminated list */ attrs = (char **)bu_calloc( attr_count + 1, sizeof( char *), "attrs" ); /* use strtok to actually grab the names */ i = 0; ptr = strtok( argv[1], "\t " ); while ( ptr && i < attr_count ) { attrs[i] = bu_strdup( ptr ); ptr = strtok( (char *)NULL, "\t " ); i++; } argc -= 2; argv += 2; break; case 't': rt_bot_tri_per_piece = atoi( argv[1] ); argc -= 2; argv += 2; break; case 'b': rt_bot_minpieces = atoi( argv[1] ); argc -= 2; argv += 2; break; case 'o': sscanf( argv[1], "%d", &set_onehit ); argc -= 2; argv += 2; break; case 'r': { float ray_len; sscanf( argv[1], "%f", &ray_len ); set_ray_length = ray_len; } argc -= 2; argv += 2; break; case 'U': sscanf( argv[1], "%d", &use_air ); argc -= 2; argv += 2; break; case 'u': sscanf( argv[1], "%x", (unsigned int *)&bu_debug ); fprintf(stderr, "librt bu_debug=x%x\n", bu_debug); argc -= 2; argv += 2; break; case 'x': sscanf( argv[1], "%x", (unsigned int *)&rt_g.debug ); fprintf(stderr, "librt rt_g.debug=x%x\n", rt_g.debug); argc -= 2; argv += 2; break; case 'X': sscanf( argv[1], "%x", (unsigned int *)&rdebug ); fprintf(stderr, "rdebug=x%x\n", rdebug); argc -= 2; argv += 2; break; case 'N': sscanf( argv[1], "%x", (unsigned int *)&rt_g.NMG_debug); fprintf(stderr, "librt rt_g.NMG_debug=x%x\n", rt_g.NMG_debug); argc -= 2; argv += 2; break; case 'd': if ( argc < 4 ) goto err; ap.a_ray.r_dir[X] = atof( argv[1] ); ap.a_ray.r_dir[Y] = atof( argv[2] ); ap.a_ray.r_dir[Z] = atof( argv[3] ); set_dir = 1; argc -= 4; argv += 4; continue; case 'p': if ( argc < 4 ) goto err; ap.a_ray.r_pt[X] = atof( argv[1] ); ap.a_ray.r_pt[Y] = atof( argv[2] ); ap.a_ray.r_pt[Z] = atof( argv[3] ); set_pt = 1; argc -= 4; argv += 4; continue; case 'a': if ( argc < 4 ) goto err; at_vect[X] = atof( argv[1] ); at_vect[Y] = atof( argv[2] ); at_vect[Z] = atof( argv[3] ); set_at = 1; argc -= 4; argv += 4; continue; case 'O': { if ( !strcmp( argv[1], "resolve" ) || !strcmp( argv[1], "0") ) overlap_claimant_handling = 0; else if ( !strcmp( argv[1], "rebuild_fastgen" ) || !strcmp( argv[1], "1") ) overlap_claimant_handling = 1; else if ( !strcmp( argv[1], "rebuild_all" ) || !strcmp( argv[1], "2") ) overlap_claimant_handling = 2; else if ( !strcmp( argv[1], "retain" ) || !strcmp( argv[1], "3") ) overlap_claimant_handling = 3; else { bu_log( "Illegal argument (%s) to '-O' option. Must be:\n", argv[1] ); bu_log( "\t'resolve' or '0'\n"); bu_log( "\t'rebuild_fastgen' or '1'\n"); bu_log( "\t'rebuild_all' or '2'\n"); bu_log( "\t'retain' or '3'\n"); bu_exit(1, NULL); } argc -= 2; argv += 2; } continue; default: err: bu_exit(1, usage); } if ( argc < 2 ) { (void)fputs(usage, stderr); bu_exit(1, "rtshot: MGED database not specified\n"); } if ( set_dir + set_pt + set_at != 2 ) goto err; if ( num_rings != 0 || rays_per_ring != 0 || bundle_radius != 0.0 ) { if ( num_rings <= 0 || rays_per_ring <= 0 || bundle_radius <= 0.0 ) { fprintf( stderr, "Must have all of \"-R\", \"-n\", and \"-c\" set\n" ); goto err; } } /* Load database */ title_file = argv[0]; argv++; argc--; if ( (rtip=rt_dirbuild(title_file, idbuf, sizeof(idbuf))) == RTI_NULL ) { bu_exit(2, "rtshot: rt_dirbuild failure\n"); } if ( overlap_claimant_handling ) rtip->rti_save_overlaps = 1; ap.a_rt_i = rtip; fprintf(stderr, "db title: %s\n", idbuf); rtip->useair = use_air; /* Walk trees */ if ( rt_gettrees_and_attrs( rtip, (const char **)attrs, argc, (const char **)argv, 1 ) ) { bu_exit(1, "rt_gettrees FAILED\n"); } ap.attrs = attrs; rt_prep(rtip); if ( R_DEBUG&RDEBUG_RAYPLOT ) { if ( (plotfp = fopen("rtshot.plot", "w")) == NULL ) { perror("rtshot.plot"); bu_exit(1, NULL); } pdv_3space( plotfp, rtip->rti_pmin, rtip->rti_pmax ); } /* Compute r_dir and r_pt from the inputs */ if ( set_at ) { if ( set_dir ) { vect_t diag; fastf_t viewsize; VSUB2( diag, rtip->mdl_max, rtip->mdl_min ); viewsize = MAGNITUDE( diag ); VJOIN1( ap.a_ray.r_pt, at_vect, -viewsize/2.0, ap.a_ray.r_dir ); } else { /* set_pt */ VSUB2( ap.a_ray.r_dir, at_vect, ap.a_ray.r_pt ); } } VUNITIZE( ap.a_ray.r_dir ); if ( rays_per_ring ) { bu_log( "Central Ray:\n" ); } VPRINT( "Pnt", ap.a_ray.r_pt ); VPRINT( "Dir", ap.a_ray.r_dir ); if ( set_onehit ) ap.a_onehit = set_onehit; else ap.a_onehit = 0; if ( set_ray_length > 0.0 ) ap.a_ray_length = set_ray_length; else ap.a_ray_length = 0.0; /* Shoot Ray */ ap.a_purpose = "main ray"; ap.a_hit = hit; ap.a_miss = miss; if ( rays_per_ring ) { vect_t avec, bvec; struct xray *rp; /* create orthogonal rays for basis of bundle */ bn_vec_ortho( avec, ap.a_ray.r_dir ); VCROSS( bvec, ap.a_ray.r_dir, avec ); VUNITIZE( bvec ); rp = (struct xray *)bu_calloc( sizeof( struct xray ), (rays_per_ring * num_rings) + 1, "ray bundle" ); rp[0] = ap.a_ray; /* struct copy */ rp[0].magic = RT_RAY_MAGIC; rt_raybundle_maker( rp, bundle_radius, avec, bvec, rays_per_ring, num_rings ); (void)rt_shootray_bundle( &ap, rp, (rays_per_ring * num_rings) + 1 ); } else { (void)rt_shootray( &ap ); } return(0); }
/** * Return the curvature of the hyp. */ void rt_hyp_curve(struct curvature *cvp, struct hit *hitp, struct soltab *stp) { struct hyp_specific *hyp = (struct hyp_specific *)stp->st_specific; vect_t vert, horiz; point_t hp; fastf_t c, h, k1, k2, denom; fastf_t x, y, ratio; switch (hitp->hit_surfno) { case HYP_NORM_BODY: /* calculate principle curvature directions */ VMOVE(hp, hitp->hit_vpriv); VMOVE(vert, hitp->hit_normal); vert[Z] += 10; VCROSS(horiz, vert, hitp->hit_normal); VUNITIZE(horiz); VCROSS(vert, hitp->hit_normal, horiz); VUNITIZE(vert); /* vertical curvature */ c = hyp->hyp_c; h = sqrt(hp[X]*hp[X] + hp[Y]*hp[Y]); denom = 1 + (c*c*c*c)*(hp[Z]*hp[Z])/(h*h); denom = sqrt(denom*denom*denom); /* k1 is in the vert direction on the hyberbola */ k1 = fabs(c*c/h - (c*c*c*c)*(hp[Z]*hp[Z])/(h*h*h)) / denom; /* horizontal curvature */ if (fabs(hp[Y]) >= fabs(hp[X])) { ratio = hyp->hyp_rx / hyp->hyp_ry; /* (b/a)^2 */ x = hp[X]; y = hp[Y]; } else { /* flip x and y to avoid div by zero */ ratio = hyp->hyp_ry / hyp->hyp_rx; x = hp[Y]; y = hp[X]; } denom = fabs(y*y*y + (ratio*ratio)*(x*x)*y); denom = sqrt(denom*denom*denom); /* k2 is in the horiz direction on the ellipse */ k2 = -fabs(ratio*y + (ratio*ratio)*(x*x)/y) / denom; if (k1 < fabs(k2)) { VMOVE(cvp->crv_pdir, vert); cvp->crv_c1 = k1; cvp->crv_c2 = k2; } else { VMOVE(cvp->crv_pdir, horiz); cvp->crv_c1 = k2; cvp->crv_c2 = k1; } break; case HYP_NORM_TOP: case HYP_NORM_BOTTOM: cvp->crv_c1 = cvp->crv_c2 = 0; bn_vec_ortho(cvp->crv_pdir, hitp->hit_normal); break; } }