]> granicus.if.org Git - postgis/commitdiff
Fix ST_RemoveRepeatedPoints dropping one extra point in certain ptarrays
authorDarafei Praliaskouski <me@komzpa.net>
Fri, 5 Jan 2018 13:16:12 +0000 (13:16 +0000)
committerDarafei Praliaskouski <me@komzpa.net>
Fri, 5 Jan 2018 13:16:12 +0000 (13:16 +0000)
Patch by Raúl Marín Rodríguez.

Closes #3969
Closes https://github.com/postgis/postgis/pull/182

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

liblwgeom/cunit/cu_algorithm.c
liblwgeom/ptarray.c
regress/remove_repeated_points.sql
regress/remove_repeated_points_expected

index 27f121c03638f1b6fca653f58b9f59f29e770204..76fdcd7ba705c099d78dd465b44e396d29e2b11d 100644 (file)
@@ -1012,7 +1012,6 @@ static void test_lwgeom_remove_repeated_points(void)
        lwgeom_remove_repeated_points_in_place(g, 1);
        ewkt = lwgeom_to_ewkt(g);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTIPOINT(0 0,10 0,10 10,0 10,5 5)");
-       // printf("%s\n", ewkt);
        lwgeom_free(g);
        lwfree(ewkt);
 
@@ -1020,20 +1019,22 @@ static void test_lwgeom_remove_repeated_points(void)
        lwgeom_remove_repeated_points_in_place(g, 0.01);
        ewkt = lwgeom_to_ewkt(g);
        CU_ASSERT_STRING_EQUAL(ewkt, "LINESTRING(1612830.15445 4841287.12672,1612829.98813 4841274.56198)");
-       // printf("%s\n", ewkt);
        lwgeom_free(g);
        lwfree(ewkt);
 
-
        g = lwgeom_from_wkt("MULTIPOINT(0 0,10 0,10 10,10 10,0 10,0 10,0 10,0 0,0 0,0 0,5 5,5 5,5 8,8 8,8 8,8 8,8 5,8 5,5 5,5 5,5 5,5 5,5 5,50 50,50 50,50 50,50 60,50 60,50 60,60 60,60 50,60 50,50 50,55 55,55 58,58 58,58 55,58 55,55 55)", LW_PARSER_CHECK_NONE);
        lwgeom_remove_repeated_points_in_place(g, 1);
        ewkt = lwgeom_to_ewkt(g);
        CU_ASSERT_STRING_EQUAL(ewkt, "MULTIPOINT(0 0,10 0,10 10,0 10,5 5,5 8,8 8,8 5,50 50,50 60,60 60,60 50,55 55,55 58,58 58,58 55)");
-       // printf("%s\n", ewkt);
        lwgeom_free(g);
        lwfree(ewkt);
 
-
+       g = lwgeom_from_wkt("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))", LW_PARSER_CHECK_NONE);
+       lwgeom_remove_repeated_points_in_place(g, 10000);
+       ewkt = lwgeom_to_ewkt(g);
+       CU_ASSERT_STRING_EQUAL(ewkt, "POLYGON((0 0,1 1,1 0,0 0))");
+       lwgeom_free(g);
+       lwfree(ewkt);
 }
 
 static void test_lwgeom_simplify(void)
