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

使用vtkPolyDataEdgeConnectivityFilter时,如何直接获取区域生长后的边界边?

如何高效获取VTK区域增长后的边界边

问题描述

使用vtkPolyDataEdgeConnectivityFilter基于选定边分割网格,执行vtkSmallRegionGrow后,需要获取新区域的边界边以继续执行vtkLargeRegionGrow。目前通过Python手动遍历单元格和邻居提取边界边,执行时间过长,询问VTK是否有内置过滤器直接返回这些边。

环境:Python 3.12 + pyvista 0.44.1 + vtk 9.3.1

当前低效代码:

feature_edges = PolyData(mesh.points, lines=edges.reshape(-1))
f = vtkPolyDataEdgeConnectivityFilter()
f.SetExtractionModeToAllRegions()
f.SetColorRegions(True)
f.SetInputData(mesh)
f.BarrierEdgesOn()
f.SetBarrierEdges(True)
f.SetSourceData(feature_edges)
f.Update()
f.SetLargeRegionThreshold(sml_thr)
f.GrowSmallRegionsOn()
f.Update()
# 手动提取边界边,效率低下
f.SetSourceData(newborders(mesh))
f.SetLargeRegionThreshold(lrg_thr)
f.GrowLargeRegionsOn()
f.Update()


def newborders(mesh):
     edges = []
     for i in range(mesh.n_cells):
         for j in range(len(mesh.cell_neighbors(i,'edges'))):
              if mesh['RegionId'][i] != mesh['RegionId'][mesh.cell_neighbors(i,'edges')[j]]:
                  edge = np.intersect1d(mesh.get_cell(i).point_ids,mesh.get_cell(mesh.cell_neighbors(i,'edges')[j]).point_ids)
                  edges.append([2 , edge[0], edge[1]])
     return np.array(edges)

解决方案

可以使用VTK内置的vtkEdgeFlagFilter过滤器,它能基于单元格标量数组(此处为RegionId)高效标记并提取不同区域之间的边界边,完全替代手动遍历的低效逻辑。

优化步骤

  1. 执行完vtkSmallRegionGrow后,获取包含更新后RegionId的输出网格。
  2. 用vtkEdgeFlagFilter标记相邻单元格RegionId不同的边。
  3. 提取标记后的边界边,转换为PolyData格式作为后续操作的输入。

优化后的代码

import vtk
import pyvista as pv
import numpy as np

# 原有分割与小区域增长逻辑
feature_edges = pv.PolyData(mesh.points, lines=edges.reshape(-1))
f = vtk.vtkPolyDataEdgeConnectivityFilter()
f.SetExtractionModeToAllRegions()
f.SetColorRegions(True)
f.SetInputData(mesh)
f.BarrierEdgesOn()
f.SetBarrierEdges(True)
f.SetSourceData(feature_edges)
f.Update()

f.SetLargeRegionThreshold(sml_thr)
f.GrowSmallRegionsOn()
f.Update()

# 获取小区域增长后的网格
grown_mesh = pv.wrap(f.GetOutput())

# 用vtkEdgeFlagFilter标记区域边界边
edge_filter = vtk.vtkEdgeFlagFilter()
edge_filter.SetInputData(grown_mesh)
# 指定用于判断区域的单元格标量数组
edge_filter.SetInputArrayToProcess(0, 0, 0, vtk.vtkDataObject.FIELD_ASSOCIATION_CELLS, "RegionId")
edge_filter.SetBoundaryEdges(True)
edge_filter.Update()

# 筛选并提取边界边
edge_output = edge_filter.GetOutput()
edge_flags = edge_output.GetCellData().GetArray("EdgeFlags")
border_edge_ids = [i for i in range(edge_output.GetNumberOfCells()) if edge_flags.GetValue(i) == 1]

extractor = vtk.vtkExtractCells()
extractor.SetInputData(edge_output)
extractor.SetCellIds(vtk.vtkIdList.FromList(border_edge_ids))
extractor.Update()

border_edges_polydata = pv.wrap(extractor.GetOutput())

# 继续执行大区域增长
f.SetSourceData(border_edges_polydata)
f.SetLargeRegionThreshold(lrg_thr)
f.GrowLargeRegionsOn()
f.Update()

关键说明

  • vtkEdgeFlagFilter基于C++底层实现边的标记与筛选,避免了Python循环的性能开销,在处理大规模网格时效率提升显著。
  • 该过滤器会自动给边添加EdgeFlags数组,值为1的边即为不同区域之间的边界边,直接提取即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 00:05:03