]> granicus.if.org Git - postgis/commitdiff
Addition of ST_Touches() for rasters and related regression tests.
authorBborie Park <bkpark at ucdavis.edu>
Thu, 19 Jul 2012 20:10:13 +0000 (20:10 +0000)
committerBborie Park <bkpark at ucdavis.edu>
Thu, 19 Jul 2012 20:10:13 +0000 (20:10 +0000)
Ticket is #1921

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

raster/rt_pg/rt_pg.c
raster/rt_pg/rtpostgis.sql.in.c
raster/test/regress/Makefile.in
raster/test/regress/rt_touches.sql [new file with mode: 0644]
raster/test/regress/rt_touches_expected [new file with mode: 0644]

index 5274e23757a139f03d07949e0f3a7844d49be3fb..ed5faa08e908d634ff73b6d15ac1f5eae9cc2b49 100644 (file)
@@ -273,6 +273,9 @@ Datum RASTER_intersects(PG_FUNCTION_ARGS);
 /* determine if two rasters overlap */
 Datum RASTER_overlaps(PG_FUNCTION_ARGS);
 
+/* determine if two rasters touch */
+Datum RASTER_touches(PG_FUNCTION_ARGS);
+
 /* determine if two rasters are aligned */
 Datum RASTER_sameAlignment(PG_FUNCTION_ARGS);
 
@@ -10097,6 +10100,125 @@ Datum RASTER_overlaps(PG_FUNCTION_ARGS)
        PG_RETURN_BOOL(overlaps);
 }
 
+/**
+ * See if two rasters touch
+ */
+PG_FUNCTION_INFO_V1(RASTER_touches);
+Datum RASTER_touches(PG_FUNCTION_ARGS)
+{
+       const int set_count = 2;
+       rt_pgraster *pgrast[2];
+       int pgrastpos[2] = {-1, -1};
+       rt_raster rast[2] = {NULL};
+       uint32_t bandindex[2] = {0};
+       uint32_t hasbandindex[2] = {0};
+
+       uint32_t i;
+       uint32_t j;
+       uint32_t k;
+       uint32_t numBands;
+       int rtn;
+       int touches;
+
+       for (i = 0, j = 0; i < set_count; i++) {
+               /* pgrast is null, return null */
+               if (PG_ARGISNULL(j)) {
+                       for (k = 0; k < i; k++) {
+                               rt_raster_destroy(rast[k]);
+                               PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
+                       }
+                       PG_RETURN_NULL();
+               }
+               pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
+               pgrastpos[i] = j;
+               j++;
+
+               /* raster */
+               rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
+               if (!rast[i]) {
+                       elog(ERROR, "RASTER_touches: Could not deserialize the %s raster", i < 1 ? "first" : "second");
+                       for (k = 0; k <= i; k++) {
+                               if (k < i)
+                                       rt_raster_destroy(rast[k]);
+                               PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
+                       }
+                       PG_RETURN_NULL();
+               }
+
+               /* numbands */
+               numBands = rt_raster_get_num_bands(rast[i]);
+               if (numBands < 1) {
+                       elog(NOTICE, "The %s raster provided has no bands", i < 1 ? "first" : "second");
+                       if (i > 0) i++;
+                       for (k = 0; k < i; k++) {
+                               rt_raster_destroy(rast[k]);
+                               PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
+                       }
+                       PG_RETURN_NULL();
+               }
+
+               /* band index */
+               if (!PG_ARGISNULL(j)) {
+                       bandindex[i] = PG_GETARG_INT32(j);
+                       if (bandindex[i] < 1 || bandindex[i] > numBands) {
+                               elog(NOTICE, "Invalid band index (must use 1-based) for the %s raster. Returning NULL", i < 1 ? "first" : "second");
+                               if (i > 0) i++;
+                               for (k = 0; k < i; k++) {
+                                       rt_raster_destroy(rast[k]);
+                                       PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
+                               }
+                               PG_RETURN_NULL();
+                       }
+                       hasbandindex[i] = 1;
+               }
+               else
+                       hasbandindex[i] = 0;
+               POSTGIS_RT_DEBUGF(4, "hasbandindex[%d] = %d", i, hasbandindex[i]);
+               POSTGIS_RT_DEBUGF(4, "bandindex[%d] = %d", i, bandindex[i]);
+               j++;
+       }
+
+       /* hasbandindex must be balanced */
+       if (
+               (hasbandindex[0] && !hasbandindex[1]) ||
+               (!hasbandindex[0] && hasbandindex[1])
+       ) {
+               elog(NOTICE, "Missing band index.  Band indices must be provided for both rasters if any one is provided");
+               for (k = 0; k < set_count; k++) {
+                       rt_raster_destroy(rast[k]);
+                       PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
+               }
+               PG_RETURN_NULL();
+       }
+
+       /* SRID must match */
+       if (rt_raster_get_srid(rast[0]) != rt_raster_get_srid(rast[1])) {
+               elog(ERROR, "The two rasters provided have different SRIDs");
+               for (k = 0; k < set_count; k++) {
+                       rt_raster_destroy(rast[k]);
+                       PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
+               }
+               PG_RETURN_NULL();
+       }
+
+       rtn = rt_raster_touches(
+               rast[0], (hasbandindex[0] ? bandindex[0] - 1 : -1),
+               rast[1], (hasbandindex[1] ? bandindex[1] - 1 : -1),
+               &touches
+       );
+       for (k = 0; k < set_count; k++) {
+               rt_raster_destroy(rast[k]);
+               PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
+       }
+
+       if (!rtn) {
+               elog(ERROR, "RASTER_touches: Unable to test for touch on the two rasters");
+               PG_RETURN_NULL();
+       }
+
+       PG_RETURN_BOOL(touches);
+}
+
 /**
  * See if two rasters are aligned
  */
