]> granicus.if.org Git - postgis/commitdiff
ST_RemoveRepeatedPoints [RT-SIGTA]
authorSandro Santilli <strk@keybit.net>
Sun, 21 Feb 2010 12:22:08 +0000 (12:22 +0000)
committerSandro Santilli <strk@keybit.net>
Sun, 21 Feb 2010 12:22:08 +0000 (12:22 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@5273 b70326c6-7e19-0410-871a-916f4a2858ee

14 files changed:
NEWS
doc/reference_processing.xml
liblwgeom/liblwgeom.h
liblwgeom/lwcollection.c
liblwgeom/lwgeom.c
liblwgeom/lwline.c
liblwgeom/lwmpoint.c
liblwgeom/lwpoly.c
liblwgeom/ptarray.c
postgis/lwgeom_functions_basic.c
postgis/postgis.sql.in.c
regress/Makefile.in
regress/remove_repeated_points.sql [new file with mode: 0644]
regress/remove_repeated_points_expected [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index e8a3dd7214aacea09933e955b20bab79803b81b7..42a4eecd1789f36a49476dcaa53eb0275df002f1 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@ YYYY/MM/DD
   * New Features *
 
   - ST_isValidDetail (Sandro Santilli - work done for Regione Toscana-SIGTA)
+  - ST_RemoveRepeatedPoints (Sandro Santilli for RT-SIGTA)
 
 PostGIS 1.5.0
 2010/02/04
index e075f42ac9749c531d27a5dcd18aa7534c3b155e..e10396252e880c125d760df7232b1a0e0ba4578b 100644 (file)
@@ -1548,6 +1548,40 @@ FROM (SELECT ST_Buffer('POINT(1 3)', 10,12) As the_geom) As foo;
                  </refsection>
        </refentry>
 
+       <refentry id="ST_RemoveRepeatedPoints">
+         <refnamediv>
+               <refname>ST_RemoveRepeatedPoints</refname>
+               <refpurpose>Returns a version of the given geometry with
+                               duplicated points removed.</refpurpose>
+         </refnamediv>
+
+         <refsynopsisdiv>
+               <funcsynopsis>
+                 <funcprototype>
+                       <funcdef>geometry <function>ST_RemoveRepeatedPoints</function></funcdef>
+                       <paramdef><type>geometry</type> <parameter>geom</parameter></paramdef>
+                 </funcprototype>
+               </funcsynopsis>
+         </refsynopsisdiv>
+
+         <refsection>
+               <title>Description</title>
+               <para>Returns a version of the given geometry with
+                               duplicated points emoved. Will actually do something only with
+                               (multi)lines, (multi)polygons and multipoints but you can safely call it with
+                               any kind of geometry. Since simplification occurs on a
+                               object-by-object basis you can also feed a GeometryCollection to
+                               this function.</para>
+
+               <para>Availability: 2.0.0</para>
+         </refsection>
+
+                 <refsection>
+                       <title>See Also</title>
+                       <para><xref linkend="ST_Simplify" /></para>
+                 </refsection>
+       </refentry>
+
        <refentry id="ST_SymDifference">
          <refnamediv>
                <refname>ST_SymDifference</refname>
index 980afe1552c1c2919f088b324e244641de0c7d11..45f55b2652566ba80847b389d05bc83b412df617 100644 (file)
@@ -3,9 +3,10 @@
  *
  * PostGIS - Spatial Types for PostgreSQL
  * http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
- * Copyright 2007-2008 Mark Cave-Ayland
+ * Copyright 2010 Sandro Santilli <strk@keybit.net>
  * Copyright 2008 Paul Ramsey <pramsey@cleverelephant.ca>
+ * Copyright 2007-2008 Mark Cave-Ayland
+ * Copyright 2001-2006 Refractions Research Inc.
  *
  * This is free software; you can redistribute and/or modify it under
  * the terms of the GNU General Public Licence. See the COPYING file.
@@ -1372,7 +1373,6 @@ extern POINTARRAY *ptarray_addPoint(const POINTARRAY *pa, uchar *p, size_t pdims
                                            unsigned int where);
 extern POINTARRAY *ptarray_removePoint(POINTARRAY *pa, unsigned int where);
 extern POINTARRAY *ptarray_merge(POINTARRAY *pa1, POINTARRAY *pa2);
-extern POINTARRAY *ptarray_remove_repeated_points(POINTARRAY *in);
 
 extern int ptarray_isclosed2d(const POINTARRAY *pa);
 extern int ptarray_isclosed3d(const POINTARRAY *pa);
@@ -1387,6 +1387,18 @@ extern void closest_point_on_segment(POINT2D *p, POINT2D *A, POINT2D *B, POINT2D
 extern LWLINE *lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end);
 extern LWMLINE* lwmline_measured_from_lwmline(const LWMLINE *lwmline, double m_start, double m_end);
 
+/*
+ * Remove adjacent duplicated points from given argument.
+ *
+ * Always return a newly allocated object.
+ */
+extern POINTARRAY *ptarray_remove_repeated_points(POINTARRAY *in);
+extern LWGEOM *lwmpoint_remove_repeated_points(LWMPOINT *in);
+extern LWGEOM *lwline_remove_repeated_points(LWLINE *in);
+extern LWGEOM *lwpoly_remove_repeated_points(LWPOLY *in);
+extern LWGEOM *lwcollection_remove_repeated_points(LWCOLLECTION *in);
+extern LWGEOM *lwgeom_remove_repeated_points(LWGEOM *in);
+
 /*
  * Ensure every segment is at most 'dist' long.
  * Returned LWGEOM might is unchanged if a POINT.
index a7c7c77a2dc5d45e53e51eeb2f8e90f650f26c79..e9029ca4bb55dcbe71c700c33b16aa4a386822b9 100644 (file)
@@ -605,3 +605,20 @@ LWCOLLECTION* lwcollection_extract(LWCOLLECTION *col, int type)
        return outcol;
 }
 
+LWGEOM*
+lwcollection_remove_repeated_points(LWCOLLECTION *coll)
+{
+       unsigned int i;
+       LWGEOM **newgeoms;
+
+       newgeoms = lwalloc(sizeof(LWGEOM *)*coll->ngeoms);
+       for (i=0; i<coll->ngeoms; i++)
+       {
+               newgeoms[i] = lwgeom_remove_repeated_points(coll->geoms[i]);
+       }
+
+       return (LWGEOM*)lwcollection_construct(coll->type,
+                                              coll->SRID, coll->bbox ? box2d_clone(coll->bbox) : NULL,
+                                              coll->ngeoms, newgeoms);
+
+}
index 734090565a6934cffcb6ec6d730fb0b958259f57..93687c43d2e6718fbe65ca5750bff2da44ea4905 100644 (file)
@@ -1177,3 +1177,44 @@ extern int lwgeom_dimensionality(LWGEOM *geom)
        }
        return 0;
 }
+
+extern LWGEOM* lwgeom_remove_repeated_points(LWGEOM *in)
+{
+       LWDEBUGF(3, "lwgeom_remove_repeated_points got type %d", TYPE_GETTYPE(in->type));
+       switch (TYPE_GETTYPE(in->type))
+       {
+       case MULTIPOINTTYPE:
+               return lwmpoint_remove_repeated_points((LWMPOINT*)in);
+               break;
+       case LINETYPE:
+               return lwline_remove_repeated_points((LWLINE*)in);
+
+       case MULTILINETYPE:
+       case COLLECTIONTYPE:
+       case MULTIPOLYGONTYPE:
+               return lwcollection_remove_repeated_points((LWCOLLECTION *)in);
+
+       case POLYGONTYPE:
+               return lwpoly_remove_repeated_points((LWPOLY *)in);
+               break;
+
+       case POINTTYPE:
+               /* No point is repeated for a single point */
+               return in;
+
+       case CIRCSTRINGTYPE:
+       case COMPOUNDTYPE:
+       case MULTICURVETYPE:
+       case CURVEPOLYTYPE:
+       case MULTISURFACETYPE:
+               /* Dunno how to handle these, will return untouched */
+               return in;
+
+       default:
+               lwnotice("unsupported input geometry type: %d",
+                        TYPE_GETTYPE(in->type));
+               return in;
+               break;
+       }
+       return 0;
+}
index bc5b03ecb38e1c4e8f08ad0c0c01a8fae8567953..790f9ba8cfa1f7eb147854503e5a216ffc041b80 100644 (file)
@@ -585,3 +585,15 @@ lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end)
 
        return lwline_construct(lwline->SRID, NULL, pa);
 }
