You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于vtkPolydata的多高程温度分布切片绘制优化

问题描述

我有一份vtkPolydata数据,包含网格顶点的3D坐标,以及存储为点场数据的各点Temperature值。我想要绘制不同高程处的温度分布,已经构建了处理管线并获取到了所需切片,但渲染后显示的是散点图(放大后存在空白区域)。我觉得需要通过插值或创建等高线来解决,但查了很久资料都没头绪,求帮助。

用户提供的原始代码:

import vtk
from vtk.util import numpy_support
import numpy as np

# Load vtkPolydata function
def loadvtp(fname):
    reader = vtk.vtkXMLPolyDataReader()
    reader.SetFileName(fname)
    reader.Update()
    data=reader.GetOutput()
    return data

# Load vtkPolydata
polydata=loadvtp("TestPolydata.vtp")

# Set the elevation at which data need to be plotted
ele=12

# %% Clip polydata based on the elevation
# Create plane in +Z to cut the polydata below elevation
plane = vtk.vtkPlane()
plane.SetOrigin(0, 0, ele)
plane.SetNormal(0, 0, 1)

# create polydata clipper
clipper = vtk.vtkClipPolyData()
clipper.SetInputData(polydata)
clipper.SetClipFunction(plane)
clipper.Update()

out_data=clipper.GetOutput()

# Create plane in -Z to cut the polydata above elevation
plane = vtk.vtkPlane()
plane.SetOrigin(0, 0, ele+0.5)
plane.SetNormal(0, 0, -1)
clipper = vtk.vtkClipPolyData()
clipper.SetInputData(out_data)
clipper.SetClipFunction(plane)
clipper.Update()

# Cliped polydata
sampled_data=clipper.GetOutput()

# Get the "Temperature" Array from the polydata
point_scalars = sampled_data.GetPointData().GetArray("Temperature")

# Create a lookup table to map the point field data to colors
lut = vtk.vtkLookupTable()
lut.SetNumberOfTableValues(2)
lut.SetTableValue(0, 1, 0, 0, 1) # red
lut.SetTableValue(1, 0, 1, 0, 1) # green
lut.Build()

# Create a mapper and actor to display the cliped plane
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(clipper.GetOutputPort())
mapper.SetScalarModeToUsePointFieldData()
mapper.ScalarVisibilityOn()
mapper.SetColorModeToMapScalars()
mapper.SelectColorArray(0)
mapper.SetLookupTable(lut)
mapper.SetScalarRange(point_scalars.GetRange())

actor = vtk.vtkActor()
actor.SetMapper(mapper)

# Create the RenderWindow, Renderer
colors = vtk.vtkNamedColors()

ren1 = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren1)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

ren1.AddActor(actor)

ren1.SetBackground(colors.GetColor3d('Gainsboro'))
renWin.SetSize(650, 650)
renWin.SetWindowName('Test')

style = vtk.vtkInteractorStyleTrackballCamera()
iren.SetInteractorStyle(style)

ren1.TwoSidedLightingOff()

ren1.ResetCamera()

renWin.Render()
iren.Start()

解决方案

问题核心是:直接渲染剪切后的离散点集,没有构建连续的网格面,导致呈现散点状。以下是两种可行的解决方法:

方案一:生成等高线(适合展示温度沿轮廓的分布)

直接基于原始数据在指定高程生成等高线,同时保留温度值映射:

import vtk
from vtk.util import numpy_support
import numpy as np

def loadvtp(fname):
    reader = vtk.vtkXMLPolyDataReader()
    reader.SetFileName(fname)
    reader.Update()
    return reader.GetOutput()

polydata = loadvtp("TestPolydata.vtp")
ele = 12

# 生成指定高程的等高线(等值面)
contour_filter = vtk.vtkContourFilter()
contour_filter.SetInputData(polydata)
contour_filter.SetValue(0, ele)  # 0为索引,ele是目标Z轴高程
contour_filter.Update()

# 获取等高线数据,自动继承原始点的Temperature字段
contour_data = contour_filter.GetOutput()

# 创建渐变颜色映射表
lut = vtk.vtkLookupTable()
lut.SetHueRange(0.0, 0.3)  # 红到绿的渐变范围
lut.SetSaturationRange(1.0, 1.0)
lut.SetValueRange(1.0, 1.0)
lut.Build()

# 设置映射器
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(contour_data)
mapper.SetScalarModeToUsePointFieldData()
mapper.SelectColorArray("Temperature")  # 明确指定温度字段
mapper.SetLookupTable(lut)
mapper.SetScalarRange(contour_data.GetPointData().GetArray("Temperature").GetRange())

