[vtkusers] Strange segfault (wxPython + wxVTKRenderWindowInteractor + widget)

Paul Melis paul at science.uva.nl
Wed Mar 7 10:12:33 EST 2007


Well, a colleague here had the fix: instead of turning on the 
vtkImagePlaneWidget immediately after creation a deferred call to On() 
will show the widget correctly without segfaulting. Currently I enable 
it once in an idle handler, not a really pretty solution.

Paul

Paul Melis wrote:

> Hmmm,
>
> The code didn't get through correctly in the post, so I've put a copy 
> at http://www.pecm.nl/wxapp_with_widget.py
>
> Paul
>
> Paul Melis wrote:
>
>> Hello,
>>
>> I'm trying to use one of the 3D VTK widgets in a wxPython 
>> application. I originally stumbled upon the segfault described below 
>> while trying to use a vtkImagePlaneWidget, but found that 
>> vtkBoxWidget and vtkSphereWidget also show the same problem. I 
>> include here a stripped version of my original app for easy 
>> demonstration. This is all with a recent CVS version of VTK, wxPython 
>> 2.6.3 and Python 2.4.3 on Fedora Core 4.
>>
>> The code below derives a custom frame from wx.Frame, places a button 
>> and a wxVTKRenderWindowInteractor on that frame. The standard 
>> headsq/quarter VTK dataset is loaded when the button is pressed and a 
>> volume rendering is set up using the dataset. A wx.App is created 
>> that creates the frame and then runs the application main loop. This 
>> all works as expected, the volume is rendered and can be rotated, 
>> zoomed, etc.
>>
>> Problems start when adding a vtkImagePlaneWidget to the pipeline, so 
>> as to show image slices of the data set. The addition of the widget 
>> in the code below is guarded with an "if False:", but changing to 
>> True will add the widget and set its interactor to the 
>> wxVTKRenderWindowInteractor of the frame. The widget is then placed 
>> with PlaceWidget() and enabled with On(). When the app is run with 
>> the widget enabled then any mouse interaction after the dataset is 
>> loaded will cause a segfault. The relevant (top) part of the stack 
>> trace is:
>>
>> #0  0x00000000 in ?? ()
>> #1  0x04543d87 in vtkImagePlaneWidget::ProcessEvents () from 
>> /home/paul/vtk/bin/libvtkWidgets.so.5.1
>> #2  0x055989c1 in vtkCallbackCommand::Execute () from 
>> /home/paul/vtk/bin/libvtkCommon.so.5.1
>> #3  0x0561289a in vtkSubjectHelper::InvokeEvent () from 
>> /home/paul/vtk/bin/libvtkCommon.so.5.1
>> #4  0x05612904 in vtkObject::InvokeEvent () from 
>> /home/paul/vtk/bin/libvtkCommon.so.5.1
>> #5  0x023af093 in 
>> vtkGenericRenderWindowInteractor::LeftButtonPressEvent () from 
>> /home/paul/vtk/bin/libvtkRendering.so.5.1
>> #6  0x03026dd4 in 
>> PyvtkGenericRenderWindowInteractor_LeftButtonPressEvent () from 
>> /home/paul/vtk/bin/libvtkRenderingPythonD.so.5.1
>> #7  0x003106c3 in PyCFunction_Call () from /usr/lib/libpython2.4.so.1.0
>> #8  0x0034931c in PyEval_EvalFrame () from /usr/lib/libpython2.4.so.1.0
>> #9  0x0034aa1c in PyEval_EvalCodeEx () from /usr/lib/libpython2.4.so.1.0
>> #10 0x002ff0b1 in PyFunction_SetClosure () from 
>> /usr/lib/libpython2.4.so.1.0
>> #11 0x002ea7c6 in PyObject_Call () from /usr/lib/libpython2.4.so.1.0
>> #12 0x002f20ee in PyMethod_Fini () from /usr/lib/libpython2.4.so.1.0
>> #13 0x002ea7c6 in PyObject_Call () from /usr/lib/libpython2.4.so.1.0
>> #14 0x00343b1c in PyEval_CallObjectWithKeywords () from 
>> /usr/lib/libpython2.4.so.1.0
>> #15 0x004be8de in wxPyCallback::EventThunker () from 
>> /usr/lib/python2.4/site-packages/wx-2.6-gtk2-unicode/wx/_core_.so
>> #16 0x009fed3d in wxAppConsole::HandleEvent () from 
>> /usr/lib/libwx_baseu-2.6.so.0
>> #17 0x00a87c7f in wxEvtHandler::ProcessEventIfMatches () from 
>> /usr/lib/libwx_baseu-2.6.so.0
>> #18 0x00a87d40 in wxEvtHandler::SearchDynamicEventTable () from 
>> /usr/lib/libwx_baseu-2.6.so.0
>> #19 0x00a87fe5 in wxEvtHandler::ProcessEvent () from 
>> /usr/lib/libwx_baseu-2.6.so.0
>> #20 0x00f07fda in wxWinModule::wxCreateObject () from 
>> /usr/lib/libwx_gtk2u_core-2.6.so.0
>> [...]
>>
>> There seems to be a null pointer being used somewhere, but looking at 
>> vtkImagePlaneWidget::ProcessEvents() the only candidate for that 
>> would be the parameter "clientdata" as it is the only one used in the 
>> method. This is so deep within VTK that I don't know what's going on. 
>> Perhaps I'm setting things up slightly wrong or maybe there's a 
>> problem with the wxVTKRenderWindowInteractor.
>>
>> Any help would be greatly appreciated,
>> Paul
>>
>> ===============================
>> #!/usr/bin/env python
>> import sys
>> import wx
>>
>> import vtk
>> from vtk.wx.wxVTKRenderWindowInteractor import 
>> wxVTKRenderWindowInteractor
>>
>> from vtk.util.misc import vtkGetDataRoot
>> VTK_DATA_ROOT = vtkGetDataRoot()
>>
>> class MainFrame(wx.Frame):
>>      def __init__(self, parent, title):
>>        wx.Frame.__init__(self, parent, -1, title)
>>              self.button = wx.Button(self, -1, "Load!")              
>> self.button.SetDefault()
>>        self.Bind(wx.EVT_BUTTON, self.OnLoad, self.button)
>>
>>        self.vtk_widget = wxVTKRenderWindowInteractor(self, -1, 
>> size=wx.Size(800,600))              
>> self.vtk_widget.Enable(1)                                    sizer = 
>> wx.BoxSizer(wx.VERTICAL)              sizer.Add(self.button, 0, 
>> wx.EXPAND)
>>        sizer.Add(self.vtk_widget, 1, wx.EXPAND|wx.ALL, 1)             
>>        self.CreateStatusBar()
>>        self.SetStatusText("")
>>              self.vtk_renderer = vtk.vtkRenderer()
>>        self.vtk_renderer.AddObserver("StartEvent", lambda o,e: 
>> self.OnRenderingStart(o,e))
>>        self.vtk_renderer.AddObserver("EndEvent", lambda o,e: 
>> self.OnRenderingEnd(o,e))                    
>> self.vtk_widget.GetRenderWindow().AddRenderer(self.vtk_renderer)
>>              self.SetSizer(sizer)
>>        sizer.SetSizeHints(self)     def OnRenderingStart(self, obj, 
>> evt):
>>        self.SetStatusText("Rendering")
>>        self.Update()
>>        wx.Yield()                def OnRenderingEnd(self, obj, evt):
>>        self.SetStatusText("")
>>        self.Update()
>>        wx.Yield()                def OnLoad(self, evt):
>>
>>        # Load a volume, use the widget to control what's volume
>>        # rendered. Basically the idea is that the vtkBoxWidget 
>> provides a box
>>        # which clips the volume rendering.
>>        v16 = vtk.vtkVolume16Reader()
>>        v16.SetDataDimensions(64, 64)
>>        v16.GetOutput().SetOrigin(0.0, 0.0, 0.0)
>>        v16.SetDataByteOrderToLittleEndian()
>>              v16.SetFilePrefix(VTK_DATA_ROOT+ "/Data/headsq/quarter")
>>        v16.SetImageRange(1, 93)
>>        v16.SetDataSpacing(3.2, 3.2, 1.5)
>>                      print "scalar range:", 
>> v16.GetOutput().GetScalarRange()
>>
>>        tfun = vtk.vtkPiecewiseFunction()
>>        tfun.AddPoint(70.0, 0.0)
>>        tfun.AddPoint(599.0, 0)
>>        tfun.AddPoint(600.0, 0)
>>        tfun.AddPoint(1195.0, 0)
>>        tfun.AddPoint(1200, .2)
>>        tfun.AddPoint(1300, .3)
>>        tfun.AddPoint(2000, .3)
>>        tfun.AddPoint(4095.0, 1.0)
>>
>>        ctfun = vtk.vtkColorTransferFunction()
>>        ctfun.AddRGBPoint(0.0, 0.5, 0.0, 0.0)
>>        ctfun.AddRGBPoint(600.0, 1.0, 0.5, 0.5)
>>        ctfun.AddRGBPoint(1280.0, 0.9, 0.2, 0.3)
>>        ctfun.AddRGBPoint(1960.0, 0.81, 0.27, 0.1)
>>        ctfun.AddRGBPoint(4095.0, 0.5, 0.5, 0.5)
>>
>>        compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()
>>
>>        volumeMapper = vtk.vtkVolumeRayCastMapper()
>>        volumeMapper.SetInputConnection(v16.GetOutputPort())
>>        volumeMapper.SetVolumeRayCastFunction(compositeFunction)
>>
>>        volumeProperty = vtk.vtkVolumeProperty()
>>        volumeProperty.SetColor(ctfun)
>>        volumeProperty.SetScalarOpacity(tfun)
>>        volumeProperty.SetInterpolationTypeToLinear()
>>        volumeProperty.ShadeOn()
>>
>>        newvol = vtk.vtkVolume()
>>        newvol.SetMapper(volumeMapper)
>>        newvol.SetProperty(volumeProperty)
>>              self.vtk_renderer.AddVolume(newvol)
>>        self.vtk_renderer.SetBackground(0, 0, 0)
>>
>>        # Show an outline (box)
>>        if False:                      outline = vtk.vtkOutlineFilter()
>>            outline.SetInputConnection(v16.GetOutputPort())
>>            outlineMapper = vtk.vtkPolyDataMapper()
>>            outlineMapper.SetInputConnection(outline.GetOutputPort())
>>            outlineActor = vtk.vtkActor()
>>            outlineActor.SetMapper(outlineMapper)
>>            
>> self.vtk_renderer.AddActor(outlineActor)                       
>>                      # vtkImagePlaneWidget
>>        if False:
>>            ipw = vtk.vtkImagePlaneWidget()                  
>> ipw.SetInput(v16.GetOutput())                                  
>> ipw.SetPlaneOrientationToXAxes()
>>            ipw.SetSliceIndex(1)
>>            ipw.DisplayTextOn()
>>                      picker = vtk.vtkCellPicker()
>>            ipw.SetPicker(picker)
>>                      
>> ipw.SetInteractor(self.vtk_widget._Iren)                          
>> ipw.PlaceWidget()
>>            ipw.On()
>>                  # vtkSphereWidget
>>        if False:
>>            w = vtk.vtkSphereWidget()
>>            w.SetInput(v16.GetOutput())
>>            w.SetInteractor(self.vtk_widget._Iren)
>>            w.PlaceWidget()
>>            w.On()
>>
>> class MyApp(wx.App):
>>      def OnInit(self):
>>        frame = MainFrame(None, "VTK")                     
>> self.SetTopWindow(frame)
>>        frame.Show(True)
>>
>>        return True
>>
>> app = MyApp(redirect=False)
>>
>> app.MainLoop()
>>
>> ==========================
>>
>>
>> _______________________________________________
>> This is the private VTK discussion list. Please keep messages 
>> on-topic. Check the FAQ at: http://www.vtk.org/Wiki/VTK_FAQ
>> Follow this link to subscribe/unsubscribe:
>> http://www.vtk.org/mailman/listinfo/vtkusers
>
>
>
> _______________________________________________
> This is the private VTK discussion list. Please keep messages 
> on-topic. Check the FAQ at: http://www.vtk.org/Wiki/VTK_FAQ
> Follow this link to subscribe/unsubscribe:
> http://www.vtk.org/mailman/listinfo/vtkusers





More information about the vtkusers mailing list