+
+LWGEOM*
+lwline_remove_repeated_points(LWLINE *lwline)
+{
+       POINTARRAY* npts = ptarray_remove_repeated_points(lwline->points);
+
+       LWDEBUGF(3, "lwline_remove_repeated_points: npts %p", npts);
+
+       return (LWGEOM*)lwline_construct(lwline->SRID,
+                                        lwline->bbox ? box2d_clone(lwline->bbox) : 0,
+                                        npts);
+}
index 9983087e6e5b3416ee851d266697537c3777e30c..7960d90b44b28d7c02bde44c00a55001f6c73d68 100644 (file)
@@ -148,3 +148,35 @@ void lwmpoint_free(LWMPOINT *mpt)
 
 }
 
+LWGEOM*
+lwmpoint_remove_repeated_points(LWMPOINT *mpoint)
+{
+       unsigned int nnewgeoms;
+       unsigned int i, j;
+       LWGEOM **newgeoms;
+
+       newgeoms = lwalloc(sizeof(LWGEOM *)*mpoint->ngeoms);
+       nnewgeoms = 0;
+       for (i=0; i<mpoint->ngeoms; ++i)
+       {
+               /* Brute force, may be optimized by building an index */
+               int seen=0;
+               for (j=0; j<nnewgeoms; ++j)
+               {
+                       if ( lwpoint_same((LWPOINT*)newgeoms[j],
+                                         (LWPOINT*)mpoint->geoms[i]) )
+                       {
+                               seen=1;
+                               break;
+                       }
+               }
+               if ( seen ) continue;
+               newgeoms[nnewgeoms++] = (LWGEOM*)lwpoint_clone(mpoint->geoms[i]);
+       }
+
+       return (LWGEOM*)lwcollection_construct(mpoint->type,
+                                              mpoint->SRID, mpoint->bbox ? box2d_clone(mpoint->bbox) : NULL,
+                                              nnewgeoms, newgeoms);
+
+}
+
index 9450184a384f9650a5eb49160257a92f1354b1e9..34c680418d375ce0657954dc133b92627c34f32d 100644 (file)
@@ -591,3 +591,21 @@ lwpoly_from_lwlines(const LWLINE *shell,
        ret = lwpoly_construct(SRID, NULL, nrings, rings);
        return ret;
 }
+
+LWGEOM*
+lwpoly_remove_repeated_points(LWPOLY *poly)
+{
+       unsigned int i;
+       POINTARRAY **newrings;
+
+       newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
+       for (i=0; i<poly->nrings; i++)
+       {
+               newrings[i] = ptarray_remove_repeated_points(poly->rings[i]);
+       }
+
+       return (LWGEOM*)lwpoly_construct(poly->SRID,
+                                        poly->bbox ? box2d_clone(poly->bbox) : NULL,
+                                        poly->nrings, newrings);
+
+}
index 216259604dc97ac7d4fc40d58cf12526334eeb2e..375f2543c3a364ccbfbca102f68aef4845ca222d 100644 (file)
@@ -915,8 +915,7 @@ dynptarray_addPoint4d(DYNPTARRAY *dpa, POINT4D *p4d, int allow_duplicates)
  * Returns a POINTARRAY with consecutive equal points
  * removed. Equality test on all dimensions of input.
  *
- * May return the input untouched, or a newly allocated
- * POINTARRAY (and point list)
+ * Always returns a newly allocated object.
  *
  */
 POINTARRAY *
@@ -929,10 +928,12 @@ ptarray_remove_repeated_points(POINTARRAY *in)
        LWDEBUG(3, "ptarray_remove_repeated_points called.");
 
        /* Single or zero point arrays can't have duplicates */
-       if ( in->npoints < 2 ) return in;
+       if ( in->npoints < 2 ) return ptarray_clone(in);
 
        ptsize = pointArray_ptsize(in);
 
+       LWDEBUGF(3, "ptsize: %d", ptsize);
+
        /* Allocate enough space for all points */
        out = ptarray_construct(TYPE_HASZ(in->dims),
                                TYPE_HASM(in->dims), in->npoints);
@@ -940,7 +941,8 @@ ptarray_remove_repeated_points(POINTARRAY *in)
        /* Now fill up the actual points (NOTE: could be optimized) */
 
        opn=1;
