PyQt5のQGraphicsViewにGPXファイルを表示してワイプも表示してみた
2020/10/28 categories:PyQt5| tags:Python|QGraphicsView|GPX|PyQt5|
以前作成したGPXファイルを表示するプログラムにワイプを表示する機能を追加してみました。イメージはAviUtlのVSD for GPSなどで作成する動画のような感じです。
ワイプの表示
GPXファイルの読み込みはgpxpyを使用して、QGraphicsViewのQGraphicsScene上にアイテムを描画していて、これらの処理は以前作成したプログラムと同じです。ワイプ部分は、読み込んだGPXファイルの一部分をnumpy配列のスライスで抜き出して、QGraphicsPathItemとして描画するという処理にしています。
x1, y1 = self.gpx_position[0], self.gpx_position[1]
ellipse1 = QtWidgets.QGraphicsEllipseItem()
ellipse1.setRect(x1 - self.ellipse_size/2, y1 - self.ellipse_size/2, self.ellipse_size, self.ellipse_size)
array = self.gpx[:, s:e]
polygon = QtGui.QPolygonF()
polygon_offset_x, polygon_offset_y = x1 - self.gpx[0][self.gpx_index], y1 - self.gpx[1][self.gpx_index]
for lat, lon in zip(array[0], array[1]):
polygon.append( QtCore.QPointF(polygon_offset_x + lat, polygon_offset_y + lon) )
path = QtGui.QPainterPath()
path.addPolygon(polygon)
item = QtWidgets.QGraphicsPathItem(path)
ソースコード
import cv2
import gpxpy
import numpy as np
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.central_widget = QtWidgets.QWidget(self)
self.vertical_layout = QtWidgets.QVBoxLayout(self.central_widget)
self.graphics_view = QtWidgets.QGraphicsView(self.central_widget)
self.graphics_view.setScene( QtWidgets.QGraphicsScene(0, 0, 600, 600, self.graphics_view) )
self.slider = QtWidgets.QSlider(QtCore.Qt.Horizontal, self.central_widget)
self.vertical_layout.addWidget(self.graphics_view)
self.vertical_layout.addWidget(self.slider)
self.setCentralWidget(self.central_widget)
self.resize(800, 660)
self.slider.valueChanged.connect(self.update_view)
self.gpx = None
self.gpx_index = 0
self.gpx_index_max = 0
self.gpx_range = 20
self.gpx_size = 600
self.gpx_position = [500, 100]
self.ellipse_size = 10
self.gpx_polygon = None
def update_view(self):
self.gpx_index = self.slider.value()
s, e = self.gpx_index - self.gpx_range, self.gpx_index + self.gpx_range
if s < 0:
s = 0
if e > self.gpx_index_max - 1:
e = self.gpx_index_max - 1
x1, y1 = self.gpx_position[0], self.gpx_position[1]
ellipse1 = QtWidgets.QGraphicsEllipseItem()
ellipse1.setRect(x1 - self.ellipse_size/2, y1 - self.ellipse_size/2, self.ellipse_size, self.ellipse_size)
ellipse2 = QtWidgets.QGraphicsEllipseItem()
x2, y2 = self.gpx_polygon.at(self.gpx_index).x(), self.gpx_polygon.at(self.gpx_index).y()
ellipse2.setRect(x2 - self.ellipse_size/2, y2 - self.ellipse_size/2, self.ellipse_size, self.ellipse_size)
array = self.gpx[:, s:e]
polygon = QtGui.QPolygonF()
polygon_offset_x, polygon_offset_y = x1 - self.gpx[0][self.gpx_index], y1 - self.gpx[1][self.gpx_index]
for lat, lon in zip(array[0], array[1]):
polygon.append( QtCore.QPointF(polygon_offset_x + lat, polygon_offset_y + lon) )
path = QtGui.QPainterPath()
path.addPolygon(polygon)
item = QtWidgets.QGraphicsPathItem(path)
self.graphics_view.scene().clear()
self.graphics_view.scene().addItem(QtWidgets.QGraphicsPolygonItem(self.gpx_polygon))
self.graphics_view.scene().addItem(item)
self.graphics_view.scene().addItem(ellipse1)
self.graphics_view.scene().addItem(ellipse2)
def set_array(self, array):
self.gpx = array.copy()
self.gpx[0] = ( self.gpx[0] - min(self.gpx[0]) )
self.gpx[0] = self.gpx[0] * (self.gpx_size / max(self.gpx[0]) )
self.gpx[1] = ( self.gpx[1] - min(self.gpx[1]) )
self.gpx[1] = self.gpx_size - self.gpx[1] * (self.gpx_size / max(self.gpx[1]) )
self.gpx_index = 0
self.gpx_index_max = array.shape[1]
self.slider.setMaximum(self.gpx_index_max-1)
lon_def = array[0] - min(array[0])
lat_def = array[1] - min(array[1])
if max(lon_def) > max(lat_def):
ratio = 600 / max(lon_def)
else:
ratio = 600 / max(lat_def)
polygon = QtGui.QPolygonF()
longitude = (lon_def) * ratio
latitude = 600 - (lat_def) * ratio
for lat, lon in zip(longitude, latitude):
polygon.append( QtCore.QPointF(lat, lon) )
self.gpx_polygon = polygon
self.update_view()
def main():
gpx_file = open('track-1155.gpx', mode='r', encoding='utf8')
gpx = gpxpy.parse(gpx_file)
array = np.array([
[p.longitude for p in gpx.tracks[0].segments[0].points],
[p.latitude for p in gpx.tracks[0].segments[0].points]
])
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.set_array(array)
window.show()
app.exec()
if __name__ == '__main__':
main()