7

There are many online tools for planning routes (e.g. Gaia GPS for hiking, Strava for cycling) in an interactive way (by clicking) such that the route generated conforms to an underlying route layer (e.g. OpenStreetMap roads or trails). For example, here is a screen recording of the Gaia GPS interface: Screen recording of interactive route planning in Gaia GPS.

Does QGIS have any functionality or plug-ins that would allow a similar procedure?

Previous questions (e.g. How to route railcars along railroads? and Least cost path between various points QGIS) indicate that it is possible to generate snapping routes following a pre-defined set of points, which seems to be only a small step away from what I would like to do.

1
  • If you wish to also ask about ArcGIS (ArcGIS Pro, ArcMap or ArcGIS Online), then please do that as a separate question and specify which.
    – PolyGeo
    Nov 27, 2022 at 8:35

3 Answers 3

5

QGIS has en editing tool call Automatic tracing.

Here the documentation section of this tool :

  1. Enable the tracing Tracing tool (in the Snapping toolbar) by pushing the icon or pressing T key.

  2. Snap to a vertex or segment of a feature you want to trace along.

  3. Move the mouse over another vertex or segment you’d like to snap and, instead of the usual straight line, the digitizing rubber band represents a path from the last point you snapped to the current position. The tool also works with curved geometries

    QGIS actually uses the underlying features topology to build the shortest path between the two points. Tracing requires snapping to be activated in traceable layers to build the path. You should also snap to an existing vertex or segment while digitizing and ensure that the two nodes are topologically connectable through existing features edges, otherwise QGIS is unable to connect them and thus traces a single straight line.

  4. Click and QGIS places the intermediate vertices following the displayed path.

5

Expanding the solution by @Dror Bogin you can use this expression together with array_foreach() to include not just two points, but any number of points - in the following example points 1 to 9 (first expression below):

enter image description here

In this case, you connect points in a regular order: 1,2,3,4... Changing the expression a bit, you can even define any arbitrary order of the points like from point 17 to 10 to 4 to 3 as can be seen on the next screenshot (second expression below):

enter image description here

First expression to connect points in a regular order, to be defined in line 4:

collect_geometries (
    array_filter (
        array_foreach (
            generate_series (1,9), -- define here the list of $id's of the points to be included
            line_substring(
                $geometry,
                line_locate_point(
                    $geometry,
                    closest_point(
                        $geometry,
                        geometry(get_feature_by_id ('points',@element))
                    )
                ),
                line_locate_point( 
                    $geometry,
                    closest_point(
                        $geometry,
                        geometry(get_feature_by_id ('points',@element+1))
                    )
                )
            )
        ),
        @element IS NOT NULL
    )
)

Second expression to connect points in any arbitrary order, to be defined in line 3:

with_variable (
    'array',
    array (17,10,4,3),  -- define here the order in which the points should be connected
    collect_geometries (
        array_filter (
            array_foreach (
                @array,
                line_substring(
                    $geometry,
                    line_locate_point(
                        $geometry,
                        closest_point(
                            $geometry,
                            geometry(get_feature_by_id ('points',@element))
                        )
                    ),
                    line_locate_point( 
                        $geometry,
                        closest_point(
                            $geometry,
                            geometry(get_feature_by_id ('points',array_get (@array,array_find (@array, @element)+1)))
                        )
                    )
                )
            ),
            @element IS NOT NULL
        )
    )
)
1
  • 1
    Nice, I'll add that to the post
    – Dror Bogin
    Nov 27, 2022 at 11:02
4

It isn't clear from your question what you tried so far.
You could use the QGIS native shortest path algortihm which will find your path using a lines layer as a road network.

If you just want get a part of a single line using 2 points which are near the line, you could use an expression for that.

I have an example in a blog post about it here and the final expression there is this:

line_substring(
      $geometry,
     line_locate_point(
        $geometry,
        closest_point(
           $geometry,
           geometry(
                get_feature_by_id( 'points',1)
                )
          )
      ),
      line_locate_point( $geometry,
        closest_point(
       $geometry,
       geometry(
            get_feature_by_id( 'points',2)
            )
         )
      )
  )

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.