Failing event binding with vtkRemoteView
cardinalgeo opened this issue · comments
Describe the bug
Under the following conditions, the error message JS Error => RangeError: Maximum call stack size exceeded
is produced.
1.) Use of vtkRemoteView()
(this error is not produced for vtkLocalView()
)
2.) an arbitrary function is bound to an event, such as LeftButtonDown
3.) the contents of the event are passed as an input to the function
4.) the event is triggered
To Reproduce
Steps to reproduce the behavior:
- Run the script below (an MRE using a two-segment polyline passed to a tube filter as an actor)
- Click anywhere in the display
- See error
Code
import vtk
from trame.app import get_server
from trame.widgets import vuetify, vtk as vtk_widgets
from trame.ui.vuetify import SinglePageLayout
from vtkmodules.vtkRenderingCore import (
vtkActor,
vtkPolyDataMapper,
vtkRenderer,
vtkRenderWindow,
vtkRenderWindowInteractor,
)
from vtkmodules.vtkFiltersCore import vtkTubeFilter
from vtkmodules.vtkInteractionStyle import (
vtkInteractorStyleTrackballCamera)
import vtkmodules.vtkRenderingOpenGL2 # noqa (needed for vtkHardwareSelector)
# -----------------------------------------------------------------------------
# Generate dataset
# -----------------------------------------------------------------------------
points = vtk.vtkPoints()
points.SetNumberOfPoints(4)
line = vtk.vtkLine()
lines = vtk.vtkCellArray()
# create first line segment
points.SetPoint(0, 0, 0, 0)
line.GetPointIds().SetId(0, 0)
points.SetPoint(1, 1, 1, 1)
line.GetPointIds().SetId(1, 1)
lines.InsertNextCell(line)
# create second line segment
points.SetPoint(2, 1, 1, 1)
line.GetPointIds().SetId(0, 2)
points.SetPoint(3, 2, 2, 2)
line.GetPointIds().SetId(1, 3)
lines.InsertNextCell(line)
linesPolyData = vtk.vtkPolyData()
linesPolyData.SetPoints(points)
linesPolyData.SetLines(lines)
# -----------------------------------------------------------------------------
# Trame initialization
# -----------------------------------------------------------------------------
server = get_server()
state, ctrl = server.state, server.controller
# -----------------------------------------------------------------------------
# Interactions
# -----------------------------------------------------------------------------
def foo(pickData):
print("hello")
# -----------------------------------------------------------------------------
# VTK pipeline
# -----------------------------------------------------------------------------
tubes_filter = vtkTubeFilter()
tubes_filter.SetInputData(linesPolyData)
tubes_filter.SetRadius(2)
tubes_filter.SetNumberOfSides(3)
tubes_filter.Update()
mapper = vtkPolyDataMapper()
mapper.SetInputConnection(tubes_filter.GetOutputPort())
actor = vtkActor()
actor.SetMapper(mapper)
renderer = vtkRenderer()
renderer.SetBackground(1, 1, 1)
renderer.AddActor(actor)
render_window = vtkRenderWindow()
render_window.AddRenderer(renderer)
rw_interactor = vtkRenderWindowInteractor()
rw_interactor.SetRenderWindow(render_window)
rw_interactor.GetInteractorStyle().SetCurrentStyleToTrackballCamera()
renderer.ResetCamera()
# -----------------------------------------------------------------------------
# GUI layout
# -----------------------------------------------------------------------------
with SinglePageLayout(server) as layout:
with layout.content:
with vuetify.VContainer(fluid=True, classes="fill-height pa-0 ma-0"):
view = vtk_widgets.VtkRemoteView(
render_window,
interactor_events=("events", ["LeftButtonPress"]),
LeftButtonPress=(foo, "[$event]")
)
view.update
view.reset_camera
# -----------------------------------------------------------------------------
# Main
# -----------------------------------------------------------------------------
if __name__ == "__main__":
server.start(port=0)
Expected behavior
I expect that, upon clicking anywhere in the display, "hello" will be printed.
Screenshots
If applicable, add screenshots to help explain your problem (drag and drop the image).
Platform:
Trame:
- Version 1.x
- Version 2.x
Device:
- Desktop
- Mobile
OS:
- Windows
- MacOS
- Linux
- Android
- iOS
Browsers Affected:
- Chrome
- Firefox
- Microsoft Edge
- Safari
- Opera
- Brave
- IE 11
The reason why it is failing is that $event
is not serializable which through an exception on the JS side. We provide a helper to extract a serializable version of that event.
To fix your example, just replace that line
LeftButtonPress=(foo, "[utils.vtk.event($event)]")
You can see the documentation about it:
The working code base can be found here
Stellar, it now works! This was (hopefully) the last piece of the puzzle for an mvp with vtkRemoteView. (There's a separate issue I'll open for vtkLocalView). Thanks @jourdain!
Did you figure out the remaining part of your cell picking? Or are you still missing some details?
Ok sounds good.