3

In QGIS, a have point vector Layer_A with a unique ID field and point vector Layer_B with multiple points for each Layer_A ID. For each point on Layer_A I want I need to create a line that connects the two closest points on Layer_B that have the same ID as the current Layer_A feature.

How can this be solved using the expression builder in the Model Designer?

My current approach for the Geometry by expression tool using Layer_A as input layer is:

make_line(
    overlay_nearest(
         @Layer_B_OUTPUT,
         $geometry,
         limit:=2
    )[1],
    overlay_nearest(
         @Layer_B_OUTPUT,
         $geometry,          
         limit:=2
    )[0]
)

Here's an example screenshot with Layer_A points in yellow and Layer_B points in grey:

Example screenshot

As expected, I am still missing a filter for overlay_nearest() to select only the features with a matching ID. And I don't know if limiting it to the first two occurrences actually returns the two closest features.

I tried to add a filter like this, but it does not seem to work:

with_variable(
    'current_id',
    "ID",
    make_line(
        overlay_nearest(
             @Layer_B_OUTPUT,
             $geometry,
             filter:= ID = @current_id, --This does not seem to work
             limit:=2
        )[1],
        overlay_nearest(
             @Layer_B_OUTPUT,
             $geometry,
             filter:= ID = @current_id, --This does not seem to work
             limit:=2
        )[0]
    )
)

Maybe it's related to the problem described here?

0

1 Answer 1

5

In theory you should be able to adapt your expression to include a filter as follows:

with_variable('layer_a_id',$id,
    make_line(
        overlay_nearest(
             layer:='Layer_B',
             expression:=$geometry,
             filter:="id"=@layer_a_id,
             limit:=2
        )[1],
        overlay_nearest(
             layer:='Layer_B',
             expression:=$geometry,          
             filter:="id"=@layer_a_id,
             limit:=2
        )[0]
    )
)

The problem is that there is a bug (probably) where variables in filter expressions appear to get ignored. See: Variable is not recognize in QGIS expression using overlay_nearest function for details.

So the workaround is - as noted in the above question - to wrap the overlay_nearest calls in an eval. It's very clunky and hopefully it will be fixed in QGIS at some point.

with_variable('layer_a_id',attribute('id'),
    make_line(
        eval(
            'overlay_nearest(
                 layer:=\'Layer_B\',
                 expression:=$geometry,
                 filter:="id"='|| @layer_a_id ||',
                 limit:=2
            )[1]'),
        eval(
            'overlay_nearest(
                 layer:=\'Layer_B\',
                 expression:=$geometry,
                 filter:="id"='|| @layer_a_id ||',
                 limit:=2
            )[0]')
    )
)

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.