TVTK三维可视化笔记2(快速绘图)

0.准备
1.点和线
2.二维图像的可视化
3.网格面mesh
4.标量场
5.矢量场

0.准备

虽然VTK可视化软件包的功能很强大,Python的TVTK库也很方便简洁,但是用这些快速编写实用的三维可视化程序仍然是非常具有挑战性的。因此基于VTK开发出了许多可视化软件,例如ParaView、VTKDesigner2、Mayavi2等。

Mayavi2完全用Python编写,它不但是一个方便实用的可视化软件,而且可以用Python编写扩展,嵌入到用户编写的Python程序中,并且提供了面向脚本的mlab模块,以方便用户快速绘制三维图。和matplotlib的pylab一样,Mayavi的mlab模块提供了方便快捷的三维绘制函数。只要将数据准备好,通常只需要调用一次mlab模块的绘图函数,就可以看到数据的三维显示效果,非常适合在IPython中交互使用。下面的程序是用ipython运行的,jupyternotebook运行太慢总是无响应。
先说明下mgrid,ogrid,meshgrid的区别
在这里插入图片描述在这里插入图片描述

1.点和线

三维空间中独立的点使用point3d()绘制,而plot3d()则将一系列的点连接起来绘制三维曲线。
points3d(x, y, z, s, …) #s为保存每个点对应的标量值的数组
points3d(x, y, z, f, …) #f为计算每个点对应的标量值的函数
这些数组的形状完全相同,前3个参数x、y、z对应点的X、Y和Z轴的坐标值;而如果有第4个参数s,它指定每个坐标点所对应的数值(标量值)。point3d()的第4个参数还可以是通过坐标计算标量值的函数。

"以plot3d()绘制洛伦茨吸引子轨迹为例"
from scipy.integrate import odeint
from mayavi import mlab
import numpy as np

def lorenz(w, t, p, r, b):
    x, y, z = w
    return np.array([p*(y-x), x*(r-z)-y, x*y-b*z])
t = np.arange(0, 30, 0.01)
#使用odeint()得到的轨迹数据track1是一个二维数组,数组的第0轴的长度是轨迹的点数,第1轴的长度为3,分别为轨迹上每点的X、Y、Z轴坐标。
track1 = odeint(lorenz, (0.0, 1.00, 0.0), t, args=(10.0, 28.0, 3.0)) 
#track1大小:(3000, 3)
#array([[ 0.00000000e+00,  1.00000000e+00,  0.00000000e+00],
 #      [ 9.51228522e-02,  1.00353502e+00,  4.78470951e-04],
 #      [ 1.82774668e-01,  1.03241643e+00,  1.86429073e-03],
 #     ...,
 #      [-3.53767572e-01,  1.74983009e+00,  2.15790509e+01],
 #     [-1.55336337e-01,  1.71558331e+00,  2.09369871e+01],
 #     [ 2.15508902e-02,  1.69382719e+00,  2.03171150e+01]])
X, Y, Z = track1.T
#将track1拆分为三个一维数组之后,调用plot3d()绘制轨迹曲线。这里用时间数组t作为标量值数组,因此轨迹上每个点所对应的标量值就是到达此点的#时间。tube_radius参数设置曲线的粗细,曲线实际上采用极细的圆管绘制。
mlab.plot3d(X, Y, Z, t, tube_radius=0.2) 
mlab.show()

