[vtkusers] Strange segfault (wxPython + wxVTKRenderWindowInteractor + widget)
Paul Melis
paul at science.uva.nl
Wed Mar 7 07:18:11 EST 2007
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()
==========================
More information about the vtkusers
mailing list