[vtkusers] 3D axis that follows main actor: Python / wxWindows / VTK

Uwe Rempler rempler at mechbau.uni-stuttgart.de
Wed Feb 4 09:57:57 EST 2004


hi list,

not so long ago i needed to create a 3d axis that automatically orients 
itself relative to the actor in the main renderer. i've found a very 
helpful snippet in the mailing list archive written in c++:
http://public.kitware.com/pipermail/vtkusers/2001-September/007992.html
because of my other partially finished program i made a translation in 
python using AddObserver() instead of the vtkCallbackCommand() which i 
was not really able to access within python. in addition to steve boyd's 
code i made the overlaying renderer transparent via different layers and 
removeable...
because of the nice community here which helped me a lot (and i hope 
it'll do this in future too ;-) i would like to share my little piece of 
code with you.
hope this example is of assistance to you ;-)

thank you all
greetings
uwe



#!/usr/bin/python

#------------------------------------ +++ 
--------------------------------------
# Alpha:
# ======
# and now for something completely different...
#
anfang = '- ALPHA ' * 7 + '-'
print
print anfang
print '-' * len(anfang)
print
#------------------------------------ +++ 
--------------------------------------


#-------------------------------------------------------------------------------
# import modules
import vtk
from wxPython.wx import *
from vtk.wx.wxVTKRenderWindow import *


#-------------------------------------------------------------------------------
# global / static variable
SHOW = 'TRUE'


#-------------------------------------------------------------------------------
# wx-stuff..
[wxID_AXISMAINWINDOW, wxID_AXISMAINWINDOWBTNSHOWAXIS,
wxID_AXISMAINWINDOWPANEL1, wxID_AXISMAINWINDOWBTNQUIT,
] = map(lambda _init_ctrls: wxNewId(), range(4))


#-------------------------------------------------------------------------------
class DisplayAxis:
    def __init__(self, app, main):
        global SHOW
        self.app = app
        self.main = main
        self.renwin = self.main.widget.GetRenderWindow()
        try:
            self.main.ren.Render()
            if SHOW == 'TRUE':
                self._showAxis()
                SHOW = 'FALSE'
            else:
                self._hideAxis()
                SHOW = 'TRUE'
        except:
            print 'no renderwidget...'

    def _showAxis(self):
        # create / show 3D-axis
        self.axisXArrow = vtk.vtkArrowSource()
        self.axisYArrow = vtk.vtkArrowSource()
        self.axisZArrow = vtk.vtkArrowSource()

        self.axisXMapper = vtk.vtkPolyDataMapper()
        self.axisXMapper.SetInput(self.axisXArrow.GetOutput())
        self.axisXMapper.ScalarVisibilityOff()
        self.axisYMapper = vtk.vtkPolyDataMapper()
        self.axisYMapper.SetInput(self.axisYArrow.GetOutput())
        self.axisYMapper.ScalarVisibilityOff()
        self.axisZMapper = vtk.vtkPolyDataMapper()
        self.axisZMapper.SetInput(self.axisZArrow.GetOutput())
        self.axisZMapper.ScalarVisibilityOff()

        self.axisXArrowActor = vtk.vtkActor()
        self.axisXArrowActor.SetMapper(self.axisXMapper)
        self.axisXArrowActor.GetProperty().SetColor(1, 0, 0) # x-axis >> red
        self.axisYArrowActor = vtk.vtkActor()
        self.axisYArrowActor.RotateY(-90)
        self.axisYArrowActor.GetProperty().SetColor(0, 1, 0) # y-axis >> 
green
        self.axisYArrowActor.SetMapper(self.axisYMapper)
        self.axisZArrowActor = vtk.vtkActor()
        self.axisZArrowActor.RotateZ(90)
        self.axisZArrowActor.GetProperty().SetColor(0, 0, 1) # z-axis >> 
blue
        self.axisZArrowActor.SetMapper(self.axisZMapper)

        self.axisAssembly = vtk.vtkAssembly()
        self.axisAssembly.AddPart(self.axisXArrowActor)
        self.axisAssembly.AddPart(self.axisYArrowActor)
        self.axisAssembly.AddPart(self.axisZArrowActor)
        self.axisAssembly.PickableOff()

        self.axisRenderer = vtk.vtkRenderer()
        self.axisRenderer.AddActor(self.axisAssembly)
        self.axisRenderer.SetViewport(0.8, 0, 1, 0.2)
        self.axisRenderer.InteractiveOff()
        self.axisRenderer.AddActor(self.axisAssembly)

        self.renwin.AddRenderer(self.axisRenderer)
        self.renwin.SetNumberOfLayers(2)
        self.main.ren.SetLayer(1)
        self.axisRenderer.SetLayer(0)
        self._updateAxis()
        self.renwin.Render()

        # add observer to get any changes made to the main renderer
        self.main.ren.AddObserver('AnyEvent', self._updateAxis)

    def _hideAxis(self):
        # hide / remove 3D-axis
        self.axisRenderer = self.renwin.GetRenderers()
        self.axisRenderer.RemoveItem(1)
        self.main.ren.RemoveObserver(0)
        self.renwin.Render()

    def _updateAxis(self, object = None, event_string = None):
        # set the axis camera according to the main renderer
        camPos, camFoc, axisFoc = [], [], []
        camPos = self.main.ren.GetActiveCamera().GetPosition()
        camFoc = self.main.ren.GetActiveCamera().GetFocalPoint()
        axisFoc = self.axisRenderer.GetActiveCamera().GetFocalPoint()
        
