You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何固定pyqtgraph中GLTextItem的方位角与仰角?

解决GLTextItem随相机旋转的问题:固定文本角度与尺寸

GLTextItem默认会自动朝向相机(即所谓的“横幅效应”),要让文本保持固定的世界空间角度,同时维持尺寸不随视角变化,可通过重写其paint方法,手动控制绘制时的模型矩阵来实现。

修改后的完整代码

import numpy as np
from PySide6 import QtWidgets, QtGui
import pyqtgraph as pg
from pyqtgraph.opengl import GLViewWidget, GLTextItem
from pyqtgraph.opengl.GLGraphicsItem import GLGraphicsItem

def euler_matrix(azimuth_deg, elevation_deg):
    a, e = np.radians([azimuth_deg, elevation_deg])
    ca, sa = np.cos(a), np.sin(a)
    ce, se = np.cos(e), np.sin(e)
    Rz = np.array([[ ca, -sa, 0],
                   [ sa,  ca, 0],
                   [  0,   0, 1]])
    Rx = np.array([[1,  0,   0],
                   [0, ce, -se],
                   [0, se,  ce]])
    return Rx @ Rz

class CustomText(GLTextItem):
    def __init__(self, *args, worldTextHeight=0.1, fixed_azimuth=0, fixed_elevation=0, **kwargs):
        super().__init__(*args, **kwargs)
        self.worldTextHeight = worldTextHeight
        # 设置固定的旋转矩阵(可自定义角度)
        self.fixed_rot = euler_matrix(fixed_azimuth, fixed_elevation)
        self.setGLOptions('translucent')

    def update_text_size(self):
        # 计算当前位置的像素尺寸,保持文本世界高度固定
        unit_per_pixel = self.view().pixelSize(np.array(self.pos))
        pixel_height = max(1, int(self.worldTextHeight / unit_per_pixel))
        f = QtGui.QFont(self.font)
        f.setPixelSize(pixel_height)
        self.font = f
        self.update()

    def paint(self):
        self.update_text_size()
        gl = self.view().gl
        
        # 保存当前模型视图矩阵
        gl.glPushMatrix()
        
        # 获取相机的视图矩阵,提取平移和缩放,替换旋转为固定旋转
        cam = self.view().cameraParams()
        # 构建固定旋转的模型矩阵:平移到位置 -> 固定旋转 -> 相机缩放
        model_matrix = np.eye(4)
        # 平移到文本位置
        model_matrix[:3, 3] = self.pos
        # 应用固定旋转
        model_matrix[:3, :3] = self.fixed_rot
        # 应用相机的缩放(保持尺寸适配)
        model_matrix[:3, :3] *= cam['distance'] / 5  # 基准距离为5,可根据初始相机位置调整
        
        # 将矩阵转换为OpenGL可用的格式
        gl.glMultMatrixf(model_matrix.T.flatten())
        
        # 禁止父类自动应用相机旋转,直接绘制文本
        GLGraphicsItem.paint(self)
        
        # 恢复之前的矩阵
        gl.glPopMatrix()

class CustomGLView(GLViewWidget):
    def __init__(self):
        super().__init__()
        # 创建固定角度的文本(可自定义azimuth和elevation)
        self.text_item = CustomText(pos=(0,0,0), text="固定角度文本", 
                                   worldTextHeight=1, fixed_azimuth=0, fixed_elevation=0)
        self.addItem(self.text_item)
                
        self.addItem(pg.opengl.GLAxisItem())
        self.setCameraPosition(distance=5)

if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    view = CustomGLView()
    view.show()
    app.exec()

关键说明

  1. 固定旋转矩阵:通过euler_matrix自定义文本的初始旋转角度,确保无论相机如何旋转,文本始终保持该角度。
  2. 手动控制模型矩阵:在paint方法中,跳过GLTextItem默认的相机旋转逻辑,手动构建包含固定旋转的模型矩阵,同时保留相机的缩放和平移,确保文本位置和尺寸正确。
  3. 尺寸固定逻辑:通过pixelSize计算当前视角下的单位像素比例,动态调整文本的像素高度,保证文本在世界空间中的高度固定。

内容的提问来源于stack exchange,提问作者THATS MY QUANT MY QUANTITATIVE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 08:04:53