[postgis-tickets] r15942 - Back out ptarray changes for now (references #3877)
Paul Ramsey
pramsey at cleverelephant.ca
Tue Oct 10 06:26:03 PDT 2017
Author: pramsey
Date: 2017-10-10 06:26:02 -0700 (Tue, 10 Oct 2017)
New Revision: 15942
Modified:
trunk/liblwgeom/cunit/cu_algorithm.c
trunk/liblwgeom/liblwgeom_internal.h
trunk/liblwgeom/lwcollection.c
trunk/liblwgeom/lwgeom.c
trunk/liblwgeom/lwline.c
trunk/liblwgeom/lwmpoint.c
trunk/liblwgeom/lwpoly.c
trunk/liblwgeom/ptarray.c
Log:
Back out ptarray changes for now (references #3877)
Modified: trunk/liblwgeom/cunit/cu_algorithm.c
===================================================================
--- trunk/liblwgeom/cunit/cu_algorithm.c 2017-10-10 08:29:21 UTC (rev 15941)
+++ trunk/liblwgeom/cunit/cu_algorithm.c 2017-10-10 13:26:02 UTC (rev 15942)
@@ -1003,28 +1003,6 @@
CU_ASSERT_EQUAL(gh, rs);
}
-static void test_lwgeom_remote_repeated_points(void)
-{
- LWGEOM *g;
- char *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, 0 0, 5 5)", 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)");
- // 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);
-}
-
static void test_lwgeom_simplify(void)
{
LWGEOM *l;
@@ -1314,5 +1292,4 @@
PG_ADD_TEST(suite,test_median_handles_3d_correctly);
PG_ADD_TEST(suite,test_median_robustness);
PG_ADD_TEST(suite,test_lwpoly_construct_circle);
- PG_ADD_TEST(suite,test_lwgeom_remote_repeated_points);
}
Modified: trunk/liblwgeom/liblwgeom_internal.h
===================================================================
--- trunk/liblwgeom/liblwgeom_internal.h 2017-10-10 08:29:21 UTC (rev 15941)
+++ trunk/liblwgeom/liblwgeom_internal.h 2017-10-10 13:26:02 UTC (rev 15942)
@@ -398,10 +398,12 @@
/*
* Repeated points
*/
+POINTARRAY *ptarray_remove_repeated_points_minpoints(const POINTARRAY *in, double tolerance, int minpoints);
POINTARRAY *ptarray_remove_repeated_points(const POINTARRAY *in, double tolerance);
+LWGEOM* lwmpoint_remove_repeated_points(const LWMPOINT *in, double tolerance);
LWGEOM* lwline_remove_repeated_points(const LWLINE *in, double tolerance);
-void ptarray_remove_repeated_points_in_place(POINTARRAY *pa, double tolerance, int min_points);
-void lwgeom_remove_repeated_points_in_place(LWGEOM *geom, double tolerance);
+LWGEOM* lwcollection_remove_repeated_points(const LWCOLLECTION *in, double tolerance);
+LWGEOM* lwpoly_remove_repeated_points(const LWPOLY *in, double tolerance);
/*
* Closure test
Modified: trunk/liblwgeom/lwcollection.c
===================================================================
--- trunk/liblwgeom/lwcollection.c 2017-10-10 08:29:21 UTC (rev 15941)
+++ trunk/liblwgeom/lwcollection.c 2017-10-10 13:26:02 UTC (rev 15942)
@@ -456,7 +456,24 @@
return outcol;
}
+LWGEOM*
+lwcollection_remove_repeated_points(const LWCOLLECTION *coll, double tolerance)
+{
+ uint32_t 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], tolerance);
+ }
+
+ return (LWGEOM*)lwcollection_construct(coll->type,
+ coll->srid, coll->bbox ? gbox_copy(coll->bbox) : NULL,
+ coll->ngeoms, newgeoms);
+}
+
+
LWCOLLECTION*
lwcollection_force_dims(const LWCOLLECTION *col, int hasz, int hasm)
{
Modified: trunk/liblwgeom/lwgeom.c
===================================================================
--- trunk/liblwgeom/lwgeom.c 2017-10-10 08:29:21 UTC (rev 15941)
+++ trunk/liblwgeom/lwgeom.c 2017-10-10 13:26:02 UTC (rev 15942)
@@ -1486,9 +1486,53 @@
extern LWGEOM* lwgeom_remove_repeated_points(const LWGEOM *in, double tolerance)
{
- LWGEOM *out = lwgeom_clone_deep(in);
- lwgeom_remove_repeated_points_in_place(out, tolerance);
- return out;
+ LWDEBUGF(4, "lwgeom_remove_repeated_points got type %s",
+ lwtype_name(in->type));
+
+ if(lwgeom_is_empty(in))
+ {
+ return lwgeom_clone_deep(in);
+ }
+
+ switch (in->type)
+ {
+ case MULTIPOINTTYPE:
+ return lwmpoint_remove_repeated_points((LWMPOINT*)in, tolerance);
+ break;
+ case LINETYPE:
+ return lwline_remove_repeated_points((LWLINE*)in, tolerance);
+
+ case MULTILINETYPE:
+ case COLLECTIONTYPE:
+ case MULTIPOLYGONTYPE:
+ case POLYHEDRALSURFACETYPE:
+ return lwcollection_remove_repeated_points((LWCOLLECTION *)in, tolerance);
+
+ case POLYGONTYPE:
+ return lwpoly_remove_repeated_points((LWPOLY *)in, tolerance);
+ break;
+
+ case POINTTYPE:
+ case TRIANGLETYPE:
+ case TINTYPE:
+ /* No point is repeated for a single point, or for Triangle or TIN */
+ return lwgeom_clone_deep(in);
+
+ case CIRCSTRINGTYPE:
+ case COMPOUNDTYPE:
+ case MULTICURVETYPE:
+ case CURVEPOLYTYPE:
+ case MULTISURFACETYPE:
+ /* Dunno how to handle these, will return untouched */
+ return lwgeom_clone_deep(in);
+
+ default:
+ lwnotice("%s: unsupported geometry type: %s",
+ __func__, lwtype_name(in->type));
+ return lwgeom_clone_deep(in);
+ break;
+ }
+ return 0;
}
void lwgeom_swap_ordinates(LWGEOM *in, LWORD o1, LWORD o2)
@@ -1580,152 +1624,10 @@
}
}
-
/**************************************************************/
void
-lwgeom_remove_repeated_points_in_place(LWGEOM *geom, double tolerance)
-{
- switch (geom->type)
- {
- /* No-op! Cannot remote points */
- case POINTTYPE:
- return;
- case LINETYPE:
- {
- LWLINE *g = (LWLINE*)(geom);
- POINTARRAY *pa = g->points;
- ptarray_remove_repeated_points_in_place(pa, tolerance, 2);
- /* Invalid output */
- if (pa->npoints == 1 && pa->maxpoints > 1)
- {
- /* Use first point as last point */
- pa->npoints = 2;
- ptarray_copy_point(pa, 0, 1);
- }
- break;
- }
- case POLYGONTYPE:
- {
- int i, j = 0;
- LWPOLY *g = (LWPOLY*)(geom);
- for (i = 0; i < g->nrings; i++)
- {
- POINTARRAY *pa = g->rings[i];
- int minpoints = 4;
- /* Skip zero'ed out rings */
- if(!pa)
- continue;
- ptarray_remove_repeated_points_in_place(pa, tolerance, minpoints);
- /* Drop collapsed rings */
- if(pa->npoints < 4)
- {
- ptarray_free(pa);
- continue;
- }
- g->rings[j++] = pa;
- }
- /* Update ring count */
- g->nrings = j;
- break;
- }
- case MULTIPOINTTYPE:
- {
- static int out_stack_size = 32;
- double tolsq = tolerance*tolerance;
- int i, j, n = 0;
- LWMPOINT *mpt = (LWMPOINT *)(geom);
- LWPOINT **out;
- LWPOINT *out_stack[out_stack_size];
- int use_heap = (mpt->ngeoms > out_stack_size);
-
- /* No-op on empty */
- if (mpt->ngeoms == 0) return;
-
- /* We cannot write directly back to the multipoint */
- /* geoms array because we're reading out of it still */
- /* so we use a side array */
- if (use_heap)
- out = lwalloc(sizeof(LWMPOINT *) * mpt->ngeoms);
- else
- out = out_stack;
-
- /* Inefficient O(n^2) implementation */
- for (i = 0; i < mpt->ngeoms; i++)
- {
- int seen = 0;
- LWPOINT *p1 = mpt->geoms[i];
- const POINT2D *pt1 = getPoint2d_cp(p1->point, 0);
- for (j = 0; j < n; j++)
- {
- LWPOINT *p2 = out[j];
- const POINT2D *pt2 = getPoint2d_cp(p2->point, 0);
- if (distance2d_sqr_pt_pt(pt1, pt2) <= tolsq)
- {
- seen = 1;
- break;
- }
- }
- if (seen) continue;
- out[n++] = p1;
- }
-
- /* Copy remaining points back into the input */
- /* array */
- memcpy(mpt->geoms, out, sizeof(LWPOINT *) * n);
- mpt->ngeoms = n;
- if (use_heap) lwfree(out);
- return;
- }
-
- case CIRCSTRINGTYPE:
- /* Dunno how to handle these, will return untouched */
- return;
-
- /* Can process most multi* types as generic collection */
- case MULTILINETYPE:
- case MULTIPOLYGONTYPE:
- case COLLECTIONTYPE:
- /* Curve types we mostly ignore, but allow the linear */
- /* portions to be processed by recursing into them */
- case MULTICURVETYPE:
- case CURVEPOLYTYPE:
- case MULTISURFACETYPE:
- case COMPOUNDTYPE:
- {
- int i, j = 0;
- LWCOLLECTION *col = (LWCOLLECTION*)(geom);
- for (i = 0; i < col->ngeoms; i++)
- {
- LWGEOM *g = col->geoms[i];
- if (!g) continue;
- lwgeom_remove_repeated_points_in_place(g, tolerance);
- /* Drop zero'ed out geometries */
- if(lwgeom_is_empty(g))
- {
- lwgeom_free(g);
- continue;
- }
- col->geoms[j++] = g;
- }
- /* Update geometry count */
- col->ngeoms = j;
- break;
- }
- default:
- {
- lwerror("%s: unsupported geometry type: %s", __func__, lwtype_name(geom->type));
- break;
- }
- }
- return;
-}
-
-
-/**************************************************************/
-
-void
lwgeom_simplify_in_place(LWGEOM *geom, double epsilon, int preserve_collapsed)
{
switch (geom->type)
@@ -1820,6 +1722,9 @@
return;
}
+
+/**************************************************************/
+
LWGEOM* lwgeom_simplify(const LWGEOM *igeom, double dist, int preserve_collapsed)
{
LWGEOM *lwgeom_out = lwgeom_clone_deep(igeom);
@@ -1828,9 +1733,7 @@
return lwgeom_out;
}
-/**************************************************************/
-
double lwgeom_area(const LWGEOM *geom)
{
int type = geom->type;
Modified: trunk/liblwgeom/lwline.c
===================================================================
--- trunk/liblwgeom/lwline.c 2017-10-10 08:29:21 UTC (rev 15941)
+++ trunk/liblwgeom/lwline.c 2017-10-10 13:26:02 UTC (rev 15942)
@@ -449,7 +449,13 @@
LWGEOM*
lwline_remove_repeated_points(const LWLINE *lwline, double tolerance)
{
- return lwgeom_remove_repeated_points((LWGEOM*)lwline, tolerance);
+ POINTARRAY* npts = ptarray_remove_repeated_points_minpoints(lwline->points, tolerance, 2);
+
+ LWDEBUGF(3, "%s: npts %p", __func__, npts);
+
+ return (LWGEOM*)lwline_construct(lwline->srid,
+ lwline->bbox ? gbox_copy(lwline->bbox) : 0,
+ npts);
}
int
Modified: trunk/liblwgeom/lwmpoint.c
===================================================================
--- trunk/liblwgeom/lwmpoint.c 2017-10-10 08:29:21 UTC (rev 15941)
+++ trunk/liblwgeom/lwmpoint.c 2017-10-10 13:26:02 UTC (rev 15942)
@@ -88,7 +88,41 @@
lwfree(mpt);
}
+LWGEOM*
+lwmpoint_remove_repeated_points(const LWMPOINT *mpoint, double tolerance)
+{
+ uint32_t nnewgeoms;
+ uint32_t i, j;
+ LWGEOM **newgeoms;
+ LWGEOM *lwpt1, *lwpt2;
+ newgeoms = lwalloc(sizeof(LWGEOM *)*mpoint->ngeoms);
+ nnewgeoms = 0;
+ for (i=0; i<mpoint->ngeoms; ++i)
+ {
+ lwpt1 = (LWGEOM*)mpoint->geoms[i];
+ /* Brute force, may be optimized by building an index */
+ int seen=0;
+ for (j=0; j<nnewgeoms; ++j)
+ {
+ lwpt2 = (LWGEOM*)newgeoms[j];
+ if ( lwgeom_mindistance2d(lwpt1, lwpt2) <= tolerance )
+ {
+ seen=1;
+ break;
+ }
+ }
+ if ( seen ) continue;
+ newgeoms[nnewgeoms++] = lwgeom_clone_deep(lwpt1);
+ }
+
+ return (LWGEOM*)lwcollection_construct(mpoint->type,
+ mpoint->srid,
+ mpoint->bbox ? gbox_copy(mpoint->bbox) : NULL,
+ nnewgeoms, newgeoms);
+
+}
+
LWMPOINT*
lwmpoint_from_lwgeom(const LWGEOM *g)
{
Modified: trunk/liblwgeom/lwpoly.c
===================================================================
--- trunk/liblwgeom/lwpoly.c 2017-10-10 08:29:21 UTC (rev 15941)
+++ trunk/liblwgeom/lwpoly.c 2017-10-10 13:26:02 UTC (rev 15942)
@@ -387,6 +387,25 @@
return ret;
}
+LWGEOM*
+lwpoly_remove_repeated_points(const LWPOLY *poly, double tolerance)
+{
+ uint32_t i;
+ POINTARRAY **newrings;
+
+ newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
+ for (i=0; i<poly->nrings; i++)
+ {
+ newrings[i] = ptarray_remove_repeated_points_minpoints(poly->rings[i], tolerance, 4);
+ }
+
+ return (LWGEOM*)lwpoly_construct(poly->srid,
+ poly->bbox ? gbox_copy(poly->bbox) : NULL,
+ poly->nrings, newrings);
+
+}
+
+
LWPOLY*
lwpoly_force_dims(const LWPOLY *poly, int hasz, int hasm)
{
Modified: trunk/liblwgeom/ptarray.c
===================================================================
--- trunk/liblwgeom/ptarray.c 2017-10-10 08:29:21 UTC (rev 15941)
+++ trunk/liblwgeom/ptarray.c 2017-10-10 13:26:02 UTC (rev 15942)
@@ -1429,86 +1429,93 @@
*
* Always returns a newly allocated object.
*/
-static POINTARRAY *
+POINTARRAY *
ptarray_remove_repeated_points_minpoints(const POINTARRAY *in, double tolerance, int minpoints)
{
- POINTARRAY *out = ptarray_clone_deep(in);
- ptarray_remove_repeated_points_in_place(out, tolerance, minpoints);
- return out;
-}
+ POINTARRAY *out;
+ size_t ptsize = ptarray_point_size(in);
+ int has_z = FLAGS_GET_Z(in->flags);
+ int has_m = FLAGS_GET_M(in->flags);
+ int ipn = 1, opn = 1;
+ const POINT2D *prev_point, *this_point;
+ uint8_t *p1, *p2;
+ double tolsq = tolerance * tolerance;
-POINTARRAY *
-ptarray_remove_repeated_points(const POINTARRAY *in, double tolerance)
-{
- return ptarray_remove_repeated_points_minpoints(in, tolerance, 2);
-}
+ LWDEBUGF(3, "%s called", __func__);
+ /* Single or zero point arrays can't have duplicates */
+ if ( in->npoints < 3 ) return ptarray_clone_deep(in);
-void
-ptarray_remove_repeated_points_in_place(POINTARRAY *pa, double tolerance, int min_points)
-{
- int i;
- double tolsq = tolerance * tolerance;
- const POINT2D *last = NULL;
- const POINT2D *pt;
- int n_points = pa->npoints;
- int n_points_out = 0;
- int pt_size = ptarray_point_size(pa);
- double dsq;
+ /* Condition minpoints */
+ if ( minpoints < 1 ) minpoints = 1;
- /* No-op on short inputs */
- if ( n_points <= 2 ) return;
+ /* Allocate enough output space for all points */
+ out = ptarray_construct(has_z, has_m, in->npoints);
- for (i = 0; i < n_points; i++)
+ /* Keep the first point */
+ p1 = getPoint_internal(out, 0);
+ p2 = getPoint_internal(in, 0);
+ memcpy(p1, p2, ptsize);
+
+ /* Now fill up the actual points */
+ prev_point = getPoint2d_cp(in, 0);
+ LWDEBUGF(3, " first point copied, out points: %d", opn);
+ for ( ipn = 1; ipn < in->npoints; ipn++ )
{
- int last_point = (i == n_points-1);
+ this_point = getPoint2d_cp(in, ipn);
- /* Look straight into the abyss */
- pt = getPoint2d_cp(pa, i);
-
- /* Preserve first point always */
- if (last)
+ /*
+ * If number of points left > number of points we need
+ * then it's still OK to drop dupes
+ */
+ if ( in->npoints - ipn > minpoints - opn )
{
- /* 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)
- {
- continue;
- }
- }
- else
- {
- /* At tolerance zero, only skip exact dupes */
- if (memcmp((char*)pt, (char*)last, pt_size) == 0)
- continue;
- }
+ /* within the removal tolerance? */
+ double dsq = distance2d_sqr_pt_pt(prev_point, this_point);
+ if (dsq <= tolsq)
+ /* then skip it */
+ continue;
}
+ else
+ {
+ /* exact duplicate? */
+ p1 = getPoint_internal(in, ipn-1);
+ p2 = getPoint_internal(in, ipn);
+ if (memcmp(p1, p2, ptsize) == 0)
+ /* then skip it */
+ continue;
+ }
}
+ /*
+ * The point is different (see above) from
+ * the previous point, so add it to output
+ */
+ p1 = getPoint_internal(out, opn++);
+ p2 = getPoint_internal(in, ipn);
+ memcpy(p1, p2, ptsize);
- /* 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 && tolerance > 0.0 && dsq <= tolsq)
- {
- n_points_out--;
- }
+ prev_point = this_point;
+ }
- /* Compact all remaining values to front of array */
- ptarray_copy_point(pa, i, n_points_out++);
- last = pt;
- }
- /* Adjust array length */
- pa->npoints = n_points_out;
- return;
+ /* Keep the last point */
+ p1 = getPoint_internal(out, opn-1); /* Last output point */
+ p2 = getPoint_internal(in, ipn-1); /* Last input point */
+ if ( memcmp(p1, p2, ptsize) != 0 )
+ memcpy(p1, p2, ptsize);
+
+ LWDEBUGF(3, " in:%d out:%d", out->npoints, opn);
+ out->npoints = opn;
+
+ return out;
}
+POINTARRAY *
+ptarray_remove_repeated_points(const POINTARRAY *in, double tolerance)
+{
+ return ptarray_remove_repeated_points_minpoints(in, tolerance, 2);
+}
/************************************************************************/
More information about the postgis-tickets
mailing list