在PyQT中将二维屏幕坐标转换为三维坐标

在PyQT中将二维屏幕坐标转换为三维坐标,qt,3d,pyqt,2d,2d-3d-conversion,Qt,3d,Pyqt,2d,2d 3d Conversion,我第一次使用PyQT,但我很难确定鼠标在3D空间中的位置。显然,这不是一个完美的1对1映射,但假设我在QtGui上单击一个位置(x,y,0)。如何使用相机将鼠标单击转换为其三维位置 上下文:我正在尝试让用户在3-D中绘制样条曲线,为了做到这一点,我需要知道在渲染样条曲线时用户单击的位置。我正在使用PythonOCC构建一个应用程序。我在下面附上了我的代码 import random import sys import IPython from OCC.Display.qtDisplay imp

我第一次使用PyQT,但我很难确定鼠标在3D空间中的位置。显然,这不是一个完美的1对1映射,但假设我在QtGui上单击一个位置(x,y,0)。如何使用相机将鼠标单击转换为其三维位置

上下文:我正在尝试让用户在3-D中绘制样条曲线,为了做到这一点,我需要知道在渲染样条曲线时用户单击的位置。我正在使用PythonOCC构建一个应用程序。我在下面附上了我的代码

import random
import sys
import IPython

from OCC.Display.qtDisplay import qtViewer3d, get_qt_modules
from OCC.gp import gp_Pnt2d, gp_Pnt
from OCC.BRepBuilderAPI import (BRepBuilderAPI_MakeEdge,
                                BRepBuilderAPI_MakeVertex,
                                BRepBuilderAPI_MakeWire)
from OCC.BRepFill import BRepFill_Filling
from OCC.GeomAbs import GeomAbs_C0
from OCC.GeomAPI import GeomAPI_PointsToBSpline
from OCC.TColgp import TColgp_Array1OfPnt


QtCore, QtGui, QtOpenGL = get_qt_modules()

try:
    from OpenGL.GL import (glViewport, glMatrixMode, glOrtho, glLoadIdentity,
                           GL_PROJECTION, GL_MODELVIEW)

except ImportError:
    msg = "for this example, the OpenGL module is required" \
          "why not run \"pip install PyOpenGL\"\?"
    sys.exit(status=1)


