如何绘制python中由向量给出的结构的表面?

如何绘制python中由向量给出的结构的表面?,python,matplotlib,Python,Matplotlib,我想画出数据的表面,它由笛卡尔坐标x,y,z中的三维向量给出。数据不能用平滑函数表示 首先,我们使用函数eq_points(N_count,r)生成一些虚拟数据,该函数返回一个数组points,其中包含对象表面上每个点的x,y,z坐标。ω的数量是立体角,现在不感兴趣 #credit to Markus Deserno from MPI #https://www.cmu.edu/biolphys/deserno/pdf/sphere_equi.pdf def eq_points(N_count,

我想画出数据的表面,它由笛卡尔坐标x,y,z中的三维向量给出。数据不能用平滑函数表示

首先,我们使用函数
eq_points(N_count,r)
生成一些虚拟数据,该函数返回一个数组
points
,其中包含对象表面上每个点的x,y,z坐标。ω的数量是立体角,现在不感兴趣

#credit to Markus Deserno from MPI
#https://www.cmu.edu/biolphys/deserno/pdf/sphere_equi.pdf
def eq_points(N_count, r):
    points = []
    a = 4*np.pi*r**2/N_count
    d = np.sqrt(a)
    M_theta = int(np.pi/d)
    d_theta = np.pi/M_theta
    d_phi = a/d_theta
    for m in range(M_theta):
        theta = np.pi*(m+0.5)/M_theta
        M_phi = int(2*np.pi*np.sin(theta)/d_phi)
        for n in range(M_phi):
            phi = 2*np.pi*n/M_phi

            points.append(np.array([r*np.sin(theta)*np.cos(phi),
                                    r*np.sin(theta)*np.sin(phi),
                                    r*np.cos(theta)]))

    omega = 4*np.pi/N_count

    return np.array(points), omega

#starting plotting sequence

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

points, omega = eq_points(400, 1.)

ax.scatter(points[:,0], points[:,1], points[:,2])
ax.scatter(0., 0., 0., c="r")
ax.set_xlabel(r'$x$ axis')
ax.set_ylabel(r'$y$ axis')
ax.set_zlabel(r'$Z$ axis')

plt.savefig("./sphere.png", format="png", dpi=300)
plt.clf()
结果是下图所示的球体。蓝色点标记
数组中的数据,而红色点是原点。

我想要这样的东西 摘自。但是,mplot3d教程中的数据始终是平滑函数的结果。除了我用于球体绘图的
ax.scatter()
函数之外

所以最终我的目标是绘制一些只显示其表面的数据。该数据是通过更改到每个蓝点原点的径向距离生成的。此外,还需要确保每个点都与表面接触。在
plot\u surface()
中绘制的曲面是如何详细构造的?一些实际的实时数据如下所示:

我建议找到船体,然后绘制简单图(即构成船体的三角形)。确保适当更新x、y、z限制

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from scipy.spatial import ConvexHull

N = 1000
pts = np.random.randn(N, 3)

# exclude outliers
# obviously, this is data dependent
cutoff = 3.
is_outlier = np.any(np.abs(pts) > cutoff, axis=1)
pts = pts[~is_outlier]

# plot points
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(pts[:,0], pts[:,1], pts[:,2])

ax.set_xlim(-(cutoff +1), cutoff+1)
ax.set_ylim(-(cutoff +1), cutoff+1)
ax.set_zlim(-(cutoff +1), cutoff+1)


使用所有点都接触表面的新规范解决问题。假设如示例中所示由用户设置角度,则通过计算单位球体上具有与相关数据集中相同角度的点形成的外壳的单体,很容易预计算形成构成曲面的单体的点的索引。然后我们可以使用这些指数来获得感兴趣的表面

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from scipy.spatial import ConvexHull

def eq_points(N_count, r):
    points = []
    a = 4*np.pi*r**2/N_count
    d = np.sqrt(a)
    M_theta = int(np.pi/d)
    d_theta = np.pi/M_theta
    d_phi = a/d_theta
    for m in range(M_theta):
        theta = np.pi*(m+0.5)/M_theta
        M_phi = int(2*np.pi*np.sin(theta)/d_phi)
        for n in range(M_phi):
            phi = 2*np.pi*n/M_phi

            points.append(np.array([r*np.sin(theta)*np.cos(phi),
                                    r*np.sin(theta)*np.sin(phi),
                                    r*np.cos(theta)]))

    omega = 4*np.pi/N_count

    return np.array(points), omega

