一:主要的知识点
1、说明
本文只是教程内容的一小段,因博客字数限制,故进行拆分。主教程链接:vtk教程——逐行解析官网所有Python示例-CSDN博客
2、知识点纪要
本段代码主要涉及的有①vtkDiscretizableColorTransferFunction既可以连续颜色映射也可以离散颜色映射
二:代码及注释
import vtkmodules.vtkInteractionStyle import vtkmodules.vtkRenderingOpenGL2 from vtkmodules.vtkRenderingCore import vtkActor, vtkActor2D, vtkDiscretizableColorTransferFunction, vtkTextProperty, \ vtkPolyDataMapper, vtkTextMapper, vtkRenderer, vtkRenderWindow, vtkRenderWindowInteractor from vtkmodules.vtkCommonColor import vtkNamedColors from vtkmodules.vtkFiltersSources import vtkCylinderSource from vtkmodules.vtkFiltersCore import vtkElevationFilter from vtkmodules.vtkRenderingAnnotation import vtkScalarBarActor def get_ctf(modern): """ vtkDiscretizableColorTransferFunction 与vtkColorTransferFunction一样,用于将 标量值映射为颜色 不过是vtkColorTransferFunction的增强版,可以理解为可选择离散化(discretizable)的颜色传递函数 支持将颜色映射离散化成固定数量的颜色级别,并且能自动生成对应的 vtkLookupTable,方便在渲染器或 mapper 中直接使用 类的功能概览 连续颜色映射: 像 vtkColorTransferFunction 一样,支持通过插值生成连续颜色梯度 离散颜色映射: 可以指定“分几级颜色”,自动将颜色区间离散化 可生成 LookupTable:可直接输出一个 vtkLookupTable,供 mapper 使用 支持透明度(Alpha): 可以在颜色之外控制透明度函数。 支持直接输入 RGB/HSV 空间颜色节点: 可选择在不同颜色空间中插值 """ ctf = vtkDiscretizableColorTransferFunction() ctf.SetColorSpaceToRGB() ctf.SetScaleToLinear() # 设置颜色映射为线性比例 ctf.SetNanColor(0.5, 0.5, 0.5) # 设置当遇到无效数据(NaN)时使用的颜色 ctf.SetBelowRangeColor(0.0, 0.0, 0.0, ) # 设置低于 CTF 定义的最小标量值的数据点所使用的颜色 ctf.UseBelowRangeColorOn() # 启用上述设置的“低于范围颜色,如果不开启这个选项,于范围的数据通常会沿用颜色条最底端的颜色。开启后,它们将使用明确设置的黑色 ctf.SetAboveRangeColor(1.0, 1.0, 1.0) ctf.UseAboveRangeColorOn() if modern: ctf.AddRGBPoint(-1.0, 1.0, 0.0, 0.0) # Red ctf.AddRGBPoint(-2.0 / 3.0, 1.0, 128.0 / 255.0, 0.0) # Orange #ff8000 ctf.AddRGBPoint(-1.0 / 3.0, 1.0, 1.0, 0.0) # Yellow ctf.AddRGBPoint(0.0, 0.0, 1.0, 0.0) # Green #00ff00 ctf.AddRGBPoint(1.0 / 3.0, 0.0, 1.0, 1.0) # Cyan ctf.AddRGBPoint(2.0 / 3.0, 0.0, 0.0, 1.0) # Blue ctf.AddRGBPoint(1.0, 128.0 / 255.0, 0.0, 1.0) # Violet #8000ff else: ctf.AddRGBPoint(-1.0, 1.0, 0.0, 0.0) # Red ctf.AddRGBPoint(-2.0 / 3.0, 1.0, 165.0 / 255.0, 0.0) # Orange #00a500 ctf.AddRGBPoint(-1.0 / 3.0, 1.0, 1.0, 0.0) # Yellow ctf.AddRGBPoint(0.0, 0.0, 125.0 / 255.0, 0.0) # Green #008000 ctf.AddRGBPoint(1.0 / 3.0, 0.0, 153.0 / 255.0, 1.0) # Blue #0099ff ctf.AddRGBPoint(2.0 / 3.0, 68.0 / 255.0, 0, 153.0 / 255.0) # Indigo #4400ff ctf.AddRGBPoint(1.0, 153.0 / 255.0, 0.0, 1.0) # Violet #9900ff ctf.SetNumberOfValues(7) ctf.DiscretizeOn() # 颜色离散化 return ctf def rescale(values, new_min, new_max): # 将一组原始数值从它们当前的范围,线性地转换(映射)到用户指定的新范围内 res = list() old_min, old_max = min(values), max(values) for v in values: new_v = (new_max - new_min) / (old_max - old_min) * (v - old_min) + new_min res.append(new_v) return res def rescale_ctf(ctf, new_min, new_max, reverse): if new_min > new_max: r0 = new_max r1 = new_min else: r0 = new_min r1 = new_max xv = [] rgbv = [] nv = [0] * 6 """ 为什么nv是一个长度为6的列表? 因为ctf.GetNodeValue(i, nv)返回的列表包含一个颜色节点(color node)的全部信息,而这个颜色节点在 vtk中包含的信息有[X,R,G,B,MidPoint,Sharpness] 其中X是对应的标量数据值,R,G,B是对应的颜色 MidPoint是中点参数,控制颜色过渡的非线性成都。0表示线性插值,1表示中点在两个颜色之间距离100%的位置 Sharpness是尖锐度参数,控制插值曲线的陡峭程度,通常用于创建更锐利或更平滑的过渡效果 """ for i in range(0, ctf.GetNumberOfValues()): ctf.GetNodeValue(i, nv) x = nv[0] rgb = nv[1:4] xv.append(x) rgbv.append(rgb) xvr = rescale(xv, r0, r1) return generate_new_ctf(ctf, xvr, rgbv, reverse=reverse) def generate_new_ctf(old_ctf, new_x, new_rgb, reverse): new_ctf = vtkDiscretizableColorTransferFunction() # 获取标量数据值如何沿着颜色条进行映射和差值,得到的结果要么是线性要么是对数,对数适合数据范围跨国多个量级 new_ctf.SetScale(old_ctf.GetScale()) new_ctf.SetColorSpace(old_ctf.GetColorSpace()) new_ctf.SetNanColor(old_ctf.GetNanColor()) if not reverse: new_ctf.SetBelowRangeColor(old_ctf.GetBelowRangeColor()) new_ctf.SetUseBelowRangeColor(old_ctf.GetUseBelowRangeColor()) new_ctf.SetAboveRangeColor(old_ctf.GetAboveRangeColor()) new_ctf.SetUseAboveRangeColor(old_ctf.GetUseAboveRangeColor()) else: new_ctf.SetBelowRangeColor(old_ctf.GetAboveRangeColor()) new_ctf.SetUseBelowRangeColor(old_ctf.GetUseAboveRangeColor()) new_ctf.SetAboveRangeColor(old_ctf.GetBelowRangeColor()) new_ctf.SetUseAboveRangeColor(old_ctf.GetUseBelowRangeColor()) new_ctf.SetNumberOfValues(len(new_x)) new_ctf.SetDiscretize(old_ctf.GetDiscretize()) if not reverse: for i in range(0, len(new_x)): new_ctf.AddRGBPoint(new_x[i], *new_rgb[i]) else: sz = len(new_x) for i in range(0, sz): j = sz - (i + 1) new_ctf.AddRGBPoint(new_x[i], *new_rgb[j]) new_ctf.Build() return new_ctf def main(): colors = vtkNamedColors() colors.SetColor("ParaViewBkg", (82, 87, 110, 255)) # 负责创建和配置四个不同的颜色传递函数变体,以便在四个不同的3D视图中进行比较 ctf = [] ctf.append(get_ctf(False)) ctf.append(rescale_ctf(ctf[0], 0, 1, False)) ctf.append(rescale_ctf(ctf[0], *ctf[0].GetRange(), True)) ctf.append(rescale_ctf(ctf[0], 0, 1, True)) # 定义viewport xmins = [0.0, 0.0, 0.5, 0.5] xmaxs = [0.5, 0.5, 1.0, 1.0] ymins = [0.5, 0.0, 0.5, 0.0] ymaxs = [1.0, 0.5, 1.0, 0.5] titles = ['Original', 'Rescaled', 'Reversed', 'Rescaled and Reversed'] text_property = vtkTextProperty() text_property.SetFontSize(36) text_property.SetJustificationToCentered() text_property.SetColor(colors.GetColor3d('LightGoldenrodYellow')) ren_win = vtkRenderWindow() ren_win.SetSize(640 * 2, 480 * 2) ren_win.SetWindowName('RescaleReverseLUT') iren = vtkRenderWindowInteractor() iren.SetRenderWindow(ren_win) # style = vtkInteractorStyleTrackballCamera() # iren.SetInteractorStyle(style) sources = list() elevation_filters = list() mappers = list() actors = list() scalar_bars = list() renderers = list() text_mappers = list() text_actors = list() for i in range(0, 4): cylinder = vtkCylinderSource() cylinder.SetCenter(0.0, 0.0, 0.0) cylinder.SetResolution(6) cylinder.Update() bounds = cylinder.GetOutput().GetBounds() sources.append(cylinder) """ vtkElevationFilter 根据点在空间中的位置(通常是高度/方向)来为每个点生成一个标量值(即“标高”或“海拔”) """ elevation_filter = vtkElevationFilter() elevation_filter.SetScalarRange(0, 1) elevation_filter.SetLowPoint(0, bounds[2], 0) elevation_filter.SetHighPoint(0, bounds[3], 0) elevation_filter.SetInputConnection(sources[i].GetOutputPort()) elevation_filters.append(elevation_filter) mapper = vtkPolyDataMapper() mapper.SetInputConnection(elevation_filters[i].GetOutputPort()) mapper.SetLookupTable(ctf[i]) mapper.SetColorModeToMapScalars() mapper.InterpolateScalarsBeforeMappingOn() mappers.append(mapper) actor = vtkActor() actor.SetMapper(mappers[i]) actors.append(actor) # Add a scalar bar. """ 创建和显示一个颜色标尺 """ scalar_bar = vtkScalarBarActor() scalar_bar.SetLookupTable(ctf[i]) scalar_bars.append(scalar_bar) text_mappers.append(vtkTextMapper()) text_mappers[i].SetInput(titles[i]) text_mappers[i].SetTextProperty(text_property) text_actors.append(vtkActor2D()) text_actors[i].SetMapper(text_mappers[i]) # Note: The position of an Actor2D is specified in display coordinates. text_actors[i].SetPosition(300, 16) ren = vtkRenderer() ren.SetBackground(colors.GetColor3d('ParaViewBkg')) ren.AddActor(actors[i]) ren.AddActor(scalar_bars[i]) ren.AddActor(text_actors[i]) ren.SetViewport(xmins[i], ymins[i], xmaxs[i], ymaxs[i]) renderers.append(ren) ren_win.AddRenderer(renderers[i]) ren_win.Render() iren.Start() if __name__ == '__main__': main()