【问题标题】:How to detect intersection of two faces in 3D如何在 3D 中检测两个人脸的交集
【发布时间】:2016-03-18 21:35:17
【问题描述】:

让我们说

struct myFace
{
    3DPoint p0;
    3DPoint p1;
    3DPoint p2;
    3DPoint p3;
    3DPoint pNormal;

};

face1 和 face2 分别是 myFace 的哪一种类型。

double ac = face1.pNormal * face2.pNormal;

如果 (!(ac0.99999999) && !(ac>-1.00000001 && ac

那么面不平行。

但是如何检测它们是否相交?

【问题讨论】:

  • 因为你有 4 个点,这变得相当复杂。这样做的一般方法是首先计算两个平面相交处的无限线,然后计算该线与两个面相交的点集,然后查看这些集是否重叠。稍后我会尝试提供更完整的答案。
  • 谢谢。我将等待您的完整答复。
  • 点是以逆时针/顺时针方式定义的吗?我会假设他们是(而且他们应该是)

标签: c++ 3d intersection plane face


【解决方案1】:

糟糕,忽略我的评论:想到了另一种方法。


  • 第 1 步:

对于面部F1F2,将F2 的点作为两个三角形,例如(p0, p1, p2)(p1, p2, p3) 分别。然后取F1 的边,即(p0, p1)(p1, p2)(p2, p3)(p3, p0),然后将它们中的每一个与两个三角形相交。

我找到了一些代码来做到这一点:(改编自http://geomalgorithms.com/a06-_intersect-2.html

#define SMALL_NUM   0.00000001

/* 
   returns: 0 if no intersection 
            1 if parallel but disjoint
            2 if coplanar
*/
int intersect3D_RayTriangle(Vector P0, Vector P1, Vector V0, Vector V1, Vector V2)
{
    Vector    u, v, n;              // triangle vectors
    Vector    dir, w0, w;           // ray vectors
    float     r, a, b;              // params to calc ray-plane intersect

    // get triangle edge vectors and plane normal
    u = V1 - V0;
    v = V2 - V0;
    n = cross(u, v);

    dir = P1 - P0;             // ray direction vector
    w0 = P0 - V0;
    a = -dot(n, w0);
    b = dot(n, dir);
    if (fabs(b) < SMALL_NUM)   // ray is parallel to triangle plane
        return (fabs(a) < SMALL_NUM ? 2 : 0);

    // get intersect point of ray with triangle plane
    r = a / b;
    if (r < 0.0 || r > 1.0)
        return 0;                   // => no intersect
    Vector I = R.P0 + r * dir;      // intersect point of ray and plane

    // is I inside T?
    float uu, uv, vv, wu, wv, D;
    uu = dot(u, u);
    uv = dot(u, v);
    vv = dot(v, v);
    w = I - V0;
    wu = dot(w, u);
    wv = dot(w, v);
    D = uv * uv - uu * vv;

    // get and test parametric coords
    float s, t;
    s = (uv * wv - vv * wu) / D;
    if (s < 0.0 || s > 1.0)         // I is outside T
        return 0;
    t = (uv * wu - uu * wv) / D;
    if (t < 0.0 || (s + t) > 1.0)  // I is outside T
        return 0;

    return 1;                       // I is in T
}

P0P1 形成 F1 的边之一,而 V0V1V2 形成 F2 的三角形之一。

  • 如果其中一项检查(应该有 8 个)返回 1,那么它们肯定相交(立即返回 true)。
  • 如果所有个都返回0,那么它们不相交。
  • 如果其中一个检查返回 2(第一个检查可能会这样做),那么我们需要一个不同的方法。停止这些检查并立即进入第 2 步。

  • 第 2 步:

这部分适用于多边形是否共面(即平行且在同一平面内)。这一次,取F1 的所有边和F2 的所有边;对于F1 的每一条边,检查它是否与F2 的任何一条边相交,如果一对相交,则立即返回true。

要做这样的边相交:(改编自https://gist.github.com/hanigamal/6556506

A0A1F1 形成边缘,而B0B1F2 形成边缘。

int intersection(Vector A0, Vector A1, Vector B0, Vector B1)
{
   Vector dA = A1 - A0;
   Vector dB = B1 - B0;
   Vector dC = B0 - A0;

   double s = dot(cross(dC, dB), cross(dA, dB)) / norm2(cross(dA, dB));
    return (s >= 0.0 && s <= 1.0);
}

【讨论】:

  • 谢谢。我还考虑了射线三角形算法,但我不知道射线三角形适用于有限射线。我会试试。再次感谢您。
  • @siyah 使用有限光线实际上并不比无限光线复杂 - 但您需要对其进行参数化并在相应参数上设置一个限制
猜你喜欢
  • 2015-12-18
  • 2013-10-23
  • 1970-01-01
  • 2016-11-18
  • 2016-02-06
  • 2012-04-17
  • 2019-11-18
  • 2013-09-02
  • 1970-01-01
相关资源
最近更新 更多