def eq_points_with_random_radius(N_count, r):
    points = []
    a = 4*np.pi*r**2/N_count
    d = np.sqrt(a)
    M_theta = int(np.pi/d)
    d_theta = np.pi/M_theta
    d_phi = a/d_theta
    for m in range(M_theta):
        theta = np.pi*(m+0.5)/M_theta
        M_phi = int(2*np.pi*np.sin(theta)/d_phi)
        for n in range(M_phi):
            phi = 2*np.pi*n/M_phi
            rr = r * np.random.rand()
            points.append(np.array([rr*np.sin(theta)*np.cos(phi),
                                    rr*np.sin(theta)*np.sin(phi),
                                    rr*np.cos(theta)]))

    omega = 4*np.pi/N_count

    return np.array(points), omega


N = 400
pts, _ = eq_points(N, 1.)
pts_rescaled, _ = eq_points_with_random_radius(N, 1.)
extremum = 2.

# plot points
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(pts_rescaled[:,0], pts_rescaled[:,1], pts_rescaled[:,2])
ax.set_xlim(-extremum, extremum)
ax.set_ylim(-extremum, extremum)
ax.set_zlim(-extremum, extremum)


指向MatLab教程的链接是漫反射的。能否在教程中指定一个部分?你是说,例如?不,我用
plot\u trisurf()
标注零件。谢谢你的澄清。我建议将“此处”的链接改为。我想添加图片和结果,但我无法添加,因为迄今为止声誉不足,在你知道之前声誉就已经累积,你可以返回到以前的问题,并通过(例如)图像和细节来改进它们。耐心点,同事!谢谢你的回答。如何确保数据的每个点都与曲面接触?凸壳曲面无法解决这一问题。原始问题没有规定每个点都应与曲面接触。如果你认为在别人给出答案后,你需要实质性地改变问题,那么你应该提出一个新的问题。另外,如果你不想要船体,我同意欧内斯特的观点,即问题没有明确说明。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from scipy.spatial import ConvexHull

def eq_points(N_count, r):
    points = []
    a = 4*np.pi*r**2/N_count
    d = np.sqrt(a)
    M_theta = int(np.pi/d)
    d_theta = np.pi/M_theta
    d_phi = a/d_theta
    for m in range(M_theta):
        theta = np.pi*(m+0.5)/M_theta
        M_phi = int(2*np.pi*np.sin(theta)/d_phi)
        for n in range(M_phi):
            phi = 2*np.pi*n/M_phi

            points.append(np.array([r*np.sin(theta)*np.cos(phi),
                                    r*np.sin(theta)*np.sin(phi),
                                    r*np.cos(theta)]))

    omega = 4*np.pi/N_count

    return np.array(points), omega

def eq_points_with_random_radius(N_count, r):
    points = []
    a = 4*np.pi*r**2/N_count
    d = np.sqrt(a)
    M_theta = int(np.pi/d)
    d_theta = np.pi/M_theta
    d_phi = a/d_theta
    for m in range(M_theta):
        theta = np.pi*(m+0.5)/M_theta
        M_phi = int(2*np.pi*np.sin(theta)/d_phi)
        for n in range(M_phi):
            phi = 2*np.pi*n/M_phi
            rr = r * np.random.rand()
            points.append(np.array([rr*np.sin(theta)*np.cos(phi),
                                    rr*np.sin(theta)*np.sin(phi),
                                    rr*np.cos(theta)]))

    omega = 4*np.pi/N_count

    return np.array(points), omega


N = 400
pts, _ = eq_points(N, 1.)
pts_rescaled, _ = eq_points_with_random_radius(N, 1.)
extremum = 2.

# plot points
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(pts_rescaled[:,0], pts_rescaled[:,1], pts_rescaled[:,2])
ax.set_xlim(-extremum, extremum)
ax.set_ylim(-extremum, extremum)
ax.set_zlim(-extremum, extremum)
# get indices of simplices making up the surface using points on unit sphere;
# index into rescaled points  
hull = ConvexHull(pts)
vertices = [pts_rescaled[s] for s in hull.simplices]

fig = plt.figure()
ax = Axes3D(fig)
triangles = Poly3DCollection(vertices, edgecolor='k')
ax.add_collection3d(triangles)
ax.set_xlim(-extremum, extremum)
ax.set_ylim(-extremum, extremum)
ax.set_zlim(-extremum, extremum)
plt.show()