/** * 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; }
void bn_ae_vec(fastf_t *azp, fastf_t *elp, const vect_t v) { register fastf_t az; if ((az = bn_atan2(v[Y], v[X]) * RAD2DEG) < 0) { *azp = 360 + az; } else if (az >= 360) { *azp = az - 360; } else { *azp = az; } *elp = bn_atan2(v[Z], hypot(v[X], v[Y])) * RAD2DEG; }
void bn_aet_vec( fastf_t *az, fastf_t *el, fastf_t *twist, fastf_t *vec_ae, fastf_t *vec_twist, fastf_t accuracy) { vect_t zero_twist, ninety_twist; vect_t z_dir; /* Get az and el as usual */ bn_ae_vec(az, el, vec_ae); /* stabilize fluctuation between 0 and 360 * change azimuth near 360 to 0 */ if (NEAR_EQUAL(*az, 360.0, accuracy)) { *az = 0.0; } /* if elevation is +/-90 set twist to zero and calculate azimuth */ if (NEAR_EQUAL(*el, 90.0, accuracy) || NEAR_ZERO(*el + 90.0, accuracy)) { *twist = 0.0; *az = bn_atan2(-vec_twist[X], vec_twist[Y]) * RAD2DEG; } else { /* Calculate twist from vec_twist */ VSET(z_dir, 0, 0, 1); VCROSS(zero_twist, z_dir, vec_ae); VUNITIZE(zero_twist); VCROSS(ninety_twist, vec_ae, zero_twist); VUNITIZE(ninety_twist); *twist = bn_atan2(VDOT(vec_twist, ninety_twist), VDOT(vec_twist, zero_twist)) * RAD2DEG; /* stabilize flutter between +/- 180 */ if (NEAR_EQUAL(*twist, -180.0, accuracy)) { *twist = 180.0; } } }
static int test_bn_atan2(int argc, char *argv[]) { double x, y, expected, actual; if (argc != 5) { bu_exit(1, "<args> format: X Y <expected_result> [%s]\n", argv[0]); } sscanf(argv[2], "%lg", &y); sscanf(argv[3], "%lg", &x); sscanf(argv[4], "%lg", &expected); actual = bn_atan2(y, x); return !NEAR_EQUAL(expected, actual, 0.00001); }