QGIS – Cropping Voronoi Polygons to Specific Distance from Input Points

bufferclippolygonqgisvoronoi-thiessen

The Voronoi polygon algorithm propagates the polygons to the extent of the input layer (the points), which means some massive polygons. The majority of those massive polygons are nonsense data – we can't have any confidence that the values there are reasonable just because the value at a point a long way away is X (and that happens to be the nearest point sampled).

Potential solutions:

  1. set a single universal maximum distance from node point, so the polygons would be rounded out instead of continue.
  2. set a dynamic maximum distance based on nearby points… but I suspect that'd get complicated quick.

I'm not sure how to do this though. The Voronois are created by an algorithm in QGis, using the points as input. But the resulting voronoi polygons layer doesn't know where the points are. There doesn't look to be an option for this in the algorithm (Python function), sadly.

Possibly I could attach the input points to the output Voronoi somehow, to act as centroids for step 2. Step 2: apply some kind of buffering algorithm to each polygon, i.e. "set extent to be the current bounds or a circle of Y radius, whichever's smallest.

Has anyone ever done this?

Voronois being untrustable at a certain projection distance seems like something others would have had to deal with.

This picture shows points around Florida, USA. Easy to remove the centre by masking land, but I need ocean points to append to a grid and lots of them are going to be unreasonable/wrong.

Voronoi

Best Answer

Quick solution / principles

See below for variation with dynamic distance buffer

  1. Create voronoi polygons from your points (as you already did).
  2. Create a buffer around your points and be sure to check the dissolve option.
  3. Intersect buffer with polygon layer.

Voronoi polygons (blue) of the white points; red: dissolved buffer around the points: enter image description here

Green: voronoi polygons intersected with the buffers - everything outside of the buffer layer is clipped from the voronoi layer: enter image description here

Variations

  1. Make buffer with a dynamic distance, based on the density of the points (based on the nearest neighboring point). In the buffer tool, for Distance use data driven override and insert this expression (you can modify it to vary the buffer size even further):
length (
    make_line (
        $geometry, 
        array_first (
            overlay_nearest (
                'points',
                $geometry
))))

enter image description here

  1. On the buffer layer, run Multipart to single parts before intersection.

  2. After intersection, on the output layer check if there are any polygons that do not contain points (this is the case where the buffer of a points partially falls inside the voronoi polygon of another point - see screenshot). To select these "empty" poylgons, use Select by expression with this expression, where points is the name of the layer containing the points: overlay_contains( 'points') = false. Delete the selected polygons.

"Empty" polygons, highlighted in yellow; red: buffer with dynamic size, black lines: boundary of the voronoi polygons: enter image description here

Green: resulting voronoi polygons, clipped with a buffer with dynamic distance: enter image description here

Result, showing the whole result: voronoi-polygons clipped to a dynamic distance around the points, based on the density of the points (the closer points are, the smaller the voronoi polygons). Of course, there are no overlaps between polygons, but sometimes gaps between them: enter image description here