图6.具有4个元素和5个节点的网格。方括号[]中显示的标量节点数据以及方括号外的节点号。标量单元格数据显示在大括号{}中。节点标签从左下角开始,然后增加,逆时针移动。
创建了四个不同的查找表以可视化
图6
中
所示
的数据。最终结果
如图7
所示。下面以与在
图7
的标题中描述的顺序相同的顺序讨论它们。代码清单中的查找表被命名为
lut_n
,其中
n
是查找表的编号。类似地,相应的映射器和其他对象也相应地编号。仅
vtkPolyData
创建一个网格(一个实例)。由于每个映射器都链接到其相应的查找表,因此出现了可视化方面的差异。范围使用以下设置:
lut_1.SetTableRange(5.0, 7.5)
lut_2.SetTableRange(5.0, 7.5)
lut_3.SetTableRange(5.0, 7.5)
lut_4.SetTableRange(0.0, 1.0)
前三个查询表使用平滑渐变显示点数据,而第四个用于可视化为单元格存储的类别数据。因此,它具有不同的范围。第一个查询表保留默认设置。
.Build()
在分配给相应的映射器之前,只有方法被调用。
lut_1.Build()
mesh_mapper_1.SetLookupTable(lut_1)
第二个查找表修改HSV颜色值以创建单个彩色渐变,其中HSV颜色描述中的V大小会发生变化,而色相和饱和度则是固定的。结果是创建了与较低和较高标量数据值相对应的较暗和较亮的区域。对于3D模型,应谨慎使用此方法。在3D阴影中,当以与网格数据无关的方式渲染模型时,也会使用阴影,因此应谨慎使用这种特殊的着色技术。
lut_2.SetHueRange(0.5, 0.5)
lut_2.SetSaturationRange(1.0, 1.0)
lut_2.SetValueRange(0.25, 1.0)
lut_2.Build()
mesh_mapper_2.SetLookupTable(lut_2)
第三个查找表创建自定义的颜色组合,在构建查找表时从中创建渐变。这是使用的方法创建
如上所述
。选择了三种颜色,并将它们设置为反映值范围的低端,中端和高端。A
vtkColorTransferFunction
用于对颜色值进行插值,以在这三个点之间创建渐变。
no_of_colours = 256
lut_3.SetNumberOfColors(no_of_colours)
ctransfer = vtk.vtkColorTransferFunction()
ctransfer.AddRGBPoint(0.0, 1.0, 0.25, 0.0) # Orange
ctransfer.AddRGBPoint(0.5, 1.0, 0.00, 0.0) # Red
ctransfer.AddRGBPoint(1.0, 1.0, 0.95, 0.95) # White
for i in range(no_of_colours):
new_colour = ctransfer.GetColor(i / float(no_of_colours))
lut_3.SetTableValue(i, *new_colour)
lut_3.Build()
mesh_mapper_3.SetLookupTable(lut_3)
最终查找表使用3种自定义颜色来显示4个类别之一中的每个单元格的成员资格。使用设置颜色数为3,
lut_4.SetNumberOfColors(3)
并分别设置要使用的3种颜色中的每一种。表范围[0.0,1.0]设置得较早。这意味着要将单元格的颜色设置为红色,琥珀色或绿色,需要将其值设置为0.0、0.5或1.0。请注意,从
图6可以
看出,每个单元格都具有这些值之一作为其单元格数据。将查找表设置为相应的映射器后,
.SetScalarModeToUseCellData()
将使用该方法。由于网格同时包含像元数据和点数据,因此VTK将默认使用点数据进行可视化。需要调用此方法。
.SetScalarModeToUsePointData()
但是,点数据的相应方法是默认值,因为点数据是默认方法,而以前的查找表从未使用过该方法。
lut_4.SetNumberOfColors(3)
lut_4.SetTableValue(0, 1.0, 0.0, 0.0) # Red
lut_4.SetTableValue(1, 1.0, 0.75, 0.0) # Amber
lut_4.SetTableValue(2, 0.0, 1.0, 0.0) # Green
lut_4.Build()
mesh_mapper_4.SetLookupTable(lut_4)
mesh_mapper_4.SetScalarModeToUseCellData()
的实例
vtkScalarBarActor
已添加到每个渲染器。它们通过显示颜色及其对应的值来帮助注释可视化。对于分类信息,我们的代码使用单元格值将成员资格分配给某个类别,但是实际值本身对查看可视化效果的用户没有用。默认标签被从标量栏中,通过使用该方法其数量设置为0除去
.SetNumberOfLabels(0)
上
vtkScalarBarActor
bar_4
。使用查找表方法在查找表中设置每个类别的注释
.SetAnnotation(value, annotation)
。
lut_4.SetAnnotation(0.0, "Red")
lut_4.SetAnnotation(0.5, "Amber")
lut_4.SetAnnotation(1.0, "Green")
条形图使用对应的查找表进行关联,
bar.SetLookupTable(lut)
并作为角色添加到渲染器中。作为2D演员,使用方法将它们添加
.AddActor2D(actor)
。关于2D画布和2D角色的更多讨论将在下一章中介绍。
所有4个结果
如图7
所示。
图7.从
图6中
的网格创建的可视化。左上角按顺时针方向显示的结果是:默认查找表;固定HSV模型中的色相和饱和度,并允许其值变化;通过在任意选择的颜色之间插值颜色而创建的自定义颜色渐变;以及用于将元素分为三类的单元格数据。
VTK可以通过多种方式转换场景中的模型。多边形网格将具有其自己的局部原点。分析人员正在构建的整个场景也有其起源。使用角色引用的网格的
.AddActor(actor)
方法
vtkRenderer
将角色添加到场景时,会将角色添加到场景中。放置网格时,应使网格的本地原点与装配场景的全局原点重合,其中局部轴和全局轴均已对齐。
如果要移动模型,则可以修改面数据本身。如果这样做,您将修改每个引用该数据的对象所使用的数据。先前的示例表明,可以创建一个几何实例,然后让多个映射器引用相同的数据。如果随后修改了数据,则对该数据的所有引用都将被修改。相反,每个角色都允许您定义一个转换,该转换描述模型如何在场景中移动。有几种定义这些转换的方法。下面我们讨论如何通过调用方法来完成此操作
vtkActor
。在后面的章节中将介绍另外两种方法,其中涉及定义该
vtkTransform
参与者所引用的对象。此处描述的方法更简单,适用于大多数情况。
演员有几种定义转换的方法。我们对平移,缩放和旋转actor的3个操作感兴趣。
该
.SetPosition(x, y, z)
演员的方法,将移动的演员,使得演员的本地原点移动到指定的位置
x
,
y
和
z
。演员的当前位置可通过该
.GetPosition()
方法获得。如果你想演员相对的移动到其目前的现在的位置,而不是你可以使用一个绝对位置
.GetPosition()
,添加到这些返回的
x
,
y
,
z
坐标,然后调用
.SetPosition(x, y, z)
但是VTK还提供了
.AddPosition(x, y, z)
执行所有这一切都从一个单一的方法方法。
演员的比例是通过该
.SetScale()
方法设置的。它可以使用1或3个参数。单个标量值将在所有方向上均等地缩放角色,例如,用于在所有方向上将
.SetScale(3.0)
模型的大小均等地增加三倍。要在模型的宽度和深度而不是高度上缩放模型(请记住VTK使用Y轴作为其垂直方向),可以将其
.SetScale(x, 1, x)
用作缩放因子
x
。在actor下方,首先在每个方向上将因子缩放为5,然后在x,y和z方向上将因子缩放为4、2和3。
factor = 5
actor.SetScale(factor)
factor = [4.0, 2.0, 3.0]
actor.SetScale(factor)
演员可以用三种方式进行旋转:
.RotateX(theta)
,
.RotateY(theta)
,和
.RotateZ(theta)
。这
theta
是旋转模型的角度(以度为单位)。这些角度是相对于模型的局部坐标系,而不是全局坐标系。
关于订购的注意事项
重要的是要考虑旋转的顺序。以不同顺序执行的相同旋转可能会提供不同的方向。平移发生在全局坐标系中,比例因子和旋转相对于模型的局部坐标系。您不仅需要考虑旋转是一般旋转还是非交换(这意味着如果以不同的顺序执行旋转,它们可能会产生不同的结果),而且定义旋转的坐标系也会随旋转而变化。因此,调用
.RotateX(theta)
实际上取决于绕其进行的旋转来指定绕不同轴的旋转。
与上一点在一起的是,有多种方法可以旋转对象以达到特定方向。Actor具有一种
.GetOrientation()
返回模型当前方向的方法。指定这些值,以便如果按照z,x,然后y的顺序执行旋转,则actor将到达其当前方向。类似地,该方法
.AddOrientation(x, y, z)
是相当于执行
.RotateZ(z)
,
.RotateX(x)
和
.RotateY(y)
以该顺序。
示例:3D绘图脚本
在本章的3D绘图应用程序示例中,将本章前面开发的许多较小的技能结合在一起。VTK库通常提供几种方法来获得相同的结果。有很多方法可以开发此示例。选择此处使用的方法是因为它们建立在上面开发的技能之上。最终结果是一个小型应用程序,可以绘制3D中任意曲面的方程式。尽管这显示的是由方程式定义的更抽象的表面,而不是现实生活中的对象或几何图形-VTK非常适合该对象或几何图形-这是仅使用上面开发的技能创建的有用且完整的应用程序的示例。
第一步是提供用于绘制表面的必要输入参数。当然,这些参数中的第一个是将要绘制的函数本身。函数是
func_to_calculate(x, y)
。给定X和Y坐标时,它可以是返回Z值的任何有效函数。
x0 = -7 # X domain low end
y0 = -7 # Y domain low end
x_max = 7 # X domain high end
y_max = 7 # Y domain high end
X = 100 # Resolution in x direction. Integer
Y = 100 # Resolution in y direction. Integer
上面列出了下一个输入参数。它们描述了要绘制的函数的域以及进行该绘制的数值分辨率。这些参数也显示在[
mesh_grid_with_origin_figure
]
中
。其中指定域中的4个变量是
x0
,
x_max
,
y_0
,和
y_max
。它们描述了XX 和 ÿÿ 指示。
在此示例的代码清单中,没有错误检查,但是更精致的示例将检查这些参数以确保它们正确。这可以包括确保
x_max
比
x0
其他检查更大。实际上,比起在Python文件顶部输入参数,更精美的示例将找到一种更优雅的方式来输入这些参数!参数
X
和
Y
指定要在其各自方向上使用的像元数。通过这些详细信息,我们可以计算出XX 和 ÿÿ 每个单元的尺寸。
deltax = (x_max - x0) / float(X)
deltay = (y_max - y0) / float(Y)
并非必须使用float(),但很有用,因为如果
int
仅对(整数)个值执行除法,则Python版本2会丢弃余数。此功能可强制进行浮点除法并避免此问题。
就像前面的示例一样,我们创建的实例,
vtkPoints
并
vtkCellArray
在其中存储单元和点以定义曲面。
points = vtk.vtkPoints()
cells = vtk.vtkCellArray()
我们需要计算网格中的所有点。该表面由在x和y方向上具有均匀间距的四边形单元定义。对于x和y方向,点的行比单元格多。作为
X
并
Y
包含每个维度上的像元数,我们遍历
X+1
并
Y+1
指向每个维度。
zvals = []
for j in range(Y+1):
for i in range(X+1):
x = x0 + deltax*i
y = y0 + deltay*j
z_val = func_to_calculate(x, y)
zvals.append(z_val)
coord = x, y, z_val
points.InsertNextPoint(coord)
在上面,Z值存储在列表中,
zvals
以供以后在代码中以及在使用该
.InsertNextPoint(coord)
方法的坐标点中使用。将它们存储在本地Python数据结构中也更加方便。请注意,
.InsertNextPoint()
和
.append()
方法在同一循环中调用。该点的相同全局ID(在
.InsertNextPoint()
调用时隐式设置)也可以用于索引
zvals
以获取相同的Z值。稍后在创建添加到网格的标量点数据时使用。
for j in range(Y):
for i in range(X):
quad = vtk.vtkQuad()
corner_id = get_id(i, j)
quad.GetPointIds().SetId(0, corner_id)
quad.GetPointIds().SetId(1, corner_id + 1)
quad.GetPointIds().SetId(2, corner_id + (X+2))
quad.GetPointIds().SetId(3, corner_id + (X+1))
cells.InsertNextCell(quad)
下一步是
vtkQuad
在多边形网格中创建元素。这些元素有四个ID为0、1、2和3的本地点,这些本地点需要与4个全局点ID关联。使用插入点的顺序分配了点ID
points.InsertNextPoint(coord)
。如果使用了上面代码清单所示的二维循环,则ID,ññ,具有最低节点的 XX 和 ÿÿ坐标(请参见[
arbitrary_cell
]
)由i + j (X+ 1 )一世+Ĵ(X+1个),其中
X
提供了输入参数。和ññ其他3个点的ID可以直接确定。创建点和像元后,它们将被添加到网格中。
mesh = vtk.vtkPolyData()
mesh.SetPoints(points)
mesh.SetPolys(cells)
点数据放置在中
vtkDoubleArray
(见下文)。然后将其设置为网格中的点数据。
point_data = vtk.vtkDoubleArray()
point_data.SetNumberOfComponents(1)
for zval in zvals:
point_data.InsertNextTuple([zval])
mesh.GetPointData().SetScalars(point_data)
本可视化中有两个新功能尚未在本章中介绍。如果您已经阅读了本章的上一内容,尽管它们是新的,但它们的用法很简单。当我们渲染表面时,它被框的轮廓和轴所围绕。这两个附加功能可以帮助可视化对象:第一个功能是在模型周围勾勒出一个框,第二个功能是显示坐标轴以帮助确定尺寸。这两个都要求
vtkPolyDataNormals
从多边形网格派生实例。使用以下内容可以轻松生成此信息:
norms_generator = vtk.vtkPolyDataNormals()
norms_generator.SetInputData(mesh)
然后使用该数据生成坐标轴。
axes = vtk.vtkCubeAxesActor2D()
axes.SetInputConnection(norms_generator.GetOutputPort())
axes.SetCamera(renderer.GetActiveCamera())
axes.SetLabelFormat("%1.1g")
类似地,轮廓过滤器使用以下内容创建。
outline_filter = vtk.vtkOutlineFilter()
outline_filter.SetInputConnection(norms_generator.GetOutputPort())
轴是Actor2D,可以像其他任何actor一样添加到渲染器中。轮廓过滤器可以像常规实例一样对待,
vtkPolyData
这意味着将其连接到a
vtkPolyDataMapper
和a
vtkActor
,然后使用添加到渲染器
renderer.AddActor(outline_actor)
。
最终结果如下所示。
在科学的可视化中,颜色的使用非常重要。在VTK中,数据通常被映射到一个调色板,当呈现时,该调色板允许用户非常快速地吸收有关一组数据的大量信息。了解VTK中颜色的定义非常重要,尤其是对于定义查找表而言。
通过指定3个单独的浮点值可以描述任何颜色。VTK使用范围[0.0,1.0]。VTK使用两种模型来描述颜色。第一个颜色模型是红/绿/蓝(RGB)模型[
2
]。VTK中的方法采用或返回[0.0,1.0]范围内的3个浮点数。这些描述了构成该颜色的红色,绿色和蓝色的数量。RGB值(1.0,0.0,0.0)为亮红色;(1.0,1.0,1.0)的RGB值为白色,(0.0,0.0,0.0)的RGB值为黑色。同时增大或减小这三个值将使所得的颜色变亮或变暗。
图12.三行色样,显示了更改HSV参数时结果颜色的效果。在每一行中,一个参数都会变化,而其他参数则保持最大值。第一行:色调变化,显示红色,黄色,绿色和蓝色之间的变化。第二行:紫色的饱和度降低了,变为灰色。第三行:与第二行相同的颜色值降低了,变为黑色。
另一个模型是色相/饱和度/值(HSV)模型[
3
]。这也需要3个参数来描述颜色,但是这3个值描述了不同的信息。对于某些人来说,该模型可能更直观。第一个数字
hue
是一个人可能会认为
的
颜色。想象一下,穿过彩虹,色调将决定颜色是红色,橙色,黄色等。饱和度和值描述了这种颜色的强度,但是以两种不同的方式。饱和度描述了有多少种颜色。饱和度为0.0会更改所有颜色以灰度显示。该值描述颜色的亮或暗。不管其他值如何,值0.0始终会产生黑色,而最亮的值为1.0。
在某些地方,指定了第4个值:alpha值。这指定了表面的透明度。Alpha值0.0是一个完全透明的表面,而与其他3种颜色值无关。Alpha值为1.0时,表面完全是不透明/不透明,并显示为其他3个值指定的颜色。alpha值为1.0时将完全不透明。
下表总结了本章中描述的命令。
lut.UseBelowRangeColorOn()
lut.UseBelowRangeColorOff()
lut.UseAboveRangeColorOn()
lut.UseAboveRangeColorOff()
对于查找表,
lut
控制是否对范围之外的值使用自定义颜色。默认情况下关闭。
lut.SetHueRange(low, high)
lut.SetSaturationRange(low, high)
lut.SetValueRange(low, high)
对于该
vtkLookupTable
lut
设置,色相,饱和度或值范围从
low
到
high
。设置
low
=
high
固定为单个值。