Eu estou tentando calcular estatísticas raster (min, max, média) para cada polígono em uma camada de vetor usando PostgreSQL / PostGIS.
Esta resposta GIS.SE descreve como fazer isso, calculando a interseção entre o polígono e a varredura e calculando uma média ponderada: https://gis.stackexchange.com/a/19858/12420
Estou usando a seguinte consulta (onde dem
está minha varredura, topo_area_su_region
é meu vetor e toid
é um ID exclusivo:
SELECT toid, Min((gv).val) As MinElevation, Max((gv).val) As MaxElevation, Sum(ST_Area((gv).geom) * (gv).val) / Sum(ST_Area((gv).geom)) as MeanElevation FROM (SELECT toid, ST_Intersection(rast, geom) AS gv FROM topo_area_su_region,dem WHERE ST_Intersects(rast, geom)) foo GROUP BY toid ORDER BY toid;
Isso funciona, mas é muito lento. Minha camada vetorial possui recursos de 2489k, cada um levando cerca de 90ms para processar - levaria dias para processar toda a camada. A velocidade do cálculo não parece ser significativamente melhorada se eu calcular apenas o mínimo e o máximo (o que evita as chamadas para ST_Area).
Se eu fizer um cálculo semelhante usando Python (GDAL, NumPy e PIL), posso reduzir significativamente o tempo necessário para processar os dados, se, em vez de vetorizar a varredura (usando ST_Intersection), eu rasterizar o vetor. Veja o código aqui: https://gist.github.com/snorfalorpagus/7320167
Eu realmente não preciso de uma média ponderada - uma abordagem "se tocar, está dentro" é boa o suficiente - e estou razoavelmente certa de que é isso que está atrasando as coisas.
Pergunta : Existe alguma maneira de fazer com que o PostGIS se comporte dessa maneira? ou seja, para retornar os valores de todas as células da varredura que um polígono toca, em vez da interseção exata.
Eu sou muito novo no PostgreSQL / PostGIS, então talvez haja algo mais que não esteja fazendo certo. Estou executando o PostgreSQL 9.3.1 e o PostGIS 2.1 no Windows 7 (2.9GHz i7, 8GB de RAM) e aprimorei a configuração do banco de dados conforme sugerido aqui: http://postgis.net/workshops/postgis-intro/tuning.html
fonte
Respostas:
Você está certo, usando
ST_Intersection
retarda sua consulta perceptível.Em vez de usá-
ST_Intersection
lo, é melhor recortar (ST_Clip
) sua varredura com os polígonos (seus campos) e despejar o resultado como polígonos (ST_DumpAsPolygons
). Assim, cada célula raster será convertida em um pequeno retângulo de polígono com valores distintos.Para receber min, max ou média dos despejos, você pode usar as mesmas instruções.
Esta consulta deve fazer o truque:
Na declaração,
ST_Clip
você define a varredura, a banda da varredura (= 1), o polígono e se o corte deve ser VERDADEIRO ou FALSO.Além disso, você pode usar
avg((gv).val)
para calcular o valor médio.EDITAR
O resultado da sua abordagem é o mais exato, mas o mais lento. Os resultados da combinação de
ST_Clip
eST_DumpAsPolygons
estão ignorando as células de varredura que se cruzam com menos de 50% (ou 51%) de seu tamanho.Essas duas capturas de tela de um cruzamento do CORINE Land Use mostram a diferença. Primeira foto com
ST_Intersection
, segunda foto comST_Clip
eST_DumpAsPolygons
.fonte