如何找到在平面上投影的点的坐标 [英] how to find the coordinate of points projection on a planar surface
问题描述
希望一切顺利.我有两个numpy数组,两者都是空间中的一些点.我想使用python首先找到通过第一个数据集( surface_maker
)的曲面,然后找到第二个数组( contact_maker 代码>)在创建的曲面上.
surface_maker
始终创建平面.对于投影,我只希望从相邻点到表面垂直.实际上,两组中都有很多点,但是我在这里复制了一个简单的案例:
surface_maker = np.array([[50.,15.,46.04750574],[50.,5.,45.56400925],[44.83018398,5.,25.],[44.76296902,15.,25.],[50.,25.,45.56400925],[44.83018398,25.,25.],[59.8336792,5.,75.],[59.71483707,15.,75.],[59.8336792,25.,75.]]contact_maker = np.array([[10.,5.,70.00014782],[10.,15.,70.00018358],[10.,25.,70.0001955],[30.,5.,69.99981105],[30.,15.,69.99982297],[30.,25.,69.99985874],[70.,5.,50.00000298],[70.,15.,50.00002682],[70.,25.,50.00005066],[90.,5.,49.99996871],[90.,15.,49.99999255],[90.,25.,50.00001788]])
我尝试了几种解决方案,例如
在此,我真的很感谢您的帮助.
我了解您需要解决两个问题:
- 找到适合点集合的平面
- 沿特定方向将第二个点集合投影到该平面上
第二个问题已经在另一个答案中得到了充分解决,因此我正在为第一个问题提供一种更通用的方法.
是的,当您肯定地知道所有点都位于一个平面上时,您可以选择三个未对齐的点并计算该平面.但是您的点可能来自带有一些噪声的真实测量,并且您可能希望找到最能抓住您的点的平面.
以下功能解决了找到最适合点集合的平面的一般问题.请参阅注释中的说明:
将numpy导入为npPRECISION = 1e-8#用于实际目的的任意零def plane_from_points(points):#调整后的平面越过点集合的质心重心= np.mean(点,轴= 0)#使用SVD计算点集合的主轴#(特征向量)及其相对大小(特征值)_,特征值,特征向量= np.linalg.svd(点-重心)#每个特征值都与其特征向量配对,并从中进行排序#最大到最小特征值.#调整后的平面必须包含对应于#两个最大的特征值.如果只有一个特征向量是不同的#从零开始,然后对齐点,并且它们不定义平面.如果特征值[1] <精确:引发ValueError(点对齐,无法定义平面")#因此,平面法线是特征值最小的特征向量正常=特征向量[2]#计算平面方程ax + by + cz + d = 0的系数(a,b,c,d).#前三个系数由法线给出,第四个系数#one(d)是飞机到坐标原点的标志距离d = -np.dot(质心,正常)平面= np.append(法线,d)#如果最小特征向量接近零,则#点非常平坦.特征向量越大,平坦度越小.#您可能想知道这一点.厚度=特征值[2]返回平面,厚度
您可以检查以下内容:
>>>surface_maker = np.array([[50.,15.,46.04750574],[50.,5.,45.56400925],[44.83018398,5.,25.],[44.76296902,15.,25.],[50.,25.,45.56400925],[44.83018398,25.,25.],[59.8336792,5.,75.],[59.71483707,15.,75.],[59.8336792,25.,75.]])>>>平面,厚度= plane_from_points(surface_maker)>>>打印(平面)[-0.95725318 0. 0.28925136 35.2806339]>>>印刷(厚度)1.3825669490602308
因此,实际上,您的点分布不是平坦的(厚度明显不同于零),并且不能仅仅选择三个任意点来解决问题.
Hope doing well. I have two numpy array, both are some points in the space. Using python, I want to firstly find the surface passing the first data set (surface_maker
) and then find the x,y and z of the projection adjacent opoints of the second array (contact_maker
) on the created surface. surface_maker
always created planar surfaces. For projection, I only want a vertical going from adjacent point toward the surface. In reality I have lots of points in both sets but I copies a simple case here:
surface_maker=np.array([[50., 15., 46.04750574],
[50., 5., 45.56400925],
[44.83018398, 5., 25.],
[44.76296902, 15., 25.],
[50., 25., 45.56400925],
[44.83018398, 25., 25.],
[59.8336792, 5., 75.],
[59.71483707, 15., 75.],
[59.8336792, 25., 75.]])
contact_maker=np.array([[10., 5., 70.00014782],
[10., 15., 70.00018358],
[10., 25., 70.0001955 ],
[30., 5., 69.99981105],
[30., 15., 69.99982297],
[30., 25., 69.99985874],
[70., 5., 50.00000298],
[70., 15., 50.00002682],
[70., 25., 50.00005066],
[90., 5., 49.99996871],
[90., 15., 49.99999255],
[90., 25., 50.00001788]])
I have tried several solutions like 1, 2 and so on. But I was successful to solve my issue.
For me it is important to have the location of projection as x, y and z. The figure also shows what I want (as it shows, I need only location six adjacent point of the contact_maker
projected on the surface created by surface_maker
):
In advance, I truely appreciate any help.
I understand you need to solve two problems:
- Find the plane that fits a collection of points
- Project a second collection of points onto that plane along a specific direction
The second problem has been fully addressed in another answer, so I'm contributing a more generic approach to the first problem.
It's true that when you positively know that all your points lie on a plane, you may just select three non-aligned ones and calculate the plane. But your points may come from real measurements with some noise, and you may wish to find the plane that best fists your points.
The following function solves the general problem of finding the plane that best fits a collection of points. See the explanations in the comments:
import numpy as np
PRECISION = 1e-8 # Arbitrary zero for real-world purposes
def plane_from_points(points):
# The adjusted plane crosses the centroid of the point collection
centroid = np.mean(points, axis=0)
# Use SVD to calculate the principal axes of the point collection
# (eigenvectors) and their relative size (eigenvalues)
_, eigenvalues, eigenvectors = np.linalg.svd(points - centroid)
# Each eigenvalue is paired with its eigenvector and they are sorted from
# largest to smallest eigenvalue.
# The adjusted plane plane must contain the eigenvectors corresponding to
# the two largest eigenvalues. If only one eigenvector is different
# from zero, then points are aligned and they don't define a plane.
if eigenvalues[1] < PRECISION:
raise ValueError("Points are aligned, can't define a plane")
# So the plane normal is the eigenvector with the smallest eigenvalue
normal = eigenvectors[2]
# Calculate the coefficients (a,b,c,d) of the plane's equation ax+by+cz+d=0.
# The first three coefficients are given by the normal, and the fourth
# one (d) is the plane's signed distance to the origin of coordinates
d = -np.dot(centroid, normal)
plane = np.append(normal, d)
# If the smallest eigenvector is close to zero, the collection of
# points is perfectly flat. The larger the eigenvector, the less flat.
# You may wish to know this.
thickness = eigenvalues[2]
return plane, thickness
You can check this:
>>> surface_maker=np.array([[50., 15., 46.04750574], [50., 5., 45.56400925], [44.83018398, 5., 25.], [44.76296902, 15., 25.], [50., 25., 45.56400925], [44.83018398, 25., 25.], [59.8336792, 5., 75.], [59.71483707, 15., 75.], [59.8336792, 25., 75.]])
>>> plane, thickness = plane_from_points(surface_maker)
>>> print(plane)
[-0.95725318 0. 0.28925136 35.2806339 ]
>>> print(thickness)
1.3825669490602308
So, in fact, your point distribution is not flat (thickness clearly different from zero), and you can't just select three arbitrary points to solve your problem.
这篇关于如何找到在平面上投影的点的坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!