pyqtgraph将箭头项的原点移动到本地中心

2024-10-16 17:28:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我用pyqtgraph来绘制机器人的轨迹(机器人驾驶的路径)。现在我想在绘图中添加一个标记,以指示机器人当前的位置和方向。我认为ArrowItem是正确的选择,因为它具有缩放不变性,并且可以很容易地旋转。然而,箭头的本地起源是这样的

但我希望它像这样在中心

我怎么能做到呢?我也希望对这个问题有不同的解决办法。在

更新

在应用了eyllansec的代码之后,我遇到了一些渲染问题。一个最小的例子(必须缩放或移动视图才能禁用自动缩放):

import pyqtgraph as pg
import numpy as np
import time

class CenteredArrowItem(pg.ArrowItem):
    def paint(self, p, *args):
        p.translate(-self.boundingRect().center())
        pg.ArrowItem.paint(self, p, *args)


if __name__ == '__main__':
    app = pg.QtGui.QApplication([])  
    window = pg.GraphicsWindow(size=(1280, 720))
    window.setAntialiasing(True)
    tracker = window.addPlot(title='Tracker')

    while True:
        for i in range(300):         
            arrow = CenteredArrowItem(angle=i, headLen=40, tipAngle=45, baseAngle=30)   
            arrow.setPos(i / 300, i / 300)
            tracker.addItem(arrow)
            app.processEvents()
            time.sleep(0.02)
            tracker.removeItem(arrow)

正如您可能注意到的,我在每次迭代中都添加和删除箭头。这是因为arrow.setStyle(angle=i)不工作,因为它不更新箭头的旋转(可能是一个bug)。在


Tags: importselftimeasargs机器人箭头window
2条回答

一种可能的解决方案是覆盖ArrowItem的绘制方法并移动qpaiter:

import numpy as np
from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg

class MyArrowItem(pg.ArrowItem):
    def paint(self, p, *args):
        p.translate(-self.boundingRect().center())
        pg.ArrowItem.paint(self, p, *args)

app = QtGui.QApplication([])

w = QtGui.QMainWindow()
p = pg.PlotWidget()
p.showGrid(x = True, y = True, alpha = 0.3)
w.show()
w.resize(640, 480)
w.setCentralWidget(p)
w.setWindowTitle('pyqtgraph example: Arrow')


a = pg.ArrowItem(angle=-160, tipAngle=60, headLen=40, tailLen=40, tailWidth=20, pen={'color': 'w', 'width': 3},  brush='r')
b = MyArrowItem(angle=-160, tipAngle=60, headLen=40, tailLen=40, tailWidth=20, pen={'color': 'w', 'width': 3})

a.setPos(10,0)
b.setPos(10,0)

p.addItem(a)
p.addItem(b)

## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

如下图所示,红色箭头是默认的ArrowItem,蓝色箭头是偏移量,两者都位于与绘图相同的位置。在

enter image description here

更新:

这个问题是由使用默认变换中心旋转用作坐标中心的项的方法引起的,也就是说(0,0),我们必须移动它:

^{pr2}$

在研究了pyqtgraph的源代码之后,我得到了一个适合我需要的特殊函数。我在创建箭头路径时应用转换,而不是在渲染它时。幸运的是,这也解决了漫游错误(无论出于什么原因)。在

示例:

import pyqtgraph as pg
import numpy as np
import time
import pyqtgraph.functions

class CenteredArrowItem(pg.ArrowItem):
    def setData(self, x, y, angle):
        self.opts['angle'] = angle
        opt = dict([(k, self.opts[k]) for k in ['headLen', 'tipAngle', 'baseAngle', 'tailLen', 'tailWidth']])
        path = pg.functions.makeArrowPath(**opt)
        b = path.boundingRect()
        tr = pg.QtGui.QTransform()              
        tr.rotate(angle)
        tr.translate(-b.x() - b.width() / 2, -b.y() - b.height() / 2)  
        self.path = tr.map(path)
        self.setPath(self.path)
        self.setPos(x, y)


if __name__ == '__main__':
    app = pg.QtGui.QApplication([])  
    window = pg.GraphicsWindow(size=(1280, 720))
    window.setAntialiasing(True)
    tracker = window.addPlot(title='Tracker')

    arrow = CenteredArrowItem(headLen=40, tipAngle=45, baseAngle=30)   
    tracker.addItem(arrow)
    tracker.addItem(pg.InfiniteLine(pos=(0,0), angle=45))
    center = pg.ScatterPlotItem([], [], brush='r')
    tracker.addItem(center)

    while True:
        for i in range(300):
            arrow.setData(i, i, i)     
            center.setData([i], [i])    
            app.processEvents()
            time.sleep(0.02)

相关问题 更多 >