1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
#include <float.h>
/**********************************************************************
** GIDX structure.
**
** This is an n-dimensional (practically, the
** implementation is 2-4 dimensions) box used for index keys. The
** coordinates are anonymous, so we can have any number of dimensions.
** The sizeof a GIDX is 1 + 2 * ndims * sizeof(float).
** The order of values in a GIDX is
** xmin,xmax,ymin,ymax,zmin,zmax...
*/
typedef struct
{
int32 varsize;
float c[1];
} GIDX;
/*
** For some GiST support functions, it is more efficient to allocate
** memory for our GIDX off the stack and cast that memory into a GIDX.
** But, GIDX is variable length, what to do? We'll bake in the assumption
** that no GIDX is more than 4-dimensional for now, and ensure that much
** space is available.
** 4 bytes varsize + 4 dimensions * 2 ordinates * 4 bytes float size = 36 bytes
*/
#define GIDX_MAX_SIZE 36
#define GIDX_MAX_DIM 4
/*
* This macro is based on PG_FREE_IF_COPY, except that it accepts two pointers.
* See PG_FREE_IF_COPY comment in src/include/fmgr.h in postgres source code
* for more details.
*/
#define POSTGIS_FREE_IF_COPY_P(ptrsrc, ptrori) \
do { \
if ((Pointer) (ptrsrc) != (Pointer) (ptrori)) \
pfree(ptrsrc); \
} while (0)
/**********************************************************************
** BOX2DF structure.
**
** This is a 2-dimensional key for simple cartesian indexes,
** with backwards compatible behavior to previous indexes in
** PostGIS
*/
typedef struct
{
float xmin, xmax, ymin, ymax;
} BOX2DF;
/*********************************************************************************
** GIDX support functions.
**
** We put the GIDX support here rather than libgeom because it is a specialized
** type only used for indexing purposes. It also makes use of some PgSQL
** infrastructure like the VARSIZE() macros.
*/
/* allocate a new gidx object on the heap */
GIDX* gidx_new(int ndims) ;
/* Increase the size of a GIDX */
void gidx_expand(GIDX *a, float d);
/* Note empty GIDX */
bool gidx_is_unknown(const GIDX *a);
/* Generate human readable form for GIDX. */
char* gidx_to_string(GIDX *a) ;
/* typedef to correct array-bounds checking for casts to GIDX - do not
use this ANYWHERE except in the casts below */
typedef float _gidx_float_array[sizeof(float) * 2 * 4];
/* Returns number of dimensions for this GIDX */
#define GIDX_NDIMS(gidx) ((VARSIZE((gidx)) - VARHDRSZ) / (2 * sizeof(float)))
/* Minimum accessor. */
#define GIDX_GET_MIN(gidx, dimension) (*((_gidx_float_array *)(&(gidx)->c)))[2*(dimension)]
/* Maximum accessor. */
#define GIDX_GET_MAX(gidx, dimension) (*((_gidx_float_array *)(&(gidx)->c)))[2*(dimension)+1]
/* Minimum setter. */
#define GIDX_SET_MIN(gidx, dimension, value) ((gidx)->c[2*(dimension)] = (value))
/* Maximum setter. */
#define GIDX_SET_MAX(gidx, dimension, value) ((gidx)->c[2*(dimension)+1] = (value))
/* Returns the size required to store a GIDX of requested dimension */
#define GIDX_SIZE(dimensions) (sizeof(int32) + 2*(dimensions)*sizeof(float))
/* Allocate a copy of the box */
BOX2DF* box2df_copy(BOX2DF *b);
/* Grow the first argument to contain the second */
void box2df_merge(BOX2DF *b_union, BOX2DF *b_new);
/* Allocate a copy of the box */
GIDX* gidx_copy(GIDX *b);
/* Grow the first argument to contain the second */
void gidx_merge(GIDX **b_union, GIDX *b_new);
/* Note empty BOX2DF */
bool box2df_is_empty(const BOX2DF *a);
/* Fill in a gbox from a GIDX */
void gbox_from_gidx(GIDX *a, GBOX *gbox, int flags);
/* Fill in a gbox from a BOX2DF */
int box2df_to_gbox_p(BOX2DF *a, GBOX *box);
/*********************************************************************************
** GSERIALIZED support functions.
**
** Fast functions for pulling boxes out of serializations.
*/
/* Pull out the #GIDX bounding box with a absolute minimum system overhead */
int gserialized_datum_get_gidx_p(Datum gserialized_datum, GIDX *gidx);
/* Pull out the gidx bounding box from an already de-toasted geography */
int gserialized_get_gidx_p(const GSERIALIZED *g, GIDX *gidx);
/* Copy a new bounding box into an existing gserialized */
GSERIALIZED* gserialized_set_gidx(GSERIALIZED *g, GIDX *gidx);
/* Given two datums, do they overlap? Computed very fast using embedded boxes. */
/* int gserialized_datum_overlaps(Datum gs1, Datum gs2); */
/* Remove the box from a disk serialization */
GSERIALIZED* gserialized_drop_gidx(GSERIALIZED *g);
bool box2df_contains(const BOX2DF *a, const BOX2DF *b);
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);
bool gidx_contains(GIDX *a, GIDX *b);
int gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df);
|