5

I have created a buffer out of point values with a fixed buffer zone of 150m. I would like to make the buffer look more naturally.

I would accept an error margin of +/- 20 meters to flatten the curves into a more "natural" look. How do I do that?

Example of a non-smoothen buffer

1
  • 3
    Can you add a drawing showing what you're after
    – Bera
    Commented Dec 10, 2022 at 16:53

4 Answers 4

10

This is a case for a convex or concave hull - depending how much additional space you want to include.

Concave hull gives you more flexibility: there is just one single convex hull per geometry, but different possible concave hulls (depending on input paramenters).

In QGIS, there are several options to create such hull, including QGIS expressions (concave hull, however, requires GEOS 3.11 or later, which is not the case in my installation).

Another option is to use the tools under Menu Processing > Toolbox - type "hull" to find the relevant algorithms. See the screenshot for results: black line corresponds to convex hull, red line to Concave Hull (K-Nearest Neighbor) with the settings as you can see on the screenshot. Change these values to adapt results: a small value is close to the input geometry, a large value will result in a convex hull.

enter image description here


An alternative would be creating a Concave hull (Alpha shapes) based on your input points first and only then buffer the result:

Same data as before: red dots=input points; blue line=Concave hull (Alpha shapes); blue polygon=buffered alpha shapes; dotted lines in black and red: result from the first solution (see screenshot above): enter image description here

3
  • 1
    Not sure what you mean... The examples above were also created from one single layer. If you buffer first, be sure to convert multipart to single parts first bevore proceeding with convex/concave hull
    – Babel
    Commented Dec 10, 2022 at 14:59
  • Is it possible to Concave Hull (K-Nearest Neighbor) for polygones composed of around ~ 1000 points? My QGis always crashes if I try this, but not if I choose a smaller polygon.
    – Cristian
    Commented Dec 12, 2022 at 18:49
  • Try generalizing (simplify) the polygon
    – Babel
    Commented Dec 12, 2022 at 19:05
4

You can increase the number of segments used to approximate a curve using the "Segments" parameter of the QGIS's Buffer tool:

150m buffer created using the default 5 segments on top of a buffer created with 100 segments:

enter image description here

4

Another option is first to apply another buffer at a relativele larger distance and then apply once again a buffer with the negative value of this distance. This keeps the result more or less at the initial buffer you have, but flattens it, eliminating "bays". The advantage is that depending on the (additional) buffer distance, you can have heavier or lesser flattening effects.

Red points with initial buffer (150 m) = black line, 300 m distance buffer (blue line) and final buffer (red line), a -300 m buffer from the blue one: enter image description here

A good and easy way to test differint buffer distances and see in realtime the "flattening" effects is to use geometry generator with the following expression (change the value of 300 to see different flattening effects):

with_variable ('dist', 300, -- change value here
    buffer (buffer ($geometry,@dist),-@dist)
)

"Preview" with geometry generator and different distances to test which one fits best your needs: enter image description here

When satisfied with the result, run the regular buffer tool (Menu Vector > Geoprocessing tools) twice with the distance and its negative value or run Menu Processing > Toolbox > Geometry by Expression with the same expression to get the result as actual polygon.

4

In such cases, I usually use the following expression, which allows you to configure the final vector result very flexibly:

smooth(
    simplify(
        buffer($geometry, distance:=150, segments:=30),
    tolerance:=10),
iterations:=5)

This particular construction of the expression assumes that all your points are combined into one multipoint object (i.e. there will be one row in the attribute table of the layer). If all your points are separate objects, then I think it will not be difficult for you to create a derived layer in which all the points will be combined into one multipoint.

There are two functions involved in this expression that allow flatten the curves into a more "natural" ("organic") look:

  1. simplify - simplifies a geometry by removing nodes using a distance-based threshold (the algorithm preserves large deviations in geometries and reduces the number of vertices in nearly straight segments).
    In our case, in my opinion, a value of 10 m for argument "tolerance" gives a good result.

  2. smooth - smooths a geometry by adding extra nodes which round off corners in the geometry.
    This algorithm has a rich set of arguments that allow you to flexibly control the smoothing process and, accordingly, adjust the geometry features of the resulting result. In our case, to get an excellent result, in my opinion, it is quite enough to use only one argument "iterations", setting the value "5" for it.

If you just need to visualize the result, then use the geometry generator with the above expression.

enter image description here


To get the result that suits you best, try changing the argument "tolerance". It all depends on your preferences in terms of simplifying the final geometry, but, as for me, the values in the range from 5 to 20 for our case look quite "natural".
At the same time, to get a better result, you can slightly increase the argument "distance" for the "buffer" algorithm (for example, up to 160 m). For example:

enter image description here


When the result satisfies you, you can create an actual polygon layer.
To do this, use the "Geometry by expression" algorithm (Menu Processing > Toolbox > Geometry by Expression) with the same expression.


If you do not need to create an actual polygon layer (when you just need a beautiful visualization), and all the points are separate objects and it is not convenient or you do not want to combine them into one multipoint, just use the following expression for the geometry generator:

smooth(
    simplify(
        buffer(collect($geometry), distance:=150, segments:=30),
    tolerance:=10),
iterations:=5)

I hope this method will be useful in your projects.

1
  • Smooth is indeed a great way to do that - good idea!
    – Babel
    Commented Jan 6, 2023 at 22:00

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.