Reintroduced ST_Intersects(geometry, raster) and ST_Intersects(raster,

geometry).  Added notes regarding the use of ST_Polygon when needing to
test the spatial relationship between a raster and a geometry.

git-svn-id: http://svn.osgeo.org/postgis/trunk@10095 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
Bborie Park 2012-07-23 17:49:57 +00:00
parent 9e9beba0c8
commit 743417d895
4 changed files with 715 additions and 4 deletions

View file

@ -8764,6 +8764,54 @@ a_rid | b_rid | overleft
</paramdef> </paramdef>
</funcprototype> </funcprototype>
<funcprototype>
<funcdef>boolean <function>ST_Intersects</function></funcdef>
<paramdef>
<type>raster </type>
<parameter>rast</parameter>
</paramdef>
<paramdef>
<type>integer </type>
<parameter>nband</parameter>
</paramdef>
<paramdef>
<type>geometry </type>
<parameter>geommin</parameter>
</paramdef>
</funcprototype>
<funcprototype>
<funcdef>boolean <function>ST_Intersects</function></funcdef>
<paramdef>
<type>raster </type>
<parameter>rast</parameter>
</paramdef>
<paramdef>
<type>geometry </type>
<parameter>geommin</parameter>
</paramdef>
<paramdef choice='opt'>
<type>integer </type>
<parameter>nband=NULL</parameter>
</paramdef>
</funcprototype>
<funcprototype>
<funcdef>boolean <function>ST_Intersects</function></funcdef>
<paramdef>
<type>geometry </type>
<parameter>geommin</parameter>
</paramdef>
<paramdef>
<type>raster </type>
<parameter>rast</parameter>
</paramdef>
<paramdef choice='opt'>
<type>integer </type>
<parameter>nband=NULL</parameter>
</paramdef>
</funcprototype>
</funcsynopsis> </funcsynopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -8786,7 +8834,7 @@ a_rid | b_rid | overleft
<warning> <warning>
<para> <para>
Changed: The ST_Intersects(raster, geometry) and ST_Intersects(geometry, raster) variants present before PostGIS 2.1.0 have been removed. Use ST_Intersects(ST_Polygon(raster), geometry) instead. Changed: In 2.1.0, the behavior of the ST_Intersects(raster, geometry) variants changed to match that of ST_Intersects(geometry, raster).
</para> </para>
</warning> </warning>
@ -8864,6 +8912,12 @@ a_rid | b_rid | overleft
This operand will make use of any indexes that may be available on the rasters. This operand will make use of any indexes that may be available on the rasters.
</para> </para>
</note> </note>
<note>
<para>
To test the spatial relationship of a raster and a geometry, use ST_Polygon on the raster, e.g. ST_Overlaps(ST_Polygon(raster), geometry).
</para>
</note>
<para>Availability: 2.1.0</para> <para>Availability: 2.1.0</para>
</refsection> </refsection>
@ -8940,7 +8994,13 @@ a_rid | b_rid | overleft
This operand will make use of any indexes that may be available on the rasters. This operand will make use of any indexes that may be available on the rasters.
</para> </para>
</note> </note>
<note>
<para>
To test the spatial relationship of a raster and a geometry, use ST_Polygon on the raster, e.g. ST_Touches(ST_Polygon(raster), geometry).
</para>
</note>
<para>Availability: 2.1.0</para> <para>Availability: 2.1.0</para>
</refsection> </refsection>
@ -9016,7 +9076,13 @@ a_rid | b_rid | overleft
This operand will make use of any indexes that may be available on the rasters. This operand will make use of any indexes that may be available on the rasters.
</para> </para>
</note> </note>
<note>
<para>
To test the spatial relationship of a raster and a geometry, use ST_Polygon on the raster, e.g. ST_Contains(ST_Polygon(raster), geometry) or ST_Contains(geometry, ST_Polygon(raster)).
</para>
</note>
<para>Availability: 2.1.0</para> <para>Availability: 2.1.0</para>
</refsection> </refsection>

View file

