用vtkUnstructuredGrid的属性对其进行着色

本文介绍如何读取一个包含Unstructured Grid数据的vtk文件,并利用文件中的nHP属性进行颜色着色。通过创建颜色映射表并设置vtk显示该标量的颜色,展示了使用nHP属性着色的过程。同时,提供了在运行时更换属性着色的方法。

我们读取一个vtk文件,文件里是一个Unstructured Grid数据。

文件中有很多属性,其中第一个被读进来的属性是nHP,我们就用这个属性的值作为着色的基础。

为此需要一个颜色映射表。

同时设置vtk对标量显示颜色。

默认情况下vtk是对scalar显示颜色的

代码:关键部分都做了注释

#include <iostream>
using namespace std;
#include <vtkUnstructuredGrid.h>
#include <vtkUnstructuredGridReader.h>
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkDataSetMapper.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPoi
import vtk import math def create_slice_actor(data_to_slice, slice_type, angle_degrees, earth_radius=0.5, lookup_table=None, scalar_array_name=None): # 新增 scalar_array_name """ 创建沿经度或纬度切割非结构化网格的Actor。 参数: data_to_slice (vtkUnstructuredGrid): 要切割的VTK非结构化网格数据。 slice_type (str): 切割类型, "longitude" (经度) 或 "latitude" (纬度)。 angle_degrees (float): 经度或纬度的角度值(度)。 earth_radius (float): 地球模型的半径,用于定位纬度切片。 lookup_table (vtkLookupTable, optional): 用于给切片着色的查找表。 scalar_array_name (str, optional): 要用于着色的标量数组的名称。 """ # 确保 data_to_slice 是 vtkUnstructuredGrid 对象 if not isinstance(data_to_slice, vtk.vtkDataSet): # vtkUnstructuredGrid 是 vtkDataSet 的子类 print(f"警告: 输入数据类型不是 vtkDataSet 的子类,而是 {type(data_to_slice)}") if hasattr(data_to_slice, 'GetOutput') and isinstance(data_to_slice.GetOutput(), vtk.vtkDataSet): data_to_slice = data_to_slice.GetOutput() elif hasattr(data_to_slice, 'GetProducer') and hasattr(data_to_slice.GetProducer(), 'GetOutput') and \ isinstance(data_to_slice.GetProducer().GetOutput(), vtk.vtkDataSet): data_to_slice.GetProducer().Update() #确保 filter 执行 data_to_slice = data_to_slice.GetProducer().GetOutput() else: print("无法处理输入数据进行切片。") return None if not isinstance(data_to_slice, vtk.vtkUnstructuredGrid): print(f"最终处理的数据类型仍不是 vtkUnstructuredGrid,而是 {type(data_to_slice)},尝试继续...") plane = vtk.vtkPlane() angle_radians = math.radians(angle_degrees) if slice_type.lower() == "longitude": nx = math.sin(angle_radians) ny = -math.cos(angle_radians) plane.SetOrigin(0, 0, 0) plane.SetNormal(nx, ny, 0) elif slice_type.lower() == "latitude": plane.SetOrigin(0, 0, earth_radius * math.sin(angle_radians)) plane.SetNormal(0, 0, 1) else: raise ValueError("slice_type 必须是 'longitude' 或 'latitude'") cutter = vtk.vtkCutter() cutter.SetCutFunction(plane) cutter.SetInputData(data_to_slice) print(data_to_slice) # cutter.SetValue(0, 0.0) # 对于 vtkPlane, 0.0 是默认值,可以不设 cutter.GenerateValues(1, 0.0, 0.0) # 生成一个等值面,其值为0.0(即平面) cutter.Update() # 执行切割 # 检查切割器是否有输出 slice_polydata = cutter.GetOutput() if not slice_polydata or slice_polydata.GetNumberOfPoints() == 0: print(f"警告: 切割器未能生成有效的 PolyData (类型: {slice_type}, 角度: {angle_degrees}). 切片将为空。") # print(f" Input to cutter has {data_to_slice.GetNumberOfPoints()} points, {data_to_slice.GetNumberOfCells()} cells.") # print(f" Plane Origin: {plane.GetOrigin()}, Normal: {plane.GetNormal()}") return None # 返回 None 表示无法创建 Actor print('test') print(lookup_table.GetRange()) slice_mapper = vtk.vtkPolyDataMapper() slice_mapper.SetInputConnection(cutter.GetOutputPort()) if lookup_table: slice_mapper.SetLookupTable(lookup_table) # 使用LookupTable的范围,这通常是全局数据的范围 slice_mapper.SetScalarRange(lookup_table.GetRange()) # print(lookup_table) # 关键: 告诉mapper使用哪个标量数组 if scalar_array_name: # 检查切片输出上是否存在此数组 if slice_polydata.GetPointData().HasArray(scalar_array_name): slice_mapper.SelectColorArray(scalar_array_name) print(f"切片Mapper已选择点标量数组: {scalar_array_name}") elif slice_polydata.GetCellData().HasArray(scalar_array_name): # cutter 通常生成点数据,但以防万一 slice_mapper.SelectColorArray(scalar_array_name) slice_mapper.SetScalarModeToUseCellData() print(f"切片Mapper已选择单元标量数组: {scalar_array_name}") else: # 如果指定的数组不在切片结果上,尝试用默认的(第一个) if slice_polydata.GetPointData().GetNumberOfArrays() > 0: default_array_name = slice_polydata.GetPointData().GetArrayName(0) slice_mapper.SelectColorArray(default_array_name) print(f"警告: 指定标量数组 '{scalar_array_name}' 未在切片结果的点数据中找到。使用默认数组: '{default_array_name}'") elif slice_polydata.GetCellData().GetNumberOfArrays() > 0: default_array_name = slice_polydata.GetCellData().GetArrayName(0) slice_mapper.SelectColorArray(default_array_name) slice_mapper.SetScalarModeToUseCellData() print(f"警告: 指定标量数组 '{scalar_array_name}' 未在切片结果的单元数据中找到。使用默认数组: '{default_array_name}'") else: print(f"警告: 指定标量数组 '{scalar_array_name}' 未在切片结果中找到,且无其他可用标量数组。") slice_mapper.ScalarVisibilityOff() # 没有数据,关闭标量着色 # vtkCutter 通常在其输出上生成点数据(插值自输入单元/点) slice_mapper.SetScalarModeToUsePointData() slice_mapper.ScalarVisibilityOn() # 调试信息:检查切片后的数据 print(f"Slice PolyData for {slice_type} {angle_degrees}:") print(f" Points: {slice_polydata.GetNumberOfPoints()}, Polys: {slice_polydata.GetNumberOfPolys()}") if slice_polydata.GetPointData().GetScalars(): print(f" Point Scalars Name: {slice_polydata.GetPointData().GetScalars().GetName()}") print(f" Point Scalars Range: {slice_polydata.GetPointData().GetScalars().GetRange()}") else: print(" No active point scalars on slice output.") for i in range(slice_polydata.GetPointData().GetNumberOfArrays()): print(f" Available Point Array {i}: {slice_polydata.GetPointData().GetArrayName(i)}") print(slice_polydata.GetPointData().GetScalars()) else: # 没有 lookup_table slice_mapper.ScalarVisibilityOff() slice_actor = vtk.vtkActor() slice_actor.SetMapper(slice_mapper) if not lookup_table or not slice_mapper.GetScalarVisibility(): slice_actor.GetProperty().SetColor(0.8, 0.1, 0.1) # 默认深红色,如果无标量着色 return slice_actor 我这个代码运行后显示No active point scalars on slice output,也即slice_polydata.GetPointData().GetScalars()为none是什么原因
06-05
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C++程序员Carea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值