]> granicus.if.org Git - postgis/commitdiff
Added box3d support and expand(geom|box2d|box3d, double)
authorSandro Santilli <strk@keybit.net>
Mon, 6 Sep 2004 09:13:13 +0000 (09:13 +0000)
committerSandro Santilli <strk@keybit.net>
Mon, 6 Sep 2004 09:13:13 +0000 (09:13 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@767 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/MISSING_OBJECTS
lwgeom/Makefile
lwgeom/lwgeom.h
lwgeom/lwgeom_api.c
lwgeom/lwgeom_box2dfloat4.c
lwgeom/lwgeom_box3d.c [new file with mode: 0644]
lwgeom/lwgeom_functions_basic.c
lwgeom/lwpostgis.sql.in

index 91a6dd227ad345a955347aae53ea87401725ae6b..27da89305c7c6d4b1ca74f744805c4649e1601b0 100644 (file)
@@ -10,7 +10,10 @@ FUNC: KEEPING FUNCTION: [box(geometry)]
 
 FUNC: KEEPING FUNCTION: [envelope(geometry)]
 FUNC: KEEPING FUNCTION: [equals(geometry, geometry)]
+
 FUNC: KEEPING FUNCTION: [expand(geometry, double precision)]
+FUNC: KEEPING FUNCTION: [expand(box3d, double precision)]
+
 FUNC: KEEPING FUNCTION: [isempty(geometry)]
 FUNC: KEEPING FUNCTION: [segmentize(geometry, double precision)]
 FUNC: KEEPING FUNCTION: [unite_garray(geometry[])]
@@ -61,9 +64,6 @@ FUNC: KEEPING FUNCTION: [compression(chip)]
 FNCAST: KEEPING FNCAST geometry(chip) (see CAST)
 
 --- BOX3D
-FUNC: KEEPING FUNCTION: [box3d_in(cstring)]
-FUNC: KEEPING FUNCTION: [box3d_out(box3d)]
-TYPE: KEEPING TYPE [box3d]
 FUNC: KEEPING FUNCTION: [xmax(box3d)]
 FUNC: KEEPING FUNCTION: [xmin(box3d)]
 FUNC: KEEPING FUNCTION: [ymax(box3d)]
@@ -75,5 +75,4 @@ FNCAST: KEEPING FNCAST geometry(box3d) (see CAST)
 FUNC: KEEPING FUNCTION: [box3d(geometry)]
 FUNC: KEEPING FUNCTION: [box3dtobox(box3d)]
 FUNC: KEEPING FUNCTION: [combine_bbox(box3d, geometry)]
-FUNC: KEEPING FUNCTION: [expand(box3d, double precision)]
 FUNC: KEEPING FUNCTION: [geometry(box3d)]
index 99fc69379dbfa15bce73ffe848621170d2df93ce..038b088c45c257e2674dba859ba2ba338cbf5010 100644 (file)
@@ -132,7 +132,7 @@ ifeq ($(USE_STATS),1)
        override CFLAGS += -DUSE_STATS
 endif
  
-OBJS=lwgeom_pg.o lwgeom_spheroid.o lwgeom_api.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_geos.o lwgeom_inout.o lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o lwgeom_transform.o stringBuffer.o lwgeom_box2dfloat4.o lex.yy.o wktparse.tab.o lwgparse.o wktunparse.o $(GEOS_WRAPPER)
+OBJS=lwgeom_pg.o lwgeom_spheroid.o lwgeom_api.o lwgeom_ogc.o lwgeom_functions_analytic.o lwgeom_geos.o lwgeom_inout.o lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o lwgeom_transform.o stringBuffer.o lwgeom_box3d.o lwgeom_box2dfloat4.o lex.yy.o wktparse.tab.o lwgparse.o wktunparse.o $(GEOS_WRAPPER)
 
 OTHERS=y.output lex.yy.c wktparse.tab.c wktparse.tab.h lwgeom.sql lwpostgis.sql
 
index 0fd449474946257a3ea668b60fa913b9aea7acd9..ad3704ac27b6250b5696466c230549ad13f35e5a 100644 (file)
@@ -493,6 +493,8 @@ extern BOX2DFLOAT4 *box3d_to_box2df(BOX3D *box);
 extern BOX2DFLOAT4 *box_to_box2df(BOX *box);  // postgresql standard type
 
 extern BOX3D box2df_to_box3d(BOX2DFLOAT4 *box);
+extern void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *box3d);
+
 extern BOX   box2df_to_box(BOX2DFLOAT4 *box);  // postgresql standard type
 extern BOX3D *combine_boxes(BOX3D *b1, BOX3D *b2);
 
@@ -503,6 +505,10 @@ extern BOX3D *combine_boxes(BOX3D *b1, BOX3D *b2);
 extern BOX2DFLOAT4 getbox2d(char *serialized_form);
 extern void getbox2d_p(char *serialized_form, BOX2DFLOAT4 *box);
 
+// Expand given box of 'd' units in all directions 
+void expand_box2d(BOX2DFLOAT4 *box, double d);
+void expand_box3d(BOX3D *box, double d);
+
 //****************************************************************
 // memory management -- these only delete the memory associated
 //  directly with the structure - NOT the stuff pointing into
@@ -664,7 +670,6 @@ Datum box2d_contain(PG_FUNCTION_ARGS);
 Datum box2d_inter(PG_FUNCTION_ARGS);
 Datum box2d_union(PG_FUNCTION_ARGS);
 
-
 Datum gist_lwgeom_compress(PG_FUNCTION_ARGS);
 Datum gist_lwgeom_consistent(PG_FUNCTION_ARGS);
 Datum gist_rtree_decompress(PG_FUNCTION_ARGS);
@@ -681,6 +686,11 @@ extern float LWGEOM_Maxf(float a, float b);
 
 extern BOX3D *lw_geom_getBB_simple(char *serialized_form);
 
+extern float  nextDown_f(double d);
+extern float  nextUp_f(double d);
+extern double nextDown_d(float d);
+extern double nextUp_d(float d);
+
 
 
 #if ! defined(__MINGW32__)
index 7847aa66c630847fa6ea46df63d8d3fa8ec1af39..85a26497a2ae194ad0ce2096e5a525d7ad35a9cd 100644 (file)
 
 //forward decs
 
-extern float  nextDown_f(double d);
-extern float  nextUp_f(double d);
-extern double nextDown_d(float d);
-extern double nextUp_d(float d);
 
 
 extern  BOX3D *lw_geom_getBB_simple(char *serialized_form);
@@ -217,6 +213,7 @@ BOX2DFLOAT4 *box_to_box2df(BOX *box)
 }
 
 // convert BOX2D to BOX3D
+// zmin and zmax are set to 0.0
 BOX3D box2df_to_box3d(BOX2DFLOAT4 *box)
 {
        BOX3D result;
@@ -224,15 +221,32 @@ BOX3D box2df_to_box3d(BOX2DFLOAT4 *box)
        if (box == NULL)
                return result;
 
-       result.xmin = nextDown_d(box->xmin);
-       result.ymin = nextDown_d(box->ymin);
+       result.xmin = box->xmin;
+       result.ymin = box->ymin;
 
-       result.xmax = nextUp_d(box->xmax);
-       result.ymax = nextUp_d(box->ymax);
+       result.xmax = box->xmax;
+       result.ymax = box->ymax;
+
+       result.zmin = result.zmax = 0.0;
 
        return result;
 }
 
+// convert BOX2D to BOX3D, using pre-allocated BOX3D as output
+// Z values are set to 0.0.
+void box2df_to_box3d_p(BOX2DFLOAT4 *box, BOX3D *out)
+{
+       if (box == NULL) return;
+
+       out->xmin = box->xmin;
+       out->ymin = box->ymin;
+
+       out->xmax = box->xmax;
+       out->ymax = box->ymax;
+
+       out->zmin = out->zmax = 0.0;
+}
+
 
 // convert BOX2D to postgresql BOX
 BOX   box2df_to_box(BOX2DFLOAT4 *box)
