]> granicus.if.org Git - postgis/commitdiff
Move snap-to-grid functions into lwgeom where they belong.
authorPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 20 Feb 2015 20:31:25 +0000 (20:31 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Fri, 20 Feb 2015 20:31:25 +0000 (20:31 +0000)
Modernize geometry construction to use accessors more

git-svn-id: http://svn.osgeo.org/postgis/trunk@13255 b70326c6-7e19-0410-871a-916f4a2858ee

15 files changed:
liblwgeom/cunit/cu_misc.c
liblwgeom/g_serialized.c
liblwgeom/liblwgeom.h.in
liblwgeom/liblwgeom_internal.h
liblwgeom/lwcircstring.c
liblwgeom/lwcollection.c
liblwgeom/lwgeom.c
liblwgeom/lwgeom_api.c
liblwgeom/lwline.c
liblwgeom/lwpoint.c
liblwgeom/lwpoly.c
liblwgeom/ptarray.c
libpgcommon/lwgeom_pg.h
postgis/lwgeom_functions_analytic.c
postgis/lwgeom_ogc.c

index cd483dbbfcdc4a821b0c1639b1a3b73e53492778..24a8a1900c1f33d9c19e5745cde835d389a49542 100644 (file)
@@ -119,6 +119,27 @@ static void test_misc_wkb(void)
                
 }
 
+
+static void test_grid(void)
+{
+       gridspec grid;
+       static char *wkt = "MULTIPOLYGON(((0 0, 10 0, 10 10, 0 10, 0 0)))";
+       LWGEOM *geom = lwgeom_from_wkt(wkt, LW_PARSER_CHECK_ALL);
+       LWGEOM *geomgrid;
+       char *str;
+       
+       grid.ipx = grid.ipy = 0;
+       grid.xsize = grid.ysize = 20;
+
+       geomgrid = lwgeom_grid(geom, &grid);
+       str = lwgeom_to_ewkt(geomgrid);
+       CU_ASSERT_STRING_EQUAL(str, "MULTIPOLYGON EMPTY");
+       lwfree(str);
+       lwgeom_free(geom);
+       lwgeom_free(geomgrid);          
+}
+
+
 /*
 ** Used by the test harness to register the tests in this file.
 */
@@ -131,4 +152,5 @@ void misc_suite_setup(void)
        PG_ADD_TEST(suite, test_misc_count_vertices);
        PG_ADD_TEST(suite, test_misc_area);
        PG_ADD_TEST(suite, test_misc_wkb);
+       PG_ADD_TEST(suite, test_grid);
 }
index 5e3f06ec6113e684ce52963cc0f2cd63f01a5e50..fa36da7950957256bc895178ba7d9004d6ded3a7 100644 (file)
@@ -42,7 +42,7 @@ int gserialized_ndims(const GSERIALIZED *gser)
        return FLAGS_NDIMS(gser->flags);
 }
 
-uint32_t gserialized_max_header_size() 
+uint32_t gserialized_max_header_size(void
 {
        /* read GSERIALIZED size + max bbox according gbox_serialized_size (2 + Z + M) + 1 int for type */
        return sizeof(GSERIALIZED) + 8 * sizeof(float) + sizeof(int);
index 523247aa4add4edaa38b84aeec684161fc24dd26..0c0b807062e4e4d0a8971b552a10f569d4a9b4eb 100644 (file)
@@ -578,7 +578,9 @@ typedef struct
 }
 LWTIN;
 
-
+/**
+* TWKB Support Structures 
+*/
 typedef struct
 {
        int64_t id;     //Id, from function parameter
@@ -599,6 +601,22 @@ typedef struct
 }
 twkb_geom_arrays;
 
+/**
+* Snap-to-grid Support
+*/
+typedef struct gridspec_t
+{
+       double ipx;
+       double ipy;
+       double ipz;
+       double ipm;
+       double xsize;
+       double ysize;
+       double zsize;
+       double msize;
+}
+gridspec;
+
 /* Casts LWGEOM->LW* (return NULL if cast is illegal) */
 extern LWMPOLY *lwgeom_as_lwmpoly(const LWGEOM *lwgeom);
 extern LWMLINE *lwgeom_as_lwmline(const LWGEOM *lwgeom);
@@ -660,7 +678,7 @@ extern uint32_t gserialized_get_type(const GSERIALIZED *g);
 * Returns the size in bytes to read from toast to get the basic 
 * information from a geometry: GSERIALIZED struct, bbox and type 
 */
-extern uint32_t gserialized_max_header_size();
+extern uint32_t gserialized_max_header_size(void);
 
 /**
 * Extract the SRID from the serialized form (it is packed into
@@ -829,6 +847,14 @@ extern const POINT2D* getPoint2d_cp(const POINTARRAY *pa, int n);
 */
 extern const POINT3DZ* getPoint3dz_cp(const POINTARRAY *pa, int n);
 
+/**
+* Returns a POINT4D pointer into the POINTARRAY serialized_ptlist, 
+* suitable for reading from. This is very high performance
+* and declared const because you aren't allowed to muck with the 
+* values, only read them.
+*/
+extern const POINT4D* getPoint4d_cp(const POINTARRAY *pa, int n);
+
 /*
  * set point N to the given value
  * NOTE that the pointarray can be of any
index 77eb6dcb4a479638dd061ff1ebc68b1f80f70a9e..a1eafdb7f22c2a7cdaa37f39b5693b8b6cc0e855 100644 (file)
@@ -354,7 +354,16 @@ int lwcompound_is_closed(const LWCOMPOUND *curve);
 int lwpsurface_is_closed(const LWPSURFACE *psurface);
 int lwtin_is_closed(const LWTIN *tin);
 
-
+/**
+* Snap to grid
+*/
+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);
 
 /*
 * What side of the line formed by p1 and p2 does q fall? 
index a8f73f04bbc863fd8b9300609649bb32de7f68b0..3361cd603f0ba213537105cab389378d0e70d50a 100644 (file)
@@ -298,3 +298,23 @@ LWPOINT* lwcircstring_get_lwpoint(LWCIRCSTRING *circ, int where) {
        lwpoint = lwpoint_construct(circ->srid, NULL, pa);
        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;
+}
+
index 089ad61afa22cadf19fa5b61b6aec2543e1b7f12..8d81ab5893461b22fa0406d1eb6abd115645c1d3 100644 (file)
@@ -564,3 +564,21 @@ lwcollection_startpoint(const LWCOLLECTION* col, POINT4D* pt)
                
        return lwgeom_startpoint(col->geoms[0], pt);
 }
+
+
+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;
+}
index ad76eeee98def0337a4d9098ce8fda211242df95..07faeaf23a84d4aee271d5f48c9dd6d8be858191 100644 (file)
@@ -1754,3 +1754,29 @@ lwgeom_startpoint(const LWGEOM* lwgeom, POINT4D* pt)
        }
 }
 
+
+LWGEOM *
+lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid)
+{
+       switch ( lwgeom->type )
+       {
+               case POINTTYPE:
+                       return (LWGEOM *)lwpoint_grid((LWPOINT *)lwgeom, grid);
+               case LINETYPE:
+                       return (LWGEOM *)lwline_grid((LWLINE *)lwgeom, grid);
+               case POLYGONTYPE:
+                       return (LWGEOM *)lwpoly_grid((LWPOLY *)lwgeom, grid);
+               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);
+               default:
+                       lwerror("lwgeom_grid: Unsupported geometry type: %s",
+                               lwtype_name(lwgeom->type));
+                       return NULL;
+       }
+}
index c35a1506e3141682ba6a2798a7fc83f5b1286226..1e9fcd8fd5bd10451f085758b10784a5d31dfb30 100644 (file)
@@ -488,6 +488,27 @@ getPoint3dz_cp(const POINTARRAY *pa, int n)
 }
 
 
+const POINT4D*
+getPoint4d_cp(const POINTARRAY *pa, int n)
+{
+       if ( ! pa ) return 0;
+       
+       if ( ! (FLAGS_GET_Z(pa->flags) && FLAGS_GET_Z(pa->flags)) )
+       {
+               lwerror("getPoint3dz_cp: no Z and M coordinates in point array");
+               return 0; /*error */
+       }
+
+       if ( (n<0) || (n>=pa->npoints))
+       {
+               lwerror("getPoint3dz_cp: point offset out of range");
+               return 0; /*error */
+       }
+
+       return (const POINT4D*)getPoint_internal(pa, n);
+}
+
+
 
 /*
  * set point N to the given value
index 0fe0138a605ac1ee7428aa6e593f9f41d19280d8..446b208456feb71e97915f4ecf869a1d27eca32e 100644 (file)
@@ -504,3 +504,22 @@ double lwline_length_2d(const LWLINE *line)
                return 0.0;
        return ptarray_length_2d(line->points);
 }
+
+
+
+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;
+}
+
index 8da187bd68c526f9e7c70ef8c8abe7a635362dc3..c9e8612a8d9f2e0268a30c12fc7b60f59e8fd628 100644 (file)
@@ -262,3 +262,11 @@ int lwpoint_is_empty(const LWPOINT *point)
        return LW_FALSE;
 }
 
+
+LWPOINT *
+lwpoint_grid(const LWPOINT *point, const gridspec *grid)
+{
+       POINTARRAY *opa = ptarray_grid(point->point, grid);
+       return lwpoint_construct(point->srid, NULL, opa);
+}
+
index 4954a35514d9571f824883e35dc921bcfb132941..d11aa3349822669568fa2f859868605ae8373c2f 100644 (file)
@@ -489,3 +489,58 @@ lwpoly_startpoint(const LWPOLY* poly, POINT4D* pt)
        return ptarray_startpoint(poly->rings[0], pt);
 }
 
+
+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;
+}
index 8330ce59a689eba98055e23ae5224568ba47fb64..2a9d96ca6ab85f8c5b0f0ab14acfe6d307aac66f 100644 (file)
@@ -1733,3 +1733,54 @@ ptarray_startpoint(const POINTARRAY* pa, POINT4D* pt)
 {
        return getPoint4d_p(pa, 0, pt);
 }
+
+
+
+
+/*
+ * Stick an array of points to the given gridspec.
+ * Return "gridded" points in *outpts and their number in *outptsn.
+ *
+ * Two consecutive points falling on the same grid cell are collapsed
+ * into one single point.
+ *
+ */
+POINTARRAY *
+ptarray_grid(const POINTARRAY *pa, const gridspec *grid)
+{
+       POINT4D pt;
+       int ipn; /* input point numbers */
+       POINTARRAY *dpa;
+
+       LWDEBUGF(2, "ptarray_grid called on %p", pa);
+
+       dpa = ptarray_construct_empty(FLAGS_GET_Z(pa->flags),FLAGS_GET_M(pa->flags), pa->npoints);
+
+       for (ipn=0; ipn<pa->npoints; ++ipn)
+       {
+
+               getPoint4d_p(pa, ipn, &pt);
+
+               if ( grid->xsize )
+                       pt.x = rint((pt.x - grid->ipx)/grid->xsize) *
+                                grid->xsize + grid->ipx;
+
+               if ( grid->ysize )
+                       pt.y = rint((pt.y - grid->ipy)/grid->ysize) *
+                                grid->ysize + grid->ipy;
+
+               if ( FLAGS_GET_Z(pa->flags) && grid->zsize )
+                       pt.z = rint((pt.z - grid->ipz)/grid->zsize) *
+                                grid->zsize + grid->ipz;
+
+               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);
+
+       }
+
+       return dpa;
+}
+
index 9de4eaff569144dd1f05201d9d852c29cffb55f0..4c6b1ff900ab1b8135f8f186bfbf0d8de13f3b50 100644 (file)
@@ -25,6 +25,8 @@
 /* Install PosgreSQL handlers for liblwgeom use */
 void pg_install_lwgeom_handlers(void);
 
+#define PG_GETARG_GSERIALIZED(varno) ((GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(varno)))
+
 /* Debugging macros */
 #if POSTGIS_DEBUG_LEVEL > 0
 
index 60b32c29ebe46233dccb3a74c023c51ecda01692..1229b4f709468972683ddcc77da5d77d8f7a2857 100644 (file)
@@ -271,319 +271,40 @@ Datum LWGEOM_line_interpolate_point(PG_FUNCTION_ARGS)
 #define CHECK_RING_IS_CLOSE
 #define SAMEPOINT(a,b) ((a)->x==(b)->x&&(a)->y==(b)->y)
 
-typedef struct gridspec_t
-{
-       double ipx;
-       double ipy;
-       double ipz;
-       double ipm;
-       double xsize;
-       double ysize;
-       double zsize;
-       double msize;
-}
-gridspec;
 
 
 /* Forward declarations */
-LWGEOM *lwgeom_grid(LWGEOM *lwgeom, gridspec *grid);
-LWCOLLECTION *lwcollection_grid(LWCOLLECTION *coll, gridspec *grid);
-LWPOINT * lwpoint_grid(LWPOINT *point, gridspec *grid);
-LWPOLY * lwpoly_grid(LWPOLY *poly, gridspec *grid);
-LWLINE *lwline_grid(LWLINE *line, gridspec *grid);
-LWCIRCSTRING *lwcirc_grid(LWCIRCSTRING *line, gridspec *grid);
-POINTARRAY *ptarray_grid(POINTARRAY *pa, gridspec *grid);
 Datum LWGEOM_snaptogrid(PG_FUNCTION_ARGS);
 Datum LWGEOM_snaptogrid_pointoff(PG_FUNCTION_ARGS);
-static int grid_isNull(const gridspec *grid);
-#if POSTGIS_DEBUG_LEVEL >=4
-static void grid_print(const gridspec *grid);
-#endif
-
-/* A NULL grid is a grid in which size in all dimensions is 0 */
-static int
-grid_isNull(const gridspec *grid)
-{
-       if ( grid->xsize==0 &&
-               grid->ysize==0 &&
-               grid->zsize==0 &&
-               grid->msize==0 ) return 1;
-       else return 0;
-}
-
-#if POSTGIS_DEBUG_LEVEL >= 4
-/* Print grid using given reporter */
-static void
-grid_print(const gridspec *grid)
-{
-       lwnotice("GRID(%g %g %g %g, %g %g %g %g)",
-                grid->ipx, grid->ipy, grid->ipz, grid->ipm,
-                grid->xsize, grid->ysize, grid->zsize, grid->msize);
-}
-#endif
-
-/*
- * Stick an array of points to the given gridspec.
- * Return "gridded" points in *outpts and their number in *outptsn.
- *
- * Two consecutive points falling on the same grid cell are collapsed
- * into one single point.
- *
- */
-POINTARRAY *
-ptarray_grid(POINTARRAY *pa, gridspec *grid)
-{
-       POINT4D pbuf;
-       int ipn; /* input point numbers */
-       POINTARRAY *dpa;
-
-       POSTGIS_DEBUGF(2, "ptarray_grid called on %p", pa);
-
-       dpa = ptarray_construct_empty(FLAGS_GET_Z(pa->flags),FLAGS_GET_M(pa->flags), pa->npoints);
-
-       for (ipn=0; ipn<pa->npoints; ++ipn)
-       {
-
-               getPoint4d_p(pa, ipn, &pbuf);
-
-               if ( grid->xsize )
-                       pbuf.x = rint((pbuf.x - grid->ipx)/grid->xsize) *
-                                grid->xsize + grid->ipx;
-
-               if ( grid->ysize )
-                       pbuf.y = rint((pbuf.y - grid->ipy)/grid->ysize) *
-                                grid->ysize + grid->ipy;
-
-               if ( FLAGS_GET_Z(pa->flags) && grid->zsize )
-                       pbuf.z = rint((pbuf.z - grid->ipz)/grid->zsize) *
-                                grid->zsize + grid->ipz;
-
-               if ( FLAGS_GET_M(pa->flags) && grid->msize )
-                       pbuf.m = rint((pbuf.m - grid->ipm)/grid->msize) *
-                                grid->msize + grid->ipm;
-
-               ptarray_append_point(dpa, &pbuf, LW_FALSE);
-
-       }
 
-       return dpa;
-}
-
-LWLINE *
-lwline_grid(LWLINE *line, 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;
-}
-
-LWCIRCSTRING *
-lwcirc_grid(LWCIRCSTRING *line, 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;
-}
-
-LWPOLY *
-lwpoly_grid(LWPOLY *poly, gridspec *grid)
-{
-       LWPOLY *opoly;
-       int ri;
-       POINTARRAY **newrings = NULL;
-       int nrings = 0;
-#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
-
-       nrings = 0;
-
-       POSTGIS_DEBUGF(3, "grid_polygon3d: applying grid to polygon with %d rings",
-                poly->nrings);
-
-       for (ri=0; ri<poly->nrings; ri++)
-       {
-               POINTARRAY *ring = poly->rings[ri];
-               POINTARRAY *newring;
-
-#if POSTGIS_DEBUG_LEVEL >= 4
-               POINT2D p1, p2;
-               getPoint2d_p(ring, 0, &p1);
-               getPoint2d_p(ring, ring->npoints-1, &p2);
-               if ( ! SAMEPOINT(&p1, &p2) )
-                       POSTGIS_DEBUG(4, "Before gridding: first point != last point");
-#endif
-
-               newring = ptarray_grid(ring, grid);
-
-               /* Skip ring if not composed by at least 4 pts (3 segments) */
-               if ( newring->npoints < 4 )
-               {
-                       pfree(newring);
-
-                       POSTGIS_DEBUGF(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 POSTGIS_DEBUG_LEVEL >= 4
-               getPoint2d_p(newring, 0, &p1);
-               getPoint2d_p(newring, newring->npoints-1, &p2);
-               if ( ! SAMEPOINT(&p1, &p2) )
-                       POSTGIS_DEBUG(4, "After gridding: first point != last point");
-#endif
 
-               POSTGIS_DEBUGF(3, "grid_polygon3d: ring%d simplified from %d to %d points", ri,
-                        ring->npoints, newring->npoints);
-
-               /*
-                * Add ring to simplified ring array
-                * (TODO: dinamic allocation of pts_per_ring)
-                */
-               if ( ! nrings )
-               {
-                       newrings = palloc(sizeof(POINTARRAY *));
-               }
-               else
-               {
-                       newrings = repalloc(newrings, sizeof(POINTARRAY *)*(nrings+1));
-               }
-               if ( ! newrings )
-               {
-                       elog(ERROR, "Out of virtual memory");
-                       return NULL;
-               }
-               newrings[nrings++] = newring;
-       }
-
-       POSTGIS_DEBUGF(3, "grid_polygon3d: simplified polygon with %d rings", nrings);
-
-       if ( ! nrings ) return NULL;
-
-       opoly = lwpoly_construct(poly->srid, NULL, nrings, newrings);
-       return opoly;
-}
-
-LWPOINT *
-lwpoint_grid(LWPOINT *point, gridspec *grid)
-{
-       LWPOINT *opoint;
-       POINTARRAY *opa;
-
-       opa = ptarray_grid(point->point, grid);
-
-       /* TODO: grid bounding box ? */
-       opoint = lwpoint_construct(point->srid, NULL, opa);
-
-       POSTGIS_DEBUG(2, "lwpoint_grid called");
-
-       return opoint;
-}
-
-LWCOLLECTION *
-lwcollection_grid(LWCOLLECTION *coll, gridspec *grid)
-{
-       uint32 i;
-       LWGEOM **geoms;
-       uint32 ngeoms=0;
-
-       geoms = palloc(coll->ngeoms * sizeof(LWGEOM *));
-
-       for (i=0; i<coll->ngeoms; i++)
-       {
-               LWGEOM *g = lwgeom_grid(coll->geoms[i], grid);
-               if ( g ) geoms[ngeoms++] = g;
-       }
-
-       if ( ! ngeoms ) return lwcollection_construct_empty(coll->type, coll->srid, 0, 0);
-
-       return lwcollection_construct(coll->type, coll->srid,
-                                     NULL, ngeoms, geoms);
-}
-
-LWGEOM *
-lwgeom_grid(LWGEOM *lwgeom, gridspec *grid)
-{
-       switch (lwgeom->type)
-       {
-       case POINTTYPE:
-               return (LWGEOM *)lwpoint_grid((LWPOINT *)lwgeom, grid);
-       case LINETYPE:
-               return (LWGEOM *)lwline_grid((LWLINE *)lwgeom, grid);
-       case POLYGONTYPE:
-               return (LWGEOM *)lwpoly_grid((LWPOLY *)lwgeom, grid);
-       case MULTIPOINTTYPE:
-       case MULTILINETYPE:
-       case MULTIPOLYGONTYPE:
-       case COLLECTIONTYPE:
-       case COMPOUNDTYPE:
-               return (LWGEOM *)lwcollection_grid((LWCOLLECTION *)lwgeom, grid);
-       case CIRCSTRINGTYPE:
-               return (LWGEOM *)lwcirc_grid((LWCIRCSTRING *)lwgeom, grid);
-       default:
-               elog(ERROR, "lwgeom_grid: Unsupported geometry type: %s",
-                    lwtype_name(lwgeom->type));
-               return NULL;
-       }
-}
 
 PG_FUNCTION_INFO_V1(LWGEOM_snaptogrid);
 Datum LWGEOM_snaptogrid(PG_FUNCTION_ARGS)
 {
-       Datum datum;
-       GSERIALIZED *in_geom;
        LWGEOM *in_lwgeom;
        GSERIALIZED *out_geom = NULL;
        LWGEOM *out_lwgeom;
        gridspec grid;
-       /* BOX3D box3d; */
 
-       if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
-       datum = PG_GETARG_DATUM(0);
-       in_geom = (GSERIALIZED *)PG_DETOAST_DATUM(datum);
+       GSERIALIZED *in_geom = PG_GETARG_GSERIALIZED(0);
 
-       if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
-       grid.ipx = PG_GETARG_FLOAT8(1);
+       /* Set grid values to zero to start */
+       memset(&grid, 0, sizeof(gridspec));
 
-       if ( PG_ARGISNULL(2) ) PG_RETURN_NULL();
+       grid.ipx = PG_GETARG_FLOAT8(1);
        grid.ipy = PG_GETARG_FLOAT8(2);
-
-       if ( PG_ARGISNULL(3) ) PG_RETURN_NULL();
        grid.xsize = PG_GETARG_FLOAT8(3);
-
-       if ( PG_ARGISNULL(4) ) PG_RETURN_NULL();
        grid.ysize = PG_GETARG_FLOAT8(4);
 
-       /* Do not support gridding Z and M values for now */
-       grid.ipz=grid.ipm=grid.zsize=grid.msize=0;
-
-       /* Return input geometry if grid is null or input geometry is empty */
-       if ( grid_isNull(&grid) || gserialized_is_empty(in_geom) )
+       /* Return input geometry if input geometry is empty */
+       if ( gserialized_is_empty(in_geom) )
+       {
+               PG_RETURN_POINTER(in_geom);
+       }
+       
+       /* Return input geometry if input grid is meaningless */
+       if ( grid.xsize==0 && grid.ysize==0 && grid.zsize==0 && grid.msize==0 )
        {
                PG_RETURN_POINTER(in_geom);
        }
@@ -596,7 +317,8 @@ Datum LWGEOM_snaptogrid(PG_FUNCTION_ARGS)
        if ( out_lwgeom == NULL ) PG_RETURN_NULL();
 
        /* COMPUTE_BBOX TAINTING */
-       if ( in_lwgeom->bbox ) lwgeom_add_bbox(out_lwgeom);
+       if ( in_lwgeom->bbox ) 
+               lwgeom_add_bbox(out_lwgeom);
 
 
        POSTGIS_DEBUGF(3, "SnapToGrid made a %s", lwtype_name(out_lwgeom->type));
@@ -606,10 +328,22 @@ Datum LWGEOM_snaptogrid(PG_FUNCTION_ARGS)
        PG_RETURN_POINTER(out_geom);
 }
 
+
+#if POSTGIS_DEBUG_LEVEL >= 4
+/* Print grid using given reporter */
+static void
+grid_print(const gridspec *grid)
+{
+       lwnotice("GRID(%g %g %g %g, %g %g %g %g)",
+                grid->ipx, grid->ipy, grid->ipz, grid->ipm,
+                grid->xsize, grid->ysize, grid->zsize, grid->msize);
+}
+#endif
+
+
 PG_FUNCTION_INFO_V1(LWGEOM_snaptogrid_pointoff);
 Datum LWGEOM_snaptogrid_pointoff(PG_FUNCTION_ARGS)
 {
-       Datum datum;
        GSERIALIZED *in_geom, *in_point;
        LWGEOM *in_lwgeom;
        LWPOINT *in_lwpoint;
@@ -619,29 +353,24 @@ Datum LWGEOM_snaptogrid_pointoff(PG_FUNCTION_ARGS)
        /* BOX3D box3d; */
        POINT4D offsetpoint;
 
-       if ( PG_ARGISNULL(0) ) PG_RETURN_NULL();
-       datum = PG_GETARG_DATUM(0);
-       in_geom = (GSERIALIZED *)PG_DETOAST_DATUM(datum);
+       in_geom = PG_GETARG_GSERIALIZED(0);
 
-       if ( PG_ARGISNULL(1) ) PG_RETURN_NULL();
-       datum = PG_GETARG_DATUM(1);
-       in_point = (GSERIALIZED *)PG_DETOAST_DATUM(datum);
+       /* Return input geometry if input geometry is empty */
+       if ( gserialized_is_empty(in_geom) )
+       {
+               PG_RETURN_POINTER(in_geom);
+       }
+
+       in_point = PG_GETARG_GSERIALIZED(1);
        in_lwpoint = lwgeom_as_lwpoint(lwgeom_from_gserialized(in_point));
        if ( in_lwpoint == NULL )
        {
                lwerror("Offset geometry must be a point");
        }
 
-       if ( PG_ARGISNULL(2) ) PG_RETURN_NULL();
        grid.xsize = PG_GETARG_FLOAT8(2);
-
-       if ( PG_ARGISNULL(3) ) PG_RETURN_NULL();
        grid.ysize = PG_GETARG_FLOAT8(3);
-
-       if ( PG_ARGISNULL(4) ) PG_RETURN_NULL();
        grid.zsize = PG_GETARG_FLOAT8(4);
-
-       if ( PG_ARGISNULL(5) ) PG_RETURN_NULL();
        grid.msize = PG_GETARG_FLOAT8(5);
 
        /* Take offsets from point geometry */
@@ -656,9 +385,9 @@ Datum LWGEOM_snaptogrid_pointoff(PG_FUNCTION_ARGS)
 #if POSTGIS_DEBUG_LEVEL >= 4
        grid_print(&grid);
 #endif
-
-       /* Return input geometry if grid is null */
-       if ( grid_isNull(&grid) )
+       
+       /* Return input geometry if input grid is meaningless */
+       if ( grid.xsize==0 && grid.ysize==0 && grid.zsize==0 && grid.msize==0 )
        {
                PG_RETURN_POINTER(in_geom);
        }
index 11eb6a9cc644f7a225af6323585d10db2b66b362..33fed1f41ab5262c74585d394ed469f983de60b4 100644 (file)
@@ -169,21 +169,21 @@ Datum geometry_geometrytype(PG_FUNCTION_ARGS)
 {
        GSERIALIZED *gser;
        text *type_text;
-       char *type_str = palloc(32);
+       static int type_str_len = 32;
+       char type_str[type_str_len];
 
        /* Read just the header from the toasted tuple */
        gser = (GSERIALIZED*)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(0), 0, gserialized_max_header_size());
 
        /* Make it empty string to start */
-       *type_str = 0;
+       type_str[0] = 0;
 
        /* Build up the output string */
-       strncat(type_str, "ST_", 32);
-       strncat(type_str, lwtype_name(gserialized_get_type(gser)), 32);
+       strncat(type_str, "ST_", type_str_len);
+       strncat(type_str, lwtype_name(gserialized_get_type(gser)), type_str_len);
        
        /* Build a text type to store things in */
        type_text = cstring2text(type_str);
-       pfree(type_str);
 
        PG_FREE_IF_COPY(gser, 0);
        PG_RETURN_TEXT_P(type_text);