7

I have a a dataframe of polygons in GeoPandas/shapely. Most of them are valid, and remaining invalid polygons can be removed with ".is_valid" command. However, some polygons are in theory valid, but in practice useless.

My issue is the case in the image below. The polygon consists of 3 vertices, but one vertex is, all but, on the line with the other points. Is there a way I can mark this polygon as invalid and remove it? I know the QGIS Fix Geometries is able to identify this issue. I can do a quick fix by using the polygon area and removing under a threshold, but I was hoping there is a more elegant solution to detect this.

Polygon is the line, point show vertices for clarity

3
  • 2
    Does the area method detect polygons you want to keep or what is the problem?
    – Bera
    Commented Oct 3, 2022 at 16:59
  • Similarily not sure why area method is not good enough. Another approach would be to check for each point of a 3-point polygon if one of the vertices is very close to the line connecting the two other points (buffer this line and check if the 3rd vertex is inside).
    – Babel
    Commented Oct 4, 2022 at 7:17
  • Another approach: calculate lengths of the 3 sides and see if the largest side is more or less equal (allowing a small threshold) than the sum of the two other sides.
    – Babel
    Commented Oct 4, 2022 at 7:19

2 Answers 2

8

What determines your polygon that is too skinny? You could calculate the isoperimetric quotient for you polygons, then determine an IQ value that meets your criteria. Then select and delete those polygons with an IQ that is too small.

Here is the formula for IQ where a result of 1.0 describes a perfect circle.

IQ = (4 * pi * area) / (perimeter^2)
0

You can use shapely.set_precision on the polygons with a grid_size ~10 times larger than the maximum sliver width you want to clean.

This will have the following effects:

  • Coordinates will be rounded if the precision grid specified is less precise than the input geometry. Duplicated vertices will be dropped from lines and polygons.
  • Line and polygon geometries will become "empty" if all vertices are closer together than the grid size or, for polygons, if they become significantly narrower than the grid size.
  • Spikes or sections in Polygons significantly narrower than grid_size after rounding the vertices will be removed.

Based on some tests I did in the past, using a grid size >= 0.00000001 (10e-8) cleaned up all lines in the output of an overlay operation for my data.

If you don't want to change the input polygons that would not be cleaned up, you can ofcourse just filter the ones that become empty based om set_precision.

Code sample:

import geopandas as gpd
import shapely


# Test data
sliver_width = 0.0001
sliver = shapely.Polygon([(0, 0), (10, 0), (10, sliver_width), (0, 0)])
poly = shapely.Polygon([(0 + sliver_width, 1), (10, 1), (10, 5), (0, 5), (0, 1)])
gdf = gpd.GeoDataFrame(geometry=[sliver, poly])

# Set precision with a grid_size ~10 times larger than the sliver width
precision_gdf = gdf.copy()
precision_gdf.geometry = shapely.set_precision(
    precision_gdf.geometry, grid_size=sliver_width * 10
)
filtered_gdf = gdf.loc[~precision_gdf.is_empty]

print(f"Input\n{gdf}")
print(f"Result of set_precision\n{precision_gdf}")
print(f"Result of only filtering with set_precision\n{filtered_gdf}")

# Output:
# Input
#                                             geometry
# 0  POLYGON ((0.00000 0.00000, 10.00000 0.00000, 1...
# 1  POLYGON ((0.00010 1.00000, 10.00000 1.00000, 1...
# Result of set_precision
#                                             geometry
# 0                                      POLYGON EMPTY
# 1  POLYGON ((0.00000 5.00000, 10.00000 5.00000, 1...
# Result of only filtering with set_precision
#                                             geometry
# 1  POLYGON ((0.00010 1.00000, 10.00000 1.00000, 1...

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.