I have a shapefile that contains several thousand Polygons/MultiPolygons and another shapefile that has a variable number of LineStrings. In the example below the blue Polygons are those that intersect with the red LineString and the brown Polygons are those that do not.
I am using the Shapely intersects
binary predicate to check whether each LineString intersects with any one of the Polygons:
import fiona
from shapely.geometry import LineString, Polygon, MultiPolygon
# Open each layer
poly_layer = fiona.open('polygon_layer.shp', 'r')
line_layer = fiona.open('line_layer.shp', 'r')
# Create each Polygon/MultiPolygon
the_polygons = []
for poly in poly_layer:
if poly['geometry']['type'] == 'Polygon':
the_polygons.append((poly['properties']['poly_id'],
Polygon(poly['geometry']['coordinates'][0])))
elif poly['geometry']['type'] == 'MultiPolygon':
all_polygons = []
for poly_coords in poly['geometry']['coordinates']:
all_polygons.append(Polygon(poly_coords[0]))
the_polygons.append((poly['properties']['poly_id'],
MultiPolygon(all_polygons)))
else:
print poly['geometry']['type']
raw_input()
# Create each LineString
the_lines = []
for line in line_layer:
the_lines.append(LineString(line['geometry']['coordinates']))
# Check for Polygons/MultiPolygons that the LineString intersects with
covered_polygons = {}
for poly_id, poly in the_polygons:
for line in the_lines:
if poly.intersects(line):
covered_polygons[poly_id] = covered_polygons.get(poly_id, 0) + 1
The above code takes a long time to run, and being new to Fiona and Shapely I am not sure that this is the most efficient way to accomplish things. So is there a better way to do what I want?
Edit: The key to speeding up the computations was to use a spatial index. The linked question does not have what I believe is the fastest solution - using GeoPandas.
the_polygons = [shape(g['geometry']) for g in poly_layer]
to create Shapely geometries from the Fiona records.