Eu tenho algum código que estou usando para determinar quais polígonos esculturais / MultiPolygons se cruzam com um número de linhas de formas bem torneadas. Através das respostas a esta pergunta, o código passou disso:
import fiona
from shapely.geometry import LineString, Polygon, MultiPolygon, shape
# Open each layer
poly_layer = fiona.open('polygon_layer.shp')
line_layer = fiona.open('line_layer.shp')
# Convert to lists of shapely geometries
the_lines = [shape(line['geometry']) for line in line_layer]
the_polygons = [(poly['properties']['GEOID'], shape(poly['geometry'])) for poly in poly_layer]
# 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
onde todas as interseções possíveis são verificadas, para isso:
import fiona
from shapely.geometry import LineString, Polygon, MultiPolygon, shape
import rtree
# Open each layer
poly_layer = fiona.open('polygon_layer.shp')
line_layer = fiona.open('line_layer.shp')
# Convert to lists of shapely geometries
the_lines = [shape(line['geometry']) for line in line_layer]
the_polygons = [(poly['properties']['GEOID'], shape(poly['geometry'])) for poly in poly_layer]
# Create spatial index
spatial_index = rtree.index.Index()
for idx, poly_tuple in enumerate(the_polygons):
_, poly = poly_tuple
spatial_index.insert(idx, poly.bounds)
# Check for Polygons/MultiPolygons that the LineString intersects with
covered_polygons = {}
for line in the_lines:
for idx in list(spatial_index.intersection(line.bounds)):
if the_polygons[idx][1].intersects(line):
covered_polygons[idx] = covered_polygons.get(idx, 0) + 1
onde o índice espacial é usado para reduzir o número de verificações de interseção.
Com os shapefiles que tenho (aproximadamente 4000 polígonos e 4 linhas), o código original executa 12936 .intersection()
verificações e leva cerca de 114 segundos para executar. O segundo pedaço de código que usa o índice espacial executa apenas 1816 .intersection()
verificações, mas também leva aproximadamente 114 segundos para ser executado.
O código para criar o índice espacial leva apenas 1-2 segundos para ser executado. Portanto, as verificações de 1816 no segundo trecho de código estão demorando quase a mesma quantidade de tempo que as 12936 verificam no código original (desde o carregamento do shapefiles e a conversão para geometrias Shapely são iguais em ambas as partes do código).
Não vejo nenhuma razão para que o índice espacial .intersects()
demore mais tempo a verificação; portanto, não sei por que isso está acontecendo.
Só consigo pensar que estou usando o índice espacial RTree incorretamente. Pensamentos?
intersects()
método leva mais tempo quando o índice espacial está sendo usado (veja a comparação de tempos acima), e é por isso que não tenho certeza se estou usando o índice espacial incorretamente. Ao ler a documentação e os posts vinculados, acho que sou, mas esperava que alguém pudesse apontar se não o fizesse.