]> granicus.if.org Git - postgis/commitdiff
Changed getbox2d_p signature to return 0 for EMPTY geometries.
authorSandro Santilli <strk@keybit.net>
Mon, 6 Sep 2004 16:04:13 +0000 (16:04 +0000)
committerSandro Santilli <strk@keybit.net>
Mon, 6 Sep 2004 16:04:13 +0000 (16:04 +0000)
Ported DP simplifier.

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

lwgeom/MISSING_OBJECTS
lwgeom/TODO
lwgeom/lwgeom.h
lwgeom/lwgeom_api.c
lwgeom/lwgeom_box2dfloat4.c
lwgeom/lwgeom_box3d.c
lwgeom/lwgeom_functions_analytic.c
lwgeom/lwgeom_functions_basic.c
lwgeom/lwgeom_inout.c
lwgeom/lwpostgis.sql.in

index 586eb232c3fa0e490cb6597aa5ea88f08633398b..5e800ea30b59b15fb9148c2a2648e068e7c832da 100644 (file)
@@ -1,6 +1,5 @@
 # This is a list of objects still missing lwgeom support
 
-FNCAST: KEEPING FNCAST geometry(text) (see CAST)
 FUNC: KEEPING FUNCTION: [line_interpolate_point(geometry, double precision)]
 FUNC: KEEPING FUNCTION: [simplify(geometry, double precision)]
 FUNC: KEEPING FUNCTION: [segmentize(geometry, double precision)]
index feaf007cfc60e0bcf62964ba17a245407183aa1b..ed170f8a0b64779c37a384e70fe209f9b8eafdbc 100644 (file)
@@ -1,4 +1,6 @@
 
+- WKB: what to do with that ? do we want to keep it as a type ?
+
 - Check spheroid misure functions
        o can't understand if 3d computation works since
          I get same result w/ 2d and 3d.
index d73a69434f86766761af1acd837ab8203ffb2cc5..af2ae67a445f38b128286a5aa6db2e219f6a0379 100644 (file)
@@ -229,7 +229,7 @@ typedef struct
        POINTARRAY    *points; // array of POINT3D
 } LWLINE; //"light-weight line"
 
-// construct a new LWLINE.  points will be copied
+// construct a new LWLINE.  points will *NOT* be copied
 // use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
 extern LWLINE *lwline_construct(int ndims, int SRID, POINTARRAY *points);
 
@@ -504,7 +504,7 @@ extern BOX3D *combine_boxes(BOX3D *b1, BOX3D *b2);
 // if this has a pre-built BOX2d, then we use it,
 // otherwise we need to compute it.
 extern BOX2DFLOAT4 getbox2d(char *serialized_form);
-extern void getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box);
+extern int getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box);
 
 // Expand given box of 'd' units in all directions 
 void expand_box2d(BOX2DFLOAT4 *box, double d);
@@ -702,3 +702,30 @@ extern double nextUp_d(float d);
 #endif
 #define abs(a)                 ((a) <  (0) ? (-a) : (a))
 
+
+// general utilities 
+double lwgeom_polygon_area(LWPOLY *poly);
+double lwgeom_polygon_perimeter(LWPOLY *poly);
+double lwgeom_polygon_perimeter2d(LWPOLY *poly);
+double lwgeom_pointarray_length2d(POINTARRAY *pts);
+double lwgeom_pointarray_length(POINTARRAY *pts);
+void lwgeom_force2d_recursive(char *serialized, char *optr, int *retsize);
+void lwgeom_force3d_recursive(char *serialized, char *optr, int *retsize);
+double distance2d_pt_pt(POINT2D *p1, POINT2D *p2);
+double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B);
+double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D);
+double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa);
+double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2);
+int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring);
+int pt_in_poly_2d(POINT2D *p, LWPOLY *poly);
+double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly);
+double distance2d_point_point(LWPOINT *point1, LWPOINT *point2);
+double distance2d_point_line(LWPOINT *point, LWLINE *line);
+double distance2d_line_line(LWLINE *line1, LWLINE *line2);
+double distance2d_point_poly(LWPOINT *point, LWPOLY *poly);
+double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2);
+double distance2d_line_poly(LWLINE *line, LWPOLY *poly);
+double lwgeom_mindistance2d_recursive(char *lw1, char *lw2);
+void lwgeom_translate_recursive(char *serialized, double xoff, double yoff, double zoff);
+void lwgeom_translate_ptarray(POINTARRAY *pa, double xoff, double yoff, double zoff);
+int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad);
index f2fd1ecf6c038510f97788368196223a792b2e3a..1510f4b3ac2ebdea45aa4bb2fde5655e24887f2f 100644 (file)
@@ -376,7 +376,7 @@ BOX2DFLOAT4 getbox2d(char *serialized_form)
 
 
 // same as getbox2d, but modifies box instead of returning result on the stack
