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_selectionin the project I linked to see that this works: selected points get a red ring around them. Create this as variable
Create a circle around each point with the radius such that it reaches to point furthest away of the
Nnearest neighbors, where
Nis the number defined in line 8 (here:
3). Thus the circle covers all
Nneighbors. 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 layer
points_circlein the linked project: you see that a circle is created. Create this as variable
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
@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.
What went wrong with the expression: why doesn't it work as expected (see also screenshot at the bottom)?
- 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: