如何找到在平面上投影的点的坐标 [英] how to find the coordinate of points projection on a planar surface

查看:97
本文介绍了如何找到在平面上投影的点的坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

希望一切顺利.我有两个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