I want to locate or highlight all the holes (invalid interior rings that do not connect at all vertices and edges) and redundant geometry in a polygon shapefile in QGIS so that I can go back and manually correct all the vertices and geometry. I do not want to use the "Delete Holes" tool because I want to do it manually.
-
3Please Edit the Question to demonstrate which you mean by "holes", since there are valid "interior rings" and invalid interior rings, and both overlaps and underlaps that damage topologic completeness.– VinceCommented Jan 16 at 22:19
-
@Vince edited as requested– MapDeathCommented Jan 17 at 1:08
-
4Well, no. What makes them invalid? Valid interior rings also to not connect at edges. I was really looking for a demonstration. A graphic. If you can't define this mathematically, you can't do it manually.– VinceCommented Jan 17 at 1:30
-
2Do you mean like the first polygon: i.sstatic.net/0uCM9.png ?– BeraCommented Jan 17 at 6:24
2 Answers
You can easily find all invalid polygons by using the "Check validity" tool on the layer. In the output file with invalid polygons of this tool, there will also be a column that specifies why it is invalid:
Use QGIS expressions with functions interior_ring_n()
, exterior_ring()
and is_valid()
to get polygons that have holes and/or are invalid/vaild. Combine them to fit your needs like identifying or deleting holes. You have different options as you can see below.
Alternatives are Check validity tool, Geometry Checker Plugin and Topology Checker Plugin.
Automatically delete all holes from polygons
Use Geoemtry Generator or Geometry by expression (see here for both options) with this expression:
make_polygon (exterior_ring ($geometry))
Select polygons with holes
To identify polygons with holes, use Select by Expression and expression function interior_ring_n()
to return the first interior ring and if this indeed returns a geometry (and is not NULL
), you know the polygon has interior rings.
interior_ring_n ($geometry, 1) is not NULL
Alternatively, use num_interior_rings()
function:
num_interior_rings ($geometry) > 0
Show holes
To show holes, use the following expression with Geometry Generator to create a point marker for each hole (thus showing even very small, invisible holes):
collect_geometries(
array_foreach (
generate_series (1, num_interior_rings ($geometry)),
point_on_surface(make_polygon(interior_ring_n ($geometry, @element)))
)
)
Select polygons that are (in)valid
To identify polygons that are valid, use is_valid()
:
is_valid($geometry)
Select polygons with holes and validity combined
If you combine both, you can identify polygon with holes that are not valid:
interior_ring_n ($geometry, 1) is not NULL and
NOT is_valid($geometry)
Two polygons with invalid interior rings are selected (yellow); the polygon on the upper left is invalid, but not selected as it has no holes:
Show invalid interior rings as geometries
collect_geometries(
array_filter(
array_foreach (
generate_series (1, num_interior_rings ($geometry)),
case
when not is_valid (make_polygon(interior_ring_n ($geometry, @element)))
then make_polygon(interior_ring_n ($geometry, @element))
end
),
@element is not NULL
)
)
Blue polygons are invalid interior rings:
Show invalid interior rings as point markers
Alternatively, you could in line 7 you could enclose the make_polygon()
function into a point_on_surface()
function to get a point marker where you have invalid interior rings. Like this, you can see even extremely small interior rings (ke slivers) when zoomed out:
Red arrows shows location of point marker where an extremely small, invalid interior ring is located: