FUNC: KEEPING FUNCTION: [asbinary(geometry)]
FUNC: KEEPING FUNCTION: [asbinary(geometry, text)]
FUNC: KEEPING FUNCTION: [boundary(geometry)]
-FUNC: KEEPING FUNCTION: [box(geometry)]
-
-FUNC: KEEPING FUNCTION: [envelope(geometry)]
FUNC: KEEPING FUNCTION: [equals(geometry, geometry)]
-
FUNC: KEEPING FUNCTION: [isempty(geometry)]
FUNC: KEEPING FUNCTION: [segmentize(geometry, double precision)]
FUNC: KEEPING FUNCTION: [unite_garray(geometry[])]
FUNC: KEEPING FUNCTION: [compression(chip)]
FNCAST: KEEPING FNCAST geometry(chip) (see CAST)
---- BOX3D
-FNCAST: KEEPING FNCAST box3dtobox(box3d) (see CAST)
-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: [geometry(box3d)]
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 void box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out); // postgresql standard type
-extern BOX box2df_to_box(BOX2DFLOAT4 *box); // postgresql standard type
extern BOX3D *combine_boxes(BOX3D *b1, BOX3D *b2);
extern float LWGEOM_Minf(float a, float b);
extern float LWGEOM_Maxf(float a, float b);
+extern double LWGEOM_Mind(double a, double b);
+extern double LWGEOM_Maxd(double a, double b);
return result;
}
+// convert BOX2D to postgresql BOX
+void
+box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out)
+{
+ if (box == NULL) return;
+
+ out->low.x = nextDown_d(box->xmin);
+ out->low.y = nextDown_d(box->ymin);
+
+ out->high.x = nextUp_d(box->xmax);
+ out->high.y = nextUp_d(box->ymax);
+}
+
// returns a BOX3D that encloses b1 and b2
// combine_boxes(NULL,A) --> A
Datum BOX2DFLOAT4_ymin(PG_FUNCTION_ARGS);
Datum BOX2DFLOAT4_xmax(PG_FUNCTION_ARGS);
Datum BOX2DFLOAT4_ymax(PG_FUNCTION_ARGS);
+Datum BOX2DFLOAT4_combine(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(LWGEOM_to_BOX2DFLOAT4);
Datum LWGEOM_to_BOX2DFLOAT4(PG_FUNCTION_ARGS)
{
- char *lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- BOX2DFLOAT4 box, *result;
+ LWGEOM *lwgeom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ BOX2DFLOAT4 *result;
- box = getbox2d(lwgeom+4);
result = palloc(sizeof(BOX2DFLOAT4));
- memcpy(result,&box, sizeof(BOX2DFLOAT4));
+ getbox2d_p(SERIALIZED_FORM(lwgeom), result);
PG_RETURN_POINTER(result);
}
BOX2DFLOAT4 *box = (BOX2DFLOAT4 *)PG_GETARG_POINTER(0);
PG_RETURN_FLOAT4(box->ymax);
}
+
+PG_FUNCTION_INFO_V1(BOX2DFLOAT4_combine);
+Datum BOX2DFLOAT4_combine(PG_FUNCTION_ARGS)
+{
+ Pointer box2d_ptr = PG_GETARG_POINTER(0);
+ Pointer geom_ptr = PG_GETARG_POINTER(1);
+ BOX2DFLOAT4 *a,*b;
+ char *lwgeom;
+ BOX2DFLOAT4 box, *result;
+
+ if ( (box2d_ptr == NULL) && (geom_ptr == NULL) )
+ {
+ PG_RETURN_NULL(); // combine_box2d(null,null) => null
+ }
+
+ result = (BOX2DFLOAT4 *)palloc(sizeof(BOX2DFLOAT4));
+
+ if (box2d_ptr == NULL)
+ {
+ lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+
+ box = getbox2d(lwgeom+4);
+ memcpy(result, &box, sizeof(BOX2DFLOAT4));
+ PG_RETURN_POINTER(result);
+ }
+
+ // combine_bbox(BOX3D, null) => BOX3D
+ if (geom_ptr == NULL)
+ {
+ memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(BOX2DFLOAT4));
+ PG_RETURN_POINTER(result);
+ }
+
+ //combine_bbox(BOX3D, geometry) => union(BOX3D, geometry->bvol)
+
+ lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+ box = getbox2d(lwgeom+4);
+
+ a = (BOX2DFLOAT4 *)PG_GETARG_DATUM(0);
+ b = &box;
+
+ result->xmax = LWGEOM_Maxf(a->xmax, b->xmax);
+ result->ymax = LWGEOM_Maxf(a->ymax, b->ymax);
+ result->xmin = LWGEOM_Minf(a->xmin, b->xmin);
+ result->ymin = LWGEOM_Minf(a->ymin, b->ymin);
+
+ PG_RETURN_POINTER(result);
+}
+
Datum BOX3D_in(PG_FUNCTION_ARGS);
Datum BOX3D_out(PG_FUNCTION_ARGS);
Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS);
+Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS);
Datum BOX3D_expand(PG_FUNCTION_ARGS);
Datum BOX3D_to_BOX2DFLOAT4(PG_FUNCTION_ARGS);
-
+Datum BOX3D_to_BOX(PG_FUNCTION_ARGS);
Datum BOX3D_xmin(PG_FUNCTION_ARGS);
Datum BOX3D_ymin(PG_FUNCTION_ARGS);
Datum BOX3D_zmin(PG_FUNCTION_ARGS);
Datum BOX3D_xmax(PG_FUNCTION_ARGS);
Datum BOX3D_ymax(PG_FUNCTION_ARGS);
Datum BOX3D_zmax(PG_FUNCTION_ARGS);
+Datum BOX3D_combine(PG_FUNCTION_ARGS);
/*
* BOX3D_in - takes a string rep of BOX3D and returns internal rep
PG_RETURN_POINTER(out);
}
+PG_FUNCTION_INFO_V1(BOX3D_to_BOX);
+Datum BOX3D_to_BOX(PG_FUNCTION_ARGS)
+{
+ BOX3D *in = (BOX3D *)PG_GETARG_POINTER(0);
+ BOX2DFLOAT4 *box2d = box3d_to_box2df(in);
+ BOX *box = palloc(sizeof(BOX));
+
+ box2df_to_box_p(box2d, box);
+ PG_RETURN_POINTER(box);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_to_LWGEOM);
+Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS)
+{
+ BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
+ POINT2D *pts = palloc(sizeof(POINT2D)*5);
+ POINTARRAY *pa[1];
+ LWPOLY *poly;
+ int wantbbox = 0;
+ LWGEOM *result;
+ char *ser;
+
+ // 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, -1, 1, pa);
+
+ // Serialize polygon
+ ser = lwpoly_serialize(poly);
+
+ // Construct LWGEOM
+ result = LWGEOM_construct(ser, -1, wantbbox);
+
+ PG_RETURN_POINTER(result);
+}
+
/* Expand given box of 'd' units in all directions */
void
expand_box3d(BOX3D *box, double d)
Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS)
{
LWGEOM *lwgeom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- BOX2DFLOAT4 box;
BOX3D *result;
result = lw_geom_getBB(SERIALIZED_FORM(lwgeom));
BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
PG_RETURN_FLOAT8(box->zmax);
}
+
+
+PG_FUNCTION_INFO_V1(BOX3D_combine);
+Datum BOX3D_combine(PG_FUNCTION_ARGS)
+{
+ Pointer box3d_ptr = PG_GETARG_POINTER(0);
+ Pointer geom_ptr = PG_GETARG_POINTER(1);
+ BOX3D *a,*b;
+ LWGEOM *lwgeom;
+ BOX3D *box, *result;
+
+ if ( (box3d_ptr == NULL) && (geom_ptr == NULL) )
+ {
+ PG_RETURN_NULL();
+ }
+
+ result = (BOX3D *)palloc(sizeof(BOX3D));
+
+ if (box3d_ptr == NULL)
+ {
+ lwgeom = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+ box = lw_geom_getBB(SERIALIZED_FORM(lwgeom));
+ memcpy(result, box, sizeof(BOX3D));
+ PG_RETURN_POINTER(result);
+ }
+
+ // combine_bbox(BOX3D, null) => BOX3D
+ if (geom_ptr == NULL)
+ {
+ memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(BOX3D));
+ PG_RETURN_POINTER(result);
+ }
+
+ lwgeom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+ box = lw_geom_getBB(SERIALIZED_FORM(lwgeom));
+
+ a = (BOX3D *)PG_GETARG_DATUM(0);
+ b = box;
+
+ result->xmax = LWGEOM_Maxd(a->xmax, b->xmax);
+ result->ymax = LWGEOM_Maxd(a->ymax, b->ymax);
+ result->zmax = LWGEOM_Maxd(a->zmax, b->zmax);
+ result->xmin = LWGEOM_Mind(a->xmin, b->xmin);
+ result->ymin = LWGEOM_Mind(a->ymin, b->ymin);
+ result->zmin = LWGEOM_Mind(a->zmin, b->zmin);
+
+ PG_RETURN_POINTER(result);
+}
+
+//min(a,b)
+double LWGEOM_Mind(double a, double b)
+{
+ if (a<b)
+ return a;
+ return b;
+}
+
+//max(a,b)
+double LWGEOM_Maxd(double a, double b)
+{
+ if (b>a)
+ return b;
+ return a;
+}
//#define DEBUG
-Datum combine_box2d(PG_FUNCTION_ARGS);
Datum LWGEOM_mem_size(PG_FUNCTION_ARGS);
Datum LWGEOM_summary(PG_FUNCTION_ARGS);
Datum LWGEOM_npoints(PG_FUNCTION_ARGS);
Datum LWGEOM_accum(PG_FUNCTION_ARGS);
Datum LWGEOM_collect_garray(PG_FUNCTION_ARGS);
Datum LWGEOM_expand(PG_FUNCTION_ARGS);
+Datum LWGEOM_to_BOX(PG_FUNCTION_ARGS);
+Datum LWGEOM_envelope(PG_FUNCTION_ARGS);
// internal
char * lwgeom_summary_recursive(char *serialized, int offset);
/*------------------------------------------------------------------*/
-PG_FUNCTION_INFO_V1(combine_box2d);
-Datum combine_box2d(PG_FUNCTION_ARGS)
-{
- Pointer box2d_ptr = PG_GETARG_POINTER(0);
- Pointer geom_ptr = PG_GETARG_POINTER(1);
- BOX2DFLOAT4 *a,*b;
- char *lwgeom;
- BOX2DFLOAT4 box, *result;
-
- if ( (box2d_ptr == NULL) && (geom_ptr == NULL) )
- {
- PG_RETURN_NULL(); // combine_box2d(null,null) => null
- }
-
- result = (BOX2DFLOAT4 *)palloc(sizeof(BOX2DFLOAT4));
-
- if (box2d_ptr == NULL)
- {
- lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
-
- box = getbox2d(lwgeom+4);
- memcpy(result, &box, sizeof(BOX2DFLOAT4));
- PG_RETURN_POINTER(result);
- }
-
- // combine_bbox(BOX3D, null) => BOX3D
- if (geom_ptr == NULL)
- {
- memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(BOX2DFLOAT4));
- PG_RETURN_POINTER(result);
- }
-
- //combine_bbox(BOX3D, geometry) => union(BOX3D, geometry->bvol)
-
- lwgeom = (char *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
- box = getbox2d(lwgeom+4);
-
- a = (BOX2DFLOAT4 *)PG_GETARG_DATUM(0);
- b = &box;
-
- result->xmax = LWGEOM_Maxf(a->xmax, b->xmax);
- result->ymax = LWGEOM_Maxf(a->ymax, b->ymax);
- result->xmin = LWGEOM_Minf(a->xmin, b->xmin);
- result->ymin = LWGEOM_Minf(a->ymin, b->ymin);
-
- PG_RETURN_POINTER(result);
-}
-
//find the size of geometry
PG_FUNCTION_INFO_V1(LWGEOM_mem_size);
Datum LWGEOM_mem_size(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(result);
}
+
+// Convert geometry to BOX (internal postgres type)
+PG_FUNCTION_INFO_V1(LWGEOM_to_BOX);
+Datum LWGEOM_to_BOX(PG_FUNCTION_ARGS)
+{
+ LWGEOM *lwgeom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ BOX2DFLOAT4 box2d;
+ BOX *result = (BOX *)palloc(sizeof(BOX));
+
+ getbox2d_p(SERIALIZED_FORM(lwgeom), &box2d);
+ box2df_to_box_p(&box2d, result);
+
+ PG_RETURN_POINTER(result);
+}
+
+// makes a polygon of the 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_envelope);
+Datum LWGEOM_envelope(PG_FUNCTION_ARGS)
+{
+ LWGEOM *geom = (LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ 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));
+
+ // 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);
+}
AS '@MODULE_FILENAME@', 'LWGEOM_expand'
LANGUAGE 'C' WITH (iscachable,isstrict);
+CREATEFUNCTION envelope(geometry)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@', 'LWGEOM_envelope'
+ LANGUAGE 'C' WITH (iscachable,isstrict);
+
------------------------------------------------------------------------
--
CREATEFUNCTION combine_bbox(box2d,geometry)
RETURNS box2d
- AS '@MODULE_FILENAME@', 'combine_box2d'
+ AS '@MODULE_FILENAME@', 'BOX2DFLOAT4_combine'
LANGUAGE 'C';
CREATE AGGREGATE extent(
stype = box2d
);
+CREATEFUNCTION combine_bbox(box3d,geometry)
+ RETURNS box3d
+ AS '@MODULE_FILENAME@', 'BOX3D_combine'
+ LANGUAGE 'C';
+
+CREATE AGGREGATE extent3d(
+ sfunc = combine_bbox,
+ basetype = geometry,
+ stype = box3d
+ );
+
-----------------------------------------------------------------------
-- CREATE_HISTOGRAM2D( <box2d>, <size> )
-----------------------------------------------------------------------
CREATE CAST (geometry as box3d) WITH FUNCTION box3d(geometry) AS IMPLICIT ;
+CREATEFUNCTION box(geometry)
+ RETURNS box
+ AS '@MODULE_FILENAME@','LWGEOM_to_BOX'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE CAST (geometry as box) WITH FUNCTION box(geometry) AS IMPLICIT ;
+
CREATEFUNCTION box2d(box3d)
RETURNS box2d
AS '@MODULE_FILENAME@','BOX3D_to_BOX2DFLOAT4'
CREATE CAST (box2d as box3d) WITH FUNCTION box3d(box2d) AS IMPLICIT ;
+CREATEFUNCTION box(box3d)
+ RETURNS box
+ AS '@MODULE_FILENAME@','BOX3D_to_BOX'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
+-- this is kept for backward-compatibility
+CREATEFUNCTION box3dtobox(box3d)
+ RETURNS box
+ AS 'SELECT box($1)'
+ LANGUAGE 'SQL' WITH (isstrict,iscachable);
+
+CREATE CAST (box3d as box) WITH FUNCTION box(box3d) AS IMPLICIT ;
+
+CREATEFUNCTION geometry(box3d)
+ RETURNS geometry
+ AS '@MODULE_FILENAME@','BOX3D_to_LWGEOM'
+ LANGUAGE 'C' WITH (isstrict,iscachable);
+
+CREATE CAST (box3d as geometry) WITH FUNCTION geometry(box3d) AS IMPLICIT ;
+
---------------------------------------------------------------
-- END
---------------------------------------------------------------