marcomusy
(Marco Musy)
March 15, 2022, 1:03pm
1
Picker is not picking at the correct position - there seems to be a factor 2 somewhere which screws up the result:
import sys
import vtk
from PyQt5 import Qt
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
class MainWindow(Qt.QMainWindow):
def __init__(self, parent = None):
Qt.QMainWindow.__init__(self, parent)
self.frame = Qt.QFrame()
self.vl = Qt.QVBoxLayout()
self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
self.ren = vtk.vtkRenderer()
self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()
self.picker = vtk.vtkPropPicker()
# Create source
source = vtk.vtkSphereSource()
# Create a mapper
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(source.GetOutputPort())
# Create an actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
self.ren.AddActor(actor)
self.ren.ResetCamera()
self.vl.addWidget(self.vtkWidget)
self.frame.setLayout(self.vl)
self.setCentralWidget(self.frame)
self.show()
self.iren.AddObserver("LeftButtonPressEvent", self.onclick)
self.iren.Initialize()
self.iren.Start()
def onclick(self, iren, event):
x, y = self.iren.GetEventPosition()
print("Left button pressed at", x,y)
self.picker.PickProp(x, y, self.ren)
picked = self.picker.GetProp3D()
if picked:
picked3d = self.picker.GetPickPosition()
print(" 3d picked pt", picked3d)
source = vtk.vtkSphereSource()
source.SetRadius(0.02)
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(source.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(255,0,0)
actor.SetPosition(picked3d)
self.ren.AddActor(actor)
if __name__ == "__main__":
app = Qt.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
(clicking the black empty area close to the bottom-left corner places a red sphere).
I’m also getting a warning message:
qt.qpa.window: <QNSWindow: 0x7fa833705d90; contentView=<QNSView: 0x7fa833704bd0; QCocoaWindow(0x60000167c790, window=QWidgetWindow(0x60000057d4a0, name="QFrameClassWindow"))>> has active key-value observers (KVO)! These will stop working now that the window is recreated, and will result in exceptions when the observers are removed. Break in QCocoaWindow::recreateWindowIfNeeded to debug.
System info:
vtk version : 9.1.0
python version : 3.9.7 (default, Sep 16 2021, 08:50:36) [Clang 10.0.0 ]
python interpreter: /Users/mmusy/Software/miniconda3/bin/python
system : Darwin 21.3.0 posix x86_64
Screen: Color LCD
Size: 1280 x 800
lassoan
(Andras Lasso)
March 17, 2022, 5:40am
2
It seems that event position is not scaled with the correct device pixel ratio in QVTKRenderWindowInteractor. You can add logs or attach a debugger to see why that happens. Maybe using tolerance and other techniques that are used in QVTKInteractorAdapter will have to be implemented in the Python class.
You could have a look a this error report, too - maybe they are related problems:
Dear people,
Recently I migrated code from VTK 8.1 to 9.1. Giving or taking minor changes (mostly related to deprecated API), most of VTK code stayed the same. However, the behavior of vtkPropPicker::GetPickPosition() has changed. It now returns the wrong world pick coordinates. Here’s the code (it was fine in VTK 8.1):
// Get pick position in 2D screen coordinates.
int* clickPos = this->GetInteractor()->GetEventPosition();
// Get the 3D object under the 2D screen coordinates (ray casting…
Thanks for posting this problem. Same problem with PySide6 on Mac OSX (see code below). Picking does not work. The message “3d picked pt” never appears. Still having the problem and looking for a solution.
(comcab) NIWA-1019500~/comcab-master$ uname -a
Darwin NIWA-1019500 21.4.0 Darwin Kernel Version 21.4.0: Fri Mar 18 00:45:05 PDT 2022; root:xnu-8020.101.4~15/RELEASE_X86_64 x86_64
python --version; python -c “import vtk;print(f’{vtk.VTK_MAJOR_VERSION}.{vtk.VTK_MINOR_VERSION}’)”
Python 3.9.4
9.1
import sys
import vtk
from PySide6 import QtWidgets
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent = None):
QtWidgets.QMainWindow.__init__(self, parent)
self.frame = QtWidgets.QFrame()
self.vl = QtWidgets.QVBoxLayout()
self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
self.ren = vtk.vtkRenderer()
self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()
self.picker = vtk.vtkPropPicker()
# Create source
source = vtk.vtkSphereSource()
# Create a mapper
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(source.GetOutputPort())
# Create an actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
self.ren.AddActor(actor)
self.ren.ResetCamera()
self.vl.addWidget(self.vtkWidget)
self.frame.setLayout(self.vl)
self.setCentralWidget(self.frame)
self.show()
self.iren.AddObserver("LeftButtonPressEvent", self.onclick)
self.iren.Initialize()
self.iren.Start()
def onclick(self, iren, event):
x, y = self.iren.GetEventPosition()
print("Left button pressed at", x,y)
self.picker.PickProp(x, y, self.ren)
picked = self.picker.GetProp3D()
if picked:
picked3d = self.picker.GetPickPosition()
print(" 3d picked pt", picked3d)
source = vtk.vtkSphereSource()
source.SetRadius(0.02)
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(source.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(255,0,0)
actor.SetPosition(picked3d)
self.ren.AddActor(actor)
if name == “main ”:
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec_())
It seems vtkCellPicker suffers from the same problem (OS X and VTK 9.1), see code below. The picker returns the wrong world position.
import sys
import math
import vtk
from PySide6 import QtWidgets
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent = None):
QtWidgets.QMainWindow.__init__(self, parent)
self.frame = QtWidgets.QFrame()
self.vl = QtWidgets.QVBoxLayout()
self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
self.ren = vtk.vtkRenderer()
self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()
self.picker = vtk.vtkCellPicker() #vtkPropPicker()
# Create source
source = vtk.vtkSphereSource()
# Create a mapper
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(source.GetOutputPort())
# Create an actor
actor = vtk.vtkActor()
actor.SetMapper(mapper)
self.ren.AddActor(actor)
self.ren.ResetCamera()
# self.iren.SetPicker(self.picker)
self.vl.addWidget(self.vtkWidget)
self.frame.setLayout(self.vl)
self.setCentralWidget(self.frame)
self.show()
self.iren.AddObserver("LeftButtonPressEvent", self.onclick)
self.iren.Initialize()
self.iren.Start()
def onclick(self, iren, event):
x, y = self.iren.GetEventPosition()
print("Left button pressed at", x,y)
cellId = self.picker.Pick(x, y, 0, self.ren)
if cellId >= 0:
xyz = self.picker.GetPickPosition()
radius = math.sqrt(xyz[0]**2 + xyz[1]**2 + xyz[2]**2)
print(f" 3d picked pt {xyz} radius: {radius} ")
source = vtk.vtkSphereSource()
source.SetRadius(0.02)
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(source.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(1,0,0)
actor.SetPosition(xyz)
self.ren.AddActor(actor)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
sys.exit(app.exec())
Depending on where you pick, you might see something like
Left button pressed at 150 172
3d picked pt (0.19066947142160784, -0.22312961309267365, -0.3825671026006565) radius: 0.48218177025198994
(The radius should be close to 1.)