Get nearest neighbour on same or another layer to connect points by drawin a line in QGIS

linenearest neighborpointpyqgisqgis

In my project I try to find the shortest way from a point to a specific line (street).
Fortunately, this is no big deal in QGIS 3.0 using "Points along lines" and "Distance to Nearest Hub (Line)".
But if not the street but another point on the same layer is closer, I would like to connect to the nearest point on the same layer.
(A little tolerance to prefer the connection to the street would be ideal)

So this is what is now:

enter image description here

This would help me a lot

enter image description here

One of the difficulties I'm struggling with is to find the nearest point on the same layer (and draw a line to it). A solution for that as a first step would be very helpful, too.

Best Answer

The basic idea

Create lines connecting each point to it's closest neigbour. You will get lines with gaps in between. To close the gaps, connect each of these lines with the closest point on the nearest neighboring line. Finally, connect each of these lines to the closest point on the nearest section of the street layer.

How to do it in QGIS: create lines with Geometry by expression

  1. Create a line from each point to its closest neighbor using the following expression with Geometry by expression and replace points with the name of your point layer: make_line ( $geometry, overlay_nearest( 'points', $geometry, limit:=2)[1])

    Each point connected with red lines to the nearest neighboring point:

    enter image description here

  2. Clean the output of step 1 using these four steps: i) apply Explode lines, ii) Delete duplicate geometries, iii) select all features and then Merge selected and iv) finally turn Multipart to single parts.

  3. Connecting lines: each line should be connected to the closest point of the nearest line. Use this expression on the output of step 2 with Geometry by expression and replace Singleparts with the name of the layer from step 2:

     union (
         $geometry, 
         make_line (
             closest_point (
                 $geometry,
                 overlay_nearest( 
                     'Singleparts', 
                     $geometry, 
                     limit:=2
                 )[1]
             ),
             closest_point (
                 overlay_nearest( 
                     'Singleparts', 
                     $geometry, 
                     limit:=2
                 )[1],
                 $geometry
             )
         )
     )
    
  4. Clean the output of step 3, repeating the four steps of step 2 above.

    The red dotted line is the output from step 4:

    enter image description here

  5. Now you have to connect each resulting line to the street layer. Use once again Geometry by expression on the output of step 4 with this expression and replace street with the name of your street layer:

     union (
         $geometry,
         make_line (
             closest_point (
                 overlay_nearest ('street', $geometry)[0],
                 $geometry
             ),
             closest_point (
                 $geometry,
                 overlay_nearest ('street', $geometry)[0]
             )
         )
     )
    

See final output: enter image description here