[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