An overlay can leave a line or a point behind: inside a GEOMETRYCOLLECTION,
or – where everything left of a polygon is a shared edge – as a bare
LINESTRING sitting directly in the geometry column. Only the polygons carry
area, and the residue causes trouble downstream out of all proportion to the
area it represents, which is none.
keep_polygons(x)sf object holding only non-empty POLYGON / MULTIPOLYGON
features. May have more rows than x, when a collection held several
polygons, and fewer when a feature had no polygonal part at all.
GEOMETRYCOLLECTION is not enoughTwo polygons that share only an edge intersect in a bare LINESTRING, with
no collection anywhere in the result, so a guard written as
if (any(st_geometry_type(x) == "GEOMETRYCOLLECTION")) never fires.
The way that fails is worth spelling out. terra::vect() drops a
non-polygon geometry while keeping its attribute row, so the SpatVector
comes back carrying more attribute rows than it has geometries. Nothing
complains at the time; the next thing to touch the attributes fails instead,
a long way from the cause. Measured on one tile of a real study area, exactly
one of 6,871 differences was such a line, and it surfaced two function calls
later as [as,sf] coercion failed.
Filtering in sf is what makes this safe: attributes are columns of the same
data frame as the geometry, so they cannot desynchronise.