名前

ST_MapAlgebraFct — 2バンド版 - 二つの入力バンドに対する妥当な PostgreSQL 関数で形成された、指定したピクセルタイプとなる 1バンドラスターを生成します。バンドを指定しない場合には、1番と仮定します。"extenttype"のデフォルトは INTERSECTION です。

概要

raster ST_MapAlgebraFct(raster rast1, raster rast2, regprocedure tworastuserfunc, text pixeltype=same_as_rast1, text extenttype=INTERSECTION, text[] VARIADIC userargs);

raster ST_MapAlgebraFct(raster rast1, integer band1, raster rast2, integer band2, regprocedure tworastuserfunc, text pixeltype=same_as_rast1, text extenttype=INTERSECTION, text[] VARIADIC userargs);

説明

[警告]

ST_MapAlgebraFct は 2.1.0で非推奨になりました。代わりにST_MapAlgebra (callback function version)を使います。

二つの入力ラスター (rast1, rast2) に対してtworastuserfuncで指定される妥当な PostgreSQL 関数で形成されるラスターを返します。band1またはband2が指定されていない場合には、1番と仮定します。新しいラスターは、元のラスターと同じ地理参照、幅、高さを持ちますが、一つのバンドしか持ちません。

pixeltypeが渡された場合には、新しいラスターはそのピクセルタイプのバンドを持ちます。pixelteype として NULL が渡されたりピクセルタイプを指定しない場合には、新しいラスターはrast1の入力バンドと同じピクセルタイプになります。

tworastuserfunc引数は、SQL または PL/pgSQL 関数の名前とシグニチャでなければならず、regprocedure にキャストしなければなりません。PL/pgSQL 関数の例は次の通りです:

コード
CREATE OR REPLACE FUNCTION simple_function_for_two_rasters(pixel1 FLOAT, pixel2 FLOAT, pos INTEGER[], VARIADIC args TEXT[])
RETURNS FLOAT
AS $$ BEGIN
    RETURN 0.0;
END; $$
LANGUAGE 'plpgsql' IMMUTABLE;

tworastuserfuncは 3または 4の引数を受け付けます。すなわち、一つ目の倍精度浮動小数点数、二つ目の倍精度浮動小数点数、任意引数の整列配列、VARIADIC 文字列配列です。第 1引数はrast1のラスターセルごとの値です (ラスターのデータ型に関係なく)。第 1引数はrast2のラスターセルごとの値です。第 3引数は現在の処理セルの位置で、'{x,y}'であらわされます。第 4引数はST_MapAlgebraFctへのパラメータの残っているもの全てがtworastuserfuncに渡されることを示します。

regprocedure引数を SQL 関数に渡す場合には、渡し先の完全な関数シグネチャが必要で、さらにregprocedureにキャストします。上の例の PL/pgSQL 関数を引数として渡すには、引数の SQL は次のようになります:

コード
'simple_function(double precision, double precision, integer[], text[])'::regprocedure

引数には関数名が含まれ、関数引数の型、関数名と引数型を引用符で括ったもの、regprocedureへのキャストが存在することに注意して下さい。

tworastuserfunc引数は variadic text配列です。どのST_MapAlgebraFctにもついてくる全ての文字列引数は、指定されたtworastuserfuncに、そのまま渡されて、userargs引数内に入ります。

[注記]

VARIADIC キーワードに関する詳細情報については、PostgreSQL 文書とQuery Language (SQL) Functions (訳注: 日本語版は「問い合わせ言語 (SQL)関数」です) の"SQL Functions with Variable Numbers of Arguments" (訳注: 日本語版は「可変長引数を取る SQL 関数」) 節を参照して下さい。

[注記]

text[]引数は、ユーザ関数 tworastuserfuncに処理用の引数を渡すかどうかにかかわらず求められます。

Availability: 2.0.0

例: 別個のバンドとしてキャンバス上にラスターをオーバレイする

非推奨になっている 2ラスターのコールバック形式を、現在有効な 2ラスター用の ST_MapAlgebra (callback function version) の式形式で表現することができます。この例では二つの入力ラスターを描画し、重なる部分を平均化したラスターを構築します。

コード
WITH canvas AS (
    SELECT ST_AddBand(
        ST_MakeEmptyRaster(80, 80, 0, 80, 1, -1, 0, 0, 0),
        1, '8BUI', 0, 0
    ) AS rast
), inputs AS (
    SELECT
        ST_AsRaster(ST_Buffer(ST_Point(30, 40), 25), rast, '8BUI', 80, 0)
            AS raster_1,
        ST_AsRaster(ST_Buffer(ST_Point(50, 40), 25), rast, '8BUI', 220, 0)
            AS raster_2
    FROM canvas
), variants AS (
    SELECT 'raster 1' AS title, raster_1 AS rendered FROM inputs
    UNION ALL
    SELECT 'raster 2', raster_2 FROM inputs
    UNION ALL
    SELECT 'averaged', ST_MapAlgebra(
        raster_1, 1,
        raster_2, 1,
        '([rast1] + [rast2]) / 2',
        '8BUI',
        'UNION'
    ) FROM inputs
)
SELECT title, ST_AsPNG(rendered) AS image
FROM variants
ORDER BY title DESC;
出力
title   | image
----------+-------------------------
 raster 2 | PNG image, 50 x 50 pixels
 raster 1 | PNG image, 50 x 50 pixels
 averaged | PNG image, 70 x 50 pixels
Geometry figure for visual-rt-st-mapalgebrafct2-01

ユーザー定義関数を定義します。

コード

CREATE OR REPLACE FUNCTION raster_mapalgebra_union(
    rast1 double precision,
    rast2 double precision,
    pos integer[],
    VARIADIC userargs text[]
)
    RETURNS double precision
    AS $$
    DECLARE
    BEGIN
        CASE
            WHEN rast1 IS NOT NULL AND rast2 IS NOT NULL THEN
                RETURN ((rast1 + rast2)/2.);
            WHEN rast1 IS NULL AND rast2 IS NULL THEN
                RETURN NULL;
            WHEN rast1 IS NULL THEN
                RETURN rast2;
            ELSE
                RETURN rast1;
        END CASE;

        RETURN NULL;
    END;
    $$ LANGUAGE 'plpgsql' IMMUTABLE COST 1000;

ラスターのテスト用テーブルの準備。

コード
DROP TABLE IF EXISTS map_shapes;
CREATE TABLE map_shapes(rid serial PRIMARY KEY, rast raster, bnum integer, descrip text);
INSERT INTO map_shapes(rast,bnum, descrip)
WITH mygeoms
    AS ( SELECT 2 As bnum, ST_Buffer(ST_Point(90,90),30) As geom, 'circle' As descrip
            UNION ALL
            SELECT 3 AS bnum,
                ST_Buffer(ST_GeomFromText('LINESTRING(50 50,150 150,150 50)'), 15) As geom, 'big road' As descrip
            UNION ALL
            SELECT 1 As bnum,
                ST_Translate(ST_Buffer(ST_GeomFromText('LINESTRING(60 50,150 150,150 50)'), 8,'join=bevel'), 10,-6) As geom, 'small road' As descrip
            ),
   -- define our canvas to be 1 to 1 pixel to geometry
   canvas
    AS ( SELECT ST_AddBand(
        ST_MakeEmptyRaster(
            250,
            250,
            ST_XMin(e)::integer,
            ST_YMax(e)::integer,
            1, -1, 0, 0),
        '8BUI'::text,
        0) As rast
        FROM (SELECT ST_Extent(geom) As e,
                    Max(ST_SRID(geom)) As srid
                    from mygeoms
                    ) As foo
            )
-- return our rasters aligned with our canvas
SELECT ST_AsRaster(m.geom, canvas.rast, '8BUI', 240) As rast, bnum, descrip
                FROM mygeoms AS m CROSS JOIN canvas
UNION ALL
SELECT canvas.rast, 4, 'canvas'
FROM canvas;

単一バンドの地図代数と ST_AddBand を使った結果の集約。

