3

I am trying to find the shortest paths given a number of points with a specific order for each path. Specifically, my point data have the following format:

enter image description here

I used the approved solution given in Routing with several stops using QGIS, and it works perfectly if my data have only 1 route.

How can I modify the proposed script for making it work for several routes?

1 Answer 1

3

You can use this script: (Reference)

# CHANGE LAYER NAMES
networkLayer = QgsProject.instance().mapLayersByName('networkLayerName')[0]
pointLayer = QgsProject.instance().mapLayersByName('pointLayerName')[0]

output_folder = "/path/to/a/folder" # ADD A FOLDER PATH

route_field_index = pointLayer.fields().indexFromName('route')
unique_routes = pointLayer.uniqueValues(route_field_index)

for unique_route in unique_routes:

    pointLayer.selectByExpression(f"route='{unique_route}'")

    stops = []
    for feat in pointLayer.selectedFeatures():
        stops.append((feat['stop'], feat.geometry().asPoint()))

    #sort by order column
    stops.sort(key=lambda x: x[0])
    paths = []
    for i, (order, point) in enumerate(stops[0:-1]):
        endPoint = stops[i + 1][1]
        parameters = {'INPUT': networkLayer,
                      'STRATEGY': 0,
                      'DIRECTION_FIELD': '',
                      'VALUE_FORWARD': '',
                      'VALUE_BACKWARD': '',
                      'VALUE_BOTH': '',
                      'DEFAULT_DIRECTION': 2,
                      'SPEED_FIELD': '',
                      'DEFAULT_SPEED': 50.0,
                      'TOLERANCE': 20.0,
                      'START_POINT': point,
                      'END_POINT': endPoint,
                      'OUTPUT': 'memory:'}

        path = processing.run('qgis:shortestpathpointtopoint', parameters)['OUTPUT']
        paths.append(path)    
    
    output = f'{output_folder}/{unique_route}.shp'
    pathsMerged = processing.run('qgis:mergevectorlayers',
                                 {'LAYERS': paths,
                                  'OUTPUT': output})['OUTPUT']
                                  
    vlayer = QgsVectorLayer(pathsMerged, str(unique_route), 'ogr')
    QgsProject.instance().addMapLayer(vlayer)

enter image description here

I didn't merge the route layers. You may need to merge them.

10
  • Thank you a lot! However I am getting that error: Traceback (most recent call last): File "C:\PROGRA~1\QGIS3~1.6\apps\Python37\lib\code.py", line 90, in runcode exec(code, self.locals) File "<input>", line 1, in <module> File "<string>", line 8, in <module> NameError: name 'stop_field_index' is not defined
    – Anas.S
    Feb 10, 2022 at 11:42
  • 1
    My mistake. Change stop_field_index to route_field_index . Feb 10, 2022 at 11:44
  • Now I am getting that error during the first time:
    – Anas.S
    Feb 10, 2022 at 11:56
  • 1
    I don't know why, but it works at the second run. Feb 10, 2022 at 12:02
  • 1
    Yes, You need to provide an order to the script. Otherwise, it cannot know the order. The order have to be sortable by the script. 2>15>7>1>20 is not sortable. Feb 10, 2022 at 12:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.