@ -3134,6 +3134,162 @@ CREATE OR REPLACE FUNCTION st_intersects(rast1 raster, rast2 raster)
LANGUAGE 'sql' IMMUTABLE LANGUAGE 'sql' IMMUTABLE
COST 1000; COST 1000;
-----------------------------------------------------------------------
-- ST_Intersects(geometry, raster)
-----------------------------------------------------------------------
-- This function can not be STRICT
CREATE OR REPLACE FUNCTION _st_intersects(geom geometry, rast raster, nband integer DEFAULT NULL)
RETURNS boolean AS $$
DECLARE
hasnodata boolean := TRUE;
nodata float8 := 0.0;
convexhull geometry;
geomintersect geometry;
x1w double precision := 0.0;
x2w double precision := 0.0;
y1w double precision := 0.0;
y2w double precision := 0.0;
x1 integer := 0;
x2 integer := 0;
x3 integer := 0;
x4 integer := 0;
y1 integer := 0;
y2 integer := 0;
y3 integer := 0;
y4 integer := 0;
x integer := 0;
y integer := 0;
xinc integer := 0;
yinc integer := 0;
pixelval double precision;
bintersect boolean := FALSE;
gtype text;
scale float8;
w int;
h int;
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_Intersects(geom, convexhull) IS NOT TRUE THEN
RETURN FALSE;
ELSEIF nband IS NULL OR hasnodata IS FALSE THEN
RETURN TRUE;
END IF;
-- Get the intersection between with the geometry.
-- We will search for withvalue pixel only in this area.
geomintersect := st_intersection(geom, convexhull);
--RAISE NOTICE 'geomintersect=%', st_astext(geomintersect);
-- If the intersection is empty, return false
IF st_isempty(geomintersect) THEN
RETURN FALSE;
END IF;
-- We create a minimalistic buffer around the intersection in order to scan every pixels
-- that would touch the edge or intersect with the geometry
SELECT sqrt(scalex * scalex + skewy * skewy), width, height INTO scale, w, h FROM ST_Metadata(rast);
IF scale != 0 THEN
geomintersect := st_buffer(geomintersect, scale / 1000000);
END IF;
--RAISE NOTICE 'geomintersect2=%', st_astext(geomintersect);
-- Find the world coordinates of the bounding box of the intersecting area
x1w := st_xmin(geomintersect);
y1w := st_ymin(geomintersect);
x2w := st_xmax(geomintersect);
y2w := st_ymax(geomintersect);
nodata := st_bandnodatavalue(rast, nband);
--RAISE NOTICE 'x1w=%, y1w=%, x2w=%, y2w=%', x1w, y1w, x2w, y2w;
-- Convert world coordinates to raster coordinates
x1 := st_world2rastercoordx(rast, x1w, y1w);
y1 := st_world2rastercoordy(rast, x1w, y1w);
x2 := st_world2rastercoordx(rast, x2w, y1w);
y2 := st_world2rastercoordy(rast, x2w, y1w);
x3 := st_world2rastercoordx(rast, x1w, y2w);
y3 := st_world2rastercoordy(rast, x1w, y2w);
x4 := st_world2rastercoordx(rast, x2w, y2w);
y4 := st_world2rastercoordy(rast, x2w, y2w);
--RAISE NOTICE 'x1=%, y1=%, x2=%, y2=%, x3=%, y3=%, x4=%, y4=%', x1, y1, x2, y2, x3, y3, x4, y4;
-- Order the raster coordinates for the upcoming FOR loop.
x1 := int4smaller(int4smaller(int4smaller(x1, x2), x3), x4);
y1 := int4smaller(int4smaller(int4smaller(y1, y2), y3), y4);
x2 := int4larger(int4larger(int4larger(x1, x2), x3), x4);
y2 := int4larger(int4larger(int4larger(y1, y2), y3), y4);
-- Make sure the range is not lower than 1.
-- This can happen when world coordinate are exactly on the left border
-- of the raster and that they do not span on more than one pixel.
x1 := int4smaller(int4larger(x1, 1), w);
y1 := int4smaller(int4larger(y1, 1), h);
-- Also make sure the range does not exceed the width and height of the raster.
-- This can happen when world coordinate are exactly on the lower right border
-- of the raster.
x2 := int4smaller(x2, w);
y2 := int4smaller(y2, h);
--RAISE NOTICE 'x1=%, y1=%, x2=%, y2=%', x1, y1, x2, y2;
-- Search exhaustively for withvalue pixel on a moving 3x3 grid
-- (very often more efficient than searching on a mere 1x1 grid)
FOR xinc in 0..2 LOOP
FOR yinc in 0..2 LOOP
FOR x IN x1+xinc..x2 BY 3 LOOP
FOR y IN y1+yinc..y2 BY 3 LOOP
-- Check first if the pixel intersects with the geometry. Often many won't.
bintersect := NOT st_isempty(st_intersection(st_pixelaspolygon(rast, x, y), geom));
IF bintersect THEN
-- If the pixel really intersects, check its value. Return TRUE if with value.
pixelval := st_value(rast, nband, x, y);
IF pixelval != nodata THEN
RETURN TRUE;
END IF;
END IF;
END LOOP;
END LOOP;
END LOOP;
END LOOP;
RETURN FALSE;
END;
$$ LANGUAGE 'plpgsql' IMMUTABLE
COST 1000;
-- This function can not be STRICT
CREATE OR REPLACE FUNCTION st_intersects(geom geometry, rast raster, nband integer DEFAULT NULL)
RETURNS boolean AS
$$ SELECT $1 && $2::geometry AND _st_intersects($1, $2, $3); $$
LANGUAGE 'sql' IMMUTABLE
COST 1000;
-----------------------------------------------------------------------
-- ST_Intersects(raster, geometry)
-----------------------------------------------------------------------
CREATE OR REPLACE FUNCTION st_intersects(rast raster, geom geometry, nband integer DEFAULT NULL)
RETURNS boolean
AS $$ SELECT $1::geometry && $2 AND _st_intersects($2, $1, $3) $$
LANGUAGE 'sql' IMMUTABLE
COST 1000;
CREATE OR REPLACE FUNCTION st_intersects(rast raster, nband integer, geom geometry)
RETURNS boolean
AS $$ SELECT $1::geometry && $3 AND _st_intersects($3, $1, $2) $$
LANGUAGE 'sql' IMMUTABLE
COST 1000;
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- ST_Overlaps(raster, raster) -- ST_Overlaps(raster, raster)
----------------------------------------------------------------------- -----------------------------------------------------------------------
@ -3200,6 +3356,28 @@ CREATE OR REPLACE FUNCTION st_contains(rast1 raster, rast2 raster)
LANGUAGE 'sql' IMMUTABLE LANGUAGE 'sql' IMMUTABLE
COST 1000; COST 1000;
-----------------------------------------------------------------------
-- ST_Within(raster, raster)
-----------------------------------------------------------------------
CREATE OR REPLACE FUNCTION _st_within(rast1 raster, nband1 integer, rast2 raster, nband2 integer)
RETURNS boolean
AS $$ SELECT _st_contains($3, $4, $1, $2) $$
LANGUAGE 'sql' IMMUTABLE
COST 1000;
CREATE OR REPLACE FUNCTION st_within(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_within(st_convexhull($1), st_convexhull($3)) ELSE _st_contains($3, $4, $1, $2) END $$
LANGUAGE 'sql' IMMUTABLE
COST 1000;
CREATE OR REPLACE FUNCTION st_within(rast1 raster, rast2 raster)
RETURNS boolean
AS $$ SELECT st_within($1, NULL::integer, $2, NULL::integer) $$
LANGUAGE 'sql' IMMUTABLE
COST 1000;
----------------------------------------------------------------------- -----------------------------------------------------------------------
-- ST_Intersection(geometry, raster) in geometry-space -- ST_Intersection(geometry, raster) in geometry-space
----------------------------------------------------------------------- -----------------------------------------------------------------------

View file

@ -1,8 +1,15 @@
SET client_min_messages TO warning;
DROP TABLE IF EXISTS raster_intersects_rast; DROP TABLE IF EXISTS raster_intersects_rast;
DROP TABLE IF EXISTS raster_intersects_geom;
CREATE TABLE raster_intersects_rast ( CREATE TABLE raster_intersects_rast (
rid integer, rid integer,
rast raster rast raster
); );
CREATE TABLE raster_intersects_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) 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 RETURNS void
AS $$ AS $$
@ -169,4 +176,261 @@ JOIN raster_intersects_rast r2
ON r1.rid != r2.rid ON r1.rid != r2.rid
WHERE r1.rid = 0; WHERE r1.rid = 0;
-- point
INSERT INTO raster_intersects_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_intersects_geom VALUES (
11, (
SELECT ST_Collect(geom) FROM raster_intersects_geom WHERE gid BETWEEN 1 AND 10
)
), (
12, (
SELECT ST_Collect(geom) FROM raster_intersects_geom WHERE gid BETWEEN 3 AND 10
)
), (
13, (
SELECT ST_Collect(geom) FROM raster_intersects_geom WHERE gid BETWEEN 4 AND 10
)
), (
14, (
SELECT ST_Collect(geom) FROM raster_intersects_geom WHERE gid BETWEEN 5 AND 10
)
), (
15, (
SELECT ST_Collect(geom) FROM raster_intersects_geom WHERE gid BETWEEN 6 AND 10
)
);
-- linestring
INSERT INTO raster_intersects_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_intersects_geom VALUES (
31, (
SELECT ST_MakePolygon(geom) FROM raster_intersects_geom WHERE gid = 24
)
), (
32, (
SELECT ST_MakePolygon(geom) FROM raster_intersects_geom WHERE gid = 25
)
), (
33, (
SELECT ST_MakePolygon(geom) FROM raster_intersects_geom WHERE gid = 26
)
), (
34, (
SELECT ST_MakePolygon(geom) FROM raster_intersects_geom WHERE gid = 27
)
), (
35, (
SELECT ST_MakePolygon(geom) FROM raster_intersects_geom WHERE gid = 28
)
), (
36, (
SELECT ST_MakePolygon(geom) FROM raster_intersects_geom WHERE gid = 29
)
);
-- multipolygon
INSERT INTO raster_intersects_geom VALUES (
41, (
SELECT ST_Multi(ST_Union(geom)) FROM raster_intersects_geom WHERE gid BETWEEN 31 and 40
)
), (
42, (
SELECT ST_Multi(ST_Union(geom)) FROM raster_intersects_geom WHERE gid BETWEEN 32 and 40
)
), (
43, (
SELECT ST_Multi(ST_Union(geom)) FROM raster_intersects_geom WHERE gid BETWEEN 33 and 40
)
), (
44, (
SELECT ST_Multi(ST_Union(geom)) FROM raster_intersects_geom WHERE gid BETWEEN 34 and 40
)
), (
45, (
SELECT ST_Multi(ST_Union(geom)) FROM raster_intersects_geom WHERE gid BETWEEN 35 and 40
)
), (
46, (
SELECT ST_Multi(ST_Union(geom)) FROM raster_intersects_geom WHERE gid BETWEEN 36 and 40
)
);
SELECT
'2.1',
r1.rid,
g1.gid,
ST_GeometryType(g1.geom),
ST_Intersects(r1.rast, g1.geom)
FROM raster_intersects_rast r1
CROSS JOIN raster_intersects_geom g1
WHERE r1.rid = 0;
SELECT
'2.2',
r1.rid,
g1.gid,
ST_GeometryType(g1.geom),
ST_Intersects(g1.geom, r1.rast)
FROM raster_intersects_rast r1
CROSS JOIN raster_intersects_geom g1
WHERE r1.rid = 0;
SELECT
'2.3',
r1.rid,
g1.gid,
ST_GeometryType(g1.geom),
ST_Intersects(r1.rast, g1.geom)
FROM raster_intersects_rast r1
CROSS JOIN raster_intersects_geom g1
WHERE r1.rid = 2;
SELECT
'2.4',
r1.rid,
g1.gid,
ST_GeometryType(g1.geom),
ST_Intersects(g1.geom, r1.rast)
FROM raster_intersects_rast r1
CROSS JOIN raster_intersects_geom g1
WHERE r1.rid = 2;
SELECT
'2.5',
r1.rid,
g1.gid,
ST_GeometryType(g1.geom),
ST_Intersects(r1.rast, g1.geom, 1)
FROM raster_intersects_rast r1
CROSS JOIN raster_intersects_geom g1
WHERE r1.rid = 0;
SELECT
'2.6',
r1.rid,
g1.gid,
ST_GeometryType(g1.geom),
ST_Intersects(r1.rast, g1.geom, 1)
FROM raster_intersects_rast r1
CROSS JOIN raster_intersects_geom g1
WHERE r1.rid = 2;
DROP TABLE IF EXISTS raster_intersects_rast; DROP TABLE IF EXISTS raster_intersects_rast;
DROP TABLE IF EXISTS raster_intersects_geom;

