VTK provide three different world point converted from three methods with one display point

I am using VTK in my project, and I need to get the world point from a display point.

I find three method: vtkPropPicker, vtkCellPicker, vtkCoordinate. But I find they return different world point for the same display point.

The test code is:

import vtk

cone = vtk.vtkConeSource()
cone.SetCenter(150, 150, 0)
cone.SetHeight(100)
cone.SetRadius(50)
cone.Update()
coneMapper = vtk.vtkPolyDataMapper()
coneMapper.SetInputData(cone.GetOutput())
coneMapper.Update()
coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)

ren = vtk.vtkRenderer()
ren.AddActor(coneActor)
ren.SetBackground(0.1, 0.2, 0.4)


renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
renWin.SetSize(400, 400)

iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

renWin.Render()
X = 100
Y = 100
picker = vtk.vtkPropPicker()
picker.Pick(X, Y, 0, ren)
pickerWorld = picker.GetPickPosition()
print('world point from vtkPropPicker: ', pickerWorld)

picker = vtk.vtkCellPicker()
picker.Pick(X, Y, 0, ren)
cellWorld = picker.GetPickPosition()
print('world point from vtkCellPicker: ', cellWorld)

coordinate = vtk.vtkCoordinate()
coordinate.SetCoordinateSystemToDisplay()
coordinate.SetValue(X, Y)
coorWorld = coordinate.GetComputedWorldValue(ren)
print('world point from vtkCoordinate: ', coorWorld)

And the result is:

world point from vtkPropPicker:  (108.0365506828649, 108.0365506828649, 7.141902959080343)
world point from vtkCellPicker:  (108.0089599111793, 108.0089599111793, 6.935962635578974)
world point from vtkCoordinate:  (119.0534474476644, 119.0534474476644, 89.37313989502613)

We can see: for the same display point (100, 100), vtkPropPicker, vtkCellPicker, vtkCoordinate return different world point.

It really make me crazy!!

Any suggestion is appreciated!

Each picker works slightly differently, so it is normal that you get slightly different results from them. Cell picker is the slowest and most accurate. Hardware pickers rely on the z buffer, which has lower precision and may be impacted by rendering (special rendering passes and, z offset/scaling used for coincident topology resolution, etc).

The most important thing is that the world point from vtkPropPicker , vtkCoordinate is not slightly different. I think they are very different:

world point from vtkPropPicker:  (108.0365506828649, 108.0365506828649, 7.141902959080343)
world point from vtkCellPicker:  (108.0089599111793, 108.0089599111793, 6.935962635578974)
world point from vtkCoordinate:  (119.0534474476644, 119.0534474476644, 89.37313989502613)

We can show it as:

import vtk

cone = vtk.vtkConeSource()
cone.SetCenter(150, 150, 0)
cone.SetHeight(100)
cone.SetRadius(50)
cone.Update()
coneMapper = vtk.vtkPolyDataMapper()
coneMapper.SetInputData(cone.GetOutput())
coneMapper.Update()
coneActor = vtk.vtkActor()
coneActor.SetMapper(coneMapper)

ren = vtk.vtkRenderer()
ren.AddActor(coneActor)
ren.SetBackground(0.1, 0.2, 0.4)


renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(ren)
renWin.SetSize(400, 400)

iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)

renWin.Render()
X = 100
Y = 100
picker = vtk.vtkPropPicker()
picker.Pick(X, Y, 0, ren)
pickerWorld = picker.GetPickPosition()
print('world point from vtkPropPicker: ', pickerWorld)

picker = vtk.vtkCellPicker()
picker.Pick(X, Y, 0, ren)
cellWorld = picker.GetPickPosition()
print('world point from vtkCellPicker: ', cellWorld)

coordinate = vtk.vtkCoordinate()
coordinate.SetCoordinateSystemToDisplay()
coordinate.SetValue(X, Y)
coorWorld = coordinate.GetComputedWorldValue(ren)
print('world point from vtkCoordinate: ', coorWorld)


from vedo import *
show(coneActor,
     Point(pickerWorld, c='green'),
     Point(cellWorld, c='red'),
     Point(coorWorld, c='blue'),
     axes=1,
)

And the result is:

From the above figure, we can see that the world point from vtkPropPicker (green point) is similar with that from vtkCellPicker (red point). However, the point from vtkCoordinate (blue point) is very different with vtkPropPicker point.

What you report is consistent what is expected. vtkCellPicker should be accurate, while vtkPropPicker (hardware picker) gives a good approximation. Hardware picker accuracy depends on your camera clipping plane distances and Z buffer computation function. There can room for improvement for this, so if you are familiar with C++ then you can dig into the details and see how you could make things better. Also try latest VTK master, which contains some changes (and there are some ongoing investigation on changed Z buffer computation in latest master).

vtkCoordinate is not a picker. It does not give you 3D coordinates of the clicked point, but intersection of the view ray with some fixed plane (camera focal plane or something similar).

So, what’s the meaning of the above code? Does this code convert the display point to world point?