42 #include "access/gist.h"
43 #include "access/itup.h"
44 #include "access/skey.h"
46 #include "../postgis_config.h"
50 #include "lwgeom_pg.h"
51 #include "gserialized_gist.h"
60 #define LIMIT_RATIO 0.1
65 #if POSTGIS_DEBUG_LEVEL > 0
66 static int g2d_counter_leaf = 0;
67 static int g2d_counter_internal = 0;
125 return pstrdup(
"<NULLPTR>");
143 BOX2DF *c = (BOX2DF*)palloc(
sizeof(BOX2DF));
144 memcpy((
void*)c, (
void*)b,
sizeof(BOX2DF));
145 POSTGIS_DEBUGF(5,
"copied box2df (%p) to box2df (%p)", b, c);
159 a->xmin = a->xmax = a->ymin = a->ymax =
NAN;
165 if ( ! isfinite(a->xmax) )
167 if ( ! isfinite(a->ymax) )
169 if ( ! isfinite(a->ymin) )
170 a->ymin = -1*FLT_MAX;
171 if ( ! isfinite(a->xmin) )
172 a->xmin = -1*FLT_MAX;
182 if (b_union->xmin > b_new->xmin || isnan(b_union->xmin))
183 b_union->xmin = b_new->xmin;
184 if (b_union->ymin > b_new->ymin || isnan(b_union->ymin))
185 b_union->ymin = b_new->ymin;
187 if (b_union->xmax < b_new->xmax || isnan(b_union->xmax))
188 b_union->xmax = b_new->xmax;
189 if (b_union->ymax < b_new->ymax || isnan(b_union->ymax))
190 b_union->ymax = b_new->ymax;
210 memset(box, 0,
sizeof(
GBOX));
230 if ( b->xmax < b->xmin )
236 if ( b->ymax < b->ymin )
250 if ( (a->xmin > b->xmax) || (b->xmin > a->xmax) ||
251 (a->ymin > b->ymax) || (b->ymin > a->ymax) )
268 if ( (a->xmin > b->xmin) || (a->xmax < b->xmax) ||
269 (a->ymin > b->ymin) || (a->ymax < b->ymax) )
286 if ( (a->xmin < b->xmin) || (a->xmax > b->xmax) ||
287 (a->ymin < b->ymin) || (a->ymax > b->ymax) )
305 else if ((a->xmin == b->xmin) && (a->xmax == b->xmax) && (a->ymin == b->ymin) && (a->ymax == b->ymax))
317 return a->xmax <= b->xmax;
326 return a->xmax < b->xmin;
335 return a->xmin > b->xmax;
344 return a->xmin >= b->xmin;
353 return a->ymax <= b->ymax;
362 return a->ymax < b->ymin;
371 return a->ymin > b->ymax;
380 return a->ymin >= b->ymin;
389 double a_x = (a->xmax + a->xmin) / 2.0;
390 double a_y = (a->ymax + a->ymin) / 2.0;
391 double b_x = (b->xmax + b->xmin) / 2.0;
392 double b_y = (b->ymax + b->ymin) / 2.0;
395 return sqrt((a_x - b_x) * (a_x - b_x) + (a_y - b_y) * (a_y - b_y));
399 static inline double pt_distance(
double ax,
double ay,
double bx,
double by)
401 return sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
416 return pt_distance(a->xmax, a->ymin, b->xmin, b->ymax);
418 return pt_distance(a->xmax, a->ymax, b->xmin, b->ymin);
420 return (
double)b->xmin - (double)a->xmax;
425 return pt_distance(a->xmin, a->ymin, b->xmax, b->ymax);
427 return pt_distance(a->xmin, a->ymax, b->xmax, b->ymin);
429 return (
double)a->xmin - (double)b->xmax;
434 return pt_distance(a->xmax, a->ymin, b->xmin, b->ymax);
436 return pt_distance(a->xmin, a->ymin, b->xmax, b->ymax);
438 return (
double)a->ymin - (double)b->ymax;
443 return pt_distance(a->xmax, a->ymax, b->xmin, b->ymin);
445 return pt_distance(a->xmin, a->ymax, b->xmax, b->ymin);
447 return (
double)b->ymin - (double)a->ymax;
463 int need_detoast = PG_GSERIALIZED_DATUM_NEEDS_DETOAST((
struct varlena *)gsdatum);
515 int need_detoast = PG_GSERIALIZED_DATUM_NEEDS_DETOAST((
struct varlena *)gsdatum);
529 memcpy(box2df, f,
sizeof(BOX2DF));
560 BOX2DF b1, b2, *br1=NULL, *br2=NULL;
561 POSTGIS_DEBUG(3,
"entered function");
566 if ( predicate(br1, br2) )
577 BOX2DF b2, *br2=NULL;
578 POSTGIS_DEBUG(3,
"entered function");
582 if ( predicate(br1, br2) )
597 POSTGIS_DEBUG(3,
"entered function");
599 PG_RETURN_BOOL(
true);
601 PG_RETURN_BOOL(
false);
607 if (
box2df_contains((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
608 PG_RETURN_BOOL(
true);
610 PG_RETURN_BOOL(
false);
616 POSTGIS_DEBUG(3,
"entered function");
618 PG_RETURN_BOOL(
true);
620 PG_RETURN_BOOL(
false);
626 if (
box2df_within((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
627 PG_RETURN_BOOL(
true);
629 PG_RETURN_BOOL(
false);
635 POSTGIS_DEBUG(3,
"entered function");
637 PG_RETURN_BOOL(
true);
639 PG_RETURN_BOOL(
false);
645 if (
box2df_overlaps((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
646 PG_RETURN_BOOL(
true);
648 PG_RETURN_BOOL(
false);
659 Datum gs1 = PG_GETARG_DATUM(0);
660 Datum gs2 = PG_GETARG_DATUM(1);
662 POSTGIS_DEBUG(3,
"entered function");
672 PG_RETURN_FLOAT8(FLT_MAX);
679 Datum gs1 = PG_GETARG_DATUM(0);
680 Datum gs2 = PG_GETARG_DATUM(1);
682 POSTGIS_DEBUG(3,
"entered function");
692 PG_RETURN_FLOAT8(FLT_MAX);
699 PG_RETURN_BOOL(
true);
701 PG_RETURN_BOOL(
false);
707 POSTGIS_DEBUG(3,
"entered function");
709 PG_RETURN_BOOL(
true);
711 PG_RETURN_BOOL(
false);
717 POSTGIS_DEBUG(3,
"entered function");
719 PG_RETURN_BOOL(
true);
721 PG_RETURN_BOOL(
false);
728 PG_RETURN_BOOL(
true);
730 PG_RETURN_BOOL(
false);
737 PG_RETURN_BOOL(
true);
739 PG_RETURN_BOOL(
false);
746 PG_RETURN_BOOL(
true);
748 PG_RETURN_BOOL(
false);
755 PG_RETURN_BOOL(
true);
757 PG_RETURN_BOOL(
false);
764 PG_RETURN_BOOL(
true);
766 PG_RETURN_BOOL(
false);
773 PG_RETURN_BOOL(
true);
775 PG_RETURN_BOOL(
false);
782 PG_RETURN_BOOL(
true);
784 PG_RETURN_BOOL(
false);
791 PG_RETURN_BOOL(
true);
793 PG_RETURN_BOOL(
false);
800 PG_RETURN_BOOL(
true);
802 PG_RETURN_BOOL(
false);
819 GISTENTRY *entry_in = (GISTENTRY*)PG_GETARG_POINTER(0);
820 GISTENTRY *entry_out = NULL;
824 POSTGIS_DEBUG(4,
"[GIST] 'compress' function called");
830 if ( ! entry_in->leafkey )
832 POSTGIS_DEBUG(4,
"[GIST] non-leafkey entry, returning input unaltered");
833 PG_RETURN_POINTER(entry_in);
836 POSTGIS_DEBUG(4,
"[GIST] processing leafkey input");
837 entry_out = palloc(
sizeof(GISTENTRY));
843 if ( DatumGetPointer(entry_in->key) == NULL )
845 POSTGIS_DEBUG(4,
"[GIST] leafkey is null");
846 gistentryinit(*entry_out, (Datum) 0, entry_in->rel,
847 entry_in->page, entry_in->offset,
false);
848 POSTGIS_DEBUG(4,
"[GIST] returning copy of input");
849 PG_RETURN_POINTER(entry_out);
859 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
860 entry_in->rel, entry_in->page, entry_in->offset,
false);
862 POSTGIS_DEBUG(4,
"[GIST] empty geometry!");
863 PG_RETURN_POINTER(entry_out);
866 POSTGIS_DEBUGF(4,
"[GIST] got entry_in->key: %s",
box2df_to_string(&bbox_out));
869 if ( ! isfinite(bbox_out.xmax) || ! isfinite(bbox_out.xmin) ||
870 ! isfinite(bbox_out.ymax) || ! isfinite(bbox_out.ymin) )
873 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
874 entry_in->rel, entry_in->page, entry_in->offset,
false);
876 POSTGIS_DEBUG(4,
"[GIST] infinite geometry!");
877 PG_RETURN_POINTER(entry_out);
884 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
885 entry_in->rel, entry_in->page, entry_in->offset,
false);
888 POSTGIS_DEBUG(4,
"[GIST] 'compress' function complete");
889 PG_RETURN_POINTER(entry_out);
900 POSTGIS_DEBUG(5,
"[GIST] 'decompress' function called");
902 PG_RETURN_POINTER(PG_GETARG_POINTER(0));
914 POSTGIS_DEBUGF(4,
"[GIST] leaf consistent, strategy [%d], count[%i]",
915 strategy, g2d_counter_leaf++);
921 case RTOverlapStrategyNumber:
924 case RTSameStrategyNumber:
927 case RTContainsStrategyNumber:
928 case RTOldContainsStrategyNumber:
931 case RTContainedByStrategyNumber:
932 case RTOldContainedByStrategyNumber:
937 case RTAboveStrategyNumber:
940 case RTBelowStrategyNumber:
943 case RTRightStrategyNumber:
946 case RTLeftStrategyNumber:
951 case RTOverAboveStrategyNumber:
954 case RTOverBelowStrategyNumber:
957 case RTOverRightStrategyNumber:
960 case RTOverLeftStrategyNumber:
978 POSTGIS_DEBUGF(4,
"[GIST] internal consistent, strategy [%d], count[%i], query[%s], key[%s]",
985 case RTOverlapStrategyNumber:
988 case RTSameStrategyNumber:
989 case RTContainsStrategyNumber:
990 case RTOldContainsStrategyNumber:
993 case RTContainedByStrategyNumber:
994 case RTOldContainedByStrategyNumber:
999 case RTAboveStrategyNumber:
1002 case RTBelowStrategyNumber:
1005 case RTRightStrategyNumber:
1008 case RTLeftStrategyNumber:
1013 case RTOverAboveStrategyNumber:
1016 case RTOverBelowStrategyNumber:
1019 case RTOverRightStrategyNumber:
1022 case RTOverLeftStrategyNumber:
1040 GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
1041 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
1043 BOX2DF query_gbox_index;
1047 bool *recheck = (
bool *) PG_GETARG_POINTER(4);
1054 POSTGIS_DEBUG(4,
"[GIST] 'consistent' function called");
1057 if ( DatumGetPointer(PG_GETARG_DATUM(1)) == NULL )
1059 POSTGIS_DEBUG(4,
"[GIST] null query pointer (!?!), returning false");
1060 PG_RETURN_BOOL(
false);
1064 if ( DatumGetPointer(entry->key) == NULL )
1066 POSTGIS_DEBUG(4,
"[GIST] null index entry, returning false");
1067 PG_RETURN_BOOL(
false);
1073 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1074 PG_RETURN_BOOL(
false);
1078 if (GIST_LEAF(entry))
1081 (BOX2DF*)DatumGetPointer(entry->key),
1082 &query_gbox_index, strategy);
1087 (BOX2DF*)DatumGetPointer(entry->key),
1088 &query_gbox_index, strategy);
1114 GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
1117 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
1119 bool *recheck = (
bool *) PG_GETARG_POINTER(4);
1121 POSTGIS_DEBUG(4,
"[GIST] 'distance' function called");
1125 if ( strategy != 13 && strategy != 14 ) {
1126 elog(ERROR,
"unrecognized strategy number: %d", strategy);
1127 PG_RETURN_FLOAT8(FLT_MAX);
1133 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1134 PG_RETURN_FLOAT8(FLT_MAX);
1138 entry_box = (BOX2DF*)DatumGetPointer(entry->key);
1141 if ( strategy == 14 )
1146 else if ( strategy == 13 )
1153 if (GIST_LEAF(entry))
1158 elog(ERROR,
"%s: reached unreachable code", __func__);
1184 unsigned value : 31, sign : 1;
1187 unsigned value : 30, realm : 1, sign : 1;
1192 a.rbits.value = a.vbits.value >> 1;
1193 a.rbits.realm = realm;
1201 float b1xmin = b1->xmin, b1xmax = b1->xmax;
1202 float b1ymin = b1->ymin, b1ymax = b1->ymax;
1203 float b2xmin = b2->xmin, b2xmax = b2->xmax;
1204 float b2ymin = b2->ymin, b2ymax = b2->ymax;
1206 float box_union_xmin = Min(b1xmin, b2xmin), box_union_xmax = Max(b1xmax, b2xmax);
1207 float box_union_ymin = Min(b1ymin, b2ymin), box_union_ymax = Max(b1ymax, b2ymax);
1209 float b1dx = b1xmax - b1xmin, b1dy = b1ymax - b1ymin;
1210 float box_union_dx = box_union_xmax - box_union_xmin, box_union_dy = box_union_ymax - box_union_ymin;
1212 float box_union_area = box_union_dx * box_union_dy, box1area = b1dx * b1dy;
1213 float box_union_edge = box_union_dx + box_union_dy, box1edge = b1dx + b1dy;
1215 float area_extension = box_union_area - box1area;
1216 float edge_extension = box_union_edge - box1edge;
1219 if (area_extension > FLT_EPSILON)
1222 else if (edge_extension > FLT_EPSILON)
1235 GISTENTRY *origentry = (GISTENTRY*) PG_GETARG_POINTER(0);
1236 GISTENTRY *newentry = (GISTENTRY*) PG_GETARG_POINTER(1);
1237 float *
result = (
float*) PG_GETARG_POINTER(2);
1240 b1 = (BOX2DF *)DatumGetPointer(origentry->key);
1241 b2 = (BOX2DF *)DatumGetPointer(newentry->key);
1252 PG_RETURN_POINTER(
result);
1261 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1262 int *sizep = (
int *) PG_GETARG_POINTER(1);
1264 BOX2DF *box_cur, *box_union;
1266 POSTGIS_DEBUG(4,
"[GIST] 'union' function called");
1268 numranges = entryvec->n;
1270 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[0].key);
1274 for ( i = 1; i < numranges; i++ )
1276 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[i].key);
1280 *sizep =
sizeof(BOX2DF);
1282 POSTGIS_DEBUGF(4,
"[GIST] 'union', numranges(%i), pageunion %s", numranges,
box2df_to_string(box_union));
1284 PG_RETURN_POINTER(box_union);
1294 BOX2DF *b1 = (BOX2DF*)PG_GETARG_POINTER(0);
1295 BOX2DF *b2 = (BOX2DF*)PG_GETARG_POINTER(1);
1296 bool *
result = (
bool*)PG_GETARG_POINTER(2);
1298 POSTGIS_DEBUG(4,
"[GIST] 'same' function called");
1302 PG_RETURN_POINTER(
result);
1311 if (b->xmax < addon->xmax || isnan(b->xmax))
1312 b->xmax = addon->xmax;
1313 if (b->xmin > addon->xmin || isnan(b->xmin))
1314 b->xmin = addon->xmin;
1315 if (b->ymax < addon->ymax || isnan(b->ymax))
1316 b->ymax = addon->ymax;
1317 if (b->ymin > addon->ymin || isnan(b->ymin))
1318 b->ymin = addon->ymin;
1330 BOX2DF *unionL = NULL,
1334 maxoff = entryvec->n - 1;
1336 nbytes = (maxoff + 2) *
sizeof(OffsetNumber);
1337 v->spl_left = (OffsetNumber *) palloc(nbytes);
1338 v->spl_right = (OffsetNumber *) palloc(nbytes);
1339 v->spl_nleft = v->spl_nright = 0;
1341 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1343 BOX2DF *
cur = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1345 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
1347 v->spl_left[v->spl_nleft] = i;
1350 unionL = (BOX2DF *) palloc(
sizeof(BOX2DF));
1360 v->spl_right[v->spl_nright] = i;
1363 unionR = (BOX2DF *) palloc(
sizeof(BOX2DF));
1373 if (v->spl_ldatum_exists)
1374 adjustBox(unionL, (BOX2DF *) DatumGetPointer(v->spl_ldatum));
1375 v->spl_ldatum = BoxPGetDatum(unionL);
1377 if (v->spl_rdatum_exists)
1378 adjustBox(unionR, (BOX2DF *) DatumGetPointer(v->spl_rdatum));
1379 v->spl_rdatum = BoxPGetDatum(unionR);
1381 v->spl_ldatum_exists = v->spl_rdatum_exists =
false;
1444 else if (isnan(lower2))
1450 if (lower1 < lower2)
1452 else if (lower1 > lower2)
1476 else if (isnan(upper2))
1482 if (upper1 < upper2)
1484 else if (upper1 > upper2)
1508 float rightLower,
int minLeftCount,
1509 float leftUpper,
int maxLeftCount)
1517 POSTGIS_DEBUGF(5,
"consider split: dimNum = %d, rightLower = %f, "
1518 "minLeftCount = %d, leftUpper = %f, maxLeftCount = %d ",
1519 dimNum, rightLower, minLeftCount, leftUpper, maxLeftCount);
1527 leftCount = minLeftCount;
1531 if (maxLeftCount <= context->entriesCount / 2)
1532 leftCount = maxLeftCount;
1542 ratio = ((float4) Min(leftCount, rightCount)) /
1547 bool selectthis =
false;
1561 overlap = (leftUpper - rightLower) / range;
1566 else if (context->
dim == dimNum)
1572 if (overlap < context->overlap ||
1573 (overlap == context->
overlap && ratio > context->
ratio))
1596 (range > context->
range &&
1604 context->
first =
false;
1605 context->
ratio = ratio;
1606 context->
range = range;
1610 context->
dim = dimNum;
1611 POSTGIS_DEBUG(5,
"split selected");
1625 if (delta1 < delta2)
1627 else if (delta1 > delta2)
1662 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1663 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1677 POSTGIS_DEBUG(3,
"[GIST] 'picksplit' entered");
1681 maxoff = entryvec->n - 1;
1682 nentries = context.
entriesCount = maxoff - FirstOffsetNumber + 1;
1691 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1693 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1694 if (i == FirstOffsetNumber)
1706 context.
first =
true;
1707 for (dim = 0; dim < 2; dim++)
1715 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1717 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1720 intervalsLower[i - FirstOffsetNumber].
lower = box->xmin;
1721 intervalsLower[i - FirstOffsetNumber].
upper = box->xmax;
1725 intervalsLower[i - FirstOffsetNumber].
lower = box->ymin;
1726 intervalsLower[i - FirstOffsetNumber].
upper = box->ymax;
1734 memcpy(intervalsUpper, intervalsLower,
1777 rightLower = intervalsLower[i1].
lower;
1778 leftUpper = intervalsUpper[i2].
lower;
1784 while (i1 < nentries && (rightLower == intervalsLower[i1].lower ||
1785 isnan(intervalsLower[i1].lower)))
1787 leftUpper = Max(leftUpper, intervalsLower[i1].upper);
1792 rightLower = intervalsLower[i1].
lower;
1798 while (i2 < nentries && intervalsUpper[i2].upper <= leftUpper)
1813 rightLower = intervalsLower[i1].
upper;
1814 leftUpper = intervalsUpper[i2].
upper;
1820 while (i2 >= 0 && (leftUpper == intervalsUpper[i2].upper ||
1821 isnan(intervalsUpper[i2].upper)))
1823 rightLower = Min(rightLower, intervalsUpper[i2].lower);
1828 leftUpper = intervalsUpper[i2].
upper;
1834 while (i1 >= 0 && intervalsLower[i1].lower >= rightLower)
1841 rightLower, i1 + 1, leftUpper, i2 + 1);
1850 POSTGIS_DEBUG(4,
"no acceptable splits, trivial split");
1852 PG_RETURN_POINTER(v);
1863 POSTGIS_DEBUGF(4,
"split direction: %d", context.
dim);
1866 v->spl_left = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
1867 v->spl_right = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
1872 leftBox = palloc0(
sizeof(BOX2DF));
1873 rightBox = palloc0(
sizeof(BOX2DF));
1879 commonEntriesCount = 0;
1883 #define PLACE_LEFT(box, off) \
1885 if (v->spl_nleft > 0) \
1886 adjustBox(leftBox, box); \
1888 *leftBox = *(box); \
1889 v->spl_left[v->spl_nleft++] = off; \
1892 #define PLACE_RIGHT(box, off) \
1894 if (v->spl_nright > 0) \
1895 adjustBox(rightBox, box); \
1897 *rightBox = *(box); \
1898 v->spl_right[v->spl_nright++] = off; \
1905 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1913 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1914 if (context.
dim == 0)
1925 if (upper <= context.
leftUpper || isnan(upper))
1928 if (lower >= context.
rightLower || isnan(lower))
1931 commonEntries[commonEntriesCount++].
index = i;
1959 if (commonEntriesCount > 0)
1971 for (i = 0; i < commonEntriesCount; i++)
1973 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
1974 commonEntries[i].
index].key);
1987 for (i = 0; i < commonEntriesCount; i++)
1989 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
1990 commonEntries[i].
index].key);
1996 if (v->spl_nleft + (commonEntriesCount - i) <= m)
1998 else if (v->spl_nright + (commonEntriesCount - i) <= m)
2010 v->spl_ldatum = PointerGetDatum(leftBox);
2011 v->spl_rdatum = PointerGetDatum(rightBox);
2013 POSTGIS_DEBUG(4,
"[GIST] 'picksplit' completed");
2015 PG_RETURN_POINTER(v);
2025 ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2026 errmsg(
"function box2df_in not implemented")));
2027 PG_RETURN_POINTER(NULL);
2033 BOX2DF *box = (BOX2DF *) PG_GETARG_POINTER(0);
2035 PG_RETURN_CSTRING(
result);
char result[OUT_DOUBLE_BUFFER_SIZE]
int gserialized_has_bbox(const GSERIALIZED *g)
Check if a GSERIALIZED has a bounding box without deserializing first.
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *gbox)
Read the box from the GSERIALIZED or calculate it if necessary.
const float * gserialized_get_float_box_p(const GSERIALIZED *g, size_t *ndims)
Access to the float bounding box, if there is one.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
uint32_t gserialized_max_header_size(void)
Returns the size in bytes to read from toast to get the basic information from a geometry: GSERIALIZE...
lwflags_t gserialized_get_lwflags(const GSERIALIZED *g)
Read the flags from a GSERIALIZED and return a standard lwflag integer.
bool box2df_left(const BOX2DF *a, const BOX2DF *b)
static char * box2df_to_string(const BOX2DF *a)
void box2df_merge(BOX2DF *b_union, BOX2DF *b_new)
static void fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
Datum gserialized_overbelow_2d(PG_FUNCTION_ARGS)
void box2df_set_empty(BOX2DF *a)
Datum gserialized_gist_same_2d(PG_FUNCTION_ARGS)
Datum gserialized_contains_box2df_geom_2d(PG_FUNCTION_ARGS)
bool box2df_is_empty(const BOX2DF *a)
static int gserialized_datum_predicate_2d(Datum gs1, Datum gs2, box2df_predicate predicate)
Support function.
Datum gserialized_within_2d(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(gserialized_contains_box2df_geom_2d)
Datum box2df_out(PG_FUNCTION_ARGS)
Datum gserialized_within_box2df_geom_2d(PG_FUNCTION_ARGS)
Datum gserialized_gist_penalty_2d(PG_FUNCTION_ARGS)
Datum gserialized_left_2d(PG_FUNCTION_ARGS)
Datum gserialized_contains_2d(PG_FUNCTION_ARGS)
Datum gserialized_gist_consistent_2d(PG_FUNCTION_ARGS)
static int interval_cmp_upper(const void *i1, const void *i2)
Datum gserialized_distance_box_2d(PG_FUNCTION_ARGS)
bool box2df_equals(const BOX2DF *a, const BOX2DF *b)
bool box2df_contains(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_gist_union_2d(PG_FUNCTION_ARGS)
#define PLACE_RIGHT(box, off)
Datum gserialized_gist_compress_2d(PG_FUNCTION_ARGS)
Datum gserialized_distance_centroid_2d(PG_FUNCTION_ARGS)
Datum gserialized_contains_box2df_box2df_2d(PG_FUNCTION_ARGS)
Datum gserialized_overlaps_2d(PG_FUNCTION_ARGS)
Datum gserialized_overlaps_box2df_geom_2d(PG_FUNCTION_ARGS)
Datum gserialized_within_box2df_box2df_2d(PG_FUNCTION_ARGS)
bool box2df_right(const BOX2DF *a, const BOX2DF *b)
bool box2df_overlaps(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_overleft_2d(PG_FUNCTION_ARGS)
void box2df_set_finite(BOX2DF *a)
static bool gserialized_gist_consistent_internal_2d(BOX2DF *key, BOX2DF *query, StrategyNumber strategy)
Datum gserialized_overlaps_box2df_box2df_2d(PG_FUNCTION_ARGS)
Datum gserialized_gist_distance_2d(PG_FUNCTION_ARGS)
Datum gserialized_overright_2d(PG_FUNCTION_ARGS)
static bool box2df_within(const BOX2DF *a, const BOX2DF *b)
bool box2df_above(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_right_2d(PG_FUNCTION_ARGS)
bool box2df_overbelow(const BOX2DF *a, const BOX2DF *b)
bool(* box2df_predicate)(const BOX2DF *a, const BOX2DF *b)
static double box2df_distance(const BOX2DF *a, const BOX2DF *b)
Calculate the box->box distance.
static double box2df_distance_leaf_centroid(const BOX2DF *a, const BOX2DF *b)
Calculate the centroid->centroid distance between the boxes.
Datum gserialized_below_2d(PG_FUNCTION_ARGS)
Datum gserialized_overabove_2d(PG_FUNCTION_ARGS)
static void g_box_consider_split(ConsiderSplitContext *context, int dimNum, float rightLower, int minLeftCount, float leftUpper, int maxLeftCount)
int box2df_to_gbox_p(BOX2DF *a, GBOX *box)
static int interval_cmp_lower(const void *i1, const void *i2)
bool box2df_overright(const BOX2DF *a, const BOX2DF *b)
static double pt_distance(double ax, double ay, double bx, double by)
static float pack_float(const float value, const uint8_t realm)
static int common_entry_cmp(const void *i1, const void *i2)
Datum gserialized_gist_decompress_2d(PG_FUNCTION_ARGS)
int gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
int gserialized_datum_get_internals_p(Datum gsdatum, GBOX *gbox, lwflags_t *flags, uint8_t *type, int32_t *srid)
Peak into a GSERIALIZED datum to find its bounding box and some other metadata.
int gserialized_datum_get_gbox_p(Datum gsdatum, GBOX *gbox)
Given a GSERIALIZED datum, as quickly as possible (peaking into the top of the memory) return the gbo...
static int box2df_from_gbox_p(GBOX *box, BOX2DF *a)
bool box2df_overabove(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_gist_picksplit_2d(PG_FUNCTION_ARGS)
#define PLACE_LEFT(box, off)
void box2df_validate(BOX2DF *b)
static float box2df_penalty(const BOX2DF *b1, const BOX2DF *b2)
bool box2df_below(const BOX2DF *a, const BOX2DF *b)
static bool gserialized_gist_consistent_leaf_2d(BOX2DF *key, BOX2DF *query, StrategyNumber strategy)
bool box2df_overleft(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_above_2d(PG_FUNCTION_ARGS)
static int gserialized_datum_predicate_box2df_geom_2d(const BOX2DF *br1, Datum gs2, box2df_predicate predicate)
BOX2DF * box2df_copy(BOX2DF *b)
Datum gserialized_same_2d(PG_FUNCTION_ARGS)
Datum box2df_in(PG_FUNCTION_ARGS)
static void adjustBox(BOX2DF *b, BOX2DF *addon)
static float non_negative(float val)
#define LWSIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
float next_float_up(double d)
#define LW_TRUE
Return types for functions with status returns.
float next_float_down(double d)
This library is the generic geometry handling section of PostGIS.
#define OUT_MAX_BYTES_DOUBLE
int lwprint_double(double d, int maxdd, char *buf)
#define POSTGIS_FREE_IF_COPY_P(ptrsrc, ptrori)
static double distance(double x1, double y1, double x2, double y2)