-void
+int
 getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box)
 {
        unsigned char type = (unsigned char) serialized_form[0];
@@ -391,17 +391,22 @@ getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box)
                //woot - this is easy
 //elog(NOTICE,"getbox2d has box");
                memcpy(box,loc, sizeof(BOX2DFLOAT4));
-               return ;
+               return 1;
        }
 
        //we have to actually compute it!
 //elog(NOTICE,"getbox2d_p:: computing box");
        box3d = lw_geom_getBB_simple(serialized_form);
+       if ( ! box3d )
+       {
+               return 0;
+       }
        box2 = box3d_to_box2df(box3d);
 
        memcpy(box,box2, sizeof(BOX2DFLOAT4));
        pfree(box3d);
        pfree(box2);
+       return 1;
 }
 
 //************************************************************************
@@ -759,7 +764,7 @@ int32 get_int32(char *loc)
 // basic LWLINE functions
 
 
-// construct a new LWLINE.  points will be copied
+// construct a new LWLINE.  points will *NOT* be copied
 // use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
 LWLINE *lwline_construct(int ndims, int SRID,  POINTARRAY *points)
 {
@@ -2894,6 +2899,11 @@ lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox)
        BOX3D *box3d;
        char *ser;
 
+       if ( exploded->npoints + exploded->nlines + exploded->npolys == 0 )
+       {
+               return lwgeom_constructempty(exploded->SRID, exploded->ndims);
+       }
+
        // find size of all geoms.
        // If BBOX and SRID are included this size could be
        // larger then needed, but that should not be a problem
@@ -2928,6 +2938,11 @@ lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox)
        elog(NOTICE, " computed outtype: %d, ngeoms: %d", outtype, ngeoms);
 #endif
 
+       if ( ! ngeoms )
+       {
+               return lwgeom_constructempty(exploded->SRID, exploded->ndims);
+       }
+
 
        // For a single geometry just set SRID and BBOX (if requested)
        if ( ngeoms < 2 )
index 829682ff06fbd4014d8205623a40ee6192cf6e83..05f615a93f0398ee5cb93840835e4d6d8226452a 100644 (file)
@@ -104,7 +104,10 @@ Datum LWGEOM_to_BOX2DFLOAT4(PG_FUNCTION_ARGS)
        BOX2DFLOAT4 *result;
 
        result = palloc(sizeof(BOX2DFLOAT4));
-       getbox2d_p(SERIALIZED_FORM(lwgeom), result);
+       if ( ! getbox2d_p(SERIALIZED_FORM(lwgeom), result) )
+       {
+               PG_RETURN_NULL(); // must be the empty geometry
+       }
        PG_RETURN_POINTER(result);
 }
 
