Estou tendo problemas para entender o uso de índices espaciais com o RTree.
Exemplo: tenho 300 pontos de buffer e preciso conhecer a área de interseção de cada buffer com um shapefile de polígono. O arquivo de forma do polígono possui> 20.000 polígonos. Foi sugerido o uso de índices espaciais para acelerar o processo.
SO ... Se eu criar um índice espacial para o meu shapefile de polígono, ele será "anexado" ao arquivo de alguma forma ou o índice permanecerá sozinho? Ou seja, depois de criá-lo, posso apenas executar minha função de interseção no arquivo polígono e obter resultados mais rápidos? A interseção "verá" que existem índices espaciais e sabe o que fazer? Ou preciso executá-lo no índice e relacionar esses resultados ao meu arquivo de polígono original por meio de FIDs ou algo assim?
A documentação do RTree não está me ajudando muito (provavelmente porque estou apenas aprendendo programação). Eles mostram como criar um índice lendo pontos criados manualmente e consultando-o em relação a outros pontos criados manualmente, que retornam IDs contidos na janela. Faz sentido. Mas eles não explicam como isso se relacionaria com algum arquivo original de onde o índice teria vindo.
Eu estou pensando que deve ser algo como isto:
- Puxe bboxes para cada recurso de polígono do meu shapefile de polígono e coloque-os em um índice espacial, fornecendo a eles um ID que seja igual ao ID no shapefile.
- Consulte esse índice para obter os IDs que se cruzam.
- Em seguida, execute novamente a interseção apenas nos recursos do meu shapefile original que foram identificados consultando meu índice (não tenho certeza de como eu faria essa última parte).
Eu tenho a ideia certa? Estou faltando alguma coisa?
No momento, estou tentando fazer com que esse código funcione em um shapefile de ponto que contém apenas um recurso de ponto e um shapefile de polígono que contém> 20.000 recursos de polígono.
Estou importando os shapefiles usando o Fiona, adicionando o índice espacial usando o RTree e tentando fazer a interseção usando o Shapely.
Meu código de teste é assim:
#point shapefile representing location of desired focal statistic
traps = fiona.open('single_pt_speed_test.shp', 'r')
#polygon shapefile representing land cover of interest
gl = MultiPolygon([shape(pol['geometry']) for pol in fiona.open('class3_aa.shp', 'r')])
#search area
areaKM2 = 20
#create empty spatial index
idx = index.Index()
#set initial search radius for buffer
areaM2 = areaKM2 * 1000000
r = (math.sqrt(areaM2/math.pi))
#create spatial index from gl
for i, shape in enumerate(gl):
idx.insert(i, shape.bounds)
#query index for ids that intersect with buffer (will eventually have multiple points)
for point in traps:
pt_buffer = shape(point['geometry']).buffer(r)
intersect_ids = pt_buffer.intersection(idx)
Mas continuo recebendo TypeError: o objeto 'Polygon' não pode ser chamado
.qix
é o índice quadtree MapServer / GDAL / OGR / SpatiaLiteTypeError: 'Polygon' object is not callable
seu exemplo de atualização porque substitui ashape
função que você importou de bem torneado com um objeto Polygon criado com esta linha:for i, shape in enumerate(gl):
Respostas:
Essa é a essência disso. A árvore R permite fazer uma primeira passagem muito rápida e fornece um conjunto de resultados que terão "falsos positivos" (caixas delimitadoras podem se cruzar quando as geometrias não precisarem). Em seguida, você examina o conjunto de candidatos (buscando-os no shapefile pelo índice) e faz um teste de interseção matematicamente preciso usando, por exemplo, Shapely. Essa é a mesma estratégia empregada em bancos de dados espaciais como o PostGIS.
fonte
Você quase conseguiu, mas cometeu um pequeno erro. Você precisa usar o
intersection
método no índice espacial, em vez de passar o índice para ointersection
método no ponto de buffer. Depois de encontrar uma lista de recursos em que as caixas delimitadoras se sobrepõem, é necessário verificar se o ponto em buffer realmente cruza as geometrias.Se você estiver interessado em encontrar pontos a uma distância mínima da sua classe de terra, use o
distance
método (troque a seção apropriada da anterior).Se estiver demorando muito tempo para criar seu índice espacial e você o fizer mais do que algumas vezes, tente serializar o índice em um arquivo. A documentação descreve como fazer isso: http://toblerity.org/rtree/tutorial.html#serializing-your-index-to-a-file
Você também pode observar o carregamento em massa das caixas delimitadoras na rtree usando um gerador, como este:
fonte
Sim, essa é a ideia. Aqui está um trecho deste tutorial sobre o uso de um índice espacial r-tree em Python , usando formas bem torneadas, Fiona e geopandas:
fonte