[postgis-tickets] r14612 - #3433, ST_ClusterIntersecting gives incorrect result for MultiPoints

Daniel Baston dbaston at gmail.com
Wed Jan 20 04:18:14 PST 2016


Author: dbaston
Date: 2016-01-20 04:18:14 -0800 (Wed, 20 Jan 2016)
New Revision: 14612

Modified:
   branches/2.2/NEWS
   branches/2.2/liblwgeom/cunit/cu_geos_cluster.c
   branches/2.2/liblwgeom/lwgeom_geos_cluster.c
Log:
#3433, ST_ClusterIntersecting gives incorrect result for MultiPoints

Modified: branches/2.2/NEWS
===================================================================
--- branches/2.2/NEWS	2016-01-20 11:57:21 UTC (rev 14611)
+++ branches/2.2/NEWS	2016-01-20 12:18:14 UTC (rev 14612)
@@ -6,6 +6,7 @@
   - #3422, Improve ST_Split robustness on standard precision double
            systems (arm64, ppc64el, s390c, powerpc, ...)
   - #3427, Update spatial_ref_sys to EPSG version 8.8
+  - #3433, ST_ClusterIntersecting incorrect for MultiPoints
   - #3436, memory handling mistake in ptarray_clone_deep
 
 PostGIS 2.2.1

Modified: branches/2.2/liblwgeom/cunit/cu_geos_cluster.c
===================================================================
--- branches/2.2/liblwgeom/cunit/cu_geos_cluster.c	2016-01-20 11:57:21 UTC (rev 14611)
+++ branches/2.2/liblwgeom/cunit/cu_geos_cluster.c	2016-01-20 12:18:14 UTC (rev 14612)
@@ -238,6 +238,23 @@
 	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 @@
 	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);
 }

Modified: branches/2.2/liblwgeom/lwgeom_geos_cluster.c
===================================================================
--- branches/2.2/liblwgeom/lwgeom_geos_cluster.c	2016-01-20 11:57:21 UTC (rev 14611)
+++ branches/2.2/liblwgeom/lwgeom_geos_cluster.c	2016-01-20 12:18:14 UTC (rev 14612)
@@ -124,12 +124,26 @@
 
 	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]);
 		}
-		int geos_result = GEOSPreparedIntersects(cxt->prep, cxt->geoms[q]);
+		else
+		{
+			geos_result = GEOSIntersects(cxt->geoms[p], cxt->geoms[q]);
+		}
 		if (geos_result > 1)
 		{
 			cxt->error = geos_result;



More information about the postgis-tickets mailing list