]> granicus.if.org Git - postgis/commitdiff
#3433, ST_ClusterIntersecting gives incorrect result for MultiPoints
authorDaniel Baston <dbaston@gmail.com>
Wed, 20 Jan 2016 11:57:21 +0000 (11:57 +0000)
committerDaniel Baston <dbaston@gmail.com>
Wed, 20 Jan 2016 11:57:21 +0000 (11:57 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@14611 b70326c6-7e19-0410-871a-916f4a2858ee

liblwgeom/cunit/cu_geos_cluster.c
liblwgeom/lwgeom_geos_cluster.c

index 39450f00218f601946776ef70609cdc7d585f96c..80215e935fb698673fe10f41bc17d0f44d38fcc0 100644 (file)
@@ -238,6 +238,23 @@ static void empty_inputs_test(void)
        perform_cluster_within_distance_test(1, wkt_inputs, 2, expected_outputs, 2);
 }
 
+static void multipoint_test(void)
+{
+       /* See #3433 */
+       char* wkt_inputs_mp[] = { "MULTIPOINT ((0 0), (0 1))", "POINT (0 0)"};
+       char* expected_outputs_mp[] = { "GEOMETRYCOLLECTION(MULTIPOINT ((0 0), (0 1)), POINT (0 0))"};
+
+       char* wkt_inputs_gc[] = { "GEOMETRYCOLLECTION (POINT (0 0), POINT (0 1))", "POINT (0 0)"};
+       char* expected_outputs_gc[] = { "GEOMETRYCOLLECTION(GEOMETRYCOLLECTION (POINT (0 0), POINT (0 1)), POINT (0 0))"};
+
+       char* wkt_inputs_pt[] = { "POINT (3 3)", "POINT (3 3)"};
+       char* expected_outputs_pt[] = { "GEOMETRYCOLLECTION(POINT (3 3), POINT (3 3))"};
+
+       perform_cluster_intersecting_test(wkt_inputs_mp, 2, expected_outputs_mp, 1);
+       perform_cluster_intersecting_test(wkt_inputs_gc, 2, expected_outputs_gc, 1);
+       perform_cluster_intersecting_test(wkt_inputs_pt, 2, expected_outputs_pt, 1);
+}
+
 void geos_cluster_suite_setup(void);
 void geos_cluster_suite_setup(void)
 {
@@ -247,4 +264,5 @@ void geos_cluster_suite_setup(void)
        PG_ADD_TEST(suite, basic_distance_test);
        PG_ADD_TEST(suite, single_input_test);
        PG_ADD_TEST(suite, empty_inputs_test);
+       PG_ADD_TEST(suite, multipoint_test);
 }
index 97a6fdb8542b9bcd0f637bbd56ab6c7588b44cea..a9421afafc9ee9a27a50a8fa75d7430aa1457d86 100644 (file)
@@ -136,12 +136,26 @@ union_if_intersecting(void* item, void* userdata)
 
        if (p != q && UF_find(cxt->uf, p) != UF_find(cxt->uf, q))
        {
-               /* Lazy initialize prepared geometry */
-               if (cxt->prep == NULL)
+               int geos_type = GEOSGeomTypeId(cxt->geoms[p]);
+               int geos_result;
+
+               /* Don't build prepared a geometry around a Point or MultiPoint -
+                * there are some problems in the implementation, and it's not clear
+                * there would be a performance benefit in any case.  (See #3433)
+                */
+               if (geos_type != GEOS_POINT && geos_type != GEOS_MULTIPOINT)
                {
-                       cxt->prep = GEOSPrepare(cxt->geoms[p]);
+                       /* Lazy initialize prepared geometry */
+                       if (cxt->prep == NULL)
+                       {
+                               cxt->prep = GEOSPrepare(cxt->geoms[p]);
+                       }
+                       geos_result = GEOSPreparedIntersects(cxt->prep, cxt->geoms[q]);
+               }
+               else
+               {
+                       geos_result = GEOSIntersects(cxt->geoms[p], cxt->geoms[q]);
                }
-               int geos_result = GEOSPreparedIntersects(cxt->prep, cxt->geoms[q]);
                if (geos_result > 1)
                {
                        cxt->error = geos_result;