【问题标题】:Check if a 3D point lies inside a 3D platonic solid?检查 3D 点是否位于 3D 柏拉图立体内部?
【发布时间】:2016-03-26 14:14:49
【问题描述】:

是否有任何已知的方法可以快速有效地确定 3D 点是否位于已知大小的柏拉图体积内?

这似乎很容易用立方体(六面体)或圆形(椭圆体)来完成。我似乎无法弄清楚四面体、八面体、十二面体或二十面体。我猜有可能将形状分解成几个子实体,然后检查每个子实体,但如果可能的话,我想避免使用任何类型的迭代求解器。

【问题讨论】:

  • 点应位于用于构建形状的每个平面的右侧。

标签: c++ algorithm geometry computational-geometry


【解决方案1】:

一种简单的方法是将实体表示为半空间的交集。

3d 平面有隐式方程:

ax + by + cz + d = 0

其中(a, b, c) 是平面法线,d 是平面任意点的-(a*x + b*y + c*z) 值(计算的值不会取决于您选择的点)。

对于平面一侧的空间点,a*x+ b*y + c*z + d 的结果将为负数,而另一侧的结果将为正数。

柏拉图立体(任何凸立体)可以表示为所有面的非正侧上的空间点,即

a[i]*x + b[i]*y + c[i]*z + d[i] <= 0

因此,一个相当快的测试可能是:

struct Plane {
    double a, b, c, d;
};

struct Point {
    double x, y, z;
};

int side(const Point pt, const Plane& pl) {
    double v = pt.x*pl.a + pt.y*pl.b + pt.z*pl.c + pl.d;
    if (v < -EPS) return -1;
    if (v > EPS) return 1;
    return 0;
}

struct ConvexSolid {
    std::vector<Plane> planes;

    bool contains(const Point& pt) const {
        return std::all_of(planes.begin(), planes.end(),
                           [&](const Plane& pl){
                               return side(pt, pl) <= 0;
                           });
    }
};

此外,如果您知道自己的大部分观点都在实体范围内,那么添加快速接受测试可能是个好主意。考虑中心和与面的距离......如果您的点位于以中心为中心的球体内并且具有该半径,那么肯定也在实体内。

因此,如果您预计许多点都在该范围内,那么首先检查它可能是一项不错的投资,因为它只需要检查

 r2 = (x-xc)*(x-xc) + (y-yc)*(y-yc) + (z-zc)*(z-zc)

这应该比检查一架飞机的成本略高。

但是请注意,如果大多数点不在该范围内,那么进行此检查确实是一种悲观。

另一个加速方法是同时考虑边界球具有相同的中心...在这种情况下,您只能使用相同的r2 计算来进行“波段”检查,您将仅当r2 &gt; r2min(即,如果该点不在内球体内)和r2 &lt; r2max(即,如果该点不在外球体内)时才需要运行完整检查。

【讨论】:

    【解决方案2】:

    如果您正在寻找优化的算法,您可以尝试检查该点是否位于实体的边界球之外,并且仅在不在时才检查表面。

    【讨论】:

    • 并且,作为这个想法的延伸,还要检查它是否在内接球体内。
    • 如果这加上用于检查点是否在多面体内部的通用算法不是最实用的解决方案,我会感到相当惊讶。假设输入点分布均匀且多面体的体积与总空间相比较小,则该算法的运行时间几乎是恒定的。
    【解决方案3】:

    point in polygon 在查找 2D 点是否位于任何类型的多边形(2D 空间)内时是一个众所周知的问题。参见例如

    多面体(3D)中的点问题——对于任何类型的多面体来说——相当棘手。但是,在您的情况下,您正在严格考虑 多面体,因为所有柏拉图立体都是后一种类型。

    在这种情况下,我可以为您指出解决此问题的两种方法。

    1 :(任何凸 polytope 的一般方法)您可以将您的问题视为查找一个点是否在一组已知点的 convex hull 内,在您的情况下,您的点是你的柏拉图立体的顶点,它们准确地描述了它们自己的凸包(由于凸性,没有“内部”顶点)。已经讨论了如何实现这个问题的一般解决方案,例如这里:

    2 :如上所述,多边形中的 2D 点已得到充分研究,您甚至可以找到它的 C++ 代码in the SO link I provided above。由于您正在考虑 3D 中的凸多面体,因此我们知道穿过此类多面体的 2D 平面的交点将描述凸多边形。因此,对于您要研究的每个点,您都创建了包含该点并且与多面体(您的柏拉图立体)相交的平面:剩下的问题是解决“多边形内的二维点问题”,在这架飞机上。

    【讨论】:

      【解决方案4】:

      从该点画一条线到形状之外的某个地方,并计算它通过了多少个表面。如果是奇数,点在里面,否则在外面。

      QED

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多