コード
INSERT INTO map_shapes(rast,bnum,descrip)
SELECT ST_AddBand(ST_AddBand(rasts[1], rasts[2]),rasts[3]), 4, 'map bands overlay fct union (canvas)'
    FROM (SELECT ARRAY(SELECT ST_MapAlgebraFct(
            m1.rast,
            m2.rast,
            'raster_mapalgebra_union(double precision, double precision, integer[], text[])'::regprocedure,
            '8BUI',
            'FIRST')
                FROM map_shapes As m1 CROSS JOIN map_shapes As m2
    WHERE m1.descrip = 'canvas' AND m2.descrip <
> 'canvas' ORDER BY m2.bnum) As rasts) As foo;

小型で実行可能なコールバックの例。元のラスターと平均値で上書きしたものがビルド時に描画されます。

コード
CREATE OR REPLACE FUNCTION pg_temp.raster_average(
    value_1 double precision,
    value_2 double precision,
    position integer[],
    VARIADIC userargs text[]
) RETURNS double precision
LANGUAGE SQL IMMUTABLE
AS 'SELECT COALESCE(($1 + $2) / 2.0, $1, $2)';

WITH canvas AS (
    SELECT ST_AddBand(
        ST_MakeEmptyRaster(80, 80, 0, 80, 1, -1, 0, 0, 0),
        1, '8BUI', 0, 0
    ) AS rast
), inputs AS (
    SELECT
        ST_AsRaster(ST_Buffer(ST_Point(30, 40), 25), rast, '8BUI', 80, 0)
            AS raster_1,
        ST_AsRaster(ST_Buffer(ST_Point(50, 40), 25), rast, '8BUI', 220, 0)
            AS raster_2
    FROM canvas
), variants AS (
    SELECT 'raster 1' AS title, raster_1 AS rendered FROM inputs
    UNION ALL
    SELECT 'raster 2', raster_2 FROM inputs
    UNION ALL
    SELECT 'averaged', ST_MapAlgebraFct(
        raster_1,
        raster_2,
        'pg_temp.raster_average(double precision,double precision,integer[],text[])'::regprocedure,
        '8BUI',
        'UNION'
    ) FROM inputs
)
SELECT title, ST_AsPNG(rendered) AS image
FROM variants
ORDER BY title DESC;
出力
title    | image
----------+---------------------------
 raster 2 | PNG image, 50 x 50 pixels
 raster 1 | PNG image, 50 x 50 pixels
 averaged | PNG image, 70 x 50 pixels

追加引数を取るユーザ定義関数

コード
CREATE OR REPLACE FUNCTION raster_mapalgebra_userargs(
    rast1 double precision,
    rast2 double precision,
    pos integer[],
    VARIADIC userargs text[]
)
    RETURNS double precision
    AS $$
    DECLARE
    BEGIN
        CASE
            WHEN rast1 IS NOT NULL AND rast2 IS NOT NULL THEN
                RETURN least(userargs[1]::integer,(rast1 + rast2)/2.);
            WHEN rast1 IS NULL AND rast2 IS NULL THEN
                RETURN userargs[2]::integer;
            WHEN rast1 IS NULL THEN
                RETURN greatest(rast2, random()*userargs[3]::integer)::integer;
            ELSE
                RETURN greatest(rast1, random()*userargs[4]::integer)::integer;
        END CASE;

        RETURN NULL;
    END;
    $$ LANGUAGE 'plpgsql' VOLATILE COST 1000;

SELECT ST_MapAlgebraFct(
    m1.rast,
    1,
    m1.rast,
    3,
    'raster_mapalgebra_userargs(double precision, double precision, integer[], text[])'::regprocedure,
    '8BUI',
    'INTERSECT',
    '100', '200', '200', '0')
                FROM map_shapes As m1
    WHERE m1.descrip = 'map bands overlay fct union (canvas)';
                    

上に示した生成されたコールバックの図はこの形式で使われるラスターのアライメントとオーバーラップを示します。正確なコールバックの結果はテキストで見ることができます。