From 71c48ef768e9e3b10bd28a91fc0ba144029cbb81 Mon Sep 17 00:00:00 2001 From: Bborie Park Date: Thu, 19 Jul 2012 20:09:53 +0000 Subject: [PATCH] Extracted most of code in rt_raster_overlaps to create generic GEOS spatial relationship testing function rt_raster_geos_spatial_relationship(). Refactored rt_raster_overlaps() call rt_raster_geos_spatial_relationship(). Added rt_raster_touches() and associated regression tests git-svn-id: http://svn.osgeo.org/postgis/trunk@10076 b70326c6-7e19-0410-871a-916f4a2858ee --- raster/rt_core/rt_api.c | 143 +++++++--- raster/rt_core/rt_api.h | 27 ++ raster/test/core/testapi.c | 527 +++++++++++++++++++++++++++++++++++++ 3 files changed, 661 insertions(+), 36 deletions(-) diff --git a/raster/rt_core/rt_api.c b/raster/rt_core/rt_api.c index 2dd11e011..119b17f51 100644 --- a/raster/rt_core/rt_api.c +++ b/raster/rt_core/rt_api.c @@ -11456,32 +11456,19 @@ rt_raster_intersects( return 1; } -/** - * Return zero if error occurred in function. - * Parameter overlaps returns non-zero if two rasters overlap - * - * @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 overlaps : non-zero value if the two rasters' bands overlaps - * - * @return if zero, an error occurred in function - */ -int rt_raster_overlaps( +static +int rt_raster_geos_spatial_relationship( rt_raster rast1, int nband1, rt_raster rast2, int nband2, - int *overlaps + rt_geos_spatial_test testtype, + int *testresult ) { LWMPOLY *surface1 = NULL; LWMPOLY *surface2 = NULL; GEOSGeometry *geom1 = NULL; GEOSGeometry *geom2 = NULL; int rtn = 0; + int flag = 0; RASTER_DEBUG(3, "Starting"); @@ -11497,12 +11484,12 @@ int rt_raster_overlaps( assert(nband2 >= 0 && nband2 < rt_raster_get_num_bands(rast2)); } - /* initialize to zero, two rasters do not overlap */ - *overlaps = 0; + /* initialize to zero, false result of spatial relationship test */ + *testresult = 0; /* same srid */ if (rt_raster_get_srid(rast1) != rt_raster_get_srid(rast2)) { - rterror("rt_raster_overlaps: The two rasters provided have different SRIDs"); + rterror("rt_raster_geos_spatial_relationship: The two rasters provided have different SRIDs"); return 0; } @@ -11511,17 +11498,17 @@ int rt_raster_overlaps( /* get LWMPOLY of each band */ surface1 = rt_raster_surface(rast1, nband1, &rtn); if (!rtn) { - rterror("rt_raster_overlaps: Unable to get surface of the specified band from the first raster"); + rterror("rt_raster_geos_spatial_relationship: Unable to get surface of the specified band from the first raster"); return 0; } surface2 = rt_raster_surface(rast2, nband2, &rtn); if (!rtn) { - rterror("rt_raster_overlaps: Unable to get surface of the specified band from the second raster"); + rterror("rt_raster_geos_spatial_relationship: Unable to get surface of the specified band from the second raster"); lwmpoly_free(surface1); return 0; } - /* either surface is NULL, does not overlap */ + /* either surface is NULL, spatial relationship test is false */ if (surface1 == NULL || surface2 == NULL) { if (surface1 != NULL) lwmpoly_free(surface1); if (surface2 != NULL) lwmpoly_free(surface2); @@ -11532,7 +11519,7 @@ int rt_raster_overlaps( geom1 = LWGEOM2GEOS(lwmpoly_as_lwgeom(surface1)); lwmpoly_free(surface1); if (geom1 == NULL) { - rterror("rt_raster_overlaps: Unable to convert surface of the specified band from the first raster to a GEOSGeometry"); + rterror("rt_raster_geos_spatial_relationship: Unable to convert surface of the specified band from the first raster to a GEOSGeometry"); lwmpoly_free(surface2); return 0; } @@ -11540,24 +11527,108 @@ int rt_raster_overlaps( geom2 = LWGEOM2GEOS(lwmpoly_as_lwgeom(surface2)); lwmpoly_free(surface2); if (geom2 == NULL) { - rterror("rt_raster_overlaps: Unable to convert surface of the specified band from the second raster to a GEOSGeometry"); + rterror("rt_raster_geos_spatial_relationship: Unable to convert surface of the specified band from the second raster to a GEOSGeometry"); return 0; } - rtn = GEOSOverlaps(geom1, geom2); + switch (testtype) { + case GSR_OVERLAPS: + rtn = GEOSOverlaps(geom1, geom2); + if (rtn == 2) { + rterror("rt_raster_geos_spatial_relationship: Unable to run overlap test using GEOSOverlaps()"); + flag = 0; + } + else { + RASTER_DEBUGF(4, "the two rasters do %soverlap", rtn != 1 ? "NOT " : ""); + if (rtn != 0) + *testresult = 1; + flag = 1; + } + break; + case GSR_TOUCHES: + rtn = GEOSTouches(geom1, geom2); + if (rtn == 2) { + rterror("rt_raster_geos_spatial_relationship: Unable to run touch test using GEOSTouches()"); + flag = 0; + } + else { + RASTER_DEBUGF(4, "the two rasters do %touch", rtn != 1 ? "NOT " : ""); + if (rtn != 0) + *testresult = 1; + flag = 1; + } + break; + default: + rterror("rt_raster_geos_spatial_relationship: Unknown or unsupported GEOS spatial relationship test"); + flag = 0; + break; + } GEOSGeom_destroy(geom1); GEOSGeom_destroy(geom2); - if (rtn != 2) { - RASTER_DEBUGF(4, "the two rasters do %soverlap", rtn != 1 ? "NOT " : ""); - if (rtn != 0) - *overlaps = 1; - return 1; - } - else - rterror("rt_raster_overlaps: Unable to run overlap test using GEOSOverlaps()"); + return flag; +} - return 0; +/** + * Return zero if error occurred in function. + * Parameter overlaps returns non-zero if two rasters overlap + * + * @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 overlaps : non-zero value if the two rasters' bands overlaps + * + * @return if zero, an error occurred in function + */ +int rt_raster_overlaps( + rt_raster rast1, int nband1, + rt_raster rast2, int nband2, + int *overlaps +) { + RASTER_DEBUG(3, "Starting"); + + return rt_raster_geos_spatial_relationship( + rast1, nband1, + rast2, nband2, + GSR_OVERLAPS, + overlaps + ); +} + +/** + * Return zero if error occurred in function. + * Parameter touches returns non-zero if two rasters touch + * + * @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 touches : non-zero value if the two rasters' bands touch + * + * @return if zero, an error occurred in function + */ +int rt_raster_touches( + rt_raster rast1, int nband1, + rt_raster rast2, int nband2, + int *touches +) { + RASTER_DEBUG(3, "Starting"); + + return rt_raster_geos_spatial_relationship( + rast1, nband1, + rast2, nband2, + GSR_TOUCHES, + touches + ); } /* diff --git a/raster/rt_core/rt_api.h b/raster/rt_core/rt_api.h index c6ef5b160..697a590d9 100644 --- a/raster/rt_core/rt_api.h +++ b/raster/rt_core/rt_api.h @@ -179,6 +179,11 @@ typedef enum { ET_SECOND } rt_extenttype; +typedef enum { + GSR_OVERLAPS = 0, + GSR_TOUCHES +} rt_geos_spatial_test; + /** * Global functions for memory/logging handlers. */ @@ -1472,6 +1477,28 @@ int rt_raster_overlaps( int *overlaps ); +/** + * Return zero if error occurred in function. + * Parameter touches returns non-zero if two rasters touch + * + * @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 touches : non-zero value if the two rasters' bands touch + * + * @return if zero, an error occurred in function + */ +int rt_raster_touches( + rt_raster rast1, int nband1, + rt_raster rast2, int nband2, + int *touches +); + /* * 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 620b5bafc..7b14611b9 100644 --- a/raster/test/core/testapi.c +++ b/raster/test/core/testapi.c @@ -2846,6 +2846,529 @@ static void testOverlaps() { deepRelease(rast1); } +static void testTouches() { + rt_raster rast1; + rt_raster rast2; + rt_band band1; + rt_band band2; + double nodata; + int rtn; + int touches; + + /* + 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_touches( + rast1, 0, + rast1, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 1)); + + /* + 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 1)); + + rtn = rt_raster_touches( + rast1, -1, + rast2, -1, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 1)); + + /* + rast2 + + (0, 0) + +-+-+ + |0|1| + +-+-+ + |1|1| + +-+-+ + (2, 2) + */ + rtn = rt_band_set_pixel(band2, 0, 0, 0); + + rtn = rt_raster_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches == 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches == 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 1)); + + /* + rast2 + + (0, 1) + +-+-+ + |1|1| + +-+-+ + |1|1| + +-+-+ + (2, 3) + */ + rt_raster_set_offsets(rast2, 0, 1); + + 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches == 1)); + + /* + rast2 + + (-1, 1) + +-+-+ + |1|1| + +-+-+ + |1|1| + +-+-+ + (1, 3) + */ + rt_raster_set_offsets(rast2, -1, 1); + + 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches == 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches == 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches == 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_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 1)); + + /* rast2 (skewed by -1, 1) */ + rt_raster_set_skews(rast2, -1, 1); + + rtn = rt_raster_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 1)); + + /* rast2 (skewed by 1, -1) */ + rt_raster_set_skews(rast2, 1, -1); + + rtn = rt_raster_touches( + rast1, 0, + rast2, 0, + &touches + ); + CHECK((rtn != 0)); + CHECK((touches != 1)); + + deepRelease(rast2); + deepRelease(rast1); +} + static void testAlignment() { rt_raster rast1; rt_raster rast2; @@ -3786,6 +4309,10 @@ main() testOverlaps(); printf("OK\n"); + printf("Testing rt_raster_touches... "); + testTouches(); + printf("OK\n"); + printf("Testing rt_raster_same_alignment... "); testAlignment(); printf("OK\n"); -- 2.50.1