@@ -1259,7 +1273,7 @@ elog(NOTICE, "lwpoint_findlength: returning (%d)", result+32);
 //********************************************************************
 // basic polygon manipulation
 
-// construct a new LWLINE.  arrays (points/points per ring) will NOT be copied
+// construct a new LWPOLY.  arrays (points/points per ring) will NOT be copied
 // use SRID=-1 for unknown SRID (will have 8bit type's S = 0)
 LWPOLY *lwpoly_construct(int ndims, int SRID, int nrings,POINTARRAY **points)
 {
@@ -1357,83 +1371,83 @@ LWPOLY *lwpoly_deserialize(char *serialized_form)
 // points copied
 char *lwpoly_serialize(LWPOLY *poly)
 {
-               int size=1;  // type byte
-               char hasSRID;
-               char *result;
-               int t,u;
-               int total_points = 0;
-               int npoints;
-               char *loc;
+       int size=1;  // type byte
+       char hasSRID;
+       char *result;
+       int t,u;
+       int total_points = 0;
+       int npoints;
+       char *loc;
 
-               hasSRID = (poly->SRID != -1);
+       hasSRID = (poly->SRID != -1);
 
-               if (hasSRID)
-                       size +=4;  //4 byte SRID
+       if (hasSRID)
+               size +=4;  //4 byte SRID
 
-               size += 4; // nrings
-               size += 4*poly->nrings; //npoints/ring
+       size += 4; // nrings
+       size += 4*poly->nrings; //npoints/ring
 
 
-               for (t=0;t<poly->nrings;t++)
-               {
-                       total_points  += poly->rings[t]->npoints;
-               }
-               if (poly->ndims == 3)
-                       size += 24*total_points;
-               else if (poly->ndims == 2)
-                       size += 16*total_points;
-               else if (poly->ndims == 4)
-                       size += 32*total_points;
+       for (t=0;t<poly->nrings;t++)
+       {
+               total_points  += poly->rings[t]->npoints;
+       }
+       if (poly->ndims == 3)
+               size += 24*total_points;
+       else if (poly->ndims == 2)
+               size += 16*total_points;
+       else if (poly->ndims == 4)
+               size += 32*total_points;
 
-               result = palloc(size);
+       result = palloc(size);
 
-               result[0] = (unsigned char) lwgeom_makeType(poly->ndims,hasSRID, POLYGONTYPE);
-               loc = result+1;
+       result[0] = (unsigned char) lwgeom_makeType(poly->ndims,hasSRID, POLYGONTYPE);
+       loc = result+1;
 
-               if (hasSRID)
-               {
-                       memcpy(loc, &poly->SRID, sizeof(int32));
-                       loc += 4;
-               }
+       if (hasSRID)
+       {
+               memcpy(loc, &poly->SRID, sizeof(int32));
+               loc += 4;
+       }
 
-               memcpy(loc, &poly->nrings, sizeof(int32));  // nrings
-               loc+=4;
+       memcpy(loc, &poly->nrings, sizeof(int32));  // nrings
+       loc+=4;
 
 
 
-               for (t=0;t<poly->nrings;t++)
+       for (t=0;t<poly->nrings;t++)
+       {
+               POINTARRAY *pa = poly->rings[t];
+               npoints = poly->rings[t]->npoints;
+               memcpy(loc, &npoints, sizeof(int32)); //npoints this ring
+               loc+=4;
+               if (poly->ndims == 3)
                {
-                       POINTARRAY *pa = poly->rings[t];
-                       npoints = poly->rings[t]->npoints;
-                       memcpy(loc, &npoints, sizeof(int32)); //npoints this ring
-                       loc+=4;
-                       if (poly->ndims == 3)
+                       for (u=0;u<npoints;u++)
                        {
-                               for (u=0;u<npoints;u++)
-                               {
-                                       getPoint3d_p(pa, u, loc);
-                                       loc+= 24;
-                               }
+                               getPoint3d_p(pa, u, loc);
+                               loc+= 24;
                        }
-                       else if (poly->ndims == 2)
+               }
+               else if (poly->ndims == 2)
+               {
+                       for (u=0;u<npoints;u++)
                        {
-                               for (u=0;u<npoints;u++)
-                               {
-                                       getPoint2d_p(pa, u, loc);
-                                       loc+= 16;
-                               }
+                               getPoint2d_p(pa, u, loc);
+                               loc+= 16;
                        }
-                       else if (poly->ndims == 4)
+               }
+               else if (poly->ndims == 4)
+               {
+                       for (u=0;u<npoints;u++)
                        {
-                               for (u=0;u<npoints;u++)
-                               {
-                                       getPoint4d_p(pa, u, loc);
-                                       loc+= 32;
-                               }
+                               getPoint4d_p(pa, u, loc);
+                               loc+= 32;
                        }
                }
+       }
 
-               return result;
+       return result;
 }
 
 // create the serialized form of the polygon writing it into the
index e56ce1ece658ef4469bd1853dae5432cca2f08fe..03947e50dd5c4ea394933a74b36136f6b807cbb3 100644 (file)
 // basic implementation of BOX2D
 
 
-               //forward defs
+//forward defs
 Datum BOX2DFLOAT4_in(PG_FUNCTION_ARGS);
 Datum BOX2DFLOAT4_out(PG_FUNCTION_ARGS);
 Datum LWGEOM_to_BOX2DFLOAT4(PG_FUNCTION_ARGS);
+Datum BOX2DFLOAT4_expand(PG_FUNCTION_ARGS);
+Datum BOX2DFLOAT4_to_BOX3D(PG_FUNCTION_ARGS);
 
 
 
@@ -34,41 +36,41 @@ Datum LWGEOM_to_BOX2DFLOAT4(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(BOX2DFLOAT4_in);
 Datum BOX2DFLOAT4_in(PG_FUNCTION_ARGS)
 {
-           char                    *str = PG_GETARG_CSTRING(0);
-               int nitems;
-           BOX2DFLOAT4      *box = (BOX2DFLOAT4 *) palloc(sizeof(BOX2DFLOAT4));
+       char *str = PG_GETARG_CSTRING(0);
+       int nitems;
+       BOX2DFLOAT4 *box = (BOX2DFLOAT4 *) palloc(sizeof(BOX2DFLOAT4));
 
 
 
 //printf( "box3d_in gets '%s'\n",str);
 
-               if (strstr(str,"BOX(") !=  str )
-               {
-                                pfree(box);
-                                elog(ERROR,"BOX2DFLOAT4 parser - doesnt start with BOX(");
-                                PG_RETURN_NULL();
-               }
-               nitems = sscanf(str,"BOX(%f %f,%f %f)", &box->xmin,&box->ymin,&box->xmax,&box->ymax);
-               if (nitems != 4)
-               {
-                        pfree(box);
-                        elog(ERROR,"BOX2DFLOAT4 parser - couldnt parse.  It should look like: BOX(xmin ymin,xmax ymax)");
-                        PG_RETURN_NULL();
-               }
-
-               if (box->xmin > box->xmax)
-               {
-                       float tmp = box->xmin;
-                       box->xmin = box->xmax;
-                       box->xmax = tmp;
-               }
-               if (box->ymin > box->ymax)
-               {
-                               float tmp = box->ymin;
-                               box->ymin = box->ymax;
-                               box->ymax = tmp;
-               }
-               PG_RETURN_POINTER(box);
+       if (strstr(str,"BOX(") !=  str )
+       {
+                pfree(box);
+                elog(ERROR,"BOX2DFLOAT4 parser - doesnt start with BOX(");
+                PG_RETURN_NULL();
+       }
+       nitems = sscanf(str,"BOX(%f %f,%f %f)", &box->xmin,&box->ymin,&box->xmax,&box->ymax);
+       if (nitems != 4)
+       {
+                pfree(box);
+                elog(ERROR,"BOX2DFLOAT4 parser - couldnt parse.  It should look like: BOX(xmin ymin,xmax ymax)");
+                PG_RETURN_NULL();
+       }
+
+       if (box->xmin > box->xmax)
+       {
+               float tmp = box->xmin;
+               box->xmin = box->xmax;
+               box->xmax = tmp;
+       }
+       if (box->ymin > box->ymax)
+       {
+               float tmp = box->ymin;
+               box->ymin = box->ymax;
+               box->ymax = tmp;
+       }
+       PG_RETURN_POINTER(box);
 }
 
 //writer  "BOX(xmin ymin,xmax ymax)"
@@ -290,5 +292,37 @@ float LWGEOM_Maxf(float a, float b)
 }
 
 
+/* Expand given box of 'd' units in all directions */
+void
+expand_box2d(BOX2DFLOAT4 *box, double d)
+{
+       box->xmin -= d;
+       box->ymin -= d;
+
+       box->xmax += d;
+       box->ymax += d;
+}
 
+PG_FUNCTION_INFO_V1(BOX2DFLOAT4_expand);
+Datum BOX2DFLOAT4_expand(PG_FUNCTION_ARGS)
+{
+       BOX2DFLOAT4 *box = (BOX2DFLOAT4 *)PG_GETARG_POINTER(0);
+       double d = PG_GETARG_FLOAT8(1);
+       BOX2DFLOAT4 *result = (BOX2DFLOAT4 *)palloc(sizeof(BOX2DFLOAT4));
 
+       memcpy(result, box, sizeof(BOX2DFLOAT4));
+       expand_box2d(result, d);
+
+       PG_RETURN_POINTER(result);
+}
+
+PG_FUNCTION_INFO_V1(BOX2DFLOAT4_to_BOX3D);
+Datum BOX2DFLOAT4_to_BOX3D(PG_FUNCTION_ARGS)
+{
+       BOX2DFLOAT4 *box = (BOX2DFLOAT4 *)PG_GETARG_POINTER(0);
+       BOX3D *result = palloc(sizeof(BOX3D));
+
+       box2df_to_box3d_p(box, result);
+
+       PG_RETURN_POINTER(result);
+}
diff --git a/lwgeom/lwgeom_box3d.c b/lwgeom/lwgeom_box3d.c
new file mode 100644 (file)
index 0000000..b1fe34c
--- /dev/null
@@ -0,0 +1,175 @@
+/**********************************************************************
+ *
+ * BOX3D IO and conversions
+ *
+ **********************************************************************/
+
+#include "postgres.h"
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "fmgr.h"
+#include "utils/elog.h"
+
+#include "lwgeom.h"
+
+
+//#define DEBUG
+// basic implementation of BOX2D
+
+#define SHOW_DIGS_DOUBLE 15
+#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
+
+//forward defs
+Datum BOX3D_in(PG_FUNCTION_ARGS);
+Datum BOX3D_out(PG_FUNCTION_ARGS);
+Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS);
+Datum BOX3D_expand(PG_FUNCTION_ARGS);
+Datum BOX3D_to_BOX2DFLOAT4(PG_FUNCTION_ARGS);
+
+/*
+ *  BOX3D_in - takes a string rep of BOX3D and returns internal rep
+ *
+ *  example:
+ *     "BOX3D(x1 y1 z1,x2 y2 z2)"
+ * or  "BOX3D(x1 y1,x2 y2)"   z1 and z2 = 0.0
+ *
+ *
+ */
+
+PG_FUNCTION_INFO_V1(BOX3D_in);
+Datum BOX3D_in(PG_FUNCTION_ARGS)
+{
+       char *str = PG_GETARG_CSTRING(0);
+       int nitems;
+       BOX3D *box = (BOX3D *) palloc(sizeof(BOX3D));
+       box->zmin = 0;
+       box->zmax = 0;
+
+
+//printf( "box3d_in gets '%s'\n",str);
+
+       if (strstr(str,"BOX3D(") !=  str )
+       {
+                pfree(box);
+                elog(ERROR,"BOX3D parser - doesnt start with BOX3D(");
+                PG_RETURN_NULL();
+       }
+
+       nitems = sscanf(str,"BOX3D(%le %le %le,%le %le %le)",
+               &box->xmin, &box->ymin, &box->zmin,
+               &box->xmax, &box->ymax, &box->zmax);
+       if (nitems != 6 )
+       {
+               nitems = sscanf(str,"BOX3D(%le %le,%le %le)",
+                       &box->xmin, &box->ymin, &box->xmax, &box->ymax);
+               if (nitems != 4)
+               {
+                        pfree(box);
+                        elog(ERROR,"BOX3D parser - couldnt parse.  It should look like: BOX3D(xmin ymin zmin,xmax ymax zmax) or BOX3D(xmin ymin,xmax ymax)");
+                        PG_RETURN_NULL();
+               }
+       }
+
+       if (box->xmin > box->xmax)
+       {
+               float tmp = box->xmin;
+               box->xmin = box->xmax;
+               box->xmax = tmp;
+       }
+       if (box->ymin > box->ymax)
+       {
+               float tmp = box->ymin;
+               box->ymin = box->ymax;
+               box->ymax = tmp;
+       }
+       if (box->zmin > box->zmax)
+       {
+               float tmp = box->zmin;
+               box->zmin = box->zmax;
+               box->zmax = tmp;
+       }
+       PG_RETURN_POINTER(box);
+}
+
+
+/*
+ *  Takes an internal rep of a BOX3D and returns a string rep.
+ *
+ *  example:
+ *     "BOX3D(xmin ymin zmin, xmin ymin zmin)"
+ */
+PG_FUNCTION_INFO_V1(BOX3D_out);
+Datum BOX3D_out(PG_FUNCTION_ARGS)
+{
+       BOX3D  *bbox = (BOX3D *) PG_GETARG_POINTER(0);
+       int size;
+       char *result;
+
+       if (bbox == NULL)
+       {
+               result = palloc(5);
+               strcat(result,"NULL");
+               PG_RETURN_CSTRING(result);
+       }
+
+       size = MAX_DIGS_DOUBLE*6+5+2+4+5+1;
+       result = (char *) palloc(size); //double digits+ "BOX3D"+ "()" + commas +null
+       sprintf(result, "BOX3D(%.15g %.15g %.15g,%.15g %.15g %.15g)",
+                       bbox->xmin, bbox->ymin, bbox->zmin,
+                       bbox->xmax,bbox->ymax,bbox->zmax);
+
+       PG_RETURN_CSTRING(result);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_to_BOX2DFLOAT4);
+Datum BOX3D_to_BOX2DFLOAT4(PG_FUNCTION_ARGS)
+{
+       BOX3D *in = (BOX3D *)PG_GETARG_POINTER(0);
+       BOX2DFLOAT4 *out = box3d_to_box2df(in);
+       PG_RETURN_POINTER(out);
+}
+
+/* Expand given box of 'd' units in all directions */
+void
+expand_box3d(BOX3D *box, double d)
+{
+       box->xmin -= d;
+       box->ymin -= d;
+       box->zmin -= d;
+
+       box->xmax += d;
+       box->ymax += d;
+       box->zmax += d;
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_expand);
+Datum BOX3D_expand(PG_FUNCTION_ARGS)
+{
+       BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
+       double d = PG_GETARG_FLOAT8(1);
+       BOX3D *result = (BOX3D *)palloc(sizeof(BOX3D));
+
+       memcpy(result, box, sizeof(BOX3D));
+       expand_box3d(result, d);
+
+       PG_RETURN_POINTER(result);
+}
+
+//convert a LWGEOM to BOX3D
+PG_FUNCTION_INFO_V1(LWGEOM_to_BOX3D);
+Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS)
+{
+       LWGEOM *lwgeom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       BOX2DFLOAT4 box;
+       BOX3D *result = palloc(sizeof(BOX3D));
+
+       getbox2d_p(SERIALIZED_FORM(lwgeom), &box);
+       box2df_to_box3d_p(&box, result);
+
+       PG_RETURN_POINTER(result);
+}
index a0e04a88d158a1c0499a6c314d5ae1aa8226efba..9193475f4db0c9e0955a84e1d7dd450ec069fe1c 100644 (file)
@@ -38,6 +38,7 @@ Datum LWGEOM_inside_circle_point(PG_FUNCTION_ARGS);
 Datum LWGEOM_collect(PG_FUNCTION_ARGS);
 Datum LWGEOM_accum(PG_FUNCTION_ARGS);
 Datum LWGEOM_collect_garray(PG_FUNCTION_ARGS);
