]> granicus.if.org Git - postgis/commitdiff
From dbaston <https://github.com/postgis/postgis/pull/40> resolves outstanding TODO...
authorPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 7 Jul 2015 21:02:03 +0000 (21:02 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Tue, 7 Jul 2015 21:02:03 +0000 (21:02 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@13788 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/cunit/cu_libgeom.c
liblwgeom/g_box.c
liblwgeom/liblwgeom.h.in
postgis/lwgeom_geos.c

index 99c5d13f1b75ea882a495766b966af7d8b808499..6fb3187d1e765f85ec44981d37c0424d8a84f787 100644 (file)
@@ -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);
 }
index aac64f786e2703c0a4aeed65363be11a24b01f4a..3269ac3b578cd6fa207f6818663e7670bfa80946 100644 (file)
@@ -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 */
index a3a249baf3874c0335b4f1d30d7ae1e405da5fda..9677f706c5578045ed6115a1e7641417135e341f 100644 (file)
@@ -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
  *
index f26394c7250f459902725dfd846d7098568c3d4e..0a5aed515feec151a0f5ad52b6a9d7bc3fa01adc 100644 (file)
@@ -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);
                }