[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