[postgis-tickets] r15888 - Make lwgeom_grid_in_place, and move around function

Paul Ramsey pramsey at cleverelephant.ca
Wed Oct 4 13:29:57 PDT 2017


Author: pramsey
Date: 2017-10-04 13:29:57 -0700 (Wed, 04 Oct 2017)
New Revision: 15888

Modified:
   trunk/liblwgeom/cunit/cu_lwstroke.c
   trunk/liblwgeom/cunit/cu_misc.c
   trunk/liblwgeom/liblwgeom.h.in
   trunk/liblwgeom/liblwgeom_internal.h
   trunk/liblwgeom/lwcircstring.c
   trunk/liblwgeom/lwcollection.c
   trunk/liblwgeom/lwgeom.c
   trunk/liblwgeom/lwgeom_topo.c
   trunk/liblwgeom/lwgeom_transform.c
   trunk/liblwgeom/lwline.c
   trunk/liblwgeom/lwpoint.c
   trunk/liblwgeom/lwpoly.c
   trunk/liblwgeom/lwtriangle.c
   trunk/liblwgeom/ptarray.c
   trunk/postgis/lwgeom_functions_analytic.c
   trunk/postgis/lwgeom_functions_basic.c
Log:
Make lwgeom_grid_in_place, and move around function 
signatures in support of the in_place project
(References #3877)


Modified: trunk/liblwgeom/cunit/cu_lwstroke.c
===================================================================
--- trunk/liblwgeom/cunit/cu_lwstroke.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/cunit/cu_lwstroke.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -296,11 +296,11 @@
 	out = lwcurve_linearize(in, M_PI/4.0,
 													 LW_LINEARIZE_TOLERANCE_TYPE_MAX_ANGLE,
 													 LW_LINEARIZE_FLAG_SYMMETRIC);
-	lwgeom_reverse(in);
+	lwgeom_reverse_in_place(in);
 	out2 = lwcurve_linearize(in, M_PI/4.0,
 													 LW_LINEARIZE_TOLERANCE_TYPE_MAX_ANGLE,
 													 LW_LINEARIZE_FLAG_SYMMETRIC);
-	lwgeom_reverse(out2);
+	lwgeom_reverse_in_place(out2);
 	if ( ! lwgeom_same(out, out2) )
 	{
 		fprintf(stderr, "linearization is not direction neutral:\n");

Modified: trunk/liblwgeom/cunit/cu_misc.c
===================================================================
--- trunk/liblwgeom/cunit/cu_misc.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/cunit/cu_misc.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -138,6 +138,70 @@
 	lwgeom_free(geomgrid);
 }
 
+static void do_grid_test(const char *wkt_in, const char *wkt_out, double size)
+{
+	char *wkt_result, *wkt_norm;
+	gridspec grid;
+	LWGEOM *g = lwgeom_from_wkt(wkt_in, LW_PARSER_CHECK_ALL);
+	LWGEOM *go = lwgeom_from_wkt(wkt_out, LW_PARSER_CHECK_ALL);
+	wkt_norm = lwgeom_to_ewkt(go);
+	memset(&grid, 0, sizeof(gridspec));
+	grid.xsize = grid.ysize = grid.zsize = grid.msize = size;
+	lwgeom_grid_in_place(g, &grid);
+	wkt_result = lwgeom_to_ewkt(g);
+    // printf("%s ==%ld==> %s == %s\n", wkt_in, lround(size), wkt_result, wkt_out);
+	CU_ASSERT_STRING_EQUAL(wkt_result, wkt_norm);
+	lwfree(wkt_result);
+	lwfree(wkt_norm);
+	lwgeom_free(g);
+	lwgeom_free(go);
+}
+
+static void test_grid_in_place(void)
+{
+	do_grid_test(
+		"POINT ZM (5.1423999999 5.1423999999 5.1423999999 5.1423999999)",
+		"POINT(5.1424 5.1424 5.1424 5.1424)",
+		0.0001
+	);
+	do_grid_test(
+		"MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)))",
+		"MULTIPOLYGON EMPTY",
+		20
+	);
+	do_grid_test(
+		"MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0)))",
+		"MULTIPOLYGON(((0 0,10 0,10 10, 0 10,0 0)))",
+		1
+	);
+	do_grid_test(
+		"LINESTRING(0 0,1 1, 2 2, 3 3, 4 4, 5 5)",
+		"LINESTRING(0 0,2 2,4 4)",
+		2
+	);
+	do_grid_test(
+		"MULTIPOINT(0 0,1 1, 2 2, 3 3, 4 4, 5 5)",
+		/* This preserves current behaviour, but is probably not right */
+		"MULTIPOINT(0 0,0 0,2 2,4 4,4 4,4 4)",
+		2
+	);
+	do_grid_test(
+		"MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(4 4, 4 5, 5 5, 5 4, 4 4)))",
+		"MULTIPOLYGON(((0 0,10 0,10 10, 0 10,0 0)))",
+		2
+	);
+	do_grid_test(
+		"MULTIPOLYGON(((0 0,10 0,10 10,0 10,0 0),(4 4, 4 5, 5 5, 5 4, 4 4)))",
+		"MULTIPOLYGON EMPTY",
+		20
+	);
+	do_grid_test(
+		"POINT Z (5 5 5)",
+		"POINT(0 0 0)",
+		20
+	);
+}
+
 static void test_clone(void)
 {
 	static char *wkt = "GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0))),POINT(1 1),LINESTRING(2 3,4 5))";
@@ -183,6 +247,7 @@
 	PG_ADD_TEST(suite, test_misc_area);
 	PG_ADD_TEST(suite, test_misc_wkb);
 	PG_ADD_TEST(suite, test_grid);
+	PG_ADD_TEST(suite, test_grid_in_place);
 	PG_ADD_TEST(suite, test_clone);
 	PG_ADD_TEST(suite, test_lwmpoint_from_lwgeom);
 }

Modified: trunk/liblwgeom/liblwgeom.h.in
===================================================================
--- trunk/liblwgeom/liblwgeom.h.in	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/liblwgeom.h.in	2017-10-04 20:29:57 UTC (rev 15888)
@@ -981,7 +981,6 @@
 extern LWGEOM* lwgeom_force_3dm(const LWGEOM *geom);
 extern LWGEOM* lwgeom_force_4d(const LWGEOM *geom);
 
-extern LWGEOM* lwgeom_simplify(const LWGEOM *igeom, double dist, int preserve_collapsed);
 extern LWGEOM* lwgeom_set_effective_area(const LWGEOM *igeom, int set_area, double area);
 
 /*
@@ -1196,8 +1195,6 @@
 extern double lwgeom_length_2d(const LWGEOM *geom);
 extern double lwgeom_perimeter(const LWGEOM *geom);
 extern double lwgeom_perimeter_2d(const LWGEOM *geom);
-extern void lwgeom_affine(LWGEOM *geom, const AFFINE *affine);
-extern void lwgeom_scale(LWGEOM *geom, const POINT4D *factors);
 extern int lwgeom_dimension(const LWGEOM *geom);
 
 extern LWPOINT* lwline_get_lwpoint(const LWLINE *line, int where);
@@ -1212,22 +1209,44 @@
 extern int azimuth_pt_pt(const POINT2D *p1, const POINT2D *p2, double *ret);
 extern int lwpoint_inside_circle(const LWPOINT *p, double cx, double cy, double rad);
 
-extern void lwgeom_reverse(LWGEOM *lwgeom);
+extern LWGEOM* lwgeom_reverse(const LWGEOM *lwgeom);
 extern char* lwgeom_summary(const LWGEOM *lwgeom, int offset);
 extern char* lwpoint_to_latlon(const LWPOINT *p, const char *format);
 extern int lwgeom_startpoint(const LWGEOM* lwgeom, POINT4D* pt);
 
+extern void interpolate_point4d(POINT4D *A, POINT4D *B, POINT4D *I, double F);
+
 /**
 * Ensure the outer ring is clockwise oriented and all inner rings
 * are counter-clockwise.
 */
-extern void lwgeom_force_clockwise(LWGEOM *lwgeom);
 extern int lwgeom_is_clockwise(LWGEOM *lwgeom);
 
-extern void interpolate_point4d(POINT4D *A, POINT4D *B, POINT4D *I, double F);
 
+
+/****************************************************************
+* READ/WRITE FUNCTIONS
+*
+* Coordinate writing functions, which will alter the coordinates
+* and potentially the structure of the input geometry. When
+* called from within PostGIS, the LWGEOM argument should be built
+* on top of a gserialized copy, created using
+* PG_GETARG_GSERIALIZED_P_COPY()
+****************************************************************/
+
+extern void lwgeom_reverse_in_place(LWGEOM *lwgeom);
+extern void lwgeom_force_clockwise(LWGEOM *lwgeom);
 extern void lwgeom_longitude_shift(LWGEOM *lwgeom);
+extern LWGEOM* lwgeom_simplify(const LWGEOM *igeom, double dist, int preserve_collapsed);
+extern void lwgeom_affine(LWGEOM *geom, const AFFINE *affine);
+extern void lwgeom_scale(LWGEOM *geom, const POINT4D *factors);
 
+
+
+
+/****************************************************************/
+
+
 /**
  * @brief wrap geometry on given cut x value
  *
@@ -2313,9 +2332,8 @@
  * @param inpj the input (or current, or source) projection
  * @param outpj the output (or destination) projection
  */
-int lwgeom_transform(LWGEOM *geom, projPJ inpj, projPJ outpj) ;
-int ptarray_transform(POINTARRAY *geom, projPJ inpj, projPJ outpj) ;
-int point4d_transform(POINT4D *pt, projPJ srcpj, projPJ dstpj) ;
+int lwgeom_transform(LWGEOM *geom, projPJ inpj, projPJ outpj);
+int ptarray_transform(POINTARRAY *pa, projPJ inpj, projPJ outpj);
 
 
 /*******************************************************************************

Modified: trunk/liblwgeom/liblwgeom_internal.h
===================================================================
--- trunk/liblwgeom/liblwgeom_internal.h	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/liblwgeom_internal.h	2017-10-04 20:29:57 UTC (rev 15888)
@@ -362,6 +362,11 @@
 char lwcircstring_same(const LWCIRCSTRING *p1, const LWCIRCSTRING *p2);
 
 /*
+* Transform
+*/
+int point4d_transform(POINT4D *pt, projPJ srcpj, projPJ dstpj);
+
+/*
 * Shift
 */
 void ptarray_longitude_shift(POINTARRAY *pa);
@@ -369,11 +374,7 @@
 /*
 * Reverse
 */
-void lwcircstring_reverse(LWCIRCSTRING *curve);
-void ptarray_reverse(POINTARRAY *pa);
-void lwline_reverse(LWLINE *line);
-void lwpoly_reverse(LWPOLY *poly);
-void lwtriangle_reverse(LWTRIANGLE *triangle);
+void ptarray_reverse_in_place(POINTARRAY *pa);
 
 /*
 * Startpoint
@@ -429,13 +430,15 @@
 gridspec;
 
 LWGEOM* lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid);
-LWCOLLECTION* lwcollection_grid(const LWCOLLECTION *coll, const gridspec *grid);
-LWPOINT* lwpoint_grid(const LWPOINT *point, const gridspec *grid);
-LWPOLY* lwpoly_grid(const LWPOLY *poly, const gridspec *grid);
-LWLINE* lwline_grid(const LWLINE *line, const gridspec *grid);
-LWCIRCSTRING* lwcircstring_grid(const LWCIRCSTRING *line, const gridspec *grid);
-POINTARRAY* ptarray_grid(const POINTARRAY *pa, const gridspec *grid);
 
+void lwgeom_grid_in_place(LWGEOM *lwgeom, const gridspec *grid);
+void lwcollection_grid_in_place(LWCOLLECTION *coll, const gridspec *grid);
+void lwpoint_grid_in_place(LWPOINT *point, const gridspec *grid);
+void lwpoly_grid_in_place(LWPOLY *poly, const gridspec *grid);
+void lwline_grid_in_place(LWLINE *line, const gridspec *grid);
+void lwcircstring_grid_in_place(LWCIRCSTRING *line, const gridspec *grid);
+void ptarray_grid_in_place(POINTARRAY *pa, const gridspec *grid);
+
 /*
 * What side of the line formed by p1 and p2 does q fall?
 * Returns -1 for left and 1 for right and 0 for co-linearity

Modified: trunk/liblwgeom/lwcircstring.c
===================================================================
--- trunk/liblwgeom/lwcircstring.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/lwcircstring.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -32,7 +32,6 @@
 #include "lwgeom_log.h"
 
 void printLWCIRCSTRING(LWCIRCSTRING *curve);
-void lwcircstring_reverse(LWCIRCSTRING *curve);
 void lwcircstring_release(LWCIRCSTRING *lwcirc);
 char lwcircstring_same(const LWCIRCSTRING *me, const LWCIRCSTRING *you);
 LWCIRCSTRING *lwcircstring_from_lwpointarray(int srid, uint32_t npoints, LWPOINT **points);
@@ -127,12 +126,6 @@
 	return (LWCIRCSTRING *)lwline_clone((LWLINE *)g);
 }
 
-
-void lwcircstring_reverse(LWCIRCSTRING *curve)
-{
-	ptarray_reverse(curve->points);
-}
-
 /* check coordinate equality */
 char
 lwcircstring_same(const LWCIRCSTRING *me, const LWCIRCSTRING *you)
@@ -312,22 +305,4 @@
 	return lwpoint;
 }
 
-/*
-* Snap to grid
-*/
-LWCIRCSTRING* lwcircstring_grid(const LWCIRCSTRING *line, const gridspec *grid)
-{
-	LWCIRCSTRING *oline;
-	POINTARRAY *opa;
 
-	opa = ptarray_grid(line->points, grid);
-
-	/* Skip line3d with less then 2 points */
-	if ( opa->npoints < 2 ) return NULL;
-
-	/* TODO: grid bounding box... */
-	oline = lwcircstring_construct(line->srid, NULL, opa);
-
-	return oline;
-}
-

Modified: trunk/liblwgeom/lwcollection.c
===================================================================
--- trunk/liblwgeom/lwcollection.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/lwcollection.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -586,19 +586,3 @@
 }
 
 
-LWCOLLECTION* lwcollection_grid(const LWCOLLECTION *coll, const gridspec *grid)
-{
-	uint32_t i;
-	LWCOLLECTION *newcoll;
-
-	newcoll = lwcollection_construct_empty(coll->type, coll->srid, lwgeom_has_z((LWGEOM*)coll), lwgeom_has_m((LWGEOM*)coll));
-
-	for (i=0; i<coll->ngeoms; i++)
-	{
-		LWGEOM *g = lwgeom_grid(coll->geoms[i], grid);
-		if ( g )
-			lwcollection_add_lwgeom(newcoll, g);
-	}
-
-	return newcoll;
-}

Modified: trunk/liblwgeom/lwgeom.c
===================================================================
--- trunk/liblwgeom/lwgeom.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/lwgeom.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -88,40 +88,71 @@
 	}
 }
 
+LWGEOM *
+lwgeom_reverse(const LWGEOM *geom)
+{
+	LWGEOM *geomout = lwgeom_clone_deep(geom);
+	lwgeom_reverse_in_place(geomout);
+	return geomout;
+}
+
 /** Reverse vertex order of LWGEOM **/
 void
-lwgeom_reverse(LWGEOM *lwgeom)
+lwgeom_reverse_in_place(LWGEOM *geom)
 {
 	int i;
 	LWCOLLECTION *col;
+	if (!geom)
+		return;
 
-	switch (lwgeom->type)
+	switch (geom->type)
 	{
-	case LINETYPE:
-		lwline_reverse((LWLINE *)lwgeom);
-		return;
-	case POLYGONTYPE:
-		lwpoly_reverse((LWPOLY *)lwgeom);
-		return;
-	case TRIANGLETYPE:
-		lwtriangle_reverse((LWTRIANGLE *)lwgeom);
-		return;
-	case CIRCSTRINGTYPE:
-		lwcircstring_reverse((LWCIRCSTRING *)lwgeom);
-		return;
-	case MULTICURVETYPE:
-	case MULTILINETYPE:
-	case MULTIPOLYGONTYPE:
-	case MULTISURFACETYPE:
-	case POLYHEDRALSURFACETYPE:
-	case TINTYPE:
-	case COLLECTIONTYPE:
-	case COMPOUNDTYPE:
-	case CURVEPOLYTYPE:
-		col = (LWCOLLECTION *)lwgeom;
-		for (i=0; i<col->ngeoms; i++)
-			lwgeom_reverse(col->geoms[i]);
-		return;
+		case MULTIPOINTTYPE:
+		case POINTTYPE:
+		{
+			return;
+		}
+		case TRIANGLETYPE:
+		case CIRCSTRINGTYPE:
+		case LINETYPE:
+		{
+			LWLINE *line = (LWLINE *)(geom);
+			ptarray_reverse_in_place(line->points);
+			return;
+		}
+		case POLYGONTYPE:
+		{
+			LWPOLY *poly = (LWPOLY *)(geom);
+			if (!poly->rings)
+				return;
+			int r;
+			for (r = 0; r < poly->nrings; r++)
+				ptarray_reverse_in_place(poly->rings[r]);
+			return;
+		}
+		case MULTICURVETYPE:
+		case MULTILINETYPE:
+		case MULTIPOLYGONTYPE:
+		case MULTISURFACETYPE:
+		case POLYHEDRALSURFACETYPE:
+		case TINTYPE:
+		case COLLECTIONTYPE:
+		case COMPOUNDTYPE:
+		case CURVEPOLYTYPE:
+		{
+			col = (LWCOLLECTION *)(geom);
+			if (!col->geoms)
+				return;
+			for (i=0; i<col->ngeoms; i++)
+				lwgeom_reverse_in_place(col->geoms[i]);
+			return;
+		}
+		default:
+		{
+			lwerror("%s: Unknown geometry type: %s", __func__, lwtype_name(geom->type));
+			return;
+		}
+
 	}
 }
 