View file

@ -1,4 +1,3 @@
NOTICE: table "raster_intersects_rast" does not exist, skipping
1.1|0|1|t 1.1|0|1|t
1.1|0|2|t 1.1|0|2|t
1.1|0|10|t 1.1|0|10|t
@ -31,3 +30,207 @@ NOTICE: table "raster_intersects_rast" does not exist, skipping
1.2|0|30|t 1.2|0|30|t
1.2|0|31|t 1.2|0|31|t
1.2|0|32|t 1.2|0|32|t
2.1|0|1|ST_Point|t
2.1|0|2|ST_Point|t
2.1|0|3|ST_Point|t
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|t
2.1|0|12|ST_MultiPoint|t
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|t
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|t
2.1|0|27|ST_LineString|t
2.1|0|28|ST_LineString|t
2.1|0|29|ST_LineString|f
2.1|0|31|ST_Polygon|t
2.1|0|32|ST_Polygon|t
2.1|0|33|ST_Polygon|t
2.1|0|34|ST_Polygon|t
2.1|0|35|ST_Polygon|t
2.1|0|36|ST_Polygon|f
2.1|0|41|ST_MultiPolygon|t
2.1|0|42|ST_MultiPolygon|t
2.1|0|43|ST_MultiPolygon|t
2.1|0|44|ST_MultiPolygon|t
2.1|0|45|ST_MultiPolygon|t
2.1|0|46|ST_MultiPolygon|f
2.2|0|1|ST_Point|t
2.2|0|2|ST_Point|t
2.2|0|3|ST_Point|t
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|t
2.2|0|12|ST_MultiPoint|t
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|t
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|t
2.2|0|27|ST_LineString|t
2.2|0|28|ST_LineString|t
2.2|0|29|ST_LineString|f
2.2|0|31|ST_Polygon|t
2.2|0|32|ST_Polygon|t
2.2|0|33|ST_Polygon|t
2.2|0|34|ST_Polygon|t
2.2|0|35|ST_Polygon|t
2.2|0|36|ST_Polygon|f
2.2|0|41|ST_MultiPolygon|t
2.2|0|42|ST_MultiPolygon|t
2.2|0|43|ST_MultiPolygon|t
2.2|0|44|ST_MultiPolygon|t
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|t
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|t
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|t
2.3|2|22|ST_LineString|t
2.3|2|23|ST_LineString|t
2.3|2|24|ST_LineString|t
2.3|2|25|ST_LineString|t
2.3|2|26|ST_LineString|t
2.3|2|27|ST_LineString|t
2.3|2|28|ST_LineString|t
2.3|2|29|ST_LineString|t
2.3|2|31|ST_Polygon|t
2.3|2|32|ST_Polygon|t
2.3|2|33|ST_Polygon|t
2.3|2|34|ST_Polygon|t
2.3|2|35|ST_Polygon|t
2.3|2|36|ST_Polygon|t
2.3|2|41|ST_MultiPolygon|t
2.3|2|42|ST_MultiPolygon|t
2.3|2|43|ST_MultiPolygon|t
2.3|2|44|ST_MultiPolygon|t
2.3|2|45|ST_MultiPolygon|t
2.3|2|46|ST_MultiPolygon|t
2.4|2|1|ST_Point|t
2.4|2|2|ST_Point|t
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|t
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|t
2.4|2|22|ST_LineString|t
2.4|2|23|ST_LineString|t
2.4|2|24|ST_LineString|t
2.4|2|25|ST_LineString|t
2.4|2|26|ST_LineString|t
2.4|2|27|ST_LineString|t
2.4|2|28|ST_LineString|t
2.4|2|29|ST_LineString|t
2.4|2|31|ST_Polygon|t
2.4|2|32|ST_Polygon|t
2.4|2|33|ST_Polygon|t
2.4|2|34|ST_Polygon|t
2.4|2|35|ST_Polygon|t
2.4|2|36|ST_Polygon|t
2.4|2|41|ST_MultiPolygon|t
2.4|2|42|ST_MultiPolygon|t
2.4|2|43|ST_MultiPolygon|t
2.4|2|44|ST_MultiPolygon|t
2.4|2|45|ST_MultiPolygon|t
2.4|2|46|ST_MultiPolygon|t
2.5|0|1|ST_Point|t
2.5|0|2|ST_Point|t
2.5|0|3|ST_Point|t
2.5|0|4|ST_Point|t
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|t
2.5|0|12|ST_MultiPoint|t
2.5|0|13|ST_MultiPoint|t
2.5|0|14|ST_MultiPoint|f
2.5|0|15|ST_MultiPoint|f
2.5|0|21|ST_LineString|t
2.5|0|22|ST_LineString|t
2.5|0|23|ST_LineString|t
2.5|0|24|ST_LineString|f
2.5|0|25|ST_LineString|f
2.5|0|26|ST_LineString|t
2.5|0|27|ST_LineString|t
2.5|0|28|ST_LineString|t
2.5|0|29|ST_LineString|f
2.5|0|31|ST_Polygon|t
2.5|0|32|ST_Polygon|t
2.5|0|33|ST_Polygon|t
2.5|0|34|ST_Polygon|t
2.5|0|35|ST_Polygon|t
2.5|0|36|ST_Polygon|f
2.5|0|41|ST_MultiPolygon|t
2.5|0|42|ST_MultiPolygon|t
2.5|0|43|ST_MultiPolygon|t
2.5|0|44|ST_MultiPolygon|t
2.5|0|45|ST_MultiPolygon|t
2.5|0|46|ST_MultiPolygon|f
2.6|2|1|ST_Point|t
2.6|2|2|ST_Point|t
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|t
2.6|2|11|ST_MultiPoint|t
2.6|2|12|ST_MultiPoint|t
2.6|2|13|ST_MultiPoint|t
2.6|2|14|ST_MultiPoint|t
2.6|2|15|ST_MultiPoint|t
2.6|2|21|ST_LineString|t
2.6|2|22|ST_LineString|t
2.6|2|23|ST_LineString|t
2.6|2|24|ST_LineString|t
2.6|2|25|ST_LineString|t
2.6|2|26|ST_LineString|t
2.6|2|27|ST_LineString|t
2.6|2|28|ST_LineString|t
2.6|2|29|ST_LineString|t
2.6|2|31|ST_Polygon|t
2.6|2|32|ST_Polygon|t
2.6|2|33|ST_Polygon|t
2.6|2|34|ST_Polygon|t
2.6|2|35|ST_Polygon|t
2.6|2|36|ST_Polygon|t
2.6|2|41|ST_MultiPolygon|t
2.6|2|42|ST_MultiPolygon|t
2.6|2|43|ST_MultiPolygon|t
2.6|2|44|ST_MultiPolygon|t
2.6|2|45|ST_MultiPolygon|t
2.6|2|46|ST_MultiPolygon|t