Skip to content

Commit

Permalink
fix for routing
Browse files Browse the repository at this point in the history
  • Loading branch information
riccardoklinger committed Oct 7, 2023
1 parent eee63f6 commit 402f58b
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 63 deletions.
123 changes: 123 additions & 0 deletions decodeGeom.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Copyright (C) 2019 HERE Europe B.V.
# Licensed under MIT, see full license in LICENSE
# SPDX-License-Identifier: MIT
# License-Filename: LICENSE

from collections import namedtuple
LEVEL = 1
ALTITUDE = 2
ELEVATION = 3
# Reserved values 4 and 5 should not be selectable
CUSTOM1 = 6
CUSTOM2 = 7
THIRD_DIM_MAP = {ALTITUDE: 'alt', ELEVATION: 'elv', LEVEL: 'lvl', CUSTOM1: 'cst1', CUSTOM2: 'cst2'}
FORMAT_VERSION = 1

__all__ = [
'decode', 'dict_decode', 'iter_decode',
'get_third_dimension', 'decode_header', 'PolylineHeader'
]

DECODING_TABLE = [
62, -1, -1, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
22, 23, 24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
]


PolylineHeader = namedtuple('PolylineHeader', 'precision,third_dim,third_dim_precision')


def decode_header(decoder):
"""Decode the polyline header from an `encoded_char`. Returns a PolylineHeader object."""
version = next(decoder)
if version != FORMAT_VERSION:
raise ValueError('Invalid format version')
value = next(decoder)
precision = value & 15
value >>= 4
third_dim = value & 7
third_dim_precision = (value >> 3) & 15
return PolylineHeader(precision, third_dim, third_dim_precision)


def get_third_dimension(encoded):
"""Return the third dimension of an encoded polyline.
Possible returned values are: ABSENT, LEVEL, ALTITUDE, ELEVATION, CUSTOM1, CUSTOM2."""
header = decode_header(decode_unsigned_values(encoded))
return header.third_dim


def decode_char(char):
"""Decode a single char to the corresponding value"""
char_value = ord(char)

try:
value = DECODING_TABLE[char_value - 45]
except IndexError:
raise ValueError('Invalid encoding')
if value < 0:
raise ValueError('Invalid encoding')
return value


def to_signed(value):
"""Decode the sign from an unsigned value"""
if value & 1:
value = ~value
value >>= 1
return value


def decode_unsigned_values(encoded):
"""Return an iterator over encoded unsigned values part of an `encoded` polyline"""
result = shift = 0

for char in encoded:
value = decode_char(char)

result |= (value & 0x1F) << shift
if (value & 0x20) == 0:
yield result
result = shift = 0
else:
shift += 5

if shift > 0:
raise ValueError('Invalid encoding')


def iter_decode(encoded):
"""Return an iterator over coordinates. The number of coordinates are 2 or 3
depending on the polyline content."""

last_lat = last_lng = last_z = 0
decoder = decode_unsigned_values(encoded)

header = decode_header(decoder)
factor_degree = 10.0 ** header.precision
factor_z = 10.0 ** header.third_dim_precision
third_dim = header.third_dim

while True:
try:
last_lat += to_signed(next(decoder))
except StopIteration:
return # sequence completed

try:
last_lng += to_signed(next(decoder))

if third_dim:
last_z += to_signed(next(decoder))
yield (last_lat / factor_degree, last_lng / factor_degree, last_z / factor_z)
else:
yield (last_lat / factor_degree, last_lng / factor_degree)
except StopIteration:
raise ValueError("Invalid encoding. Premature ending reached")

def decode(encoded):
"""Return a list of coordinates. The number of coordinates are 2 or 3
depending on the polyline content."""
return list(iter_decode(encoded))
68 changes: 42 additions & 26 deletions hqgis.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from .GetMapCoordinates import GetMapCoordinates
# Import the code for the dialog
from .hqgis_dialog import HqgisDialog
from .decodeGeom import decode
import os.path
import requests
import json
Expand Down Expand Up @@ -926,53 +927,68 @@ def calculateRouteSingle(self):
self.getCredentials()
type = self.dlg.Type.currentText()
mode = self.dlg.TransportMode.currentText()
if mode == 'public transport':
mode = 'publicTransport'
if mode == "pedestrian" or mode == "bicycle":
type="fast"
#if mode == 'public transport':
# mode = 'publicTransport'
traffic = self.dlg.trafficMode.currentText()
url = "https://route.ls.hereapi.com/routing/7.2/calculateroute.json?apiKey=" + self.appId + "&routeAttributes=shape&mode=" + type + \
";" + mode + ";traffic:" + traffic + "&waypoint0=geo!" + self.dlg.FromLabel.text() + "&waypoint1=geo!" + self.dlg.ToLabel.text()
if self.dlg.trafficMode.currentText() == "enabled":
url = "https://router.hereapi.com/v8/routes?apiKey=" + self.appId + "&return=polyline,summary&routingMode=" + type + \
"&transportMode=" + mode + "&origin=" + self.dlg.FromLabel.text() + "&destination=" + self.dlg.ToLabel.text()
if self.dlg.trafficMode.currentText() == "default":
# print(self.dlg.dateTimeEditBatch.dateTime())
url += "&departure=" + \
self.dlg.dateTimeEdit.dateTime().toString("yyyy-MM-dd'T'hh:mm:ss'Z'")
time2 = self.dlg.dateTimeEdit.dateTime().toString("yyyyMMdd-hh:mm:ss")
timestamp = QDateTime.fromString(time2, "yyyyMMdd-hh:mm:ss")
else:
timestamp = None
timestamp = "any"
print(url)
r = requests.get(url)