self.axisRenderer.GetActiveCamera().SetViewUp(self.main.ren.GetActiveCamera().GetViewUp())
        self.axisRenderer.GetActiveCamera().SetPosition(
            camPos[0] - camFoc[0] + axisFoc[0],
            camPos[1] - camFoc[1] + axisFoc[1],
            camPos[2] - camFoc[2] + axisFoc[2])
        self.axisRenderer.ResetCamera()
        size = self.main.widget.GetSize()
        self.axisRenderer.SetViewport(
            (float(size[0]) - 120.) / float(size[0]), 0.,
            1.,
            120. / float(size[1]))


#-------------------------------------------------------------------------------
# mainwindow
class AxisMainWindow(wxFrame):

    def _init_ctrls(self, prnt):
        wxFrame.__init__(self, id=wxID_AXISMAINWINDOW,
            name='AxisMainWindow', parent=prnt, pos=wxPoint(300, 400),
            size=wxSize(500, 500), style=wxDEFAULT_FRAME_STYLE,
            title='AxisMainWindow')

        self.btnShowAxis = wxButton(id=wxID_AXISMAINWINDOWBTNSHOWAXIS,
            label='Show Axis', name='btnShowAxis', parent=self,
            pos=wxPoint(10, 10), size=wxSize(100, 30), style=0)
        EVT_BUTTON(self.btnShowAxis, wxID_AXISMAINWINDOWBTNSHOWAXIS,
            self.OnBtnshowAxisButton)

        self.btnQuit = wxButton(id=wxID_AXISMAINWINDOWBTNQUIT,
            label='Quit', name='btnQuit', parent=self,
            pos=wxPoint(390, 10),size=wxSize(100, 30),
            style=wxBU_AUTODRAW, validator=wxDefaultValidator)
        EVT_BUTTON(self.btnQuit, wxID_AXISMAINWINDOWBTNQUIT,
            self.OnBtnquitButton)

        self.panel1 = wxPanel(id=wxID_AXISMAINWINDOWPANEL1,
            name='panel1', parent=self, pos=wxPoint(10, 50),
            size=wxSize(480, 440), style=wxSUNKEN_BORDER)
        EVT_SIZE(self.panel1, self.OnAxisMainWindowSize)

    def __init__(self, parent, app):
        self.app = app
        self._init_ctrls(parent)
        self.panel1.SetAutoLayout(true)
        self.CreateRenderFrame()
        self.AxisMainWindowSetSizer()

    def AxisMainWindowSetSizer(self):
        ButtonBoxTop = wxBoxSizer(wxHORIZONTAL)
        ButtonBoxTop.Add(self.btnShowAxis, 0)
        ButtonBoxTop.Add(0, 0, 1, 0)
        ButtonBoxTop.Add(self.btnQuit, 0, wxALIGN_RIGHT, 0)

        PanelBox = wxBoxSizer(wxHORIZONTAL)
        PanelBox.Add(self.panel1, 1, wxEXPAND, 0)

        BigBox = wxBoxSizer(wxVERTICAL)
        BigBox.Add(ButtonBoxTop, 0, wxEXPAND | wxTOP | wxRIGHT | wxLEFT, 10)
        BigBox.Add(PanelBox, 1, wxEXPAND | wxALL, 10)

        self.SetAutoLayout(true)
        self.SetSizer(BigBox)

    def CreateRenderFrame(self):
        self.widget = wxVTKRenderWindow(self.panel1, -1,
            size=self.panel1.GetSizeTuple())

        self.ren = vtkRenderer()
        self.ren.SetBackground(1, 1, 1)
        self.widget.GetRenderWindow().AddRenderer(self.ren)

        self.cone = vtkConeSource()
        self.cone.SetResolution(8)
        self.coneMapper = vtkPolyDataMapper()
        self.coneMapper.SetInput(self.cone.GetOutput())
        self.coneActor = vtkActor()
        self.coneActor.SetMapper(self.coneMapper)

        self.ren.AddActor(self.coneActor)
        self.widget.Render()
        DisplayAxis(self.app, self)

    def OnBtnquitButton(self, event):
        self.AxisMainWindowQuit()

    def OnBtnshowAxisButton(self, event):
        DisplayAxis(self.app, self)

    def OnAxisMainWindowSize(self, event):
        try:
            self.size = event.GetSize()
            self.widget.SetSize(self.size)  # resize renderwindow with
                                            # panel event.size
            self.widget.Reset()             # reset view
        except:
            pass

    def AxisMainWindowQuit(self):
        self.app.AxisQuit()


#-------------------------------------------------------------------------------
# application
class AxisApp(wxApp):
    def OnInit(self):
        self.main = create(None, self)
        self.SetTopWindow(self.main)
        self.main.Show();self.main.Hide();self.main.Show()
        return True

    def AxisQuit(self):
        self.ExitMainLoop()


#-------------------------------------------------------------------------------
# create / return mainwindow
def create(parent, app):
    return AxisMainWindow(parent, app)


#-------------------------------------------------------------------------------
# start mainloop()
def main():
    application = AxisApp(0)
    application.MainLoop()


#-------------------------------------------------------------------------------
# on startup call main()
if __name__ == '__main__':
    main()


#------------------------------------ +++ 
--------------------------------------
# Omega:
# ======
# that's all folks...
#
print
ende = '- OMEGA ' * 7 + '-'
print '-' * len(ende)
print ende
print
#------------------------------------ +++ 
--------------------------------------



More information about the vtkusers mailing list