def calculate(self): overwrite = self.checkBoxRemovePrevious.isChecked() LOG.debug("isochrones layer name = {}".format(self.getBasename())) try: point = self.originSearchBox.point except WrongLocationException as e: pushWarning( self.tr("Invalid location: {error_message}").format( error_message=str(e) ) ) return try: intervals = self.getInterval() if not (1 <= len(intervals) <= 10): raise Exception( self.tr("Must have at least one and maximum 10 intervals.") ) except Exception as e: pushWarning("Invalid intervals: %s" % str(e)) return vehicle = self.comboBoxVehicles.currentIndex() profile, costingOptions = vehicles.options_for_vehicle(vehicle) is_isodistance = ( self.comboBoxReachabilityMode.currentText() == self.reachabilityMode["isodistance"] ) costingOptions["shortest"] = is_isodistance colors = [] try: colors = self.getColorFromInterval() generateIsochrones( point, profile, costingOptions, intervals, colors, self.getBasename(), overwrite, ) except OverwriteError as e: LOG.error(e) pushWarning( self.tr("Please change the basename or activate the overwrite checkbox") ) except Valhalla400Exception as e: # Expecting the content can be parsed as JSON, see # https://valhalla.readthedocs.io/en/latest/api/turn-by-turn/api-reference/#http-status-codes-and-conditions json_error = json.loads(str(e)) pushWarning( self.tr('Can not generate the error because "{error_message}"').format( error_message=json_error.get("error") ) ) except Exception as e: pushWarning("could not generate isochrones") raise Exception(e)
def prepareIsochronesParameters(self, points, profile, options, intervals, colors): travel_constraint = "distance" if options.get('shortest') else "time" # build contour json if len(intervals) != len(colors): pushWarning( self. tr("The number of intervals and colors are different, using default color" )) contours = [{travel_constraint: x} for x in intervals] else: contours = [] for i in range(0, len(intervals)): contours.append({ travel_constraint: intervals[i], "color": colors[i] }) params = dict( costing=profile, locations=points, polygons=True, contours=contours, costing_options={profile: options}, ) return params
def calculate(self): try: ( layer, points, profile, allAreasToAvoidWGS, costingOptions, allPatrolAreaWGS, ) = self.prepareValhalla() except TypeError: pushWarning( self.tr("Could not compute patrol: no polygon selected")) return try: layer.updateRoute(points, profile, allAreasToAvoidWGS, costingOptions, allPatrolAreaWGS) self.btnNavigate.setEnabled(True) except Exception as e: if "Failed to find a route between two locations for Chinese Postman route" in str( e): self.show_chinese_postman_warning(str(e)) else: pushWarning(str(e)) LOG.error(e, exc_info=True) LOG.error("Could not compute route")
def updateFromPolyline(self, polyline, profile, costingOptions): try: response = self.valhalla.mapmatching(polyline, profile, costingOptions) self.computeFromResponse(response) except Exception as e: LOG.warning(e) pushWarning(self.tr("Could not compute route from polyline"))
def getCoordFromGPS(self): connection = getGpsConnection() if connection: info = connection.currentGPSInformation() pointString = "{:.6f},{:.6f}".format(info.longitude, info.latitude) self.searchBox.setText(pointString) self.setPoint(QgsPointXY(info.longitude, info.latitude)) # TODO: Perhaps put reverse geocoding here self.setLocationName(pointString) else: pushWarning(self.tr("Cannot connect to GPS"))
def updateFromPins(self): try: for i, pin in enumerate(self.pins): self.points[i] = QgsPointXY(pin.position()) response = self.valhalla.route(self.points, self.profile, self.costingOptions) self.computeFromResponse(response) self.triggerRepaint() except Exception as e: logging.error(e, exc_info=True) # TODO more fine-grained error control pushWarning(self.tr("Could not compute route")) logging.error("Could not compute route")
def getTiles(self): try: remote_tiles = self.getRemoteTiles() except Exception as e: pushWarning("Cannot get tiles from the URL because %s " % str(e)) remote_tiles = [] local_tiles = self.getLocalTiles() # Merge the tiles all_tiles = [] all_tiles.extend(remote_tiles) remote_tile_ids = [remote_tile["id"] for remote_tile in remote_tiles] for local_tile in local_tiles: if local_tile["id"] not in remote_tile_ids: all_tiles.append(local_tile) return all_tiles
def calculate(self): try: ( layer, points, profile, allAreasToAvoidWGS, costingOptions, ) = self.prepareValhalla() except TypeError: # exit if prepareValhalla raised a warning to the user return try: layer.updateRoute(points, profile, allAreasToAvoidWGS, costingOptions) self.btnNavigate.setEnabled(True) except Exception as e: LOG.error(e, exc_info=True) # TODO more fine-grained error control pushWarning(self.tr("Could not compute route")) LOG.error("Could not compute route") raise (e)
def reprojectToWGS84(self, geom): geomType = geom.type() if geomType == QgsWkbTypes.LineGeometry: geomList = geom.asPolyline() elif geomType == QgsWkbTypes.PolygonGeometry: geomList = geom.asPolygon() newGeom = [] for j in range(len(geomList)): if geomType == QgsWkbTypes.LineGeometry: newGeom.append(self.transformer.transform(geomList[j])) elif geomType == QgsWkbTypes.PolygonGeometry: line = geomList[j] for i in range(len(line)): point = line[i] newGeom.append(self.transformer.transform(point)) if geomType == QgsWkbTypes.LineGeometry: return QgsGeometry.fromPolylineXY(newGeom) elif geomType == QgsWkbTypes.PolygonGeometry: return QgsGeometry.fromPolygonXY([newGeom]) else: # TODO, from qgis 3.18 it will be possible to use the method # QgsWkbTypes.translatedDisplayString() to have much nicer error message pushWarning( "not implemented: cannot save layer type: {}".format(geomType))
def calculate(self): layer = self.layerSelector.getSelectedLayer() if layer is None: pushWarning(self.tr("Please, select a valid destination layer")) return try: points = [self.originSearchBox.point] points.extend(self.waypoints) points.append(self.destinationSearchBox.point) except WrongLocationException as e: pushWarning(self.tr("Invalid location:") + str(e)) return if None in points: pushWarning( self.tr("Both origin and destination points are required")) return shortest = self.radioButtonShortest.isChecked() vehicle = self.comboBoxVehicles.currentIndex() profile, costingOptions = vehicles.options_for_vehicle(vehicle) ''' areasToAvoid = None if self.radioAreasToAvoidPolygon.isChecked(): areasToAvoid = self.areasToAvoid elif self.radioAreasToAvoidLayer.isChecked(): avoidLayer = self.comboAreasToAvoidLayers.currentData() if avoidLayer is not None: geoms = [f.geometry() for f in avoidLayer.getFeatures()] areasToAvoid = QgsGeometry.collectGeometry(geoms) # TODO: use areas to avoid ''' if shortest: costingOptions["shortest"] = True try: layer.updateRoute(points, profile, costingOptions) self.btnNavigate.setEnabled(True) except Exception as e: raise logging.error(e, exc_info=True) # TODO more fine-grained error control pushWarning(self.tr("Could not compute route")) logging.error("Could not compute route")
def prepareValhalla(self): ( layer, points, profile, allAreasToAvoidWGS, costingOptions, ) = super().prepareValhalla() if self.radioPatrolAreaPolygon.isChecked(): # Currently only single polygon is accepted patrolArea = self.patrolArea canvasCrs = self.canvas.mapSettings().destinationCrs() transformer = transformToWGS(canvasCrs) if patrolArea is None: # if the custom polygon button is checked, but no polygon has been drawn pushWarning( self. tr("Custom polygon button is checked, but no polygon is drawn" )) return elif self.radioPatrolAreaLayer.isChecked(): patrolLayer = self.comboPatrolAreaLayers.currentData() if patrolLayer is not None: layerCrs = patrolLayer.crs() transformer = transformToWGS(layerCrs) patrolFeatures = [f for f in patrolLayer.getFeatures()] if len(patrolFeatures) != 1: pushWarning( self. tr("The polygon layer for Patrol must contain exactly only one polygon." )) return else: patrolArea = patrolFeatures[0].geometry() else: # If polygon layer button is checked, but no layer polygon is selected pushWarning( self. tr("Polygon layer button is checked for Patrol, but no layer polygon is selected" )) return else: # No areas to avoid patrolArea = None patrolAreaWGS = None # transform to WGS84 (Valhalla's requirement) if patrolArea: patrolAreaJson = json.loads(patrolArea.asJson()) patrolAreaWGS = [] polygon = patrolAreaJson["coordinates"][0] for point in polygon: pointWGS = transformer.transform(point[0], point[1]) patrolAreaWGS.append([pointWGS.x(), pointWGS.y()]) return layer, points, profile, allAreasToAvoidWGS, costingOptions, patrolAreaWGS
def buttonClicked(self): status = self.data["status"] if status == DataCatalogueClient.UP_TO_DATE: ret = self.dataCatalogueClient.uninstall(self.data["id"]) if not ret: pushWarning( self. tr("Cannot remove previous version of the {name} map package" ).format(name=self.data["title"])) else: pushMessage( self.tr("Map package {name} has been successfully deleted " ).format(name=self.data["title"])) self.data["status"] = DataCatalogueClient.NOT_INSTALLED elif status == DataCatalogueClient.LOCAL_ONLY: ret = self.dataCatalogueClient.uninstall(self.data["id"]) if not ret: pushWarning( self. tr("Cannot remove previous version of the {name} map package" ).format(name=self.data["title"])) else: pushMessage( self.tr("Map package {name} has been successfully deleted " ).format(name=self.data["title"])) self.data["status"] = DataCatalogueClient.LOCAL_DELETED else: ret = self.dataCatalogueClient.install(self.data) if not ret: pushWarning( self.tr("Cannot install map package {name}").format( name=self.data["title"])) else: pushMessage( self.tr( "Map package {name} has been successfully installed "). format(name=self.data["title"])) self.data["status"] = DataCatalogueClient.UP_TO_DATE if ret: self.updateContent()
def download_canceled(self): pushWarning(tr("Download is canceled!")) LOG.debug("Download is canceled")
def func(*args, **kw): if ValhallaClient.getInstance().isAvailable(): method(*args, **kw) else: pushWarning(tr("Valhalla is not installed or it cannot be found"))
def prepareValhalla(self): layer = self.layerSelector.getSelectedLayer() if layer is None: pushWarning(self.tr("Please, select a valid destination layer")) return try: points = [self.originSearchBox.point] if len(self.waypoints) > 0: points.extend(self.waypoints) points.append(self.destinationSearchBox.point) except WrongLocationException as e: pushWarning(self.tr("Invalid location:") + str(e)) return if None in points: pushWarning(self.tr("Both origin and destination points are required")) return try: shortest = self.radioButtonShortest.isChecked() except AttributeError: shortest = False vehicle = self.comboBoxVehicles.currentIndex() QgsSettings().setValue( "/kadasrouting/current_vehicle", self.comboBoxVehicles.currentIndex() ) profile, costingOptions = vehicles.options_for_vehicle(vehicle) if self.radioAreasToAvoidPolygon.isChecked(): areasToAvoid = self.areasToAvoid canvasCrs = self.canvas.mapSettings().destinationCrs() transformer = transformToWGS(canvasCrs) if areasToAvoid is None: # if the custom polygon button is checked, but no polygon has been drawn pushWarning( self.tr("Custom polygon button is checked, but no polygon is drawn") ) return elif self.radioAreasToAvoidLayer.isChecked(): avoidLayer = self.comboAreasToAvoidLayers.currentData() if avoidLayer is not None: layerCrs = avoidLayer.crs() transformer = transformToWGS(layerCrs) areasToAvoid = [f.geometry() for f in avoidLayer.getFeatures()] else: # If polygon layer button is checked, but no layer polygon is selected pushWarning( self.tr( "Polygon layer button is checked, but no layer polygon is selected" ) ) return else: # No areas to avoid areasToAvoid = None areasToAvoidWGS = None allAreasToAvoidWGS = None if shortest: costingOptions["shortest"] = True # transform to WGS84 (Valhalla's requirement) allAreasToAvoidWGS = [] if areasToAvoid: for areasToAvoidGeom in areasToAvoid: areasToAvoidJson = json.loads(areasToAvoidGeom.asJson()) areasToAvoidWGS = [] for i, polygon in enumerate(areasToAvoidJson["coordinates"]): areasToAvoidWGS.append([]) for point in polygon: pointWGS = transformer.transform(point[0], point[1]) areasToAvoidWGS[i].append([pointWGS.x(), pointWGS.y()]) allAreasToAvoidWGS.extend(areasToAvoidWGS) return layer, points, profile, allAreasToAvoidWGS, costingOptions