+Datum LWGEOM_expand(PG_FUNCTION_ARGS);
 
 // internal
 char * lwgeom_summary_recursive(char *serialized, int offset);
@@ -2276,3 +2277,51 @@ Datum LWGEOM_collect_garray(PG_FUNCTION_ARGS)
 
        PG_RETURN_POINTER( result );
 }
+
+// makes a polygon of the expanded features bvol - 1st point = LL 3rd=UR
+// 2d only. (3d might be worth adding).
+// create new geometry of type polygon, 1 ring, 5 points
+PG_FUNCTION_INFO_V1(LWGEOM_expand);
+Datum LWGEOM_expand(PG_FUNCTION_ARGS)
+{
+       LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       double d = PG_GETARG_FLOAT8(1);
+       BOX2DFLOAT4 box;
+       POINT2D *pts = palloc(sizeof(POINT2D)*5);
+       POINTARRAY *pa[1];
+       LWPOLY *poly;
+       int SRID;
+       LWGEOM *result;
+       char *ser;
+
+       // get geometry box and SRID
+       getbox2d_p(SERIALIZED_FORM(geom), &box);
+       SRID = lwgeom_getsrid(SERIALIZED_FORM(geom));
+
+       // expand it
+       expand_box2d(&box, d);
+
+       // Assign coordinates to POINT2D array
+       pts[0].x = box.xmin; pts[0].y = box.ymin;
+       pts[1].x = box.xmin; pts[1].y = box.ymax;
+       pts[2].x = box.xmax; pts[2].y = box.ymax;
+       pts[3].x = box.xmax; pts[3].y = box.ymin;
+       pts[4].x = box.xmin; pts[4].y = box.ymin;
+
+       // Construct point array
+       pa[0] = palloc(sizeof(POINTARRAY));
+       pa[0]->serialized_pointlist = (char *)pts;
+       pa[0]->ndims = 2;
+       pa[0]->npoints = 5;
+
+       // Construct polygon
+       poly = lwpoly_construct(2, SRID, 1, pa);
+
+       // Serialize polygon
+       ser = lwpoly_serialize(poly);
+
+       // Construct LWGEOM 
+       result = LWGEOM_construct(ser, SRID, lwgeom_hasBBOX(geom->type));
+       
+       PG_RETURN_POINTER(result);
+}
index 8e49f7b57dbca5091e8f64141d3f8252e247da58..98925eb8bed120b09671e0f1f60ecf2927b29058 100644 (file)
@@ -107,6 +107,40 @@ CREATE TYPE geometry (
         storage = main
 );
 
