]> granicus.if.org Git - postgis/commitdiff
Added RANGE uniontype option for ST_Union(raster) Ticket #2097
authorBborie Park <bkpark at ucdavis.edu>
Fri, 16 Nov 2012 22:59:46 +0000 (22:59 +0000)
committerBborie Park <bkpark at ucdavis.edu>
Fri, 16 Nov 2012 22:59:46 +0000 (22:59 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@10696 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
doc/reference_raster.xml
raster/rt_pg/rt_pg.c
raster/test/regress/rt_union.sql
raster/test/regress/rt_union_expected

diff --git a/NEWS b/NEWS
index 01329e8316294bd781d892945ac74963641476f6..c88aab06b3d9289a5839bc3334a4b4bd5b101aaa 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -80,6 +80,7 @@ PostGIS 2.1.0
   - Additional default values for parameters of ST_Aspect and ST_HillShade
   - #2078, New variants of ST_Slope, ST_Aspect and ST_HillShade to provide
     solution to handling tiles in a coverage
+  - #2097, Added RANGE uniontype option for ST_Union(raster)
 
 * Fixes *
 
index a28d89c514a701977c7729ffc409041e0dad3d8c..39f5bf9101c1da0bb795a46cb54c0e582df46c65 100644 (file)
@@ -10114,7 +10114,7 @@ UPDATE wind
                        <refsection>
                                <title>Description</title>
                                
-                               <para>Returns the union of a set of raster tiles into a single raster composed of at least one band.  If <varname>nband</varname> is not specified, band 1 is assumed.  The resulting raster's extent is the extent of the whole set.  In the case of intersection, the resulting value is defined by <varname>uniontype</varname> which is one of the following: LAST (default), FIRST, MIN, MAX, COUNT, SUM, MEAN.</para>
+                               <para>Returns the union of a set of raster tiles into a single raster composed of at least one band.  If <varname>nband</varname> is not specified, band 1 is assumed.  The resulting raster's extent is the extent of the whole set.  In the case of intersection, the resulting value is defined by <varname>uniontype</varname> which is one of the following: LAST (default), FIRST, MIN, MAX, COUNT, SUM, MEAN, RANGE.</para>
 
                                <para>Availability: 2.0.0 </para>
                                <para>Enhanced: 2.1.0 Improved Speed (fully C-Based).</para>
index a41abc30c15eb7795f6ed9ebdbbf5a6825a63057..1a3204d7417be9da65cdd0638f1e15307a9f5040 100644 (file)
@@ -15624,7 +15624,8 @@ typedef enum {
        UT_MAX,
        UT_COUNT,
        UT_SUM,
-       UT_MEAN
+       UT_MEAN,
+       UT_RANGE
 } rtpg_union_type;
 
 /* internal function translating text of UNION type to enum */
@@ -15645,6 +15646,8 @@ static rtpg_union_type rtpg_uniontype_index_from_name(const char *cutype) {
                return UT_SUM;
        else if (strcmp(cutype, "MEAN") == 0)
                return UT_MEAN;
+       else if (strcmp(cutype, "RANGE") == 0)
+               return UT_RANGE;
 
        return UT_LAST;
 }
@@ -15765,6 +15768,7 @@ static int rtpg_union_callback(
                        *value = arg->values[0][0][0] + arg->values[1][0][0];
                        break;
                case UT_MEAN:
+               case UT_RANGE:
                        break;
                case UT_LAST:
                default:
@@ -15814,6 +15818,41 @@ static int rtpg_union_mean_callback(
        return 1;
 }
 
+static int rtpg_union_range_callback(
+       rt_iterator_arg arg, void *userarg,
+       double *value, int *nodata
+) {
+       if (arg == NULL)
+               return 0;
+
+       if (
+               arg->rasters != 2 ||
+               arg->rows != 1 ||
+               arg->columns != 1
+       ) {
+               elog(ERROR, "rtpg_union_range_callback: Invalid arguments passed to callback");
+               return 0;
+       }
+
+       *value = 0;
+       *nodata = 1;
+
+       POSTGIS_RT_DEBUGF(4, "rast0: %f %d", arg->values[0][0][0], arg->nodata[0][0][0]);
+       POSTGIS_RT_DEBUGF(4, "rast1: %f %d", arg->values[1][0][0], arg->nodata[1][0][0]);
+
+       if (
+               !arg->nodata[0][0][0] &&
+               !arg->nodata[1][0][0]
+       ) {
+               *value = arg->values[1][0][0] - arg->values[0][0][0];
+               *nodata = 0;
+       }
+
+       POSTGIS_RT_DEBUGF(4, "value, nodata = (%f, %d)", *value, *nodata);
+
+       return 1;
+}
+
 /* called for ST_Union(raster, unionarg[]) */
 static int rtpg_union_unionarg_process(rtpg_union_arg arg, ArrayType *array) {
        Oid etype;
@@ -15901,8 +15940,12 @@ static int rtpg_union_unionarg_process(rtpg_union_arg arg, ArrayType *array) {
                arg->bandarg[i].nband = nband - 1;
                arg->bandarg[i].raster = NULL;
 
-               if (utype != UT_MEAN)
+               if (
+                       utype != UT_MEAN &&
+                       utype != UT_RANGE
+               ) {
                        arg->bandarg[i].numraster = 1;
+               }
                else
                        arg->bandarg[i].numraster = 2;
        }
@@ -16085,8 +16128,12 @@ Datum RASTER_union_transfn(PG_FUNCTION_ARGS)
                                        iwr->bandarg[0].uniontype = utype;
                                        iwr->bandarg[0].nband = 0;
 
-                                       if (iwr->bandarg[0].uniontype == UT_MEAN)
+                                       if (
+                                               iwr->bandarg[0].uniontype == UT_MEAN ||
+                                               iwr->bandarg[0].uniontype == UT_RANGE
+                                       ) {
                                                iwr->bandarg[0].numraster = 2;
+                                       }
                                        else
                                                iwr->bandarg[0].numraster = 1;
                                        iwr->bandarg[0].raster = NULL;
@@ -16156,8 +16203,12 @@ Datum RASTER_union_transfn(PG_FUNCTION_ARGS)
                        utype = rtpg_uniontype_index_from_name(rtpg_strtoupper(utypename));
                        iwr->bandarg[0].uniontype = utype;
 
-                       if (utype == UT_MEAN)
+                       if (
+                               utype == UT_MEAN ||
+                               utype == UT_RANGE
+                       ) {
                                iwr->bandarg[0].numraster = 2;
+                       }
                }
 
                /* allocate space for pointers to rt_raster */
@@ -16248,7 +16299,8 @@ Datum RASTER_union_transfn(PG_FUNCTION_ARGS)
                                        nodataval = rt_band_get_min_value(_band);
                        }
 
-                       /* UT_MEAN requires two passes, first for UT_COUNT and second for UT_SUM */
+                       /* UT_MEAN and UT_RANGE require two passes */
+                       /* UT_MEAN: first for UT_COUNT and second for UT_SUM */
                        if (iwr->bandarg[i].uniontype == UT_MEAN) {
                                /* first pass, UT_COUNT */
                                if (j < 1)
@@ -16256,6 +16308,14 @@ Datum RASTER_union_transfn(PG_FUNCTION_ARGS)
                                else
                                        utype = UT_SUM;
                        }
+                       /* UT_RANGE: first for UT_MIN and second for UT_MAX */
+                       else if (iwr->bandarg[i].uniontype == UT_RANGE) {
+                               /* first pass, UT_MIN */
+                               if (j < 1)
+                                       utype = UT_MIN;
+                               else
+                                       utype = UT_MAX;
+                       }
 
                        /* force band settings for UT_COUNT */
                        if (utype == UT_COUNT) {
@@ -16372,8 +16432,11 @@ Datum RASTER_union_finalfn(PG_FUNCTION_ARGS)
        }
 
        for (i = 0; i < iwr->numband; i++) {
-               if (iwr->bandarg[i].uniontype == UT_MEAN) {
-                       /* raster containing the SUM is at index 1 */
+               if (
+                       iwr->bandarg[i].uniontype == UT_MEAN ||
+                       iwr->bandarg[i].uniontype == UT_RANGE
+               ) {
+                       /* raster containing the SUM or MAX is at index 1 */
                        _band = rt_raster_get_band(iwr->bandarg[i].raster[1], 0);
 
                        pixtype = rt_band_get_pixtype(_band);
@@ -16388,16 +16451,30 @@ Datum RASTER_union_finalfn(PG_FUNCTION_ARGS)
                        itrset[1].nband = 0;
 
                        /* pass everything to iterator */
-                       _raster = rt_raster_iterator(
-                               itrset, 2,
-                               ET_UNION, NULL,
-                               pixtype,
-                               hasnodata, nodataval,
-                               0, 0,
-                               NULL,
-                               rtpg_union_mean_callback,
-                               &noerr
-                       );
+                       if (iwr->bandarg[i].uniontype == UT_MEAN) {
+                               _raster = rt_raster_iterator(
+                                       itrset, 2,
+                                       ET_UNION, NULL,
+                                       pixtype,
+                                       hasnodata, nodataval,
+                                       0, 0,
+                                       NULL,
+                                       rtpg_union_mean_callback,
+                                       &noerr
+                               );
+                       }
+                       else if (iwr->bandarg[i].uniontype == UT_RANGE) {
+                               _raster = rt_raster_iterator(
+                                       itrset, 2,
+                                       ET_UNION, NULL,
+                                       pixtype,
+                                       hasnodata, nodataval,
+                                       0, 0,
+                                       NULL,
+                                       rtpg_union_range_callback,
+                                       &noerr
+                               );
+                       }
 
                        if (!noerr) {
                                elog(ERROR, "RASTER_union_finalfn: Unable to run raster iterator function");
@@ -16423,8 +16500,12 @@ Datum RASTER_union_finalfn(PG_FUNCTION_ARGS)
                POSTGIS_RT_DEBUG(4, "destroying source rasters");
 
                /* destroy source rasters */
-               if (iwr->bandarg[i].uniontype == UT_MEAN)
+               if (
+                       iwr->bandarg[i].uniontype == UT_MEAN ||
+                       iwr->bandarg[i].uniontype == UT_RANGE
+               ) {
                        rt_raster_destroy(_raster);
+               }
                        
                for (j = 0; j < iwr->bandarg[i].numraster; j++) {
                        if (iwr->bandarg[i].raster[j] == NULL)
index 339c81b6caf70f7c6a7c2a161d92c6fd2b079a6d..60846c652d4548378cf5b084ea3ef3404e808cda 100644 (file)
@@ -57,6 +57,12 @@ INSERT INTO raster_union_out
                ST_Union(rast, 'mean') AS rast
        FROM raster_union_in;
 
+INSERT INTO raster_union_out
+       SELECT
+               'RANGE',
+               ST_Union(rast, 'range') AS rast
+       FROM raster_union_in;
+
 SELECT
        uniontype,
        x,
@@ -129,6 +135,12 @@ INSERT INTO raster_union_out
                ST_Union(rast, 1, 'mean') AS rast
        FROM raster_union_in;
 
+INSERT INTO raster_union_out
+       SELECT
+               'RANGE',
+               ST_Union(rast, 1, 'RANGE') AS rast
+       FROM raster_union_in;
+
 SELECT
        uniontype,
        x,
@@ -192,6 +204,12 @@ INSERT INTO raster_union_out
                ST_Union(rast, 2, 'mean') AS rast
        FROM raster_union_in;
 
+INSERT INTO raster_union_out
+       SELECT
+               'RANGE',
+               ST_Union(rast, 2, 'RANGE') AS rast
+       FROM raster_union_in;
+
 SELECT
        uniontype,
        x,
@@ -284,6 +302,12 @@ INSERT INTO raster_union_out
                ST_Union(rast, ARRAY[ROW(1, 'MEAN'), ROW(2, 'MEAN')]::unionarg[]) AS rast
        FROM raster_union_in;
 
+INSERT INTO raster_union_out
+       SELECT
+               'RANGE',
+               ST_Union(rast, ARRAY[ROW(1, 'RANGE'), ROW(2, 'RANGE')]::unionarg[]) AS rast
+       FROM raster_union_in;
+
 SELECT
        uniontype,
        x,
index f9e06ef5a44fcf5b69cf6201ad30b070f02bb352..56b9eb5ddc57c1be4eff0b612dab4da5f50762f8 100644 (file)
@@ -54,6 +54,15 @@ MIN|3|2|2
 MIN|1|3|
 MIN|2|3|2
 MIN|3|3|2
+RANGE|1|1|
+RANGE|2|1|
+RANGE|3|1|
+RANGE|1|2|
+RANGE|2|2|1
+RANGE|3|2|
+RANGE|1|3|
+RANGE|2|3|
+RANGE|3|3|
 SUM|1|1|1
 SUM|2|1|1
 SUM|3|1|
@@ -279,6 +288,42 @@ MIN|3|6|1
 MIN|4|6|1
 MIN|5|6|1
 MIN|6|6|1
+RANGE|1|1|
+RANGE|2|1|
+RANGE|3|1|
+RANGE|4|1|
+RANGE|5|1|
+RANGE|6|1|
+RANGE|1|2|
+RANGE|2|2|
+RANGE|3|2|
+RANGE|4|2|
+RANGE|5|2|
+RANGE|6|2|
+RANGE|1|3|
+RANGE|2|3|
+RANGE|3|3|
+RANGE|4|3|
+RANGE|5|3|
+RANGE|6|3|
+RANGE|1|4|
+RANGE|2|4|
+RANGE|3|4|
+RANGE|4|4|
+RANGE|5|4|
+RANGE|6|4|
+RANGE|1|5|
+RANGE|2|5|
+RANGE|3|5|
+RANGE|4|5|
+RANGE|5|5|
+RANGE|6|5|
+RANGE|1|6|
+RANGE|2|6|
+RANGE|3|6|
+RANGE|4|6|
+RANGE|5|6|
+RANGE|6|6|
 SUM|1|1|1
 SUM|2|1|1
 SUM|3|1|1
@@ -369,6 +414,15 @@ MIN|3|2|2
 MIN|1|3|
 MIN|2|3|2
 MIN|3|3|2
+RANGE|1|1|0
+RANGE|2|1|0
+RANGE|3|1|
+RANGE|1|2|0
+RANGE|2|2|1
+RANGE|3|2|0
+RANGE|1|3|
+RANGE|2|3|0
+RANGE|3|3|0
 SUM|1|1|1
 SUM|2|1|1
 SUM|3|1|
@@ -441,6 +495,15 @@ MIN|3|2|2
 MIN|1|3|
 MIN|2|3|2
 MIN|3|3|2
+RANGE|1|1|
+RANGE|2|1|
+RANGE|3|1|
+RANGE|1|2|
+RANGE|2|2|1
+RANGE|3|2|
+RANGE|1|3|
+RANGE|2|3|
+RANGE|3|3|
 SUM|1|1|1
 SUM|2|1|1
 SUM|3|1|
@@ -504,6 +567,15 @@ MIN|3|2|200
 MIN|1|3|
 MIN|2|3|200
 MIN|3|3|200
+RANGE|1|1|0
+RANGE|2|1|0
+RANGE|3|1|
+RANGE|1|2|0
+RANGE|2|2|100
+RANGE|3|2|0
+RANGE|1|3|
+RANGE|2|3|0
+RANGE|3|3|0
 SUM|1|1|100
 SUM|2|1|100
 SUM|3|1|