提高 LineLine 相交法(3D)的数值精度

Improve numerical accuracy of LineLine intersection method (3D)

我编写了以下 LineLine 相交方法:

double LineLineIntersection(
    const Eigen::Vector3d& origin1,
    const Eigen::Vector3d& ray1,
    const Eigen::Vector3d& origin2,
    const Eigen::Vector3d& ray2)
{
    if(abs((origin1 - origin2).norm() - 1.0) < 0.000001) return 0;
    auto n1 = (origin2 - origin1).cross(ray2);
    auto n2 = ray1.cross(ray2);

    // Use this to test whether the vectors point in the same or opposite directions
    auto n = n2.normalized();
    // If n2 is the 0 vector or if the cross products are not colinear, no solution exists
    if(n2.norm() < 0.00001 || abs(abs(n1.dot(n)) - n1.norm()) > 0.000001)
        return std::numeric_limits<double>::infinity();;

    return n1.dot(n) / n2.dot(n);
}

解释了其工作原理here。但是页面有错误,只取绝对值只有大小,抹去了方向。因此,必须取横向的点积。这样,距离可以是正数也可以是负数,具体取决于向量是否指向同一方向。

这在技术上可行,但我 运行 遇到了很大的数字错误。例如,在我的一项测试中,我得到:

The difference between i1.x() and Eigen::Vector3d(-0.581, 1.232, 0).x() is 0.0024061184231309873, which exceeds 0.001, where
i1.x() evaluates to -0.58340611842313095,
Eigen::Vector3d(-0.581, 1.232, 0).x() evaluates to -0.58099999999999996, and
0.001 evaluates to 0.001.

大于 0.001 的错误是巨大的。我该怎么做才能使该方法更准确?

这是 i1 的值:-0.583406 1.23237 0 很抱歉之前没有包含它。

您正在使用类型“double”,尝试将其更改为“long double”或“__float128”(如果它存在于您的 G++ 版本中)。此外,您可以在 Java 中使用“BigDecimal”以获得更高的准确性,或者使用 Python.

中的一些长算术