+        
+CREATEFUNCTION geometry(text)
+        RETURNS geometry
+        AS '@MODULE_FILENAME@','parse_WKT_lwgeom'
+        LANGUAGE 'C' WITH (isstrict,iscachable);
+
+-------------------------------------------------------------------
+--  BOX3D TYPE
+-------------------------------------------------------------------
+
+#if USE_VERSION < 73
+# define BOX3D_IN_REP opaque
+# define BOX3D_OUT_REP opaque
+#else
+# define BOX3D_IN_REP box3d
+# define BOX3D_OUT_REP cstring
+#endif
+
+CREATEFUNCTION box3d_in(BOX3D_OUT_REP)
+       RETURNS BOX3D_IN_REP
+       AS '@MODULE_FILENAME@', 'BOX3D_in'
+       LANGUAGE 'C' WITH (isstrict);
+
+CREATEFUNCTION box3d_out(BOX3D_IN_REP)
+       RETURNS BOX3D_OUT_REP
+       AS '@MODULE_FILENAME@', 'BOX3D_out'
+       LANGUAGE 'C' WITH (isstrict);
+
+CREATE TYPE box3d (
+       alignment = double,
+       internallength = 48,
+       input = box3d_in,
+       output = box3d_out
+);
 
 -----------------------------------------------------------------------
 --
