GradientBackground 比较不同类型的背景渐变着色模式与坐标转换

一:主要的知识点

1、说明

本文只是教程内容的一小段,因博客字数限制,故进行拆分。主教程链接:vtk教程------逐行解析官网所有Python示例-CSDN博客

2、知识点纪要

本段代码主要涉及的有①背景渐变着色的区分,②vtkCoordinate坐标系统的转化

二:代码及注释

python 复制代码
from vtkmodules.vtkFiltersSources import vtkConeSource, vtkSphereSource
from vtkmodules.vtkIOLegacy import vtkPolyDataReader
from vtkmodules.vtkIOXML import vtkXMLPolyDataReader
from vtkmodules.vtkIOGeometry import vtkOBJReader, vtkBYUReader, vtkSTLReader
from vtkmodules.vtkIOPLY import vtkPLYReader
from vtkmodules.vtkRenderingCore import vtkActor, vtkRenderer, vtkRenderWindow, vtkRenderWindowInteractor, \
    vtkPolyDataMapper, vtkTextMapper, vtkTextProperty, vtkViewport, vtkCoordinate, vtkActor2D, vtkPolyDataMapper2D
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkPoints
from vtkmodules.vtkCommonDataModel import (
    vtkCellArray,
    vtkPolyData,
    vtkPolyLine
)


def read_polydata_(path):
    poly_data = vtkPolyData()

    if path is None:
        # Default to a cone if the path is empty.
        source = vtkConeSource()
        source.SetResolution(25)
        source.SetDirection(0, 1, 0)
        source.SetHeight(1)
        source.Update()
        poly_data.DeepCopy(source.GetOutput())
        return poly_data

    valid_suffixes = ['.g', '.obj', '.stl', '.ply', '.vtk', '.vtp']
    ext = path.suffix.lower()
    if path.suffix not in valid_suffixes:
        print('Warning:', path, 'unknown extension, using a sphere instead.')
        source = vtkSphereSource()
        source.SetPhiResolution(50)
        source.SetThetaResolution(50)
        source.Update()
        poly_data.DeepCopy(source.GetOutput())
    else:
        if ext == '.ply':
            reader = vtkPLYReader()
            reader.SetFileName(file_name)
            reader.Update()
            poly_data.DeepCopy(reader.GetOutput())
        elif ext == '.vtp':
            reader = vtkXMLPolyDataReader()
            reader.SetFileName(file_name)
            reader.Update()
            poly_data.DeepCopy(reader.GetOutput())
        elif ext == '.obj':
            reader = vtkOBJReader()
            reader.SetFileName(file_name)
            reader.Update()
            poly_data.DeepCopy(reader.GetOutput())
        elif ext == '.stl':
            reader = vtkSTLReader()
            reader.SetFileName(file_name)
            reader.Update()
            poly_data.DeepCopy(reader.GetOutput())
        elif ext == '.vtk':
            reader = vtkPolyDataReader()
            reader.SetFileName(file_name)
            reader.Update()
            poly_data.DeepCopy(reader.GetOutput())
        elif ext == '.g':
            reader = vtkBYUReader()
            reader.SetGeometryFileName(file_name)
            reader.Update()
            poly_data.DeepCopy(reader.GetOutput())

    return poly_data


