CellTypeSource

一:主要的知识点

1、说明

本文只是教程内容的一小段,因博客字数限制,故进行拆分。主教程链接:https://mp.csdn.net/mp_blog/creation/editor/151804258

2、知识点纪要

本段代码主要涉及的有①vtkTessellatorFilter 的作用,②

二:代码及注释

python 复制代码
# !/usr/bin/env python
# -*- coding: utf-8 -*-

# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingFreeType
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import (
    vtkColorSeries,
    vtkNamedColors
)
from vtkmodules.vtkCommonCore import (
    vtkIntArray,
    vtkLookupTable,
    vtkMinimalStandardRandomSequence,
    vtkPoints
)
from vtkmodules.vtkCommonDataModel import (
    VTK_CUBIC_LINE,
    VTK_HEXAHEDRON,
    VTK_LINE,
    VTK_PYRAMID,
    VTK_QUAD,
    VTK_QUADRATIC_EDGE,
    VTK_QUADRATIC_HEXAHEDRON,
    VTK_QUADRATIC_PYRAMID,
    VTK_QUADRATIC_QUAD,
    VTK_QUADRATIC_TETRA,
    VTK_QUADRATIC_TRIANGLE,
    VTK_QUADRATIC_WEDGE,
    VTK_TETRA,
    VTK_TRIANGLE,
    VTK_WEDGE,
    vtkCellTypes
)
from vtkmodules.vtkFiltersGeneral import (
    vtkShrinkFilter,
    vtkTessellatorFilter
)
from vtkmodules.vtkFiltersSources import vtkCellTypeSource
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkActor2D,
    vtkDataSetMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer,
    vtkTextMapper,
    vtkTextProperty
)


