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?

Matt
  • 16,843
  • 3
  • 21
  • 52
  • 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 Feb 24 '22 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 Feb 24 '22 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 Feb 24 '22 at 17:16

1 Answers1

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
Babel
  • 71,072
  • 14
  • 78
  • 208