]> granicus.if.org Git - postgis/commitdiff
Added support to pass pixel positions of both rasters to user function in 2-raster...
authorBborie Park <bkpark at ucdavis.edu>
Mon, 6 Feb 2012 20:53:19 +0000 (20:53 +0000)
committerBborie Park <bkpark at ucdavis.edu>
Mon, 6 Feb 2012 20:53:19 +0000 (20:53 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@9052 b70326c6-7e19-0410-871a-916f4a2858ee

raster/rt_pg/rt_pg.c
raster/test/regress/rt_mapalgebrafct_2raster.sql

index 1e4ef01d43bb3c66c3f89db55e0a5068921852c6..d0126471071e9bf735caa7c8ddcf07ec1f5a8bc5 100644 (file)
@@ -8438,10 +8438,10 @@ Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS)
        int hasnodatanodataval = 0;
        double nodatanodataval = 0;
 
-       Oid ufcnoid = InvalidOid;
-       FmgrInfo uflinfo;
-       FunctionCallInfoData ufcinfo;
-       int ufcnullcount = 0;
+       Oid ufc_noid = InvalidOid;
+       FmgrInfo ufl_info;
+       FunctionCallInfoData ufc_info;
+       int ufc_nullcount = 0;
 
        int idx = 0;
        uint32_t i = 0;
