三维三角形交叉口在3d空间

Sak*_*nan 8 algorithm 3d geometry intersection

我正在使用一些3d几何体.我需要找到三角形与另一个三角形的交点.

我可以使用什么算法?

小智 10

许多人显然依赖于 2006 年在以下论文(PDF 链接)中描述的方法的实现(链接到源代码):

Tropp、Oren、Ayellet Tal 和 Ilan Shimshoni。“用于碰撞检测的快速三角形到三角形相交测试。” 计算机动画和虚拟世界 17.5 (2006):527-535。

然而,该代码存在一个问题(除了采用旧的编程风格,使用非常规符号并失去基本的几何解释):如果以错误的方式完成,“行列式”不一定会使您的数学更健壮。

我建议要么使用 Moeller 的方法(指向 PDF 的链接),要么查看在CGAL 库中实现的Delliver 的论文(指向 PDF 的链接)链接,“Triangle_3_Triangle_3_do_intersect.h”)。

一个例子:上面实现的交集程序告诉由以下点定义的三角形 (p0,p1,p2) 和 (q0,q1,q2)

p0 = (-21, -72, 63)
p1 = (-78, 99, 40)
p2 = (-19, -78, -83)
q0 = (96, 77, -51)
q1 = (-95, -1, -16)
q2 = (9, 5, -21)
Run Code Online (Sandbox Code Playgroud)

相交的。这是三角形的图片:

相交三角形

这是代码片段(附加到原始代码):

#include <iostream>

inline void setPoint(double p[3], const double x, const double y, const double z)
{
    p[0] = x; p[1] = y; p[2] = z;
}

inline void computeEdges(double v0[3], double v1[3], const double p0[3], const double p1[3], const double p2[3])
{
    v0[0] = p1[0]-p0[0];
    v0[1] = p1[1]-p0[1];
    v0[2] = p1[2]-p0[2];
    v1[0] = p2[0]-p0[0];
    v1[1] = p2[1]-p0[1];
    v1[2] = p2[2]-p0[2];
}

void main()
{
    unsigned int numErrors(0), count(0);
    double p0[3], p1[3], p2[3], q0[3], q1[3], q2[3];
    double v0[3], v1[3], w0[3], w1[3];
    bool res, answer;
    int ret;

    std::cout << "Testing the correctness of tr_tri_intersect3D" << std::endl;

    {
        // Non excluding triangles in generic positions, big determinants, intersecting
        ++count;
        setPoint(p0, -21, -72, 63);
        setPoint(p1, -78, 99, 40);
        setPoint(p2, -19, -78, -83);
        setPoint(q0, 96, 77, -51);
        setPoint(q1, -95, -1, -16);
        setPoint(q2, 9, 5, -21);
        answer = true;

        computeEdges(v0, v1, p0, p1, p2);
        computeEdges(w0, w1, q0, q1, q2);
        int ret = tr_tri_intersect3D(p0, v0, v1, q0, w0, w1);
        bool res = ( ret != 0 );

        if( res != answer )
        {
            std::cout << "# wrong answer on test " << count << "!\n";
            ++numErrors;
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

关于算术运算数量的最后说明:由于该方法需要输入预先计算的边缘向量,因此应将 12 个 +/- 运算添加到论文的表 I. 中。

最后但并非最不重要的一点:请自行验证我在写什么,如果您认为我误解了什么,请给我反馈!

  • 刚刚找到这个代码,可能对寻找一个快速的、已经实施的 Delliver 方法解决方案的人有用:https://raw.githubusercontent.com/erich666/jgt-code/master/Volume_08/Number_1/Guigue2003/tri_tri_intersect.c (4认同)

Mic*_*elM 5

本文描述了一种实现:

http://knight.temple.edu/~lakaemper/courses/cis350_2004/etc/moeller_triangle.pdf

请注意,根据您是想知道发生相交的点/线段,还是只想知道是否发生了相交,有不同的技术。本文将为您提供表示相交的线段。


com*_*orm 5

Devillers 等人有一篇很好的论文,标题是“更快的三角-三角相交测试”——(是的,进行了谷歌搜索,但搜索关键字很重要......)

无论如何,他们的观点(与 MichaelM 的答案中的 Moeller 论文相比)是,你确实应该通过对选定的 4 个点组进行行列式来获取组合信息(论文描述了如何进行)。这避免了计算可能出现不一致问题的中间值,并且实际上可能不会更快......

您可以将这些行列式视为确定由 4 个点形成的四面体是右手四面体、左手四面体还是简并四面体(即平面四面体)。该值还确定 4 个点中的任何一个是否位于其他三个点形成的平面的一侧或另一侧,以及 4 个点中的任意两个形成的(有向)线是否位于该平面的一侧或另一侧。由另外两条形成的线。

长话短说,做行列式会让你的数学更加稳健,如果你注意的话,你通常可以将最初不做行列式的算法转换成做行列式的算法。或者,您可以阅读报纸。