From: Sandro Santilli Date: Mon, 6 Sep 2004 09:13:13 +0000 (+0000) Subject: Added box3d support and expand(geom|box2d|box3d, double) X-Git-Tag: pgis_0_9_1~27 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c50db67ca8c3a04c2eef9f4683c707ca9c532aaa;p=postgis Added box3d support and expand(geom|box2d|box3d, double) git-svn-id: http://svn.osgeo.org/postgis/trunk@767 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/lwgeom/MISSING_OBJECTS b/lwgeom/MISSING_OBJECTS index 91a6dd227..27da89305 100644 --- a/lwgeom/MISSING_OBJECTS +++ b/lwgeom/MISSING_OBJECTS @@ -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)] diff --git a/lwgeom/Makefile b/lwgeom/Makefile index 99fc69379..038b088c4 100644 --- a/lwgeom/Makefile +++ b/lwgeom/Makefile @@ -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 diff --git a/lwgeom/lwgeom.h b/lwgeom/lwgeom.h index 0fd449474..ad3704ac2 100644 --- a/lwgeom/lwgeom.h +++ b/lwgeom/lwgeom.h @@ -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__) diff --git a/lwgeom/lwgeom_api.c b/lwgeom/lwgeom_api.c index 7847aa66c..85a26497a 100644 --- a/lwgeom/lwgeom_api.c +++ b/lwgeom/lwgeom_api.c @@ -21,10 +21,6 @@ //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;tnrings;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;tnrings;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;tnrings;t++) + for (t=0;tnrings;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;undims == 2) + } + else if (poly->ndims == 2) + { + for (u=0;undims == 4) + } + else if (poly->ndims == 4) + { + for (u=0;uxmin,&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 index 000000000..b1fe34c1f --- /dev/null +++ b/lwgeom/lwgeom_box3d.c @@ -0,0 +1,175 @@ +/********************************************************************** + * + * BOX3D IO and conversions + * + **********************************************************************/ + +#include "postgres.h" + +#include +#include +#include +#include +#include + +#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); +} diff --git a/lwgeom/lwgeom_functions_basic.c b/lwgeom/lwgeom_functions_basic.c index a0e04a88d..9193475f4 100644 --- a/lwgeom/lwgeom_functions_basic.c +++ b/lwgeom/lwgeom_functions_basic.c @@ -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); +} diff --git a/lwgeom/lwpostgis.sql.in b/lwgeom/lwpostgis.sql.in index 8e49f7b57..98925eb8b 100644 --- a/lwgeom/lwpostgis.sql.in +++ b/lwgeom/lwpostgis.sql.in @@ -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 ---------------------------------------------------------------