【问题标题】:How to connect an oval or cylinder formed shape between two updating 3D points using pyqtgraph and OpenGL?如何使用 pyqtgraph 和 OpenGL 在两个更新的 3D 点之间连接椭圆或圆柱形状?
【发布时间】:2020-07-22 02:34:47
【问题描述】:

我想使用 pyqtgraph 和 OpenGL 在 3D 空间中的两个更新点之间形成一个形状。目前,我只发现可以将GLLinePlotItemGLMeshItem 与两点之间的顶点和平面连接起来。但是,我希望在点之间连接一个椭圆形或圆柱体形式,但我似乎无法找到一种方法来使用集成的 MeshData 球体和圆柱体,而不跳入复杂的数学、旋转矩阵和三角函数。

有没有更简单的方法,类似于 GLLinePlotItem 或 GLMeshItem?

说明我现在拥有什么,以及我想要拥有什么:

示例代码:

from pyqtgraph.Qt import QtCore, QtGui
import pyqtgraph as pg
import pyqtgraph.opengl as gl
import numpy as np
import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QMainWindow, QApplication
from random import randint

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        w = gl.GLViewWidget()
        w.show()
        w.setCameraPosition(distance=15, azimuth=-90)

        self.timer = QTimer()
        self.timer.start(1000)
        self.timer.timeout.connect(self.start)

        g = gl.GLGridItem()
        g.scale(2, 2, 1)
        w.addItem(g)


        self.md = gl.MeshData.sphere(rows=10, cols=20)
        self.m1 = gl.GLMeshItem(meshdata=self.md,
                                smooth=True,
                                color=(1, 0, 0, 0.2),
                                shader="balloon",
                                glOptions="additive")
        w.addItem(self.m1)

        self.lineMesh = gl.GLLinePlotItem(width=1, antialias=False)
        w.addItem(self.lineMesh)


    def start(self):
        # coordinates

        point1 = np.array([randint(0,25), randint(0,25), 0])
        point2 = np.array([randint(0,25), randint(0,25), 20])

        line = np.array([point1, point2])
        self.lineMesh.setData(pos=line)

        length = (((point2[0] - point1[0]) ** 2 + (point2[1] - point1[1]) ** 2 + (
                point2[2] - point1[2]) ** 2) ** 0.5)*0.5

        center = (point1 + point2) / 2
        #radius = np.linalg.norm(point2 - point1) / 2


        self.md = gl.MeshData.sphere(rows=10, cols=20, radius=[1])
        self.m1.setMeshData(meshdata=self.md)

        self.m1.resetTransform()
        self.m1.scale(1, 1, length)
        self.m1.translate(*center)



if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainWindow()
    ex.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python opengl pyqt pyqtgraph


    【解决方案1】:

    我不认为你可以避免在这里做一些数学运算,但是三角函数还不错:

            v = point2 - point1
            theta = np.arctan2(v[1], v[0])
            phi = np.arctan2(np.linalg.norm(v[:2]), v[2])
    
            tr = pg.Transform3D()
            tr.translate(*point1)
            tr.rotate(theta * 180 / np.pi, 0, 0, 1)
            tr.rotate(phi * 180 / np.pi, 0, 1, 0)
            tr.scale(1, 1, np.linalg.norm(v) / 2)
            tr.translate(0, 0, 1)
    
            self.m1.setTransform(tr)
    

    如果你更喜欢线性代数而不是三角函数,那也不错,虽然有点冗长:

            # pick 4 points on the untransformed sphere
            a = np.array([
                [0., 0., -1.],
                [0., 0., 1.],
                [1., 0., -1.],
                [0., 1., -1.],
            ])
    
            # and 4 corresponding points on the transformed sphere
            v1 = np.cross(point1-point2, [0., 0., 1.])
            v2 = np.cross(point1-point2, v1)
            b = np.array([
                point1,
                point2,
                point1 + v1 / np.linalg.norm(v1),
                point1 + v2 / np.linalg.norm(v2),
            ])
    
            # solve the transform mapping from a to b
            tr = pg.solve3DTransform(a, b)
    
            # make this transform work in opengl's homogeneous coordinate system
            tr[3,3] = 1
    
            self.m1.setTransform(tr)
    

    【讨论】:

    • 非常感谢卢克。它完美地工作。我使用了第一个解决方案,因为我最了解这个解决方案。
    • 你能帮我找到最后一个旋转“psi”吗?
    • 你的意思是围绕连接两个端点的轴旋转吗?我不确定您要使用什么标准,因为这需要第三个参考点..
    • 是的。然而,你是对的。我实际上有第三个参考点,我想出了如何计算角度。感谢您的指导。
    猜你喜欢
    • 2016-02-05
    • 2010-12-25
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    • 2017-03-04
    • 1970-01-01
    • 2014-08-31
    • 1970-01-01
    相关资源
    最近更新 更多