python中plot_surface用一系列坐标点是如何拟合出三维曲面的

python中plot_surface用一系列坐标点是如何拟合出三维曲面的,即各点之间是如何连接?

img

以此图为例,是由128*128共16384个点利用plot_surface拟合而成,想知道各各点之间是如何连接,即python中plot_surface根据一系列离散的坐标点进行三维曲面拟合时采用何种算法

检查修改

无论是mplot3d,还是OpenGl,或者是从OpenGL分化出去的VTK / Mayavi,绘制曲面的接口大致上分为两种方式:一是提供组成曲面的若干三角形或四角形的顶点坐标,二是基于一个假象的网格传入该网格上各个顶点的坐标——这个假象的网格通常被称为mesh。 mplot3d也提供了两种曲面绘制函数,plot_surface是前面提到的第二种,即mesh方式,plot_trisurf则是第一种,即接受若干三角形的顶点坐标作为参数。下面的例子演示了两种曲面绘制函数的用法。

在开始之前,需要理解mplot3d的坐标系和OpenGl不同:如果固定x轴从屏幕左侧指向右侧,mplot3d的z轴指向屏幕上方,y轴指向屏幕(向内),而OpenGl则是y轴指向屏幕上方,z轴指向屏幕外面(向外)。如此,就不难理解(0,0,1)是z轴正方向上的点,该点和x轴
上的(1,0,0), (0,-1,0)以及y轴上的(0,1,0), (0,-1,0)组成4个三角形。

>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> from mpl_toolkits.mplot3d import Axes3D
>>> vs = np.array([
    [0,0,1],[1,0,0],[0,-1,0], # 第1个三角形
    [0,0,1],[0,-1,0],[-1,0,0], # 第2个三角形
    [0,0,1],[-1,0,0],[0,1,0], # 第3个三角形
    [0,0,1],[0,1,0],[1,0,0] # 第4个三角形
])
>>> ax = plt.axes(projection='3d')
>>> ax.plot_trisurf(vs[...,0], vs[...,1], vs[...,2])
<mpl_toolkits.mplot3d.art3d.Poly3DCollection object at 0x000001ED8B873208>
>>> ax.set_xlabel('X')
Text(0.5, 0, 'X')
>>> ax.set_ylabel('Y')
Text(0.5, 0.5, 'Y')
>>> ax.set_zlabel('Z')
Text(0.5, 0, 'Z')
>>> plt.show()

img

绘制mesh也不难理解,就以下面这张全球地图为例。

img

>>> import numpy as np
>>> from PIL import Image
>>> im = np.array(Image.open(r'd:\earth_1080.jpg'))
>>> im.shape
(540, 1080, 3)
>>> im = np.float32(im)/255 # 将0-255之间的整型颜色值变为0-1之间的浮点数

这张地图分辨率是1080x540,对应的经度范围从0°到360°,对应的纬度范围从90°到-90°。可以设想一个经纬度网格,经度范围从0°到360°,纬度范围从90°到-90°,只要计算出网格上每一点的空间坐标坐标,然后用图中对应点的颜色绘制该点,就得到了一个三维的地球。使用plot_surface函数绘制的话,传入的x,y,z必须是和网格保持相同shape的二维数组。

>>> import matplotlib.pyplot as plt
>>> from mpl_toolkits.mplot3d import Axes3D
>>> lats, lons = np.mgrid[90:-90:540j, 0:360:1080j]
>>> lats = np.radians(lats)
>>> lons = np.radians(lons)
>>> z = np.sin(lats)
>>> x = np.cos(lats) * np.cos(lons)
>>> y = np.cos(lats) * np.sin(lons)
>>> ax = plt.axes(projection='3d')
>>> ax.plot_surface(x, y, z, facecolors=im)
<mpl_toolkits.mplot3d.art3d.Poly3DCollection object at 0x000001ED90F7C608>
>>> plt.show()

最终的效果只能是差强人意,毕竟mplot3d只是matplotlib的一个扩展包,不能和OpenGL相提并论。

img


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

fig = plt.figure()
ax3 = plt.axes(projection='3d')

plt.rcParams['font.sans-serif']=['FangSong'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号

#定义三维数据
xx = np.arange(-5,5,0.5)
yy = np.arange(-5,5,0.5)
X, Y = np.meshgrid(xx, yy)
Z = np.sin(X)+np.cos(Y)

#作图
ax3.plot_surface(X,Y,Z,cmap='rainbow') 
# 改变cmap参数可以控制三维曲面的颜色组合, 一般我们见到的三维曲面就是 rainbow 的

plt.show()