@@ -131,19 +165,6 @@ CREATE TYPE box2d (
         storage = plain
 );
 
-CREATEFUNCTION box2d(geometry)
-        RETURNS box2d
-        AS '@MODULE_FILENAME@','LWGEOM_to_BOX2DFLOAT4'
-        LANGUAGE 'C' WITH (isstrict,iscachable);
-
-
-
-        
-CREATEFUNCTION geometry(text)
-        RETURNS geometry
-        AS '@MODULE_FILENAME@','parse_WKT_lwgeom'
-        LANGUAGE 'C' WITH (isstrict,iscachable);
-
 ---- BOX2D  support functions
 
 
@@ -1214,6 +1235,21 @@ CREATE AGGREGATE collect (
        finalfunc = collect_garray
        );
 
+CREATEFUNCTION expand(box3d,float8)
+       RETURNS box3d
+       AS '@MODULE_FILENAME@', 'BOX3D_expand'
+       LANGUAGE 'C' WITH (iscachable,isstrict);
+
+CREATEFUNCTION expand(box2d,float8)
+       RETURNS box2d
+       AS '@MODULE_FILENAME@', 'BOX2DFLOAT4_expand'
+       LANGUAGE 'C' WITH (iscachable,isstrict);
+
+CREATEFUNCTION expand(geometry,float8)
+       RETURNS geometry
+       AS '@MODULE_FILENAME@', 'LWGEOM_expand'
+       LANGUAGE 'C' WITH (iscachable,isstrict);
+
 ------------------------------------------------------------------------
 
 --
