-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
Hi geopandas dev team:
The Issue / Question That I have
I am trying to come up with a consistent way to "clip" data that is in line with a typical GIS (think arcgis or qgis) workflow as follows:
- Clip takes a point, line or polygon feature to be clipped and a boundary polygon as the clipping extent
- Clip outputs a point, line or polygon feature that has ONLY features contained in the boundary polygon. Each feature if it's a line or poly is thus "CLIPPED" to that extent if that is required.
- Clip maintains the attributes of the clipped point, line or polygon features
On the back end - clipping points, lines or polygons is actually quite different. On the front end however - to a user - it is the "same" input and output.
input: some (shapefile) i want to clip to an extent
output: some clipped shapefile
What I tried initially - overlay()
Initially i tried to use overlay() with the how="intersection" argument. however that approach only seems to support polygon features. Did I do something wrong? I spent some time on this.
What I did / Tried
I am trying to create a simpler way for my students to "clip" a point, line or polygon layer using a boundary polygon object that exposes less of the back end differences between these object types when processed.
Below i've created a set of functions to make up a parent function that clips points, lines or polygons. I wondered if you could have a look at my code to help me determine if my approach is the most efficient one. I haven't built any tests -- yet but will.
Question 2 -- If applicable would this fit in geopandas? Or is there a better approach?
My next question if you don't mind and if i am able to find an approach that fits the project -- is if the geopandas project is open to such a function housed in geopandas? It is a task I and my colleagues do often!
Any feedback is appreciated. I do still owe you another PR for more documentation surrounding dissolve as well.
The Functions I Wrote
# Create function to clip point data using geopandas
def clip_points(shp, clip_obj):
'''
Docs Here
'''
poly = clip_obj.geometry.unary_union
return(shp[shp.geometry.intersects(poly)])
# Create function to clip line and polygon data using geopandas
def clip_line_poly(shp, clip_obj):
'''
docs
'''
# Create a single polygon object for clipping
poly = clip_obj.geometry.unary_union
spatial_index = shp.sindex
# Create a box for the initial intersection
bbox = poly.bounds
# Get a list of id's for each road line that overlaps the bounding box and subset the data to just those lines
sidx = list(spatial_index.intersection(bbox))
shp_sub = shp[shp.index.isin(sidx)]
# Clip the data - with these data
ne_roads_sub['geometry'] = ne_roads_sub.intersection(poly)
# Return the clipped layer with no null geometry values
return(ne_roads_sub.geometry.notnull())
## I just updated the above as I realized I could do this with one less line by updating the geometry col
# Final clip function that handles points, lines and polygons
def clip_shp(shp, clip_obj):
'''
'''
if shp["geometry"][0].type == "Point":
return(clip_points(shp, clip_obj))
else:
return(clip_line_poly(shp, clip_obj))