class GLWidget(qtViewer3d):
    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self._initialized = False

        midnight = QtCore.QTime(0, 0, 0)
        random.seed(midnight.secsTo(QtCore.QTime.currentTime()))

        self.object = 0
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.image = QtGui.QImage()
        self.bubbles = []
        self.lastPos = QtCore.QPoint()
        self.lines = []
        self.current_point = None
        self.pts = []
        self.shiftHeld = True

        self.trolltechGreen = QtGui.QColor.fromCmykF(0.40, 0.0, 1.0, 0.0)
        self.trolltechPurple = QtGui.QColor.fromCmykF(0.39, 0.39, 0.0, 0.0)

        self.animationTimer = QtCore.QTimer()
        self.animationTimer.setSingleShot(False)
        self.animationTimer.timeout.connect(self.animate)
        self.animationTimer.start(25)

        self.setAutoFillBackground(False)

        self.setMinimumSize(200, 200)
        self.setWindowTitle("Overpainting a Scene")

        # parameters for overpainting
        self.setAttribute(QtCore.Qt.WA_NoSystemBackground, 0)
        self.setAttribute(QtCore.Qt.WA_OpaquePaintEvent)

    def setXRotation(self, angle):
        if angle != self.xRot:
            self.xRot = angle

    def setYRotation(self, angle):
        if angle != self.yRot:
            self.yRot = angle

    def setZRotation(self, angle):
        if angle != self.zRot:
            self.zRot = angle



    def mousePressEvent(self, event):
        self.lastPos = event.pos()

        super(GLWidget, self).mousePressEvent(event)

        worldCoords = super(GLWidget, self).mapToGlobal( self.lastPos )
        print self.lastPos


        if event.buttons() & QtCore.Qt.RightButton and not (event.modifiers() & QtCore.Qt.ShiftModifier):
            print 'first'
            self.pts.append(gp_Pnt(self.lastPos.x(), self.lastPos.y(), 0.0))
        elif event.buttons() & QtCore.Qt.RightButton and (event.modifiers() & QtCore.Qt.ShiftModifier):
            print 'second'
            curve = self.points_to_bspline(self.pts)
            self._display.DisplayShape(curve, update=True)
            self.pts = [] #clear it




    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        """
        if (event.buttons() & QtCore.Qt.LeftButton):
            self.setXRotation(self.xRot + 8 * dy)
            self.setYRotation(self.yRot + 8 * dx)



        elif (event.buttons() & QtCore.Qt.RightButton):
            self.setXRotation(self.xRot + 8 * dy)
            self.setZRotation(self.zRot + 8 * dx)
        """


        self.lastPos = event.pos()
        super(GLWidget, self).mouseMoveEvent(event)

    def paintGL(self):
        if self._inited:
            self._display.Context.UpdateCurrentViewer()

    def paintEvent(self, event):
        if self._inited:

            self._display.Context.UpdateCurrentViewer()
            self.makeCurrent()
            painter = QtGui.QPainter(self)
            painter.setRenderHint(QtGui.QPainter.Antialiasing)

            if self.context().isValid():
                self.swapBuffers()

                if self._drawbox:
                    painter.setPen(QtGui.QPen(QtGui.QColor(0, 0, 0), 1))
                    rect = QtCore.QRect(*self._drawbox)
                    painter.drawRect(rect)

                """
                for bubble in self.bubbles:
                    if bubble.rect().intersects(QtCore.QRectF(event.rect())):
                        bubble.drawBubble(painter)
                """

                painter.end()
                self.doneCurrent()
            else:
                print('invalid OpenGL context: Qt cannot overpaint viewer')

    def showEvent(self, event):
        pass
        #self.createBubbles(20 - len(self.bubbles))

    def sizeHint(self):
        return QtCore.QSize(400, 400)


    def animate(self):
        pass
        """
        for bubble in self.bubbles:
            bubble.move(self.rect())
        self.update()
        """

    def setupViewport(self, width, height):
        side = min(width, height)
        glViewport((width - side) // 2, (height - side) // 2, side, side)

        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        glOrtho(-0.5, +0.5, +0.5, -0.5, 4.0, 15.0)
        glMatrixMode(GL_MODELVIEW)

    def points_to_bspline(self, pnts):
        pts = TColgp_Array1OfPnt(0, len(pnts)-1)
        for n, i in enumerate(pnts):
            pts.SetValue(n, i)
        crv = GeomAPI_PointsToBSpline(pts)
        return crv.Curve()




if __name__ == '__main__':
    def TestOverPainting():
        class AppFrame(QtGui.QWidget):
            def __init__(self, parent=None):
                QtGui.QWidget.__init__(self, parent)
                self.setWindowTitle(self.tr("qtDisplay3d overpainting example"))
                self.resize(640, 480)
                self.canva = GLWidget(self)
                mainLayout = QtGui.QHBoxLayout()
                mainLayout.addWidget(self.canva)
                mainLayout.setContentsMargins(0, 0, 0, 0)
                self.setLayout(mainLayout)

            def runTests(self):
                self.canva._display.Test()

        app = QtGui.QApplication(sys.argv)
        frame = AppFrame()
        frame.show()
        frame.canva.InitDriver()
        frame.runTests()
        app.exec_()

    TestOverPainting()

回答我自己的问题:

(x,y,z,vx,vy,vz)=self.\u display.View.ConvertWithProj(self.lastPos.x(),self.lastPos.y())


给出了x和y可以映射到的整条点线,其中x、y和z是一个点,vx、vy和vz给出了线的参数化。

我不明白。老鼠生活在2D世界中。假设鼠标的x-y移动对应于x-y坐标的变化,那么什么用户操作会改变z坐标?我使用的是3D查看器。可以旋转、缩放和平移视图。如果你点击屏幕上的某个点(x,y),那么我们可以自由选择一个z坐标,比如说,z=0。然后,应该有一个从(x,y,z)到当前世界视图(x',y',z')坐标的映射。简言之,我正在寻找如何访问相机的4x4变换矩阵,如果没有其他。