Search code examples
pythonvtkcoordinate-systemspyvista

Convert from plotter coordinates to world coordinates in PyVista


I am new to PyVista and vtk. I am implementing a mesh editing tool (Python=3.10, pyvista=0.37,vtk=9.1 ) When a user clicks all points within a given radius of the mouse cursor's world coordinates (e.g. projected point on the surface) should be selected. I have implemented this much through callbacks to mouse clicks using the pyvista plotters track_click_position method.

My problem is that I also want for a user to be able to preview the selection (highlight the vertices that will be selected) before they click. For this it is necessary to track the mouse location in world coordinates and to attach a callback function to the movement of the mouse that will highlight the relevant nodes.

The pyvista plotter's 'track_mouse_position' method doesn't support attaching callbacks but I figured out a work around for that. In the minimal example below I have managed to track changes to the mouse cursor location in pixels in the plotter's coordinate system. I am stuck now as to how to convert these into world coordinates. When the mouse hovers over the sphere these 'world coordinates' this should be the projected location on the sphere. When the mouse hovers off the sphere then it should return nothing or inf or some other useless value.

import pyvista as pv
def myCallback(src,evt):
    C = src.GetEventPosition() # appears to be in pixels of the viewer
    print(C)
    # how to convert C into world coordinates on the sphere

sp = pv.Sphere()
p = pv.Plotter()
p.add_mesh(sp)
p.iren.add_observer("MouseMoveEvent",myCallback)
p.show()

Thank you very much for your help. Harry


Solution

  • I figured this one out. They key was to use 'pick_mouse_position' after calling 'track_mouse_position'.

    import pyvista as pv
    def myCallback(src,evt):
        out = p.pick_mouse_position()
        print(out)
         
    sp = pv.Sphere()
    p = pv.Plotter()
    p.add_mesh(sp)
    p.track_mouse_position()
    p.iren.add_observer("MouseMoveEvent",myCallback)
    p.show()