74 #include <utils/builtins.h>
75 #include "access/spgist.h"
76 #include "catalog/pg_type_d.h"
78 #include "../postgis_config.h"
81 #include "lwgeom_pg.h"
82 #include <gserialized_gist.h>
83 #include <lwgeom_pg.h>
106 double x = *(
double *)a;
107 double y = *(
double *)b;
111 return (
x >
y) ? 1 : -1;
157 float infinity = FLT_MAX;
159 rect_box->
left.xmin = -infinity;
160 rect_box->
left.xmax = infinity;
162 rect_box->
left.ymin = -infinity;
163 rect_box->
left.ymax = infinity;
165 rect_box->
right.xmin = -infinity;
166 rect_box->
right.xmax = infinity;
168 rect_box->
right.ymin = -infinity;
169 rect_box->
right.ymax = infinity;
186 memcpy(next_rect_box, rect_box,
sizeof(
RectBox));
208 return next_rect_box;
215 return (rect_box->
left.xmin <= query->xmax && rect_box->
right.xmax >= query->xmin) &&
216 (rect_box->
left.ymin <= query->ymax && rect_box->
right.ymax >= query->ymin);
223 return (rect_box->
right.xmax >= query->xmax && rect_box->
left.xmin <= query->xmin) &&
224 (rect_box->
right.ymax >= query->ymax && rect_box->
left.ymin <= query->ymin);
231 return rect_box->
right.xmax <= query->xmin;
238 return rect_box->
right.xmax <= query->xmax;
245 return rect_box->
left.xmin >= query->xmax;
252 return rect_box->
left.xmin >= query->xmin;
259 return rect_box->
right.ymax <= query->ymin;
266 return rect_box->
right.ymax <= query->ymax;
273 return rect_box->
left.ymin >= query->ymax;
280 return rect_box->
left.ymin >= query->ymin;
291 spgConfigOut *
cfg = (spgConfigOut *)PG_GETARG_POINTER(1);
292 Oid boxoid = InvalidOid;
293 postgis_initialize_cache(fcinfo);
294 boxoid = postgis_oid(BOX2DFOID);
296 cfg->prefixType = boxoid;
297 cfg->labelType = VOIDOID;
298 cfg->leafType = boxoid;
299 cfg->canReturnData =
false;
300 cfg->longValuesOK =
false;
313 spgChooseIn *in = (spgChooseIn *)PG_GETARG_POINTER(0);
314 spgChooseOut *out = (spgChooseOut *)PG_GETARG_POINTER(1);
315 BOX2DF *
centroid = (BOX2DF *)DatumGetPointer(in->prefixDatum), *box = (BOX2DF *)DatumGetPointer(in->leafDatum);
317 out->resultType = spgMatchNode;
318 out->result.matchNode.restDatum = PointerGetDatum(box);
337 spgPickSplitIn *in = (spgPickSplitIn *)PG_GETARG_POINTER(0);
338 spgPickSplitOut *out = (spgPickSplitOut *)PG_GETARG_POINTER(1);
341 double *lowXs = palloc(
sizeof(
double) * in->nTuples);
342 double *highXs = palloc(
sizeof(
double) * in->nTuples);
343 double *lowYs = palloc(
sizeof(
double) * in->nTuples);
344 double *highYs = palloc(
sizeof(
double) * in->nTuples);
347 for (i = 0; i < in->nTuples; i++)
349 BOX2DF *box = (BOX2DF *)DatumGetPointer(in->datums[i]);
351 lowXs[i] = (double)box->xmin;
352 highXs[i] = (
double)box->xmax;
353 lowYs[i] = (double)box->ymin;
354 highYs[i] = (
double)box->ymax;
362 median = in->nTuples / 2;
366 centroid->xmin = (float)lowXs[median];
367 centroid->xmax = (float)highXs[median];
368 centroid->ymin = (float)lowYs[median];
369 centroid->ymax = (float)highYs[median];
372 out->hasPrefix =
true;
373 out->prefixDatum = BoxPGetDatum(
centroid);
376 out->nodeLabels = NULL;
378 out->mapTuplesToNodes = palloc(
sizeof(
int) * in->nTuples);
379 out->leafTupleDatums = palloc(
sizeof(Datum) * in->nTuples);
384 for (i = 0; i < in->nTuples; i++)
386 BOX2DF *box = (BOX2DF *)DatumGetPointer(in->datums[i]);
389 out->leafTupleDatums[i] = PointerGetDatum(box);
390 out->mapTuplesToNodes[i] = quadrant;
408 spgInnerConsistentIn *in = (spgInnerConsistentIn *)PG_GETARG_POINTER(0);
409 spgInnerConsistentOut *out = (spgInnerConsistentOut *)PG_GETARG_POINTER(1);
411 MemoryContext old_ctx;
419 out->nNodes = in->nNodes;
420 out->nodeNumbers = (
int *)palloc(
sizeof(
int) * in->nNodes);
421 for (i = 0; i < in->nNodes; i++)
422 out->nodeNumbers[i] = i;
431 if (in->traversalValue)
432 rect_box = in->traversalValue;
436 centroid = (BOX2DF *)DatumGetPointer(in->prefixDatum);
440 out->nodeNumbers = (
int *)palloc(
sizeof(
int) * in->nNodes);
441 out->traversalValues = (
void **)palloc(
sizeof(
void *) * in->nNodes);
448 old_ctx = MemoryContextSwitchTo(in->traversalMemoryContext);
450 for (quadrant = 0; quadrant < in->nNodes; quadrant++)
455 for (i = 0; i < in->nkeys; i++)
457 StrategyNumber strategy = in->scankeys[i].sk_strategy;
459 Datum query = in->scankeys[i].sk_argument;
460 BOX2DF query_gbox_index;
463 if (DatumGetPointer(query) == NULL)
465 POSTGIS_DEBUG(4,
"[SPGIST] null query pointer (!?!), returning false");
466 PG_RETURN_BOOL(
false);
471 POSTGIS_DEBUG(4,
"[SPGIST] null query_gbox_index!");
472 PG_RETURN_BOOL(
false);
477 case RTOverlapStrategyNumber:
478 case RTContainedByStrategyNumber:
479 case RTOldContainedByStrategyNumber:
480 flag =
overlap4D(next_rect_box, &query_gbox_index);
483 case RTContainsStrategyNumber:
484 case RTSameStrategyNumber:
485 flag =
contain4D(next_rect_box, &query_gbox_index);
488 case RTLeftStrategyNumber:
489 flag = !
overRight4D(next_rect_box, &query_gbox_index);
492 case RTOverLeftStrategyNumber:
493 flag = !
right4D(next_rect_box, &query_gbox_index);
496 case RTRightStrategyNumber:
497 flag = !
overLeft4D(next_rect_box, &query_gbox_index);
500 case RTOverRightStrategyNumber:
501 flag = !
left4D(next_rect_box, &query_gbox_index);
504 case RTAboveStrategyNumber:
505 flag = !
overBelow4D(next_rect_box, &query_gbox_index);
508 case RTOverAboveStrategyNumber:
509 flag = !
below4D(next_rect_box, &query_gbox_index);
512 case RTBelowStrategyNumber:
513 flag = !
overAbove4D(next_rect_box, &query_gbox_index);
516 case RTOverBelowStrategyNumber:
517 flag = !
above4D(next_rect_box, &query_gbox_index);
521 elog(ERROR,
"unrecognized strategy: %d", strategy);
531 out->traversalValues[out->nNodes] = next_rect_box;
532 out->nodeNumbers[out->nNodes] = quadrant;
541 pfree(next_rect_box);
546 MemoryContextSwitchTo(old_ctx);
558 spgLeafConsistentIn *in = (spgLeafConsistentIn *)PG_GETARG_POINTER(0);
559 spgLeafConsistentOut *out = (spgLeafConsistentOut *)PG_GETARG_POINTER(1);
560 BOX2DF *key = (BOX2DF *)DatumGetPointer(in->leafDatum);
565 if (DatumGetPointer(key) == NULL)
567 POSTGIS_DEBUG(4,
"[SPGIST] null index entry, returning false");
568 PG_RETURN_BOOL(
false);
572 out->recheck =
false;
575 out->leafValue = in->leafDatum;
578 for (i = 0; i < in->nkeys; i++)
580 StrategyNumber strategy = in->scankeys[i].sk_strategy;
581 Datum query = in->scankeys[i].sk_argument;
582 BOX2DF query_gbox_index;
585 if (DatumGetPointer(query) == NULL)
587 POSTGIS_DEBUG(4,
"[SPGIST] null query pointer (!?!), returning false");
588 PG_RETURN_BOOL(
false);
593 POSTGIS_DEBUG(4,
"[SPGIST] null query_gbox_index!");
594 PG_RETURN_BOOL(
false);
599 case RTOverlapStrategyNumber:
603 case RTContainsStrategyNumber:
604 case RTOldContainsStrategyNumber:
608 case RTContainedByStrategyNumber:
609 case RTOldContainedByStrategyNumber:
613 case RTSameStrategyNumber:
617 case RTLeftStrategyNumber:
621 case RTOverLeftStrategyNumber:
625 case RTRightStrategyNumber:
629 case RTOverRightStrategyNumber:
633 case RTAboveStrategyNumber:
637 case RTOverAboveStrategyNumber:
641 case RTBelowStrategyNumber:
645 case RTOverBelowStrategyNumber:
650 elog(ERROR,
"unrecognized strategy: %d", strategy);
658 PG_RETURN_BOOL(flag);
665 Datum gsdatum = PG_GETARG_DATUM(0);
666 BOX2DF *bbox_out = palloc(
sizeof(BOX2DF));
669 POSTGIS_DEBUG(4,
"[SPGIST] 'compress' function called");
679 POSTGIS_DEBUG(4,
"[SPGIST] empty geometry!");
680 PG_RETURN_POINTER(bbox_out);
684 if ((!isfinite(bbox_out->xmax) || !isfinite(bbox_out->xmin)) ||
685 (!isfinite(bbox_out->ymax) || !isfinite(bbox_out->ymin)))
689 POSTGIS_DEBUG(4,
"[SPGIST] infinite geometry!");
690 PG_RETURN_POINTER(bbox_out);
697 POSTGIS_DEBUG(4,
"[SPGIST] 'compress' function complete");
698 PG_RETURN_POINTER(bbox_out);
bool box2df_left(const BOX2DF *a, const BOX2DF *b)
void box2df_set_empty(BOX2DF *a)
bool box2df_equals(const BOX2DF *a, const BOX2DF *b)
bool box2df_contains(const BOX2DF *a, const BOX2DF *b)
bool box2df_right(const BOX2DF *a, const BOX2DF *b)
bool box2df_overlaps(const BOX2DF *a, const BOX2DF *b)
void box2df_set_finite(BOX2DF *a)
bool box2df_above(const BOX2DF *a, const BOX2DF *b)
bool box2df_overbelow(const BOX2DF *a, const BOX2DF *b)
bool box2df_overright(const BOX2DF *a, const BOX2DF *b)
int gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
Peak into a GSERIALIZED datum to find the bounding box.
bool box2df_overabove(const BOX2DF *a, const BOX2DF *b)
void box2df_validate(BOX2DF *b)
bool box2df_below(const BOX2DF *a, const BOX2DF *b)
bool box2df_overleft(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_spgist_compress_2d(PG_FUNCTION_ARGS)
Datum gserialized_spgist_choose_2d(PG_FUNCTION_ARGS)
static bool right4D(RectBox *rect_box, BOX2DF *query)
static bool overRight4D(RectBox *rect_box, BOX2DF *query)
static bool overlap4D(RectBox *rect_box, BOX2DF *query)
static bool overAbove4D(RectBox *rect_box, BOX2DF *query)
static bool above4D(RectBox *rect_box, BOX2DF *query)
static int compareDoubles(const void *a, const void *b)
Datum gserialized_spgist_config_2d(PG_FUNCTION_ARGS)
static uint8 getQuadrant4D(BOX2DF *centroid, BOX2DF *inBox)
static RectBox * nextRectBox(RectBox *rect_box, BOX2DF *centroid, uint8 quadrant)
PG_FUNCTION_INFO_V1(gserialized_spgist_config_2d)
static RectBox * initRectBox(void)
static bool contain4D(RectBox *rect_box, BOX2DF *query)
static bool left4D(RectBox *rect_box, BOX2DF *query)
Datum gserialized_spgist_picksplit_2d(PG_FUNCTION_ARGS)
Datum gserialized_spgist_leaf_consistent_2d(PG_FUNCTION_ARGS)
static bool below4D(RectBox *rect_box, BOX2DF *query)
static bool overBelow4D(RectBox *rect_box, BOX2DF *query)
static bool overLeft4D(RectBox *rect_box, BOX2DF *query)
Datum gserialized_spgist_inner_consistent_2d(PG_FUNCTION_ARGS)
This library is the generic geometry handling section of PostGIS.
Datum centroid(PG_FUNCTION_ARGS)