index a4e36434af02c87a15e060bfb269f48b2096fc24..6a993e087835667af7f8cc91755085d02dc425dd 100644 (file)
@@ -3324,6 +3324,112 @@ CREATE OR REPLACE FUNCTION st_overlaps(geom geometry, rast raster, nband integer
        LANGUAGE 'sql' IMMUTABLE
        COST 1000;
 
+-----------------------------------------------------------------------
+-- ST_Touches(raster, raster)
+-----------------------------------------------------------------------
+
+CREATE OR REPLACE FUNCTION _st_touches(rast1 raster, nband1 integer, rast2 raster, nband2 integer)
+       RETURNS boolean
+       AS 'MODULE_PATHNAME', 'RASTER_touches'
+       LANGUAGE 'c' IMMUTABLE STRICT
+       COST 1000;
+
+CREATE OR REPLACE FUNCTION st_touches(rast1 raster, nband1 integer, rast2 raster, nband2 integer)
+       RETURNS boolean
+       AS $$ SELECT $1 && $3 AND CASE WHEN $2 IS NULL OR $4 IS NULL THEN st_touches(st_convexhull($1), st_convexhull($3)) ELSE _st_touches($1, $2, $3, $4) END $$
+       LANGUAGE 'sql' IMMUTABLE
+       COST 1000;
+
+CREATE OR REPLACE FUNCTION st_touches(rast1 raster, rast2 raster)
+       RETURNS boolean
+       AS $$ SELECT st_touches($1, NULL::integer, $2, NULL::integer) $$
+       LANGUAGE 'sql' IMMUTABLE
+       COST 1000;
+
+-----------------------------------------------------------------------
+-- ST_Touches(raster, geometry) in raster-space
+-----------------------------------------------------------------------
+
+CREATE OR REPLACE FUNCTION _st_touches(rast raster, geom geometry, nband integer DEFAULT NULL)
+       RETURNS boolean
+       AS $$
+       DECLARE
+               gr raster;
+               scale double precision;
+       BEGIN
+               IF ST_Touches(geom, ST_ConvexHull(rast)) IS NOT TRUE THEN
+                       RETURN FALSE;
+               ELSEIF nband IS NULL THEN
+                       RETURN TRUE;
+               END IF;
+
+               -- scale is set to 1/100th of raster for granularity
+               SELECT least(scalex, scaley) / 100. INTO scale FROM ST_Metadata(rast);
+               gr := _st_asraster(geom, scale, scale);
+               IF gr IS NULL THEN
+                       RAISE EXCEPTION 'Unable to convert geometry to a raster';
+                       RETURN FALSE;
+               END IF;
+
+               RETURN ST_Touches(rast, nband, gr, 1);
+       END;
+       $$ LANGUAGE 'plpgsql' IMMUTABLE
+       COST 1000;
+
+CREATE OR REPLACE FUNCTION st_touches(rast raster, geom geometry, nband integer DEFAULT NULL)
+       RETURNS boolean
+       AS $$ SELECT $1::geometry && $2 AND _st_touches($1, $2, $3) $$
+       LANGUAGE 'sql' IMMUTABLE
+       COST 1000;
+
+CREATE OR REPLACE FUNCTION st_touches(rast raster, nband integer, geom geometry)
+       RETURNS boolean
+       AS $$ SELECT $1::geometry && $3 AND _st_touches($1, $3, $2) $$
+       LANGUAGE 'sql' IMMUTABLE
+       COST 1000;
+
+-----------------------------------------------------------------------
+-- ST_Touches(geometry, raster) in geometry-space
+-----------------------------------------------------------------------
+
+-- This function can not be STRICT
+CREATE OR REPLACE FUNCTION _st_touches(geom geometry, rast raster, nband integer DEFAULT NULL)
+       RETURNS boolean AS $$
+       DECLARE
+               convexhull geometry;
+               hasnodata boolean := TRUE;
+               surface geometry;
+       BEGIN
+               convexhull := ST_ConvexHull(rast);
+               IF nband IS NOT NULL THEN
+                       SELECT CASE WHEN bmd.nodatavalue IS NULL THEN FALSE ELSE NULL END INTO hasnodata FROM ST_BandMetaData(rast, nband) AS bmd;
+               END IF;
+
+               IF ST_Touches(geom, convexhull) IS NOT TRUE THEN
+                       RETURN FALSE;
+               ELSEIF nband IS NULL OR hasnodata IS FALSE THEN
+                       RETURN TRUE;
+               END IF;
+
+               -- get band polygon
+               surface := ST_Polygon(rast, nband);
+
+               IF surface IS NOT NULL THEN
+                       RETURN ST_Touches(geom, surface);
+               END IF;
+
+               RETURN FALSE;
+       END;
+       $$ LANGUAGE 'plpgsql' IMMUTABLE
+       COST 1000;
+
+-- This function can not be STRICT
+CREATE OR REPLACE FUNCTION st_touches(geom geometry, rast raster, nband integer DEFAULT NULL)
+       RETURNS boolean AS
+       $$ SELECT $1 && $2::geometry AND _st_touches($1, $2, $3); $$
+       LANGUAGE 'sql' IMMUTABLE
+       COST 1000;
+
 -----------------------------------------------------------------------
 -- ST_Intersection(geometry, raster) in geometry-space
 -----------------------------------------------------------------------
index a9880e1d03996d6cc3fe43aca114244c61bd70cf..e14ed9b1e0c6b8f3034130901c2fd2394cb76802 100644 (file)
@@ -124,9 +124,9 @@ TEST_GIST = \
        drop_rt_gist_test
        
 TEST_SREL = \
-       rt_spatial_relationship \
        rt_intersects \
        rt_overlaps \
+       rt_touches \
        rt_samealignment
        
 TEST_BUGS = \
diff --git a/raster/test/regress/rt_touches.sql b/raster/test/regress/rt_touches.sql
new file mode 100644 (file)
index 0000000..9ebb1b7
--- /dev/null
@@ -0,0 +1,441 @@
+SET client_min_messages TO warning;
+
+DROP TABLE IF EXISTS raster_touches_rast;
+DROP TABLE IF EXISTS raster_touches_geom;
+CREATE TABLE raster_touches_rast (
+       rid integer,
+       rast raster
+);
+CREATE TABLE raster_touches_geom (
+       gid integer,
+       geom geometry
+);
+CREATE OR REPLACE FUNCTION make_test_raster(
+       rid integer,
+       width integer DEFAULT 2, height integer DEFAULT 2,
+       ul_x double precision DEFAULT 0, ul_y double precision DEFAULT 0,
+       skew_x double precision DEFAULT 0, skew_y double precision DEFAULT 0
+)
+       RETURNS void
+       AS $$
+       DECLARE
+               x int;
+               y int;
+               rast raster;
+       BEGIN
+               rast := ST_MakeEmptyRaster(width, height, ul_x, ul_y, 1, 1, skew_x, skew_y, 0);
+               rast := ST_AddBand(rast, 1, '8BUI', 1, 0);
+
+
+               INSERT INTO raster_touches_rast VALUES (rid, rast);
+
+               RETURN;
+       END;
+       $$ LANGUAGE 'plpgsql';
+SELECT make_test_raster(0, 2, 2, -1, -1);
+SELECT make_test_raster(1, 2, 2);
+SELECT make_test_raster(2, 3, 3);
+DROP FUNCTION make_test_raster(integer, integer, integer, double precision, double precision, double precision, double precision);
+
+INSERT INTO raster_touches_rast VALUES (10, (
+       SELECT
+               ST_SetValue(rast, 1, 1, 1, 0)
+       FROM raster_touches_rast
+       WHERE rid = 1
+));
+INSERT INTO raster_touches_rast VALUES (11, (
+       SELECT
+               ST_SetValue(rast, 1, 2, 1, 0)
+       FROM raster_touches_rast
+       WHERE rid = 1
+));
+INSERT INTO raster_touches_rast VALUES (12, (
+       SELECT
+               ST_SetValue(
+                       ST_SetValue(
+                               ST_SetValue(rast, 1, 1, 1, 0),
+                               1, 2, 1, 0
+                       ),
+                       1, 1, 2, 0
+               )
+       FROM raster_touches_rast
+       WHERE rid = 1
+));
+INSERT INTO raster_touches_rast VALUES (13, (
+       SELECT
+               ST_SetValue(
+                       ST_SetValue(
+                               ST_SetValue(
+                                       ST_SetValue(rast, 1, 1, 1, 0),
+                                       1, 2, 1, 0
+                               ),
+                               1, 1, 2, 0
+                       ),
+                       1, 2, 2, 0
+               )
+       FROM raster_touches_rast
+       WHERE rid = 1
+));
+INSERT INTO raster_touches_rast VALUES (14, (
+       SELECT
+               ST_SetUpperLeft(rast, 2, 0)
+       FROM raster_touches_rast
+       WHERE rid = 1
+));
+INSERT INTO raster_touches_rast VALUES (15, (
+       SELECT
+               ST_SetScale(
+                       ST_SetUpperLeft(rast, 0.1, 0.1),
+                       0.4, 0.4
+               )
+       FROM raster_touches_rast
+       WHERE rid = 1
+));
+INSERT INTO raster_touches_rast VALUES (16, (
+       SELECT
+               ST_SetScale(
+                       ST_SetUpperLeft(rast, -0.1, 0.1),
+                       0.4, 0.4
+               )
+       FROM raster_touches_rast
+       WHERE rid = 1
+));
+
+INSERT INTO raster_touches_rast VALUES (20, (
+       SELECT
+               ST_SetUpperLeft(rast, -2, -2)
+       FROM raster_touches_rast
+       WHERE rid = 2
+));
+INSERT INTO raster_touches_rast VALUES (21, (
+       SELECT
+               ST_SetValue(
+                       ST_SetValue(
+                               ST_SetValue(rast, 1, 1, 1, 0),
+                               1, 2, 2, 0
+                       ),
+                       1, 3, 3, 0
+               )
+       FROM raster_touches_rast
+       WHERE rid = 20
+));
+INSERT INTO raster_touches_rast VALUES (22, (
+       SELECT
+               ST_SetValue(
+                       ST_SetValue(
+                               rast, 1, 3, 2, 0
+                       ),
+                       1, 2, 3, 0
+               )
+       FROM raster_touches_rast
+       WHERE rid = 21
+));
+INSERT INTO raster_touches_rast VALUES (23, (
+       SELECT
+               ST_SetValue(
+                       ST_SetValue(
+                               rast, 1, 3, 1, 0
+                       ),
+                       1, 1, 3, 0
+               )
+       FROM raster_touches_rast
+       WHERE rid = 22
+));
+
+INSERT INTO raster_touches_rast VALUES (30, (
+       SELECT
+               ST_SetSkew(rast, -0.5, 0.5)
+       FROM raster_touches_rast
+       WHERE rid = 2
+));
+INSERT INTO raster_touches_rast VALUES (31, (
+       SELECT
+               ST_SetSkew(rast, -1, 1)
+       FROM raster_touches_rast
+       WHERE rid = 2
+));
+INSERT INTO raster_touches_rast VALUES (32, (
+       SELECT
+               ST_SetSkew(rast, 1, -1)
+       FROM raster_touches_rast
+       WHERE rid = 2
+));
+
+SELECT
+       '1.1',
+       r1.rid,
+       r2.rid,
+       ST_Touches(r1.rast, NULL, r2.rast, NULL)
+FROM raster_touches_rast r1
+JOIN raster_touches_rast r2
+       ON r1.rid != r2.rid
+WHERE r1.rid = 0;
+
+SELECT
+       '1.2',
+       r1.rid,
+       r2.rid,
+       ST_Touches(r1.rast, 1, r2.rast, 1)
+FROM raster_touches_rast r1
+JOIN raster_touches_rast r2
+       ON r1.rid != r2.rid
+WHERE r1.rid = 0;
+
+-- point
+INSERT INTO raster_touches_geom VALUES (
+       1, (
+               SELECT ST_SetSRID(ST_MakePoint(0, 0), 0)
+       )
+), (
+       2, (
+               SELECT ST_SetSRID(ST_MakePoint(0.1, 0.1), 0)
+       )
+), (
+       3, (
+               SELECT ST_SetSRID(ST_MakePoint(-0.1, -0.1), 0)
+       )
+), (
+       4, (
+               SELECT ST_SetSRID(ST_MakePoint(-1, -1), 0)
+       )
+), (
+       5, (
+               SELECT ST_SetSRID(ST_MakePoint(-1.1, -1), 0)
+       )
+), (
+       6, (
+               SELECT ST_SetSRID(ST_MakePoint(-1, -1.1), 0)
+       )
+), (
+       7, (
+               SELECT ST_SetSRID(ST_MakePoint(-1.5, -1.5), 0)
+       )
+), (
+       8, (
+               SELECT ST_SetSRID(ST_MakePoint(3, 3), 0)
+       )
+);
+
+-- multipoint
+INSERT INTO raster_touches_geom VALUES (
+       11, (
+               SELECT ST_Collect(geom) FROM raster_touches_geom WHERE gid BETWEEN 1 AND 10
+       )
+), (
+       12, (
+               SELECT ST_Collect(geom) FROM raster_touches_geom WHERE gid BETWEEN 3 AND 10
+       )
+), (
+       13, (
+               SELECT ST_Collect(geom) FROM raster_touches_geom WHERE gid BETWEEN 4 AND 10
+       )
+), (
+       14, (
+               SELECT ST_Collect(geom) FROM raster_touches_geom WHERE gid BETWEEN 5 AND 10
+       )
+), (
+       15, (
+               SELECT ST_Collect(geom) FROM raster_touches_geom WHERE gid BETWEEN 6 AND 10
+       )
+);
+
+-- linestring
+INSERT INTO raster_touches_geom VALUES (
+       21, (
+               SELECT ST_SetSRID(ST_MakeLine(ARRAY[
+                       ST_MakePoint(1, 1),
+                       ST_MakePoint(1, 0)
+               ]), 0)
+       )
+), (
+       22, (
+               SELECT ST_SetSRID(ST_MakeLine(ARRAY[
+                       ST_MakePoint(-1, -1),
+                       ST_MakePoint(1, 1),
+                       ST_MakePoint(1, 0)
+               ]), 0)
+       )
+), (
+       23, (
+               SELECT ST_SetSRID(ST_MakeLine(ARRAY[
+                       ST_MakePoint(-1, -1),
+                       ST_MakePoint(-1, 1),
+                       ST_MakePoint(1, 1),
+                       ST_MakePoint(1, -1)
+               ]), 0)
+       )
+), (
+       24, (
+               SELECT ST_SetSRID(ST_MakeLine(ARRAY[
+                       ST_MakePoint(-1.1, 1.1),
+                       ST_MakePoint(1.1, 1.1),
+                       ST_MakePoint(1.1, -1.1),
+                       ST_MakePoint(-1.1, -1.1),
+                       ST_MakePoint(-1.1, 1.1)
+               ]), 0)
+       )
+), (
+       25, (
+               SELECT ST_SetSRID(ST_MakeLine(ARRAY[
+                       ST_MakePoint(-2, 1),
+                       ST_MakePoint(1, 2),
+                       ST_MakePoint(2, -1),
+                       ST_MakePoint(-1, -2),
+                       ST_MakePoint(-2, 1)
+               ]), 0)
+       )
+), (
+       26, (
+               SELECT ST_SetSRID(ST_MakeLine(ARRAY[
+                       ST_MakePoint(-0.5, 0.5),
+                       ST_MakePoint(0, 0.5),
+                       ST_MakePoint(0, 0),
+                       ST_MakePoint(0, -0.5),
+                       ST_MakePoint(-0.5, 0.5)
+               ]), 0)
+       )
+), (
+       27, (
+               SELECT ST_SetSRID(ST_MakeLine(ARRAY[
+                       ST_MakePoint(0.5, 0.5),
+                       ST_MakePoint(1, 1),
+                       ST_MakePoint(1, 0),
+                       ST_MakePoint(0.5, 0.5)
+               ]), 0)
+       )
+), (
+       28, (
+               SELECT ST_SetSRID(ST_MakeLine(ARRAY[
+                       ST_MakePoint(1, 1),
+                       ST_MakePoint(0, 2),
+                       ST_MakePoint(1, 2),
+                       ST_MakePoint(1, 1)
+               ]), 0)
+       )
+), (
+       29, (
+               SELECT ST_SetSRID(ST_MakeLine(ARRAY[
+                       ST_MakePoint(0, 2),
+                       ST_MakePoint(1, 2),
+                       ST_MakePoint(1, 4),
+                       ST_MakePoint(0, 2)
+               ]), 0)
+       )
+);
+
+-- polygon
+INSERT INTO raster_touches_geom VALUES (
+       31, (
+               SELECT ST_MakePolygon(geom) FROM raster_touches_geom WHERE gid = 24
+       )
+), (
+       32, (
+               SELECT ST_MakePolygon(geom) FROM raster_touches_geom WHERE gid = 25
+       )
+), (
+       33, (
+               SELECT ST_MakePolygon(geom) FROM raster_touches_geom WHERE gid = 26
+       )
+), (
+       34, (
+               SELECT ST_MakePolygon(geom) FROM raster_touches_geom WHERE gid = 27
+       )
+), (
+       35, (
+               SELECT ST_MakePolygon(geom) FROM raster_touches_geom WHERE gid = 28
+       )
+), (
+       36, (
+               SELECT ST_MakePolygon(geom) FROM raster_touches_geom WHERE gid = 29
+       )
+);
+
+-- multipolygon
+INSERT INTO raster_touches_geom VALUES (
+       41, (
+               SELECT ST_Multi(ST_Union(geom)) FROM raster_touches_geom WHERE gid BETWEEN 31 and 40
+       )
+), (
+       42, (
+               SELECT ST_Multi(ST_Union(geom)) FROM raster_touches_geom WHERE gid BETWEEN 32 and 40
+       )
+), (
+       43, (
+               SELECT ST_Multi(ST_Union(geom)) FROM raster_touches_geom WHERE gid BETWEEN 33 and 40
+       )
+), (
+       44, (
+               SELECT ST_Multi(ST_Union(geom)) FROM raster_touches_geom WHERE gid BETWEEN 34 and 40
+       )
+), (
+       45, (
+               SELECT ST_Multi(ST_Union(geom)) FROM raster_touches_geom WHERE gid BETWEEN 35 and 40
+       )
+), (
+       46, (
+               SELECT ST_Multi(ST_Union(geom)) FROM raster_touches_geom WHERE gid BETWEEN 36 and 40
+       )
+);
+
+SELECT
+       '2.1',
+       r1.rid,
+       g1.gid,
+       ST_GeometryType(g1.geom),
+       ST_Touches(r1.rast, g1.geom)
+FROM raster_touches_rast r1
+CROSS JOIN raster_touches_geom g1
+WHERE r1.rid = 0;
+
+SELECT
+       '2.2',
+       r1.rid,
+       g1.gid,
+       ST_GeometryType(g1.geom),
+       ST_Touches(g1.geom, r1.rast)
+FROM raster_touches_rast r1
+CROSS JOIN raster_touches_geom g1
+WHERE r1.rid = 0;
+
+SELECT
+       '2.3',
+       r1.rid,
+       g1.gid,
+       ST_GeometryType(g1.geom),
+       ST_Touches(r1.rast, g1.geom)
+FROM raster_touches_rast r1
+CROSS JOIN raster_touches_geom g1
+WHERE r1.rid = 2;
+
+SELECT
+       '2.4',
+       r1.rid,
+       g1.gid,
+       ST_GeometryType(g1.geom),
+       ST_Touches(g1.geom, r1.rast)
+FROM raster_touches_rast r1
+CROSS JOIN raster_touches_geom g1
+WHERE r1.rid = 2;
+
+SELECT
+       '2.5',
+       r1.rid,
+       g1.gid,
+       ST_GeometryType(g1.geom),
+       ST_Touches(r1.rast, g1.geom, 1)
+FROM raster_touches_rast r1
+CROSS JOIN raster_touches_geom g1
+WHERE r1.rid = 0;
+
+SELECT
+       '2.6',
+       r1.rid,
+       g1.gid,
+       ST_GeometryType(g1.geom),
+       ST_Touches(r1.rast, g1.geom, 1)
+FROM raster_touches_rast r1
+CROSS JOIN raster_touches_geom g1
+WHERE r1.rid = 2;
+
+DROP TABLE IF EXISTS raster_touches_rast;
+DROP TABLE IF EXISTS raster_touches_geom;
diff --git a/raster/test/regress/rt_touches_expected b/raster/test/regress/rt_touches_expected
new file mode 100644 (file)
index 0000000..4279a18
--- /dev/null
@@ -0,0 +1,236 @@
+1.1|0|1|f
+1.1|0|2|f
+1.1|0|10|f
+1.1|0|11|f
+1.1|0|12|f
+1.1|0|13|f
+1.1|0|14|f
+1.1|0|15|f
+1.1|0|16|f
+1.1|0|20|f
+1.1|0|21|f
+1.1|0|22|f
+1.1|0|23|f
+1.1|0|30|f
+1.1|0|31|f
+1.1|0|32|f
+1.2|0|1|f
+1.2|0|2|f
+1.2|0|10|t
+1.2|0|11|f
+1.2|0|12|t
+1.2|0|13|f
+1.2|0|14|f
+1.2|0|15|f
+1.2|0|16|f
+1.2|0|20|f
+1.2|0|21|f
+1.2|0|22|t
+1.2|0|23|t
+1.2|0|30|f
+1.2|0|31|f
+1.2|0|32|f
+2.1|0|1|ST_Point|f
+2.1|0|2|ST_Point|f
+2.1|0|3|ST_Point|f
+2.1|0|4|ST_Point|t
+2.1|0|5|ST_Point|f
+2.1|0|6|ST_Point|f
+2.1|0|7|ST_Point|f
+2.1|0|8|ST_Point|f
+2.1|0|11|ST_MultiPoint|f
+2.1|0|12|ST_MultiPoint|f
+2.1|0|13|ST_MultiPoint|t
+2.1|0|14|ST_MultiPoint|f
+2.1|0|15|ST_MultiPoint|f
+2.1|0|21|ST_LineString|t
+2.1|0|22|ST_LineString|f
+2.1|0|23|ST_LineString|t
+2.1|0|24|ST_LineString|f
+2.1|0|25|ST_LineString|f
+2.1|0|26|ST_LineString|f
+2.1|0|27|ST_LineString|f
+2.1|0|28|ST_LineString|t
+2.1|0|29|ST_LineString|f
+2.1|0|31|ST_Polygon|f
+2.1|0|32|ST_Polygon|f
+2.1|0|33|ST_Polygon|f
+2.1|0|34|ST_Polygon|f
+2.1|0|35|ST_Polygon|t
+2.1|0|36|ST_Polygon|f
+2.1|0|41|ST_MultiPolygon|f
+2.1|0|42|ST_MultiPolygon|f
+2.1|0|43|ST_MultiPolygon|f
+2.1|0|44|ST_MultiPolygon|f
+2.1|0|45|ST_MultiPolygon|t
+2.1|0|46|ST_MultiPolygon|f
+2.2|0|1|ST_Point|f
+2.2|0|2|ST_Point|f
+2.2|0|3|ST_Point|f
+2.2|0|4|ST_Point|t
+2.2|0|5|ST_Point|f
+2.2|0|6|ST_Point|f
+2.2|0|7|ST_Point|f
+2.2|0|8|ST_Point|f
+2.2|0|11|ST_MultiPoint|f
+2.2|0|12|ST_MultiPoint|f
+2.2|0|13|ST_MultiPoint|t
+2.2|0|14|ST_MultiPoint|f
+2.2|0|15|ST_MultiPoint|f
+2.2|0|21|ST_LineString|t
+2.2|0|22|ST_LineString|f
+2.2|0|23|ST_LineString|t
+2.2|0|24|ST_LineString|f
+2.2|0|25|ST_LineString|f
+2.2|0|26|ST_LineString|f
+2.2|0|27|ST_LineString|f
+2.2|0|28|ST_LineString|t
+2.2|0|29|ST_LineString|f
+2.2|0|31|ST_Polygon|f
+2.2|0|32|ST_Polygon|f
+2.2|0|33|ST_Polygon|f
+2.2|0|34|ST_Polygon|f
+2.2|0|35|ST_Polygon|t
+2.2|0|36|ST_Polygon|f
+2.2|0|41|ST_MultiPolygon|f
+2.2|0|42|ST_MultiPolygon|f
+2.2|0|43|ST_MultiPolygon|f
+2.2|0|44|ST_MultiPolygon|f
+2.2|0|45|ST_MultiPolygon|t
+2.2|0|46|ST_MultiPolygon|f
+2.3|2|1|ST_Point|t
+2.3|2|2|ST_Point|f
+2.3|2|3|ST_Point|f
+2.3|2|4|ST_Point|f
+2.3|2|5|ST_Point|f
+2.3|2|6|ST_Point|f
+2.3|2|7|ST_Point|f
+2.3|2|8|ST_Point|t
+2.3|2|11|ST_MultiPoint|f
+2.3|2|12|ST_MultiPoint|t
+2.3|2|13|ST_MultiPoint|t
+2.3|2|14|ST_MultiPoint|t
+2.3|2|15|ST_MultiPoint|t
+2.3|2|21|ST_LineString|f
+2.3|2|22|ST_LineString|f
+2.3|2|23|ST_LineString|f
+2.3|2|24|ST_LineString|f
+2.3|2|25|ST_LineString|f
+2.3|2|26|ST_LineString|t
+2.3|2|27|ST_LineString|f
+2.3|2|28|ST_LineString|f
+2.3|2|29|ST_LineString|f
+2.3|2|31|ST_Polygon|f
+2.3|2|32|ST_Polygon|f
+2.3|2|33|ST_Polygon|t
+2.3|2|34|ST_Polygon|f
+2.3|2|35|ST_Polygon|f
+2.3|2|36|ST_Polygon|f
+2.3|2|41|ST_MultiPolygon|f
+2.3|2|42|ST_MultiPolygon|f
+2.3|2|43|ST_MultiPolygon|f
+2.3|2|44|ST_MultiPolygon|f
+2.3|2|45|ST_MultiPolygon|f
+2.3|2|46|ST_MultiPolygon|f
+2.4|2|1|ST_Point|t
+2.4|2|2|ST_Point|f
+2.4|2|3|ST_Point|f
+2.4|2|4|ST_Point|f
+2.4|2|5|ST_Point|f
+2.4|2|6|ST_Point|f
+2.4|2|7|ST_Point|f
+2.4|2|8|ST_Point|t
+2.4|2|11|ST_MultiPoint|f
+2.4|2|12|ST_MultiPoint|t
+2.4|2|13|ST_MultiPoint|t
+2.4|2|14|ST_MultiPoint|t
+2.4|2|15|ST_MultiPoint|t
+2.4|2|21|ST_LineString|f
+2.4|2|22|ST_LineString|f
+2.4|2|23|ST_LineString|f
+2.4|2|24|ST_LineString|f
+2.4|2|25|ST_LineString|f
+2.4|2|26|ST_LineString|t
+2.4|2|27|ST_LineString|f
+2.4|2|28|ST_LineString|f
+2.4|2|29|ST_LineString|f
+2.4|2|31|ST_Polygon|f
+2.4|2|32|ST_Polygon|f
+2.4|2|33|ST_Polygon|t
+2.4|2|34|ST_Polygon|f
+2.4|2|35|ST_Polygon|f
+2.4|2|36|ST_Polygon|f
+2.4|2|41|ST_MultiPolygon|f
+2.4|2|42|ST_MultiPolygon|f
+2.4|2|43|ST_MultiPolygon|f
+2.4|2|44|ST_MultiPolygon|f
+2.4|2|45|ST_MultiPolygon|f
+2.4|2|46|ST_MultiPolygon|f
+2.5|0|1|ST_Point|f
+2.5|0|2|ST_Point|f
+2.5|0|3|ST_Point|f
+2.5|0|4|ST_Point|f
+2.5|0|5|ST_Point|f
+2.5|0|6|ST_Point|f
+2.5|0|7|ST_Point|f
+2.5|0|8|ST_Point|f
+2.5|0|11|ST_MultiPoint|f
+2.5|0|12|ST_MultiPoint|f
+2.5|0|13|ST_MultiPoint|f
+2.5|0|14|ST_MultiPoint|f
+2.5|0|15|ST_MultiPoint|f
+2.5|0|21|ST_LineString|f
+2.5|0|22|ST_LineString|f
+2.5|0|23|ST_LineString|f
+2.5|0|24|ST_LineString|f
+2.5|0|25|ST_LineString|f
+2.5|0|26|ST_LineString|f
+2.5|0|27|ST_LineString|f
+2.5|0|28|ST_LineString|f
+2.5|0|29|ST_LineString|f
+2.5|0|31|ST_Polygon|f
+2.5|0|32|ST_Polygon|f
+2.5|0|33|ST_Polygon|f
+2.5|0|34|ST_Polygon|f
+2.5|0|35|ST_Polygon|f
+2.5|0|36|ST_Polygon|f
+2.5|0|41|ST_MultiPolygon|f
+2.5|0|42|ST_MultiPolygon|f
+2.5|0|43|ST_MultiPolygon|f
+2.5|0|44|ST_MultiPolygon|f
+2.5|0|45|ST_MultiPolygon|f
+2.5|0|46|ST_MultiPolygon|f
+2.6|2|1|ST_Point|f
+2.6|2|2|ST_Point|f
+2.6|2|3|ST_Point|f
+2.6|2|4|ST_Point|f
+2.6|2|5|ST_Point|f
+2.6|2|6|ST_Point|f
+2.6|2|7|ST_Point|f
+2.6|2|8|ST_Point|f
+2.6|2|11|ST_MultiPoint|f
+2.6|2|12|ST_MultiPoint|f
+2.6|2|13|ST_MultiPoint|f
+2.6|2|14|ST_MultiPoint|f
+2.6|2|15|ST_MultiPoint|f
+2.6|2|21|ST_LineString|f
+2.6|2|22|ST_LineString|f
+2.6|2|23|ST_LineString|f
+2.6|2|24|ST_LineString|f
+2.6|2|25|ST_LineString|f
+2.6|2|26|ST_LineString|f
+2.6|2|27|ST_LineString|f
+2.6|2|28|ST_LineString|f
+2.6|2|29|ST_LineString|f
+2.6|2|31|ST_Polygon|f
+2.6|2|32|ST_Polygon|f
+2.6|2|33|ST_Polygon|t
+2.6|2|34|ST_Polygon|f
+2.6|2|35|ST_Polygon|f
+2.6|2|36|ST_Polygon|f
+2.6|2|41|ST_MultiPolygon|f
+2.6|2|42|ST_MultiPolygon|f
+2.6|2|43|ST_MultiPolygon|f
+2.6|2|44|ST_MultiPolygon|f
+2.6|2|45|ST_MultiPolygon|f
+2.6|2|46|ST_MultiPolygon|f