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>
107 double x = *(
double *)a;
108 double y = *(
double *)b;
112 return (
x >
y) ? 1 : -1;
158 float infinity = FLT_MAX;
160 rect_box->
left.xmin = -infinity;
161 rect_box->
left.xmax = infinity;
163 rect_box->
left.ymin = -infinity;
164 rect_box->
left.ymax = infinity;
166 rect_box->
right.xmin = -infinity;
167 rect_box->
right.xmax = infinity;
169 rect_box->
right.ymin = -infinity;
170 rect_box->
right.ymax = infinity;
187 memcpy(next_rect_box, rect_box,
sizeof(
RectBox));
209 return next_rect_box;
216 return (rect_box->
left.xmin <= query->xmax && rect_box->
right.xmax >= query->xmin) &&
217 (rect_box->
left.ymin <= query->ymax && rect_box->
right.ymax >= query->ymin);
224 return (rect_box->
right.xmax >= query->xmax && rect_box->
left.xmin <= query->xmin) &&
225 (rect_box->
right.ymax >= query->ymax && rect_box->
left.ymin <= query->ymin);
232 return rect_box->
right.xmax <= query->xmin;
239 return rect_box->
right.xmax <= query->xmax;
246 return rect_box->
left.xmin >= query->xmax;
253 return rect_box->
left.xmin >= query->xmin;
260 return rect_box->
right.ymax <= query->ymin;
267 return rect_box->
right.ymax <= query->ymax;
274 return rect_box->
left.ymin >= query->ymax;
281 return rect_box->
left.ymin >= query->ymin;
292 spgConfigOut *
cfg = (spgConfigOut *)PG_GETARG_POINTER(1);
293 Oid boxoid = InvalidOid;
295 postgis_initialize_cache(fcinfo);
296 boxoid = postgis_oid(BOX2DFOID);
298 cfg->prefixType = boxoid;
299 cfg->labelType = VOIDOID;
300 cfg->leafType = boxoid;
301 cfg->canReturnData =
false;
302 cfg->longValuesOK =
false;
315 spgChooseIn *in = (spgChooseIn *)PG_GETARG_POINTER(0);
316 spgChooseOut *out = (spgChooseOut *)PG_GETARG_POINTER(1);
317 BOX2DF *
centroid = (BOX2DF *)DatumGetPointer(in->prefixDatum), *box = (BOX2DF *)DatumGetPointer(in->leafDatum);
319 out->resultType = spgMatchNode;
320 out->result.matchNode.restDatum = PointerGetDatum(box);
339 spgPickSplitIn *in = (spgPickSplitIn *)PG_GETARG_POINTER(0);
340 spgPickSplitOut *out = (spgPickSplitOut *)PG_GETARG_POINTER(1);
343 double *lowXs = palloc(
sizeof(
double) * in->nTuples);
344 double *highXs = palloc(
sizeof(
double) * in->nTuples);
345 double *lowYs = palloc(
sizeof(
double) * in->nTuples);
346 double *highYs = palloc(
sizeof(
double) * in->nTuples);
349 for (i = 0; i < in->nTuples; i++)
351 BOX2DF *box = (BOX2DF *)DatumGetPointer(in->datums[i]);
353 lowXs[i] = (double)box->xmin;
354 highXs[i] = (
double)box->xmax;
355 lowYs[i] = (double)box->ymin;
356 highYs[i] = (
double)box->ymax;
364 median = in->nTuples / 2;
368 centroid->xmin = (float)lowXs[median];
369 centroid->xmax = (float)highXs[median];
370 centroid->ymin = (float)lowYs[median];
371 centroid->ymax = (float)highYs[median];
374 out->hasPrefix =
true;
375 out->prefixDatum = BoxPGetDatum(
centroid);
378 out->nodeLabels = NULL;
380 out->mapTuplesToNodes = palloc(
sizeof(
int) * in->nTuples);
381 out->leafTupleDatums = palloc(
sizeof(Datum) * in->nTuples);
386 for (i = 0; i < in->nTuples; i++)
388 BOX2DF *box = (BOX2DF *)DatumGetPointer(in->datums[i]);
391 out->leafTupleDatums[i] = PointerGetDatum(box);
392 out->mapTuplesToNodes[i] = quadrant;
410 spgInnerConsistentIn *in = (spgInnerConsistentIn *)PG_GETARG_POINTER(0);
411 spgInnerConsistentOut *out = (spgInnerConsistentOut *)PG_GETARG_POINTER(1);
413 MemoryContext old_ctx;
421 out->nNodes = in->nNodes;
422 out->nodeNumbers = (
int *)palloc(
sizeof(
int) * in->nNodes);
423 for (i = 0; i < in->nNodes; i++)
424 out->nodeNumbers[i] = i;
433 if (in->traversalValue)
434 rect_box = in->traversalValue;
438 centroid = (BOX2DF *)DatumGetPointer(in->prefixDatum);
442 out->nodeNumbers = (
int *)palloc(
sizeof(
int) * in->nNodes);
443 out->traversalValues = (
void **)palloc(
sizeof(
void *) * in->nNodes);
450 old_ctx = MemoryContextSwitchTo(in->traversalMemoryContext);
452 for (quadrant = 0; quadrant < in->nNodes; quadrant++)
457 for (i = 0; i < in->nkeys; i++)
459 StrategyNumber strategy = in->scankeys[i].sk_strategy;
461 Datum query = in->scankeys[i].sk_argument;
462 BOX2DF query_gbox_index;
465 if (DatumGetPointer(query) == NULL)
467 POSTGIS_DEBUG(4,
"[SPGIST] null query pointer (!?!), returning false");
468 PG_RETURN_BOOL(
false);
473 POSTGIS_DEBUG(4,
"[SPGIST] null query_gbox_index!");
474 PG_RETURN_BOOL(
false);
479 case RTOverlapStrategyNumber:
480 case RTContainedByStrategyNumber:
481 case RTOldContainedByStrategyNumber:
482 flag =
overlap4D(next_rect_box, &query_gbox_index);
485 case RTContainsStrategyNumber:
486 case RTSameStrategyNumber:
487 flag =
contain4D(next_rect_box, &query_gbox_index);
490 case RTLeftStrategyNumber:
491 flag = !
overRight4D(next_rect_box, &query_gbox_index);
494 case RTOverLeftStrategyNumber:
495 flag = !
right4D(next_rect_box, &query_gbox_index);
498 case RTRightStrategyNumber:
499 flag = !
overLeft4D(next_rect_box, &query_gbox_index);
502 case RTOverRightStrategyNumber:
503 flag = !
left4D(next_rect_box, &query_gbox_index);
506 case RTAboveStrategyNumber:
507 flag = !
overBelow4D(next_rect_box, &query_gbox_index);
510 case RTOverAboveStrategyNumber:
511 flag = !
below4D(next_rect_box, &query_gbox_index);
514 case RTBelowStrategyNumber:
515 flag = !
overAbove4D(next_rect_box, &query_gbox_index);
518 case RTOverBelowStrategyNumber:
519 flag = !
above4D(next_rect_box, &query_gbox_index);
523 elog(ERROR,
"unrecognized strategy: %d", strategy);
533 out->traversalValues[out->nNodes] = next_rect_box;
534 out->nodeNumbers[out->nNodes] = quadrant;
543 pfree(next_rect_box);
548 MemoryContextSwitchTo(old_ctx);
560 spgLeafConsistentIn *in = (spgLeafConsistentIn *)PG_GETARG_POINTER(0);
561 spgLeafConsistentOut *out = (spgLeafConsistentOut *)PG_GETARG_POINTER(1);
562 BOX2DF *key = (BOX2DF *)DatumGetPointer(in->leafDatum);
567 if (DatumGetPointer(key) == NULL)
569 POSTGIS_DEBUG(4,
"[SPGIST] null index entry, returning false");
570 PG_RETURN_BOOL(
false);
574 out->recheck =
false;
577 out->leafValue = in->leafDatum;
580 for (i = 0; i < in->nkeys; i++)
582 StrategyNumber strategy = in->scankeys[i].sk_strategy;
583 Datum query = in->scankeys[i].sk_argument;
584 BOX2DF query_gbox_index;
587 if (DatumGetPointer(query) == NULL)
589 POSTGIS_DEBUG(4,
"[SPGIST] null query pointer (!?!), returning false");
590 PG_RETURN_BOOL(
false);
595 POSTGIS_DEBUG(4,
"[SPGIST] null query_gbox_index!");
596 PG_RETURN_BOOL(
false);
601 case RTOverlapStrategyNumber:
605 case RTContainsStrategyNumber:
606 case RTOldContainsStrategyNumber:
610 case RTContainedByStrategyNumber:
611 case RTOldContainedByStrategyNumber:
615 case RTSameStrategyNumber:
619 case RTLeftStrategyNumber:
623 case RTOverLeftStrategyNumber:
627 case RTRightStrategyNumber:
631 case RTOverRightStrategyNumber:
635 case RTAboveStrategyNumber:
639 case RTOverAboveStrategyNumber:
643 case RTBelowStrategyNumber:
647 case RTOverBelowStrategyNumber:
652 elog(ERROR,
"unrecognized strategy: %d", strategy);
660 PG_RETURN_BOOL(flag);
667 Datum gsdatum = PG_GETARG_DATUM(0);
668 BOX2DF *bbox_out = palloc(
sizeof(BOX2DF));
671 POSTGIS_DEBUG(4,
"[SPGIST] 'compress' function called");
681 POSTGIS_DEBUG(4,
"[SPGIST] empty geometry!");
682 PG_RETURN_POINTER(bbox_out);
686 if ((!isfinite(bbox_out->xmax) || !isfinite(bbox_out->xmin)) ||
687 (!isfinite(bbox_out->ymax) || !isfinite(bbox_out->ymin)))
691 POSTGIS_DEBUG(4,
"[SPGIST] infinite geometry!");
692 PG_RETURN_POINTER(bbox_out);
699 POSTGIS_DEBUG(4,
"[SPGIST] 'compress' function complete");
700 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)