在VTK中为vtkGlyph3D对象设置动画颜色

时间:2014-02-14 10:44:36

标签: python vtk

我想渲染固定数量的具有固定位置的球体,并随时间修改颜色。

我创建一个具有相应位置的vtkPolyData对象,然后创建一个vtkGlyph3D,其中vtkPolyData对象作为输入,vtkSphereSource对象作为源。 颜色存储在vtkPolyData对象的Scalars数组中。

目前我正在使用RepeatingTimer,我在vtkGlyph3D方法中反复设置execute对象的输入和来源。这似乎是一种非常低效的方法。有没有办法只更新vtkPolyData对象的Scalars数组中的颜色值? 显然只是更改数组值并调用Update对象的vtkGlyph3D方法不起作用。

import numpy as np
import vtk

class vtkTimerCallback():

    def __init__(self, tspan, radius, mapper, actor, glyph, polyData):
        self._tspan = tspan
        self._radius = radius
        self._mapper = mapper
        self._actor = actor
        self._glyph = glyph
        self._polyData = polyData
        self._timeIndex = 0

    def execute(self, obj, event):
        array = self._polyData.GetPointData().GetScalars()
        for i in xrange(coords.shape[0]):
            v = int(float(i) / coords.shape[0] * 255)
            if self._timeIndex % 2 == 0:
                red = 0
                green = 255 - v
                blue = v
            else:
                red = v
                green = 0
                blue = 255 - v
            array.InsertTuple3(i, red, green, blue)
        self._polyData.Update()    
        sphereSource = vtk.vtkSphereSource()
        sphereSource.SetRadius(self._radius)
        self._glyph.SetColorModeToColorByScalar()
        self._glyph.SetSource(sphereSource.GetOutput())
        self._glyph.SetInput(self._polyData)
        self._glyph.Update()
        self._mapper.SetInput(self._glyph.GetOutput())
        self._mapper.Update()

        self._timeIndex += 1
        if self._timeIndex >= self._tspan.shape[0]:
            self._timeIndex = 0
        iren = obj
        iren.GetRenderWindow().Render()

def viewData(coords, tspan, radius=0.1, interval=50):
    points = vtk.vtkPoints()
    points.SetNumberOfPoints(coords.shape[0])
    for i in xrange(coords.shape[0]):
        coord = coords[i, :]
        points.InsertPoint(i, coord[0], coord[1], coord[2])

    polyData = vtk.vtkPolyData()
    polyData.SetPoints(points)

    array = vtk.vtkUnsignedCharArray()
    array.SetName('colors')
    array.SetNumberOfComponents(3)
    array.SetNumberOfTuples(coords.shape[0])
    polyData.GetPointData().SetScalars(array)

    sphereSource = vtk.vtkSphereSource()
    sphereSource.SetRadius(radius)

    glyph = vtk.vtkGlyph3D()
    glyph.SetColorModeToColorByScalar()
    if vtk.VTK_MAJOR_VERSION <= 5:
        glyph.SetSource(sphereSource.GetOutput())
        glyph.SetInput(polyData)
    else:
        glyph.SetSourceConnection(sphereSource.GetOutputPort())
        glyph.SetInputData(polyData)
    glyph.ScalingOff()
    glyph.Update()

    #glyph.FillCellDataOn()

    # Create a mapper and actor
    mapper = vtk.vtkPolyDataMapper()
    if vtk.VTK_MAJOR_VERSION <= 5:
        mapper.SetInput(glyph.GetOutput())
    else:
        mapper.SetInputConnection(glyph.GetOutputPort())

    actor = vtk.vtkActor()
    actor.SetMapper(mapper)

    # Create a renderer, render window, and interactor
    renderer = vtk.vtkRenderer()
    renderer.AddActor(actor)

    renderWindow = vtk.vtkRenderWindow()
    renderWindow.AddRenderer(renderer)
    renderWindowInteractor = vtk.vtkRenderWindowInteractor()
    renderWindowInteractor.SetRenderWindow(renderWindow)
    renderWindowInteractor.Initialize()

    # Register callback for animation
    cb = vtkTimerCallback(tspan, radius, mapper, actor, glyph, polyData)
    renderWindowInteractor.AddObserver('TimerEvent', cb.execute)
    timeId = renderWindowInteractor.CreateRepeatingTimer(interval)

    cb.execute(renderWindowInteractor, None)

    renderWindow.Render()

    # Render and interact
    renderWindowInteractor.Start()

if __name__ == '__main__':
    # Create a 3D-grid of 11x11x11 points
    r = np.linspace(-10.0, 10.0, 15)
    X, Y, Z = np.meshgrid(r, r, r)
    X, Y, Z = X.flatten(), Y.flatten(), Z.flatten()
    coords = np.array([(X[i], Y[i], Z[i]) for i in xrange(X.shape[0])], dtype=np.double)
    tspan = np.arange(100, dtype=np.double)
    viewData(coords, tspan, radius=0.5, interval=1)

0 个答案:

没有答案