-       memcpy(getPoint_internal(in, 0), getPoint_internal(out, 0), ptsize);
+       memcpy(getPoint_internal(out, 0), getPoint_internal(in, 0), ptsize);
+       LWDEBUGF(3, " first point copied, out points: %d", opn);
        for (ipn=1; ipn<in->npoints; ++ipn)
        {
                if ( memcmp(getPoint_internal(in, ipn-1),
@@ -948,11 +950,14 @@ ptarray_remove_repeated_points(POINTARRAY *in)
                {
                        /* The point is different from the previous,
                         * we add it to output */
-                       memcpy(getPoint_internal(in, ipn),
-                              getPoint_internal(out, opn++), ptsize);
+                       memcpy(getPoint_internal(out, opn++),
+                              getPoint_internal(in, ipn), ptsize);
+                       LWDEBUGF(3, " Point %d differs from point %d. Out points: %d",
+                                ipn, ipn-1, opn);
                }
        }
 
+       LWDEBUGF(3, " in:%d out:%d", out->npoints, opn);
        out->npoints = opn;
 
        return out;
index 81c51f71c54acf8c00f964a8c4bc06d85e60b200..724acea10388cc7ed843c5c51f054bc0ce3480da 100644 (file)
@@ -3630,3 +3630,23 @@ Datum ST_CollectionExtract(PG_FUNCTION_ARGS)
 
        PG_RETURN_POINTER(output);
 }
+
+Datum ST_RemoveRepeatedPoints(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(ST_RemoveRepeatedPoints);
+Datum ST_RemoveRepeatedPoints(PG_FUNCTION_ARGS)
+{
+       PG_LWGEOM *input = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       PG_LWGEOM *output;
+       LWGEOM *lwgeom_in = pglwgeom_deserialize(input);
+       LWGEOM *lwgeom_out;
+
+       /* lwnotice("ST_RemoveRepeatedPoints got %p", lwgeom_in); */
+
+       lwgeom_out = lwgeom_remove_repeated_points(lwgeom_in);
+       output = pglwgeom_serialize(lwgeom_out);
+
+       lwgeom_free(lwgeom_in);
+       PG_FREE_IF_COPY(input, 0);
+
+       PG_RETURN_POINTER(output);
+}
index 89a87d000a0fe712e732acb5199322656f0ee42b..f1fe7b4c8440e7b63972156a4f9edb6f2bcf852d 100644 (file)
@@ -4014,6 +4014,19 @@ CREATE OR REPLACE FUNCTION ST_Union(geometry,geometry)
        AS 'MODULE_PATHNAME','geomunion'
        LANGUAGE 'C' IMMUTABLE STRICT;
 
+-- ST_RemoveRepeatedPoint(in geometry)
+--
+-- Removes duplicate vertices in input.
+-- Only checks consecutive points for lineal and polygonal geoms.
+-- Checks all points for multipoint geoms.
+--
+-- Availability: 2.0.0
+CREATE OR REPLACE FUNCTION ST_RemoveRepeatedPoints(geometry)
+       RETURNS geometry
+       AS 'MODULE_PATHNAME', 'ST_RemoveRepeatedPoints'
+       LANGUAGE 'C' IMMUTABLE STRICT
+       COST 100;
+
 --------------------------------------------------------------------------------
 -- ST_CleanGeometry / ST_MakeValid
 --------------------------------------------------------------------------------
index f9cb167afac8718fa03c2aff5b8b5488232b9afb..52ef890c85bce1a13d8159b8c44b6332e1af4a98 100644 (file)
@@ -70,7 +70,8 @@ TESTS = \
        dumppoints \
        wmsservers \
        tickets \
-       clean
+       clean \
+       remove_repeated_points
 
 # Styled buffer only if GEOS >= 3.2
 ifeq ($(shell expr $(POSTGIS_GEOS_VERSION) ">=" 32),1)
diff --git a/regress/remove_repeated_points.sql b/regress/remove_repeated_points.sql
new file mode 100644 (file)
index 0000000..5e2ff1f
--- /dev/null
@@ -0,0 +1,38 @@
+SELECT 0, ST_AsText(ST_RemoveRepeatedPoints('GEOMETRYCOLLECTION EMPTY'));
+SELECT 1, ST_AsText(ST_RemoveRepeatedPoints('LINESTRING(0 0, 1 1, 1 1, 2 2)'));
+SELECT 2, ST_AsText(ST_RemoveRepeatedPoints('LINESTRING(0 0, 1 1, 1 1, 2 2, 2 2, 2 2, 2 2, 3 3, 3 3)'));
+SELECT 3, ST_AsText(ST_RemoveRepeatedPoints('MULTILINESTRING((0 0, 1 1, 1 1, 2 2, 2 2, 2 2, 2 2, 3 3, 3 3),(5 5, 5 5, 5 5, 4 4, 2 2))'));
+SELECT 4, ST_AsText(ST_RemoveRepeatedPoints('POLYGON((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))'));
+SELECT 5, ST_AsText(ST_RemoveRepeatedPoints('MULTIPOLYGON(((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)))'));
+SELECT 6, ST_AsText(ST_RemoveRepeatedPoints('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)'));
+SELECT 7, ST_AsText(ST_RemoveRepeatedPoints('GEOMETRYCOLLECTION(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),MULTIPOLYGON(((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))))'));
+SELECT 8, ST_AsText(ST_RemoveRepeatedPoints('POINT(0 0)'));
+SELECT 9, ST_AsText(ST_RemoveRepeatedPoints('CURVEPOLYGON(CIRCULARSTRING(
+                -2 0 0 0,
+                -1 -1 1 2,
+                0 0 2 4,
+                1 -1 3 6,
+                2 0 4 8,
+                0 2 2 4,
+                -2 0 0 0),
+                (-1 0 1 2,                                                                      0 0.5 2 4,
+                1 0 3 6,                                                                        0 1 3 4,                                                                        -1 0 1 2))'));        
+SELECT 0, ST_AsText(ST_RemoveRepeatedPoints('GEOMETRYCOLLECTION EMPTY'));
+SELECT 1, ST_AsText(ST_RemoveRepeatedPoints('LINESTRING(0 0, 1 1, 1 1, 2 2)'));
+SELECT 2, ST_AsText(ST_RemoveRepeatedPoints('LINESTRING(0 0, 1 1, 1 1, 2 2, 2 2, 2 2, 2 2, 3 3, 3 3)'));
+SELECT 3, ST_AsText(ST_RemoveRepeatedPoints('MULTILINESTRING((0 0, 1 1, 1 1, 2 2, 2 2, 2 2, 2 2, 3 3, 3 3),(5 5, 5 5, 5 5, 4 4, 2 2))'));
+SELECT 4, ST_AsText(ST_RemoveRepeatedPoints('POLYGON((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))'));
+SELECT 5, ST_AsText(ST_RemoveRepeatedPoints('MULTIPOLYGON(((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)))'));
+SELECT 6, ST_AsText(ST_RemoveRepeatedPoints('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)'));
+SELECT 7, ST_AsText(ST_RemoveRepeatedPoints('GEOMETRYCOLLECTION(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),MULTIPOLYGON(((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))))'));
+SELECT 8, ST_AsText(ST_RemoveRepeatedPoints('POINT(0 0)'));
+SELECT 9, ST_AsText(ST_RemoveRepeatedPoints('CURVEPOLYGON(CIRCULARSTRING(
+                -2 0 0 0,
+                -1 -1 1 2,
+                0 0 2 4,
+                1 -1 3 6,
+                2 0 4 8,
+                0 2 2 4,
+                -2 0 0 0),
+                (-1 0 1 2,                                                                      0 0.5 2 4,
+                1 0 3 6,                                                                        0 1 3 4,                                                                        -1 0 1 2))'));        
diff --git a/regress/remove_repeated_points_expected b/regress/remove_repeated_points_expected
new file mode 100644 (file)
index 0000000..002b3ec
--- /dev/null
@@ -0,0 +1,20 @@
+0|GEOMETRYCOLLECTION EMPTY
+1|LINESTRING(0 0,1 1,2 2)
+2|LINESTRING(0 0,1 1,2 2,3 3)
+3|MULTILINESTRING((0 0,1 1,2 2,3 3),(5 5,4 4,2 2))
+4|POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,5 8,8 8,8 5,5 5))
+5|MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(5 5,5 8,8 8,8 5,5 5)),((50 50,50 60,60 60,60 50,50 50),(55 55,55 58,58 58,58 55,55 55)))
+6|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)
+7|GEOMETRYCOLLECTION(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),MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(5 5,5 8,8 8,8 5,5 5)),((50 50,50 60,60 60,60 50,50 50),(55 55,55 58,58 58,58 55,55 55))))
+8|POINT(0 0)
+9|CURVEPOLYGON(CIRCULARSTRING(-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0 0.5,1 0,0 1,-1 0))
+0|GEOMETRYCOLLECTION EMPTY
+1|LINESTRING(0 0,1 1,2 2)
+2|LINESTRING(0 0,1 1,2 2,3 3)
+3|MULTILINESTRING((0 0,1 1,2 2,3 3),(5 5,4 4,2 2))
+4|POLYGON((0 0,10 0,10 10,0 10,0 0),(5 5,5 8,8 8,8 5,5 5))
+5|MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(5 5,5 8,8 8,8 5,5 5)),((50 50,50 60,60 60,60 50,50 50),(55 55,55 58,58 58,58 55,55 55)))
+6|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)
+7|GEOMETRYCOLLECTION(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),MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(5 5,5 8,8 8,8 5,5 5)),((50 50,50 60,60 60,60 50,50 50),(55 55,55 58,58 58,58 55,55 55))))
+8|POINT(0 0)
+9|CURVEPOLYGON(CIRCULARSTRING(-2 0,-1 -1,0 0,1 -1,2 0,0 2,-2 0),(-1 0,0 0.5,1 0,0 1,-1 0))