从笛卡尔坐标转换为球坐标和浮点不精确度

时间:2020-02-15 15:27:14

标签: precision trigonometry numeric atan2 atan

我需要将笛卡尔坐标转换为球坐标,但是我的实现遇到了浮点不精确的问题。到目前为止,这是我正在做的事情:

template<typename RealType>
Point3<RealType> cartesian_to_spherical(Point3<RealType> const& p)
{
    auto const &x = p.x, &y = p.y, &z = p.z;
//  (x, y, z) = (r sin θ cos ϕ, r sin θ sin ϕ, r cos θ)

    auto const r_squared = x * x + y * y + z * z;
    if (r_squared > 0)
    {
        auto const r = std::sqrt(r_squared);
        auto const theta = std::acos(z / r);

        if (0 < theta && theta < pi<RealType>)
        {
            RealType phi;
            if (x > 0)
            {
                phi = std::atan(y / x);
                if (y < 0)
                    phi += 2 * pi<RealType>;
            }
            else if (x < 0)
                phi = pi<RealType> + std::atan(y / x);
            else // x == 0
                phi = y > 0 ? phi = pi<RealType> / 2 : 3 * pi<RealType> / 2;

            return { r, theta, phi };
        }
        else
            throw std::domain_error("theta = 0 or theta = pi");
    }
    else
        throw std::domain_error("r = 0");
}

例如,如果用cartesian_to_sphericalRealType = float调用p = {.000157882227f, .000284417125f, 1 },则r_squared1.00000012并计算其平方根r1(显然是错误的)。结果,theta被计算为0,而正确的值将是0.000325299694...

我们可以改进代码以使这些计算更加准确吗?

((您可能想记下使用std::atan2描述的here的转换。但是,如果我没有丢失某些内容,则std::sin(theta)为0时会产生错误的结果(即theta为0或pi),并且在示例中,它还计算了theta0。)

0 个答案:

没有答案
相关问题