def viewport_border(renderer, sides, border_color, border_width):
    """
    在给定的 3D渲染器(vtkRenderer)对应的 2D视口(Viewport)周围绘制一个用户自定义颜色和宽度的边框
    """
    colors = vtkNamedColors()

    """
    先定义点的坐标
    这里的坐标(x, y)是在标准化视口坐标系中定义的,范围从0到1
    (0, 0)代表视口的左下角,(1, 1)代表视口的右上角。这四个点定义了视口区域的四个角
    """
    points = vtkPoints()
    points.SetNumberOfPoints(4)
    points.InsertPoint(0, 1, 1, 0)
    points.InsertPoint(1, 0, 1, 0)
    points.InsertPoint(2, 0, 0, 0)
    points.InsertPoint(3, 1, 0, 0)

    cells = vtkCellArray()
    cells.Initialize()

    if sides[0]:
        # Top
        top = vtkPolyLine()
        top.GetPointIds().SetNumberOfIds(2)
        top.GetPointIds().SetId(0, 0)
        top.GetPointIds().SetId(1, 1)
        cells.InsertNextCell(top)
    if sides[1]:
        # Left
        left = vtkPolyLine()
        left.GetPointIds().SetNumberOfIds(2)
        left.GetPointIds().SetId(0, 1)
        left.GetPointIds().SetId(1, 2)
        cells.InsertNextCell(left)
    if sides[2]:
        # Bottom
        bottom = vtkPolyLine()
        bottom.GetPointIds().SetNumberOfIds(2)
        bottom.GetPointIds().SetId(0, 2)
        bottom.GetPointIds().SetId(1, 3)
        cells.InsertNextCell(bottom)
    if sides[3]:
        # Right
        right = vtkPolyLine()
        right.GetPointIds().SetNumberOfIds(2)
        right.GetPointIds().SetId(0, 3)
        right.GetPointIds().SetId(1, 0)
        cells.InsertNextCell(right)

    poly = vtkPolyData()
    poly.Initialize()
    poly.SetPoints(points)
    poly.SetLines(cells)

    """
    vtkCoordinate 负责处理 不同坐标系统之间的坐标转换,特别是在渲染(Renderer)和显示(Display)过程中
    简单来说  vtkCoordinate就是用来表示并转换一个点在不同坐标系统中的位置
    vtk中常见的坐标系统
    名称       英文标识                     描述                       
   
    世界坐标     **World**                三维空间中物体的真实坐标(例如几何模型的点位置) 
    视图坐标     **View**                 相机变换后的坐标(相机坐标系)          
    规范化视口坐标  **Normalized Viewport**  渲染窗口中的归一化坐标,范围 [0,1]     
    视口坐标     **Viewport**             渲染窗口内的像素坐标(受相机投影影响)      
    显示坐标     **Display**              屏幕上的实际像素坐标(例如鼠标点击位置)     
    规范化显示坐标  **Normalized Display**   屏幕归一化坐标,范围 [0,1]         

    """
    coordinate = vtkCoordinate()
    coordinate.SetCoordinateSystemToNormalizedViewport()  # 设置 coordinate 的坐标系统为 Normalized Viewport(规范化视口坐标系)

    mapper = vtkPolyDataMapper2D()
    mapper.SetInputData(poly)
    mapper.SetTransformCoordinate(coordinate)

    actor = vtkActor2D()
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(colors.GetColor3d(border_color))

    actor.GetProperty().SetLineWidth(border_width)

    renderer.AddViewProp(actor)


