]> granicus.if.org Git - postgis/commitdiff
First steps of add ST_SetValues() variant for array of values
authorBborie Park <bkpark at ucdavis.edu>
Tue, 31 Jul 2012 23:43:56 +0000 (23:43 +0000)
committerBborie Park <bkpark at ucdavis.edu>
Tue, 31 Jul 2012 23:43:56 +0000 (23:43 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@10145 b70326c6-7e19-0410-871a-916f4a2858ee

raster/rt_pg/rt_pg.c
raster/rt_pg/rtpostgis.sql.in.c

index 89705a823692d85d6b512a17abcba35871152936..b294477823eb8310f5e8f4bdfe5ab57e7d5f09ae 100644 (file)
@@ -196,8 +196,9 @@ Datum RASTER_setBandNoDataValue(PG_FUNCTION_ARGS);
 /* Get pixel value */
 Datum RASTER_getPixelValue(PG_FUNCTION_ARGS);
 
-/* Set pixel value */
+/* Set pixel value(s) */
 Datum RASTER_setPixelValue(PG_FUNCTION_ARGS);
+Datum RASTER_setPixelValuesArray(PG_FUNCTION_ARGS);
 
 /* Get pixel geographical shape */
 Datum RASTER_getPixelPolygons(PG_FUNCTION_ARGS);
@@ -2405,14 +2406,14 @@ Datum RASTER_setPixelValue(PG_FUNCTION_ARGS)
 
        /* Validate pixel coordinates are not null */
        if (PG_ARGISNULL(2)) {
-               elog(NOTICE, "X coordinate can not be NULL when getting pixel value. Value not set. Returning original raster");
+               elog(NOTICE, "X coordinate can not be NULL when setting pixel value. Value not set. Returning original raster");
                skipset = TRUE;
        }
        else
                x = PG_GETARG_INT32(2);
 
        if (PG_ARGISNULL(3)) {
-               elog(NOTICE, "Y coordinate can not be NULL when getting pixel value. Value not set. Returning original raster");
+               elog(NOTICE, "Y coordinate can not be NULL when setting pixel value. Value not set. Returning original raster");
                skipset = TRUE;
        }
        else
@@ -2468,6 +2469,150 @@ Datum RASTER_setPixelValue(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(pgrtn);
 }
 
+PG_FUNCTION_INFO_V1(RASTER_setPixelValuesArray);
+Datum RASTER_setPixelValuesArray(PG_FUNCTION_ARGS)
+{
+       rt_pgraster *pgraster = NULL;
+       rt_pgraster *pgrtn = NULL;
+       rt_raster raster = NULL;
+       rt_band band = NULL;
+       int numbands = 0;
+
+       int nband = 0;
+       int width = 0;
+       int height = 0;
+
+       ArrayType *array;
+       Oid etype;
+       Datum *e;
+       bool *nulls;
+       int16 typlen;
+       bool typbyval;
+       char typalign;
+       int ndims = 1;
+       int *dims;
+       int *lbs;
+
+       HeapTupleHeader tup;
+       bool isnull;
+       Datum tupv;
+
+       int ul[2] = {0};
+       double **vals = NULL;
+
+       int i = 0;
+       int j = 0;
+       int x = 0;
+       int y = 0;
+
+       /* pgraster is null, return null */
+       if (PG_ARGISNULL(0))
+               PG_RETURN_NULL();
+       pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+       /* raster */
+       raster = rt_raster_deserialize(pgraster, FALSE);
+       if (!raster) {
+               elog(ERROR, "RASTER_setPixelValuesArray: Could not deserialize raster");
+               PG_FREE_IF_COPY(pgraster, 0);
+               PG_RETURN_NULL();
+       }
+
+       /* raster attributes */
+       numbands = rt_raster_get_num_bands(raster);
+       width = rt_raster_get_width(raster);
+       height = rt_raster_get_height(raster);
+
+       /* nband */
+       if (PG_ARGISNULL(1)) {
+               elog(NOTICE, "Band index cannot be NULL.  Value must be 1-based.  Returning original raster");
+               rt_raster_destroy(raster);
+               PG_RETURN_POINTER(pgraster);
+       }
+
+       nband = PG_GETARG_INT32(1);
+       if (nband < 1 || nband > numbands) {
+               elog(NOTICE, "Band index is invalid.  Value must be 1-based.  Returning original raster");
+               rt_raster_destroy(raster);
+               PG_RETURN_POINTER(pgraster);
+       }
+
+       /* x, y */
+       for (i = 2, j = 0; i < 4; i++, j++) {
+               if (PG_ARGISNULL(i)) {
+                       elog(NOTICE, "%s cannot be NULL.  Value must be 1-based.  Returning original raster", j < 1 ? "X" : "Y");
+                       rt_raster_destroy(raster);
+                       PG_RETURN_POINTER(pgraster);
+               }
+
+               ul[j] = PG_GETARG_INT32(i);
+               if (
+                       (ul[j] < 1) || (
+                               (j < 1 && ul[j] > width) ||
+                               (j > 0 && ul[j] > height)
+                       )
+               ) {
+                       elog(NOTICE, "%s is invalid.  Value must be 1-based.  Returning original raster", j < 1 ? "X" : "Y");
+                       rt_raster_destroy(raster);
+                       PG_RETURN_POINTER(pgraster);
+               }
+       }
+
+       /* new value set */
+       if (PG_ARGISNULL(4)) {
+               elog(NOTICE, "No values to set.  Returning original raster");
+               rt_raster_destroy(raster);
+               PG_RETURN_POINTER(pgraster);
+       }
+
+       array = PG_GETARG_ARRAYTYPE_P(4);
+       etype = ARR_ELEMTYPE(array);
+       get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
+
+       switch (etype) {
+               case FLOAT4OID:
+               case FLOAT8OID:
+                       break;
+               default:
+                       elog(ERROR, "RASTER_setPixelValuesArray: Invalid data type for new values");
+                       rt_raster_destroy(raster);
+                       PG_FREE_IF_COPY(pgraster, 0);
+                       PG_RETURN_NULL();
+                       break;
+       }
+
+       ndims = ARR_NDIM(array);
+       dims = ARR_DIMS(array);
+       lbs = ARR_LBOUND(array);
+       POSTGIS_RT_DEBUGF(4, "ndims = %d", ndims);
+
+       if (ndims != 2) {
+               elog(ERROR, "RASTER_setPixelValuesArray: Array for new values must be of 2 dimensions");
+               rt_raster_destroy(raster);
+               PG_RETURN_POINTER(pgraster);
+       }
+       POSTGIS_RT_DEBUGF(4, "dims = (%d, %d)", dims[0], dims[1]);
+
+       /* HOW DO I HANDLE MULTIDIMENSIONAL ARRAYS???? */
+       {
+               Datum *elements;
+               bool *nulls;
+               int num;
+
+               deconstruct_array(
+                       array,
+                       etype,
+                       typlen, typbyval, typalign,
+                       &elements, &nulls, &num
+               );
+
+               POSTGIS_RT_DEBUGF(4, "num = %d", num);
+       }
+
+
+       PG_RETURN_NULL();
+}
+
 /**
  * Return the geographical shape of all pixels
  */
index 3076c62b6e6a60a62aed0c0fd124dc5e77562d12..9c64792522f663354961435cf8fd46aebd273827 100644 (file)
@@ -2867,6 +2867,10 @@ CREATE OR REPLACE FUNCTION st_setbandisnodata(rast raster, band integer DEFAULT
 -- Raster Pixel Editors
 -----------------------------------------------------------------------
 
+-----------------------------------------------------------------------
+-- ST_SetValue (set one or more pixels to a single value)
+-----------------------------------------------------------------------
+
 -- This function can not be STRICT, because newvalue can be NULL for nodata
 CREATE OR REPLACE FUNCTION st_setvalue(rast raster, band integer, x integer, y integer, newvalue float8)
     RETURNS raster
@@ -2909,6 +2913,31 @@ CREATE OR REPLACE FUNCTION st_setvalue(rast raster, pt geometry, newvalue float8
     AS $$ SELECT st_setvalue($1, 1, $2, $3) $$
     LANGUAGE 'sql';
 
+-----------------------------------------------------------------------
+-- ST_SetValues (set one or more pixels to a one or more values)
+-----------------------------------------------------------------------
+CREATE OR REPLACE FUNCTION st_setvalues(
+       rast raster,
+       nband integer,
+       x integer, y integer,
+       newvalueset double precision[][],
+       noset boolean[][] DEFAULT NULL
+)
+       RETURNS raster
+       AS 'MODULE_PATHNAME', 'RASTER_setPixelValuesArray'
+       LANGUAGE 'c' IMMUTABLE;
+
+CREATE OR REPLACE FUNCTION st_setvalues(
+       rast raster,
+       nband integer,
+       x integer, y integer,
+       newvalueset double precision[],
+       noset boolean[] DEFAULT NULL
+)
+       RETURNS raster
+       AS $$ SELECT st_setvalues($1, $2, $3, $4, ARRAY[$5]::double precision[][], ARRAY[$6]::boolean[][]) $$
+       LANGUAGE 'sql' IMMUTABLE;
+
 -----------------------------------------------------------------------
 -- Raster Processing Functions
 -----------------------------------------------------------------------