Somme raster PostGIS (algèbre de carte)

14

J'ai un tableau de polygones représentant les isochrones de temps de voyage certains jours. Pour chaque point d'origine, il existe cinq géométries isochrones (stockées dans des rangées distinctes). Pour chaque point d'origine, je souhaite pixelliser les cinq isochrones (un NULL binaire ou 1), puis les combiner en une seule couche raster. Cette couche raster nécessite une algèbre de carte simple: somme / 5, de sorte que chaque origine sera finalement associée à une seule couche raster qui a des valeurs dans [NULL, 0,2, 0,4, 0,6, 0,8, 1] selon le nombre de les couches constitutives se chevauchent. C'est une surface de probabilité.

Mes données sont toutes stockées dans Postgres 9.3 (avec PostGIS). Mon problème est que même si je veux apprendre à utiliser le raster PostGIS, il semble avoir une courbe d'apprentissage très abrupte, et tous les exemples que je peux trouver concernent une seule couche raster. Dans les exemples, cette couche est utilisée dans le cadre d'une superposition de polygones, en faisant peut-être la moyenne de la valeur du raster pour chaque polygone. Je n'ai pas trouvé d'exemple reproductible pour combiner: a) vecteur -> raster b) algèbre cartographique; et c) attribut GROUP BY selon mon premier paragraphe.

Je peux utiliser GDAL ou GRASS si je le dois pour effectuer cette tâche, mais cela semble être quelque chose que PostGIS devrait être capable de gérer; ce serait pratique étant donné que mes données d'entrée sont déjà de la géométrie PostGIS; et je veux vraiment accepter les rasters PostGIS.

Quelques exemples de structure de données:

areaid    time        date          isogeom (polygon)
1000      07:15:00    2014-05-05    xxx
1000      07:15:00    2014-05-06    xxy
...
1006      07:15:00    2014-05-05    zzz

Je souhaite pixelliser, grouper par areaid, puis effectuer l'algèbre de la carte pour arriver à:

areaid    isorast (raster)
1000      aaa
1006      bbb

Je n'ai pas réussi à contenir ceci dans PostGIS. Mon approche a été de convertir le vecteur en raster, de vider les rasters en tableaux et d'effectuer la combinaison avec des tableaux numpy via psycopg2, avant de les écrire dans un GeoTIFF (pour peut-être les remettre dans PostGIS). Pas idéal, mais faisable.

alphabetasoup
la source
1
Cool question. Je partage vraiment le sentiment de raster postgis et je suis sûr que ce que vous voulez est possible. Malheureusement trop occupé aujourd'hui pour essayer.
John Powell
1
Il y a un article assez hardcore sur l'algèbre des cartes dans ce blog de BostonGIS . L'auteur de ce blog est également l'auteur de l'excellent livre, Postgis in Action, qui possède de nombreuses capacités matricielles de Postgis. Désolé, je n'ai pas pu trouver un exemple plus direct.
John Powell

Réponses:

3

Vous devrez écrire votre propre fonction d'agrégation:

CREATE OR REPLACE function sum_raster_state(raster, raster)
returns raster
language sql
as $f$

SELECT
CASE $1
WHEN NULL THEN
      $2
ELSE
    ST_MapAlgebra(
        $1, 
        $2, 
        '([rast1] + [rast2])', 
        NULL, 
        'UNION', 
        '[rast2]', 
        '[rast1]', 
        NULL)
END;
$f$;

CREATE OR REPLACE FUNCTION sum_raster_final(raster)
returns raster
language sql
as $f$
SELECT 
   $1
$f$;

create aggregate sum_raster(raster) (
    SFUNC = sum_raster_state,
    STYPE = raster,
    FINALFUNC = sum_raster_final
);

après, vous pouvez l'appeler comme ça

SELECT areaid, sum_raster(st_asraster(isogeom, ...)) FROM isochrone GROUP BY areaid

Cela vous donne la somme de tous vos rasters avec le même ID de zone. Vous devrez toujours diviser les valeurs raster par le nombre d'observations pour chaque ID de zone. (Je ne l'ai pas inclus dans la fonction d'agrégation. Vous pouvez le faire ici ou après en utilisant MapAlegbra)

Assurez-vous que vos rasters en entrée sont tous alignés, sinon cela ne fonctionnera pas.

Thomas
la source