From: Paul Ramsey Date: Sat, 7 Nov 2009 01:31:07 +0000 (+0000) Subject: Make ~= be a bounding box only operator and upgrade ST_Equals() and ST_OrderingEquals... X-Git-Tag: 1.5.0b1~276 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6f547e3120d7106856206a5521d2dfb5ccef3e6c;p=postgis Make ~= be a bounding box only operator and upgrade ST_Equals() and ST_OrderingEquals() to match the new behavior. Update regression tests to match new behavior. (#282) See also #289 for an odd quirk discovered while updating regression tests. git-svn-id: http://svn.osgeo.org/postgis/trunk@4763 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/postgis/lwgeom_gist.c b/postgis/lwgeom_gist.c index 4f965a8c2..fb39ac160 100644 --- a/postgis/lwgeom_gist.c +++ b/postgis/lwgeom_gist.c @@ -37,6 +37,7 @@ Datum LWGEOM_below(PG_FUNCTION_ARGS); Datum LWGEOM_above(PG_FUNCTION_ARGS); Datum LWGEOM_overabove(PG_FUNCTION_ARGS); Datum LWGEOM_contained(PG_FUNCTION_ARGS); +Datum LWGEOM_samebox(PG_FUNCTION_ARGS); Datum LWGEOM_contain(PG_FUNCTION_ARGS); Datum LWGEOM_gist_compress(PG_FUNCTION_ARGS); Datum LWGEOM_gist_consistent(PG_FUNCTION_ARGS); @@ -374,6 +375,34 @@ Datum LWGEOM_overabove(PG_FUNCTION_ARGS) PG_RETURN_BOOL(result); } +PG_FUNCTION_INFO_V1(LWGEOM_samebox); +Datum LWGEOM_samebox(PG_FUNCTION_ARGS) +{ + PG_LWGEOM *lwgeom1 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + PG_LWGEOM *lwgeom2 = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + bool result; + BOX2DFLOAT4 box1; + BOX2DFLOAT4 box2; + + POSTGIS_DEBUG(2, "GIST: LWGEOM_samebox --entry"); + + errorIfSRIDMismatch(pglwgeom_getSRID(lwgeom1), pglwgeom_getSRID(lwgeom2)); + + if ( ! (getbox2d_p(SERIALIZED_FORM(lwgeom1), &box1) && getbox2d_p(SERIALIZED_FORM(lwgeom2), &box2)) ) + { + PG_FREE_IF_COPY(lwgeom1, 0); + PG_FREE_IF_COPY(lwgeom2, 1); + PG_RETURN_BOOL(FALSE); + } + + result = DatumGetBool(DirectFunctionCall2(BOX2D_same, + PointerGetDatum(&box1), PointerGetDatum(&box2))); + + PG_FREE_IF_COPY(lwgeom1, 0); + PG_FREE_IF_COPY(lwgeom2, 1); + + PG_RETURN_BOOL(result); +} PG_FUNCTION_INFO_V1(LWGEOM_contained); Datum LWGEOM_contained(PG_FUNCTION_ARGS) @@ -563,11 +592,6 @@ Datum LWGEOM_gist_consistent(PG_FUNCTION_ARGS) can make things twice as slow. */ *recheck = false; - /* Our ~= operator (strategy 6) requires a re-check in order to - function according to the documentation and past behavior. - We will temporarily enable that behavior here. */ - if ( strategy == 6 ) - *recheck = true; #endif POSTGIS_DEBUG(2, "GIST: LWGEOM_gist_consistent called"); diff --git a/postgis/postgis.sql.in.c b/postgis/postgis.sql.in.c index 286240a6a..4af44663c 100644 --- a/postgis/postgis.sql.in.c +++ b/postgis/postgis.sql.in.c @@ -644,9 +644,9 @@ CREATE OR REPLACE FUNCTION geometry_overlap(geometry, geometry) AS 'MODULE_PATHNAME', 'LWGEOM_overlap' LANGUAGE 'C' IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION geometry_same(geometry, geometry) +CREATE OR REPLACE FUNCTION geometry_samebox(geometry, geometry) RETURNS bool - AS 'MODULE_PATHNAME', 'LWGEOM_same' + AS 'MODULE_PATHNAME', 'LWGEOM_samebox' LANGUAGE 'C' IMMUTABLE STRICT; @@ -705,7 +705,7 @@ CREATE OPERATOR |>> ( ); CREATE OPERATOR ~= ( - LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_same, + LEFTARG = geometry, RIGHTARG = geometry, PROCEDURE = geometry_samebox, COMMUTATOR = '~=', RESTRICT = eqsel, JOIN = eqjoinsel ); @@ -4217,13 +4217,19 @@ CREATE OR REPLACE FUNCTION Equals(geometry,geometry) AS 'MODULE_PATHNAME','geomequals' LANGUAGE 'C' IMMUTABLE STRICT; --- PostGIS equivalent function: Equals(geometry,geometry) -CREATE OR REPLACE FUNCTION ST_Equals(geometry,geometry) +-- Availability: 1.5.0 +CREATE OR REPLACE FUNCTION _ST_Equals(geometry,geometry) RETURNS boolean AS 'MODULE_PATHNAME','geomequals' LANGUAGE 'C' IMMUTABLE STRICT COST 100; +-- Availability: 1.2.1 +CREATE OR REPLACE FUNCTION ST_Equals(geometry,geometry) + RETURNS boolean + AS 'SELECT $1 ~= $2 AND _ST_Equals($1,$2)' + LANGUAGE 'SQL' IMMUTABLE STRICT; + #if HAVE_LIBXML2 ----------------------------------------------------------------------- diff --git a/postgis/sqlmm.sql.in.c b/postgis/sqlmm.sql.in.c index 51d2049b3..2008fe6da 100644 --- a/postgis/sqlmm.sql.in.c +++ b/postgis/sqlmm.sql.in.c @@ -148,11 +148,18 @@ CREATE OR REPLACE FUNCTION ST_CoordDim(geometry) -- ST_X(geometry) - already defined. -- ST_Y(geometry) - already defined. --- PostGIS equivalent function: ~= +-- Availability: 1.5.0 +CREATE OR REPLACE FUNCTION _ST_OrderingEquals(geometry, geometry) + RETURNS boolean + AS 'MODULE_PATHNAME', 'LWGEOM_same' + LANGUAGE 'C' IMMUTABLE STRICT + COST 100; + +-- Availability: 1.3.0 CREATE OR REPLACE FUNCTION ST_OrderingEquals(geometry, geometry) RETURNS boolean AS $$ - SELECT $1 && $2 AND $1 ~= $2 + SELECT $1 ~= $2 AND _ST_OrderingEquals($1, $2) $$ LANGUAGE 'SQL' IMMUTABLE STRICT; diff --git a/regress/regress.sql b/regress/regress.sql index 9b21c1c33..b70ba1eb2 100644 --- a/regress/regress.sql +++ b/regress/regress.sql @@ -95,21 +95,33 @@ select '64',ST_asewkt('MULTIPOINT(1 1, 2 2'::GEOMETRY); --- is_same() testing select '65','POINT(1 1)'::GEOMETRY ~= 'POINT(1 1)'::GEOMETRY as bool; +select '65a',st_orderingequals('POINT(1 1)'::GEOMETRY,'POINT(1 1)'::GEOMETRY) as bool; select '66','POINT(1 1 0)'::GEOMETRY ~= 'POINT(1 1)'::GEOMETRY as bool; +select '66a',st_orderingequals('POINT(1 1 0)'::GEOMETRY,'POINT(1 1)'::GEOMETRY) as bool; select '67','POINT(1 1 0)'::GEOMETRY ~= 'POINT(1 1 0)'::GEOMETRY as bool; +select '67a',st_orderingequals('POINT(1 1 0)'::GEOMETRY,'POINT(1 1 0)'::GEOMETRY) as bool; select '68','MULTIPOINT(1 1,2 2)'::GEOMETRY ~= 'MULTIPOINT(1 1,2 2)'::GEOMETRY as bool; +select '68a',st_orderingequals('MULTIPOINT(1 1,2 2)'::GEOMETRY,'MULTIPOINT(1 1,2 2)'::GEOMETRY) as bool; select '69','MULTIPOINT(2 2, 1 1)'::GEOMETRY ~= 'MULTIPOINT(1 1,2 2)'::GEOMETRY as bool; +select '69a',st_orderingequals('MULTIPOINT(2 2, 1 1)'::GEOMETRY,'MULTIPOINT(1 1,2 2)'::GEOMETRY) as bool; select '70','GEOMETRYCOLLECTION(POINT( 1 2 3),POINT(4 5 6))'::GEOMETRY ~= 'GEOMETRYCOLLECTION(POINT( 4 5 6),POINT(1 2 3))'::GEOMETRY as bool; +select '70a',st_orderingequals('GEOMETRYCOLLECTION(POINT( 1 2 3),POINT(4 5 6))'::GEOMETRY,'GEOMETRYCOLLECTION(POINT( 4 5 6),POINT(1 2 3))'::GEOMETRY) as bool; select '71','MULTIPOINT(4 5 6, 1 2 3)'::GEOMETRY ~= 'GEOMETRYCOLLECTION(POINT( 4 5 6),POINT(1 2 3))'::GEOMETRY as bool; +select '71a',st_orderingequals('MULTIPOINT(4 5 6, 1 2 3)'::GEOMETRY,'GEOMETRYCOLLECTION(POINT( 4 5 6),POINT(1 2 3))'::GEOMETRY) as bool; select '72','MULTIPOINT(1 2 3, 4 5 6)'::GEOMETRY ~= 'GEOMETRYCOLLECTION(POINT( 4 5 6),POINT(1 2 3))'::GEOMETRY as bool; +select '72a',st_orderingequals('MULTIPOINT(1 2 3, 4 5 6)'::GEOMETRY,'GEOMETRYCOLLECTION(POINT( 4 5 6),POINT(1 2 3))'::GEOMETRY) as bool; select '73','MULTIPOINT(1 2 3, 4 5 6)'::GEOMETRY ~= 'GEOMETRYCOLLECTION(MULTIPOINT(1 2 3, 4 5 6))'::GEOMETRY as bool; +select '73a',st_orderingequals('MULTIPOINT(1 2 3, 4 5 6)'::GEOMETRY,'GEOMETRYCOLLECTION(MULTIPOINT(1 2 3, 4 5 6))'::GEOMETRY) as bool; select '74','LINESTRING(1 1,2 2)'::GEOMETRY ~= 'POINT(1 1)'::GEOMETRY as bool; +select '74a',st_orderingequals('LINESTRING(1 1,2 2)'::GEOMETRY,'POINT(1 1)'::GEOMETRY) as bool; select '75','LINESTRING(1 1, 2 2)'::GEOMETRY ~= 'LINESTRING(2 2, 1 1)'::GEOMETRY as bool; +select '75a',st_orderingequals('LINESTRING(1 1, 2 2)'::GEOMETRY,'LINESTRING(2 2, 1 1)'::GEOMETRY) as bool; select '76','LINESTRING(1 1, 2 2)'::GEOMETRY ~= 'LINESTRING(1 1, 2 2, 3 3)'::GEOMETRY as bool; +select '76a',st_orderingequals('LINESTRING(1 1, 2 2)'::GEOMETRY,'LINESTRING(1 1, 2 2, 3 3)'::GEOMETRY) as bool; --- operator testing (testing is on the BOUNDING BOX (2d), not the actual geometries) diff --git a/regress/regress_expected b/regress/regress_expected index 81d4a5a64..33204a870 100644 --- a/regress/regress_expected +++ b/regress/regress_expected @@ -76,17 +76,29 @@ HINT: "LINESTRING(1 1)" <-- parse error at position 15 within geometry ERROR: parse error - invalid geometry HINT: "MULTIPOINT(1 1, 2 2" <-- parse error at position 19 within geometry 65|t -66|f +65a|t +66|t +66a|f 67|t +67a|t 68|t +68a|t 69|t +69a|t 70|t -71|f -72|f -73|f +70a|t +71|t +71a|f +72|t +72a|f +73|t +73a|f 74|f -75|f +74a|f +75|t +75a|f 76|f +76a|f 77|t 78|t 79|f