3

I am using a Geometry Generator symbol layer to draw lines between grouped points. I am grouping points based on two fields letter and number, which I concatenate to make the groups (GeoPackage download).

Current expression:

make_line(
    array_agg(                       -- gather results into array
        expression:=$geometry, 
        group_by:=letter||number     -- concatenate fields to make groups
    )
)

make_line accepts an array of Point geometries, hence using array_agg.

The expression works and draws the lines, however, it draws a line per point. So, for a group of 4 geometries it overlays a line 4 times.

It is difficult to visualise but there is a discernible difference in colours between these lines using the Screen feature blending mode.

enter image description here

How can I adapt my expression to prevent this?

3
  • 1
    imho you can't avoid it, because the starting base has n points and it has to repeat it n times, this is the logic on which the filed calc is based
    – pigreco
    Commented Feb 24, 2022 at 16:08
  • 1
    It is, in my opinion, a major limitation of using the geometry generator to aggregate geometries. Not only are the final geometries rendered multiple times, but they are also computed multiple times, which can be expensive. On the other hand, you can create a virtual layer to compute (just once) the geometries and display them
    – JGH
    Commented Feb 24, 2022 at 16:26
  • I thought this might be the case. The only way I can think to remedy it would be to do some sort of check for a point id and then return a null geometry for any point that is not first in a group. But that would probably be a rather elaborate expression.
    – Matt
    Commented Feb 24, 2022 at 17:16

1 Answer 1

4

You can use just the first point of each group to create the geometry. Simply use an case .. when condition to check the $id and create the line only in case it is equal to the smallest $id of each group. If you don't add an else statement, you can even avoid creating empty geometries:

case
when
    $id = array_min (
        array_agg(
            $id,
            group_by:=letter||number 
        )
    )
then    make_line(
        array_agg( 
            expression:=$geometry, 
            group_by:=letter||number 
        )
    )
end
1
  • 2
    A much more elegant solution than I was anticipating.
    – Matt
    Commented Mar 20, 2022 at 21:51

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.