经过下面的调整,上面的洛伦茨吸引子轨迹图像变成了第二个。
在这里插入图片描述![在这里插入图片描述](https://img-blog.csdnimg.cn/20190810190215541.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzU4NTcxMg==,size_16,color_FFFFFF,t_70
Mayavi Scene:处于树的最顶层的对象表示场景,在其配置界面中可以设置场景的背景和前景色、场景中的灯 光以及其他一些选项。
LineSource:线数据源
Stripper:根据内部filter对象的maximum_length属性对线数据源进行分段处理。
Tube:将输入的PolyData数据中的每条线转换为表示三维圆管的PolyData数据。
Colors and legends:在其配置界面中的"Scalar LUT"选项卡中可以设置将标量值转换为颜色的查询表
在这里插入图片描述
Surface:它将Tube所输出的PolyData数据转换为最终在场景中显示的三维实体
在这里插入图片描述

2. 二维图像的可视化

三维空间中的曲面可以用surf()绘制,它实际上是将二维图像(数组)绘制成三维的曲面,用曲面的高度表示图像中每点的值。

from scipy.integrate import odeint
from mayavi import mlab
import numpy as np

x, y = np.ogrid[-2:2:20j, -2:2:20j] #❶
z = x * np.exp( - x**2 - y**2)#❷
face = mlab.surf(x, y, z, warp_scale=2)#❸
axes = mlab.axes(xlabel='x', ylabel='y', zlabel='z', color=(0, 0, 0)) #❹
outline = mlab.outline(face, color=(0, 0, 0))
mlab.show()

❶先通过ogrid对象计算两个形状分别为(20, 1)和(1, 20)的数组x和y。
❷然后通过广播运算,计算出由x和y构成的等距网格上每点的函数值z,它是一个形状为(20, 20)的数组。
❸接着调用mlab.surf(),将数组z绘制成三维空间中的曲面,所绘制的曲面在X-Y平面上的投影是一个等距离网格。
❹最后通过mlab.axes()和mlab.outline(),分别在三维场景中添加坐标轴和曲面区域的外框。需要注意的是,与matplotlib相反,在Mayavi中二维数组的第0轴表示X轴,第1轴表示Y轴。

在这里插入图片描述

3.网格面mesh

如果需要绘制更复杂的三维曲面,可以使用mesh()。

from numpy import sin, cos
import numpy as np
from mayavi import mlab
dphi, dtheta = np.pi/80.0, np.pi/80.0
phi, theta = np.mgrid[0:np.pi+dphi*1.5:dphi, 0:2*np.pi+dtheta*1.5:dtheta]
m0, m1, m2, m3, m4, m5, m6, m7 = 4,3,2,3,6,2,6,4
r = sin(m0*phi)**m1 + cos(m2*phi)**m3 + sin(m4*theta)**m5 + cos(m6*theta)**m7 #❶
x = r*sin(phi)*cos(theta) #❷
y = r*cos(phi)
z = r*sin(phi)*sin(theta)
s = mlab.mesh(x, y, z)# ❸
mlab.show()

❶曲面上各点的坐标在球坐标系中计算
❷然后按照坐标转换公式将球坐标系转换为笛卡尔坐标系。
❸程序中调用mesh()绘制曲面,它和surf()类似,其三个数组参数x、y、z都是形状相同的二维数组。这些数组的相同下标的三个数值组成曲面上某点的三维坐标。点之间的连接关系(边和面)由其在x、y、z数组中的位置关系决定。
在这里插入图片描述
在这里插入图片描述

4.标量场

前面介绍了如何对一维和二维数据进行可视化,下面看看三维数据的可视化问题。最简单的三维数据就是三维图像,可以用一个三维数组表示。图像中每个点的三维坐标都由它在数组中的下标决定,而每个点对应的标量值则是数组中对应元素的值。这种三维图像可以用来描述标量场,例如房间中的温度分布、材料的密度分布或者通过X射线断层成像(CT)技术采集到的人体的内部构造。
标量场有三种可视化方法
等值面:和二维图像的等高线类似,用标量值相等的曲面,显示标量场的形态。
体素呈像:利用透明度和颜色直接呈现标量场的形态。
切面:通过对标量场进行切面处理,显示在某个切面上场的形态。

   计算一个有两个点电荷的电势场,两个点电荷分别位于(-1, 0, 0)和(1, 0, 0)处。为了方便显示,只计算Z轴上(-2, 0)区间的电势场:

4.1.等值面法

from numpy import sin, cos
import numpy as np
from mayavi import mlab
x, y, z = np.ogrid[-2:2:40j, -2:2:40j, -2:0:40j]#((40, 1, 1), (1, 40, 1), (1, 1, 40))
s = 2/np.sqrt((x-1)**2 + y**2 + z**2) + 1/np.sqrt((x+1)**2 + y**2 + z**2)#广播运算
surface = mlab.contour3d(s)#使用contour3d()可以快速绘制此电势场的等值面
mlab.show()

将等值面的上限改成15,在最小值到15之间绘制10个等值面
在这里插入图片描述
将透明度设为0.3704
在这里插入图片描述
在这里插入图片描述

4.2体素呈像法

体素呈像法用每个点的颜色和透明度对整个标量场进行润色,从而能够呈现更多的信息。体素呈像没有对应的函数,需要我们自己创建流水线:

from numpy import sin, cos
import numpy as np
from mayavi import mlab

x, y, z = np.ogrid[-2:2:40j, -2:2:40j, -2:0:40j]# #((40, 1, 1), (1, 40, 1), (1, 1, 40))
s = 2/np.sqrt((x-1)**2 + y**2 + z**2) + 1/np.sqrt((x+1)**2 + y**2 + z**2)#广播运算
"体素呈像没有对应的函数,需要我们自己创建流水线:"
field = mlab.pipeline.scalar_field(s)
mlab.pipeline.volume(field, vmin=1.5, vmax=10)#它们指定标量值的润色范围,即只绘制标量值在vmin到vmax之间的区域
mlab.show()

在这里插入图片描述

5.矢量场

对于三维空间中的场,每个点对应一个矢量,它由X、Y、Z轴上的三个分量组成。因此需要3个三维数组表示矢量场,这些数组分别表示矢量在三个轴上的分量。

下面以洛伦茨吸引子为例

import numpy as np
from mayavi import mlab

p, r, b = (10.0, 28.0, 3.0)
#x,y,z,u,v,w 大小:(20,20,20)
x, y, z = np.mgrid[-17:20:20j, -21:28:20j, 0:48:20j]
u, v, w = p*(y-x), x*(r-z)-y, x*y-b*z
vectors = mlab.quiver3d(x, y, z, u, v, w)#三个速度分量构成一个矢量场,下面调用quiver3d()将每个点的速度矢量用一个箭头表示
mlab.show()

图一由于矢量场数据的网格过密,无法看清矢量场的内部结构。此时可以用下面的语句修改Vectors对象的一些属性以减少箭头的数量并增加箭头的长度(见图二)
在这里插入图片描述
将随进选择原始数据中1/20个点进行描绘
在这里插入图片描述
设置箭头的缩放比例为5
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值