]> granicus.if.org Git - postgis/commitdiff
Tweaked ST_Neighborhood() to use two separate distance parameters for X
authorBborie Park <bkpark at ucdavis.edu>
Wed, 19 Sep 2012 18:48:24 +0000 (18:48 +0000)
committerBborie Park <bkpark at ucdavis.edu>
Wed, 19 Sep 2012 18:48:24 +0000 (18:48 +0000)
and Y axes.

git-svn-id: http://svn.osgeo.org/postgis/trunk@10304 b70326c6-7e19-0410-871a-916f4a2858ee

doc/reference_raster.xml
raster/rt_core/rt_api.c
raster/rt_core/rt_api.h
raster/rt_pg/rt_pg.c
raster/rt_pg/rtpostgis.sql.in.c
raster/test/core/testapi.c
raster/test/regress/rt_neighborhood.sql
raster/test/regress/rt_neighborhood_expected

index 927622e1a04f9e1dcd40943132ed7f2b92789471..f78e9dcb2f3b547a6f65167108db5d42177b3684 100644 (file)
@@ -3739,7 +3739,7 @@ FROM (
                        <refnamediv>
                                <refname>ST_Neighborhood</refname>
                                <refpurpose>
-                                       Returns a 2-D double precision array of the non-<varname>NODATA</varname> 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-<varname>NODATA</varname> 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.
                                </refpurpose>
                        </refnamediv>
 
@@ -3749,18 +3749,20 @@ FROM (
                                                <funcdef>double precision[][] <function>ST_Neighborhood</function></funcdef>
                                                <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
                                                <paramdef><type>integer </type> <parameter>bandnum</parameter></paramdef>
-                                               <paramdef><type>integer </type> <parameter>columnx</parameter></paramdef>
-                                               <paramdef><type>integer </type> <parameter>rowy</parameter></paramdef>
-                                               <paramdef><type>integer </type> <parameter>distance</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>columnX</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>rowY</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>distanceX</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>distanceY</parameter></paramdef>
                                                <paramdef choice="opt"><type>boolean </type> <parameter>exclude_nodata_value=true</parameter></paramdef>
                                        </funcprototype>
 
                                        <funcprototype>
                                                <funcdef>double precision[][] <function>ST_Neighborhood</function></funcdef>
                                                <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
-                                               <paramdef><type>integer </type> <parameter>columnx</parameter></paramdef>
-                                               <paramdef><type>integer </type> <parameter>rowy</parameter></paramdef>
-                                               <paramdef><type>integer </type> <parameter>distance</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>columnX</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>rowY</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>distanceX</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>distanceY</parameter></paramdef>
                                                <paramdef choice="opt"><type>boolean </type> <parameter>exclude_nodata_value=true</parameter></paramdef>
                                        </funcprototype>
 
@@ -3769,7 +3771,8 @@ FROM (
                                                <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
                                                <paramdef><type>integer </type> <parameter>bandnum</parameter></paramdef>
                                                <paramdef><type>geometry </type> <parameter>pt</parameter></paramdef>
-                                               <paramdef><type>integer </type> <parameter>distance</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>distanceX</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>distanceY</parameter></paramdef>
                                                <paramdef choice="opt"><type>boolean </type> <parameter>exclude_nodata_value=true</parameter></paramdef>
                                        </funcprototype>
 
@@ -3777,7 +3780,8 @@ FROM (
                                                <funcdef>double precision[][] <function>ST_Neighborhood</function></funcdef>
                                                <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
                                                <paramdef><type>geometry </type> <parameter>pt</parameter></paramdef>
-                                               <paramdef><type>integer </type> <parameter>distance</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>distanceX</parameter></paramdef>
+                                               <paramdef><type>integer </type> <parameter>distanceY</parameter></paramdef>
                                                <paramdef choice="opt"><type>boolean </type> <parameter>exclude_nodata_value=true</parameter></paramdef>
                                        </funcprototype>
                                </funcsynopsis>
@@ -3786,14 +3790,14 @@ FROM (
                        <refsection>
                                <title>Description</title>
                                <para>
-                                       Returns a 2-D double precision array of the non-<varname>NODATA</varname> 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 <varname>distance</varname> 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-<varname>NODATA</varname> 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 <varname>distanceX</varname> and <varname>distanceY</varname> 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.
                                </para>
                                <para>
                                        Band numbers start at 1 and <varname>bandnum</varname> is assumed to be 1 if not specified. If <varname>exclude_nodata_value</varname> is set to false, then all pixels include <varname>nodata</varname> pixels are considered to intersect and return value. If <varname>exclude_nodata_value</varname> is not passed in then reads it from metadata of raster.
                                </para>
                                <note>
                                        <para>
-                                               The number of elements along each axis of the returning 2-D array is 2 * <varname>distance</varname> + 1.  So for a <varname>distance</varname> of 1, the returning array will be 3x3.
+                                               The number of elements along each axis of the returning 2-D array is 2 * (<varname>distanceX</varname>|<varname>distanceY</varname>) + 1.  So for a <varname>distanceX</varname> and <varname>distanceY</varname> of 1, the returning array will be 3x3.
                                        </para>
                                </note>
                                <note>
@@ -3809,27 +3813,22 @@ FROM (
                                <programlisting>
 -- 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 (
                                <programlisting>
 -- 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
 
index f8f32a74e8520278ea324803eec842781c2222c8..236eaaaf84db9ddb878e67370ea703970f6a0581 100644 (file)
@@ -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;
index c79f791f9e1f6428d4802d3d2d4ae176096bc062..9911278b21b2358d32621a1ab1ab8fedcdcfb95b 100644 (file)
@@ -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
 );
index 47a055bba551f4ea32267b7725f5a3ee9613a4d6..1e92c9d80c734db8a375d413099089c4313bc04c 100644 (file)
@@ -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]);
        }
index 9b9c0f4bc93c813c628678fac1a0bad6631b3a74..43b89e0daeedcbd058cdad170e44972949cc4e15 100644 (file)
@@ -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;
 
 ------------------------------------------------------------------------------
index ee31e925f5346d21ef71ca0891493de619f1261f..d46c31f2168e17735ddffb86000ee85846a9c589 100644 (file)
@@ -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);
 }
 
index 22a3adcada7e280f5366edabab2051f605065072..7d61eba5449f75b84778b2800559d94b23ad6225 100644 (file)
@@ -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;
index 7cfc3733731aa3091a037c675b0a06ed92dda404..49789beec016b4bf3d66b1863bcceef206f0fe17 100644 (file)
@@ -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}}