@@ -8983,24 +8983,29 @@ Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS)
                case REGPROCEDUREOID: {
                        POSTGIS_RT_DEBUG(3, "arg 4 is \"userfunction\"!");
                        if (!PG_ARGISNULL(4)) {
-                               ufcnullcount = 0;
-                               ufcnoid = PG_GETARG_OID(4);
+                               ufc_nullcount = 0;
+                               ufc_noid = PG_GETARG_OID(4);
 
                                /* get function info */
-                               fmgr_info(ufcnoid, &uflinfo);
+                               fmgr_info(ufc_noid, &ufl_info);
 
                                /* function cannot return set */
                                err = 0;
-                               if (uflinfo.fn_retset) {
+                               if (ufl_info.fn_retset) {
                                        elog(ERROR, "RASTER_mapAlgebra2: Function provided must return double precision not resultset");
                                        err = 1;
                                }
                                /* function should have correct # of args */
-                               else if (uflinfo.fn_nargs != 3) {
-                                       elog(ERROR, "RASTER_mapAlgebra2: Function does not have three input parameters");
+                               else if (ufl_info.fn_nargs < 3 || ufl_info.fn_nargs > 4) {
+                                       elog(ERROR, "RASTER_mapAlgebra2: Function provided must have three or four input parameters");
                                        err = 1;
                                }
 
+                               /*
+                                       TODO: consider adding checks of the userfunction parameters
+                                               should be able to use get_fn_expr_argtype() of fmgr.c
+                               */
+
                                if (err) {
                                        for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]);
                                        rt_raster_destroy(raster);
@@ -9008,25 +9013,29 @@ Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS)
                                        PG_RETURN_NULL();
                                }
 
-                               if (func_volatile(ufcnoid) == 'v') {
+                               if (func_volatile(ufc_noid) == 'v') {
                                        elog(NOTICE, "Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
                                }
 
                                /* prep function call data */
 #if POSTGIS_PGSQL_VERSION <= 90
-                               InitFunctionCallInfoData(ufcinfo, &uflinfo, 3, InvalidOid, NULL);
+                               InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL);
 #else
-                               InitFunctionCallInfoData(ufcinfo, &uflinfo, 3, InvalidOid, NULL, NULL);
+                               InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
 #endif
-                               memset(ufcinfo.argnull, FALSE, 3);
+                               memset(ufc_info.argnull, FALSE, ufl_info.fn_nargs);
 
+                               if (ufl_info.fn_nargs != 4)
+                                       k = 2;
+                               else
+                                       k = 3;
                                if (!PG_ARGISNULL(7)) {
-                                ufcinfo.arg[2] = PG_GETARG_DATUM(7);
+                                       ufc_info.arg[k] = PG_GETARG_DATUM(7);
                                }
                                else {
-                                ufcinfo.arg[2] = (Datum) NULL;
-                                ufcinfo.argnull[2] = TRUE;
-                                ufcnullcount++;
+                                ufc_info.arg[k] = (Datum) NULL;
+                                ufc_info.argnull[k] = TRUE;
+                                ufc_nullcount++;
                                }
                        }
                        break;
@@ -9046,7 +9055,7 @@ Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS)
                        (spi_empty != spi_count) || hasnodatanodataval
                )
        ) || (
-               (calltype == REGPROCEDUREOID) && (ufcnoid != InvalidOid)
+               (calltype == REGPROCEDUREOID) && (ufc_noid != InvalidOid)
        )) {
                for (x = 0; x < dim[0]; x++) {
                        for (y = 0; y < dim[1]; y++) {
@@ -9258,29 +9267,52 @@ Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS)
                                                }
                                        }       break;
                                        case REGPROCEDUREOID: {
+                                               Datum d[4];
+                                               ArrayType *a;
+
                                                /* build fcnarg */
                                                for (i = 0; i < set_count; i++) {
-                                                       ufcinfo.arg[i] = Float8GetDatum(_pixel[i]);
+                                                       ufc_info.arg[i] = Float8GetDatum(_pixel[i]);
 
                                                        if (_haspixel[i]) {
-                                                               ufcinfo.argnull[i] = FALSE;
-                                                               ufcnullcount--;
+                                                               ufc_info.argnull[i] = FALSE;
+                                                               ufc_nullcount--;
                                                        }
                                                        else {
-                                                               ufcinfo.argnull[i] = TRUE;
-                                                               ufcnullcount++;
+                                                               ufc_info.argnull[i] = TRUE;
+                                                               ufc_nullcount++;
                                                        }
                                                }
 
                                                /* function is strict and null parameter is passed */
                                                /* http://archives.postgresql.org/pgsql-general/2011-11/msg00424.php */
-                                               if (uflinfo.fn_strict && ufcnullcount)
+                                               if (ufl_info.fn_strict && ufc_nullcount)
                                                        break;
 
-                                               datum = FunctionCallInvoke(&ufcinfo);
+                                               /* 4 parameters, add position */
+                                               if (ufl_info.fn_nargs == 4) {
+                                                       /* Datum of 4 element array */
+                                                       /* array is (x1, y1, x2, y2) */
+                                                       for (i = 0; i < set_count; i++) {
+                                                               if (i < 1) {
+                                                                       d[0] = Int32GetDatum(_pos[i][0]);
+                                                                       d[1] = Int32GetDatum(_pos[i][1]);
+                                                               }
+                                                               else {
+                                                                       d[2] = Int32GetDatum(_pos[i][0]);
+                                                                       d[3] = Int32GetDatum(_pos[i][1]);
+                                                               }
+                                                       }
+
+                                                       a = construct_array(d, 4, INT4OID, sizeof(int4), true, 'i');
+                                                       ufc_info.arg[2] = PointerGetDatum(a);
+                                                       ufc_info.argnull[2] = FALSE;
+                                               }
+
+                                               datum = FunctionCallInvoke(&ufc_info);
 
                                                /* result is not null*/
-                                               if (!ufcinfo.isnull) {
+                                               if (!ufc_info.isnull) {
                                                        haspixel = 1;
                                                        pixel = DatumGetFloat8(datum);
                                                }
index 135ab607c6860add94f218031500244f192fd8e5..13b0c8c6b1336b11dced7be7dc1c4ad650ce6aff 100644 (file)
@@ -55,6 +55,7 @@ DROP FUNCTION IF EXISTS make_test_raster(integer, integer, integer, double preci
 CREATE OR REPLACE FUNCTION raster_mapalgebra_intersection(
        rast1 double precision,
        rast2 double precision,
+       xy int[],
        VARIADIC userargs text[]
 )
        RETURNS double precision
@@ -142,7 +143,7 @@ CREATE OR REPLACE FUNCTION raster_mapalgebra_second(
 -- INTERSECTION
 INSERT INTO raster_mapalgebra_out
        (SELECT r1.rid, r2.rid, 'INTERSECTION', st_mapalgebrafct(
-               r1.rast, r2.rast, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION'
+               r1.rast, r2.rast, 'raster_mapalgebra_intersection(double precision, double precision, int[], text[])'::regprocedure, '32BF', 'INTERSECTION'
        )
        FROM raster_mapalgebra r1
        JOIN raster_mapalgebra r2
@@ -151,7 +152,7 @@ INSERT INTO raster_mapalgebra_out
                AND r2.rid BETWEEN 1 AND 9
        ) UNION ALL (
        SELECT r1.rid, r2.rid, 'INTERSECTION', st_mapalgebrafct(
-               r1.rast, r2.rast, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION'
+               r1.rast, r2.rast, 'raster_mapalgebra_intersection(double precision, double precision, int[], text[])'::regprocedure, '32BF', 'INTERSECTION'
        )
        FROM raster_mapalgebra r1
        JOIN raster_mapalgebra r2
@@ -162,21 +163,21 @@ INSERT INTO raster_mapalgebra_out
 
 INSERT INTO raster_mapalgebra_out
        SELECT NULL AS rid, rid, 'INTERSECTION', st_mapalgebrafct(
-               NULL::raster, rast, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION'
+               NULL::raster, rast, 'raster_mapalgebra_intersection(double precision, double precision, int[], text[])'::regprocedure, '32BF', 'INTERSECTION'
        )
        FROM raster_mapalgebra
 ;
 
 INSERT INTO raster_mapalgebra_out
        SELECT rid, NULL AS rid, 'INTERSECTION', st_mapalgebrafct(
-               rast, NULL::raster, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION'
+               rast, NULL::raster, 'raster_mapalgebra_intersection(double precision, double precision, int[], text[])'::regprocedure, '32BF', 'INTERSECTION'
        )
        FROM raster_mapalgebra
 ;
 
 INSERT INTO raster_mapalgebra_out
        SELECT NULL AS rid, NULL AS rid, 'INTERSECTION', st_mapalgebrafct(
-               NULL::raster, NULL::raster, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION'
+               NULL::raster, NULL::raster, 'raster_mapalgebra_intersection(double precision, double precision, int[], text[])'::regprocedure, '32BF', 'INTERSECTION'
        )
 ;
 
@@ -335,7 +336,7 @@ FROM (
        FROM raster_mapalgebra_out
 ) AS r;
 
-DROP FUNCTION IF EXISTS raster_mapalgebra_intersection(double precision, double precision, VARIADIC text[]);
+DROP FUNCTION IF EXISTS raster_mapalgebra_intersection(double precision, double precision, int[], VARIADIC text[]);
 DROP FUNCTION IF EXISTS raster_mapalgebra_union(double precision, double precision, VARIADIC text[]);
 DROP FUNCTION IF EXISTS raster_mapalgebra_first(double precision, double precision, VARIADIC text[]);
 DROP FUNCTION IF EXISTS raster_mapalgebra_second(double precision, double precision, VARIADIC text[]);