From: Bborie Park Date: Fri, 16 Nov 2012 22:59:46 +0000 (+0000) Subject: Added RANGE uniontype option for ST_Union(raster) Ticket #2097 X-Git-Tag: 2.1.0beta2~386 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=faab58c46cb4711419dddc7594284b442905826a;p=postgis Added RANGE uniontype option for ST_Union(raster) Ticket #2097 git-svn-id: http://svn.osgeo.org/postgis/trunk@10696 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/NEWS b/NEWS index 01329e831..c88aab06b 100644 --- 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 * diff --git a/doc/reference_raster.xml b/doc/reference_raster.xml index a28d89c51..39f5bf910 100644 --- a/doc/reference_raster.xml +++ b/doc/reference_raster.xml @@ -10114,7 +10114,7 @@ UPDATE wind Description - Returns the union of a set of raster tiles into a single raster composed of at least one band. If nband 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 uniontype which is one of the following: LAST (default), FIRST, MIN, MAX, COUNT, SUM, MEAN. + Returns the union of a set of raster tiles into a single raster composed of at least one band. If nband 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 uniontype which is one of the following: LAST (default), FIRST, MIN, MAX, COUNT, SUM, MEAN, RANGE. Availability: 2.0.0 Enhanced: 2.1.0 Improved Speed (fully C-Based). diff --git a/raster/rt_pg/rt_pg.c b/raster/rt_pg/rt_pg.c index a41abc30c..1a3204d74 100644 --- a/raster/rt_pg/rt_pg.c +++ b/raster/rt_pg/rt_pg.c @@ -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) diff --git a/raster/test/regress/rt_union.sql b/raster/test/regress/rt_union.sql index 339c81b6c..60846c652 100644 --- a/raster/test/regress/rt_union.sql +++ b/raster/test/regress/rt_union.sql @@ -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, diff --git a/raster/test/regress/rt_union_expected b/raster/test/regress/rt_union_expected index f9e06ef5a..56b9eb5dd 100644 --- a/raster/test/regress/rt_union_expected +++ b/raster/test/regress/rt_union_expected @@ -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|