Closed Jimmy-KL closed 9 months ago
The issue is related to the fact that the reset_camera is evaluated locally (PyVistaLocalView) and at the time of the execution, the mesh is not yet available on the client side.
Since you have the right camera information already available on the server side, it will be easier to call push_camera
instead.
I changed the code to:
def read_mesh():
mesh = pv.Sphere(center=(1000, 1000, 0))
mesh["data"] = mesh.points[:, 0]
actor = pl.add_mesh(mesh)
# ctrl.view_reset_camera()
ctrl.view_push_camera()
ctrl.view_update()
But it's still not working, the mesh didn't show up untile I click the reset camera button.
You need to call reset camera on the server side to compute the camera position.
Then, once you have the proper camera position on the server side, you can push that camera information to the client. Moreover, you probably need to call ctrl.view_update()
first.
I've used this approach with vtkLocalView to import multiple meshes (and the zoom updates to fit all bodies which is great), however the camera orientation resets to XY view after each import. Is there a way to maintain the camera orientation throughout the import?
I'm not sure I understand your question or what you did. Calling reset camera should maintain whatever orientation you have. The only thing is that the local camera and the remote one are disconnected. So, if you want one to drive the other, you will need to sync them occasionally to ensure orientation consistency.
Apologies if my question is unclear. The relevant parts of the importSTL function are:
def importSTL(importing_stl_file=None, **kwargs):
....
renderer.AddActor(actor_stl)
renderer.ResetCamera()
ctrl.view_update()
ctrl.view_reset_camera()
ctrl.view_push_camera() #https://github.com/Kitware/trame/issues/422
Let's say I've imported a cylinder and have rotated it around:
As soon as I import another mesh, the view orientation resets:
Thanks for providing that snippet of code, as it indeed explains what you see.
The main issue is that you push the server side camera that never saw your client side rotation.
Also calling ctrl.view_reset_camera()
just after the view update won't work due to some asynchronous behavior. Basically at the time the "reset camera" is performed on the client side, the full new geometry is not yet available. So the computed bounds and so on is not what you expect.
The maybe a better approach for your usecase, could be to push (client to server) the camera at "end of interaction", so when you call renderer.ResetCamera() + ctrl.view_push_camera()
you get the proper camera angle.
You can take cue on what we do with the Remote/Local view here
Actually, what I listed above is in the wrong direction (remote -> local). What you want is local -> remote.
What you want is doing what is listed as an example here but by using the camera as arg (EndAnimation=(self.update_cam, "[$event]")
) ( not sure the $event is the camera, but the JS expression can be tweaked to get it...)
Absolutely fantastic @jourdain! Works perfectly! For future reference, code changes were:
def update_cam(event,**kwargs):
poked_camera = event['pokedRenderer']['activeCamera']
state.camera_orientation['position'] = poked_camera['position']
state.camera_orientation['focal point'] = poked_camera['focalPoint']
state.camera_orientation['view up'] = poked_camera['viewUp']
state.camera_orientation['distance'] = poked_camera['distance']
state.camera_orientation['clipping range'] = poked_camera['clippingRange']
set_camera_orientation(renderer.GetActiveCamera(),state.camera_orientation)
def set_camera_orientation(camera, p):
camera.SetPosition(p['position'])
camera.SetFocalPoint(p['focal point'])
camera.SetViewUp(p['view up'])
camera.SetDistance(p['distance'])
camera.SetClippingRange(p['clipping range'])
view = vtk.VtkLocalView(
renderWindow,
widgets=[orientation_axes],
interactor_settings=("interactorSettings", VIEW_INTERACT),
picking_modes=("[pickingMode]",),
EndAnimation=(update_cam, "[$event]"),
click="pick_data = $event"
)
Example of initial rotated mesh:
Import of new mesh maintains camera orientation but resizes to fit all actors:
Side note, you can do EndAnimation=(update_cam, "[$event.pokedRenderer.activeCamera"),
to only send the camera.
Describe the bug
I initialize the trame with no actors. Then I add an actor with a corresponding mesh. Also, I reset the camera and update the view. But nothing shows up. Then I add another button to reset the camera manually, then the mesh shows up. Alternatively, without manually resetting the camera, if I refresh the page, the mesh will show up too.
To Reproduce
Steps to reproduce the behavior:
Code Here is a simple example code to reproduce the bug.
Expected behavior
As I already wrote
ctrl.view_reset_camera()
andctrl.view_update()
in the functionread_mesh()
, I think there is no need to click the Rest Camera button again manually. The mesh has been loaded, but it seems there is some problem with the camera which looks strange to me.Screenshots 1) Click the "LOAD DATA" button 2) Click the Reset Camera button
Platform:
Device:
OS:
Browsers Affected: