I am using vtkCellPicker
in my project. In some situation, the vtkCellPicker
do not work. For example:
import vtkmodules.all as vtk
polyData = vtk.vtkPolyData()
polyData.SetPoints(vtk.vtkPoints())
polyData.SetVerts(vtk.vtkCellArray())
polyData.GetPoints().InsertNextPoint(1, 1, 1)
polyData.GetVerts().InsertNextCell(1)
polyData.GetVerts().InsertCellPoint(0)
polyData.GetPoints().Modified()
polyData.GetVerts().Modified()
polyData.Modified()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputData(polyData)
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(255, 255, 0)
actor.GetProperty().SetPointSize(10)
#################### add user matrix
# x = [1, 0, 0]
# y = [0, 0, 1]
# z = [0, 1, 0]
#
# element = [
# x[0], y[0], z[0], 0,
# x[1], y[1], z[1], 0,
# x[2], y[2], z[2], 0,
# 0, 0, 0, 1
# ]
#
# matrix = vtk.vtkMatrix4x4()
# matrix.DeepCopy(element)
# actor.SetUserMatrix(matrix)
#####################
def mousemove(iren, event):
pos = iren.GetEventPosition()
picker = vtk.vtkCellPicker()
picker.SetTolerance(0.01)
picker.Pick(pos[0], pos[1], 0, render)
actor = picker.GetProp3D()
if actor == None:
print('no actor')
else:
print('pick actor')
render = vtk.vtkRenderer()
render.AddActor(actor)
renWin = vtk.vtkRenderWindow()
renWin.AddRenderer(render)
renWin.Render()
iren = vtk.vtkRenderWindowInteractor()
iren.AddObserver('MouseMoveEvent', mousemove)
iren.SetRenderWindow(renWin)
iren.Initialize()
iren.Start()
In the above code, we can pick the actor. However, if I uncommet the code for use matrix:
#################### add user matrix
# x = [1, 0, 0]
# y = [0, 0, 1]
# z = [0, 1, 0]
#
# element = [
# x[0], y[0], z[0], 0,
# x[1], y[1], z[1], 0,
# x[2], y[2], z[2], 0,
# 0, 0, 0, 1
# ]
#
# matrix = vtk.vtkMatrix4x4()
# matrix.DeepCopy(element)
# actor.SetUserMatrix(matrix)
#####################
The actor would not be picked.
After looking for the C++ source code for vtkCellPicker
, I find the reason is:
In the vtkPicker
obtain the scale in line 630:
this->Transform->SetMatrix(lastMatrix);
this->Transform->Push();
this->Transform->Inverse();
this->Transform->GetScale(scale); // need to scale the tolerance
However, if the user matrix is:
x = [1, 0, 0]
y = [0, 0, 1]
z = [0, 1, 0]
the obtained scale is [-1, -1, -1]
, which make the actor would never be picked in this->IntersectWithLine()
since tol<0
.
The GetScale
method is tested as:
import vtkmodules.all as vtk
transform = vtk.vtkTransform()
x = [1, 0, 0]
y = [0, 0, 1]
z = [0, 1, 0]
element = [
x[0], y[0], z[0], 0,
x[1], y[1], z[1], 0,
x[2], y[2], z[2], 0,
0, 0, 0, 1
]
matrix = vtk.vtkMatrix4x4()
matrix.DeepCopy(element)
transform.SetMatrix(matrix)
s = transform.GetScale()
print(s)
Is this a bug? Any suggestion is appreciated~~~