给定一个在3D空间中具有8个顶点的立方体.我如何确定myPoint
立方体内部或外部?
cube[0] = (x0, y0, z0);
cube[1] = (x1, y1, z1);
cube[2] = (x2, y2, z2);
cube[3] = (x3, y3, z3);
cube[4] = (x4, y4, z4);
cube[5] = (x5, y5, z5);
cube[6] = (x6, y6, z6);
cube[7] = (x7, y7, z7);
myPoint = (x, y, z);
Run Code Online (Sandbox Code Playgroud)
我试图在3D中实现这种数据过滤技术
可能最简单的方法是计算绑定立方体的6个平面中的每个平面的平面方程,将点插入每个平面并确保结果标记为正(或者为负,取决于您是否计算平面到面向内或向外).平面方程是p*normal + k = 0,通过取两个边之间的叉积来计算法线,然后将其中一个点插入平面方程中得到k.
更高级的方法是想象定义X,Y和Z轴的立方体和偏移(由立方体[0]定义)并将它们插入矩阵以转换两个空间之间的点.通过此矩阵的逆转换您的点将其置于"立方体空间"中,其中立方体与X/Y/Z轴对齐,因此您可以仅对边进行幅度比较.
如果你想从链接的帖子实现想法,考虑轴对齐的立方体(实际上是平行六面体)是有意义的.在那种情况下,支票是xmin<=x<=xmax && ymin<=y<=ymax && zmin<=z<=zmax
.
特例1(轴对齐立方体):
如maxim1000的答案所示,您可以简单地检查所考虑点的X,Y,Z坐标是否位于多维数据集的X,Y,Z坐标的最小值和最大值中。
X_min <= X <= X_max and Y_min <= Y <= Y_max and Z_min <= Z <= Z_max
Run Code Online (Sandbox Code Playgroud)
如果满足上述条件,则该点位于立方体内部,否则不存在。
一般案例(定向多维数据集):
有两种解决方法。首先,将点引入立方体的局部坐标系并应用上述特殊情况。第二种情况是关于向量投影的概念。第一种情况比第二种情况稍微复杂一点,因为您需要计算旋转矩阵,该矩阵将点从世界坐标系转换为多维数据集的局部坐标系。考虑下图所示的多维数据集。
对于这两种方法,我们都需要从多维数据集表示中获取一些基本信息。让我们将原点固定在立方体左下角的立方体的局部坐标系中;在这种情况下,它是点D。现在,在三个维度上计算单位方向矢量,并计算这些方向上的立方体范围。可以如下进行。
X 局部,Y 局部和Z 局部在图中以蓝色,红色,绿色示出。X 长度,Y 长度和Z 长度是沿轴的范围。
现在让我们重新解决问题。
方法1:在多维数据集的局部坐标系中考虑点。为此,我们需要估算旋转矩阵。在这种情况下,旋转矩阵是3 x 3的矩阵,其中X 局部,Y 局部和Z 局部作为列。
使用旋转矩阵R,可以将点带入局部坐标系,然后应用轴对齐立方体的特殊情况。
方法2:
构造从立方体中心到所考虑点的方向向量,并将其投影到每个局部轴上,并检查投影是否沿该轴跨越了立方体的范围。如果投影位于沿每个轴的范围内,则点在内部,否则在立方体的外部。
如图所示,立方体的中心是I。从立方体中心到点P的方向向量是V。向量V在X local,Y local和Z local上的投影可以如下计算。
现在,只有满足以下所有条件,点P才在立方体内部。
这是方法2中python的快速实现。
import numpy as np
def inside_test(points , cube3d):
"""
cube3d = numpy array of the shape (8,3) with coordinates in the clockwise order. first the bottom plane is considered then the top one.
points = array of points with shape (N, 3).
Returns the indices of the points array which are outside the cube3d
"""
b1,b2,b3,b4,t1,t2,t3,t4 = cube3d
dir1 = (t1-b1)
size1 = np.linalg.norm(dir1)
dir1 = dir1 / size1
dir2 = (b2-b1)
size2 = np.linalg.norm(dir2)
dir2 = dir2 / size2
dir3 = (b4-b1)
size3 = np.linalg.norm(dir3)
dir3 = dir3 / size3
cube3d_center = (b1 + t3)/2.0
dir_vec = points - cube3d_center
res1 = np.where( (np.absolute(np.dot(dir_vec, dir1)) * 2) > size1 )[0]
res2 = np.where( (np.absolute(np.dot(dir_vec, dir2)) * 2) > size2 )[0]
res3 = np.where( (np.absolute(np.dot(dir_vec, dir3)) * 2) > size3 )[0]
return list( set().union(res1, res2, res3) )
Run Code Online (Sandbox Code Playgroud)