@@ -2254,6 +2290,38 @@ BEGIN
 END
 ' LANGUAGE 'plpgsql';
 
+---------------------------------------------------------------
+-- CASTS
+---------------------------------------------------------------
+
+CREATEFUNCTION box2d(geometry)
+        RETURNS box2d
+        AS '@MODULE_FILENAME@','LWGEOM_to_BOX2DFLOAT4'
+        LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE CAST (geometry as box2d) WITH FUNCTION box2d(geometry) AS IMPLICIT ;
+
+CREATEFUNCTION box3d(geometry)
+        RETURNS box3d
+        AS '@MODULE_FILENAME@','LWGEOM_to_BOX3D'
+        LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE CAST (geometry as box3d) WITH FUNCTION box3d(geometry) AS IMPLICIT ;
+
+CREATEFUNCTION box2d(box3d)
+        RETURNS box2d
+        AS '@MODULE_FILENAME@','BOX3D_to_BOX2DFLOAT4'
+        LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE CAST (box3d as box2d) WITH FUNCTION box2d(box3d) AS IMPLICIT ;
+
+CREATEFUNCTION box3d(box2d)
+        RETURNS box3d
+        AS '@MODULE_FILENAME@','BOX2DFLOAT4_to_BOX3D'
+        LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE CAST (box2d as box3d) WITH FUNCTION box3d(box2d) AS IMPLICIT ;
+
 ---------------------------------------------------------------
 -- END
 ---------------------------------------------------------------