@@ -378,8 +381,8 @@ Datum BOX2DFLOAT4_combine(PG_FUNCTION_ARGS)
        if (box2d_ptr == NULL)
        {
                lwgeom = (char *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
-               box = getbox2d(lwgeom+4);
+               // empty geom would make getbox2d_p return NULL
+               if ( ! getbox2d_p(lwgeom+4, &box) ) PG_RETURN_NULL();
                memcpy(result, &box, sizeof(BOX2DFLOAT4));
                PG_RETURN_POINTER(result);
        }
@@ -394,7 +397,12 @@ Datum BOX2DFLOAT4_combine(PG_FUNCTION_ARGS)
        //combine_bbox(BOX3D, geometry) => union(BOX3D, geometry->bvol)
 
        lwgeom = (char *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-       box = getbox2d(lwgeom+4);
+       if ( ! getbox2d_p(lwgeom+4, &box) )
+       {
+               // must be the empty geom
+               memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(BOX2DFLOAT4));
+               PG_RETURN_POINTER(result);
+       }
 
        a = (BOX2DFLOAT4 *)PG_GETARG_DATUM(0);
        b = &box;
index 29291e367bcc177374a190a18acf7318704c79e3..61e656f2733d13cd4dc439434dc1977372e784b6 100644 (file)
@@ -291,6 +291,7 @@ Datum BOX3D_combine(PG_FUNCTION_ARGS)
        {
                lwgeom = (LWGEOM *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
                box = lw_geom_getBB(SERIALIZED_FORM(lwgeom));
+               if ( ! box ) PG_RETURN_NULL(); // must be the empty geom
                memcpy(result, box, sizeof(BOX3D));
                PG_RETURN_POINTER(result);
        }
@@ -304,6 +305,11 @@ Datum BOX3D_combine(PG_FUNCTION_ARGS)
 
        lwgeom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
        box = lw_geom_getBB(SERIALIZED_FORM(lwgeom));
+       if ( ! box ) // must be the empty geom
+       {
+               memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(BOX3D));
+               PG_RETURN_POINTER(result);
+       }
 
        a = (BOX3D *)PG_GETARG_DATUM(0);
        b = box;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..430ddc84926a5be4d02d09812e63a515819c92b9 100644 (file)
@@ -0,0 +1,332 @@
+#include "postgres.h"
+#include "lwgeom.h"
+
+/***********************************************************************
+ * Simple Douglas-Peucker line simplification. 
+ * No checks are done to avoid introduction of self-intersections.
+ * No topology relations are considered.
+ *
+ * --strk@keybit.net;
+ ***********************************************************************/
+
+#define SAMEPOINT(a,b) ((a)->x==(b)->x&&(a)->y==(b)->y&&(a)->z==(b)->z)
+#define VERBOSE 0
+
+#if VERBOSE > 0
+#define REPORT_POINTS_REDUCTION
+#define REPORT_RINGS_REDUCTION
+#define REPORT_RINGS_ADJUSTMENTS
+#endif
+
+/* Prototypes */
+void DP_findsplit2d(POINTARRAY *pts, int p1, int p2, int *split, double *dist);
+POINTARRAY *DP_simplify2d(POINTARRAY *inpts, double epsilon);
+LWLINE *simplify2d_lwline(LWLINE *iline, double dist);
+LWPOLY *simplify2d_lwpoly(LWPOLY *ipoly, double dist);
+Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS);
+
+
+/*
+ * Search farthest point from segment p1-p2
+ * returns distance in an int pointer
+ */
+void
+DP_findsplit2d(POINTARRAY *pts, int p1, int p2, int *split, double *dist)
+{
+   int k;
+   POINT2D *pa, *pb, *pk;
+   double tmp;
+
+#if VERBOSE > 4
+elog(NOTICE, "DP_findsplit called");
+#endif
+
+   *dist = -1;
+   *split = p1;
+
+   if (p1 + 1 < p2)
+   {
+
+      pa = (POINT2D *)getPoint(pts, p1);
+      pb = (POINT2D *)getPoint(pts, p2);
+
+#if VERBOSE > 4
+elog(NOTICE, "DP_findsplit: P%d(%f,%f) to P%d(%f,%f)",
+   p1, pa->x, pa->y, p2, pb->x, pb->y);
+#endif
+
+      for (k=p1+1; k<p2; k++)
+      {
+         pk = (POINT2D *)getPoint(pts, k);
+
+#if VERBOSE > 4
+elog(NOTICE, "DP_findsplit: P%d(%f,%f)", k, pk->x, pk->y);
+#endif
+
+         /* distance computation */
+         tmp = distance2d_pt_seg(pk, pa, pb);
+
+         if (tmp > *dist) 
+         {
+            *dist = tmp;       /* record the maximum */
+            *split = k;
+#if VERBOSE > 4
+elog(NOTICE, "DP_findsplit: P%d is farthest (%g)", k, *dist);
+#endif
+         }
+      }
+
+   } /* length---should be redone if can == 0 */
+
+   else
+   {
+#if VERBOSE > 3
+elog(NOTICE, "DP_findsplit: segment too short, no split/no dist");
+#endif
+   }
+
+}
+
+
+POINTARRAY *
+DP_simplify2d(POINTARRAY *inpts, double epsilon)
+{
+       int stack[inpts->npoints];      /* recursion stack */
+       int sp=-1;                      /* recursion stack pointer */
+       int p1, split; 
+       double dist;
+       POINTARRAY *outpts;
+       int ptsize = sizeof(double)*inpts->ndims;
+
+       p1 = 0;
+       stack[++sp] = inpts->npoints-1;
+
+#if VERBOSE > 4
+       elog(NOTICE, "DP_simplify called input has %d pts and %d dims (ptsize: %d)", inpts->npoints, inpts->ndims, ptsize);
+#endif
+
+       // allocate space for output POINTARRAY
+       outpts = palloc(sizeof(POINTARRAY));
+       outpts->ndims = inpts->ndims;
+       outpts->npoints=1;
+       outpts->serialized_pointlist = (char *)palloc(ptsize*inpts->npoints);
+       memcpy(getPoint(outpts, 0), getPoint(inpts, 0), ptsize);
+
+#if VERBOSE > 3
+       elog(NOTICE, "DP_simplify: added P0 to simplified point array (size 1)");
+#endif
+
+
+       do
+       {
+
+               DP_findsplit2d(inpts, p1, stack[sp], &split, &dist);
+#if VERBOSE > 3
+               elog(NOTICE, "DP_simplify: farthest point from P%d-P%d is P%d (dist. %g)", p1, stack[sp], split, dist);
+#endif
+
+               if (dist > epsilon) {
+                       stack[++sp] = split;
+               } else {
+                       outpts->npoints++;
+                       memcpy(getPoint(outpts, outpts->npoints-1),
+                               getPoint(inpts, stack[sp]),
+                               ptsize);
+#if VERBOSE > 3
+                       elog(NOTICE, "DP_simplify: added P%d to simplified point array (size: %d)", stack[sp], outpts->npoints);
+#endif
+                       p1 = stack[sp--];
+               }
+#if VERBOSE > 5
+               elog(NOTICE, "stack pointer = %d", sp);
+#endif
+       }
+       while (! (sp<0) );
+
+       /*
+        * If we have reduced the number of points realloc
+        * outpoints array to free up some memory.
+        * Might be turned on and off with a SAVE_MEMORY define ...
+        */
+       if ( outpts->npoints < inpts->npoints )
+       {
+               outpts->serialized_pointlist = (char *)repalloc(
+                       outpts->serialized_pointlist,
+                       ptsize*outpts->npoints);
+               if ( outpts->serialized_pointlist == NULL ) {
+                       elog(ERROR, "Out of virtual memory");
+               }
+       }
+
+       return outpts;
+}
+
+LWLINE *
+simplify2d_lwline(LWLINE *iline, double dist)
+{
+       POINTARRAY *ipts;
+       POINTARRAY *opts;
+       LWLINE *oline;
+
+#if VERBOSE
+   elog(NOTICE, "simplify2d_lwline called");
+#endif
+
+       ipts = iline->points;
+       opts = DP_simplify2d(ipts, dist);
+       oline = lwline_construct(ipts->ndims, iline->SRID, opts);
+
+       return oline;
+}
+
+// TODO
+LWPOLY *
+simplify2d_lwpoly(LWPOLY *ipoly, double dist)
+{
+       POINTARRAY *ipts;
+       POINTARRAY **orings = NULL;
+       LWPOLY *opoly;
+       int norings=0, ri;
+
+#ifdef REPORT_RINGS_REDUCTION
+       elog(NOTICE, "simplify_polygon3d: simplifying polygon with %d rings", ipoly->nrings);
+#endif
+
+       orings = (POINTARRAY **)palloc(sizeof(POINTARRAY *)*ipoly->nrings);
+
+       for (ri=0; ri<ipoly->nrings; ri++)
+       {
+               POINTARRAY *opts;
+
+               ipts = ipoly->rings[ri];
+
+               opts = DP_simplify2d(ipts, dist);
+
+
+               if ( opts->npoints < 2 )
+               {
+                       /* There as to be an error in DP_simplify */
+                       elog(NOTICE, "DP_simplify returned a <2 pts array");
+                       pfree(opts);
+                       continue;
+               }
+
+               if ( opts->npoints < 4 )
+               {
+                       pfree(opts);
+#ifdef REPORT_RINGS_ADJUSTMENTS
+                       elog(NOTICE, "simplify_polygon3d: ring%d skipped ( <4 pts )", ri);
+#endif
+
+                       if ( ri ) continue;
+                       else break;
+               }
+
+
+#ifdef REPORT_POINTS_REDUCTION
+               elog(NOTICE, "simplify_polygon3d: ring%d simplified from %d to %d points", ri, ipts->npoints, opts->npoints);
+#endif
+
+
+               /*
+                * Add ring to simplified ring array
+                * (TODO: dinamic allocation of pts_per_ring)
+                */
+               orings[norings] = opts;
+               norings++;
+
+       }
+
+#ifdef REPORT_RINGS_REDUCTION
+elog(NOTICE, "simplify_polygon3d: simplified polygon with %d rings", norings);
+#endif
+
+       if ( ! norings ) return NULL;
+
+       opoly = palloc(sizeof(LWPOLY));
+       opoly->SRID = ipoly->SRID;
+       opoly->ndims = ipoly->ndims;
+       opoly->nrings = norings;
+       opoly->rings = orings;
+
+       return opoly;
+}
+
+PG_FUNCTION_INFO_V1(LWGEOM_simplify2d);
+Datum LWGEOM_simplify2d(PG_FUNCTION_ARGS)
+{
+       LWGEOM *geom = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       LWGEOM_EXPLODED *exp = lwgeom_explode(SERIALIZED_FORM(geom));
+       double dist = PG_GETARG_FLOAT8(1);
+       int i;
+       char **newlines;
+       int newlinesnum=0;
+       char **newpolys;
+       int newpolysnum=0;
+       LWGEOM *result;
+       char *serialized;
+
+       // no lines, no points... return input
+       if ( exp->nlines + exp->npolys == 0 )
+       {
+               pfree_exploded(exp);
+               PG_RETURN_POINTER(geom);
+       }
+
+       if ( exp->nlines )
+       {
+#if VERBOSE
+               elog(NOTICE, "%d lines in exploded geom", exp->nlines);
+#endif
+               newlines = palloc(sizeof(char *)*exp->nlines);
+               for ( i=0; i<exp->nlines; i++ )
+               {
+                       LWLINE *iline = lwline_deserialize(exp->lines[i]);
+#if VERBOSE
+                       elog(NOTICE, " line %d deserialized", i);
+#endif
+                       LWLINE *oline = simplify2d_lwline(iline, dist);
+#if VERBOSE
+                       elog(NOTICE, " line %d simplified", i);
+#endif
+                       if ( oline == NULL ) continue;
+                       newlines[newlinesnum] = lwline_serialize(oline);
+                       newlinesnum++;
+               }
+               pfree(exp->lines);
+               exp->lines = newlines;
+               exp->nlines = newlinesnum;
+       }
+
+       if ( exp->npolys )
+       {
+               newpolys = palloc(sizeof(char *)*exp->npolys);
+               for ( i=0; i<exp->npolys; i++ )
+               {
+                       LWPOLY *ipoly = lwpoly_deserialize(exp->polys[i]);
+                       LWPOLY *opoly = simplify2d_lwpoly(ipoly, dist);
+                       if ( opoly == NULL ) continue;
+                       newpolys[newpolysnum] = lwpoly_serialize(opoly);
+                       newpolysnum++;
+               }
+               pfree(exp->polys);
+               exp->polys = newpolys;
+               exp->npolys = newpolysnum;
+       }
+
+       // copy 1 (when lwexploded_serialize_buf will be implemented this
+       // can be avoided)
+       serialized = lwexploded_serialize(exp, lwgeom_hasBBOX(geom->type));
+       pfree_exploded(exp);
+
+
+       // copy 2 (see above)
+       result = LWGEOM_construct(serialized,
+               lwgeom_getSRID(geom), lwgeom_hasBBOX(geom->type));
+
+       PG_RETURN_POINTER(result);
+}
+
+/***********************************************************************
+ * --strk@keybit.net;
+ ***********************************************************************/
index edfa8531eb55d53ebd43dbc2ef64e9d9751210d0..4db73c3bb91ba582ce3dc41020ef33ca83ea5004 100644 (file)
@@ -48,32 +48,6 @@ int32 lwgeom_npoints_recursive(char *serialized);
 int32 lwgeom_nrings_recursive(char *serialized);
 void dump_lwexploded(LWGEOM_EXPLODED *exploded);
 
-// general utilities (might be moved in lwgeom_api.c)
-double lwgeom_polygon_area(LWPOLY *poly);
-double lwgeom_polygon_perimeter(LWPOLY *poly);
-double lwgeom_polygon_perimeter2d(LWPOLY *poly);
-double lwgeom_pointarray_length2d(POINTARRAY *pts);
-double lwgeom_pointarray_length(POINTARRAY *pts);
-void lwgeom_force2d_recursive(char *serialized, char *optr, int *retsize);
-void lwgeom_force3d_recursive(char *serialized, char *optr, int *retsize);
-double distance2d_pt_pt(POINT2D *p1, POINT2D *p2);
-double distance2d_pt_seg(POINT2D *p, POINT2D *A, POINT2D *B);
-double distance2d_seg_seg(POINT2D *A, POINT2D *B, POINT2D *C, POINT2D *D);
-double distance2d_pt_ptarray(POINT2D *p, POINTARRAY *pa);
-double distance2d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2);
-int pt_in_ring_2d(POINT2D *p, POINTARRAY *ring);
-int pt_in_poly_2d(POINT2D *p, LWPOLY *poly);
-double distance2d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly);
-double distance2d_point_point(LWPOINT *point1, LWPOINT *point2);
-double distance2d_point_line(LWPOINT *point, LWLINE *line);
-double distance2d_line_line(LWLINE *line1, LWLINE *line2);
-double distance2d_point_poly(LWPOINT *point, LWPOLY *poly);
-double distance2d_poly_poly(LWPOLY *poly1, LWPOLY *poly2);
-double distance2d_line_poly(LWLINE *line, LWPOLY *poly);
-double lwgeom_mindistance2d_recursive(char *lw1, char *lw2);
-void lwgeom_translate_recursive(char *serialized, double xoff, double yoff, double zoff);
-void lwgeom_translate_ptarray(POINTARRAY *pa, double xoff, double yoff, double zoff);
-int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad);
 
 
 /*------------------------------------------------------------------*/
@@ -826,15 +800,24 @@ lwgeom_summary_recursive(char *serialized, int offset)
                LWLINE *line=NULL;
                LWPOINT *point=NULL;
                LWPOLY *poly=NULL;
-               char *subgeom=NULL;
+               char *subgeom=lwgeom_getsubgeometry_inspected(inspected, j);
+
+               if ( lwgeom_getType(subgeom[0]) == 0 )
+               {
+                       size += 32;
+                       result = repalloc(result,size);
+                       sprintf(tmp,"Object %i is EMPTY()\n", idx++);
+                       strcat(result,tmp);
+                       continue;
+               }
+
 
                point = lwgeom_getpoint_inspected(inspected,j);
                if (point !=NULL)
                {
-                       size += 30;
+                       size += 32;
                        result = repalloc(result,size);
-                       sprintf(tmp,"Object %i is a POINT()\n",
-                               idx++);
+                       sprintf(tmp,"Object %i is a POINT()\n", idx++);
                        strcat(result,tmp);
                        continue;
                }
@@ -842,10 +825,10 @@ lwgeom_summary_recursive(char *serialized, int offset)
                poly = lwgeom_getpoly_inspected(inspected, j);
                if (poly !=NULL)
                {
-                       size += 57*(poly->nrings+1);
+                       size += 60*(poly->nrings+1);
                        result = repalloc(result,size);
                        sprintf(tmp,"Object %i is a POLYGON() with %i rings\n",
-                                       idx++, poly->nrings);
+                               idx++, poly->nrings);
                        strcat(result,tmp);
                        for (i=0; i<poly->nrings;i++)
                        {
@@ -861,26 +844,16 @@ lwgeom_summary_recursive(char *serialized, int offset)
                {
                        size += 57;
                        result = repalloc(result,size);
-                       sprintf(tmp,
-                               "Object %i is a LINESTRING() with %i points\n",
-                               idx++, line->points->npoints);
+                       sprintf(tmp, "Object %i is a LINESTRING() with %i points\n", idx++, line->points->npoints);
                        strcat(result,tmp);
                        continue;
                }
 
-               subgeom = lwgeom_getsubgeometry_inspected(inspected, j);
-               if ( subgeom != NULL )
-               {
-                       ptr = lwgeom_summary_recursive(subgeom, 1);
-                       size += strlen(ptr);
-                       result = repalloc(result,size);
-                       strcat(result, ptr);
-                       pfree(ptr);
-               }
-               else
-               {
-                       elog(ERROR, "What ? lwgeom_getsubgeometry_inspected returned NULL??");
-               }
+               ptr = lwgeom_summary_recursive(subgeom, j);
+               size += strlen(ptr);
+               result = repalloc(result,size);
+               strcat(result, ptr);
+               pfree(ptr);
        }
 
        pfree_inspected(inspected);
@@ -1894,7 +1867,7 @@ dump_lwexploded(LWGEOM_EXPLODED *exploded)
 // collect( geom, geom ) returns a geometry which contains
 // all the sub_objects from both of the argument geometries
 // returned geometry is the simplest possible, based on the types
-// of the colelct objects
+// of the collected objects
 // ie. if all are of either X or multiX, then a multiX is returned.
 PG_FUNCTION_INFO_V1(LWGEOM_collect);
 Datum LWGEOM_collect(PG_FUNCTION_ARGS)
@@ -2248,8 +2221,14 @@ Datum LWGEOM_expand(PG_FUNCTION_ARGS)
        LWGEOM *result;
        char *ser;
 
-       // get geometry box and SRID
-       getbox2d_p(SERIALIZED_FORM(geom), &box);
+       // get geometry box 
+       if ( ! getbox2d_p(SERIALIZED_FORM(geom), &box) )
+       {
+               // must be an EMPTY geometry
+               PG_RETURN_POINTER(geom);
+       }
+
+       // get geometry SRID
        SRID = lwgeom_getsrid(SERIALIZED_FORM(geom));
 
        // expand it
@@ -2288,7 +2267,10 @@ Datum LWGEOM_to_BOX(PG_FUNCTION_ARGS)
        BOX2DFLOAT4 box2d;
        BOX *result = (BOX *)palloc(sizeof(BOX));
 
-       getbox2d_p(SERIALIZED_FORM(lwgeom), &box2d);
+       if ( ! getbox2d_p(SERIALIZED_FORM(lwgeom), &box2d) )
+       {
+               PG_RETURN_NULL(); // must be the empty geometry
+       }
        box2df_to_box_p(&box2d, result);
 
        PG_RETURN_POINTER(result);
@@ -2309,8 +2291,14 @@ Datum LWGEOM_envelope(PG_FUNCTION_ARGS)
        LWGEOM *result;
        char *ser;
 
-       // get geometry box and SRID
-       getbox2d_p(SERIALIZED_FORM(geom), &box);
+       // get bounding box 
+       if ( ! getbox2d_p(SERIALIZED_FORM(geom), &box) )
+       {
+               // must be the EMPTY geometry
+               PG_RETURN_POINTER(geom);
+       }
+
+       // get geometry SRID
        SRID = lwgeom_getsrid(SERIALIZED_FORM(geom));
 
        // Assign coordinates to POINT2D array
index 053fe2fabda50140fedf1b4c1dadbfdf6e1f4dd8..a86a35a433ddc72b5edbd0770df89d9176b205c7 100644 (file)
@@ -131,54 +131,53 @@ Datum LWGEOM_out(PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1(LWGEOMFromWKB);
 Datum LWGEOMFromWKB(PG_FUNCTION_ARGS)
 {
-               WellKnownBinary   *wkb_input = (WellKnownBinary *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-               char   *wkb_srid_hexized;
-               int    size_result,size_header;
-               int    SRID = -1;
-               char    sridText[100];
-               char    *loc;
-               char    *lwgeom;
-               int t;
-
-
-                               if (  ( PG_NARGS()>1) && ( ! PG_ARGISNULL(1) ))
-                                       SRID = PG_GETARG_INT32(1);
-                               else
-                                       SRID = -1;
+       WellKnownBinary *wkb_input;
+       char   *wkb_srid_hexized;
+       int    size_result,size_header;
+       int    SRID = -1;
+       char    sridText[100];
+       char    *loc;
+       char    *lwgeom;
+       int t;
+
+       wkb_input = (WellKnownBinary *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+
+       if (  ( PG_NARGS()>1) && ( ! PG_ARGISNULL(1) ))
+               SRID = PG_GETARG_INT32(1);
+       else
+               SRID = -1;
 
  //       elog(NOTICE,"LWGEOMFromWKB: entry with SRID=%i",SRID);
        elog(NOTICE,"wkb => lwgeom CONVERSION");
 
 
-                       // convert WKB to hexized WKB string
-
-
-
+       // convert WKB to hexized WKB string
 
-           size_header = sprintf(sridText,"SRID=%i;",SRID);
-           size_result = size_header +  2*(wkb_input->size -4) + 1;  //SRID text size + wkb size (+1 = NULL term)
+       size_header = sprintf(sridText,"SRID=%i;",SRID);
+       //SRID text size + wkb size (+1 = NULL term)
+       size_result = size_header +  2*(wkb_input->size -4) + 1; 
 
-           wkb_srid_hexized = palloc(size_result);
-           wkb_srid_hexized[0] = 0; // empty
-           strcpy(wkb_srid_hexized, sridText);
-           loc = wkb_srid_hexized + size_header; // points to null in "SRID=#;"
+       wkb_srid_hexized = palloc(size_result);
+       wkb_srid_hexized[0] = 0; // empty
+       strcpy(wkb_srid_hexized, sridText);
+       loc = wkb_srid_hexized + size_header; // points to null in "SRID=#;"
 
-           for (t=0; t< (wkb_input->size -4); t++)
-               {
-                               deparse_hex( ((unsigned char *) wkb_input)[4 + t], &loc[t*2]);
-               }
+       for (t=0; t< (wkb_input->size -4); t++)
+       {
+               deparse_hex( ((unsigned char *) wkb_input)[4 + t], &loc[t*2]);
+       }
 
-           wkb_srid_hexized[size_result-1] = 0; // null term
+       wkb_srid_hexized[size_result-1] = 0; // null term
 
 //elog(NOTICE,"size_header = %i",size_header);
 //elog(NOTICE,"size_result = %i", size_result);
 //elog(NOTICE,"LWGEOMFromWKB :: '%s'", wkb_srid_hexized);
 
-               lwgeom =  parse_lwgeom_wkt(wkb_srid_hexized);
+       lwgeom =  parse_lwgeom_wkt(wkb_srid_hexized);
 
-               pfree(wkb_srid_hexized);
+       pfree(wkb_srid_hexized);
 
-               PG_RETURN_POINTER(lwgeom);
+       PG_RETURN_POINTER(lwgeom);
 }
 
 // WKBFromLWGEOM(lwgeom) --> wkb
@@ -189,7 +188,7 @@ Datum WKBFromLWGEOM(PG_FUNCTION_ARGS)
        char *lwgeom_input = (char *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
 
        // SRID=#;<hexized wkb>
-       char *hexized_wkb_srid = unparse_WKB(lwgeom_input,palloc_fn,free_fn);
+       char *hexized_wkb_srid = unparse_WKB(lwgeom_input, palloc_fn, free_fn);
 
        char *hexized_wkb; // hexized_wkb_srid w/o srid
        char *result; //wkb
@@ -197,41 +196,40 @@ Datum WKBFromLWGEOM(PG_FUNCTION_ARGS)
        int len_hexized_wkb;
        int                     size_result;
        char            *semicolonLoc;
-               int t;
+       int t;
 
 //elog(NOTICE, "in WKBFromLWGEOM with WKB = '%s'", hexized_wkb_srid);
        elog(NOTICE,"lwgeom => wkb CONVERSION");
 
-               hexized_wkb = hexized_wkb_srid;
-               semicolonLoc = strchr(hexized_wkb_srid,';');
+       hexized_wkb = hexized_wkb_srid;
+       semicolonLoc = strchr(hexized_wkb_srid,';');
 
 
-                               if (semicolonLoc != NULL)
-                               {
-                                       hexized_wkb = (semicolonLoc+1);
-                               }
+       if (semicolonLoc != NULL)
+       {
+               hexized_wkb = (semicolonLoc+1);
+       }
 
 //elog(NOTICE, "in WKBFromLWGEOM with WKB (with no 'SRID=#;' = '%s'", hexized_wkb);
 
+       len_hexized_wkb = strlen(hexized_wkb);
+       size_result = len_hexized_wkb/2 + 4;
+       result = palloc(size_result);
 
-               len_hexized_wkb = strlen(hexized_wkb);
-               size_result = len_hexized_wkb/2 + 4;
-               result = palloc(size_result);
-
-               memcpy(result, &size_result,4); // size header
+       memcpy(result, &size_result,4); // size header
 
 
 
-                       // have a hexized string, want to make it binary
+       // have a hexized string, want to make it binary
 
-               for (t=0; t< (len_hexized_wkb/2); t++)
-               {
-                       ((unsigned char *) result +4)[t] =      parse_hex(  hexized_wkb + (t*2) );
-               }
+       for (t=0; t< (len_hexized_wkb/2); t++)
+       {
+               ((unsigned char *) result +4)[t] = parse_hex(  hexized_wkb + (t*2) );
+       }
 
-               pfree(hexized_wkb_srid);
+       pfree(hexized_wkb_srid);
 
-               PG_RETURN_POINTER(result);
+       PG_RETURN_POINTER(result);
 }
 
 
@@ -588,9 +586,3 @@ char *parse_lwgeom_wkt(char *wkt_input)
        //return result;
 }
 
-
-
-
-
-
-
index 7d80bae14f1fb67755a2d3c19ec5a5b6fbb8f957..7047dbb03bde50f560d64135bb649ed68f4f56a8 100644 (file)
@@ -108,11 +108,6 @@ CREATE TYPE geometry (
 );
 
         
-CREATEFUNCTION geometry(text)
-        RETURNS geometry
-        AS '@MODULE_FILENAME@','parse_WKT_lwgeom'
-        LANGUAGE 'C' WITH (isstrict,iscachable);
-
 -------------------------------------------------------------------
 --  BOX3D TYPE
 -------------------------------------------------------------------
@@ -2420,6 +2415,22 @@ CREATEFUNCTION geometry(box3d)
 
 CREATE CAST (box3d as geometry) WITH FUNCTION geometry(box3d) AS IMPLICIT ;
 
+CREATEFUNCTION geometry(text)
+        RETURNS geometry
+        AS '@MODULE_FILENAME@','parse_WKT_lwgeom'
+        LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE CAST ( text AS geometry) WITH FUNCTION geometry(text) AS IMPLICIT;
+
+---------------------------------------------------------------
+-- Algorithms
+---------------------------------------------------------------
+
+CREATEFUNCTION simplify(geometry, float8)
+   RETURNS geometry
+   AS '@MODULE_FILENAME@', 'LWGEOM_simplify2d'
+   LANGUAGE 'C' WITH (isstrict);
+
 ---------------------------------------------------------------
 -- END
 ---------------------------------------------------------------