# Creating buffers to closest distances with two categories in QGIS

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:

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:

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:

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.

• Never compute distances using `3857`. Use a suitable local projection that preserve distances (UTM or else). Also make sure each point has its own ID (no duplicates)
– JGH
Nov 15, 2023 at 12:19

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`.

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
``````

Alternative solution

I use Rule-based symbology with the following expressions:

For Filter (calculate distances for each point and select distance <0.7):

``````distance(
\$geometry,
array_get(
overlay_nearest(
layer:=@layer,
expression:=\$geometry,
limit:=2
),
1
)
)<0.7
``````

For the Geometry generator (draw buffers at distance):

``````with_variable(
'dista',
distance(
\$geometry,
array_get(
overlay_nearest(
layer:=@layer,
expression:=\$geometry,
limit:=2
),
1
)
),
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)
)<@dista,
buffer(@element,@dista/1),
buffer(@element,-@dista)
)
)
)
)
``````

The result: