* PostGIS - Spatial Types for PostgreSQL
* http://postgis.refractions.net
*
- * Copyright (C) 2011 Sandro Santilli <strk@keybit.net>
+ * Copyright (C) 2011-2012 Sandro Santilli <strk@keybit.net>
* Copyright (C) 2011 Paul Ramsey <pramsey@cleverelephant.ca>
* Copyright (C) 2007-2008 Mark Cave-Ayland
* Copyright (C) 2001-2006 Refractions Research Inc.
/*
* DP simplification
*/
-POINTARRAY* ptarray_simplify(POINTARRAY *inpts, double epsilon);
+
+/**
+ * @param minpts minimun number of points to retain, if possible.
+ */
+POINTARRAY* ptarray_simplify(POINTARRAY *inpts, double epsilon, unsigned int minpts);
LWLINE* lwline_simplify(const LWLINE *iline, double dist);
LWPOLY* lwpoly_simplify(const LWPOLY *ipoly, double dist);
LWCOLLECTION* lwcollection_simplify(const LWCOLLECTION *igeom, double dist);
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.refractions.net
*
+ * Copyright (C) 2012 Sandro Santilli <strk@keybit.net>
* Copyright (C) 2001-2006 Refractions Research Inc.
*
* This is free software; you can redistribute and/or modify it under
if( lwline_is_empty(iline) )
return lwline_clone(iline);
- oline = lwline_construct(iline->srid, NULL, ptarray_simplify(iline->points, dist));
+ oline = lwline_construct(iline->srid, NULL, ptarray_simplify(iline->points, dist, 2));
oline->type = iline->type;
return oline;
}
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.refractions.net
*
+ * Copyright (C) 2012 Sandro Santilli <strk@keybit.net>
* Copyright (C) 2001-2006 Refractions Research Inc.
*
* This is free software; you can redistribute and/or modify it under
for (i = 0; i < ipoly->nrings; i++)
{
- POINTARRAY *opts = ptarray_simplify(ipoly->rings[i], dist);
-
- /* One point implies an error in the ptarray_simplify */
- if ( i && ( opts->npoints < 2 ) )
- {
- LWDEBUG(2, "ptarray_simplify returned a <2 pts array");
- ptarray_free(opts);
- continue;
- }
+ POINTARRAY *opts = ptarray_simplify(ipoly->rings[i], dist, 3);
/* Less points than are needed to form a closed ring, we can't use this */
- if ( i && ( opts->npoints < 4 ) )
+ if ( i && opts->npoints < 4 )
{
- LWDEBUGF(3, "ring%d skipped (<4 pts)", i);
+ LWDEBUGF(3, "ring%d skipped (% pts)", i, opts->npoints);
ptarray_free(opts);
- if ( i ) continue;
- else break;
+ continue;
}
LWDEBUGF(3, "ring%d simplified from %d to %d points", i, ipoly->rings[i]->npoints, opts->npoints);
/* Add ring to simplified polygon */
if( lwpoly_add_ring(opoly, opts) == LW_FAILURE )
return NULL;
+
+ /* Don't scan holes if shell is collapsed */
+ if ( !i && opts->npoints < 4 )
+ {
+ LWDEBUG(3, "nothing more to do for collapsed shell");
+ break;
+ }
}
LWDEBUGF(3, "simplified polygon with %d rings", ipoly->nrings);
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.refractions.net
- * Copyright 2001-2006 Refractions Research Inc.
+ *
+ * Copyright (C) 2012 Sandro Santilli <strk@keybit.net>
+ * Copyright (C) 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.
}
POINTARRAY *
-ptarray_simplify(POINTARRAY *inpts, double epsilon)
+ptarray_simplify(POINTARRAY *inpts, double epsilon, unsigned int minpts)
{
int *stack; /* recursion stack */
int sp=-1; /* recursion stack pointer */
p1 = 0;
stack[++sp] = inpts->npoints-1;
- LWDEBUGF(2, "Input has %d pts and %d dims", inpts->npoints, inpts->flags);
+ LWDEBUGF(2, "Input has %d pts and %d dims", inpts->npoints,
+ FLAGS_NDIMS(inpts->flags));
/* Allocate output POINTARRAY, and add first point. */
outpts = ptarray_construct_empty(FLAGS_GET_Z(inpts->flags), FLAGS_GET_M(inpts->flags), inpts->npoints);
LWDEBUGF(3, "Farthest point from P%d-P%d is P%d (dist. %g)", p1, stack[sp], split, dist);
- if (dist > epsilon)
+ if (dist > epsilon || ( outpts->npoints+sp+1 < minpts && dist > 0 ) )
{
+ LWDEBUGF(4, "Added P%d to stack (outpts:%d, minpts:%d)", split, sp, minsplits);
stack[++sp] = split;
}
else
SELECT '6', ST_astext(ST_Simplify('MULTILINESTRING((0 0 3 2, 0 10 6 1, 0 51 1 6, 50 20 6 7, 30 20 9 9, 7 32 10 5), (0 0 4 3, 1 1 2 3, 20 20 5 30))', 20));
SELECT '7', ST_astext(ST_Simplify('POLYGON((0 0 3 2, 0 10 6 1, 0 51 1 6, 50 20 6 7, 30 20 9 9, 7 32 10 5, 0 0 3 2), (1 1 4 3, 1 3 2 3, 18 18 5 30, 1 1 4 3))', 20));
SELECT '8', ST_astext(ST_Simplify('POLYGON((0 0 3 2, 0 10 6 1, 0 51 1 6, 50 20 6 7, 30 20 9 9, 7 32 10 5, 0 0 3 2), (1 1 4 3, 1 3 2 3, 18 18 5 30, 1 1 4 3))', 1));
+
+SELECT '9', ST_astext(ST_Simplify('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))', 20));