From 30321fe5c5dfb03961b55d8f25ee28612b32b8ba Mon Sep 17 00:00:00 2001 From: Bborie Park Date: Thu, 19 Jul 2012 18:18:16 +0000 Subject: [PATCH] Addition of rt_raster_overlaps and related regression tests. Fixed memory leaks in rt_raster_surface. git-svn-id: http://svn.osgeo.org/postgis/trunk@10073 b70326c6-7e19-0410-871a-916f4a2858ee --- raster/rt_core/rt_api.c | 166 +++++++++++-- raster/rt_core/rt_api.h | 29 ++- raster/rt_pg/rt_pg.c | 9 +- raster/test/core/testapi.c | 497 ++++++++++++++++++++++++++++++++++++- 4 files changed, 669 insertions(+), 32 deletions(-) diff --git a/raster/rt_core/rt_api.c b/raster/rt_core/rt_api.c index fb41b025d..2dd11e011 100644 --- a/raster/rt_core/rt_api.c +++ b/raster/rt_core/rt_api.c @@ -11456,6 +11456,110 @@ 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( + rt_raster rast1, int nband1, + rt_raster rast2, int nband2, + int *overlaps +) { + LWMPOLY *surface1 = NULL; + LWMPOLY *surface2 = NULL; + GEOSGeometry *geom1 = NULL; + GEOSGeometry *geom2 = NULL; + 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, two rasters do not overlap */ + *overlaps = 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"); + return 0; + } + + initGEOS(lwnotice, lwgeom_geos_error); + + /* 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"); + 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"); + lwmpoly_free(surface1); + return 0; + } + + /* either surface is NULL, does not overlap */ + if (surface1 == NULL || surface2 == NULL) { + if (surface1 != NULL) lwmpoly_free(surface1); + if (surface2 != NULL) lwmpoly_free(surface2); + return 1; + } + + /* convert LWMPOLY to GEOSGeometry */ + 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"); + lwmpoly_free(surface2); + return 0; + } + + 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"); + return 0; + } + + rtn = GEOSOverlaps(geom1, geom2); + 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 0; +} + /* * Return zero if error occurred in function. * Paramter aligned returns non-zero if two rasters are aligned @@ -11938,15 +12042,17 @@ rt_raster_pixel_as_polygon(rt_raster rast, int x, int y) * of the output multipolygon. * * @param raster: the raster to convert to a multipolygon - * @param nband : the 0-based band of raster rast to use + * @param nband: the 0-based band of raster rast to use * if value is less than zero, bands are ignored. + * @param err: if 0, error occurred * - * @return the raster surface or NULL on error + * @return the raster surface or NULL */ -LWMPOLY* rt_raster_surface(rt_raster raster, int nband) { +LWMPOLY* rt_raster_surface(rt_raster raster, int nband, int *err) { rt_band band = NULL; LWGEOM *mpoly = NULL; LWGEOM *tmp = NULL; + LWGEOM *clone = NULL; rt_geomval gv = NULL; int gvcount = 0; GEOSGeometry *gc = NULL; @@ -11955,23 +12061,33 @@ LWMPOLY* rt_raster_surface(rt_raster raster, int nband) { int geomscount = 0; int i = 0; + /* initialize to 1, no error occurred */ + *err = 1; + /* raster is empty, return NULL */ if (rt_raster_is_empty(raster)) return NULL; /* if nband < 0, return the convex hull as a multipolygon */ if (nband < 0) { - return lwgeom_as_lwmpoly( - lwgeom_as_multi( - lwpoly_as_lwgeom( - rt_raster_get_convex_hull(raster) - ) - ) - ); + /* + lwgeom_as_multi() only does a shallow clone internally + so input and output geometries may share memory + hence the deep clone of the output geometry for returning + is the only way to guarentee the memory isn't shared + */ + tmp = lwpoly_as_lwgeom(rt_raster_get_convex_hull(raster)); + mpoly = lwgeom_as_multi(tmp); + clone = lwgeom_clone_deep(mpoly); + lwgeom_free(tmp); + lwgeom_free(mpoly); + + return lwgeom_as_lwmpoly(clone); } /* check that nband is valid */ else if (nband >= rt_raster_get_num_bands(raster)) { rterror("rt_raster_surface: The band index %d is invalid", nband); + *err = 0; return NULL; } @@ -11979,6 +12095,7 @@ LWMPOLY* rt_raster_surface(rt_raster raster, int nband) { band = rt_raster_get_band(raster, nband); if (band == NULL) { rterror("rt_raster_surface: Error getting band %d from raster", nband); + *err = 0; return NULL; } @@ -11987,13 +12104,19 @@ LWMPOLY* rt_raster_surface(rt_raster raster, int nband) { rt_band_get_isnodata_flag(band) || !rt_band_get_hasnodata_flag(band) ) { - return lwgeom_as_lwmpoly( - lwgeom_as_multi( - lwpoly_as_lwgeom( - rt_raster_get_convex_hull(raster) - ) - ) - ); + /* + lwgeom_as_multi() only does a shallow clone internally + so input and output geometries may share memory + hence the deep clone of the output geometry for returning + is the only way to guarentee the memory isn't shared + */ + tmp = lwpoly_as_lwgeom(rt_raster_get_convex_hull(raster)); + mpoly = lwgeom_as_multi(tmp); + clone = lwgeom_clone_deep(mpoly); + lwgeom_free(tmp); + lwgeom_free(mpoly); + + return lwgeom_as_lwmpoly(clone); } /* initialize GEOS */ @@ -12004,6 +12127,7 @@ LWMPOLY* rt_raster_surface(rt_raster raster, int nband) { /* no polygons returned */ if (gvcount < 1) { RASTER_DEBUG(3, "All pixels of band are NODATA. Returning NULL"); + if (gv != NULL) rtdealloc(gv); return NULL; } /* more than 1 polygon */ @@ -12015,6 +12139,7 @@ LWMPOLY* rt_raster_surface(rt_raster raster, int nband) { rterror("rt_raster_surface: Unable to allocate memory for pixel polygons as GEOSGeometry"); for (i = 0; i < gvcount; i++) lwpoly_free(gv[i].geom); rtdealloc(gv); + *err = 0; return NULL; } for (i = 0; i < gvcount; i++) { @@ -12048,6 +12173,7 @@ LWMPOLY* rt_raster_surface(rt_raster raster, int nband) { for (i = 0; i < geomscount; i++) GEOSGeom_destroy(geoms[i]); rtdealloc(geoms); + *err = 0; return NULL; } @@ -12066,6 +12192,7 @@ LWMPOLY* rt_raster_surface(rt_raster raster, int nband) { #else rterror("rt_raster_surface: Unable to union the pixel polygons using GEOSUnionCascaded()"); #endif + *err = 0; return NULL; } @@ -12111,7 +12238,6 @@ LWMPOLY* rt_raster_surface(rt_raster raster, int nband) { if (mpoly != NULL) { /* convert to multi */ if (!lwgeom_is_collection(mpoly)) { - LWGEOM *tmp2 = NULL; tmp = mpoly; #if POSTGIS_DEBUG_LEVEL > 3 @@ -12131,10 +12257,10 @@ LWMPOLY* rt_raster_surface(rt_raster raster, int nband) { is the only way to guarentee the memory isn't shared */ mpoly = lwgeom_as_multi(tmp); - tmp2 = lwgeom_clone_deep(mpoly); + clone = lwgeom_clone_deep(mpoly); lwgeom_free(tmp); lwgeom_free(mpoly); - mpoly = tmp2; + mpoly = clone; RASTER_DEBUGF(4, "mpoly @ %p", mpoly); diff --git a/raster/rt_core/rt_api.h b/raster/rt_core/rt_api.h index e4740d1cc..c6ef5b160 100644 --- a/raster/rt_core/rt_api.h +++ b/raster/rt_core/rt_api.h @@ -1177,12 +1177,13 @@ LWPOLY* rt_raster_pixel_as_polygon(rt_raster raster, int x, int y); * of the output multipolygon. * * @param raster: the raster to convert to a multipolygon - * @param nband : the 0-based band of raster rast to use + * @param nband: the 0-based band of raster rast to use * if value is less than zero, bands are ignored. + * @param err: if 0, error occurred * - * @return the raster surface or NULL on error + * @return the raster surface or NULL */ -LWMPOLY* rt_raster_surface(rt_raster raster, int nband); +LWMPOLY* rt_raster_surface(rt_raster raster, int nband, int *err); /** * Returns a set of "geomval" value, one for each group of pixel @@ -1449,6 +1450,28 @@ int rt_raster_intersects( int *intersects ); +/** + * 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 +); + /* * Return zero if error occurred in function. * Paramter aligned returns non-zero if two rasters are aligned diff --git a/raster/rt_pg/rt_pg.c b/raster/rt_pg/rt_pg.c index 806616143..0bb727d8e 100644 --- a/raster/rt_pg/rt_pg.c +++ b/raster/rt_pg/rt_pg.c @@ -2754,6 +2754,7 @@ Datum RASTER_getPolygon(PG_FUNCTION_ARGS) rt_raster raster = NULL; int num_bands = 0; int nband = 1; + int err; LWMPOLY *surface = NULL; GSERIALIZED *rtn = NULL; @@ -2789,14 +2790,18 @@ Datum RASTER_getPolygon(PG_FUNCTION_ARGS) } /* get band surface */ - surface = rt_raster_surface(raster, nband - 1); + surface = rt_raster_surface(raster, nband - 1, &err); rt_raster_destroy(raster); PG_FREE_IF_COPY(pgraster, 0); - if (surface == NULL) { + if (!err) { elog(ERROR, "RASTER_getPolygon: Could not get raster band's surface"); PG_RETURN_NULL(); } + else if (surface == NULL) { + elog(NOTICE, "Raster is empty or all pixels of band are NODATA. Returning NULL"); + PG_RETURN_NULL(); + } rtn = geometry_serialize(lwmpoly_as_lwgeom(surface)); lwmpoly_free(surface); diff --git a/raster/test/core/testapi.c b/raster/test/core/testapi.c index f3fc9a794..620b5bafc 100644 --- a/raster/test/core/testapi.c +++ b/raster/test/core/testapi.c @@ -2375,6 +2375,477 @@ static void testIntersects() { deepRelease(rast1); } +static void testOverlaps() { + rt_raster rast1; + rt_raster rast2; + rt_band band1; + rt_band band2; + double nodata; + int rtn; + int overlaps; + + /* + 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_overlaps( + rast1, 0, + rast1, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps != 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps == 1)); + + rtn = rt_raster_overlaps( + rast1, -1, + rast2, -1, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps == 1)); + + /* + rast2 + + (0, 0) + +-+-+ + |0|1| + +-+-+ + |1|1| + +-+-+ + (2, 2) + */ + rtn = rt_band_set_pixel(band2, 0, 0, 0); + + rtn = rt_raster_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps != 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps == 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps != 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps != 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps != 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps != 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps != 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps == 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps != 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps == 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps != 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps != 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_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps == 1)); + + /* rast2 (skewed by -1, 1) */ + rt_raster_set_skews(rast2, -1, 1); + + rtn = rt_raster_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps == 1)); + + /* rast2 (skewed by 1, -1) */ + rt_raster_set_skews(rast2, 1, -1); + + rtn = rt_raster_overlaps( + rast1, 0, + rast2, 0, + &overlaps + ); + CHECK((rtn != 0)); + CHECK((overlaps == 1)); + + deepRelease(rast2); + deepRelease(rast1); +} + static void testAlignment() { rt_raster rast1; rt_raster rast2; @@ -2949,6 +3420,7 @@ static void testRasterSurface() { int x, y; char *wkt = NULL; LWMPOLY *mpoly = NULL; + int err; rast = rt_raster_new(maxX, maxY); assert(rast); @@ -2965,7 +3437,8 @@ static void testRasterSurface() { } } - mpoly = rt_raster_surface(rast, 0); + mpoly = rt_raster_surface(rast, 0, &err); + CHECK(err); CHECK((mpoly != NULL)); wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly)); CHECK(!strcmp(wkt, "MULTIPOLYGON(((0 0,0 -5,5 -5,5 0,0 0)))")); @@ -2976,7 +3449,8 @@ static void testRasterSurface() { /* 0,0 NODATA */ rt_band_set_pixel(band, 0, 0, 0); - mpoly = rt_raster_surface(rast, 0); + mpoly = rt_raster_surface(rast, 0, &err); + CHECK(err); CHECK((mpoly != NULL)); wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly)); CHECK(!strcmp(wkt, "MULTIPOLYGON(((1 0,1 -1,0 -1,0 -5,4 -5,5 -5,5 0,1 0)))")); @@ -2987,7 +3461,8 @@ static void testRasterSurface() { /* plus 1,1 NODATA */ rt_band_set_pixel(band, 1, 1, 0); - mpoly = rt_raster_surface(rast, 0); + mpoly = rt_raster_surface(rast, 0, &err); + CHECK(err); CHECK((mpoly != NULL)); wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly)); CHECK(!strcmp(wkt, "MULTIPOLYGON(((1 0,1 -1,0 -1,0 -5,4 -5,5 -5,5 0,1 0),(1 -1,1 -2,2 -2,2 -1,1 -1)))")); @@ -2998,7 +3473,8 @@ static void testRasterSurface() { /* plus 2,2 NODATA */ rt_band_set_pixel(band, 2, 2, 0); - mpoly = rt_raster_surface(rast, 0); + mpoly = rt_raster_surface(rast, 0, &err); + CHECK(err); CHECK((mpoly != NULL)); wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly)); #if POSTGIS_GEOS_VERSION >= 33 @@ -3013,7 +3489,8 @@ static void testRasterSurface() { /* plus 3,3 NODATA */ rt_band_set_pixel(band, 3, 3, 0); - mpoly = rt_raster_surface(rast, 0); + mpoly = rt_raster_surface(rast, 0, &err); + CHECK(err); CHECK((mpoly != NULL)); wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly)); #if POSTGIS_GEOS_VERSION >= 33 @@ -3028,7 +3505,8 @@ static void testRasterSurface() { /* plus 4,4 NODATA */ rt_band_set_pixel(band, 4, 4, 0); - mpoly = rt_raster_surface(rast, 0); + mpoly = rt_raster_surface(rast, 0, &err); + CHECK(err); CHECK((mpoly != NULL)); wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly)); CHECK(!strcmp(wkt, "MULTIPOLYGON(((4 -4,4 -5,0 -5,0 -1,1 -1,1 -2,2 -2,2 -3,3 -3,3 -4,4 -4)),((1 -1,1 0,5 0,5 -4,4 -4,4 -3,3 -3,3 -2,2 -2,2 -1,1 -1)))")); @@ -3042,7 +3520,8 @@ static void testRasterSurface() { rt_band_set_pixel(band, 1, 3, 0); rt_band_set_pixel(band, 0, 4, 0); - mpoly = rt_raster_surface(rast, 0); + mpoly = rt_raster_surface(rast, 0, &err); + CHECK(err); CHECK((mpoly != NULL)); wkt = lwgeom_to_text(lwmpoly_as_lwgeom(mpoly)); CHECK(!strcmp(wkt, "MULTIPOLYGON(((1 -4,2 -4,2 -3,3 -3,3 -4,4 -4,4 -5,3 -5,1 -5,1 -4)),((1 -4,0 -4,0 -1,1 -1,1 -2,2 -2,2 -3,1 -3,1 -4)),((3 -2,4 -2,4 -1,5 -1,5 -4,4 -4,4 -3,3 -3,3 -2)),((3 -2,2 -2,2 -1,1 -1,1 0,4 0,4 -1,3 -1,3 -2)))")); @@ -3303,6 +3782,10 @@ main() testIntersects(); printf("OK\n"); + printf("Testing rt_raster_overlaps... "); + testOverlaps(); + printf("OK\n"); + printf("Testing rt_raster_same_alignment... "); testAlignment(); printf("OK\n"); -- 2.50.1