4

In QGIS I want to draw the shortest line between 2 points (in this case a line between the circle point and the triangle point).

However, the shortest line created between two points cannot cross the "barrier" line layer shown in the picture (red x in the picture means wrong path) and instead it will look for another shortest point (lines drawn in red).

Do you know the solution to this problem?

enter image description here

4
  • 1
    Is the barrier made from more than 2 vertices? Commented Sep 15 at 20:15
  • @Sethinacan it could be more than 2 vertices, let say that "barrier" line as a road or railroad Commented Sep 15 at 21:09
  • @Babel It is just between points and lines only, and the shortest line created between points needs to avoid crossing the "barrier" line, not to follow it Commented Sep 15 at 21:18
  • The suggested "duplicate" post is for a different problem. Here, OP wants to go around barrier, in duplicate post it doesn't go around and completely ignores what is behind the barrier Commented Sep 16 at 13:07

2 Answers 2

2

You can use raster least cost analysis for this.

  1. Create a polygon around your start-/destination points (e.g. the bounding box)

  2. Rasterize the polyon.

  3. Rasterize the barrier (you might add a buffer around it) and set the pixel values to an extreme value, so it will be avoided at all cost

  4. Combine these two rasters into one (or subtract the barrier raster from the other raster so there or NoData pixels in this part).

  5. Use raster least cost analysis as described here.

2

A vector based solution how to draw the shortest connecting linestring from point A to point B, but not crossing a barrier. At the very end of this solution, you find an expression for Geometry generator that shows the result in realtime when you move around points/change barrier lines.

Basic idea: create a convex hull around start/destination points and all nodes of the barrier, than use routing (shortest path algorithm) on the edges of the hull. Details below.

See the result in the screenshot. The connecting lines (black) touch, but do not cross, the barrier (red line). If you want the connecting line to have a certain distance from the barrier, you could easily do that by adding a buffer around the barrier: see last screenshot at the bottom.

enter image description here

First a step by step description, below how to implement it:

  1. Create the direct, connecting lines between start and destination points.

  2. Only keep lines that do not cross a barrier.

  3. Where the line crosses a barrier, create the convex hull from the geometry collection, containing: A) start point, B) destination point, C) all nodes (vertices) of the barrier line.

  4. Get the boundary of the convex hull.

  5. Use shortest path algorithm from start to destination, using the boundary from step 4 as network.

Steps 1 to 4: Start points (blue), destination points (red); red lines: barrier; the black lines connect each blue point to the red point with same @id, avoiding crossing the barrier: enter image description here

For steps 1 to 4, use this expression:

with_variable( 'connection', make_line ( $geometry, geometry ( get_feature_by_id ('destination',@id) ) ), case when intersects ( @connection, aggregate( 'barrier', 'collect', @geometry ) ) then boundary ( convex_hull( collect_geometries( array( @geometry, geometry ( get_feature_by_id ('destination',@id) ), collect_geometries( overlay_nearest ( 'barrier', nodes_to_points (@geometry) -- or nodes_to_points (buffer (@geometry,30)) if you want to create a buffer around the barrier, change buffer size of 30 to fit your needs ) ) ) ) ) ) else @connection end ) 

For step 5, I created the lines from steps 1 to 4 using Geometry by expression with the expression above, creating the output layer Modefied Geometry. Then I used Shortest path (point to point) in batch mode to connect each start point to destination point using these lines from Modefied Geometry as network. See screenshot:

enter image description here

See the result:

enter image description here

Version with a buffer (light blue) around the barrier; to create the buffer, in the expression above modify 10th last line according to the comment there:

enter image description here

Expression for geometry generator that directly (in one step) shows the shortest connection:

enter image description here

with_variable( 'connection', make_line ( $geometry, geometry ( get_feature_by_id ('destination',@id) ) ), with_variable( 'splitbuffer', length(@connection) / 1000000, case when intersects ( @connection, aggregate( 'barrier', 'collect', @geometry ) ) then difference ( with_variable( 'res', boundary( difference( convex_hull( collect_geometries( array( @geometry, geometry ( get_feature_by_id ('destination',@id) ), collect_geometries( overlay_nearest ( 'barrier', nodes_to_points (@geometry) ) ) ) ) ), buffer (@connection, @splitbuffer) ) ), if ( length (geometries_to_array(@res)[0]) > length (geometries_to_array(@res)[1]), geometries_to_array(@res)[1], geometries_to_array(@res)[0] ) ), buffer (@connection, @splitbuffer * 1.1) ) else @connection end )) 
1
  • thank you for the help :) Commented Sep 16 at 8:23

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.