Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 查找三维曲面的洞口_Python_Math_Numpy_Geometry - Fatal编程技术网

Python 查找三维曲面的洞口

Python 查找三维曲面的洞口,python,math,numpy,geometry,Python,Math,Numpy,Geometry,我有一个数组sphere保持笛卡尔坐标XYZ。每行是对象曲面的一个点。我想找到该曲面的开口,旋转对象,使x轴指向该开口 我正在使用python和numpy,但是一般的方法和特定的实现一样好 这是我目前拥有的。x轴为红色,原点为绿色: 以下是我想要得到的: 这里有一个想法。取点的凸包。如果曲面的“开口”是平面的,则该开口将由凸面外壳中几乎共面的面覆盖。然后,所有面的法向量将具有不同的模式,这有助于识别边界。 通常,您希望对数据应用旋转矩阵。但是,您还需要找到旋转矩阵 在这种情况下,更容易直接

我有一个数组
sphere
保持笛卡尔坐标XYZ。每行是对象曲面的一个点。我想找到该曲面的开口,旋转对象,使x轴指向该开口

我正在使用python和numpy,但是一般的方法和特定的实现一样好

这是我目前拥有的。x轴为红色,原点为绿色:

以下是我想要得到的:


这里有一个想法。取点的凸包。如果曲面的“开口”是平面的,则该开口将由凸面外壳中几乎共面的面覆盖。然后,所有面的法向量将具有不同的模式,这有助于识别边界。



通常,您希望对数据应用旋转矩阵。但是,您还需要找到旋转矩阵

在这种情况下,更容易直接跳到处理协方差矩阵的特征向量。这基本上是一种主成分方法。如果我们确定数据的主要组成部分并将其旋转到该坐标系中,我们将有效地执行您想要的操作

首先,让我们生成一个类似于您的示例:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def main():
    x, y, z = generate_data()
    plot(x, y, z)
    plt.show()

def generate_data():
    lat, lon = np.radians(np.mgrid[-90:90:20j, 0:180:20j])
    lon -= np.radians(40)
    z = np.cos(lat) * np.cos(lon)
    x = np.cos(lat) * np.sin(lon)
    y = np.sin(lat)
    return x, y, z

def plot(x, y, z):
    fig, ax = plt.subplots(subplot_kw=dict(projection='3d'), facecolor='w')
    artist = ax.scatter(x, y, z, marker='o', color='y')
    ax.set(xlim=[-1.1, 1.1], ylim=[-1.1, 1.1], zlim=[-1.1, 1.1], aspect=1)
    ax.set(xlabel='X', ylabel='Y', zlabel='Z')
    return artist

main()

现在我们可以根据主坐标旋转物体:

def reorient(x, y, z):
    xyz = np.vstack([x.ravel(), y.ravel(), z.ravel()])
    cov = np.cov(xyz)

    # Find the eigenvectors of the covariance matrix
    vals, vecs = np.linalg.eigh(cov)
    idx = np.argsort(vals)
    # The eigenvalues vals are not needed below, but this puts them in
    # the same order as the eigenvectors, should they be needed in future
    # versions of this code:
    vals, vecs = vals[idx], vecs[:, idx]

    # In this case, we actually want the second eigenvector to be the x-axis
    vecs = vecs[:, [1, 0, 2]]

    # Now let's perform a change-of-basis into the new coordinate system
    return np.linalg.inv(vecs).dot(xyz)
并绘制结果:

def main():
    x, y, z = generate_data()
    plot(*reorient(x, y, z))
    plt.show()


注意:我隐式地假设您的数据已经集中在旋转发生的点上。如果情况并非如此,则需要在计算协方差矩阵之前减去旋转点(例如,平均值),然后在改变基础后再将其加回去。

这是所提出方法的高质量实现(主成分)。然而,如果球体被一个长方形(如半个足球)代替,它将无法完全按照预期工作,如果形状复杂,即使它有一个明显的(对人类而言)开口,它也无法工作,对吗?@EOL-不,一般来说不是。它不是在寻找机会。然而,一个长方形的形状应该仍然可以,尽管你需要改变你沿x轴放置的特征向量。对于完全通用的情况,曲面重建算法应该更好。然后你可以检查表面是否有凹陷和开口。不过,这相当复杂。