diff --git a/decodeGeom.py b/decodeGeom.py new file mode 100644 index 0000000..d41117e --- /dev/null +++ b/decodeGeom.py @@ -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)) \ No newline at end of file diff --git a/hqgis.py b/hqgis.py index 929d0da..f812478 100644 --- a/hqgis.py +++ b/hqgis.py @@ -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 @@ -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! diff --git a/hqgis_dialog_base.ui b/hqgis_dialog_base.ui index db8da86..7e2466d 100644 --- a/hqgis_dialog_base.ui +++ b/hqgis_dialog_base.ui @@ -276,7 +276,7 @@ - pedestrian + car @@ -286,17 +286,7 @@ - public transport - - - - - car - - - - - carHOV + pedestrian @@ -376,17 +366,12 @@ - fastest - - - - - shortest + fast - balanced + short @@ -456,7 +441,7 @@ - enabled + default diff --git a/resources.py b/resources.py index ad94c4b..58d1294 100644 --- a/resources.py +++ b/resources.py @@ -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! @@ -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()