检查 3D 点是否在基于正方形的金字塔中

Check if a 3D point is in a square based pyramid or not

如果我有一个基于正方形的金字塔,我知道其中的每个点(全部 5 个),确定给定点是否在该金字塔内的算法是什么?我在这里看到了类似的问题 Algorithm for checking if 3D point inside convex polyhedron (square pyramid) and here How to check whether the point is in the tetrahedron or not?。那里给出的答案并没有真正帮助,数学也不适合我。我见过为每个平面(4 个三角形 + 1 个正方形)创建法线并检查该点位于平面的哪一侧的方法......但是我不知道正确的数学方法。

如果有人可以帮助我 math/algorithm(最好有解释),那真的很有帮助。

visualization

示例输入:

# Pyarmid Points
A = np.array([2, 2, 4]) # pyramid top
B = np.array([1, 1, 1]) 
C = np.array([1, 3, 3])
D = np.array([3, 3, 1])
E = np.array([3, 1, 1])

# Example points
point_inside = np.array([2, 2, 2])
point_outside = np.array([3, 3, 3])

示例期望:

def check_point_in_pyramid(A, B, C, D, E, Point):

    # math...
    
    if point_inside_pyramid:

        return true


    return false

所以对于 point_inside 函数 return 为真,对于 point_outside 为假。

是的,你可以使用法线解决这个问题。

为了获得正常,计算每个平面的两条边的叉积。小心法线方向 - 严格按顺序使用顶点以获得所有外部法线或所有内部法线。

然后检查所有平面法向量对的点积符号(平面中的顶点 - 要检查的点)。

在内部点的情况下,所有点积将具有相同的符号(或者当点属于平面时为零)。

外部点示例 - 注意不同的符号:

nabc = np.cross(B - A, C - A)
nacd = np.cross(C - A, D - A)
nade = np.cross(D - A, E - A)
naeb = np.cross(E - A, B - A)
nbcd = np.cross(D - B, C - B)

r = np.dot(point_outside - A, nabc)
print(r)
r = np.dot(point_outside - A, nacd)
print(r)
r = np.dot(point_outside - A, nade)
print(r)
r = np.dot(point_outside - A, naeb)
print(r)
r = np.dot(point_outside - B, nbcd)
print(r)

8
-4
-4
8
8

我这里是右为正左为负:

根据您的金字塔,它由 5 个面定义,因此也可以由 5 个平面定义。平面只是一个平面(没有体积;只有面积)表面。 ,由方程 ax + by + cz + d = 0 定义。但是,要回答您的问题,我们只需要平面的法线,它由上面等式的三个系数给出 N = (a, b, c).

假设我们使用了您图像中的平面 ACD。我们还可以通过这样的叉积找到平面的法线:(D - A) x (C - A),这给了我们法线,N.

现在我们还需要一个方向向量,即从我们正在测试的3D点指向平面上的任何一点。为了简化,我们可以只使用其中一个点:ACD(让我们使用 A),因为它们仍然被认为是平面的一部分。

像这样:directionVector = point_outside - A

现在我们有这样的方法:

现在,如果我们对方向向量和法线进行点积 (float value = directionVector . N),我们只会得到一个数值。

然而数值的符号告诉我们该点是在内部还是外部(3D 点在平面的哪一侧)。

所以如果 value > 0,点在金字塔内部(在平面的右侧)并且如果 value < 0,该点在金字塔外部(在平面的左侧)。

现在,如果对金字塔的所有其他 4 个平面重复此过程。如果全部 return一个值,那么该点确实金字塔内部.但是,如果其中 一个 return 是 值,则该点位于金字塔外 .

注意 1:确保平面的法线朝向金字塔外面而不是里面。

注意2:如果你把正负两边颠倒了(如果现在左为正右为负),一定要把不等式也颠倒过来