Alter the in-built casts between the internal PostgreSQL BOX type and the PostGIS geometry/BOX3D types so that they do not go through an intermediate BOX2DFLOAT4 first. This prevents the float4 rounding errors appearing in the numbers when invoking the casts.

git-svn-id: http://svn.osgeo.org/postgis/trunk@3805 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
Mark Cave-Ayland 2009-03-08 16:36:20 +00:00
parent 919bac6d62
commit 15e1705f88
4 changed files with 39 additions and 26 deletions

View file

@ -1,3 +1,16 @@
/**********************************************************************
* $Id$
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.refractions.net
* Copyright 2001-2009 Refractions Research Inc.
* Copyright 2009 Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk>
*
* This is free software; you can redistribute and/or modify it under
* the terms of the GNU General Public Licence. See the COPYING file.
*
**********************************************************************/
#include "postgres.h"
#include "utils/geo_decls.h"
@ -5,38 +18,38 @@
#include "liblwgeom.h"
void box_to_box2df(BOX *box, BOX2DFLOAT4 *out);
void box_to_box3d(BOX *box, BOX3D *out);
void box3d_to_box_p(BOX3D *box, BOX *out);
/* convert postgresql BOX to BOX2D */
/* convert postgresql BOX to BOX3D */
void
box_to_box2df(BOX *box, BOX2DFLOAT4 *out)
box_to_box3d(BOX *box, BOX3D *out)
{
#if PARANOIA_LEVEL > 0
if (box == NULL) return;
#endif
out->xmin = nextDown_f(box->low.x);
out->ymin = nextDown_f(box->low.y);
out->xmin = box->low.x;
out->ymin = box->low.y;
out->xmax = nextUp_f(box->high.x);
out->ymax = nextUp_f(box->high.x);
out->xmax = box->high.x;
out->ymax = box->high.y;
}
/* convert BOX2D to postgresql BOX */
/* convert BOX3D to postgresql BOX */
void
box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out)
box3d_to_box_p(BOX3D *box, BOX *out)
{
#if PARANOIA_LEVEL > 0
if (box == NULL) return;
#endif
out->low.x = nextDown_d(box->xmin);
out->low.y = nextDown_d(box->ymin);
out->low.x = box->xmin;
out->low.y = box->ymin;
out->high.x = nextUp_d(box->xmax);
out->high.y = nextUp_d(box->ymax);
out->high.x = box->xmax;
out->high.y = box->ymax;
}

View file

@ -150,10 +150,9 @@ 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);
box3d_to_box_p(in, box);
PG_RETURN_POINTER(box);
}

View file

@ -2400,17 +2400,18 @@ Datum LWGEOM_expand(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(LWGEOM_to_BOX);
Datum LWGEOM_to_BOX(PG_FUNCTION_ARGS)
{
PG_LWGEOM *lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
BOX2DFLOAT4 box2d;
PG_LWGEOM *pg_lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
BOX3D *box3d;
BOX *result = (BOX *)lwalloc(sizeof(BOX));
LWGEOM *lwgeom = lwgeom_deserialize(SERIALIZED_FORM(pg_lwgeom));
if ( ! getbox2d_p(SERIALIZED_FORM(lwgeom), &box2d) )
{
PG_RETURN_NULL(); /* must be the empty geometry */
}
box2df_to_box_p(&box2d, result);
/* Calculate the BOX3D of the geometry */
box3d = lwgeom_compute_box3d(lwgeom);
box3d_to_box_p(box3d, result);
lwfree(box3d);
lwfree(lwgeom);
PG_FREE_IF_COPY(lwgeom, 0);
PG_FREE_IF_COPY(pg_lwgeom, 0);
PG_RETURN_POINTER(result);
}

View file

@ -82,8 +82,8 @@ extern Oid getGeometryOID(void);
/* PG-dependant */
/* BOX is postgresql standard type */
extern void box_to_box2df_p(BOX *box, BOX2DFLOAT4 *out);
extern void box2df_to_box_p(BOX2DFLOAT4 *box, BOX *out);
extern void box_to_box3d_p(BOX *box, BOX3D *out);
extern void box3d_to_box_p(BOX3D *box, BOX *out);
/* PG-exposed */
Datum BOX2D_same(PG_FUNCTION_ARGS);