6

I'm trying to clip a shapefile with another .shp using pure python.

Original shp I need to clip:

enter image description here

Area of Interest for clipping (shown overlapped to the original .shp for convenience):

enter image description here

If I invoke clipvectorbypolygon from QGIS toolbox via processing.run, I get the desired result:

params = {'INPUT': original_shape,
          'MASK': area_of_interest,
          'OPTIONS':'',
          'OUTPUT': result_shape
         }

processing.run("gdal:clipvectorbypolygon", parameters = params)

enter image description here

But, when trying to replicate it using pure python, I always obtain a clipped polygon with the inner areas filled:

I've tried by using geopandas.clip

input = gpd.read_file(original_shape)

clipped = gpd.clip(input, area_of_interest)

clipped.to_file(result_shape)

and geopandas.GeoSeries.intersection:

input = gpd.read_file(original_shape)

clipped = gpd.GeoSeries.intersection(input, area_of_interest)

clipped.to_file(result_shape)

Both produce the same result:

enter image description here

exploding the original .shp gives a slightly different output, but same problem:

input = gpd.read_file(original_shape).explode()

for index, row in input['geometry'].iteritems():
    clipped = gpd.clip(area_of_interest, row)
    clipped.to_file(os.path.join(output_path, f'{index}.shp'))

enter image description here

The only way of not getting filled polygons is passing as mask just the extent of the Area of Interest with total_bounds, but (predictably) the output is a shape with more geometry as needed:

input = gpd.read_file(original_shape)

clipped = gpd.clip(input, area_of_interest.total_bounds)

clipped.to_file(result_shape)

enter image description here

EDIT: Additional info

The problem seems to be when the result is written to a file. Plotting clipped apparently gives the expected outcome:

clipped.plot().axis('off')
clipped.boundary.plot().axis('off')

enter image description here

2

1 Answer 1

4

In case of invalid geometry, you might get a result like this.

Try make_valid function of shapely

from shapely.validation import make_valid

Before clipping:

input_df["geometry"] = input_df.geometry.apply(make_valid)

or after clipping:

clipped["geometry"] = clipped.geometry.apply(make_valid)

clipped.to_file(result_shape)
2
  • Thanks for the input. For better or worse, the geometry seems to be already valid and it doesn't have an impact on the outcome...
    – Jucjon
    Commented Apr 5, 2023 at 11:53
  • Could you share your data, if you don't mind? Commented Apr 5, 2023 at 11:55

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.