]> granicus.if.org Git - postgis/commitdiff
Extracted most of code in rt_raster_overlaps to create generic GEOS
authorBborie Park <bkpark at ucdavis.edu>
Thu, 19 Jul 2012 20:09:53 +0000 (20:09 +0000)
committerBborie Park <bkpark at ucdavis.edu>
Thu, 19 Jul 2012 20:09:53 +0000 (20:09 +0000)
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
raster/rt_core/rt_api.h
raster/test/core/testapi.c

index 2dd11e011e2b78375bac1e3503636856088a565e..119b17f51a8e12d79360e28084b838cd49c61802 100644 (file)
@@ -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
+       );
 }
 
 /*
index c6ef5b160efe48340afa79a39fbb94ef73d194fb..697a590d9b5de69592b7b5370a906cf4c4fbbe7d 100644 (file)
@@ -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
index 620b5bafc45e4e0a4c5c41d08841483b7c371f40..7b14611b913f986cb8d4055647df18d5424a9731 100644 (file)
@@ -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");