/**
 * 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;
	}
    }
}
Beispiel #4
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);
}