actor = vtk.vtkActor()
actor.SetMapper(mapper)

# 渲染窗口配置
colors = vtk.vtkNamedColors()
ren1 = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren1)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

ren1.AddActor(actor)
ren1.SetBackground(colors.GetColor3d('Gainsboro'))
renWin.SetSize(650, 650)
renWin.SetWindowName(f'Temperature Contour at Z={ele}')

style = vtk.vtkInteractorStyleTrackballCamera()
iren.SetInteractorStyle(style)

ren1.ResetCamera()
renWin.Render()
iren.Start()

方案二:构建插值曲面(解决空白区域,展示连续温度分布)

将切片点投影到XY平面,构建结构化网格后进行插值填充:

import vtk
from vtk.util import numpy_support
import numpy as np

def loadvtp(fname):
    reader = vtk.vtkXMLPolyDataReader()
    reader.SetFileName(fname)
    reader.Update()
    return reader.GetOutput()

polydata = loadvtp("TestPolydata.vtp")
ele = 12

# 提取指定高程附近的点
plane = vtk.vtkPlane()
plane.SetOrigin(0, 0, ele)
plane.SetNormal(0, 0, 1)
clipper = vtk.vtkClipPolyData()
clipper.SetInputData(polydata)
clipper.SetClipFunction(plane)
clipper.Update()

plane2 = vtk.vtkPlane()
plane2.SetOrigin(0, 0, ele+0.5)
plane2.SetNormal(0, 0, -1)
clipper2 = vtk.vtkClipPolyData()
clipper2.SetInputData(clipper.GetOutput())
clipper2.Update()
sampled_data = clipper2.GetOutput()

# 提取点坐标和温度数据
points = numpy_support.vtk_to_numpy(sampled_data.GetPoints().GetData())
temps = numpy_support.vtk_to_numpy(sampled_data.GetPointData().GetArray("Temperature"))

# 构建XY平面的规则结构化网格
x_min, x_max = points[:,0].min(), points[:,0].max()
y_min, y_max = points[:,1].min(), points[:,1].max()
x_steps = 50
y_steps = 50

grid_x, grid_y = np.meshgrid(np.linspace(x_min, x_max, x_steps), np.linspace(y_min, y_max, y_steps))
grid_points = np.column_stack((grid_x.flatten(), grid_y.flatten(), np.full(x_steps*y_steps, ele)))

# 创建vtk格式的网格点
vtk_grid_points = vtk.vtkPoints()
vtk_grid_points.SetData(numpy_support.numpy_to_vtk(grid_points, deep=True))

# 构建结构化网格
structured_grid = vtk.vtkStructuredGrid()
structured_grid.SetDimensions(x_steps, y_steps, 1)
structured_grid.SetPoints(vtk_grid_points)

# 线性插值填充温度数据
interpolator = vtk.vtkPointInterpolator()
interpolator.SetInputData(structured_grid)
interpolator.SetSourceData(sampled_data)
interpolator.SetKernel(vtk.vtkLinearKernel())
interpolator.Update()

# 设置颜色映射与渲染
lut = vtk.vtkLookupTable()
lut.SetHueRange(0.0, 0.3)
lut.Build()

mapper = vtk.vtkStructuredGridMapper()
mapper.SetInputData(interpolator.GetOutput())
mapper.SetScalarModeToUsePointFieldData()
mapper.SelectColorArray("Temperature")
mapper.SetLookupTable(lut)
mapper.SetScalarRange(interpolator.GetOutput().GetPointData().GetArray("Temperature").GetRange())

actor = vtk.vtkActor()
actor.SetMapper(mapper)

# 渲染窗口配置
colors = vtk.vtkNamedColors()
ren1 = vtk.vtkRenderer()
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren1)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

ren1.AddActor(actor)
ren1.SetBackground(colors.GetColor3d('Gainsboro'))
renWin.SetSize(650, 650)
renWin.SetWindowName(f'Interpolated Temperature Surface at Z={ele}')

style = vtk.vtkInteractorStyleTrackballCamera()
iren.SetInteractorStyle(style)

ren1.ResetCamera()
renWin.Render()
iren.Start()

关键说明

  1. 方案一直接基于原始网格生成等高线,保留数据精度,适合展示温度沿轮廓的变化;
  2. 方案二通过插值生成连续曲面,彻底解决空白区域问题,适合查看整个切片的温度渐变;
  3. 两种方案都明确指定了SelectColorArray("Temperature"),避免索引错误,同时优化了颜色映射表,让温度渐变更自然。

内容的提问来源于stack exchange,提问作者Jish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 23:10:22