qgis – How to Delete Every Other Overlapping Polygon in QGIS

overlapping-featuresqgis

I have a bunch of GPS points that need to be a minimum set distance (100m) apart from each other. I have buffered these points, however this results in long chains of overlapping polygons that I need to manually go through to delete every other polygon.

I am trying to preserve as many polygons as possible, so when I automatically select all overlapping polygons and delete, there is a huge loss in total polygons (hence the manual deletion process).

Is there any way for QGIS to automatically select every other polygon for deletion (like as seen below)?

enter image description here

Best Answer

Create an array of all id's, than generate a series of every second element of this array. Apply this only for features that intersect other features.

To do so, use this expression with select by expression:

case 
when overlay_intersects(@layer)
then
array_contains( 
    with_variable (
        'array',
        array_agg( $id),
        generate_series (1, array_length(@array),2)
    ), 
    $id
)
end

enter image description here


There might be the case that you don't have an id that follows the spatial order of your polygons. In this case, create a new field that you can use in the expression above instead of $id. For this, first create a line layer and draw a line along the polygons in the correct order. Then on the polygon layer, create this order field using the following expression:

with_variable(
    'line',  
    overlay_nearest ('lineorder', $geometry)[0],
    array_find (
        array_sort(
            array_agg (
                line_locate_point (
                    @line,
                    centroid ($geometry)
                )
            )
        ),
        line_locate_point (
            @line,
            centroid ($geometry)
        )
    )
)

Or, without creating a separate field, use this expression directly in select by expression:

with_variable (
    'order',
    with_variable(
    'line',  
    overlay_nearest ('lineorder', $geometry)[0],
    array_find (
        array_sort(
            array_agg (
                line_locate_point (
                    @line,
                    centroid ($geometry)
                )
            )
        ),
        line_locate_point (
            @line,
            centroid ($geometry)
        )
    )
),


case 
when overlay_intersects(@layer)
then
array_contains( 
    with_variable (
        'array',
        array_agg(@order),
        generate_series (1, array_length(@array),2)
    ), 
    @order
)
end
)

Correctly selecting every second polygon even though id (see labeled values) are in random order. The order of the polygon is createad as distance along the red line of the polygon's centroid: enter image description here

Related Question