Skip to content

Commit

Permalink
Improve performance of Trame camera sync (pyvista#4223)
Browse files Browse the repository at this point in the history
* Improve performance of Trame camera sync

* Improve render events with camera setting

* Fix update_image

* Snake case file names
  • Loading branch information
banesullivan authored Apr 9, 2023
1 parent 92b436e commit dd44661
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 57 deletions.
File renamed without changes.
File renamed without changes.
43 changes: 43 additions & 0 deletions examples_trame/validation/many_actors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from trame.app import get_server
from trame.ui.vuetify import SinglePageLayout
from trame.widgets import vuetify

import pyvista as pv
from pyvista.trame.ui import plotter_ui

pv.OFF_SCREEN = True

server = get_server()
state, ctrl = server.state, server.controller

state.trame__title = "PyVista Many Actors"

# -----------------------------------------------------------------------------

plotter = pv.Plotter()

for i in range(25):
for j in range(25):
actor = plotter.add_mesh(pv.Sphere(center=(i, j, 0)))


# -----------------------------------------------------------------------------
# GUI
# -----------------------------------------------------------------------------

with SinglePageLayout(server) as layout:
layout.icon.click = ctrl.view_reset_camera
layout.title.set_text(state.trame__title)

with layout.toolbar:
vuetify.VSpacer()

with layout.content:
# Use PyVista UI template for Plotters
view = plotter_ui(plotter)
ctrl.view_update = view.update

# hide footer
layout.footer.hide()

server.start()
92 changes: 68 additions & 24 deletions pyvista/plotting/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2104,7 +2104,7 @@ def set_focus(self, point):
self.camera_set = True
self.Modified()

def set_position(self, point, reset=False):
def set_position(self, point, reset=False, render=True):
"""Set camera position to a point.
Parameters
Expand All @@ -2116,6 +2116,10 @@ def set_position(self, point, reset=False):
Whether to reset the camera after setting the camera
position.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the position.
Examples
--------
Move the camera far away to ``[7, 7, 7]``.
Expand All @@ -2133,11 +2137,11 @@ def set_position(self, point, reset=False):
point = point.ravel()
self.camera.position = scale_point(self.camera, point, invert=False)
if reset:
self.reset_camera()
self.reset_camera(render=render)
self.camera_set = True
self.Modified()

def set_viewup(self, vector, reset=True):
def set_viewup(self, vector, reset=True, render=True):
"""Set camera viewup vector.
Parameters
Expand All @@ -2149,6 +2153,10 @@ def set_viewup(self, vector, reset=True):
Whether to reset the camera after setting the camera
position.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the viewup.
Examples
--------
Look from the top down by setting view up to ``[0, 1, 0]``.
Expand All @@ -2166,7 +2174,7 @@ def set_viewup(self, vector, reset=True):

self.camera.up = vector
if reset:
self.reset_camera()
self.reset_camera(render=render)

self.camera_set = True
self.Modified()
Expand Down Expand Up @@ -2339,16 +2347,16 @@ def remove_actor(self, actor, reset_camera=False, render=True):
self._actors.pop(name, None)
self.update_bounds_axes()
if reset_camera:
self.reset_camera()
self.reset_camera(render=render)
elif not self.camera_set and reset_camera is None:
self.reset_camera()
self.reset_camera(render=render)
elif render:
self.parent.render()

self.Modified()
return True

def set_scale(self, xscale=None, yscale=None, zscale=None, reset_camera=True):
def set_scale(self, xscale=None, yscale=None, zscale=None, reset_camera=True, render=True):
"""Scale all the actors in the scene.
Scaling in performed independently on the X, Y and Z axis.
Expand Down Expand Up @@ -2377,6 +2385,10 @@ def set_scale(self, xscale=None, yscale=None, zscale=None, reset_camera=True):
reset_camera : bool, default: True
Resets camera so all actors can be seen.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the scale.
Examples
--------
Set the scale in the z direction to be 2 times that of
Expand Down Expand Up @@ -2405,7 +2417,7 @@ def set_scale(self, xscale=None, yscale=None, zscale=None, reset_camera=True):
self.parent.render()
if reset_camera:
self.update_bounds_axes()
self.reset_camera()
self.reset_camera(render=render)
self.Modified()

def get_default_cam_pos(self, negative=False):
Expand Down Expand Up @@ -2508,7 +2520,7 @@ def isometric_view(self):
"""
self.view_isometric()

def view_isometric(self, negative=False):
def view_isometric(self, negative=False, render=True):
"""Reset the camera to a default isometric view.
The view will show all the actors in the scene.
Expand All @@ -2518,6 +2530,10 @@ def view_isometric(self, negative=False):
negative : bool, default: False
View from the other isometric direction.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the camera position.
Examples
--------
Isometric view.
Expand All @@ -2538,9 +2554,9 @@ def view_isometric(self, negative=False):
position = self.get_default_cam_pos(negative=negative)
self.camera_position = CameraPosition(*position)
self.camera_set = negative
self.reset_camera()
self.reset_camera(render=render)

def view_vector(self, vector, viewup=None):
def view_vector(self, vector, viewup=None, render=True):
"""Point the camera in the direction of the given vector.
Parameters
Expand All @@ -2551,22 +2567,30 @@ def view_vector(self, vector, viewup=None):
viewup : sequence[float], optional
Sequence describing the view up of the camera.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the camera position.
"""
focal_pt = self.center
if viewup is None:
viewup = self._theme.camera['viewup']
cpos = CameraPosition(vector + np.array(focal_pt), focal_pt, viewup)
self.camera_position = cpos
self.reset_camera()
self.reset_camera(render=render)

def view_xy(self, negative=False):
def view_xy(self, negative=False, render=True):
"""View the XY plane.
Parameters
----------
negative : bool, default: False
View from the opposite direction.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the camera position.
Examples
--------
View the XY plane of a built-in mesh example.
Expand All @@ -2580,16 +2604,20 @@ def view_xy(self, negative=False):
>>> pl.show()
"""
self.view_vector(*view_vectors('xy', negative=negative))
self.view_vector(*view_vectors('xy', negative=negative), render=render)

def view_yx(self, negative=False):
def view_yx(self, negative=False, render=True):
"""View the YX plane.
Parameters
----------
negative : bool, default: False
View from the opposite direction.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the camera position.
Examples
--------
View the YX plane of a built-in mesh example.
Expand All @@ -2603,16 +2631,20 @@ def view_yx(self, negative=False):
>>> pl.show()
"""
self.view_vector(*view_vectors('yx', negative=negative))
self.view_vector(*view_vectors('yx', negative=negative), render=render)

def view_xz(self, negative=False):
def view_xz(self, negative=False, render=True):
"""View the XZ plane.
Parameters
----------
negative : bool, default: False
View from the opposite direction.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the camera position.
Examples
--------
View the XZ plane of a built-in mesh example.
Expand All @@ -2626,16 +2658,20 @@ def view_xz(self, negative=False):
>>> pl.show()
"""
self.view_vector(*view_vectors('xz', negative=negative))
self.view_vector(*view_vectors('xz', negative=negative), render=render)

def view_zx(self, negative=False):
def view_zx(self, negative=False, render=True):
"""View the ZX plane.
Parameters
----------
negative : bool, default: False
View from the opposite direction.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the camera position.
Examples
--------
View the ZX plane of a built-in mesh example.
Expand All @@ -2649,16 +2685,20 @@ def view_zx(self, negative=False):
>>> pl.show()
"""
self.view_vector(*view_vectors('zx', negative=negative))
self.view_vector(*view_vectors('zx', negative=negative), render=render)

def view_yz(self, negative=False):
def view_yz(self, negative=False, render=True):
"""View the YZ plane.
Parameters
----------
negative : bool, default: False
View from the opposite direction.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the camera position.
Examples
--------
View the YZ plane of a built-in mesh example.
Expand All @@ -2672,16 +2712,20 @@ def view_yz(self, negative=False):
>>> pl.show()
"""
self.view_vector(*view_vectors('yz', negative=negative))
self.view_vector(*view_vectors('yz', negative=negative), render=render)

def view_zy(self, negative=False):
def view_zy(self, negative=False, render=True):
"""View the ZY plane.
Parameters
----------
negative : bool, default: False
View from the opposite direction.
render : bool, default: True
If the render window is being shown, trigger a render
after setting the camera position.
Examples
--------
View the ZY plane of a built-in mesh example.
Expand All @@ -2695,7 +2739,7 @@ def view_zy(self, negative=False):
>>> pl.show()
"""
self.view_vector(*view_vectors('zy', negative=negative))
self.view_vector(*view_vectors('zy', negative=negative), render=render)

def disable(self):
"""Disable this renderer's camera from being interactive."""
Expand Down
38 changes: 22 additions & 16 deletions pyvista/trame/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,32 +121,39 @@ def update_image(self, **kwargs):
"""
for view in self._html_views:
if hasattr(view, 'update_image'):
view.update_image()
view.update_image()

def update_camera(self, **kwargs):
"""Update image and camera for all associated views.
Parameters
----------
**kwargs : dict, optional
Unused keyword arguments.
"""
for view in self._html_views:
view.update_camera()

def view_isometric(self):
"""View isometric."""
self.plotter.view_isometric()
self.push_camera()
self.update()
self.plotter.view_isometric(render=False)
self.update_camera()

def view_yz(self):
"""View YZ plane."""
self.plotter.view_yz()
self.push_camera()
self.update()
self.plotter.view_yz(render=False)
self.update_camera()

def view_xz(self):
"""View XZ plane."""
self.plotter.view_xz()
self.push_camera()
self.update()
self.plotter.view_xz(render=False)
self.update_camera()

def view_xy(self):
"""View XY plane."""
self.plotter.view_xy()
self.push_camera()
self.update()
self.plotter.view_xy(render=False)
self.update_camera()

def on_edge_visiblity_change(self, **kwargs):
"""Toggle edge visibility for all actors.
Expand Down Expand Up @@ -225,8 +232,7 @@ def on_rendering_mode_change(self, **kwargs):
"""
if not kwargs[self.SERVER_RENDERING]:
self.push_camera()
self.update()
self.update_camera()

@property
def actors(self):
Expand Down
Loading

0 comments on commit dd44661

Please sign in to comment.