From b0c173cbdba0d9cfaf882a061d2606bc4ffe7832 Mon Sep 17 00:00:00 2001 From: Bborie Park Date: Wed, 25 Jul 2012 03:35:57 +0000 Subject: [PATCH] Added rt_raster_full_within_distance() and regression tests git-svn-id: http://svn.osgeo.org/postgis/trunk@10114 b70326c6-7e19-0410-871a-916f4a2858ee --- raster/rt_core/rt_api.c | 103 ++++++- raster/rt_core/rt_api.h | 31 +- raster/test/core/testapi.c | 562 +++++++++++++++++++++++++++++++++++++ 3 files changed, 690 insertions(+), 6 deletions(-) diff --git a/raster/rt_core/rt_api.c b/raster/rt_core/rt_api.c index e418f3950..f8ea315f5 100644 --- a/raster/rt_core/rt_api.c +++ b/raster/rt_core/rt_api.c @@ -11782,7 +11782,8 @@ int rt_raster_coveredby( /** * Return zero if error occurred in function. - * Parameter contains returns non-zero if rast1 is within a distance of rast2 + * Parameter contains returns non-zero if rast1 is within the specified + * distance of rast2 * * @param rast1 : the first raster whose band will be tested * @param nband1 : the 0-based band of raster rast1 to use @@ -11792,7 +11793,8 @@ int rt_raster_coveredby( * @param nband2 : the 0-based band of raster rast2 to use * if value is less than zero, bands are ignored * if nband2 gte zero, nband1 must be gte zero - * @param dwithin : non-zero value if rast1 is within a distance of rast2 + * @param dwithin : non-zero value if rast1 is within the specified distance + * of rast2 * * @return if zero, an error occurred in function */ @@ -11862,12 +11864,105 @@ int rt_raster_within_distance( lwgeom_free(surface1); lwgeom_free(surface2); - RASTER_DEBUGF(3, "(mindist, distance) = (%f, %f)", mindist, distance); - /* if distance >= mindist, true */ if (FLT_EQ(mindist, distance) || distance > mindist) *dwithin = 1; + RASTER_DEBUGF(3, "(mindist, distance) = (%f, %f, %d)", mindist, distance, *dwithin); + + return 1; +} + +/** + * Return zero if error occurred in function. + * Parameter contains returns non-zero if rast1 is fully within the specified + * distance of rast2 + * + * @param rast1 : the first raster whose band will be tested + * @param nband1 : the 0-based band of raster rast1 to use + * if value is less than zero, bands are ignored. + * if nband1 gte zero, nband2 must be gte zero + * @param rast2 : the second raster whose band will be tested + * @param nband2 : the 0-based band of raster rast2 to use + * if value is less than zero, bands are ignored + * if nband2 gte zero, nband1 must be gte zero + * @param dfwithin : non-zero value if rast1 is fully within the specified + * distance of rast2 + * + * @return if zero, an error occurred in function + */ +int rt_raster_fully_within_distance( + rt_raster rast1, int nband1, + rt_raster rast2, int nband2, + double distance, + int *dfwithin +) { + LWGEOM *surface1 = NULL; + LWGEOM *surface2 = NULL; + double maxdist = 0; + int rtn = 0; + + RASTER_DEBUG(3, "Starting"); + + assert(NULL != rast1); + assert(NULL != rast2); + + if (nband1 < 0 && nband2 < 0) { + nband1 = -1; + nband2 = -1; + } + else { + assert(nband1 >= 0 && nband1 < rt_raster_get_num_bands(rast1)); + assert(nband2 >= 0 && nband2 < rt_raster_get_num_bands(rast2)); + } + + /* initialize to zero, false result */ + *dfwithin = 0; + + /* same srid */ + if (rt_raster_get_srid(rast1) != rt_raster_get_srid(rast2)) { + rterror("rt_raster_distance_within: The two rasters provided have different SRIDs"); + return 0; + } + + /* distance cannot be less than zero */ + if (distance < 0) { + rterror("rt_raster_distance_within: Distance cannot be less than zero"); + return 0; + } + + /* get LWMPOLY of each band */ + surface1 = lwmpoly_as_lwgeom(rt_raster_surface(rast1, nband1, &rtn)); + if (!rtn) { + rterror("rt_raster_distance_within: Unable to get surface of the specified band from the first raster"); + return 0; + } + surface2 = lwmpoly_as_lwgeom(rt_raster_surface(rast2, nband2, &rtn)); + if (!rtn) { + rterror("rt_raster_distance_within: Unable to get surface of the specified band from the second raster"); + lwgeom_free(surface1); + return 0; + } + + /* either surface is NULL, test is false */ + if (surface1 == NULL || surface2 == NULL) { + if (surface1 != NULL) lwgeom_free(surface1); + if (surface2 != NULL) lwgeom_free(surface2); + return 1; + } + + /* get the maximum distance between the two surfaces */ + maxdist = lwgeom_maxdistance2d_tolerance(surface1, surface2, distance); + + lwgeom_free(surface1); + lwgeom_free(surface2); + + /* if distance >= maxdist, true */ + if (FLT_EQ(maxdist, distance) || distance > maxdist) + *dfwithin = 1; + + RASTER_DEBUGF(3, "(maxdist, distance, dfwithin) = (%f, %f, %d)", maxdist, distance, *dfwithin); + return 1; } diff --git a/raster/rt_core/rt_api.h b/raster/rt_core/rt_api.h index 1c963ebc1..cec8752a7 100644 --- a/raster/rt_core/rt_api.h +++ b/raster/rt_core/rt_api.h @@ -1601,7 +1601,8 @@ int rt_raster_coveredby( /** * Return zero if error occurred in function. - * Parameter contains returns non-zero if rast1 is within a distance of rast2 + * Parameter contains returns non-zero if rast1 is within the specified + * distance of rast2 * * @param rast1 : the first raster whose band will be tested * @param nband1 : the 0-based band of raster rast1 to use @@ -1611,7 +1612,8 @@ int rt_raster_coveredby( * @param nband2 : the 0-based band of raster rast2 to use * if value is less than zero, bands are ignored * if nband2 gte zero, nband1 must be gte zero - * @param dwithin : non-zero value if rast1 is within a distance of rast2 + * @param dwithin : non-zero value if rast1 is within the specified distance + * of rast2 * * @return if zero, an error occurred in function */ @@ -1622,6 +1624,31 @@ int rt_raster_within_distance( int *dwithin ); +/** + * Return zero if error occurred in function. + * Parameter contains returns non-zero if rast1 is fully within the specified + * distance of rast2 + * + * @param rast1 : the first raster whose band will be tested + * @param nband1 : the 0-based band of raster rast1 to use + * if value is less than zero, bands are ignored. + * if nband1 gte zero, nband2 must be gte zero + * @param rast2 : the second raster whose band will be tested + * @param nband2 : the 0-based band of raster rast2 to use + * if value is less than zero, bands are ignored + * if nband2 gte zero, nband1 must be gte zero + * @param dfwithin : non-zero value if rast1 is fully within the specified + * distance of rast2 + * + * @return if zero, an error occurred in function + */ +int rt_raster_fully_within_distance( + rt_raster rast1, int nband1, + rt_raster rast2, int nband2, + double distance, + int *dfwithin +); + /* * Return zero if error occurred in function. * Paramter aligned returns non-zero if two rasters are aligned diff --git a/raster/test/core/testapi.c b/raster/test/core/testapi.c index ecbf7105a..ee31e925f 100644 --- a/raster/test/core/testapi.c +++ b/raster/test/core/testapi.c @@ -6019,6 +6019,564 @@ static void testDWithin() { deepRelease(rast1); } +static void testDFullyWithin() { + rt_raster rast1; + rt_raster rast2; + rt_band band1; + rt_band band2; + double nodata; + int rtn; + int result; + + /* + rast1 + + (-1, -1) + +-+-+ + |1|1| + +-+-+ + |1|1| + +-+-+ + (1, 1) + */ + rast1 = rt_raster_new(2, 2); + assert(rast1); + rt_raster_set_offsets(rast1, -1, -1); + + band1 = addBand(rast1, PT_8BUI, 1, 0); + CHECK(band1); + rt_band_set_nodata(band1, 0); + rtn = rt_band_set_pixel(band1, 0, 0, 1); + rtn = rt_band_set_pixel(band1, 0, 1, 1); + rtn = rt_band_set_pixel(band1, 1, 0, 1); + rtn = rt_band_set_pixel(band1, 1, 1, 1); + + nodata = rt_band_get_nodata(band1); + CHECK_EQUALS(nodata, 0); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast1, 0, + 0., + &result + ); + CHECK((rtn != 0)); + CHECK((result != 1)); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast1, 0, + -1., + &result + ); + CHECK((rtn == 0)); + + /* + rast2 + + (0, 0) + +-+-+ + |1|1| + +-+-+ + |1|1| + +-+-+ + (2, 2) + */ + rast2 = rt_raster_new(2, 2); + assert(rast2); + + band2 = addBand(rast2, PT_8BUI, 1, 0); + CHECK(band2); + rt_band_set_nodata(band2, 0); + rtn = rt_band_set_pixel(band2, 0, 0, 1); + rtn = rt_band_set_pixel(band2, 0, 1, 1); + rtn = rt_band_set_pixel(band2, 1, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 1, 1); + + nodata = rt_band_get_nodata(band2); + CHECK_EQUALS(nodata, 0); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 0., + &result + ); + CHECK((rtn != 0)); + CHECK((result != 1)); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 1., + &result + ); + CHECK((rtn != 0)); + CHECK((result != 1)); + + rtn = rt_raster_fully_within_distance( + rast1, -1, + rast2, -1, + 5., + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + /* + rast2 + + (0, 0) + +-+-+ + |0|1| + +-+-+ + |1|1| + +-+-+ + (2, 2) + */ + rtn = rt_band_set_pixel(band2, 0, 0, 0); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 2., + &result + ); + CHECK((rtn != 0)); + CHECK((result != 1)); + + /* + rast2 + + (0, 0) + +-+-+ + |1|0| + +-+-+ + |1|1| + +-+-+ + (2, 2) + */ + rtn = rt_band_set_pixel(band2, 0, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 0, 0); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 5., + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + /* + rast2 + + (0, 0) + +-+-+ + |0|0| + +-+-+ + |0|1| + +-+-+ + (2, 2) + */ + rtn = rt_band_set_pixel(band2, 0, 0, 0); + rtn = rt_band_set_pixel(band2, 1, 0, 0); + rtn = rt_band_set_pixel(band2, 0, 1, 0); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 5, + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + /* + rast2 + + (0, 0) + +-+-+ + |0|0| + +-+-+ + |0|0| + +-+-+ + (2, 2) + */ + rtn = rt_band_set_pixel(band2, 0, 0, 0); + rtn = rt_band_set_pixel(band2, 1, 0, 0); + rtn = rt_band_set_pixel(band2, 0, 1, 0); + rtn = rt_band_set_pixel(band2, 1, 1, 0); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 10, + &result + ); + CHECK((rtn != 0)); + CHECK((result != 1)); + + /* + rast2 + + (2, 0) + +-+-+ + |1|1| + +-+-+ + |1|1| + +-+-+ + (4, 2) + */ + rt_raster_set_offsets(rast2, 2, 0); + + rtn = rt_band_set_pixel(band2, 0, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 0, 1); + rtn = rt_band_set_pixel(band2, 0, 1, 1); + rtn = rt_band_set_pixel(band2, 1, 1, 1); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 0, + &result + ); + CHECK((rtn != 0)); + CHECK((result != 1)); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 5.9, + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + /* + rast2 + + (0.1, 0.1) + +-+-+ + |1|1| + +-+-+ + |1|1| + +-+-+ + (0.9, 0.9) + */ + rt_raster_set_offsets(rast2, 0.1, 0.1); + rt_raster_set_scale(rast2, 0.4, 0.4); + + rtn = rt_band_set_pixel(band2, 0, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 0, 1); + rtn = rt_band_set_pixel(band2, 0, 1, 1); + rtn = rt_band_set_pixel(band2, 1, 1, 1); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 3, + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + /* + rast2 + + (-0.1, 0.1) + +-+-+ + |1|1| + +-+-+ + |1|1| + +-+-+ + (0.9, 0.9) + */ + rt_raster_set_offsets(rast2, -0.1, 0.1); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 2, + &result + ); + CHECK((rtn != 0)); + CHECK((result != 1)); + + deepRelease(rast2); + + /* + rast2 + + (0, 0) + +-+-+-+ + |1|1|1| + +-+-+-+ + |1|1|1| + +-+-+-+ + |1|1|1| + +-+-+-+ + (3, 3) + */ + rast2 = rt_raster_new(3, 3); + assert(rast2); + + band2 = addBand(rast2, PT_8BUI, 1, 0); + CHECK(band2); + rt_band_set_nodata(band2, 0); + rtn = rt_band_set_pixel(band2, 0, 0, 1); + rtn = rt_band_set_pixel(band2, 0, 1, 1); + rtn = rt_band_set_pixel(band2, 0, 2, 1); + rtn = rt_band_set_pixel(band2, 1, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 1, 1); + rtn = rt_band_set_pixel(band2, 1, 2, 1); + rtn = rt_band_set_pixel(band2, 2, 0, 1); + rtn = rt_band_set_pixel(band2, 2, 1, 1); + rtn = rt_band_set_pixel(band2, 2, 2, 1); + + nodata = rt_band_get_nodata(band2); + CHECK_EQUALS(nodata, 0); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 6, + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + /* + rast2 + + (-2, -2) + +-+-+-+ + |1|1|1| + +-+-+-+ + |1|1|1| + +-+-+-+ + |1|1|1| + +-+-+-+ + (1, 1) + */ + rt_raster_set_offsets(rast2, -2, -2); + + rtn = rt_band_set_pixel(band2, 0, 0, 1); + rtn = rt_band_set_pixel(band2, 0, 1, 1); + rtn = rt_band_set_pixel(band2, 0, 2, 1); + rtn = rt_band_set_pixel(band2, 1, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 1, 1); + rtn = rt_band_set_pixel(band2, 1, 2, 1); + rtn = rt_band_set_pixel(band2, 2, 0, 1); + rtn = rt_band_set_pixel(band2, 2, 1, 1); + rtn = rt_band_set_pixel(band2, 2, 2, 1); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 4.25, + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + /* + rast2 + + (-2, -2) + +-+-+-+ + |0|1|1| + +-+-+-+ + |1|0|1| + +-+-+-+ + |1|1|0| + +-+-+-+ + (1, 1) + */ + rtn = rt_band_set_pixel(band2, 0, 0, 0); + rtn = rt_band_set_pixel(band2, 0, 1, 1); + rtn = rt_band_set_pixel(band2, 0, 2, 1); + rtn = rt_band_set_pixel(band2, 1, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 1, 0); + rtn = rt_band_set_pixel(band2, 1, 2, 1); + rtn = rt_band_set_pixel(band2, 2, 0, 1); + rtn = rt_band_set_pixel(band2, 2, 1, 1); + rtn = rt_band_set_pixel(band2, 2, 2, 0); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 3.5, + &result + ); + CHECK((rtn != 0)); + CHECK((result != 1)); + + /* + rast2 + + (-2, -2) + +-+-+-+ + |0|1|1| + +-+-+-+ + |1|0|0| + +-+-+-+ + |1|0|0| + +-+-+-+ + (1, 1) + */ + rtn = rt_band_set_pixel(band2, 0, 0, 0); + rtn = rt_band_set_pixel(band2, 0, 1, 1); + rtn = rt_band_set_pixel(band2, 0, 2, 1); + rtn = rt_band_set_pixel(band2, 1, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 1, 0); + rtn = rt_band_set_pixel(band2, 1, 2, 0); + rtn = rt_band_set_pixel(band2, 2, 0, 1); + rtn = rt_band_set_pixel(band2, 2, 1, 0); + rtn = rt_band_set_pixel(band2, 2, 2, 0); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 3.65, + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + /* + rast2 + + (-2, -2) + +-+-+-+ + |0|1|0| + +-+-+-+ + |1|0|0| + +-+-+-+ + |0|0|0| + +-+-+-+ + (1, 1) + */ + rtn = rt_band_set_pixel(band2, 0, 0, 0); + rtn = rt_band_set_pixel(band2, 0, 1, 1); + rtn = rt_band_set_pixel(band2, 0, 2, 0); + rtn = rt_band_set_pixel(band2, 1, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 1, 0); + rtn = rt_band_set_pixel(band2, 1, 2, 0); + rtn = rt_band_set_pixel(band2, 2, 0, 0); + rtn = rt_band_set_pixel(band2, 2, 1, 0); + rtn = rt_band_set_pixel(band2, 2, 2, 0); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 3.6, + &result + ); + CHECK((rtn != 0)); + CHECK((result != 1)); + + /* + rast2 + + (-10, -1) + +-+-+-+ + |1|1|1| + +-+-+-+ + |1|1|1| + +-+-+-+ + |1|1|1| + +-+-+-+ + (-7, 2) + */ + rt_raster_set_offsets(rast2, -10, -1); + + rtn = rt_band_set_pixel(band2, 0, 0, 1); + rtn = rt_band_set_pixel(band2, 0, 1, 1); + rtn = rt_band_set_pixel(band2, 0, 2, 1); + rtn = rt_band_set_pixel(band2, 1, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 1, 1); + rtn = rt_band_set_pixel(band2, 1, 2, 1); + rtn = rt_band_set_pixel(band2, 2, 0, 1); + rtn = rt_band_set_pixel(band2, 2, 1, 1); + rtn = rt_band_set_pixel(band2, 2, 2, 1); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 5, + &result + ); + CHECK((rtn != 0)); + CHECK((result != 1)); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 11.5, + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + deepRelease(rast2); + + /* skew tests */ + /* rast2 (skewed by -0.5, 0.5) */ + rast2 = rt_raster_new(3, 3); + assert(rast2); + rt_raster_set_skews(rast2, -0.5, 0.5); + + band2 = addBand(rast2, PT_8BUI, 1, 0); + CHECK(band2); + rt_band_set_nodata(band2, 0); + rtn = rt_band_set_pixel(band2, 0, 0, 1); + rtn = rt_band_set_pixel(band2, 0, 1, 2); + rtn = rt_band_set_pixel(band2, 0, 2, 3); + rtn = rt_band_set_pixel(band2, 1, 0, 1); + rtn = rt_band_set_pixel(band2, 1, 1, 2); + rtn = rt_band_set_pixel(band2, 1, 2, 3); + rtn = rt_band_set_pixel(band2, 2, 0, 1); + rtn = rt_band_set_pixel(band2, 2, 1, 2); + rtn = rt_band_set_pixel(band2, 2, 2, 3); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 6.1, + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + /* rast2 (skewed by -1, 1) */ + rt_raster_set_skews(rast2, -1, 1); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 7.1, + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + /* rast2 (skewed by 1, -1) */ + rt_raster_set_skews(rast2, 1, -1); + + rtn = rt_raster_fully_within_distance( + rast1, 0, + rast2, 0, + 8, + &result + ); + CHECK((rtn != 0)); + CHECK((result == 1)); + + deepRelease(rast2); + deepRelease(rast1); +} + static void testAlignment() { rt_raster rast1; rt_raster rast2; @@ -6987,6 +7545,10 @@ main() testDWithin(); printf("OK\n"); + printf("Testing rt_raster_fully_within_distance... "); + testDFullyWithin(); + printf("OK\n"); + printf("Testing rt_raster_same_alignment... "); testAlignment(); printf("OK\n"); -- 2.50.1