@@ -1878,7 +1909,7 @@
 }
 
 int
-lwgeom_startpoint(const LWGEOM* lwgeom, POINT4D* pt)
+lwgeom_startpoint(const LWGEOM *lwgeom, POINT4D *pt)
 {
 	if ( ! lwgeom )
 		return LW_FAILURE;
@@ -1907,34 +1938,91 @@
 	}
 }
 
-
-LWGEOM *
-lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid)
+void
+lwgeom_grid_in_place(LWGEOM *geom, const gridspec *grid)
 {
-	switch ( lwgeom->type )
+	if (!geom) return;
+	switch ( geom->type )
 	{
 		case POINTTYPE:
-			return (LWGEOM *)lwpoint_grid((LWPOINT *)lwgeom, grid);
+		{
+			LWPOINT *pt = (LWPOINT*)(geom);
+			ptarray_grid_in_place(pt->point, grid);
+			return;
+		}
+		case CIRCSTRINGTYPE:
 		case LINETYPE:
-			return (LWGEOM *)lwline_grid((LWLINE *)lwgeom, grid);
+		{
+			LWLINE *ln = (LWLINE*)(geom);
+			ptarray_grid_in_place(ln->points, grid);
+			/* For invalid line, return an EMPTY */
+			if (ln->points->npoints < 2)
+				ln->points->npoints = 0;
+			return;
+		}
 		case POLYGONTYPE:
-			return (LWGEOM *)lwpoly_grid((LWPOLY *)lwgeom, grid);
+		{
+			LWPOLY *ply = (LWPOLY*)(geom);
+			int i, j = 0;
+			if (!ply->rings) return;
+			for (i = 0; i < ply->nrings; i++)
+			{
+				POINTARRAY *pa = ply->rings[i];
+				ptarray_grid_in_place(pa, grid);
+				/* Skip bad rings */
+				if (pa->npoints < 4)
+				{
+					/* If bad ring is external ring, stop everything */
+					if (i) continue;
+					else break;
+				}
+				/* Fill in just the rings we are keeping */
+				ply->rings[j++] = pa;
+			}
+			/* Adjust ring count appropriately */
+			ply->nrings = j;
+			return;
+		}
 		case MULTIPOINTTYPE:
 		case MULTILINETYPE:
 		case MULTIPOLYGONTYPE:
 		case COLLECTIONTYPE:
 		case COMPOUNDTYPE:
-			return (LWGEOM *)lwcollection_grid((LWCOLLECTION *)lwgeom, grid);
-		case CIRCSTRINGTYPE:
-			return (LWGEOM *)lwcircstring_grid((LWCIRCSTRING *)lwgeom, grid);
+		{
+			LWCOLLECTION *col = (LWCOLLECTION*)(geom);
+			int i, j = 0;
+			if (!col->geoms) return;
+			for (i = 0; i < col->ngeoms; i++)
+			{
+				LWGEOM *g = col->geoms[i];
+				lwgeom_grid_in_place(g, grid);
+				/* Skip empty geoms */
+				if (lwgeom_is_empty(g))
+					continue;
+				col->geoms[j++] = g;
+			}
+			col->ngeoms = j;
+			return;
+		}
 		default:
-			lwerror("lwgeom_grid: Unsupported geometry type: %s",
-			        lwtype_name(lwgeom->type));
-			return NULL;
+		{
+			lwerror("%s: Unsupported geometry type: %s", __func__,
+			        lwtype_name(geom->type));
+			return;
+		}
 	}
 }
 
 
+LWGEOM *
+lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid)
+{
+	LWGEOM *lwgeom_out = lwgeom_clone_deep(lwgeom);
+	lwgeom_grid_in_place(lwgeom_out, grid);
+	return lwgeom_out;
+}
+
+
 /* Prototype for recursion */
 static int
 lwgeom_subdivide_recursive(const LWGEOM *geom, int maxvertices, int depth, LWCOLLECTION *col, const GBOX *clip);

Modified: trunk/liblwgeom/lwgeom_topo.c
===================================================================
--- trunk/liblwgeom/lwgeom_topo.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/lwgeom_topo.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -1836,14 +1836,14 @@
     if ( pa == NULL )
     {
       pa = ptarray_clone_deep(edge->geom->points);
-      if ( eid < 0 ) ptarray_reverse(pa);
+      if ( eid < 0 ) ptarray_reverse_in_place(pa);
     }
     else
     {
       if ( eid < 0 )
       {
         epa = ptarray_clone_deep(edge->geom->points);
-        ptarray_reverse(epa);
+        ptarray_reverse_in_place(epa);
         ptarray_append_ptarray(pa, epa, 0);
         ptarray_free(epa);
       }
@@ -3149,7 +3149,7 @@
   /* force_lhr, if the face is not the universe */
   /* _lwt_FaceByEdges seems to guaranteed RHR */
   /* lwgeom_force_clockwise(face); */
-  if ( face_id ) lwgeom_reverse(face);
+  if ( face_id ) lwgeom_reverse_in_place(face);
 
 #if 0
   {
@@ -4596,7 +4596,7 @@
     {
       POINTARRAY *pa2;
       pa2 = ptarray_clone_deep(e2->geom->points);
-      ptarray_reverse(pa2);
+      ptarray_reverse_in_place(pa2);
       pa = ptarray_clone_deep(e1->geom->points);
       //pa = ptarray_merge(e1->geom->points, pa);
       ptarray_append_ptarray(pa, pa2, 0);
@@ -4612,7 +4612,7 @@
     }
     case 3: /* e1.start = e2.start */
       pa = ptarray_clone_deep(e2->geom->points);
-      ptarray_reverse(pa);
+      ptarray_reverse_in_place(pa);
       //pa = ptarray_merge(pa, e1->geom->points);
       ptarray_append_ptarray(pa, e1->geom->points, 0);
       newedge.end_node = e1->end_node;

Modified: trunk/liblwgeom/lwgeom_transform.c
===================================================================
--- trunk/liblwgeom/lwgeom_transform.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/lwgeom_transform.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -24,7 +24,7 @@
 
 
 #include "../postgis_config.h"
-#include "liblwgeom.h"
+#include "liblwgeom_internal.h"
 #include "lwgeom_log.h"
 #include <string.h>
 
@@ -52,15 +52,15 @@
 int
 ptarray_transform(POINTARRAY *pa, projPJ inpj, projPJ outpj)
 {
-  int i;
+	int i;
 	POINT4D p;
 
-  for ( i = 0; i < pa->npoints; i++ )
-  {
-    getPoint4d_p(pa, i, &p);
-    if ( ! point4d_transform(&p, inpj, outpj) ) return LW_FAILURE;
-    ptarray_set_point4d(pa, i, &p);
-  }
+	for ( i = 0; i < pa->npoints; i++ )
+	{
+		getPoint4d_p(pa, i, &p);
+		if ( ! point4d_transform(&p, inpj, outpj) ) return LW_FAILURE;
+		ptarray_set_point4d(pa, i, &p);
+	}
 
 	return LW_SUCCESS;
 }
@@ -87,7 +87,7 @@
 		case TRIANGLETYPE:
 		{
 			LWLINE *g = (LWLINE*)geom;
-      if ( ! ptarray_transform(g->points, inpj, outpj) ) return LW_FAILURE;
+			if ( ! ptarray_transform(g->points, inpj, outpj) ) return LW_FAILURE;
 			break;
 		}
 		case POLYGONTYPE:
@@ -95,7 +95,7 @@
 			LWPOLY *g = (LWPOLY*)geom;
 			for ( i = 0; i < g->nrings; i++ )
 			{
-        if ( ! ptarray_transform(g->rings[i], inpj, outpj) ) return LW_FAILURE;
+				if ( ! ptarray_transform(g->rings[i], inpj, outpj) ) return LW_FAILURE;
 			}
 			break;
 		}

Modified: trunk/liblwgeom/lwline.c
===================================================================
--- trunk/liblwgeom/lwline.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/lwline.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -136,12 +136,6 @@
 	lwgeom_release(lwline_as_lwgeom(lwline));
 }
 
-void
-lwline_reverse(LWLINE *line)
-{
-	if ( lwline_is_empty(line) ) return;
-	ptarray_reverse(line->points);
-}
 
 LWLINE *
 lwline_segmentize2d(LWLINE *line, double dist)
@@ -591,20 +585,3 @@
 }
 
 
-
-LWLINE* lwline_grid(const LWLINE *line, const gridspec *grid)
-{
-	LWLINE *oline;
-	POINTARRAY *opa;
-
-	opa = ptarray_grid(line->points, grid);
-
-	/* Skip line3d with less then 2 points */
-	if ( opa->npoints < 2 ) return NULL;
-
-	/* TODO: grid bounding box... */
-	oline = lwline_construct(line->srid, NULL, opa);
-
-	return oline;
-}
-

Modified: trunk/liblwgeom/lwpoint.c
===================================================================
--- trunk/liblwgeom/lwpoint.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/lwpoint.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -296,10 +296,4 @@
 }
 
 
-LWPOINT *
-lwpoint_grid(const LWPOINT *point, const gridspec *grid)
-{
-	POINTARRAY *opa = ptarray_grid(point->point, grid);
-	return lwpoint_construct(point->srid, NULL, opa);
-}
 

Modified: trunk/liblwgeom/lwpoly.c
===================================================================
--- trunk/liblwgeom/lwpoly.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/lwpoly.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -275,12 +275,12 @@
 
 	/* External ring */
 	if ( ptarray_isccw(poly->rings[0]) )
-		ptarray_reverse(poly->rings[0]);
+		ptarray_reverse_in_place(poly->rings[0]);
 
 	/* Internal rings */
 	for (i=1; i<poly->nrings; i++)
 		if ( ! ptarray_isccw(poly->rings[i]) )
-			ptarray_reverse(poly->rings[i]);
+			ptarray_reverse_in_place(poly->rings[i]);
 
 }
 
@@ -308,15 +308,6 @@
 	lwgeom_release(lwpoly_as_lwgeom(lwpoly));
 }
 
-void
-lwpoly_reverse(LWPOLY *poly)
-{
-	int i;
-	if ( lwpoly_is_empty(poly) ) return;
-	for (i=0; i<poly->nrings; i++)
-		ptarray_reverse(poly->rings[i]);
-}
-
 LWPOLY *
 lwpoly_segmentize2d(LWPOLY *poly, double dist)
 {
@@ -636,58 +627,3 @@
 }
 
 
-
-LWPOLY* lwpoly_grid(const LWPOLY *poly, const gridspec *grid)
-{
-	LWPOLY *opoly;
-	int ri;
-
-#if 0
-	/*
-	 * TODO: control this assertion
-	 * it is assumed that, since the grid size will be a pixel,
-	 * a visible ring should show at least a white pixel inside,
-	 * thus, for a square, that would be grid_xsize*grid_ysize
-	 */
-	double minvisiblearea = grid->xsize * grid->ysize;
-#endif
-
-	LWDEBUGF(3, "lwpoly_grid: applying grid to polygon with %d rings", poly->nrings);
-
-	opoly = lwpoly_construct_empty(poly->srid, lwgeom_has_z((LWGEOM*)poly), lwgeom_has_m((LWGEOM*)poly));
-
-	for (ri=0; ri<poly->nrings; ri++)
-	{
-		POINTARRAY *ring = poly->rings[ri];
-		POINTARRAY *newring;
-
-		newring = ptarray_grid(ring, grid);
-
-		/* Skip ring if not composed by at least 4 pts (3 segments) */
-		if ( newring->npoints < 4 )
-		{
-			ptarray_free(newring);
-
-			LWDEBUGF(3, "grid_polygon3d: ring%d skipped ( <4 pts )", ri);
-
-			if ( ri ) continue;
-			else break; /* this is the external ring, no need to work on holes */
-		}
-
-		if ( ! lwpoly_add_ring(opoly, newring) )
-		{
-			lwerror("lwpoly_grid, memory error");
-			return NULL;
-		}
-	}
-
-	LWDEBUGF(3, "lwpoly_grid: simplified polygon with %d rings", opoly->nrings);
-
-	if ( ! opoly->nrings )
-	{
-		lwpoly_free(opoly);
-		return NULL;
-	}
-
-	return opoly;
-}

Modified: trunk/liblwgeom/lwtriangle.c
===================================================================
--- trunk/liblwgeom/lwtriangle.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/lwtriangle.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -106,7 +106,7 @@
 lwtriangle_force_clockwise(LWTRIANGLE *triangle)
 {
 	if ( ptarray_isccw(triangle->points) )
-		ptarray_reverse(triangle->points);
+		ptarray_reverse_in_place(triangle->points);
 }
 
 int
@@ -116,13 +116,6 @@
 }
 
 void
-lwtriangle_reverse(LWTRIANGLE *triangle)
-{
-	if( lwtriangle_is_empty(triangle) ) return;
-	ptarray_reverse(triangle->points);
-}
-
-void
 lwtriangle_release(LWTRIANGLE *lwtriangle)
 {
 	lwgeom_release(lwtriangle_as_lwgeom(lwtriangle));

Modified: trunk/liblwgeom/ptarray.c
===================================================================
--- trunk/liblwgeom/ptarray.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/liblwgeom/ptarray.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -340,7 +340,7 @@
 
 
 void
-ptarray_reverse(POINTARRAY *pa)
+ptarray_reverse_in_place(POINTARRAY *pa)
 {
 	int i;
 	int last = pa->npoints-1;
@@ -359,6 +359,7 @@
 			d[(last-i)*ndims+j] = buf;
 		}
 	}
+	return;
 }
 
 
@@ -1840,8 +1841,6 @@
 }
 
 
-
-
 /*
  * Stick an array of points to the given gridspec.
  * Return "gridded" points in *outpts and their number in *outptsn.
@@ -1850,45 +1849,70 @@
  * into one single point.
  *
  */
-POINTARRAY *
-ptarray_grid(const POINTARRAY *pa, const gridspec *grid)
+void
+ptarray_grid_in_place(POINTARRAY *pa, const gridspec *grid)
 {
-	POINT4D pt;
-	int ipn; /* input point numbers */
-	POINTARRAY *dpa;
+	int i, j = 0;
+	POINT4D *p, *p_out = NULL;
+	int ndims = FLAGS_NDIMS(pa->flags);
+	int has_z = FLAGS_GET_Z(pa->flags);
+	int has_m = FLAGS_GET_M(pa->flags);
 
-	LWDEBUGF(2, "ptarray_grid called on %p", pa);
+	LWDEBUGF(2, "%s called on %p", __func__, pa);
 
-	dpa = ptarray_construct_empty(FLAGS_GET_Z(pa->flags),FLAGS_GET_M(pa->flags), pa->npoints);
-
-	for (ipn=0; ipn<pa->npoints; ++ipn)
+	for (i = 0; i < pa->npoints; i++)
 	{
+		/* Look straight into the abyss */
+		p = (POINT4D*)(getPoint_internal(pa, i));
 
-		getPoint4d_p(pa, ipn, &pt);
+    	if (grid->xsize > 0)
+    		p->x = rint((p->x - grid->ipx)/grid->xsize) * grid->xsize + grid->ipx;
 
-		if ( grid->xsize )
-			pt.x = rint((pt.x - grid->ipx)/grid->xsize) *
-			         grid->xsize + grid->ipx;
+    	if (grid->ysize > 0)
+    		p->y = rint((p->y - grid->ipy)/grid->ysize) * grid->ysize + grid->ipy;
 
-		if ( grid->ysize )
-			pt.y = rint((pt.y - grid->ipy)/grid->ysize) *
-			         grid->ysize + grid->ipy;
+		/* Read and round this point */
+		/* Z is always in third position */
+		if (has_z)
+		{
+			if (grid->zsize > 0)
+				p->z = rint((p->z - grid->ipz)/grid->zsize) * grid->zsize + grid->ipz;
+		}
+		/* M might be in 3rd or 4th position */
+		if (has_m)
+		{
+			/* In POINT M, M is in 3rd position */
+			if (grid->msize > 0 && !has_z)
+				p->z = rint((p->z - grid->ipm)/grid->msize) * grid->msize + grid->ipm;
+			/* In POINT ZM, M is in 4th position */
+			if (grid->msize > 0 && has_z)
+				p->m = rint((p->m - grid->ipm)/grid->msize) * grid->msize + grid->ipm;
+		}
 
-		if ( FLAGS_GET_Z(pa->flags) && grid->zsize )
-			pt.z = rint((pt.z - grid->ipz)/grid->zsize) *
-			         grid->zsize + grid->ipz;
+		/* Skip duplicates */
+		if ( p_out && p_out->x == p->x && p_out->y == p->y
+		   && (ndims > 2 ? p_out->z == p->z : 1)
+		   && (ndims > 3 ? p_out->m == p->m : 1) )
+		{
+			continue;
+		}
 
-		if ( FLAGS_GET_M(pa->flags) && grid->msize )
-			pt.m = rint((pt.m - grid->ipm)/grid->msize) *
-			         grid->msize + grid->ipm;
-
-		ptarray_append_point(dpa, &pt, LW_FALSE);
-
+		/* Write rounded values into the next available point */
+		p_out = (POINT4D*)(getPoint_internal(pa, j++));
+		p_out->x = p->x;
+		p_out->y = p->y;
+		if (ndims > 2)
+			p_out->z = p->z;
+		if (ndims > 3)
+			p_out->m = p->m;
 	}
 
-	return dpa;
+	/* Update output ptarray length */
+	pa->npoints = j;
+	return;
 }
 
+
 int
 ptarray_npoints_in_rect(const POINTARRAY *pa, const GBOX *gbox)
 {

Modified: trunk/postgis/lwgeom_functions_analytic.c
===================================================================
--- trunk/postgis/lwgeom_functions_analytic.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/postgis/lwgeom_functions_analytic.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -1326,10 +1326,8 @@
 
 	geom = PG_GETARG_GSERIALIZED_P_COPY(0);
 	input = lwgeom_from_gserialized(geom);
-
-    lwgeom_reverse(input);
+	lwgeom_reverse_in_place(input);
 	is_ccw = lwgeom_is_clockwise(input);
-
 	lwgeom_free(input);
 	PG_FREE_IF_COPY(geom, 0);
 

Modified: trunk/postgis/lwgeom_functions_basic.c
===================================================================
--- trunk/postgis/lwgeom_functions_basic.c	2017-10-04 18:43:11 UTC (rev 15887)
+++ trunk/postgis/lwgeom_functions_basic.c	2017-10-04 20:29:57 UTC (rev 15888)
@@ -1882,7 +1882,7 @@
 	geom = PG_GETARG_GSERIALIZED_P_COPY(0);
 
 	lwgeom = lwgeom_from_gserialized(geom);
-	lwgeom_reverse(lwgeom);
+	lwgeom_reverse_in_place(lwgeom);
 
 	geom = geometry_serialize(lwgeom);
 



More information about the postgis-tickets mailing list