def main():
    fp = None
    pd = read_polydata_(fp)

    ren_win = vtkRenderWindow()
    ren_win.SetWindowName('GradientBackground')

    iren = vtkRenderWindowInteractor()
    renderers = []

    modes = [
        vtkViewport.GradientModes.VTK_GRADIENT_VERTICAL,
        vtkViewport.GradientModes.VTK_GRADIENT_HORIZONTAL,
        vtkViewport.GradientModes.VTK_GRADIENT_RADIAL_VIEWPORT_FARTHEST_SIDE,
        vtkViewport.GradientModes.VTK_GRADIENT_RADIAL_VIEWPORT_FARTHEST_CORNER,
    ]
    """
    模式(Mode),描述,渐变方向
    VTK_GRADIENT_VERTICAL,垂直渐变,从底部 (SetBackground) 到顶部 (SetBackground2) 颜色过渡。
    VTK_GRADIENT_HORIZONTAL,水平渐变,从左侧 (SetBackground) 到右侧 (SetBackground2) 颜色过渡。
    VTK_GRADIENT_RADIAL_VIEWPORT_FARTHEST_SIDE,径向渐变(最远边),从中心 (SetBackground) 向视口最远的那条边进行径向扩散渐变,直到边缘变为 SetBackground2 的颜色。
    VTK_GRADIENT_RADIAL_VIEWPORT_FARTHEST_CORNER,径向渐变(最远角),从中心 (SetBackground) 向视口最远的那个角进行径向扩散渐变,直到角落变为 SetBackground2 的颜色。
    """

    colors = vtkNamedColors()

    mapper = vtkPolyDataMapper()
    mapper.SetInputData(pd)

    actor = vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(colors.GetColor3d('Honeydew'))
    actor.GetProperty().SetSpecular(0.3)
    actor.GetProperty().SetSpecularPower(60.0)

    ren_width = 640
    ren_height = 480

    xmins = [0.0, 0.5, 0.0, 0.5]
    ymins = [0.0, 0.0, 0.5, 0.5]
    xmaxs = [0.5, 1.0, 0.5, 1.0]
    ymaxs = [0.5, 0.5, 1.0, 1.0]

    bottom_color = colors.GetColor3d('Gold')
    top_color = colors.GetColor3d('OrangeRed')
    left_color = colors.GetColor3d('Gold')
    right_color = colors.GetColor3d('OrangeRed')
    center_color = colors.GetColor3d('Gold')
    side_color = colors.GetColor3d('OrangeRed')
    corner_color = colors.GetColor3d('OrangeRed')

    viewport_title = ["Vertical",
                      "Horizontal",
                      "Radial Farthest Side",
                      "Radial Farthest Corner",
                      ]

    text_property = vtkTextProperty()
    text_property.SetJustificationToCentered()
    text_property.SetFontSize(ren_height // 12)
    text_property.SetColor(colors.GetColor3d('MidnightBlue'))

    text_mappers = []
    text_actors = []

    lb = [False, True, True, False]
    lbr = [False, True, True, True]
    tlb = [True, True, True, False]
    tlbr = [True, True, True, True]
    border_color = 'DarkGreen'
    border_width = 4.0

    for i in range(0, 4):
        text_mappers.append(vtkTextMapper())
        text_mappers[i].SetInput(viewport_title[i])
        text_mappers[i].SetTextProperty(text_property)

        text_actors.append(vtkActor2D())
        text_actors[i].SetMapper(text_mappers[i])
        text_actors[i].SetPosition(ren_width / 2, 8)

        renderers.append(vtkRenderer())
        renderers[i].AddActor(text_actors[i])
        renderers[i].AddActor(actor)
        renderers[i].GradientBackgroundOn()
        renderers[i].SetGradientMode(modes[i])

        renderers[i].SetViewport(xmins[i], ymins[i], xmaxs[i], ymaxs[i])

        if i == 1:
            # Horizontal
            renderers[i].SetBackground(left_color)
            renderers[i].SetBackground2(right_color)
            viewport_border(renderers[i], lbr, border_color, border_width)
        elif i == 2:
            # Radial Farthest Side
            renderers[i].SetBackground(center_color)
            renderers[i].SetBackground2(side_color)
            viewport_border(renderers[i], tlb, border_color, border_width)
        elif i == 3:
            # Radial Farthest Corner
            renderers[i].SetBackground(center_color)
            renderers[i].SetBackground2(corner_color)
            viewport_border(renderers[i], tlbr, border_color, border_width)
        else:
            # Vertical
            renderers[i].SetBackground(bottom_color)
            renderers[i].SetBackground2(top_color)
            viewport_border(renderers[i], lb, border_color, border_width)
        ren_win.AddRenderer(renderers[i])
    ren_win.SetInteractor(iren)
    ren_win.Render()

    iren.Initialize()
    iren.UpdateSize(ren_width * 2, ren_height * 2)

    iren.Start()


if __name__ == '__main__':
    file_name = ""
    main()
相关推荐
用户70887690393838 分钟前
给传统 SaaS 增加 AI 能力:3个真实落地场景
python
卷无止境40 分钟前
FastAPI中间件全解析:请求处理链条上的隐形关卡
后端·python·fastapi
用户03321266636743 分钟前
使用 Python 将 HTML 内容添加到 PowerPoint 演示文稿中
python·html
看浪的路人44 分钟前
第4讲:MCP Client 开发——连接、发现、调用
windows·python·ai
Swift社区1 小时前
Python 开发环境怎么选?PyCharm、VS Code、Trae 谁更适合 AI 开发?
人工智能·python·pycharm
卷无止境1 小时前
聊聊Web开发里的流式数据 从原理到FastAPI实战
后端·python·fastapi
SMF19191 小时前
【PyCharm】让 PyCharm 使用 .venv 虚拟环境
ide·python·pycharm
修远客1 小时前
感知模块:Agent的眼睛和耳朵 — 三层降级策略让Agent永不"失明"
python·agent
circuitsosk1 小时前
Prompt Engineering进阶:面向复杂业务场景的模板化管理与动态注入策略
python·langchain·prompt·跨境电商·rag·上下文管理·动态注入
Livia要学习2 小时前
Python闭包
开发语言·jvm·python