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)
Esempio n. 2
0
 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
Esempio n. 3
0
 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")
Esempio n. 7
0
    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")
Esempio n. 11
0
    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
Esempio n. 12
0
    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()
Esempio n. 13
0
 def download_canceled(self):
     pushWarning(tr("Download is canceled!"))
     LOG.debug("Download is canceled")
Esempio n. 14
0
 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