index 639e7b5a3627bf5d51eec5d2e5453e0b4e720662..b1857dabb0a8fde42621c33b5bf89bdb7bd3622e 100644 (file)
@@ -1452,52 +1452,48 @@ ptarray_remove_repeated_points_in_place(POINTARRAY *pa, double tolerance, int mi
        const POINT2D *last = NULL;
        const POINT2D *pt;
        int n_points = pa->npoints;
-       int n_points_out = 0;
-       int pt_size = ptarray_point_size(pa);
+       int n_points_out = 1;
        double dsq = FLT_MAX;
 
        /* No-op on short inputs */
-       if ( n_points <= 2 ) return;
+       if ( n_points <= min_points ) return;
 
-       for (i = 0; i < n_points; i++)
+       last = getPoint2d_cp(pa, 0);
+       for (i = 1; i < n_points; i++)
        {
                int last_point = (i == n_points-1);
 
                /* Look straight into the abyss */
                pt = getPoint2d_cp(pa, i);
 
-               /* Preserve first point always */
-               if (last)
+               /* Don't drop points if we are running short of points */
+               if (n_points - i > min_points - n_points_out)
                {
-                       /* Don't drop points if we are running short of points */
-                       if (n_points - i > min_points - n_points_out)
+                       if (tolerance > 0.0)
                        {
-                               if (tolerance > 0.0)
+                               /* Only drop points that are within our tolerance */
+                               dsq = distance2d_sqr_pt_pt(last, pt);
+                               /* Allow any point but the last one to be dropped */
+                               if (!last_point && dsq <= tolsq)
                                {
-                                       /* Only drop points that are within our tolerance */
-                                       dsq = distance2d_sqr_pt_pt(last, pt);
-                                       /* Allow any point but the last one to be dropped */
-                                       if (!last_point && dsq <= tolsq)
-                                       {
-                                               continue;
-                                       }
-                               }
-                               else
-                               {
-                                       /* At tolerance zero, only skip exact dupes */
-                                       if (memcmp((char*)pt, (char*)last, pt_size) == 0)
-                                               continue;
+                                       continue;
                                }
                        }
-               }
+                       else
+                       {
+                               /* At tolerance zero, only skip exact dupes */
+                               if (memcmp((char*)pt, (char*)last, ptarray_point_size(pa)) == 0)
+                                       continue;
+                       }
 
-               /* Got to last point, and it's not very different from */
-               /* the point that preceded it. We want to keep the last */
-               /* point, not the second-to-last one, so we pull our write */
-               /* index back one value */
-               if (last_point && n_points_out > 1 && tolerance > 0.0 && dsq <= tolsq)
-               {
-                       n_points_out--;
+                       /* Got to last point, and it's not very different from */
+                       /* the point that preceded it. We want to keep the last */
+                       /* point, not the second-to-last one, so we pull our write */
+                       /* index back one value */
+                       if (last_point && n_points_out > 1 && tolerance > 0.0 && dsq <= tolsq)
+                       {
+                               n_points_out--;
+                       }
                }
 
                /* Compact all remaining values to front of array */
index e8bf3ba8b0f44b8f9a496a930163ce009aefa859..4b6b4a04a134c7770dca07448b23665f43f6a323 100644 (file)
@@ -27,5 +27,6 @@ SELECT 14, ST_AsText(ST_RemoveRepeatedPoints('LINESTRING(10 0,10 9,10 10)', 2));
 SELECT 15, ST_AsText(ST_RemoveRepeatedPoints('MULTIPOINT(0 0, 0 0, 1 1, 2 2)'::geometry));
 SELECT 16, ST_AsText(ST_RemoveRepeatedPoints('MULTIPOINT(0 0, 0 0, 1 1, 2 2)'::geometry,0.1));
 SELECT 17, ST_AsText(ST_RemoveRepeatedPoints('MULTIPOINT(0 0, 0 0, 1 1, 4 4)'::geometry,2));
+SELECT 18, ST_AsText(ST_RemoveRepeatedPoints('POLYGON((-215922 5325694,-218080 5321866,-218693 5322119,-216112 5325812,-215922 5325694))'::geometry, 10000));
 
 
index e15d235b5983421430273620ed591c47a3c94d9e..13e07ff42a846017a86ff85746f6b851e3633ff0 100644 (file)
@@ -16,3 +16,4 @@
 15|MULTIPOINT(0 0,1 1,2 2)
 16|MULTIPOINT(0 0,1 1,2 2)
 17|MULTIPOINT(0 0,4 4)
+18|POLYGON((-215922 5325694,-218693 5322119,-216112 5325812,-215922 5325694))