5

I have a point layer styled with the following geometry generator formula for an irregular polygon. It is the union of (a) a circular buffer with (b) a tree canopy spread buffered by 1m (where that extends beyond (a)).

 union(buffer($geometry,"tpzbsrad_m"),buffer(make_polygon(make_line(
 translate($geometry,0,max("N",0.2)),
 translate($geometry,0.6*max("E",0.2),0.6*max("N",0.2)),
 translate($geometry,max("E",0.2),0),
 translate($geometry,0.6*max("E",0.2),-0.6*max("S",0.2)),
 translate($geometry,0,-max("S",0.2)),
 translate($geometry,-0.6*max("W",0.2),-0.6*max("S",0.2)),
 translate($geometry,-max("W",0.2),0), 
 translate($geometry,-0.6*max("W",0.2),0.6*max("N",0.2)),
 translate($geometry,0,max("N",0.2)))),1))

I would like to use the geometry generator to draw a 45° line from the tree point ($geometry) to the edge of this irregular polygon.

For most cases the following suffices - a line to the edge of the circular buffer.

make_line(
 $geometry, make_point($x + "tpzbsrad_m"*cos(radians(45)), 
                       $y - ("tpzbsrad_m"*sin(radians(45)))
))

But where the tree canopy extends beyond the buffer in that area it doesn't match up. See image below:

enter image description here

What expression can I use to get the line to be long enough to always touch the edge of the irregular polygon at 45°? shortest_line() results in angles all over the place, naturally.

(Looking for an expression that ideally works in QGIS 2.18 and 3.x)

2 Answers 2

3

Thanks for sharing your great work!

[Option 1]

An idea presented below would require:

  • The irregular (sky-blue) polygon is saved as a vector layer ( your_polygon)
  • refFunctions plugin (for geomwithin() function)

Then the expression is:

intersection(
    make_line(
             $geometry, make_point($x + 2*"tpzbsrad_m"*cos(radians(45)), 
                                   $y - 2*("tpzbsrad_m"*sin(radians(45)))
    )),
    geom_from_wkt(geomwithin('your_polygon', '$geometry'))
)

(A multiplier factor 2 to your "tpzbsrad_m" has no meaning but it ensures the line is extended long enough before it gets cut at the intersecting polygon boundary).


[Option 2] without refFunctions plugin:

Instead of using refFunctions plugin, there is an additional step to link your tree (point) and polygon.

  • Join by Location to have identical id fields in both of your layers (point and polygon).

Now revised expression is:

intersection(
    make_line(
             $geometry, make_point($x + 2*"tpzbsrad_m"*cos(radians(45)), 
                                   $y - 2*("tpzbsrad_m"*sin(radians(45)))
    )),
    geometry(get_feature('your_polygon', 'id', "id"))
)

This expression uses get_feature() function which links 'id' field from the polygon (your_polygon) and the "id" field in the point layer (your tree locations).

3
  • 1
    Thanks for all your helpful replies Kazuhito!. I should've mentioned I would prefer to avoid plugins if at all possible for this solution though, as the style is meant to be distributed across a number of users and it's hard to standardise their versions let alone their plugins ... Your approach had occurred to me, intersecting the line with the polygon, but I wasn't sure of performance. Since the polygon is just a geometry generated one (on the same layer), perhaps I could try intersection without geomwithin()... Will give it a go when I'm back at a PC
    – she_weeds
    Commented Sep 4, 2018 at 21:27
  • Thank you for your reply @she_weeds , and for the additional details you have provided, too. I will try to add a modified version which does not need refFunctions plugin. (You might have tried it already).
    – Kazuhito
    Commented Sep 5, 2018 at 10:06
  • 1
    I've gone with a solution that works with my particular use case (because the irregular polygon is a geometry generator style and not an actual polygon, so using geometry() would not work), but it's based off your approach to extend the line and get the intersection so I've accepted your answer. Thanks Kazuhito!
    – she_weeds
    Commented Sep 6, 2018 at 0:00
2

Expanding on @Kazuhito's answer this is the expression I've used - simply an intersection() of the 45° line (extended x2) with the irregular polygon described in the original post.

Yet to test on larger datasets - I'm sure performance isn't optimal - but it's good enough for my use case and styling requirements.

intersection(make_line(
 $geometry,
 make_point($x + "tpzbsrad_m"*cos(radians(45))*2, 
 $y - ("tpzbsrad_m"*sin(radians(45))*2))),

union(buffer($geometry,"tpzbsrad_m"),buffer(make_polygon(make_line(
 translate($geometry,0,max("N",0.2)),
 translate($geometry,0.6*max("E",0.2),0.6*max("N",0.2)),
 translate($geometry,max("E",0.2),0),
 translate($geometry,0.6*max("E",0.2),-0.6*max("S",0.2)),
 translate($geometry,0,-max("S",0.2)),
 translate($geometry,-0.6*max("W",0.2),-0.6*max("S",0.2)),
 translate($geometry,-max("W",0.2),0), 
 translate($geometry,-0.6*max("W",0.2),0.6*max("N",0.2)),
 translate($geometry,0,max("N",0.2)))),1)))

See image below - always hits edge of the polygon now.

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.