From: Bborie Park Date: Wed, 19 Sep 2012 18:48:24 +0000 (+0000) Subject: Tweaked ST_Neighborhood() to use two separate distance parameters for X X-Git-Tag: 2.1.0beta2~636 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c800930a2b329a26103db02698025e0a62e31d65;p=postgis Tweaked ST_Neighborhood() to use two separate distance parameters for X and Y axes. git-svn-id: http://svn.osgeo.org/postgis/trunk@10304 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/doc/reference_raster.xml b/doc/reference_raster.xml index 927622e1a..f78e9dcb2 100644 --- a/doc/reference_raster.xml +++ b/doc/reference_raster.xml @@ -3739,7 +3739,7 @@ FROM ( ST_Neighborhood - Returns a 2-D double precision array of the non-NODATA values around a given band's pixel specified by either a columnx and rowy or a geometric point expressed in the same spatial reference coordinate system as the raster. + Returns a 2-D double precision array of the non-NODATA values around a given band's pixel specified by either a columnX and rowY or a geometric point expressed in the same spatial reference coordinate system as the raster. @@ -3749,18 +3749,20 @@ FROM ( double precision[][] ST_Neighborhood raster rast integer bandnum - integer columnx - integer rowy - integer distance + integer columnX + integer rowY + integer distanceX + integer distanceY boolean exclude_nodata_value=true double precision[][] ST_Neighborhood raster rast - integer columnx - integer rowy - integer distance + integer columnX + integer rowY + integer distanceX + integer distanceY boolean exclude_nodata_value=true @@ -3769,7 +3771,8 @@ FROM ( raster rast integer bandnum geometry pt - integer distance + integer distanceX + integer distanceY boolean exclude_nodata_value=true @@ -3777,7 +3780,8 @@ FROM ( double precision[][] ST_Neighborhood raster rast geometry pt - integer distance + integer distanceX + integer distanceY boolean exclude_nodata_value=true @@ -3786,14 +3790,14 @@ FROM ( Description - Returns a 2-D double precision array of the non-NODATA values around a given band's pixel specified by either a columnx and rowy or a geometric point expressed in the same spatial reference coordinate system as the raster. The distance parameter defines the number of pixels around the specified pixel, e.g. I want all values within 3 pixel distance around my pixel of interest. The center value of the 2-D array will be the value at the pixel specified by the columnx and rowy or the geometric point. + Returns a 2-D double precision array of the non-NODATA values around a given band's pixel specified by either a columnX and rowY or a geometric point expressed in the same spatial reference coordinate system as the raster. The distanceX and distanceY parameters define the number of pixels around the specified pixel in the X and Y axes, e.g. I want all values within 3 pixel distance along the X axis and 2 pixel distance along the Y axis around my pixel of interest. The center value of the 2-D array will be the value at the pixel specified by the columnX and rowY or the geometric point. Band numbers start at 1 and bandnum is assumed to be 1 if not specified. If exclude_nodata_value is set to false, then all pixels include nodata pixels are considered to intersect and return value. If exclude_nodata_value is not passed in then reads it from metadata of raster. - The number of elements along each axis of the returning 2-D array is 2 * distance + 1. So for a distance of 1, the returning array will be 3x3. + The number of elements along each axis of the returning 2-D array is 2 * (distanceX|distanceY) + 1. So for a distanceX and distanceY of 1, the returning array will be 3x3. @@ -3809,27 +3813,22 @@ FROM ( -- pixel 2x2 has value SELECT - ST_Neighborhood(rast, 2, 2, 1) + ST_Neighborhood(rast, 2, 2, 1, 1) FROM ( SELECT - ST_SetValue( - ST_SetValue( - ST_SetValue( - ST_SetValue( - ST_SetValue( - ST_AddBand( - ST_MakeEmptyRaster(5, 5, -2, 2, 1, -1, 0, 0, 0), - '8BUI'::text, 1, 0 - ), - 1, 1, 0. - ), - 2, 3, 0. - ), - 3, 5, 0. - ), - 4, 2, 0. + ST_SetValues( + ST_AddBand( + ST_MakeEmptyRaster(5, 5, -2, 2, 1, -1, 0, 0, 0), + '8BUI'::text, 1, 0 ), - 5, 4, 0. + 1, 1, 1, ARRAY[ + [0, 1, 1, 1, 1], + [1, 1, 1, 0, 1], + [1, 0, 1, 1, 1], + [1, 1, 1, 1, 0], + [1, 1, 0, 1, 1] + ]::double precision[], + 1 ) AS rast ) AS foo @@ -3841,27 +3840,22 @@ FROM ( -- pixel 2x3 is NODATA SELECT - ST_Neighborhood(rast, 2, 3, 1) + ST_Neighborhood(rast, 2, 3, 1, 1) FROM ( SELECT - ST_SetValue( - ST_SetValue( - ST_SetValue( - ST_SetValue( - ST_SetValue( - ST_AddBand( - ST_MakeEmptyRaster(5, 5, -2, 2, 1, -1, 0, 0, 0), - '8BUI'::text, 1, 0 - ), - 1, 1, 0. - ), - 2, 3, 0. - ), - 3, 5, 0. - ), - 4, 2, 0. + ST_SetValues( + ST_AddBand( + ST_MakeEmptyRaster(5, 5, -2, 2, 1, -1, 0, 0, 0), + '8BUI'::text, 1, 0 ), - 5, 4, 0. + 1, 1, 1, ARRAY[ + [0, 1, 1, 1, 1], + [1, 1, 1, 0, 1], + [1, 0, 1, 1, 1], + [1, 1, 1, 1, 0], + [1, 1, 0, 1, 1] + ]::double precision[], + 1 ) AS rast ) AS foo @@ -3874,27 +3868,21 @@ FROM ( -- pixel 3x3 has value -- exclude_nodata_value = FALSE SELECT - ST_Neighborhood(rast, 3, 3, 1, false) + ST_Neighborhood(rast, 3, 3, 1, 1, false) FROM ( - SELECT - ST_SetValue( - ST_SetValue( - ST_SetValue( - ST_SetValue( - ST_SetValue( - ST_AddBand( - ST_MakeEmptyRaster(5, 5, -2, 2, 1, -1, 0, 0, 0), - '8BUI'::text, 1, 0 - ), - 1, 1, 0. - ), - 2, 3, 0. - ), - 3, 5, 0. - ), - 4, 2, 0. + ST_SetValues( + ST_AddBand( + ST_MakeEmptyRaster(5, 5, -2, 2, 1, -1, 0, 0, 0), + '8BUI'::text, 1, 0 ), - 5, 4, 0. + 1, 1, 1, ARRAY[ + [0, 1, 1, 1, 1], + [1, 1, 1, 0, 1], + [1, 0, 1, 1, 1], + [1, 1, 1, 1, 0], + [1, 1, 0, 1, 1] + ]::double precision[], + 1 ) AS rast ) AS foo diff --git a/raster/rt_core/rt_api.c b/raster/rt_core/rt_api.c index f8f32a74e..236eaaaf8 100644 --- a/raster/rt_core/rt_api.c +++ b/raster/rt_core/rt_api.c @@ -1157,22 +1157,28 @@ int rt_pixtype_compare_clamped_values(rt_pixtype pixtype, double val, double ref * @param count: number of elements in npixel * @param x: the column of the center pixel (0-based) * @param y: the line of the center pixel (0-based) - * @param distance: the number of pixels around the center pixel + * @param distancex: the number of pixels around the specified pixel + * along the X axis + * @param distancey: the number of pixels around the specified pixel + * along the Y axis * @param value: pointer to pointer for 2D value array * @param nodata: pointer to pointer for 2D NODATA array + * @param dimx: size of value and nodata along the X axis + * @param dimy: size of value and nodata along the Y axis * - * @return 0 on error, otherwise the X/Y axis length of value and NODATA + * @return 0 on error, otherwise 1 */ int rt_pixel_set_to_array( rt_pixel npixel, int count, int x, int y, - uint16_t distance, + uint16_t distancex, uint16_t distancey, double ***value, - int ***nodata + int ***nodata, + int *dimx, int *dimy ) { uint32_t i; uint32_t j; - uint32_t length = 0; + uint32_t dim[2] = {0}; double **values = NULL; int **nodatas = NULL; int zero[2] = {0}; @@ -1182,23 +1188,24 @@ int rt_pixel_set_to_array( assert(npixel != NULL); assert(count > 0); - /* length */ - length = distance * 2 + 1; - RASTER_DEBUGF(4, "length = %d", length); + /* dimensions */ + dim[0] = distancex * 2 + 1; + dim[1] = distancey * 2 + 1; + RASTER_DEBUGF(4, "dimensions = %d x %d", dim[0], dim[1]); - /* establish 2D arrays */ - values = rtalloc(sizeof(double *) * length); - nodatas = rtalloc(sizeof(int *) * length); + /* establish 2D arrays (X axis) */ + values = rtalloc(sizeof(double *) * dim[0]); + nodatas = rtalloc(sizeof(int *) * dim[0]); if (values == NULL || nodatas == NULL) { rterror("rt_pixel_set_to_array: Unable to allocate memory for 2D array"); return 0; } - /* initialize */ - for (i = 0; i < length; i++) { - values[i] = rtalloc(sizeof(double) * length); - nodatas[i] = rtalloc(sizeof(int) * length); + /* initialize Y axis */ + for (i = 0; i < dim[0]; i++) { + values[i] = rtalloc(sizeof(double) * dim[1]); + nodatas[i] = rtalloc(sizeof(int) * dim[1]); if (values[i] == NULL || nodatas[i] == NULL) { rterror("rt_pixel_set_to_array: Unable to allocate memory for dimension of 2D array"); @@ -1224,16 +1231,16 @@ int rt_pixel_set_to_array( } /* set values to 0 */ - memset(values[i], 0, sizeof(double) * length); + memset(values[i], 0, sizeof(double) * dim[1]); /* set nodatas to 1 */ - for (j = 0; j < length; j++) + for (j = 0; j < dim[1]; j++) nodatas[i][j] = 1; } /* get zero, zero of grid */ - zero[0] = x - distance; - zero[1] = y - distance; + zero[0] = x - distancex; + zero[1] = y - distancey; /* populate 2D arrays */ for (i = 0; i < count; i++) { @@ -1254,8 +1261,10 @@ int rt_pixel_set_to_array( *value = &(*values); *nodata = &(*nodatas); + *dimx = dim[0]; + *dimy = dim[1]; - return length; + return 1; } /*- rt_band ----------------------------------------------------------*/ @@ -2343,7 +2352,10 @@ rt_band_get_pixel( * @param band: the band to get nearest pixel(s) from * @param x: the column of the pixel (0-based) * @param y: the line of the pixel (0-based) - * @param distance: the number of pixels around the specified pixel + * @param distancex: the number of pixels around the specified pixel + * along the X axis + * @param distancey: the number of pixels around the specified pixel + * along the Y axis * @param exclude_nodata_value: if non-zero, ignore nodata values * to check for pixels with value * @param npixels: return set of rt_pixel object or NULL @@ -2354,21 +2366,23 @@ rt_band_get_pixel( int rt_band_get_nearest_pixel( rt_band band, int x, int y, - uint16_t distance, + uint16_t distancex, uint16_t distancey, int exclude_nodata_value, rt_pixel *npixels ) { rt_pixel npixel = NULL; int extent[4] = {0}; + int max_extent[4] = {0}; int d0 = 0; - uint32_t _distance; + int distance[2] = {0}; + uint32_t _d[2] = {0}; uint32_t i = 0; uint32_t j = 0; uint32_t k = 0; - uint32_t max = 0; + uint32_t _max = 0; int _x = 0; int _y = 0; - int *_inc = NULL; + int *_min = NULL; double pixval = 0; double minval = 0; uint32_t count = 0; @@ -2378,15 +2392,21 @@ int rt_band_get_nearest_pixel( RASTER_DEBUG(3, "Starting"); - minval = rt_pixtype_get_min_value(band->pixtype); - RASTER_DEBUGF(4, "pixtype: %s", rt_pixtype_name(band->pixtype)); - RASTER_DEBUGF(4, "minval: %f", minval); + /* process distance */ + distance[0] = distancex; + distance[1] = distancey; - if (!distance) + /* no distance */ + if (!distance[0] && !distance[1]) d0 = 1; + /* distance for X or Y is missing */ + else if (!distance[0] || !distance[1]) { + rterror("rt_band_get_nearest_pixel: distancex and distancey must both be zero if one is zero"); + return 0; + } RASTER_DEBUGF(4, "Selected pixel: %d x %d", x, y); - RASTER_DEBUGF(4, "Distance: %d", distance); + RASTER_DEBUGF(4, "Distances: %d x %d", distance[0], distance[1]); /* shortcuts if outside band extent */ if ( @@ -2395,8 +2415,8 @@ int rt_band_get_nearest_pixel( (y < 0 || y > band->height) ) ) { - /* no distance specified, jump to pixel close to extent */ - if (!distance) { + /* no distances specified, jump to pixel close to extent */ + if (d0) { if (x < 0) x = -1; else if (x > band->width) @@ -2410,14 +2430,14 @@ int rt_band_get_nearest_pixel( RASTER_DEBUGF(4, "Moved selected pixel: %d x %d", x, y); } /* - distance specified - if distance won't capture extent of band, return 0 + distances specified + if distances won't capture extent of band, return 0 */ else if ( - ((x < 0 && abs(x) > distance) || (x - band->width >= distance)) || - ((x < 0 && abs(y) > distance) || (y - band->height >= distance)) + ((x < 0 && abs(x) > distance[0]) || (x - band->width >= distance[0])) || + ((y < 0 && abs(y) > distance[1]) || (y - band->height >= distance[1])) ) { - RASTER_DEBUG(4, "No nearest pixels possible for provided pixel and distance"); + RASTER_DEBUG(4, "No nearest pixels possible for provided pixel and distances"); return 0; } } @@ -2427,37 +2447,56 @@ int rt_band_get_nearest_pixel( exclude_nodata_value = FALSE; /* determine the maximum distance to prevent an infinite loop */ - if (!distance) { + if (d0) { int a, b; + + /* X axis */ a = abs(x); b = abs(x - band->width); if (a > b) - distance = a; + distance[0] = a; else - distance = b; + distance[0] = b; + /* Y axis */ a = abs(y); b = abs(y - band->height); - if (a > distance) - distance = a; - if (b > distance) - distance = b; + if (a > b) + distance[1] = a; + else + distance[1] = b; - RASTER_DEBUGF(4, "Maximum distance: %d", distance); + RASTER_DEBUGF(4, "Maximum distances: %d x %d", distance[0], distance[1]); } + /* minimum possible value for pixel type */ + minval = rt_pixtype_get_min_value(band->pixtype); + RASTER_DEBUGF(4, "pixtype: %s", rt_pixtype_name(band->pixtype)); + RASTER_DEBUGF(4, "minval: %f", minval); + + /* set variables */ count = 0; - _distance = 0; *npixels = NULL; + + /* maximum extent */ + max_extent[0] = x - distance[0]; /* min X */ + max_extent[1] = y - distance[1]; /* min Y */ + max_extent[2] = x + distance[0]; /* max X */ + max_extent[3] = y + distance[1]; /* max Y */ + + _d[0] = 0; + _d[1] = 0; do { - _distance++; - extent[0] = x - _distance; /* min x */ - extent[1] = y - _distance; /* min y */ - extent[2] = x + _distance; /* max x */ - extent[3] = y + _distance; /* max y */ + _d[0]++; + _d[1]++; + + extent[0] = x - _d[0]; /* min x */ + extent[1] = y - _d[1]; /* min y */ + extent[2] = x + _d[0]; /* max x */ + extent[3] = y + _d[1]; /* max y */ - RASTER_DEBUGF(4, "Processing distance: %d", _distance); + RASTER_DEBUGF(4, "Processing distances: %d x %d", _d[0], _d[1]); RASTER_DEBUGF(4, "Extent: (%d, %d, %d, %d)", extent[0], extent[1], extent[2], extent[3]); @@ -2465,17 +2504,17 @@ int rt_band_get_nearest_pixel( /* by row */ if (i < 1) - max = extent[2] - extent[0] + 1; + _max = extent[2] - extent[0] + 1; /* by column */ else - max = extent[3] - extent[1] + 1; - max = abs(max); + _max = extent[3] - extent[1] + 1; + _max = abs(_max); for (j = 0; j < 2; j++) { /* by row */ if (i < 1) { _x = extent[0]; - _inc = &_x; + _min = &_x; /* top row */ if (j < 1) @@ -2487,20 +2526,28 @@ int rt_band_get_nearest_pixel( /* by column */ else { _y = extent[1] + 1; - _inc = &_y; + _min = &_y; /* left column */ if (j < 1) { _x = extent[0]; - max -= 2; + _max -= 2; } /* right column */ else _x = extent[2]; } - RASTER_DEBUGF(4, "max: %d", max); - for (k = 0; k < max; k++) { + RASTER_DEBUGF(4, "_min, _max: %d, %d", _min, _max); + for (k = 0; k < _max; k++) { + /* check that _x and _y are not outside max extent */ + if ( + _x < max_extent[0] || _x > max_extent[2] || + _y < max_extent[1] || _y > max_extent[3] + ) { + continue; + } + /* outside band extent, set to NODATA */ if ( (_x < 0 || _x >= band->width) || @@ -2557,13 +2604,13 @@ int rt_band_get_nearest_pixel( npixel->value = pixval; } - (*_inc)++; + (*_min)++; } } } - /* distance threshhold met */ - if (_distance >= distance) + /* distance threshholds met */ + if (_d[0] >= distance[0] && _d[1] >= distance[1]) break; else if (d0 && count) break; diff --git a/raster/rt_core/rt_api.h b/raster/rt_core/rt_api.h index c79f791f9..9911278b2 100644 --- a/raster/rt_core/rt_api.h +++ b/raster/rt_core/rt_api.h @@ -345,18 +345,24 @@ int rt_pixtype_compare_clamped_values(rt_pixtype pixtype, double val, double ref * @param count: number of elements in npixel * @param x: the column of the center pixel (0-based) * @param y: the line of the center pixel (0-based) - * @param distance: the number of pixels around the center pixel + * @param distancex: the number of pixels around the specified pixel + * along the X axis + * @param distancey: the number of pixels around the specified pixel + * along the Y axis * @param value: pointer to pointer for 2D value array * @param nodata: pointer to pointer for 2D NODATA array + * @param dimx: size of value and nodata along the X axis + * @param dimy: size of value and nodata along the Y axis * - * @return 0 on error, otherwise the X/Y axis length of value and NODATA + * @return 0 on error, otherwise 1 */ int rt_pixel_set_to_array( rt_pixel npixel, int count, int x, int y, - uint16_t distance, + uint16_t distancex, uint16_t distancey, double ***value, - int ***nodata + int ***nodata, + int *dimx, int *dimy ); /*- rt_band ----------------------------------------------------------*/ @@ -600,7 +606,10 @@ int rt_band_get_pixel( * @param band: the band to get nearest pixel(s) from * @param x: the column of the pixel (0-based) * @param y: the line of the pixel (0-based) - * @param distance: the number of pixels around the specified pixel + * @param distancex: the number of pixels around the specified pixel + * along the X axis + * @param distancey: the number of pixels around the specified pixel + * along the Y axis * @param exclude_nodata_value: if non-zero, ignore nodata values * to check for pixels with value * @param npixels: return set of rt_pixel object or NULL @@ -611,7 +620,7 @@ int rt_band_get_pixel( int rt_band_get_nearest_pixel( rt_band band, int x, int y, - uint16_t distance, + uint16_t distancex, uint16_t distancey, int exclude_nodata_value, rt_pixel *npixels ); diff --git a/raster/rt_pg/rt_pg.c b/raster/rt_pg/rt_pg.c index 47a055bba..1e92c9d80 100644 --- a/raster/rt_pg/rt_pg.c +++ b/raster/rt_pg/rt_pg.c @@ -3677,7 +3677,7 @@ Datum RASTER_nearestValue(PG_FUNCTION_ARGS) count = rt_band_get_nearest_pixel( band, x, y, - 0, + 0, 0, exclude_nodata_value, &npixels ); @@ -3760,13 +3760,12 @@ Datum RASTER_neighborhood(PG_FUNCTION_ARGS) int y = 0; int _x = 0; int _y = 0; - int distance = 0; + int distance[2] = {0}; bool exclude_nodata_value = TRUE; double pixval; rt_pixel npixels = NULL; int count; - int length; double **value2D = NULL; int **nodata2D = NULL; @@ -3814,19 +3813,29 @@ Datum RASTER_neighborhood(PG_FUNCTION_ARGS) y = PG_GETARG_INT32(3); _y = y - 1; - /* distance */ - distance = PG_GETARG_INT32(4); - if (distance < 1) { - elog(NOTICE, "Invalid value for distance (must be greater than zero). Returning NULL"); + /* distance X axis */ + distance[0] = PG_GETARG_INT32(4); + if (distance[0] < 1) { + elog(NOTICE, "Invalid value for distancex (must be greater than zero). Returning NULL"); rt_raster_destroy(raster); PG_FREE_IF_COPY(pgraster, 0); PG_RETURN_NULL(); } - distance = (uint16_t) distance; + distance[0] = (uint16_t) distance[0]; + + /* distance Y axis */ + distance[1] = PG_GETARG_INT32(5); + if (distance[1] < 1) { + elog(NOTICE, "Invalid value for distancey (must be greater than zero). Returning NULL"); + rt_raster_destroy(raster); + PG_FREE_IF_COPY(pgraster, 0); + PG_RETURN_NULL(); + } + distance[1] = (uint16_t) distance[1]; /* exclude_nodata_value flag */ - if (!PG_ARGISNULL(5)) - exclude_nodata_value = PG_GETARG_BOOL(5); + if (!PG_ARGISNULL(6)) + exclude_nodata_value = PG_GETARG_BOOL(6); /* get band */ band = rt_raster_get_band(raster, bandindex - 1); @@ -3841,7 +3850,7 @@ Datum RASTER_neighborhood(PG_FUNCTION_ARGS) count = rt_band_get_nearest_pixel( band, _x, _y, - distance, + distance[0], distance[1], exclude_nodata_value, &npixels ); @@ -3852,7 +3861,7 @@ Datum RASTER_neighborhood(PG_FUNCTION_ARGS) elog(NOTICE, "Unable to get the pixel's neighborhood for band at index %d", bandindex); /* no neighbors */ else - elog(NOTICE, "Pixel has no neighbors for band at distance %d", distance); + elog(NOTICE, "Pixel has no neighbors for band at distance %d x %d", distance[0], distance[1]); rt_band_destroy(band); rt_raster_destroy(raster); @@ -3924,31 +3933,28 @@ Datum RASTER_neighborhood(PG_FUNCTION_ARGS) PG_FREE_IF_COPY(pgraster, 0); /* convert set of rt_pixel to 2D array */ - length = rt_pixel_set_to_array( + count = rt_pixel_set_to_array( npixels, count, _x, _y, - distance, + distance[0], distance[1], &value2D, - &nodata2D + &nodata2D, + &(dim[0]), &(dim[1]) ); pfree(npixels); - if (!length) { + if (!count) { elog(NOTICE, "Unable to create 2D array of neighborhood"); PG_RETURN_NULL(); } - /* dimensions of the PG array */ - dim[0] = length; - dim[1] = length; - /* 1D arrays for values and nodata from 2D arrays */ - value1D = palloc(sizeof(Datum) * length * length); - nodata1D = palloc(sizeof(bool) * length * length); + value1D = palloc(sizeof(Datum) * dim[0] * dim[1]); + nodata1D = palloc(sizeof(bool) * dim[0] * dim[1]); if (value1D == NULL || nodata1D == NULL) { elog(ERROR, "RASTER_neighborhood: Unable to allocate memory for return 2D array"); - for (i = 0; i < length; i++) { + for (i = 0; i < dim[0]; i++) { pfree(value2D[i]); pfree(nodata2D[i]); } @@ -3960,8 +3966,8 @@ Datum RASTER_neighborhood(PG_FUNCTION_ARGS) /* copy values from 2D arrays to 1D arrays */ k = 0; - for (i = 0; i < length; i++) { - for (j = 0; j < length; j++) { + for (i = 0; i < dim[0]; i++) { + for (j = 0; j < dim[1]; j++) { nodata1D[k] = (bool) nodata2D[i][j]; if (!nodata1D[k]) value1D[k] = Float8GetDatum(value2D[i][j]); @@ -3973,7 +3979,7 @@ Datum RASTER_neighborhood(PG_FUNCTION_ARGS) } /* no more need for 2D arrays */ - for (i = 0; i < length; i++) { + for (i = 0; i < dim[0]; i++) { pfree(value2D[i]); pfree(nodata2D[i]); } diff --git a/raster/rt_pg/rtpostgis.sql.in.c b/raster/rt_pg/rtpostgis.sql.in.c index 9b9c0f4bc..43b89e0da 100644 --- a/raster/rt_pg/rtpostgis.sql.in.c +++ b/raster/rt_pg/rtpostgis.sql.in.c @@ -4670,30 +4670,40 @@ CREATE OR REPLACE FUNCTION st_nearestvalue( -- ST_Neighborhood ----------------------------------------------------------------------- -CREATE OR REPLACE FUNCTION st_neighborhood( +CREATE OR REPLACE FUNCTION _st_neighborhood( rast raster, band integer, columnx integer, rowy integer, - distance integer, + distancex integer, distancey integer, exclude_nodata_value boolean DEFAULT TRUE ) RETURNS double precision[][] AS 'MODULE_PATHNAME', 'RASTER_neighborhood' LANGUAGE 'c' IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION st_neighborhood( + rast raster, band integer, + columnx integer, rowy integer, + distancex integer, distancey integer, + exclude_nodata_value boolean DEFAULT TRUE +) + RETURNS double precision[][] + AS $$ SELECT _st_neighborhood($1, $2, $3, $4, $5, $6, $7) $$ + LANGUAGE 'sql' IMMUTABLE STRICT; + CREATE OR REPLACE FUNCTION st_neighborhood( rast raster, columnx integer, rowy integer, - distance integer, + distancex integer, distancey integer, exclude_nodata_value boolean DEFAULT TRUE ) RETURNS double precision[][] - AS $$ SELECT st_neighborhood($1, 1, $2, $3, $4, $5) $$ + AS $$ SELECT _st_neighborhood($1, 1, $2, $3, $4, $5, $6) $$ LANGUAGE 'sql' IMMUTABLE STRICT; CREATE OR REPLACE FUNCTION st_neighborhood( rast raster, band integer, pt geometry, - distance integer, + distancex integer, distancey integer, exclude_nodata_value boolean DEFAULT TRUE ) RETURNS double precision[][] @@ -4709,12 +4719,12 @@ CREATE OR REPLACE FUNCTION st_neighborhood( wx := st_x($3); wy := st_y($3); - SELECT st_neighborhood( + SELECT _st_neighborhood( $1, $2, st_world2rastercoordx(rast, wx, wy), st_world2rastercoordy(rast, wx, wy), - $4, - $5 + $4, $5, + $6 ) INTO rtn; RETURN rtn; END; @@ -4723,11 +4733,11 @@ CREATE OR REPLACE FUNCTION st_neighborhood( CREATE OR REPLACE FUNCTION st_neighborhood( rast raster, pt geometry, - distance integer, + distancex integer, distancey integer, exclude_nodata_value boolean DEFAULT TRUE ) RETURNS double precision[][] - AS $$ SELECT st_neighborhood($1, 1, $2, $3, $4) $$ + AS $$ SELECT st_neighborhood($1, 1, $2, $3, $4, $5) $$ LANGUAGE 'sql' IMMUTABLE STRICT; ------------------------------------------------------------------------------ diff --git a/raster/test/core/testapi.c b/raster/test/core/testapi.c index ee31e925f..d46c31f21 100644 --- a/raster/test/core/testapi.c +++ b/raster/test/core/testapi.c @@ -6815,9 +6815,10 @@ static void testNearestPixel() { const int maxY = 10; rt_pixel npixels = NULL; - int length; double **value; int **nodata; + int dimx; + int dimy; rast = rt_raster_new(maxX, maxY); assert(rast); @@ -6854,7 +6855,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, 0, 0, - 0, + 0, 0, 1, &npixels ); @@ -6866,7 +6867,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, 1, 1, - 0, + 0, 0, 1, &npixels ); @@ -6878,7 +6879,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, 4, 4, - 0, + 0, 0, 1, &npixels ); @@ -6890,7 +6891,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, 4, 4, - 2, + 2, 2, 1, &npixels ); @@ -6902,7 +6903,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, 10, 10, - 0, + 0, 0, 1, &npixels ); @@ -6914,7 +6915,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, 11, 11, - 1, + 1, 1, 1, &npixels ); @@ -6926,7 +6927,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, -1, -1, - 0, + 0, 0, 1, &npixels ); @@ -6938,7 +6939,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, -1, -1, - 1, + 1, 1, 1, &npixels ); @@ -6950,22 +6951,25 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, -1, 1, - 1, + 1, 1, 1, &npixels ); CHECK((rtn == 2)); - length = rt_pixel_set_to_array( + rtn = rt_pixel_set_to_array( npixels, rtn, -1, 1, - 1, + 1, 1, &value, - &nodata + &nodata, + &dimx, &dimy ); - CHECK((length == 3)); + CHECK((rtn != 0)); + CHECK((dimx == 3)); + CHECK((dimy == 3)); - for (x = 0; x < length; x++) { + for (x = 0; x < dimx; x++) { rtdealloc(nodata[x]); rtdealloc(value[x]); } @@ -6980,7 +6984,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, -2, 2, - 1, + 1, 1, 1, &npixels ); @@ -6992,7 +6996,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, -10, 2, - 3, + 3, 3, 1, &npixels ); @@ -7004,7 +7008,7 @@ static void testNearestPixel() { rtn = rt_band_get_nearest_pixel( band, -10, 2, - 3, + 3, 3, 0, &npixels ); @@ -7012,6 +7016,18 @@ static void testNearestPixel() { if (rtn) rtdealloc(npixels); + /* 4,4 distance 3,2 */ + rtn = rt_band_get_nearest_pixel( + band, + 4, 4, + 3, 2, + 1, + &npixels + ); + CHECK((rtn == 27)); + if (rtn) + rtdealloc(npixels); + deepRelease(rast); } diff --git a/raster/test/regress/rt_neighborhood.sql b/raster/test/regress/rt_neighborhood.sql index 22a3adcad..7d61eba54 100644 --- a/raster/test/regress/rt_neighborhood.sql +++ b/raster/test/regress/rt_neighborhood.sql @@ -38,40 +38,40 @@ SELECT make_test_raster(); DROP FUNCTION IF EXISTS make_test_raster(); SELECT - ST_Neighborhood(rast, 1, 1, 1, 1) + ST_Neighborhood(rast, 1, 1, 1, 1, 1) FROM raster_neighborhood; SELECT - ST_Neighborhood(ST_SetBandNoDataValue(rast, NULL), 1, 1, 1, 1) + ST_Neighborhood(ST_SetBandNoDataValue(rast, NULL), 1, 1, 1, 1, 1) FROM raster_neighborhood; SELECT - ST_Neighborhood(rast, 1, 2, 2, 1) + ST_Neighborhood(rast, 1, 2, 2, 1, 1) FROM raster_neighborhood; SELECT - ST_Neighborhood(rast, 1, 5, 5, 1) + ST_Neighborhood(rast, 1, 5, 5, 1, 1) FROM raster_neighborhood; SELECT - ST_Neighborhood(rast, 1, 5, 5, 2) + ST_Neighborhood(rast, 1, 5, 5, 2, 2) FROM raster_neighborhood; SELECT - ST_Neighborhood(rast, 1, 11, 11, 1) + ST_Neighborhood(rast, 1, 11, 11, 1, 1) FROM raster_neighborhood; SELECT - ST_Neighborhood(rast, 1, 12, 12, 1) + ST_Neighborhood(rast, 1, 12, 12, 1, 1) FROM raster_neighborhood; SELECT - ST_Neighborhood(rast, 1, 0, 0, 1) + ST_Neighborhood(rast, 1, 0, 0, 1, 1) FROM raster_neighborhood; SELECT - ST_Neighborhood(rast, 1, 0, 2, 1) + ST_Neighborhood(rast, 1, 0, 2, 1, 1) FROM raster_neighborhood; SELECT - ST_Neighborhood(rast, 1, -1, 3, 1) + ST_Neighborhood(rast, 1, -1, 3, 1, 1) FROM raster_neighborhood; SELECT - ST_Neighborhood(rast, 1, -9, 3, 3) + ST_Neighborhood(rast, 1, -9, 3, 3, 3) FROM raster_neighborhood; SELECT - ST_Neighborhood(rast, 1, -9, 3, 3, FALSE) + ST_Neighborhood(rast, 1, -9, 3, 3, 3, FALSE) FROM raster_neighborhood; DROP TABLE IF EXISTS raster_neighborhood; diff --git a/raster/test/regress/rt_neighborhood_expected b/raster/test/regress/rt_neighborhood_expected index 7cfc37337..49789beec 100644 --- a/raster/test/regress/rt_neighborhood_expected +++ b/raster/test/regress/rt_neighborhood_expected @@ -5,9 +5,9 @@ NOTICE: table "raster_neighborhood" does not exist, skipping {{1,1,1},{1,1,1},{1,NULL,1}} {{1,1,NULL,1,1},{1,1,1,1,NULL},{NULL,1,1,1,1},{1,1,NULL,1,1},{1,1,1,1,NULL}} {{1,NULL,NULL},{NULL,NULL,NULL},{NULL,NULL,NULL}} -NOTICE: Pixel has no neighbors for band at distance 1 -NOTICE: Pixel has no neighbors for band at distance 1 +NOTICE: Pixel has no neighbors for band at distance 1 x 1 +NOTICE: Pixel has no neighbors for band at distance 1 x 1 {{NULL,NULL,NULL},{NULL,NULL,NULL},{NULL,1,1}} -NOTICE: Pixel has no neighbors for band at distance 1 -NOTICE: Pixel has no neighbors for band at distance 3 +NOTICE: Pixel has no neighbors for band at distance 1 x 1 +NOTICE: Pixel has no neighbors for band at distance 3 x 3 {{0,0,0,0,0,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0},{0,0,0,0,0,0,0}}