def main():
    cellName = get_program_parameters()

    # Store the cell class names in a dictionary.
    cellMap = dict()
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_LINE)] = VTK_LINE
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_QUADRATIC_EDGE)] = VTK_QUADRATIC_EDGE
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_CUBIC_LINE)] = VTK_CUBIC_LINE

    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_TRIANGLE)] = VTK_TRIANGLE
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_QUADRATIC_TRIANGLE)] = VTK_QUADRATIC_TRIANGLE
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_QUAD)] = VTK_QUAD
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_QUADRATIC_QUAD)] = VTK_QUADRATIC_QUAD

    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_TETRA)] = VTK_TETRA
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_HEXAHEDRON)] = VTK_HEXAHEDRON
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_WEDGE)] = VTK_WEDGE
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_PYRAMID)] = VTK_PYRAMID
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_QUADRATIC_WEDGE)] = VTK_QUADRATIC_WEDGE
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_QUADRATIC_PYRAMID)] = VTK_QUADRATIC_PYRAMID
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_QUADRATIC_HEXAHEDRON)] = VTK_QUADRATIC_HEXAHEDRON
    cellMap[vtkCellTypes.GetClassNameFromTypeId(VTK_QUADRATIC_TETRA)] = VTK_QUADRATIC_TETRA

    if cellName not in cellMap:
        print('Cell type ', cellName, ' is not supported.')
        return
    source = vtkCellTypeSource()
    source.SetCellType(cellMap[cellName])
    source.Update()
    print('Cell: ', cellName)

    originalPoints = source.GetOutput().GetPoints()
    points = vtkPoints()
    points.SetNumberOfPoints(source.GetOutput().GetNumberOfPoints())
    rng = vtkMinimalStandardRandomSequence()
    rng.SetSeed(5070)  # for testing
    for i in range(0, points.GetNumberOfPoints()):
        perturbation = [0.0] * 3
        for j in range(0, 3):
            rng.Next()
            perturbation[j] = rng.GetRangeValue(-0.1, 0.1)
        currentPoint = [0.0] * 3
        originalPoints.GetPoint(i, currentPoint)
        points.SetPoint(i, currentPoint[0] + perturbation[0],
                        currentPoint[1] + perturbation[1],
                        currentPoint[2] + perturbation[2])
    source.GetOutput().SetPoints(points)

    """
    VTK 数据集中的每个单元格(cell)分配一个唯一的 ID,并将其作为单元格数据(cell data)
    附加到数据集中,以便后续可以根据这些 ID 进行着色或处理
    
    """
    numCells = source.GetOutput().GetNumberOfCells()
    print('Number of cells: ', numCells)
    idArray = vtkIntArray()  # 创建int数组,用来存储和保存每个单元的ID
    idArray.SetNumberOfTuples(numCells)  # 为数组分配内存空间
    for i in range(0, numCells):
        # 在数组的第 i 个位置插入整数 i + 1。这确保了每个单元格都有一个从 1 到 numCells 的唯一 ID
        idArray.InsertTuple1(i, i + 1)
    idArray.SetName('Ids') # 赋予idArray一个名称
    """
    将 idArray 作为单元格数据附加到数据集中
    VTK 数据集分为点数据(PointData)和单元格数据(CellData)
    将 ID 作为 CellData 意味着每个 ID 都与一个单元格相关联
    """
    source.GetOutput().GetCellData().AddArray(idArray)
    """
    这行代码将刚刚添加的 'Ids' 数组设置为活动标量(active scalars)。
    在 VTK 中,"标量"通常是用来着色的数据。通过将 Ids 设置为活动标量,
    你在告诉 vtkDataSetMapper 或其他处理单元格数据的过滤器:
    "请使用这个名为 'Ids' 的数组来获取每个单元格的颜色或数值"
    """
    source.GetOutput().GetCellData().SetActiveScalars('Ids')

    shrink = vtkShrinkFilter()
    shrink.SetInputConnection(source.GetOutputPort())
    shrink.SetShrinkFactor(.8)

    """
    vtkTessellatorFilter 是 VTK 中的一个细分过滤器,它的作用是将复杂或高阶的几何单元格分解成更简单、更低阶的单元格。
    你可以把它想象成一个"几何体分解器",它能把一个复杂的形状(比如一个扭曲的四面体)转换成许多小的、规则的形状(比如许多小的、平直的三角形)。
    什么是高阶单元格?
    VTK 中的单元格可以是线性的(由直边构成)或高阶的(由曲线或曲面构成)。例如:
    线性:vtkTetra(由4个平面三角形构成)、vtkLine(由2个点构成)。
    高阶:vtkQuadraticTetra(由弯曲的边和面构成)、vtkCubicLine(由一条曲线构成)。
    高阶单元格可以更精确地表示复杂的、弯曲的几何形状,但许多图形硬件和渲染算法只能直接处理简单的线性单元格(如三角形和四边形)。
    vtkTessellatorFilter 的作用
    vtkTessellatorFilter 的任务就是解决这个问题:
    它接收一个包含高阶单元格的 VTK 数据集作为输入。
    它根据你设定的细分级别,将每个高阶单元格分解成一系列小的、线性的单元格。
    它输出一个新的 VTK 数据集,这个数据集只包含这些简单的、可渲染的线性单元格。
    例如,如果你给它一个 vtkQuadraticTetra(二次四面体),它会将其分解成多个 vtkTetra(线性四面体)。
    为什么需要它?
    渲染:如前所述,大多数图形管线无法直接渲染高阶几何体,所以需要通过细分将其转换为简单的三角形或四边形。
    计算:许多算法,例如表面积或体积计算,需要简单、线性的单元格才能高效地工作。
    总之,vtkTessellatorFilter 是 VTK 管道中一个非常重要的工具,它弥合了高阶复杂几何和低阶高效计算之间的差距。
    """
    tessellate = vtkTessellatorFilter()
    tessellate.SetInputConnection(shrink.GetOutputPort())
    tessellate.SetMaximumNumberOfSubdivisions(3)

    """
    创建了一个查找表实例。查找表是 VTK 中一个核心的概念,它的作用是将数据值映射到颜色。
    你可以将它看作一个"字典"或"表格",它能将一个数值(如 1、2、3)转换成一个特定的颜色(如红色、蓝色、绿色)
    """
    lut = vtkLookupTable()
    """
    这里创建了一个颜色系列实例。vtkColorSeries 提供了多套经过专业设计的颜色方案,
    它们能让你的可视化效果更专业、更容易理解。你不需要自己去选择颜色
    """
    colorSeries = vtkColorSeries()
    """
    这行代码选择了特定的颜色方案。BREWER_QUALITATIVE_SET3 是一种定性颜色方案,
    它包含了一组颜色,这些颜色彼此之间易于区分,但没有内在的顺序。
    """
    seriesEnum = colorSeries.BREWER_QUALITATIVE_SET3
    """
    将选择的颜色方案应用到 colorSeries 对象上
    """
    colorSeries.SetColorScheme(seriesEnum)
    # 将前面选定的颜色方案加载到查找表中
    colorSeries.BuildLookupTable(lut, colorSeries.ORDINAL)

    # Fill in a few known colors, the rest will be generated if needed.
    colors = vtkNamedColors()

    # Create a mapper and actor.
    mapper = vtkDataSetMapper()
    #mapper.SetInputConnection(source.GetOutputPort())
    #mapper.SetInputConnection(shrink.GetOutputPort())
    """
    设置了标量数据的范围
    这告诉 VTK,你的数据值在这个范围内变化,查找表(lookup table)会根据这个范围来正确地映射颜色
    """
    mapper.SetScalarRange(0, numCells + 1)
    # 根据颜色映射表,将具体数值转换为颜色
    mapper.SetLookupTable(lut)
    # 在着色时,应该使用单元格数据
    mapper.SetScalarModeToUseCellData()
    """
    这是一个用于解决**共面拓扑(coincident topology)**问题的技术
    当两个面或多边形在三维空间中完全重合时,渲染引擎可能会在它们之间来回闪烁,这被称为"Z-fighting"
    PolygonOffset 是一种解决方案,它会稍微偏移其中一个面,使其不再完全重合,从而消除闪烁问题。这通常用于渲染带有边框的多边形,以确保边框线不会与面闪烁
    """
    mapper.SetResolveCoincidentTopologyToPolygonOffset()
    if (source.GetCellType() == VTK_QUADRATIC_PYRAMID or
            source.GetCellType() == VTK_QUADRATIC_WEDGE):
        mapper.SetInputConnection(shrink.GetOutputPort())
    else:
        mapper.SetInputConnection(tessellate.GetOutputPort())
    actor = vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().EdgeVisibilityOn()
    #  actor.GetProperty().SetLineWidth(3)

    textProperty = vtkTextProperty()
    textProperty.SetFontSize(20)
    textProperty.SetJustificationToCentered()
    textProperty.SetColor(colors.GetColor3d('Lamp_Black'))

    textMapper = vtkTextMapper()
    textMapper.SetInput(cellName)
    textMapper.SetTextProperty(textProperty)

    textActor = vtkActor2D()
    textActor.SetMapper(textMapper)
    textActor.SetPosition(320, 20)

    # Create a renderer, render window, and interactor.
    renderer = vtkRenderer()
    renderWindow = vtkRenderWindow()
    renderWindow.SetWindowName('CellTypeSource')
    renderWindow.AddRenderer(renderer)
    renderWindowInteractor = vtkRenderWindowInteractor()
    renderWindowInteractor.SetRenderWindow(renderWindow)

    # Add the actors to the scene.
    renderer.AddViewProp(textActor)
    renderer.AddActor(actor)
    renderer.SetBackground(colors.GetColor3d('Silver'))

    renderer.ResetCamera()
    renderer.GetActiveCamera().Azimuth(30)
    renderer.GetActiveCamera().Elevation(30)
    renderer.ResetCameraClippingRange()

    # Render and interact.
    renderWindow.SetSize(640, 480)
    renderWindow.Render()
    renderWindowInteractor.Start()


