QGIS – Creating Buffers to Closest Distances with Two Categories

bufferknnpointpolygon-creationqgis

I would like to develop an expression that does the following nearest-neighbour analysis:

From a layer of points 'point_layer', I would like to calculate for each point the distance to the nearest point.

Once this distance value is calculated, the goal is to draw the buffer with the distance as a radius value and then symbolize the buffers with two categories:

  • Red green: points (buffers) located within 70 centimetres
  • Red red: points (buffers) located outside of 70 centimetres

Below I show a manual result recreation that should be obtained:

enter image description here

For my part, to try to obtain the expected result, I am working on this idea:

  1. To obtain the closest distances to each point I use the following function:

    array_sum (array_foreach (overlay_nearest(@layer, $geometry, limit:=2), length (make_line ( $geometry, @element))))
    

In this step, it seems that the result is correct, but it is not clear to me that it is necessary to use the function array_sum.

  1. Then I use the Geometry generator with the following expression that tries to integrate the previous function of distance calculation with the creation of buffers:
with_variable(
    'distance',
        array_sum ( array_foreach ( overlay_nearest( @layer, $geometry, limit:=2), length (make_line ($geometry, @element)))),
    collect_geometries(
        array_foreach(array_foreach(
                overlay_nearest( 
                    'point_layer',
                    $geometry, 
                    limit:=1),
                make_line(
                    $geometry,  
                    @element)),
            if (
                distance( 
                    start_point (@element), 
                    end_point ( @element))<@distance, 
                buffer (@element,@distance/2),
                buffer (@element,-@distance)))))

As you can see, with this expression I manage to draw the buffers. This is just a working idea.

Can you help with a new approach to enable me to complete the goal?

Previous result:

enter image description here

Attempt to implement the solution by @JGH user

I have implemented the solution proposed by user @JGH but it does not give the expected result. It seems that the virtual layer only loads 5 points:

enter image description here

It seems to be calculating the cumulative distance of 5 points. I am not sure.

It seems also that the distance values are too high.

Best Answer

You will need the computed distance to classify the output. One option is to create a virtual layer that will compute the distance, record it, buffer the point and that you can style as you wish using the rule based symbology.

enter image description here

Go to the menu Layer > Add Layer > Add/Edit Virtual Layer... and enter the following query. Replace myPointLayer with the real layer name, and you can add other fields from pt1.

SELECT pt1.id, pt2.id as nerest_pt_id,
       MIN(ST_Distance(pt1.geometry, pt2.geometry)) AS distance,
       st_buffer(pt1.geometry, MIN(ST_Distance(pt1.geometry, pt2.geometry))) as geometry
FROM myPointLayer AS pt1, myPointLayer AS pt2
WHERE pt1.id != pt2.id
GROUP BY pt1.id
ORDER BY distance DESC
Related Question