Skip to content
Snippets Groups Projects
Commit 7812cd3c authored by Jiří Kalvoda's avatar Jiří Kalvoda
Browse files

QGIS: Reorganization and init of clickable vehicles

parent 1e39503e
Branches
No related tags found
No related merge requests found
......@@ -5,6 +5,8 @@ from qgis.gui import *
from qgis.PyQt.QtXml import QDomDocument, QDomElement
from qgis.PyQt.QtWidgets import *
from qgis.PyQt.QtCore import *
from qgis.PyQt.QtGui import *
import sip
from qasync import QEventLoop, asyncClose, asyncSlot, QApplication
import asyncio
......@@ -14,6 +16,7 @@ from communication import dt_to_path
import datetime
import json
import sys, os
import pprint
QgsApplication.setPrefixPath("/usr/", True)
......@@ -24,11 +27,274 @@ crs_wgs=QgsCoordinateReferenceSystem(4326)
crs_wgs_mercator=QgsCoordinateReferenceSystem(3857)
crs_transform = QgsCoordinateTransform(crs_wgs, crs_wgs_mercator, QgsProject.instance())
class ClickableLabel(QLabel):
clicked = pyqtSignal()
def mouseReleaseEvent(self, event):
super(ClickableLabel, self).mouseReleaseEvent(event)
if event.button() == Qt.LeftButton and event.pos() in self.rect():
self.clicked.emit()
communications = {}
async def get_communication(cmd='ssh hluk.fnuk.eu /mnt/jr/prog/run_py server.py'):
if cmd not in communications:
s = await communication.SSHRunSocket().connect(cmd)
communications[cmd] = communication.DownloadServer(s)
return communications[cmd]
class Vehicle:
def __init__(self, json):
self.json = json
class MainWind(QMainWindow):
def __init__(self):
self.map = MapWidget()
QMainWindow.__init__(self)
self.setCentralWidget(self.map)
self._menu_data = self.menuBar().addMenu(self.tr("&Data"))
self._menu_data.addAction("Set date/time", self.set_date_time)
uri = "Point?field=vehicle_type:string(100)&field=route_short_name:string(20)&index=yes"
self.data_layer = QgsVectorLayer(uri,
'PID realtime',
'memory')
# self.data_layer.setAutoRefreshEnabled(True)
# self.data_layer.setAutoRefreshInterval(500)
d = QDomDocument()
d.setContent(open("labeling.xml").read())
labeling = QgsAbstractVectorLayerLabeling.create(d.documentElement(), QgsReadWriteContext())
self.data_layer.setLabeling(labeling)
self.data_layer.setLabelsEnabled(True)
self.data_prov = self.data_layer.dataProvider()
# set the map canvas layer set
self.map.canvas.setLayers([self.data_layer, orm, mapy_cz])
self.feature_identifier = MainTool(self, self.map.canvas)
#self.feature_identifier.setLayer(self.data_layer)
#self.feature_identifier.featureIdentified.connect(self.feature_clicked)
self.map.canvas.setMapTool(self.feature_identifier)
self.current_data = []
def set_date_time(self):
self.window_set_date_time = SetDateTimeWind(self)
self.window_set_date_time.show()
def tool_identifier(self):
self.map.canvas.setMapTool(feature_identifier)
def feature_clicked(self, feature):
print(f"You clicked on feature {feature}")
async def load_data(self, dt):
c = await get_communication()
for fname, data in (await c.get_data(dt)).items():
proc = await asyncio.create_subprocess_exec("gunzip", stdout=asyncio.subprocess.PIPE, stdin=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate(data)
self.show_data(stdout)
return
def show_data(self, source_json):
current_data = []
feats = []
data = json.loads(source_json)
layer_fields = self.data_layer.fields()
for i, dato in enumerate(data["features"]):
feat = QgsFeature(layer_fields)
coord = dato["geometry"]["coordinates"]
point = QgsPointXY(coord[0], coord[1])
geometry = QgsGeometry.fromPointXY(point)
# geometry = QgsGeometry.fromPointXY(QgsPointXY(coord[0]*130000, coord[1]*130000))
feat.setGeometry(geometry)
dato_route_short_name = dato["properties"]["trip"]["gtfs"]["route_short_name"]
feat["route_short_name"] = str(dato_route_short_name)
dato_vehicle_type = dato["properties"]["trip"]["vehicle_type"]
if dato_vehicle_type is None:
if len(dato_route_short_name) and dato_route_short_name[0] in "RSLUV":
feat["vehicle_type"] = "vlak"
else:
feat["vehicle_type"] = "None"
else:
feat["vehicle_type"] = str(dato_vehicle_type["description_cs"])
feats.append(feat)
vehicle = Vehicle(json=dato)
vehicle.point = point
current_data.append(vehicle)
self.current_data = current_data
self.data_prov.truncate()
self.data_prov.addFeatures(feats)
self.data_prov.reloadData()
print("reloadData done")
self.data_layer.triggerRepaint()
print("repaintRequested done")
class SetDateTimeCaptureLabel(ClickableLabel):
def __init__(self, dt, window_set_date_time):
QLabel.__init__(self, str(dt.second))
self.window_set_date_time = window_set_date_time
self.dt = dt
self.setStyleSheet("color: green;")
self.clicked.connect(self.on_click)
@asyncSlot()
async def on_click(self):
print(self.dt)
self.window_set_date_time.hide()
await self.window_set_date_time.window_main.load_data(self.dt)
self.window_set_date_time.window_main = None
class SetDateTimeHour(ClickableLabel):
def __init__(self, hour, window_set_date_time):
QLabel.__init__(self, str(hour))
self.window_set_date_time = window_set_date_time
self.hour = hour
self.clicked.connect(self.on_click)
self.restyle()
def restyle(self):
self.setStyleSheet("font-weight: bold;" if self.hour == self.window_set_date_time.hour else "")
print(self.hour, self.window_set_date_time.hour)
def on_click(self):
self.window_set_date_time.hour = self.hour
self.window_set_date_time.master_changed()
def clearlayout(layout):
for i in reversed(range(layout.count())):
layout.removeItem(layout.itemAt(i))
class SetDateTimeWind(QWidget):
def __init__(self, window_main):
QWidget.__init__(self)
self.window_main = window_main
self.hour = 0
self._calendar = QCalendarWidget()
self._calendar.setFirstDayOfWeek(Qt.Monday)
self._calendar.selectionChanged.connect(self.master_changed)
self._hour_layout = QGridLayout()
self._hours = [SetDateTimeHour(i, self) for i in range(24)]
for i, x in enumerate(self._hours):
self._hour_layout.addWidget(x, i//6, i%6)
self._layout = QVBoxLayout()
self.setLayout(self._layout)
self._layout_calendar = QHBoxLayout()
self._layout.addWidget(self._calendar)
self._layout.addLayout(self._layout_calendar)
self._layout_calendar.addWidget(self._calendar)
self._layout_calendar.addLayout(self._hour_layout)
self._scroll = QScrollArea()
self._scroll.setWidgetResizable(True)
self._layout.addWidget(self._scroll)
self._scroll_widget = QWidget()
self._scroll.setWidget(self._scroll_widget)
self._scroll_layout = QGridLayout()
self._scroll_widget.setLayout(self._scroll_layout)
# self._layout.addLayout(self._scroll_layout)
self._minutes_labels = [QLabel(str(i)) for i in range(60)]
for x in self._minutes_labels:
x.setStyleSheet("font-weight: bold;")
for i, x in enumerate(self._minutes_labels):
self._scroll_layout.addWidget(x, i, 0)
self._10s_layouts = [[QHBoxLayout() for _ in range(6)] for _ in range(60)]
for i, x in enumerate(self._10s_layouts):
for j, y in enumerate(x):
self._scroll_layout.addLayout(y, i, j+1)
self._10s_labels = [[[] for j in range(6)] for _ in range(60)]
self.master_changed()
def update_10s_layouts(self, _10s_labels):
for xa, xb in zip(self._10s_layouts, self._10s_labels):
for ya, yb in zip(xa, xb):
for z in yb:
z.clear()
clearlayout(ya)
self._10s_labels = _10s_labels
for xa, xb in zip(self._10s_layouts, self._10s_labels):
for ya, yb in zip(xa, xb):
for z in yb:
ya.addWidget(z)
@asyncSlot()
async def master_changed(self):
for x in self._hours:
x.restyle()
date = datetime.datetime.combine(self._calendar.selectedDate().toPyDate(), datetime.time(self.hour,0,0))
self.update_10s_layouts([[[QLabel(f"{j}0")] for j in range(6)] for _ in range(60)])
c = await get_communication()
_10s_labels = [[[] for j in range(6)] for _ in range(60)]
dts = await c.list_realtime_data(date, date+datetime.timedelta(hours=1))
# TODO Check změny
for dt in dts:
_10s_labels[dt.minute][dt.second//10].append(SetDateTimeCaptureLabel(dt, self))
self.update_10s_layouts(_10s_labels)
class MainTool(QgsMapTool):
def __init__(self, wnd, canvas):
QgsMapTool.__init__(self, canvas)
self.wnd = wnd
def canvasClicked(self, e):
pt = e.mapPoint()
data_by_dist = sorted([(crs_transform.transform(x.point).distance(pt), x) for x in self.wnd.current_data], key=lambda x:x[0])[:10]
for d, x in data_by_dist:
print(d, pt, x.point)
pprint.pp(x.json)
def canvasMoveEvent(self, e):
print("canvasMoveEvent", e)
def canvasPressEvent(self, e):
print("canvasPressEvent", e)
self.canvasClicked(e)
def canvasReleaseEvent(self, e):
print("canvasReleaseEvent", e)
class MapWidget(QWidget):
def __init__(self):
......@@ -55,6 +321,7 @@ class MapWidget(QWidget):
#self.canvas.xyCoordinates.connect(self.xyCoordinates)
self.actionPan.triggered.connect(self.pan)
#self.toolbar = self.addToolBar("Canvas actions")
#self.toolbar.addAction(self.actionZoomIn)
#self.toolbar.addAction(self.actionZoomOut)
......@@ -70,114 +337,39 @@ class MapWidget(QWidget):
self.pan()
@asyncSlot()
async def zoomIn(self):
# self.canvas.setMapTool(self.toolZoomIn)
s = await communication.SSHRunSocket().connect('ssh hluk.fnuk.eu /mnt/jr/prog/run_py server.py')
c = communication.DownloadServer(s)
#await s.write(b"Ahoj!")
for dt in await c.list_realtime_data(datetime.datetime(2023, 1, 1, 0, 0), datetime.datetime(2100, 1, 1, 0, 0)):
for fname, data in (await c.get_data(dt)).items():
print(fname)
proc = await asyncio.create_subprocess_exec("gunzip", stdout=asyncio.subprocess.PIPE, stdin=asyncio.subprocess.PIPE)
stdout, stderr = await proc.communicate(data)
self.show_data(stdout)
return
self.canvas.setExtent(QgsRectangle(
crs_transform.transform(QgsPointXY(14.373, 50.034)),
crs_transform.transform(QgsPointXY(14.500, 50.103)))
)
def show_data(self, source_json):
feats = []
self.canvas.setDestinationCrs(mapy_cz.crs())
print(source_json)
data = json.loads(source_json)
for i, dato in enumerate(data["features"]):
feat = QgsFeature(layer_fields)
coord = dato["geometry"]["coordinates"]
geometry = QgsGeometry.fromPointXY(QgsPointXY(coord[0], coord[1]))
# geometry = QgsGeometry.fromPointXY(QgsPointXY(coord[0]*130000, coord[1]*130000))
print(geometry)
feat.setGeometry(geometry)
dato_route_short_name = dato["properties"]["trip"]["gtfs"]["route_short_name"]
feat["route_short_name"] = str(dato_route_short_name)
dato_vehicle_type = dato["properties"]["trip"]["vehicle_type"]
if dato_vehicle_type is None:
if len(dato_route_short_name) and dato_route_short_name[0] in "RSLUV":
feat["vehicle_type"] = "vlak"
else:
feat["vehicle_type"] = "None"
else:
feat["vehicle_type"] = str(dato_vehicle_type["description_cs"])
feats.append(feat)
prov.truncate()
prov.addFeatures(feats)
prov.reloadData()
print("reloadData done")
mem_layer.triggerRepaint()
print("repaintRequested done")
async def zoomIn(self):
self.canvas.setMapTool(self.toolZoomIn)
def zoomOut(self):
self.canvas.setMapTool(self.toolZoomOut)
canvas.setMapTool(feature_identifier)
print(mem_layer, mem_layer.crs())
print(mapy_cz, mapy_cz.crs())
print(orm, orm.crs())
def xyCoordinates(self, x):
print(x)
def pan(self):
self.canvas.setMapTool(self.toolPan)
def tool_identifier(self):
canvas.setMapTool(feature_identifier)
def callback(self, feature):
print(f"You clicked on feature {feature}")
# create Qt application
app = QApplication([])
# create main window
wnd = MainWind()
canvas = wnd.map.canvas
# Move the app window to upper left
wnd.size()
wnd.show()
orm = QgsRasterLayer('crs=EPSG:4326&format&type=xyz&url=https://a.tiles.openrailwaymap.org/standard/%7Bz%7D/%7Bx%7D/%7By%7D.png&zmax=19&zmin=0', 'ORM-standard', 'wms')
osm = QgsRasterLayer('crs=EPSG:4326&format&type=xyz&url=http://tile.openstreetmap.org/%7Bz%7D/%7Bx%7D/%7By%7D.png&zmax=19&zmin=0', 'ORM-standard', 'wms')
mapy_cz = QgsRasterLayer('http-header:referer=https://mapy.cz/ &referer=https://mapy.cz/ &type=xyz&url=https://mapserver.mapy.cz/base-m/%7Bz%7D-%7Bx%7D-%7By%7D', 'mapycz-standard', 'wms')
# create main window
wnd = MainWind()
canvas = wnd.map.canvas
wnd.show()
uri = "Point?field=vehicle_type:string(100)&field=route_short_name:string(20)&index=yes"
mem_layer = QgsVectorLayer(uri,
'PID realtime',
'memory')
# mem_layer.setAutoRefreshEnabled(True)
# mem_layer.setAutoRefreshInterval(500)
d = QDomDocument()
d.setContent(open("labeling.xml").read())
labeling = QgsAbstractVectorLayerLabeling.create(d.documentElement(), QgsReadWriteContext())
mem_layer.setLabeling(labeling)
mem_layer.setLabelsEnabled(True)
prov = mem_layer.dataProvider()
layer_fields = mem_layer.fields()
canvas.setExtent(QgsRectangle(
crs_transform.transform(QgsPointXY(14.373, 50.034)),
crs_transform.transform(QgsPointXY(14.500, 50.103)))
)
# set the map canvas layer set
canvas.setLayers([mem_layer, orm, mapy_cz])
feature_identifier = QgsMapToolIdentifyFeature(canvas)
feature_identifier.featureIdentified.connect(wnd.map.callback)
canvas.setDestinationCrs(mapy_cz.crs())
# run!
event_loop = QEventLoop(app)
......@@ -185,8 +377,6 @@ asyncio.set_event_loop(event_loop)
app_close_event = asyncio.Event()
app.aboutToQuit.connect(app_close_event.set)
print(mem_layer, mem_layer.crs())
with event_loop:
event_loop.run_until_complete(app_close_event.wait())
#retval = app.exec_()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment