In-Context Learning不是教知识,而是模式对齐:从5个示例到100个工业级样本的真相
2026/7/1 23:59:39
1、说明
本文只是教程内容的一小段,因博客字数限制,故进行拆分。主教程链接:vtk教程——逐行解析官网所有Python示例-CSDN博客
2、知识点纪要
本段代码主要涉及的有①vtkMultiThreshold工作原理,②vtkSelectEnclosedPoints 判断一个数据集 (polyData1) 中的点是否位于另一个封闭曲面 (polyData2) 的内部
import vtkmodules.vtkRenderingOpenGL2 from vtkmodules.vtkCommonColor import vtkNamedColors from vtkmodules.vtkCommonDataModel import vtkDataObject from vtkmodules.vtkCommonTransforms import vtkTransform from vtkmodules.vtkFiltersGeneral import vtkMultiThreshold, vtkTransformPolyDataFilter from vtkmodules.vtkFiltersModeling import vtkSelectEnclosedPoints from vtkmodules.vtkIOGeometry import ( vtkBYUReader, vtkOBJReader, vtkSTLReader ) from vtkmodules.vtkIOLegacy import vtkPolyDataReader from vtkmodules.vtkIOPLY import vtkPLYReader from vtkmodules.vtkIOXML import vtkXMLPolyDataReader from vtkmodules.vtkRenderingCore import ( vtkActor, vtkDataSetMapper, vtkRenderWindow, vtkRenderWindowInteractor, vtkRenderer ) import os def ReadPolyData(file_name): path, extension = os.path.splitext(file_name) extension = extension.lower() if extension == '.ply': reader = vtkPLYReader() reader.SetFileName(file_name) reader.Update() poly_data = reader.GetOutput() elif extension == '.vtp': reader = vtkXMLPolyDataReader() reader.SetFileName(file_name) reader.Update() poly_data = reader.GetOutput() elif extension == '.obj': reader = vtkOBJReader() reader.SetFileName(file_name) reader.Update() poly_data = reader.GetOutput() elif extension == '.stl': reader = vtkSTLReader() reader.SetFileName(file_name) reader.Update() poly_data = reader.GetOutput() elif extension == '.vtk': reader = vtkPolyDataReader() reader.SetFileName(file_name) reader.Update() poly_data = reader.GetOutput() elif extension == '.g': reader = vtkBYUReader() reader.SetGeometryFileName(file_name) reader.Update() poly_data = reader.GetOutput() else: # Return a None if the extension is unknown. poly_data = None return poly_data def main(): fn1 = "Data/cow.g" fn2 = 0 polyData1 = ReadPolyData(fn1) # 根据polyData1进行旋转得到polyData2 center = polyData1.GetCenter() transform = vtkTransform() transform.Translate(center[0], center[1], center[2]) transform.RotateY(90.0) transform.Translate(-center[0], -center[1], -center[2]) transformPD = vtkTransformPolyDataFilter() transformPD.SetTransform(transform) transformPD.SetInputData(polyData1) transformPD.Update() polyData2 = transformPD.GetOutput() """ vtkSelectEnclosedPoints 判断一个数据集 (polyData1) 中的点是否位于另一个封闭曲面 (polyData2) 的内部 """ select = vtkSelectEnclosedPoints() """ SetInputData 设置输入数据集。这个数据集包含你想要进行判断的点。 """ select.SetInputData(polyData1) """ SetSurfaceData 设置参考曲面。这个数据集必须是一个封闭的、流形的多边形网格 """ select.SetSurfaceData(polyData2) """ vtkMultiThreshold 是 VTK 里一个 阈值过滤器 (threshold filter) 它的特点是 可以在一次操作里设置多个阈值条件,并根据这些条件把输入数据分成多个输出结果 普通的 vtkThreshold 只能设置一个阈值范围,比如提取标量在 [100, 200] 之间的单元格。 vtkMultiThreshold 则可以定义 多个规则,一次性生成 多个子数据集,省去了重复调用多个 vtkThreshold 的麻烦 工作原理: 你给它输入一个 数据集 (vtkDataSet),比如 vtkUnstructuredGrid 或 vtkImageData。 你定义多个阈值条件,比如: 规则 1:提取标量 < 50 规则 2:提取 50 ≤ 标量 < 100 规则 3:提取 标量 ≥ 100 它会输出多个数据集,每个对应一个规则。 """ threshold = vtkMultiThreshold() """ AddBandpassIntervalSet 作用是定义一个过滤规则,用于从数据中提取出特定范围内的单元(cells) 这段代码的具体含义是: threshold.AddBandpassIntervalSet(): 调用 vtkMultiThreshold 过滤器的这个方法,来创建一个“通带”区间集,即只保留满足特定条件的单元。 0, 0: 定义了数据值的范围。这里表示数据值必须等于 0。 vtkDataObject.FIELD_ASSOCIATION_POINTS: 指定要检查的数据是点数据(point data)。 'SelectedPoints': 指定要检查的数据数组的名称。这是 vtkSelectEnclosedPoints 过滤器在前面步骤中创建的那个数组。 0, 1: 定义了一个单元中点值满足条件的数量范围。这里表示,要被选中的单元,其所有点(0 到 1)的 'SelectedPoints' 值都必须在前面定义的 [0, 0] 范围内。 """ outsideId = threshold.AddBandpassIntervalSet(0, 0, # 区间范围:下限=0,上限=0 vtkDataObject.FIELD_ASSOCIATION_POINTS, # 作用在点数据上 "SelectedPoints", # 要筛选的数组名字 0, 1) # includeLower=0(不包含下界),includeUpper=1(包含上界) """ 具体含义 0, 0 → 选取 "SelectedPoints" 数组值在 [0, 0] 之间的点,也就是值恰好等于 0 的点。 (因为 vtkSelectEnclosedPoints 的 "SelectedPoints" 标量:内部点 = 1 外部点 = 0) vtkDataObject.FIELD_ASSOCIATION_POINTS → 指定这个筛选条件是作用在 点数据 (point data) 上,而不是单元(cell data)。 "SelectedPoints" → 要筛选的数组名字,就是 vtkSelectEnclosedPoints 生成的标量数组。 在这段代码里,它之所以是这个名字,是因为 vtkSelectEnclosedPoints 默认就会生成一个标量数组,名字叫 "SelectedPoints" 如果不知道数组名字,可以先查看数组里有哪些数组 pointData = polydata.GetPointData() for i in range(pointData.GetNumberOfArrays()): print(pointData.GetArrayName(i)) 单元数据就是下面这样写 cellData = polydata.GetCellData() for i in range(cellData.GetNumberOfArrays()): print(cellData.GetArrayName(i)) component = 0 指定数组的第几个分量(例如 0 = x, 1 = y, 2 = z) 如果数组是标量,就写 0 allScalars = 1 当数组有多个分量时,是否要求所有分量都满足区间条件 0 → 只检查指定的 component 分量 1 → 要求数组的所有分量都在 [xmin, xmax] 内 上边界和下边界就是第0和第1个索引所代表的两个数 所以这里实际上是筛选出 "SelectedPoints" == 0 的点。 返回值 outsideId 返回的是这个阈值区间的 ID,可以用来后续控制(比如启用/禁用某个条件) """ insideId = threshold.AddBandpassIntervalSet(1, 1, vtkDataObject.FIELD_ASSOCIATION_POINTS, "SelectedPoints", 0, 1) """ AddIntervalSet 寻找那些至少有一个点在内部(值1),同时至少有一个点在外部(值0)的单元。这些单元恰好就是位于边界上的单元 0, 1: 定义了数据值范围。这个区间是 [0, 1],表示所有值为 0 或 1 的点都符合条件 OPEN参数:定义了区间的开闭类型,所以 [0, 1] 在这里实际上指的是所有大于 0 且小于 1 的值。但是,由于我们前面 vtkSelectEnclosedPoints 过滤器生成的 'SelectedPoints' 数组值只有 0 和 1,所以这里的 OPEN 会使我们定义的规则变得特殊 0, 0:当与 vtkMultiThreshold.OPEN, vtkMultiThreshold.OPEN 结合使用时,它会检查一个单元中既有值在 0-1 范围内的点(即 0 或 1),又有值不在 0-1 范围内的点。在这里,它用来捕捉那些**既有值为 0 的点(外部),又有值为 1 的点(内部)**的单元 """ borderId = threshold.AddIntervalSet(0, 1, vtkMultiThreshold.OPEN, vtkMultiThreshold.OPEN, vtkDataObject.FIELD_ASSOCIATION_POINTS, 'SelectedPoints', 0, 0) threshold.SetInputConnection(select.GetOutputPort()) """ OutputSet 设置最终要输出的数据集 """ threshold.OutputSet(outsideId) threshold.OutputSet(insideId) threshold.OutputSet(borderId) threshold.Update() colors = vtkNamedColors() outsideColor = colors.GetColor3d('Crimson') insideColor = colors.GetColor3d('Banana') borderColor = colors.GetColor3d('Mint') surfaceColor = colors.GetColor3d('Peacock') backgroundColor = colors.GetColor3d('Silver') outsideMapper = vtkDataSetMapper() outsideMapper.SetInputData(threshold.GetOutput().GetBlock(outsideId).GetBlock(0)) outsideMapper.ScalarVisibilityOff() outsideActor = vtkActor() outsideActor.SetMapper(outsideMapper) outsideActor.GetProperty().SetDiffuseColor(outsideColor) outsideActor.GetProperty().SetSpecular(.6) outsideActor.GetProperty().SetSpecularPower(30) insideMapper = vtkDataSetMapper() insideMapper.SetInputData(threshold.GetOutput().GetBlock(insideId).GetBlock(0)) insideMapper.ScalarVisibilityOff() insideActor = vtkActor() insideActor.SetMapper(insideMapper) insideActor.GetProperty().SetDiffuseColor(insideColor) insideActor.GetProperty().SetSpecular(.6) insideActor.GetProperty().SetSpecularPower(30) insideActor.GetProperty().EdgeVisibilityOn() borderMapper = vtkDataSetMapper() borderMapper.SetInputData(threshold.GetOutput().GetBlock(borderId).GetBlock(0)) borderMapper.ScalarVisibilityOff() borderActor = vtkActor() borderActor.SetMapper(borderMapper) borderActor.GetProperty().SetDiffuseColor(borderColor) borderActor.GetProperty().SetSpecular(.6) borderActor.GetProperty().SetSpecularPower(30) borderActor.GetProperty().EdgeVisibilityOn() surfaceMapper = vtkDataSetMapper() surfaceMapper.SetInputData(polyData2) surfaceMapper.ScalarVisibilityOff() surfaceActor = vtkActor() surfaceActor.SetMapper(surfaceMapper) surfaceActor.GetProperty().SetDiffuseColor(surfaceColor) surfaceActor.GetProperty().SetOpacity(.1) renderer = vtkRenderer() renderWindow = vtkRenderWindow() renderWindow.AddRenderer(renderer) renderWindow.SetSize(640, 480) renderWindowInteractor = vtkRenderWindowInteractor() renderWindowInteractor.SetRenderWindow(renderWindow) renderer.SetBackground(backgroundColor) renderer.UseHiddenLineRemovalOn() renderer.AddActor(surfaceActor) renderer.AddActor(outsideActor) renderer.AddActor(insideActor) renderer.AddActor(borderActor) renderWindow.SetWindowName('CellsInsideObject') renderWindow.Render() renderer.GetActiveCamera().Azimuth(30) renderer.GetActiveCamera().Elevation(30) renderer.GetActiveCamera().Dolly(1.25) renderWindow.Render() renderWindowInteractor.Start() if __name__ == '__main__': main()