Суммирование растра PostGIS (алгебра карт)

14

У меня есть таблица полигонов, представляющих изохроны времени в пути в определенные дни. Для каждой исходной точки существует пять изохронных геометрий (хранятся в отдельных строках). Для каждой исходной точки я хочу растеризовать пять изохрон (двоичный NULL или 1), а затем объединить их в один растровый слой. Этот растровый слой требует простой алгебры карты: sum / 5, так что каждый источник в конце будет связан с одним растровым слоем, который имеет значения в [NULL, 0.2, 0.4, 0.6, 0.8, 1] в зависимости от того, сколько составляющие слои перекрываются. Это поверхность вероятности.

Все мои данные хранятся в Postgres 9.3 (с PostGIS). Моя проблема в том, что, хотя я хочу научиться использовать растр PostGIS, у него, похоже, действительно крутая кривая обучения, и все примеры, которые я могу найти, касаются одного растрового слоя. В примерах этот слой используется как часть наложения полигонов, возможно, усредняя значение растра для каждого полигона. Я не нашел воспроизводимого примера для объединения: а) вектора -> растра б) алгебры карты; и c) атрибут GROUP BY согласно моему первому абзацу.

Я в порядке, используя GDAL или GRASS, если мне нужно для выполнения этой задачи, но это похоже на то, что PostGIS должен уметь обрабатывать; было бы удобно сделать это, учитывая, что мои входные данные уже являются геометрией PostGIS; и я действительно хочу смириться с растром PostGIS.

Пример структуры данных:

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

Я хочу растеризовать, сгруппировать по areaid, а затем выполнить алгебру карты, чтобы перейти к:

areaid    isorast (raster)
1000      aaa
1006      bbb

Я не был в состоянии содержать это в PostGIS. Мой подход состоял в том, чтобы преобразовать вектор в растр, сбросить растры в массивы и выполнить комбинацию с массивными массивами с помощью psycopg2, прежде чем записывать их в GeoTIFF (который может быть возвращен в PostGIS). Не идеально, но выполнимо.

alphabetasoup
источник
1
Классный вопрос. Я делюсь тем, что действительно нужно изучать постгисным растром, и уверен, что то, что вы хотите, возможно. К сожалению, сегодня слишком занят, чтобы пойти.
Джон Пауэлл
1
В этом блоге BostonGIS есть довольно хардкорная статья об алгебре карт . Автор этого блога также является автором превосходной книги «Postgis in Action», в которой много растровых возможностей Postgis. Извините, я не смог придумать более прямой пример.
Джон Пауэлл

Ответы:

3

Вам нужно будет написать собственную агрегатную функцию:

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
);

после этого вы можете назвать это так

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

Это дает вам сумму всех ваших растров с одинаковым идентификатором области. Вам все равно нужно будет разделить растровые значения на количество наблюдений для каждого идентификатора области. (Я не включил его в агрегатную функцию. Вы можете сделать это здесь или позже, используя MapAlegbra)

Убедитесь, что все входные растры выровнены, иначе это не сработает.

Томас
источник