]> granicus.if.org Git - postgis/commitdiff
ST_ClusterKMeans crash on NULL and EMPTY
authorDarafei Praliaskouski <me@komzpa.net>
Sat, 21 Apr 2018 13:17:14 +0000 (13:17 +0000)
committerDarafei Praliaskouski <me@komzpa.net>
Sat, 21 Apr 2018 13:17:14 +0000 (13:17 +0000)
Closes #4071

git-svn-id: http://svn.osgeo.org/postgis/branches/2.3@16549 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
liblwgeom/lwkmeans.c
regress/lwgeom_regress.sql
regress/lwgeom_regress_expected

diff --git a/NEWS b/NEWS
index 8eefaeafeec401797f51415bc6bfc86b4e5795e9..2f91b128643fa8e6a07d8f30a09a8f42ad807c4e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+PostGIS 2.3.8
+2018/xx/xx
+
+  * Bug Fixes and Enchantments
+
+  - #4071, ST_ClusterKMeans crash on NULL/EMPTY fixed (Darafei Praliaskouski)
+
+
 PostGIS 2.3.7
 2018/04/06
 
index 53d02aecc4ae12b990c72e7572c29c44ef88827f..4720956a7d7aa41cfe031ae02ecbe5a3db0bbb5c 100644 (file)
@@ -92,7 +92,7 @@ lwgeom_cluster_2d_kmeans(const LWGEOM **geoms, int ngeoms, int k)
        assert(k>0);
        assert(ngeoms>0);
        assert(geoms);
-       
+
        if (ngeoms<k)
        {
                lwerror("%s: number of geometries is less than the number of clusters requested", __func__);
@@ -182,7 +182,7 @@ lwgeom_cluster_2d_kmeans(const LWGEOM **geoms, int ngeoms, int k)
 
                /* Find the data point closest to the calculated point */
                closest = lwkmeans_pt_closest(config.objs, config.num_objs, &p);
-               
+
                /* If something is terrible wrong w/ data, cannot find a closest */
                if (closest < 0)
                        lwerror("unable to calculate cluster seed points, too many NULLs or empties?");
@@ -193,7 +193,16 @@ lwgeom_cluster_2d_kmeans(const LWGEOM **geoms, int ngeoms, int k)
                {
                        if (seen[j] == closest)
                        {
-                               closest = (closest + 1) % config.num_objs;
+                               int k, t;
+                               for (k = 1; k < config.num_objs; k++)
+                               {
+                                       t = (closest + k) % config.num_objs;
+                                       if (config.objs[t])
+                                       {
+                                               closest = t;
+                                               break;
+                                       }
+                               }
                                j = 0;
                        }
                        else
index f66a4766bddc0898d5139ac9846a05e5e5066ddf..22c026a552c5ff93007dd5a13cec9b8405ddf8d7 100644 (file)
@@ -135,3 +135,11 @@ SELECT 'BoundingDiagonal5', ST_AsEwkt(ST_BoundingDiagonal(
 SELECT 'BoundingDiagonal6', ST_AsEwkt(ST_BoundingDiagonal(
     'SRID=3857;POLYGON M EMPTY'::geometry
 ));
+
+-- check that null and empty is handled in the clustering
+select '#4071', count(distinct a), count(distinct b), count(distinct c)  from
+(select
+       ST_ClusterKMeans(geom, 1) over () a,
+       ST_ClusterKMeans(geom, 2) over () b,
+       ST_ClusterKMeans(geom, 3) over () c
+from (values (null::geometry), ('POINT(1 1)'), ('POINT EMPTY'), ('POINT(0 0)'), ('POINT(4 4)')) as g (geom)) z;
index 6bc193ed0b995b4c316287b165379d2ef1bd6580..9597ccc79f41489c8aeb821b37d8cb45ee67109c 100644 (file)
@@ -21,3 +21,4 @@ BoundingDiagonal3|SRID=4326;LINESTRING(999999986991104 999999986991104,999999986
 BoundingDiagonal4|SRID=3857;LINESTRING(-1 -2 -8 2,1 2 3 9)
 BoundingDiagonal5|SRID=3857;LINESTRINGM(4 4 0,5 4 1)
 BoundingDiagonal6|SRID=3857;LINESTRINGM EMPTY
+#4071|2|3|4