From c5ed53942c36a61ad01c1831660c8d19824cd89f Mon Sep 17 00:00:00 2001 From: Alexander Bruy Date: Sun, 16 Jul 2017 11:26:44 +0300 Subject: [PATCH] [processing] restore Shortest path from point to point --- .../algs/qgis/QGISAlgorithmProvider.py | 11 +- .../algs/qgis/ShortestPathPointToPoint.py | 174 +++++++++--------- 2 files changed, 89 insertions(+), 96 deletions(-) diff --git a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py index b0f76cd820a..3b57c9dc0ae 100644 --- a/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py +++ b/python/plugins/processing/algs/qgis/QGISAlgorithmProvider.py @@ -87,6 +87,11 @@ from .Ruggedness import Ruggedness from .SaveSelectedFeatures import SaveSelectedFeatures from .SelectByAttribute import SelectByAttribute from .SelectByExpression import SelectByExpression +# from .ServiceAreaFromLayer import ServiceAreaFromLayer +# from .ServiceAreaFromPoint import ServiceAreaFromPoint +# from .ShortestPathLayerToPoint import ShortestPathLayerToPoint +# from .ShortestPathPointToLayer import ShortestPathPointToLayer +from .ShortestPathPointToPoint import ShortestPathPointToPoint from .SimplifyGeometries import SimplifyGeometries from .Slope import Slope from .Smooth import Smooth @@ -158,11 +163,6 @@ from .ZonalStatistics import ZonalStatistics # from .ExtractSpecificNodes import ExtractSpecificNodes # from .GeometryByExpression import GeometryByExpression # from .RasterCalculator import RasterCalculator -# from .ShortestPathPointToPoint import ShortestPathPointToPoint -# from .ShortestPathPointToLayer import ShortestPathPointToLayer -# from .ShortestPathLayerToPoint import ShortestPathLayerToPoint -# from .ServiceAreaFromPoint import ServiceAreaFromPoint -# from .ServiceAreaFromLayer import ServiceAreaFromLayer # from .TruncateTable import TruncateTable # from .Polygonize import Polygonize # from .ExecuteSQL import ExecuteSQL @@ -274,6 +274,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider): SaveSelectedFeatures(), SelectByAttribute(), SelectByExpression(), + ShortestPathPointToPoint(), SimplifyGeometries(), Slope(), Smooth(), diff --git a/python/plugins/processing/algs/qgis/ShortestPathPointToPoint.py b/python/plugins/processing/algs/qgis/ShortestPathPointToPoint.py index 2dc4cdb0527..179d4a7af94 100644 --- a/python/plugins/processing/algs/qgis/ShortestPathPointToPoint.py +++ b/python/plugins/processing/algs/qgis/ShortestPathPointToPoint.py @@ -36,11 +36,19 @@ from qgis.core import (QgsWkbTypes, QgsFeature, QgsFeatureSink, QgsGeometry, - QgsPointXY, QgsFields, QgsField, - QgsProcessingParameterDefinition, - QgsProcessingUtils) + QgsProcessing, + QgsProcessingException, + QgsProcessingOutputNumber, + QgsProcessingParameterEnum, + QgsProcessingParameterPoint, + QgsProcessingParameterField, + QgsProcessingParameterNumber, + QgsProcessingParameterString, + QgsProcessingParameterFeatureSink, + QgsProcessingParameterVectorLayer, + QgsProcessingParameterDefinition) from qgis.analysis import (QgsVectorLayerDirector, QgsNetworkDistanceStrategy, QgsNetworkSpeedStrategy, @@ -50,25 +58,13 @@ from qgis.analysis import (QgsVectorLayerDirector, from qgis.utils import iface from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm -from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException -from processing.core.parameters import (ParameterVector, - ParameterPoint, - ParameterNumber, - ParameterString, - ParameterTableField, - ParameterSelection - ) -from processing.core.outputs import (OutputNumber, - OutputVector - ) -from processing.tools import dataobjects pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0] class ShortestPathPointToPoint(QgisAlgorithm): - INPUT_VECTOR = 'INPUT_VECTOR' + INPUT = 'INPUT' START_POINT = 'START_POINT' END_POINT = 'END_POINT' STRATEGY = 'STRATEGY' @@ -81,7 +77,7 @@ class ShortestPathPointToPoint(QgisAlgorithm): DEFAULT_SPEED = 'DEFAULT_SPEED' TOLERANCE = 'TOLERANCE' TRAVEL_COST = 'TRAVEL_COST' - OUTPUT_LAYER = 'OUTPUT_LAYER' + OUTPUT = 'OUTPUT' def icon(self): return QIcon(os.path.join(pluginPath, 'images', 'networkanalysis.svg')) @@ -102,59 +98,60 @@ class ShortestPathPointToPoint(QgisAlgorithm): self.tr('Fastest') ] - self.addParameter(ParameterVector(self.INPUT_VECTOR, - self.tr('Vector layer representing network'), - [dataobjects.TYPE_VECTOR_LINE])) - self.addParameter(ParameterPoint(self.START_POINT, - self.tr('Start point'))) - self.addParameter(ParameterPoint(self.END_POINT, - self.tr('End point'))) - self.addParameter(ParameterSelection(self.STRATEGY, - self.tr('Path type to calculate'), - self.STRATEGIES, - default=0)) + self.addParameter(QgsProcessingParameterVectorLayer(self.INPUT, + self.tr('Vector layer representing network'), + [QgsProcessing.TypeVectorLine])) + self.addParameter(QgsProcessingParameterPoint(self.START_POINT, + self.tr('Start point'))) + self.addParameter(QgsProcessingParameterPoint(self.END_POINT, + self.tr('End point'))) + self.addParameter(QgsProcessingParameterEnum(self.STRATEGY, + self.tr('Path type to calculate'), + self.STRATEGIES, + defaultValue=0)) params = [] - params.append(ParameterTableField(self.DIRECTION_FIELD, - self.tr('Direction field'), - self.INPUT_VECTOR, - optional=True)) - params.append(ParameterString(self.VALUE_FORWARD, - self.tr('Value for forward direction'), - '', - optional=True)) - params.append(ParameterString(self.VALUE_BACKWARD, - self.tr('Value for backward direction'), - '', - optional=True)) - params.append(ParameterString(self.VALUE_BOTH, - self.tr('Value for both directions'), - '', - optional=True)) - params.append(ParameterSelection(self.DEFAULT_DIRECTION, - self.tr('Default direction'), - list(self.DIRECTIONS.keys()), - default=2)) - params.append(ParameterTableField(self.SPEED_FIELD, - self.tr('Speed field'), - self.INPUT_VECTOR, - optional=True)) - params.append(ParameterNumber(self.DEFAULT_SPEED, - self.tr('Default speed (km/h)'), - 0.0, 99999999.999999, 5.0)) - params.append(ParameterNumber(self.TOLERANCE, - self.tr('Topology tolerance'), - 0.0, 99999999.999999, 0.0)) + params.append(QgsProcessingParameterField(self.DIRECTION_FIELD, + self.tr('Direction field'), + None, + self.INPUT, + optional=True)) + params.append(QgsProcessingParameterString(self.VALUE_FORWARD, + self.tr('Value for forward direction'), + optional=True)) + params.append(QgsProcessingParameterString(self.VALUE_BACKWARD, + self.tr('Value for backward direction'), + optional=True)) + params.append(QgsProcessingParameterString(self.VALUE_BOTH, + self.tr('Value for both directions'), + optional=True)) + params.append(QgsProcessingParameterEnum(self.DEFAULT_DIRECTION, + self.tr('Default direction'), + list(self.DIRECTIONS.keys()), + defaultValue=2)) + params.append(QgsProcessingParameterField(self.SPEED_FIELD, + self.tr('Speed field'), + None, + self.INPUT, + optional=True)) + params.append(QgsProcessingParameterNumber(self.DEFAULT_SPEED, + self.tr('Default speed (km/h)'), + QgsProcessingParameterNumber.Double, + 5.0, False, 0, 99999999.99)) + params.append(QgsProcessingParameterNumber(self.TOLERANCE, + self.tr('Topology tolerance'), + QgsProcessingParameterNumber.Double, + 0.0, False, 0, 99999999.99)) for p in params: p.setFlags(p.flags() | QgsProcessingParameterDefinition.FlagAdvanced) self.addParameter(p) - self.addOutput(OutputNumber(self.TRAVEL_COST, - self.tr('Travel cost'))) - self.addOutput(OutputVector(self.OUTPUT_LAYER, - self.tr('Shortest path'), - datatype=[dataobjects.TYPE_VECTOR_LINE])) + self.addOutput(QgsProcessingOutputNumber(self.TRAVEL_COST, + self.tr('Travel cost'))) + self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, + self.tr('Shortest path'), + QgsProcessing.TypeVectorLine)) def name(self): return 'shortestpathpointtopoint' @@ -163,40 +160,33 @@ class ShortestPathPointToPoint(QgisAlgorithm): return self.tr('Shortest path (point to point)') def processAlgorithm(self, parameters, context, feedback): - layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_VECTOR), context) - startPoint = self.getParameterValue(self.START_POINT) - endPoint = self.getParameterValue(self.END_POINT) - strategy = self.getParameterValue(self.STRATEGY) + layer = self.parameterAsVectorLayer(parameters, self.INPUT, context) + startPoint = self.parameterAsPoint(parameters, self.START_POINT, context) + endPoint = self.parameterAsPoint(parameters, self.END_POINT, context) + strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) - directionFieldName = self.getParameterValue(self.DIRECTION_FIELD) - forwardValue = self.getParameterValue(self.VALUE_FORWARD) - backwardValue = self.getParameterValue(self.VALUE_BACKWARD) - bothValue = self.getParameterValue(self.VALUE_BOTH) - defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) - bothValue = self.getParameterValue(self.VALUE_BOTH) - defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION) - speedFieldName = self.getParameterValue(self.SPEED_FIELD) - defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED) - tolerance = self.getParameterValue(self.TOLERANCE) + directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context) + forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context) + backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context) + bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context) + defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context) + speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context) + defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context) + tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context) fields = QgsFields() fields.append(QgsField('start', QVariant.String, '', 254, 0)) fields.append(QgsField('end', QVariant.String, '', 254, 0)) fields.append(QgsField('cost', QVariant.Double, '', 20, 7)) - writer = self.getOutputFromName( - self.OUTPUT_LAYER).getVectorWriter(fields, QgsWkbTypes.LineString, layer.crs(), context) - - tmp = startPoint.split(',') - startPoint = QgsPointXY(float(tmp[0]), float(tmp[1])) - tmp = endPoint.split(',') - endPoint = QgsPointXY(float(tmp[0]), float(tmp[1])) + (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, + fields, QgsWkbTypes.LineString, layer.crs()) directionField = -1 - if directionFieldName is not None: + if directionField: directionField = layer.fields().lookupField(directionFieldName) speedField = -1 - if speedFieldName is not None: + if speedFieldName: speedField = layer.fields().lookupField(speedFieldName) director = QgsVectorLayerDirector(layer, @@ -230,7 +220,7 @@ class ShortestPathPointToPoint(QgisAlgorithm): tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0) if tree[idxEnd] == -1: - raise GeoAlgorithmExecutionException( + raise QgsProcessingException( self.tr('There is no route from start point to end point.')) route = [] @@ -244,8 +234,6 @@ class ShortestPathPointToPoint(QgisAlgorithm): route.append(snappedPoints[0]) route.reverse() - self.setOutputValue(self.TRAVEL_COST, cost / multiplier) - feedback.pushInfo(self.tr('Writing results...')) geom = QgsGeometry.fromPolyline(route) feat = QgsFeature() @@ -254,5 +242,9 @@ class ShortestPathPointToPoint(QgisAlgorithm): feat['end'] = endPoint.toString() feat['cost'] = cost / multiplier feat.setGeometry(geom) - writer.addFeature(feat, QgsFeatureSink.FastInsert) - del writer + sink.addFeature(feat, QgsFeatureSink.FastInsert) + + results = {} + results[self.TRAVEL_COST] = cost / multiplier + results[self.OUTPUT] = dest_id + return results