Commit 1d15d5f0 authored by Regina Obe's avatar Regina Obe

spgist 2d and 3d support for PG 11+

references #1847
Credits: Arthur Lesuisse, Esteban Zimanyi from Université Libre de Bruxelles (ULB)  and Darafei Praliaskouski
also added logic to exclude PG < 11 from including this functionality
Closes https://github.com/postgis/postgis/pull/258 



git-svn-id: http://svn.osgeo.org/postgis/trunk@16626 b70326c6-7e19-0410-871a-916f4a2858ee
parent 648795ff
Pipeline #24912967 failed with stage
in 5 minutes and 40 seconds
......@@ -6,6 +6,8 @@ PostGIS 2.5.0
2018/xx/xx
* New Features *
- #1847, spgist 2d and 3d support for PG 11+
(Arthur Lesuisse, Esteban Zimanyi, Darafei Praliaskouski)
- #4056, ST_FilterByM (Nicklas Avén)
- #4050, ST_ChaikinSmoothing (Nicklas Avén)
- #3989, ST_Buffer single sided option (Stephen Knox)
......
......@@ -467,6 +467,11 @@ if test "x$LIBLWGEOM_ONLY" = "xno"; then
HAVE_BRIN=yes
fi
HAVE_SPGIST=no
if test $POSTGIS_PGSQL_VERSION -gt 100; then
HAVE_SPGIST=yes
fi
dnl Note: We don't need the server-side LDFLAGS or CPPFLAGS because we get these from PGXS
dnl Extract the linker and include flags for the frontend (for programs that use libpq)
......@@ -536,6 +541,7 @@ if test "x$LIBLWGEOM_ONLY" = "xno"; then
AC_DEFINE_UNQUOTED([POSTGIS_PGSQL_VERSION], [$POSTGIS_PGSQL_VERSION], [PostgreSQL server version])
AC_SUBST([POSTGIS_PGSQL_VERSION])
AC_SUBST([HAVE_BRIN])
AC_SUBST([HAVE_SPGIST])
fi dnl LIBLWGEOM_ONLY != no
......
......@@ -130,7 +130,24 @@ GSERIALIZED* gserialized_set_gidx(GSERIALIZED *g, GIDX *gidx);
GSERIALIZED* gserialized_drop_gidx(GSERIALIZED *g);
bool box2df_contains(const BOX2DF *a, const BOX2DF *b);
/** needed for sp-gist support PostgreSQL 11+ **/
#if POSTGIS_PGSQL_VERSION > 100
void box2df_set_empty(BOX2DF *a);
void box2df_set_finite(BOX2DF *a);
void box2df_validate(BOX2DF *b);
bool box2df_overlaps(const BOX2DF *a, const BOX2DF *b);
bool box2df_overleft(const BOX2DF *a, const BOX2DF *b);
bool box2df_equals(const BOX2DF *a, const BOX2DF *b);
bool box2df_left(const BOX2DF *a, const BOX2DF *b);
bool box2df_right(const BOX2DF *a, const BOX2DF *b);
bool box2df_overright(const BOX2DF *a, const BOX2DF *b);
bool box2df_overbelow(const BOX2DF *a, const BOX2DF *b);
bool box2df_below(const BOX2DF *a, const BOX2DF *b);
bool box2df_above(const BOX2DF *a, const BOX2DF *b);
bool box2df_overabove(const BOX2DF *a, const BOX2DF *b);
#endif
bool gidx_contains(GIDX *a, GIDX *b);
int gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df);
......@@ -149,7 +149,36 @@ Datum BOX2D_intersects(PG_FUNCTION_ARGS);
Datum BOX2D_union(PG_FUNCTION_ARGS);
Datum LWGEOM_same(PG_FUNCTION_ARGS);
Datum BOX3D_construct(PG_FUNCTION_ARGS);
/** needed for sp-gist support PostgreSQL 11+ **/
//#if POSTGIS_PGSQL_VERSION > 100
Datum BOX3D_construct(PG_FUNCTION_ARGS);
Datum LWGEOM_to_BOX2DF(PG_FUNCTION_ARGS);
Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS);
Datum BOX3D_contains(PG_FUNCTION_ARGS);
Datum BOX3D_contained(PG_FUNCTION_ARGS);
Datum BOX3D_overlaps(PG_FUNCTION_ARGS);
Datum BOX3D_same(PG_FUNCTION_ARGS);
Datum BOX3D_left(PG_FUNCTION_ARGS);
Datum BOX3D_overleft(PG_FUNCTION_ARGS);
Datum BOX3D_right(PG_FUNCTION_ARGS) ;
Datum BOX3D_overright(PG_FUNCTION_ARGS);
Datum BOX3D_below(PG_FUNCTION_ARGS);
Datum BOX3D_overbelow(PG_FUNCTION_ARGS);
Datum BOX3D_above(PG_FUNCTION_ARGS);
Datum BOX3D_overabove(PG_FUNCTION_ARGS);
Datum BOX3D_front(PG_FUNCTION_ARGS);
Datum BOX3D_overfront(PG_FUNCTION_ARGS);
Datum BOX3D_back(PG_FUNCTION_ARGS);
Datum BOX3D_overback(PG_FUNCTION_ARGS);
Datum BOX3D_distance(PG_FUNCTION_ARGS);
#define DatumGetBox3DP(X) ((BOX3D *) DatumGetPointer(X))
#define Box3DPGetDatum(X) PointerGetDatum(X)
#define PG_GETARG_BOX3D_P(n) DatumGetBox3DP(PG_GETARG_DATUM(n))
#define PG_RETURN_BOX3D_P(x) return Box3DPGetDatum(x)
//#endif
Datum LWGEOM_force_2d(PG_FUNCTION_ARGS);
Datum LWGEOM_force_3dm(PG_FUNCTION_ARGS);
......
......@@ -50,6 +50,10 @@ ifeq (@HAVE_BRIN@,yes)
BRIN_OBJ= brin_2d.o brin_nd.o brin_common.o
endif
ifeq (@HAVE_SPGIST@,yes)
SPGIST_OBJ= gserialized_spgist_2d.o gserialized_spgist_3d.o
endif
ifeq (@HAVE_PROTOBUF@,yes)
PROTOBUF_OBJ=vector_tile.pb-c.o geobuf.pb-c.o
endif
......@@ -94,6 +98,7 @@ PG_OBJS= \
gserialized_typmod.o \
gserialized_gist_2d.o \
gserialized_gist_nd.o \
$(SPGIST_OBJ) \
$(BRIN_OBJ) \
gserialized_estimate.o \
geography_inout.o \
......
......@@ -161,13 +161,13 @@ inline bool box2df_is_empty(const BOX2DF *a)
return false;
}
static inline void box2df_set_empty(BOX2DF *a)
inline void box2df_set_empty(BOX2DF *a)
{
a->xmin = a->xmax = a->ymin = a->ymax = NAN;
return;
}
static inline void box2df_set_finite(BOX2DF *a)
inline void box2df_set_finite(BOX2DF *a)
{
if ( ! isfinite(a->xmax) )
a->xmax = FLT_MAX;
......@@ -329,7 +329,7 @@ int box2df_to_gbox_p(BOX2DF *a, GBOX *box)
*/
/* Ensure all minimums are below maximums. */
static inline void box2df_validate(BOX2DF *b)
inline void box2df_validate(BOX2DF *b)
{
float tmp;
POSTGIS_DEBUGF(5,"validating box2df (%s)", box2df_to_string(b));
......@@ -352,7 +352,7 @@ static inline void box2df_validate(BOX2DF *b)
return;
}
static bool box2df_overlaps(const BOX2DF *a, const BOX2DF *b)
bool box2df_overlaps(const BOX2DF *a, const BOX2DF *b)
{
if ( !a || !b || box2df_is_empty(a) || box2df_is_empty(b) )
return false;
......@@ -397,7 +397,7 @@ static bool box2df_within(const BOX2DF *a, const BOX2DF *b)
return box2df_contains(b,a);
}
static bool box2df_equals(const BOX2DF *a, const BOX2DF *b)
bool box2df_equals(const BOX2DF *a, const BOX2DF *b)
{
if ( !a && !b )
return true;
......@@ -413,7 +413,7 @@ static bool box2df_equals(const BOX2DF *a, const BOX2DF *b)
return false;
}
static bool box2df_overleft(const BOX2DF *a, const BOX2DF *b)
bool box2df_overleft(const BOX2DF *a, const BOX2DF *b)
{
if ( !a || !b || box2df_is_empty(a) || box2df_is_empty(b) )
return false;
......@@ -422,7 +422,7 @@ static bool box2df_overleft(const BOX2DF *a, const BOX2DF *b)
return a->xmax <= b->xmax;
}
static bool box2df_left(const BOX2DF *a, const BOX2DF *b)
bool box2df_left(const BOX2DF *a, const BOX2DF *b)
{
if ( !a || !b || box2df_is_empty(a) || box2df_is_empty(b) )
return false;
......@@ -431,7 +431,7 @@ static bool box2df_left(const BOX2DF *a, const BOX2DF *b)
return a->xmax < b->xmin;
}
static bool box2df_right(const BOX2DF *a, const BOX2DF *b)
bool box2df_right(const BOX2DF *a, const BOX2DF *b)
{
if ( !a || !b || box2df_is_empty(a) || box2df_is_empty(b) )
return false;
......@@ -440,7 +440,7 @@ static bool box2df_right(const BOX2DF *a, const BOX2DF *b)
return a->xmin > b->xmax;
}
static bool box2df_overright(const BOX2DF *a, const BOX2DF *b)
bool box2df_overright(const BOX2DF *a, const BOX2DF *b)
{
if ( !a || !b || box2df_is_empty(a) || box2df_is_empty(b) )
return false;
......@@ -449,7 +449,7 @@ static bool box2df_overright(const BOX2DF *a, const BOX2DF *b)
return a->xmin >= b->xmin;
}
static bool box2df_overbelow(const BOX2DF *a, const BOX2DF *b)
bool box2df_overbelow(const BOX2DF *a, const BOX2DF *b)
{
if ( !a || !b || box2df_is_empty(a) || box2df_is_empty(b) )
return false;
......@@ -458,7 +458,7 @@ static bool box2df_overbelow(const BOX2DF *a, const BOX2DF *b)
return a->ymax <= b->ymax;
}
static bool box2df_below(const BOX2DF *a, const BOX2DF *b)
bool box2df_below(const BOX2DF *a, const BOX2DF *b)
{
if ( !a || !b || box2df_is_empty(a) || box2df_is_empty(b) )
return false;
......@@ -467,7 +467,7 @@ static bool box2df_below(const BOX2DF *a, const BOX2DF *b)
return a->ymax < b->ymin;
}
static bool box2df_above(const BOX2DF *a, const BOX2DF *b)
bool box2df_above(const BOX2DF *a, const BOX2DF *b)
{
if ( !a || !b || box2df_is_empty(a) || box2df_is_empty(b) )
return false;
......@@ -476,7 +476,7 @@ static bool box2df_above(const BOX2DF *a, const BOX2DF *b)
return a->ymin > b->ymax;
}
static bool box2df_overabove(const BOX2DF *a, const BOX2DF *b)
bool box2df_overabove(const BOX2DF *a, const BOX2DF *b)
{
if ( !a || !b || box2df_is_empty(a) || box2df_is_empty(b) )
return false;
......
This diff is collapsed.
This diff is collapsed.
#include <postgres.h>
#include <liblwgeom.h>
#include <math.h>
#include <access/spgist.h>
#include <access/stratnum.h>
#include <catalog/namespace.h>
#include <catalog/pg_type.h>
#include <utils/builtins.h>
#include <utils/geo_decls.h>
/*****************************************************************************
* Operator strategy numbers used in the GiST and SP-GiST box3d opclasses
*****************************************************************************/
#define SPGLeftStrategyNumber 1 /* for << */
#define SPGOverLeftStrategyNumber 2 /* for &< */
#define SPGOverlapStrategyNumber 3 /* for && */
#define SPGOverRightStrategyNumber 4 /* for &> */
#define SPGRightStrategyNumber 5 /* for >> */
#define SPGSameStrategyNumber 6 /* for ~= */
#define SPGContainsStrategyNumber 7 /* for @> */
#define SPGContainedByStrategyNumber 8 /* for <@ */
#define SPGOverBelowStrategyNumber 9 /* for &<| */
#define SPGBelowStrategyNumber 10 /* for <<| */
#define SPGAboveStrategyNumber 11 /* for |>> */
#define SPGOverAboveStrategyNumber 12 /* for |&> */
#define SPGOldContainsStrategyNumber 13 /* for old spelling of @> */
#define SPGOldContainedByStrategyNumber 14 /* for old spelling of <@ */
#define SPGKNNSearchStrategyNumber 15 /* for <-> (distance) */
#define SPGContainsElemStrategyNumber 16 /* for range types @> elem */
#define SPGAdjacentStrategyNumber 17 /* for -|- */
#define SPGEqualStrategyNumber 18 /* for = */
#define SPGNotEqualStrategyNumber 19 /* for != */
#define SPGLessStrategyNumber 20 /* for < */
#define SPGLessEqualStrategyNumber 21 /* for <= */
#define SPGGreaterStrategyNumber 22 /* for > */
#define SPGGreaterEqualStrategyNumber 23 /* for >= */
#define SPGSubStrategyNumber 24 /* for inet >> */
#define SPGSubEqualStrategyNumber 25 /* for inet <<= */
#define SPGSuperStrategyNumber 26 /* for inet << */
#define SPGSuperEqualStrategyNumber 27 /* for inet >>= */
#define SPGOverFrontStrategyNumber 28 /* for &</ */
#define SPGFrontStrategyNumber 29 /* for <</ */
#define SPGBackStrategyNumber 30 /* for />> */
#define SPGOverBackStrategyNumber 31 /* for /&> */
/*****************************************************************************
* BOX3D operators
*****************************************************************************/
bool BOX3D_contains_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_contained_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_overlaps_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_same_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_left_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_overleft_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_right_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_overright_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_below_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_overbelow_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_above_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_overabove_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_front_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_overfront_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_back_internal(BOX3D *box1, BOX3D *box2);
bool BOX3D_overback_internal(BOX3D *box1, BOX3D *box2);
double BOX3D_distance_internal(BOX3D *box1, BOX3D *box2);
......@@ -28,6 +28,11 @@
#include "utils/elog.h"
#include "utils/geo_decls.h"
/** needed for sp-gist support PostgreSQL 11+ **/
#if POSTGIS_PGSQL_VERSION > 100
#include "gserialized_spgist_3d.h"
#endif
#include "../postgis_config.h"
#include "lwgeom_pg.h"
#include "liblwgeom.h"
......@@ -58,6 +63,27 @@ Datum BOX3D_zmax(PG_FUNCTION_ARGS);
Datum BOX3D_combine(PG_FUNCTION_ARGS);
Datum BOX3D_combine_BOX3D(PG_FUNCTION_ARGS);
/** needed for sp-gist support PostgreSQL 11+ **/
#if POSTGIS_PGSQL_VERSION > 100
Datum BOX3D_contains(PG_FUNCTION_ARGS);
Datum BOX3D_contained(PG_FUNCTION_ARGS);
Datum BOX3D_overlaps(PG_FUNCTION_ARGS);
Datum BOX3D_same(PG_FUNCTION_ARGS);
Datum BOX3D_left(PG_FUNCTION_ARGS);
Datum BOX3D_overleft(PG_FUNCTION_ARGS);
Datum BOX3D_right(PG_FUNCTION_ARGS) ;
Datum BOX3D_overright(PG_FUNCTION_ARGS);
Datum BOX3D_below(PG_FUNCTION_ARGS);
Datum BOX3D_overbelow(PG_FUNCTION_ARGS);
Datum BOX3D_above(PG_FUNCTION_ARGS);
Datum BOX3D_overabove(PG_FUNCTION_ARGS);
Datum BOX3D_front(PG_FUNCTION_ARGS);
Datum BOX3D_overfront(PG_FUNCTION_ARGS);
Datum BOX3D_back(PG_FUNCTION_ARGS);
Datum BOX3D_overback(PG_FUNCTION_ARGS);
Datum BOX3D_distance(PG_FUNCTION_ARGS);
#endif
/**
* BOX3D_in - takes a string rep of BOX3D and returns internal rep
*
......@@ -601,3 +627,387 @@ Datum BOX3D_construct(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(result);
}
/** needed for sp-gist support PostgreSQL 11+ **/
#if POSTGIS_PGSQL_VERSION > 100
/*****************************************************************************
* BOX3D functions
*****************************************************************************/
/* contains? */
bool
BOX3D_contains_internal(BOX3D *box1, BOX3D *box2)
{
return (box1->xmax >= box2->xmax &&
box1->xmin <= box2->xmin &&
box1->ymax >= box2->ymax &&
box1->ymin <= box2->ymin &&
box1->zmax >= box2->zmax &&
box1->zmin <= box2->zmin);
}
PG_FUNCTION_INFO_V1(BOX3D_contains);
PGDLLEXPORT Datum
BOX3D_contains(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_contains_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* contained by? */
bool
BOX3D_contained_internal(BOX3D *box1, BOX3D *box2)
{
return BOX3D_contains_internal(box2, box1);
}
PG_FUNCTION_INFO_V1(BOX3D_contained);
PGDLLEXPORT Datum
BOX3D_contained(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_contained_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* overlaps? */
bool
BOX3D_overlaps_internal(BOX3D *box1, BOX3D *box2)
{
return (box1->xmin <= box2->xmax &&
box2->xmin <= box1->xmax &&
box1->ymin <= box2->ymax &&
box2->ymin <= box1->ymax &&
box1->zmin <= box2->zmax &&
box2->zmin <= box1->zmax);
}
PG_FUNCTION_INFO_V1(BOX3D_overlaps);
PGDLLEXPORT Datum
BOX3D_overlaps(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_overlaps_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* same? */
bool
BOX3D_same_internal(BOX3D *box1, BOX3D *box2)
{
return (FPeq(box1->xmax, box2->xmax) &&
FPeq(box1->xmin, box2->xmin) &&
FPeq(box1->ymax, box2->ymax) &&
FPeq(box1->ymin, box2->ymin) &&
FPeq(box1->zmax, box2->zmax) &&
FPeq(box1->zmin, box2->zmin));
}
PG_FUNCTION_INFO_V1(BOX3D_same);
PGDLLEXPORT Datum
BOX3D_same(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_same_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* strictly left of? */
bool
BOX3D_left_internal(BOX3D *box1, BOX3D *box2)
{
return box1->xmax < box2->xmin;
}
PG_FUNCTION_INFO_V1(BOX3D_left);
PGDLLEXPORT Datum
BOX3D_left(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_left_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* does not extend to right of? */
bool
BOX3D_overleft_internal(BOX3D *box1, BOX3D *box2)
{
return box1->xmax <= box2->xmax;
}
PG_FUNCTION_INFO_V1(BOX3D_overleft);
PGDLLEXPORT Datum
BOX3D_overleft(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_overleft_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* strictly right of? */
bool
BOX3D_right_internal(BOX3D *box1, BOX3D *box2)
{
return box1->xmin > box2->xmax;
}
PG_FUNCTION_INFO_V1(BOX3D_right);
PGDLLEXPORT Datum
BOX3D_right(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_right_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* does not extend to left of? */
bool
BOX3D_overright_internal(BOX3D *box1, BOX3D *box2)
{
return box1->xmin >= box2->xmin;
}
PG_FUNCTION_INFO_V1(BOX3D_overright);
PGDLLEXPORT Datum
BOX3D_overright(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_overright_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* strictly below of? */
bool
BOX3D_below_internal(BOX3D *box1, BOX3D *box2)
{
return box1->ymax < box2->ymin;
}
PG_FUNCTION_INFO_V1(BOX3D_below);
PGDLLEXPORT Datum
BOX3D_below(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_below_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* does not extend above of? */
bool
BOX3D_overbelow_internal(BOX3D *box1, BOX3D *box2)
{
return box1->ymax <= box2->ymax;
}
PG_FUNCTION_INFO_V1(BOX3D_overbelow);
PGDLLEXPORT Datum
BOX3D_overbelow(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_overbelow_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* strictly above of? */
bool
BOX3D_above_internal(BOX3D *box1, BOX3D *box2)
{
return box1->ymin > box2->ymax;
}
PG_FUNCTION_INFO_V1(BOX3D_above);
PGDLLEXPORT Datum
BOX3D_above(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_above_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* does not extend below of? */
bool
BOX3D_overabove_internal(BOX3D *box1, BOX3D *box2)
{
return box1->ymin >= box2->ymin;
}
PG_FUNCTION_INFO_V1(BOX3D_overabove);
PGDLLEXPORT Datum
BOX3D_overabove(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_overabove_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* strictly in before of? */
bool
BOX3D_front_internal(BOX3D *box1, BOX3D *box2)
{
return box1->zmax < box2->zmin;
}
PG_FUNCTION_INFO_V1(BOX3D_front);
PGDLLEXPORT Datum
BOX3D_front(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_front_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* does not extend to the after of? */
bool
BOX3D_overfront_internal(BOX3D *box1, BOX3D *box2)
{
return box1->zmax <= box2->zmax;
}
PG_FUNCTION_INFO_V1(BOX3D_overfront);
PGDLLEXPORT Datum
BOX3D_overfront(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_overfront_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* strictly after of? */
bool
BOX3D_back_internal(BOX3D *box1, BOX3D *box2)
{
return box1->zmin > box2->zmax;
}
PG_FUNCTION_INFO_V1(BOX3D_back);
PGDLLEXPORT Datum
BOX3D_back(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_back_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* does not extend to the before of? */
bool
BOX3D_overback_internal(BOX3D *box1, BOX3D *box2)
{
return box1->zmin >= box2->zmin;
}
PG_FUNCTION_INFO_V1(BOX3D_overback);
PGDLLEXPORT Datum
BOX3D_overback(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
bool result = BOX3D_overback_internal(box1, box2);
PG_RETURN_BOOL(result);
}
/* Minimum distance between 2 bounding boxes */
double
BOX3D_distance_internal(BOX3D *box1, BOX3D *box2)
{
double sqrDist = 0;
double d;
if (BOX3D_overlaps_internal(box1, box2))
return 0.0;
/* X axis */
if (box1->xmax < box2->xmin)
{
d = box1->xmax - box2->xmin;
sqrDist += d * d;
}
else if (box1->xmin > box2->xmax)
{
d = box1->xmin - box2->xmax;
sqrDist += d * d;
}
/* Y axis */
if (box1->ymax < box2->ymin)
{
d = box1->ymax - box2->ymin;
sqrDist += d * d;
}
else if (box1->ymin > box2->ymax)
{
d = box1->ymin - box2->ymax;
sqrDist += d * d;
}
/* Z axis */
if (box1->zmax < box2->zmin)
{
d = box1->zmax - box2->zmin;
sqrDist += d * d;
}
else if (box1->zmin > box2->zmax)
{
d = box1->zmin - box2->zmax;
sqrDist += d * d;
}
return sqrt(sqrDist);
}
PG_FUNCTION_INFO_V1(BOX3D_distance);
PGDLLEXPORT Datum
BOX3D_distance(PG_FUNCTION_ARGS)
{
BOX3D *box1 = PG_GETARG_BOX3D_P(0);
BOX3D *box2 = PG_GETARG_BOX3D_P(1);
PG_RETURN_FLOAT8(BOX3D_distance_internal(box1, box2));
}
#endif
......@@ -6093,4 +6093,8 @@ GRANT SELECT ON TABLE geography_columns TO public;
GRANT SELECT ON TABLE geometry_columns TO public;
GRANT SELECT ON TABLE spatial_ref_sys TO public;