def get_program_parameters():
    import argparse
    description = 'Cell Type Source.'
    epilogue = '''
    You can supply an optional argument consisting of a vtkCell name e.g: vtkTriangle.
    The default is vtkTetra.
    '''
    parser = argparse.ArgumentParser(description=description, epilog=epilogue,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('cell_name', nargs='?', const='vtkTetra', default='vtkWedge', type=str, help='The cell name.')
    args = parser.parse_args()
    return args.cell_name


if __name__ == '__main__':
    main()
相关推荐
q***57741 小时前
Python中的简单爬虫
爬虫·python·信息可视化
韩立学长1 小时前
【开题答辩实录分享】以《粤港澳大湾区活动数据可视化分析系统》为例进行答辩实录分享
python·信息可视化·flask
陈辛chenxin2 小时前
【接口测试】Postman教程
python·selenium·测试工具·postman·可用性测试
程序员小远2 小时前
Postman详解
自动化测试·软件测试·python·测试工具·测试用例·接口测试·postman
钮钴禄·爱因斯晨3 小时前
Python常见的文件操作
android·数据库·python
AI小云3 小时前
【数据操作与可视化】Pandas数据处理-Series数据结构
开发语言·数据结构·python·numpy·pandas
Python大数据分析@3 小时前
如何理解Python中的yield用法?
python
源码之家4 小时前
基于python新闻数据分析可视化系统 Hadoop 新闻平台 爬虫 情感分析 舆情分析 可视化 Django框架 vue框架 机器学习 大数据毕业设计✅
大数据·爬虫·python·数据分析·毕业设计·情感分析·新闻
IT油腻大叔4 小时前
DeepSeek-多层注意力计算机制理解
python·深度学习·机器学习