天天看点

VTK演示回调的作用和实例

VTk通过数据流实现变信息为图形数据的。

数据流一般为:source—filter——mapper——actor——render——renderwindow——interactor。

#!/usr/bin/env python

"""
演示回调的使用。
"""

import vtk


def main():
    #  决定使用什么方法。
    use_function_callback = True

    colors = vtk.vtkNamedColors()

    # 创建渲染器、渲染窗口和渲染窗口交互器。
    ren = vtk.vtkRenderer()
    renWin = vtk.vtkRenderWindow()
    renWin.AddRenderer(ren)
    iren = vtk.vtkRenderWindowInteractor()
    iren.SetRenderWindow(renWin)

    # 使用一个圆锥作为源。
    source = vtk.vtkConeSource()
    source.SetCenter(0, 0, 0)
    # 设置圆锥的基本半径。
    source.SetRadius(1)
    # 使用黄金比例的高度。
    source.SetHeight(1.6180339887498948482)
    # 设置用来表示圆锥的面数。
    source.SetResolution(128)
    source.Update()

    # 管道
    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInputConnection(source.GetOutputPort())
    actor = vtk.vtkActor()
    actor.SetMapper(mapper)
    actor.GetProperty().SetColor(colors.GetColor3d("peacock"))
    # 照明
    #设置/获取环境照明系数
    actor.GetProperty().SetAmbient(0.3)
    # 设置 / 获取漫射照明系数。
    actor.GetProperty().SetDiffuse(0.0)
    # 设置/获取高光照明系数。
    actor.GetProperty().SetSpecular(1.0)
    # 设置/获取高光能量。
    actor.GetProperty().SetSpecularPower(20.0)

    # 获取上下文数据集的概要。
    # vtkOutlineFilter是一个过滤器,可生成任何数据集或复合数据集的线框轮廓。
    # 轮廓由数据集边界框的十二条边组成。存在用于生成面而不是线框轮廓的选项。
    outline = vtk.vtkOutlineFilter()
    outline.SetInputData(source.GetOutput())
    outlineMapper = vtk.vtkPolyDataMapper()
    outlineMapper.SetInputConnection(outline.GetOutputPort())
    outlineActor = vtk.vtkActor()
    # 轮廓线颜色
    outlineActor.GetProperty().SetColor(colors.GetColor3d("Black"))
    outlineActor.SetMapper(outlineMapper)

    # 添加演员到渲染器,设置背景和大小。
    ren.AddActor(actor)
    ren.AddActor(outlineActor)
    # 设置背景颜色
    ren.SetBackground(colors.GetColor3d("AliceBlue"))
    # 设置背景大小
    renWin.SetSize(512, 512)

    # 设置一个的相机位置。
    camera = vtk.vtkCamera()
    # 以世界坐标设置摄像机的位置
    camera.SetPosition(4.6, -2.0, 3.8)
    # 在世界坐标中设置照相机的焦距
    camera.SetFocalPoint(0.0, 0.0, 0.0)
    # 设置沿投影方向的远近裁剪平面位置
    camera.SetClippingRange(3.2, 10.2)
    # 设置摄像机的向上视图方向。
    camera.SetViewUp(0.3, 1.0, 0.13)
    # 指定这个渲染器使用的相机。
    ren.SetActiveCamera(camera)

    renWin.Render()
    renWin.SetWindowName("CallBack")

    # 设置一个坐标系,随着父图像一起旋转
    axes1 = MakeAxesActor()
    # 方向标记工具
    om1 = vtk.vtkOrientationMarkerWidget()
    # 设置标记
    om1.SetOrientationMarker(axes1)
    # 在视口的左下角。
    om1.SetViewport(0, 0, 0.2, 0.2)
    om1.SetInteractor(iren)
    om1.EnabledOn()
    om1.InteractiveOn()

    # 设置回调
    if use_function_callback:
        # 在触发事件时输出摄像机位置,所以添加了添加了活动摄像头作为属性。
        GetOrientation.cam = ren.GetActiveCamera()
        # 用观察的对象注册回调。
        iren.AddObserver('EndInteractionEvent', GetOrientation)
    else:
        # 将动态相机装入渲染窗口
        iren.AddObserver('EndInteractionEvent', OrientationObserver(ren.GetActiveCamera()))
        # Or:
        # observer = OrientationObserver(ren.GetActiveCamera())
        # iren.AddObserver('EndInteractionEvent', observer)

    iren.Initialize()
    iren.Start()


def GetOrientation(caller, ev):
    """
    打印出方向图。

    必须在调用函数中注册回调之前使用
        GetOrientation.cam = ren.GetActiveCamera()

    :param caller:
    :param ev: The event.
    :return:
    """
    # 演示谁调用了callback以及触发它的事件。
    # 打印类名
    print(caller.GetClassName(), "Event Id:", ev)
    # 打印相机方向。
    CameraOrientation(GetOrientation.cam)


class OrientationObserver(object):
    def __init__(self, cam):
        self.cam = cam

    def __call__(self, caller, ev):
        # Just do this to demonstrate who called callback and the event that triggered it.
        print(caller.GetClassName(), "Event Id:", ev)
        # Now print the camera orientation.
        CameraOrientation(self.cam)


def CameraOrientation(cam):
    fmt1 = "{:>15s}"
    fmt2 = "{:9.6g}"
    # map 创建一个迭代器,它使用来自每个迭代器的参数来计算函数。当最短的迭代结束时停止。
    print(fmt1.format("Position:"), ', '.join(map(fmt2.format, cam.GetPosition())))
    print(fmt1.format("Focal point:"), ', '.join(map(fmt2.format, cam.GetFocalPoint())))
    print(fmt1.format("Clipping range:"), ', '.join(map(fmt2.format, cam.GetClippingRange())))
    print(fmt1.format("View up:"), ', '.join(map(fmt2.format, cam.GetViewUp())))
    print(fmt1.format("Distance:"), fmt2.format(cam.GetDistance()))


def MakeAxesActor():
    axes = vtk.vtkAxesActor()
    axes.SetShaftTypeToCylinder()
    axes.SetXAxisLabelText('X')
    axes.SetYAxisLabelText('Y')
    axes.SetZAxisLabelText('Z')
    axes.SetTotalLength(1.0, 1.0, 1.0)
    axes.SetCylinderRadius(0.5 * axes.GetCylinderRadius())
    axes.SetConeRadius(1.025 * axes.GetConeRadius())
    axes.SetSphereRadius(1.5 * axes.GetSphereRadius())
    return axes


if __name__ == '__main__':
    main()
           

相机参考

https://blog.csdn.net/minmindianzi/article/details/84279290