From: Sandro Santilli Date: Thu, 16 Sep 2004 09:05:31 +0000 (+0000) Subject: Added binary predicate short-circuits X-Git-Tag: pgis_1_0_0RC1~446 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3771b8a9459413ae3d1a1754168bb363781e9b97;p=postgis Added binary predicate short-circuits git-svn-id: http://svn.osgeo.org/postgis/trunk@825 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/lwgeom/lwgeom_geos.c b/lwgeom/lwgeom_geos.c index b80d901c5..38f5d3d98 100644 --- a/lwgeom/lwgeom_geos.c +++ b/lwgeom/lwgeom_geos.c @@ -690,12 +690,28 @@ Datum isvalid(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(overlaps); Datum overlaps(PG_FUNCTION_ARGS) { - LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); + LWGEOM *geom1 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); Geometry *g1,*g2; bool result; + const BOX2DFLOAT4 *box1, *box2; errorIfGeometryCollection(geom1,geom2); + + /* + * short-circuit 1: if geom2 bounding box does not overlap + * geom1 bounding box we can prematurely return FALSE. + * Do the test IFF BOUNDING BOX AVAILABLE. + */ + if ( (box1=getbox2d_internal(SERIALIZED_FORM(geom1))) && + (box2=getbox2d_internal(SERIALIZED_FORM(geom2))) ) + { + if ( box2->xmax < box1->xmin ) PG_RETURN_BOOL(FALSE); + if ( box2->xmin > box1->xmax ) PG_RETURN_BOOL(FALSE); + if ( box2->ymax < box1->ymin ) PG_RETURN_BOOL(FALSE); + if ( box2->ymin > box2->ymax ) PG_RETURN_BOOL(FALSE); + } + initGEOS(MAXIMUM_ALIGNOF); g1 = POSTGIS2GEOS(geom1 ); @@ -722,56 +738,29 @@ Datum contains(PG_FUNCTION_ARGS) LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); Geometry *g1,*g2; bool result; - //POINT3D *testpoint; - //POLYGON3D *poly; + const BOX2DFLOAT4 *box1, *box2; errorIfGeometryCollection(geom1,geom2); /* * short-circuit 1: if geom2 bounding box is not completely inside - * geom1 bounding box we can prematurely return FALSE - */ -// DISABLED ... TODO: use only if bbox is available -#if 0 - if ( geom2->bvol.LLB.x < geom1->bvol.LLB.x ) PG_RETURN_BOOL(FALSE); - if ( geom2->bvol.URT.x > geom1->bvol.URT.x ) PG_RETURN_BOOL(FALSE); - if ( geom2->bvol.LLB.y < geom1->bvol.LLB.y ) PG_RETURN_BOOL(FALSE); - if ( geom2->bvol.URT.y > geom1->bvol.URT.y ) PG_RETURN_BOOL(FALSE); - - /* - * short-circuit 2: if geom1 is a polygon and any corner of - * geom2 bounding box is not 'within' geom1 we can prematurely - * return FALSE + * geom1 bounding box we can prematurely return FALSE. + * Do the test IFF BOUNDING BOX AVAILABLE. */ - //if ( geom1->type == POLYGONTYPE ) - //{ - // poly = (POLYGON3D *)geom1->objData; - // testpoint.x = geom2->bvol.LLB.x; - // testpoint.y = geom2->bvol.LLB.y; - // if ( !point_within_polygon(&testpoint, poly) ) - // PG_RETURN_BOOL(FALSE); - // testpoint.x = geom2->bvol.LLB.x; - // testpoint.y = geom2->bvol.URT.y; - // if ( !point_within_polygon(&testpoint, poly) ) - // PG_RETURN_BOOL(FALSE); - // testpoint.x = geom2->bvol.URT.x; - // testpoint.y = geom2->bvol.URT.y; - // if ( !point_within_polygon(&testpoint, poly) ) - // PG_RETURN_BOOL(FALSE); - // testpoint.x = geom2->bvol.URT.x; - // testpoint.y = geom2->bvol.LLB.y; - // if ( !point_within_polygon(&testpoint, poly) ) - // PG_RETURN_BOOL(FALSE); - //} -#endif + if ( (box1=getbox2d_internal(SERIALIZED_FORM(geom1))) && + (box2=getbox2d_internal(SERIALIZED_FORM(geom2))) ) + { + if ( box2->xmin < box1->xmin ) PG_RETURN_BOOL(FALSE); + if ( box2->xmax > box1->xmax ) PG_RETURN_BOOL(FALSE); + if ( box2->ymin < box1->ymin ) PG_RETURN_BOOL(FALSE); + if ( box2->ymax > box1->ymax ) PG_RETURN_BOOL(FALSE); + } initGEOS(MAXIMUM_ALIGNOF); g1 = POSTGIS2GEOS(geom1 ); g2 = POSTGIS2GEOS(geom2 ); - - result = GEOSrelateContains(g1,g2); GEOSdeleteGeometry(g1); GEOSdeleteGeometry(g2); @@ -782,8 +771,6 @@ Datum contains(PG_FUNCTION_ARGS) PG_RETURN_NULL(); //never get here } - - PG_RETURN_BOOL(result); } @@ -795,51 +782,26 @@ Datum within(PG_FUNCTION_ARGS) LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); Geometry *g1,*g2; bool result; - //POINT3D testpoint; - //POLYGON3D *poly; + const BOX2DFLOAT4 *box1, *box2; errorIfGeometryCollection(geom1,geom2); - -// DISABLED ... TODO: use only if bbox is available -#if 0 /* * short-circuit 1: if geom1 bounding box is not completely inside - * geom2 bounding box we can prematurely return FALSE + * geom2 bounding box we can prematurely return FALSE. + * Do the test IFF BOUNDING BOX AVAILABLE. */ - if ( geom1->bvol.LLB.x < geom2->bvol.LLB.x ) PG_RETURN_BOOL(FALSE); - if ( geom1->bvol.URT.x > geom2->bvol.URT.x ) PG_RETURN_BOOL(FALSE); - if ( geom1->bvol.LLB.y < geom2->bvol.LLB.y ) PG_RETURN_BOOL(FALSE); - if ( geom1->bvol.URT.y > geom2->bvol.URT.y ) PG_RETURN_BOOL(FALSE); - - /* - * short-circuit 2: if geom2 is a polygon and any corner of - * geom1 bounding box is not 'within' geom2 we can prematurely - * return FALSE - */ - //if ( geom2->type == POLYGONTYPE ) - //{ - // poly = (POLYGON3D *)geom2->objData; - // testpoint.x = geom1->bvol.LLB.x; - // testpoint.y = geom1->bvol.LLB.y; - // if ( !point_within_polygon(&testpoint, poly) ) - // PG_RETURN_BOOL(FALSE); - // testpoint.x = geom1->bvol.LLB.x; - // testpoint.y = geom1->bvol.URT.y; - // if ( !point_within_polygon(&testpoint, poly) ) - // PG_RETURN_BOOL(FALSE); - // testpoint.x = geom1->bvol.URT.x; - // testpoint.y = geom1->bvol.URT.y; - // if ( !point_within_polygon(&testpoint, poly) ) - // PG_RETURN_BOOL(FALSE); - // testpoint.x = geom1->bvol.URT.x; - // testpoint.y = geom1->bvol.LLB.y; - // if ( !point_within_polygon(&testpoint, poly) ) - // PG_RETURN_BOOL(FALSE); - //} -#endif + if ( (box1=getbox2d_internal(SERIALIZED_FORM(geom1))) && + (box2=getbox2d_internal(SERIALIZED_FORM(geom2))) ) + { + if ( box1->xmin < box2->xmin ) PG_RETURN_BOOL(FALSE); + if ( box1->xmax > box2->xmax ) PG_RETURN_BOOL(FALSE); + if ( box1->ymin < box2->ymin ) PG_RETURN_BOOL(FALSE); + if ( box1->ymax > box2->ymax ) PG_RETURN_BOOL(FALSE); + } initGEOS(MAXIMUM_ALIGNOF); + g1 = POSTGIS2GEOS(geom1 ); g2 = POSTGIS2GEOS(geom2 ); @@ -853,8 +815,6 @@ Datum within(PG_FUNCTION_ARGS) PG_RETURN_NULL(); //never get here } - - PG_RETURN_BOOL(result); } @@ -863,21 +823,33 @@ Datum within(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(crosses); Datum crosses(PG_FUNCTION_ARGS) { - LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - + LWGEOM *geom1 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); Geometry *g1,*g2; bool result; + const BOX2DFLOAT4 *box1, *box2; errorIfGeometryCollection(geom1,geom2); + + /* + * short-circuit 1: if geom2 bounding box does not overlap + * geom1 bounding box we can prematurely return FALSE. + * Do the test IFF BOUNDING BOX AVAILABLE. + */ + if ( (box1=getbox2d_internal(SERIALIZED_FORM(geom1))) && + (box2=getbox2d_internal(SERIALIZED_FORM(geom2))) ) + { + if ( box2->xmax < box1->xmin ) PG_RETURN_BOOL(FALSE); + if ( box2->xmin > box1->xmax ) PG_RETURN_BOOL(FALSE); + if ( box2->ymax < box1->ymin ) PG_RETURN_BOOL(FALSE); + if ( box2->ymin > box2->ymax ) PG_RETURN_BOOL(FALSE); + } + initGEOS(MAXIMUM_ALIGNOF); g1 = POSTGIS2GEOS(geom1 ); g2 = POSTGIS2GEOS(geom2 ); - - result = GEOSrelateCrosses(g1,g2); GEOSdeleteGeometry(g1); @@ -889,8 +861,6 @@ Datum crosses(PG_FUNCTION_ARGS) PG_RETURN_NULL(); //never get here } - - PG_RETURN_BOOL(result); } @@ -899,23 +869,33 @@ Datum crosses(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(intersects); Datum intersects(PG_FUNCTION_ARGS) { - LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - + LWGEOM *geom1 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); Geometry *g1,*g2; bool result; + const BOX2DFLOAT4 *box1, *box2; + errorIfGeometryCollection(geom1,geom2); + /* + * short-circuit 1: if geom2 bounding box does not overlap + * geom1 bounding box we can prematurely return FALSE. + * Do the test IFF BOUNDING BOX AVAILABLE. + */ + if ( (box1=getbox2d_internal(SERIALIZED_FORM(geom1))) && + (box2=getbox2d_internal(SERIALIZED_FORM(geom2))) ) + { + if ( box2->xmax < box1->xmin ) PG_RETURN_BOOL(FALSE); + if ( box2->xmin > box1->xmax ) PG_RETURN_BOOL(FALSE); + if ( box2->ymax < box1->ymin ) PG_RETURN_BOOL(FALSE); + if ( box2->ymin > box2->ymax ) PG_RETURN_BOOL(FALSE); + } - - errorIfGeometryCollection(geom1,geom2); initGEOS(MAXIMUM_ALIGNOF); g1 = POSTGIS2GEOS(geom1 ); g2 = POSTGIS2GEOS(geom2 ); - - result = GEOSrelateIntersects(g1,g2); GEOSdeleteGeometry(g1); GEOSdeleteGeometry(g2); @@ -925,8 +905,6 @@ Datum intersects(PG_FUNCTION_ARGS) PG_RETURN_NULL(); //never get here } - - PG_RETURN_BOOL(result); } @@ -934,20 +912,32 @@ Datum intersects(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(touches); Datum touches(PG_FUNCTION_ARGS) { - LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - + LWGEOM *geom1 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); Geometry *g1,*g2; bool result; + const BOX2DFLOAT4 *box1, *box2; errorIfGeometryCollection(geom1,geom2); - initGEOS(MAXIMUM_ALIGNOF); - g1 = POSTGIS2GEOS(geom1 ); - g2 = POSTGIS2GEOS(geom2 ); + /* + * short-circuit 1: if geom2 bounding box does not overlap + * geom1 bounding box we can prematurely return FALSE. + * Do the test IFF BOUNDING BOX AVAILABLE. + */ + if ( (box1=getbox2d_internal(SERIALIZED_FORM(geom1))) && + (box2=getbox2d_internal(SERIALIZED_FORM(geom2))) ) + { + if ( box2->xmax < box1->xmin ) PG_RETURN_BOOL(FALSE); + if ( box2->xmin > box1->xmax ) PG_RETURN_BOOL(FALSE); + if ( box2->ymax < box1->ymin ) PG_RETURN_BOOL(FALSE); + if ( box2->ymin > box2->ymax ) PG_RETURN_BOOL(FALSE); + } + initGEOS(MAXIMUM_ALIGNOF); + g1 = POSTGIS2GEOS(geom1 ); + g2 = POSTGIS2GEOS(geom2 ); result = GEOSrelateTouches(g1,g2); @@ -960,8 +950,6 @@ Datum touches(PG_FUNCTION_ARGS) PG_RETURN_NULL(); //never get here } - - PG_RETURN_BOOL(result); } @@ -969,19 +957,32 @@ Datum touches(PG_FUNCTION_ARGS) PG_FUNCTION_INFO_V1(disjoint); Datum disjoint(PG_FUNCTION_ARGS) { - LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - + LWGEOM *geom1 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); Geometry *g1,*g2; bool result; + const BOX2DFLOAT4 *box1, *box2; errorIfGeometryCollection(geom1,geom2); - initGEOS(MAXIMUM_ALIGNOF); - g1 = POSTGIS2GEOS(geom1 ); - g2 = POSTGIS2GEOS(geom2 ); + /* + * short-circuit 1: if geom2 bounding box does not overlap + * geom1 bounding box we can prematurely return TRUE. + * Do the test IFF BOUNDING BOX AVAILABLE. + */ + if ( (box1=getbox2d_internal(SERIALIZED_FORM(geom1))) && + (box2=getbox2d_internal(SERIALIZED_FORM(geom2))) ) + { + if ( box2->xmax < box1->xmin ) PG_RETURN_BOOL(TRUE); + if ( box2->xmin > box1->xmax ) PG_RETURN_BOOL(TRUE); + if ( box2->ymax < box1->ymin ) PG_RETURN_BOOL(TRUE); + if ( box2->ymin > box2->ymax ) PG_RETURN_BOOL(TRUE); + } + initGEOS(MAXIMUM_ALIGNOF); + + g1 = POSTGIS2GEOS(geom1 ); + g2 = POSTGIS2GEOS(geom2 ); result = GEOSrelateDisjoint(g1,g2); GEOSdeleteGeometry(g1); @@ -1110,19 +1111,32 @@ if ((g1==NULL) || (g2 == NULL)) PG_FUNCTION_INFO_V1(geomequals); Datum geomequals(PG_FUNCTION_ARGS) { - LWGEOM *geom1 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); - LWGEOM *geom2 = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); - - + LWGEOM *geom1 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); + LWGEOM *geom2 = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1)); Geometry *g1,*g2; bool result; + const BOX2DFLOAT4 *box1, *box2; errorIfGeometryCollection(geom1,geom2); - initGEOS(MAXIMUM_ALIGNOF); - g1 = POSTGIS2GEOS(geom1 ); - g2 = POSTGIS2GEOS(geom2 ); + /* + * short-circuit 1: if geom2 bounding box does not equal + * geom1 bounding box we can prematurely return FALSE. + * Do the test IFF BOUNDING BOX AVAILABLE. + */ + if ( (box1=getbox2d_internal(SERIALIZED_FORM(geom1))) && + (box2=getbox2d_internal(SERIALIZED_FORM(geom2))) ) + { + if ( box2->xmax != box1->xmax ) PG_RETURN_BOOL(FALSE); + if ( box2->xmin != box1->xmin ) PG_RETURN_BOOL(FALSE); + if ( box2->ymax != box1->ymax ) PG_RETURN_BOOL(FALSE); + if ( box2->ymin != box2->ymin ) PG_RETURN_BOOL(FALSE); + } + + initGEOS(MAXIMUM_ALIGNOF); + g1 = POSTGIS2GEOS(geom1 ); + g2 = POSTGIS2GEOS(geom2 ); result = GEOSequals(g1,g2); GEOSdeleteGeometry(g1);