The problem
In QGIS 3.20.0 (Win 10), I have an expression that does not work as expected and I don't understand why. On a point layer, one point is selected. When using Select by expression
, the expression should select the N
(freely definable number) nearest neighboring points.
Download the QGIS project with layers that show what I tried and for testing my expressions.
What I tried
I created an expression based on two elements (see the expressions below):
Get the geometry of the selected point. Check the layer
points_selection
in the project I linked to see that this works: selected points get a red ring around them. Create this as variable@selected_point
.Create a circle around each point with the radius such that it reaches to point furthest away of the
N
nearest neighbors, whereN
is the number defined in line 8 (here:3
). Thus the circle covers allN
neighbors. The radius is multiplied by 1.01 to get a small buffer around the circle to be sure that the furthest points falls within that circle and not on its boundary. Check the layerpoints_circle
in the linked project: you see that a circle is created. Create this as variable@circle
.
As you can see in the linked project, both elements work as expected. You can also check the layer points_line
: if you select a point, lines to the K
nearest neighbors are drawn.
What doesn't work
The idea is now to combine these two elements using the expression within (@selected_point, @circle)
, where @selected_point
and @circle
are the variables created with the expressions from steps 1 and 2. The within
function should return true
for those features (points) where the selected point (@selected_point
, step 1) is within the circle (@circle
) around the current feature's geometry.
The question
What went wrong with the expression: why doesn't it work as expected (see also screenshot at the bottom)?
The expressions
- Selected Point
geometry (
get_feature_by_id (
@layer,
array_first(
aggregate(
@layer,
'array_agg',
$id,
filter:=is_selected( )
)
)
)
)
- Circle around point:
make_circle (
$geometry,
array_max(
array_foreach (
overlay_nearest (
@layer,
$geometry,
limit:=3
),
length (
make_line (
$geometry,
@element
)
)
)
)*1.01,
200
)
- Defining both elements as variables and stick them together with
within
- the whole expression looks like this:
with_variable (
'selected_pt',
geometry (
get_feature_by_id (
@layer,
array_first(
aggregate(
@layer,
'array_agg',
$id,
filter:=is_selected( )
)
)
)
),
with_variable (
'circle',
make_circle (
$geometry,
array_max(
array_foreach (
overlay_nearest (
@layer,
$geometry,
limit:=9
),
length (
make_line (
$geometry,
@element
)
)
)
)*1.01,
200
),
within (
@selected_pt,
@circle
)
)
)
Screenshot: setting the limit to 9 nearest neighbors as argument of overlay_nearest
, I here still get 12 features selected (the already selected point + 11 neighbors). As you see, there are points selected further away that are selected and others, closer, that are not selected. Both (number of points and which points are selected) does not correspond to what I expect: