【问题标题】:Algorithm for checking if 3D point inside convex polyhedron (square pyramid)检查凸多面体(方形金字塔)内是否有 3D 点的算法
【发布时间】:2016-09-28 07:26:19
【问题描述】:

我正在寻找强大的碰撞检测算法,并找到了 Christer Ericson 的一本很棒的书,名为 Realtime Collision Detection。我正在尝试使用一种特定的算法来检查给定点是否在凸多面体内(在 3D 空间中,这些是方形金字塔、立方体和四面体(也就是所有边都是三角形的金字塔))。就我而言,我有一个方形金字塔。通过使用给定数量的半空间的相交体积并确定该点是在由多面体的边跨越的所有平面的前面还是后面来完成该点的验证。我很难理解参数n(见下文)的用法,它表示给定多面体的半空间数:

// Test if point p inside polyhedron given as the intersection volume of n halfspaces
int TestPointPolyhedron(Point p, Plane *h, int n) {
    for (int i = 0; i < n; i++) {
        if(DistPointPlane(p, h[i]) > 0.0f) return 0;
    }
    return 1;
}

DistPointPlane(...)计算给定点和平面之间的距离

float DistPointPlane(Point q, Plane p) {
    return Dot(q, p.n) - p.d;
}

Plane 是一个表示 3D 空间中的平面的结构

struct Plane {
    Vector n; // Plane normal. Point X on the plane satisfies Dot(n, X) = d
    float d;  // d = dot(n, p) for a given point on the plane
}

Plane ComputePlane(Point a, Point b, Point c) {
    Plane p;
    p.n = Normalize(Cross(b - a, c - a));
    p.d = Dot(p.n, a);
    return p;
}

算法的作用基本上如下:

  1. 对于给定的点,计算它到凸多面体每个平面的距离
  2. 检查距离是负数还是正数
    1. 如果距离为负,则点位于平面法线的另一侧,因此位于其后面。
    2. 其他点与平面法线位于同一侧,因此位于其前面
  3. 如果点在给定多面体的所有平面后面,则它位于内部,否则位于外部

现在就我所知的方形金字塔而言,有 10 个半空间,因为我们有 4 个边和一个底,每个边代表一个单独的平面(因此总共有 5 个平面),将 3D 空间分成两个半空间(5 planes * 2 = 10 halfspaces)。我没有得到的是上述算法代码中n 的用法。它用作循环遍历Plane 实例数组的终止条件。但是如前所述,有 10 个半空格。

经过一番挖掘,我想到的一件事是,两个平面之间的交点是一条线(金字塔的边缘)。进一步引用Wolfram Mathworld

要唯一指定行,还需要找到一个 具体点就可以了。这可以通过找到一个点来确定 同时在两个平面上

金字塔的每个顶点都满足这个要求,因为对于任何给定的两侧(包括底部),我们都会得到一条位于金字塔两个顶点之间的线。因此,就交集而言,我们确实有 5 个(基数为 4,顶点为 1)但是书中的文本(包括函数实现上方的注释)是模糊的,阅读它可能会得到错误的想法(至少那是我的情况)。

我的思路是否接近事实,还是我在数学知识方面遗漏了一些重要内容?

我已将代码移植到 Python 3 并更改了算法以仅循环遍历我的平面列表,而无需使用其他参数(如果我的想法正确,则与原始参数基本相同)并将其绘制为matplotlib。它工作得很好,但我仍然想知道我是否理解正确:

【问题讨论】:

  • 不要担心半空格,只要想想平面。对于每个具有向外指向法线的平面,您希望 DistPointPlane
  • 我认为它实际上是 C++,因为 b-a 和类似的类型是 Point (我实际上无法找到这个的实现:D),这显然是运算符重载。至于距离检查 - 是的,至少这部分算法是非常清楚的(我在我的帖子中也提到过)。它的工作没有任何问题的事实确实表明,至少我所做的更改可以提供正确的结果。由于这个 n 论点,我不确定这是数学解释。
  • 此外,数组Plane *h 内的平面数也是已知的,因为算法计算基于凸多面体的东西,我们清楚地知道这种多面体中的平面数:a方形金字塔有 5 个平面(如果我错了,请纠正我)。可能只是这个n 上的cmets 是胡言乱语。 :D
  • 是的,我看到了它对代码注释的解释。我认为作者正在考虑包含形状的 5 个半空间,而不是全部 10 个半空间。
  • 您可以将此作为答案发布。我现在也认为这就是他的意思,因为对于给定的半空间,如果点不在其中,那么它显然在另一个半空间中,所以基本上所有半空间都在这里发挥作用,即使隐含考虑了金字塔之外的半空间。谢谢!

标签: algorithm math 3d collision-detection polyhedra


【解决方案1】:

here's a similar question

基本上,您的形状是多面体,但通常简单地定义为具有许多面的形状 6。您实际上需要寻找名称四面体,这是您在上面的视觉表示中定义的经典金字塔形状。但基本答案是取 5 个平面(4 个三角形和一个正方形)的法线,并检查它们是否面向空间点的同一方向。如果它们都返回 false,那么您的点就在形状内部。如果其中任何一个返回 true,那么您就在形状之外。这种类型的测试适用于大多数凸形,因为没有平面与法线重叠的情况。

【讨论】:

    【解决方案2】:

    我会说你最了解它。我不确定您对“距离”的确切含义。通常点积提供两个向量之间的角度。在您的情况下,有一个位置向量(点)和一个法线向量。由于余弦定律,如果点积大于 0,则两个向量之间的夹角小于 90 度。另一方面,如果乘积为负,则角度大于 90 度。如果为 0,则向量是正交的。所以基本上它与距离无关,而与角度有关。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-22
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-02
      相关资源
      最近更新 更多