if r.status_code == 200:
try:
self.dlg.status2.setText("distance: " +
str(json.loads(r.text)["response"]["route"][0]["summary"]["distance"]) +
" time: " +
str(json.loads(r.text)["response"]["route"][0]["summary"]["travelTime"]))
if self.dlg.routeLayerCheckBox.checkState():
layer = self.createRouteLayer()
responseRoute = json.loads(
r.text)["response"]["route"][0]["shape"]
itemID= 0
layer = self.createRouteLayer()
pr = layer.dataProvider()
features = []
for section in json.loads(r.text)["routes"][0]["sections"]:
print(section)

try:
print("distance: " +
str(section["summary"]["length"]/1000) + " km"
" time: " +
str(section["summary"]["duration"]/60) + " min")

responseRoute = decode(section["polyline"])
vertices = []
for routePoint in responseRoute:
lat = float(routePoint.split(",")[0])
lng = float(routePoint.split(",")[1])
lat = float(routePoint[0])
lng = float(routePoint[1])
vertices.append(QgsPoint(lng, lat))
fet = QgsFeature()
print("succ1")
fet.setGeometry(QgsGeometry.fromPolyline(vertices))
print("succ2")
if not timestamp:
timerS = timestamp
else:
timerS = None
fet.setAttributes([
0,
json.loads(r.text)["response"]["route"][0]["summary"]["distance"],
json.loads(r.text)["response"]["route"][0]["summary"]["travelTime"],
itemID,
section["summary"]["length"]/1000,
section["summary"]["duration"],
mode,
traffic,
timestamp,
timerS,
type
])
pr = layer.dataProvider()
pr.addFeatures([fet])
QgsProject.instance().addMapLayer(layer)
except Exception as e:
print(e)
features.append(fet)
itemID+=1
print(features)
except Exception as e:
print(e)
pr.addFeatures(features)
QgsProject.instance().addMapLayer(layer)

def mapCategories(self, categoryName):
#TODO: add more categories!
Expand Down
25 changes: 5 additions & 20 deletions hqgis_dialog_base.ui
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@
<widget class="QComboBox" name="TransportMode">
<item>
<property name="text">
<string>pedestrian</string>
<string>car</string>
</property>
</item>
<item>
Expand All @@ -286,17 +286,7 @@
</item>
<item>
<property name="text">
<string>public transport</string>
</property>
</item>
<item>
<property name="text">
<string>car</string>
</property>
</item>
<item>
<property name="text">
<string>carHOV</string>
<string>pedestrian</string>
</property>
</item>
<item>
Expand Down Expand Up @@ -376,17 +366,12 @@
<widget class="QComboBox" name="Type">
<item>
<property name="text">
<string>fastest</string>
</property>
</item>
<item>
<property name="text">
<string>shortest</string>
<string>fast</string>
</property>
</item>
<item>
<property name="text">
<string>balanced</string>
<string>short</string>
</property>
</item>
</widget>
Expand Down Expand Up @@ -456,7 +441,7 @@
</item>
<item>
<property name="text">
<string>enabled</string>
<string>default</string>
</property>
</item>
</widget>
Expand Down
23 changes: 6 additions & 17 deletions resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Resource object code
#
# Created by: The Resource Compiler for PyQt5 (Qt v5.9.6)
# Created by: The Resource Compiler for PyQt5 (Qt v5.15.10)
#
# WARNING! All changes made in this file will be lost!

Expand Down Expand Up @@ -178,32 +178,21 @@
\x00\x00\x00\x14\x00\x02\x00\x00\x00\x01\x00\x00\x00\x03\
\x00\x00\x00\x00\x00\x00\x00\x00\
\x00\x00\x00\x2a\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x01\x68\x84\xb0\xe4\x49\
\x00\x00\x01\x8b\x0a\x60\xed\x9e\
"

qt_version = QtCore.qVersion().split('.')
if qt_version < ['5', '8', '0']:
qt_version = [int(v) for v in QtCore.qVersion().split('.')]
if qt_version < [5, 8, 0]:
rcc_version = 1
qt_resource_struct = qt_resource_struct_v1
else:
rcc_version = 2
qt_resource_struct = qt_resource_struct_v2


def qInitResources():
QtCore.qRegisterResourceData(
rcc_version,
qt_resource_struct,
qt_resource_name,
qt_resource_data)

QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)

def qCleanupResources():
QtCore.qUnregisterResourceData(
rcc_version,
qt_resource_struct,
qt_resource_name,
qt_resource_data)

QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data)

qInitResources()

0 comments on commit 402f58b

Please sign in to comment.