From: Paul Ramsey Date: Tue, 7 Jul 2015 21:02:03 +0000 (+0000) Subject: From dbaston resolves outstanding TODO... X-Git-Tag: 2.2.0rc1~258 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b8946f6cff80cf6b5c1d0ade3ee0951fe06a32ea;p=postgis From dbaston resolves outstanding TODO list item git-svn-id: http://svn.osgeo.org/postgis/trunk@13788 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/liblwgeom/cunit/cu_libgeom.c b/liblwgeom/cunit/cu_libgeom.c index 99c5d13f1..6fb3187d1 100644 --- a/liblwgeom/cunit/cu_libgeom.c +++ b/liblwgeom/cunit/cu_libgeom.c @@ -1038,6 +1038,40 @@ static void test_lwgeom_scale(void) lwgeom_free(geom); } +void test_gbox_same_2d(void); +void test_gbox_same_2d(void) +{ + LWGEOM* g1 = lwgeom_from_wkt("LINESTRING(0 0, 1 1)", LW_PARSER_CHECK_NONE); + LWGEOM* g2 = lwgeom_from_wkt("LINESTRING(0 0, 0 1, 1 1)", LW_PARSER_CHECK_NONE); + LWGEOM* g3 = lwgeom_from_wkt("LINESTRING(0 0, 1 1.000000000001)", LW_PARSER_CHECK_NONE); + + lwgeom_add_bbox(g1); + lwgeom_add_bbox(g2); + lwgeom_add_bbox(g3); + + CU_ASSERT_TRUE(gbox_same_2d(g1->bbox, g2->bbox)); + CU_ASSERT_FALSE(gbox_same_2d(g1->bbox, g3->bbox)); + + /* Serializing a GBOX with precise coordinates renders the boxes not strictly equal, + * but still equal according to gbox_same_2d_float. + */ + GSERIALIZED* s3 = gserialized_from_lwgeom(g3, LW_FALSE, NULL); + GBOX s3box; + gserialized_read_gbox_p(s3, &s3box); + + CU_ASSERT_FALSE(gbox_same_2d(g3->bbox, &s3box)); + CU_ASSERT_TRUE(gbox_same_2d_float(g3->bbox, &s3box)); + + /* The serialized box equals itself by either the exact or closest-float compares */ + CU_ASSERT_TRUE(gbox_same_2d(&s3box, &s3box)); + CU_ASSERT_TRUE(gbox_same_2d_float(&s3box, &s3box)); + + lwgeom_free(g1); + lwgeom_free(g2); + lwgeom_free(g3); + lwfree(s3); +} + /* ** Used by test harness to register the tests in this file. */ @@ -1067,4 +1101,5 @@ void libgeom_suite_setup(void) PG_ADD_TEST(suite, test_lwgeom_as_curve); PG_ADD_TEST(suite, test_lwgeom_scale); PG_ADD_TEST(suite, test_gserialized_is_empty); + PG_ADD_TEST(suite, test_gbox_same_2d); } diff --git a/liblwgeom/g_box.c b/liblwgeom/g_box.c index aac64f786..3269ac3b5 100644 --- a/liblwgeom/g_box.c +++ b/liblwgeom/g_box.c @@ -143,8 +143,7 @@ int gbox_same(const GBOX *g1, const GBOX *g2) if (FLAGS_GET_ZM(g1->flags) != FLAGS_GET_ZM(g2->flags)) return LW_FALSE; - if ( g1->xmin != g2->xmin || g1->ymin != g2->ymin || - g1->xmax != g2->xmax || g1->ymax != g2->ymax ) return LW_FALSE; + if (!gbox_same_2d(g1, g2)) return LW_FALSE; if (FLAGS_GET_Z(g1->flags) && (g1->zmin != g2->zmin || g1->zmax != g2->zmax)) return LW_FALSE; @@ -154,6 +153,24 @@ int gbox_same(const GBOX *g1, const GBOX *g2) return LW_TRUE; } +int gbox_same_2d(const GBOX *g1, const GBOX *g2) +{ + if (g1->xmin == g2->xmin && g1->ymin == g2->ymin && + g1->xmax == g2->xmax && g1->ymax == g2->ymax) + return LW_TRUE; + return LW_FALSE; +} + +int gbox_same_2d_float(const GBOX *g1, const GBOX *g2) +{ + if ((g1->xmax == g2->xmax || next_float_up(g1->xmax) == next_float_up(g2->xmax)) && + (g1->ymax == g2->ymax || next_float_up(g1->ymax) == next_float_up(g2->ymax)) && + (g1->xmin == g2->xmin || next_float_down(g1->xmin) == next_float_down(g1->xmin)) && + (g1->ymin == g2->ymin || next_float_down(g2->ymin) == next_float_down(g2->ymin))) + return LW_TRUE; + return LW_FALSE; +} + int gbox_is_valid(const GBOX *gbox) { /* X */ diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in index a3a249baf..9677f706c 100644 --- a/liblwgeom/liblwgeom.h.in +++ b/liblwgeom/liblwgeom.h.in @@ -1796,6 +1796,17 @@ extern size_t gbox_serialized_size(uint8_t flags); */ extern int gbox_same(const GBOX *g1, const GBOX *g2); +/** +* Check if 2 given GBOX are the same in x and y +*/ +extern int gbox_same_2d(const GBOX *g1, const GBOX *g2); + +/** +* Check if two given GBOX are the same in x and y, or would round to the same +* GBOX in x and if serialized in GSERIALIZED +*/ +extern int gbox_same_2d_float(const GBOX *g1, const GBOX *g2); + /** * Round given GBOX to float boundaries * diff --git a/postgis/lwgeom_geos.c b/postgis/lwgeom_geos.c index f26394c72..0a5aed515 100644 --- a/postgis/lwgeom_geos.c +++ b/postgis/lwgeom_geos.c @@ -3085,15 +3085,13 @@ Datum ST_Equals(PG_FUNCTION_ARGS) PG_RETURN_BOOL(TRUE); /* - * short-circuit: Loose test, if geom2 bounding box does not overlap - * geom1 bounding box we can prematurely return FALSE. - * - * TODO: use gbox_same_2d instead (not available at time of writing) + * short-circuit: If geom1 and geom2 do not have the same bounding box + * we can return FALSE. */ - if ( gserialized_get_gbox_p(geom1, &box1) && - gserialized_get_gbox_p(geom2, &box2) ) + if ( gserialized_read_gbox_p(geom1, &box1) && + gserialized_read_gbox_p(geom2, &box2) ) { - if ( gbox_overlaps_2d(&box1, &box2) == LW_FALSE ) + if ( gbox_same_2d_float(&box1, &box2) == LW_FALSE ) { PG_RETURN_BOOL(FALSE); }