42 #include "access/gist.h"
43 #include "access/itup.h"
44 #include "access/skey.h"
46 #include "../postgis_config.h"
49 #include "lwgeom_pg.h"
50 #include "gserialized_gist.h"
59 #define LIMIT_RATIO 0.1
64 #if POSTGIS_DEBUG_LEVEL > 0
65 static int g2d_counter_leaf = 0;
66 static int g2d_counter_internal = 0;
122 return pstrdup(
"<NULLPTR>");
125 sprintf(rv,
"BOX2DF(%.12g %.12g, %.12g %.12g)", a->xmin, a->ymin, a->xmax, a->ymax);
132 BOX2DF *c = (BOX2DF*)palloc(
sizeof(BOX2DF));
133 memcpy((
void*)c, (
void*)b,
sizeof(BOX2DF));
134 POSTGIS_DEBUGF(5,
"copied box2df (%p) to box2df (%p)", b, c);
148 a->xmin = a->xmax = a->ymin = a->ymax =
NAN;
154 if ( ! isfinite(a->xmax) )
156 if ( ! isfinite(a->ymax) )
158 if ( ! isfinite(a->ymin) )
159 a->ymin = -1*FLT_MAX;
160 if ( ! isfinite(a->xmin) )
161 a->xmin = -1*FLT_MAX;
171 if (b_union->xmin > b_new->xmin || isnan(b_union->xmin))
172 b_union->xmin = b_new->xmin;
173 if (b_union->ymin > b_new->ymin || isnan(b_union->ymin))
174 b_union->ymin = b_new->ymin;
176 if (b_union->xmax < b_new->xmax || isnan(b_union->xmax))
177 b_union->xmax = b_new->xmax;
178 if (b_union->ymax < b_new->ymax || isnan(b_union->ymax))
179 b_union->ymax = b_new->ymax;
199 memset(box, 0,
sizeof(
GBOX));
219 if ( b->xmax < b->xmin )
225 if ( b->ymax < b->ymin )
239 if ( (a->xmin > b->xmax) || (b->xmin > a->xmax) ||
240 (a->ymin > b->ymax) || (b->ymin > a->ymax) )
257 if ( (a->xmin > b->xmin) || (a->xmax < b->xmax) ||
258 (a->ymin > b->ymin) || (a->ymax < b->ymax) )
275 if ( (a->xmin < b->xmin) || (a->xmax > b->xmax) ||
276 (a->ymin < b->ymin) || (a->ymax > b->ymax) )
294 else if ((a->xmin == b->xmin) && (a->xmax == b->xmax) && (a->ymin == b->ymin) && (a->ymax == b->ymax))
306 return a->xmax <= b->xmax;
315 return a->xmax < b->xmin;
324 return a->xmin > b->xmax;
333 return a->xmin >= b->xmin;
342 return a->ymax <= b->ymax;
351 return a->ymax < b->ymin;
360 return a->ymin > b->ymax;
369 return a->ymin >= b->ymin;
378 double a_x = (a->xmax + a->xmin) / 2.0;
379 double a_y = (a->ymax + a->ymin) / 2.0;
380 double b_x = (b->xmax + b->xmin) / 2.0;
381 double b_y = (b->ymax + b->ymin) / 2.0;
384 return sqrt((a_x - b_x) * (a_x - b_x) + (a_y - b_y) * (a_y - b_y));
388 static inline double pt_distance(
double ax,
double ay,
double bx,
double by)
390 return sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
405 return pt_distance(a->xmax, a->ymin, b->xmin, b->ymax);
407 return pt_distance(a->xmax, a->ymax, b->xmin, b->ymin);
409 return (
double)b->xmin - (double)a->xmax;
414 return pt_distance(a->xmin, a->ymin, b->xmax, b->ymax);
416 return pt_distance(a->xmin, a->ymax, b->xmax, b->ymin);
418 return (
double)a->xmin - (double)b->xmax;
423 return pt_distance(a->xmax, a->ymin, b->xmin, b->ymax);
425 return pt_distance(a->xmin, a->ymin, b->xmax, b->ymax);
427 return (
double)a->ymin - (double)b->ymax;
432 return pt_distance(a->xmax, a->ymax, b->xmin, b->ymin);
434 return pt_distance(a->xmin, a->ymax, b->xmax, b->ymin);
436 return (
double)b->ymin - (double)a->ymax;
455 POSTGIS_DEBUG(4,
"entered function");
469 POSTGIS_DEBUGF(4,
"got flags %d", gpart->
gflags);
478 POSTGIS_DEBUG(4,
"copying box out of serialization");
479 memcpy(box2df, f,
sizeof(BOX2DF));
495 POSTGIS_DEBUG(4,
"could not calculate bbox");
513 BOX2DF b1, b2, *br1=NULL, *br2=NULL;
514 POSTGIS_DEBUG(3,
"entered function");
519 if ( predicate(br1, br2) )
530 BOX2DF b2, *br2=NULL;
531 POSTGIS_DEBUG(3,
"entered function");
535 if ( predicate(br1, br2) )
550 POSTGIS_DEBUG(3,
"entered function");
552 PG_RETURN_BOOL(
true);
554 PG_RETURN_BOOL(
false);
560 if (
box2df_contains((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
561 PG_RETURN_BOOL(
true);
563 PG_RETURN_BOOL(
false);
569 POSTGIS_DEBUG(3,
"entered function");
571 PG_RETURN_BOOL(
true);
573 PG_RETURN_BOOL(
false);
579 if (
box2df_within((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
580 PG_RETURN_BOOL(
true);
582 PG_RETURN_BOOL(
false);
588 POSTGIS_DEBUG(3,
"entered function");
590 PG_RETURN_BOOL(
true);
592 PG_RETURN_BOOL(
false);
598 if (
box2df_overlaps((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
599 PG_RETURN_BOOL(
true);
601 PG_RETURN_BOOL(
false);
612 Datum gs1 = PG_GETARG_DATUM(0);
613 Datum gs2 = PG_GETARG_DATUM(1);
615 POSTGIS_DEBUG(3,
"entered function");
625 PG_RETURN_FLOAT8(FLT_MAX);
632 Datum gs1 = PG_GETARG_DATUM(0);
633 Datum gs2 = PG_GETARG_DATUM(1);
635 POSTGIS_DEBUG(3,
"entered function");
645 PG_RETURN_FLOAT8(FLT_MAX);
652 PG_RETURN_BOOL(
true);
654 PG_RETURN_BOOL(
false);
660 POSTGIS_DEBUG(3,
"entered function");
662 PG_RETURN_BOOL(
true);
664 PG_RETURN_BOOL(
false);
670 POSTGIS_DEBUG(3,
"entered function");
672 PG_RETURN_BOOL(
true);
674 PG_RETURN_BOOL(
false);
681 PG_RETURN_BOOL(
true);
683 PG_RETURN_BOOL(
false);
690 PG_RETURN_BOOL(
true);
692 PG_RETURN_BOOL(
false);
699 PG_RETURN_BOOL(
true);
701 PG_RETURN_BOOL(
false);
708 PG_RETURN_BOOL(
true);
710 PG_RETURN_BOOL(
false);
717 PG_RETURN_BOOL(
true);
719 PG_RETURN_BOOL(
false);
726 PG_RETURN_BOOL(
true);
728 PG_RETURN_BOOL(
false);
735 PG_RETURN_BOOL(
true);
737 PG_RETURN_BOOL(
false);
744 PG_RETURN_BOOL(
true);
746 PG_RETURN_BOOL(
false);
753 PG_RETURN_BOOL(
true);
755 PG_RETURN_BOOL(
false);
772 GISTENTRY *entry_in = (GISTENTRY*)PG_GETARG_POINTER(0);
773 GISTENTRY *entry_out = NULL;
777 POSTGIS_DEBUG(4,
"[GIST] 'compress' function called");
783 if ( ! entry_in->leafkey )
785 POSTGIS_DEBUG(4,
"[GIST] non-leafkey entry, returning input unaltered");
786 PG_RETURN_POINTER(entry_in);
789 POSTGIS_DEBUG(4,
"[GIST] processing leafkey input");
790 entry_out = palloc(
sizeof(GISTENTRY));
796 if ( DatumGetPointer(entry_in->key) == NULL )
798 POSTGIS_DEBUG(4,
"[GIST] leafkey is null");
799 gistentryinit(*entry_out, (Datum) 0, entry_in->rel,
800 entry_in->page, entry_in->offset,
false);
801 POSTGIS_DEBUG(4,
"[GIST] returning copy of input");
802 PG_RETURN_POINTER(entry_out);
812 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
813 entry_in->rel, entry_in->page, entry_in->offset,
false);
815 POSTGIS_DEBUG(4,
"[GIST] empty geometry!");
816 PG_RETURN_POINTER(entry_out);
819 POSTGIS_DEBUGF(4,
"[GIST] got entry_in->key: %s",
box2df_to_string(&bbox_out));
822 if ( ! isfinite(bbox_out.xmax) || ! isfinite(bbox_out.xmin) ||
823 ! isfinite(bbox_out.ymax) || ! isfinite(bbox_out.ymin) )
826 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
827 entry_in->rel, entry_in->page, entry_in->offset,
false);
829 POSTGIS_DEBUG(4,
"[GIST] infinite geometry!");
830 PG_RETURN_POINTER(entry_out);
837 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
838 entry_in->rel, entry_in->page, entry_in->offset,
false);
841 POSTGIS_DEBUG(4,
"[GIST] 'compress' function complete");
842 PG_RETURN_POINTER(entry_out);
853 POSTGIS_DEBUG(5,
"[GIST] 'decompress' function called");
855 PG_RETURN_POINTER(PG_GETARG_POINTER(0));
867 POSTGIS_DEBUGF(4,
"[GIST] leaf consistent, strategy [%d], count[%i]",
868 strategy, g2d_counter_leaf++);
874 case RTOverlapStrategyNumber:
877 case RTSameStrategyNumber:
880 case RTContainsStrategyNumber:
881 case RTOldContainsStrategyNumber:
884 case RTContainedByStrategyNumber:
885 case RTOldContainedByStrategyNumber:
890 case RTAboveStrategyNumber:
893 case RTBelowStrategyNumber:
896 case RTRightStrategyNumber:
899 case RTLeftStrategyNumber:
904 case RTOverAboveStrategyNumber:
907 case RTOverBelowStrategyNumber:
910 case RTOverRightStrategyNumber:
913 case RTOverLeftStrategyNumber:
931 POSTGIS_DEBUGF(4,
"[GIST] internal consistent, strategy [%d], count[%i], query[%s], key[%s]",
938 case RTOverlapStrategyNumber:
941 case RTSameStrategyNumber:
942 case RTContainsStrategyNumber:
943 case RTOldContainsStrategyNumber:
946 case RTContainedByStrategyNumber:
947 case RTOldContainedByStrategyNumber:
952 case RTAboveStrategyNumber:
955 case RTBelowStrategyNumber:
958 case RTRightStrategyNumber:
961 case RTLeftStrategyNumber:
966 case RTOverAboveStrategyNumber:
969 case RTOverBelowStrategyNumber:
972 case RTOverRightStrategyNumber:
975 case RTOverLeftStrategyNumber:
993 GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
994 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
996 BOX2DF query_gbox_index;
1000 bool *recheck = (
bool *) PG_GETARG_POINTER(4);
1007 POSTGIS_DEBUG(4,
"[GIST] 'consistent' function called");
1010 if ( DatumGetPointer(PG_GETARG_DATUM(1)) == NULL )
1012 POSTGIS_DEBUG(4,
"[GIST] null query pointer (!?!), returning false");
1013 PG_RETURN_BOOL(
false);
1017 if ( DatumGetPointer(entry->key) == NULL )
1019 POSTGIS_DEBUG(4,
"[GIST] null index entry, returning false");
1020 PG_RETURN_BOOL(
false);
1026 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1027 PG_RETURN_BOOL(
false);
1031 if (GIST_LEAF(entry))
1034 (BOX2DF*)DatumGetPointer(entry->key),
1035 &query_gbox_index, strategy);
1040 (BOX2DF*)DatumGetPointer(entry->key),
1041 &query_gbox_index, strategy);
1044 PG_RETURN_BOOL(result);
1067 GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
1070 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
1072 bool *recheck = (
bool *) PG_GETARG_POINTER(4);
1074 POSTGIS_DEBUG(4,
"[GIST] 'distance' function called");
1078 if ( strategy != 13 && strategy != 14 ) {
1079 elog(ERROR,
"unrecognized strategy number: %d", strategy);
1080 PG_RETURN_FLOAT8(FLT_MAX);
1086 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1087 PG_RETURN_FLOAT8(FLT_MAX);
1091 entry_box = (BOX2DF*)DatumGetPointer(entry->key);
1094 if ( strategy == 14 )
1099 else if ( strategy == 13 )
1106 if (GIST_LEAF(entry))
1111 elog(ERROR,
"%s: reached unreachable code", __func__);
1137 unsigned value : 31, sign : 1;
1140 unsigned value : 30, realm : 1, sign : 1;
1145 a.rbits.value = a.vbits.value >> 1;
1146 a.rbits.realm = realm;
1154 float b1xmin = b1->xmin, b1xmax = b1->xmax;
1155 float b1ymin = b1->ymin, b1ymax = b1->ymax;
1156 float b2xmin = b2->xmin, b2xmax = b2->xmax;
1157 float b2ymin = b2->ymin, b2ymax = b2->ymax;
1159 float box_union_xmin = Min(b1xmin, b2xmin), box_union_xmax = Max(b1xmax, b2xmax);
1160 float box_union_ymin = Min(b1ymin, b2ymin), box_union_ymax = Max(b1ymax, b2ymax);
1162 float b1dx = b1xmax - b1xmin, b1dy = b1ymax - b1ymin;
1163 float box_union_dx = box_union_xmax - box_union_xmin, box_union_dy = box_union_ymax - box_union_ymin;
1165 float box_union_area = box_union_dx * box_union_dy, box1area = b1dx * b1dy;
1166 float box_union_edge = box_union_dx + box_union_dy, box1edge = b1dx + b1dy;
1168 float area_extension = box_union_area - box1area;
1169 float edge_extension = box_union_edge - box1edge;
1172 if (area_extension > FLT_EPSILON)
1175 else if (edge_extension > FLT_EPSILON)
1188 GISTENTRY *origentry = (GISTENTRY*) PG_GETARG_POINTER(0);
1189 GISTENTRY *newentry = (GISTENTRY*) PG_GETARG_POINTER(1);
1190 float *result = (
float*) PG_GETARG_POINTER(2);
1193 b1 = (BOX2DF *)DatumGetPointer(origentry->key);
1194 b2 = (BOX2DF *)DatumGetPointer(newentry->key);
1205 PG_RETURN_POINTER(result);
1214 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1215 int *sizep = (
int *) PG_GETARG_POINTER(1);
1217 BOX2DF *box_cur, *box_union;
1219 POSTGIS_DEBUG(4,
"[GIST] 'union' function called");
1221 numranges = entryvec->n;
1223 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[0].key);
1227 for ( i = 1; i < numranges; i++ )
1229 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[i].key);
1233 *sizep =
sizeof(BOX2DF);
1235 POSTGIS_DEBUGF(4,
"[GIST] 'union', numranges(%i), pageunion %s", numranges,
box2df_to_string(box_union));
1237 PG_RETURN_POINTER(box_union);
1247 BOX2DF *b1 = (BOX2DF*)PG_GETARG_POINTER(0);
1248 BOX2DF *b2 = (BOX2DF*)PG_GETARG_POINTER(1);
1249 bool *result = (
bool*)PG_GETARG_POINTER(2);
1251 POSTGIS_DEBUG(4,
"[GIST] 'same' function called");
1255 PG_RETURN_POINTER(result);
1264 if (b->xmax < addon->xmax || isnan(b->xmax))
1265 b->xmax = addon->xmax;
1266 if (b->xmin > addon->xmin || isnan(b->xmin))
1267 b->xmin = addon->xmin;
1268 if (b->ymax < addon->ymax || isnan(b->ymax))
1269 b->ymax = addon->ymax;
1270 if (b->ymin > addon->ymin || isnan(b->ymin))
1271 b->ymin = addon->ymin;
1283 BOX2DF *unionL = NULL,
1287 maxoff = entryvec->n - 1;
1289 nbytes = (maxoff + 2) *
sizeof(OffsetNumber);
1290 v->spl_left = (OffsetNumber *) palloc(nbytes);
1291 v->spl_right = (OffsetNumber *) palloc(nbytes);
1292 v->spl_nleft = v->spl_nright = 0;
1294 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1296 BOX2DF *
cur = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1298 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
1300 v->spl_left[v->spl_nleft] = i;
1303 unionL = (BOX2DF *) palloc(
sizeof(BOX2DF));
1313 v->spl_right[v->spl_nright] = i;
1316 unionR = (BOX2DF *) palloc(
sizeof(BOX2DF));
1326 if (v->spl_ldatum_exists)
1327 adjustBox(unionL, (BOX2DF *) DatumGetPointer(v->spl_ldatum));
1328 v->spl_ldatum = BoxPGetDatum(unionL);
1330 if (v->spl_rdatum_exists)
1331 adjustBox(unionR, (BOX2DF *) DatumGetPointer(v->spl_rdatum));
1332 v->spl_rdatum = BoxPGetDatum(unionR);
1334 v->spl_ldatum_exists = v->spl_rdatum_exists =
false;
1397 else if (isnan(lower2))
1403 if (lower1 < lower2)
1405 else if (lower1 > lower2)
1429 else if (isnan(upper2))
1435 if (upper1 < upper2)
1437 else if (upper1 > upper2)
1461 float rightLower,
int minLeftCount,
1462 float leftUpper,
int maxLeftCount)
1470 POSTGIS_DEBUGF(5,
"consider split: dimNum = %d, rightLower = %f, "
1471 "minLeftCount = %d, leftUpper = %f, maxLeftCount = %d ",
1472 dimNum, rightLower, minLeftCount, leftUpper, maxLeftCount);
1480 leftCount = minLeftCount;
1484 if (maxLeftCount <= context->entriesCount / 2)
1485 leftCount = maxLeftCount;
1495 ratio = ((float4) Min(leftCount, rightCount)) /
1500 bool selectthis =
false;
1514 overlap = (leftUpper - rightLower) / range;
1519 else if (context->
dim == dimNum)
1525 if (overlap < context->overlap ||
1526 (overlap == context->
overlap && ratio > context->
ratio))
1549 (range > context->
range &&
1557 context->
first =
false;
1558 context->
ratio = ratio;
1559 context->
range = range;
1563 context->
dim = dimNum;
1564 POSTGIS_DEBUG(5,
"split selected");
1578 if (delta1 < delta2)
1580 else if (delta1 > delta2)
1615 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1616 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1630 POSTGIS_DEBUG(3,
"[GIST] 'picksplit' entered");
1634 maxoff = entryvec->n - 1;
1635 nentries = context.
entriesCount = maxoff - FirstOffsetNumber + 1;
1644 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1646 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1647 if (i == FirstOffsetNumber)
1659 context.
first =
true;
1660 for (dim = 0; dim < 2; dim++)
1668 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1670 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1673 intervalsLower[i - FirstOffsetNumber].
lower = box->xmin;
1674 intervalsLower[i - FirstOffsetNumber].
upper = box->xmax;
1678 intervalsLower[i - FirstOffsetNumber].
lower = box->ymin;
1679 intervalsLower[i - FirstOffsetNumber].
upper = box->ymax;
1687 memcpy(intervalsUpper, intervalsLower,
1730 rightLower = intervalsLower[i1].
lower;
1731 leftUpper = intervalsUpper[i2].
lower;
1737 while (i1 < nentries && (rightLower == intervalsLower[i1].lower ||
1738 isnan(intervalsLower[i1].lower)))
1740 leftUpper = Max(leftUpper, intervalsLower[i1].upper);
1745 rightLower = intervalsLower[i1].
lower;
1751 while (i2 < nentries && intervalsUpper[i2].upper <= leftUpper)
1766 rightLower = intervalsLower[i1].
upper;
1767 leftUpper = intervalsUpper[i2].
upper;
1773 while (i2 >= 0 && (leftUpper == intervalsUpper[i2].upper ||
1774 isnan(intervalsUpper[i2].upper)))
1776 rightLower = Min(rightLower, intervalsUpper[i2].lower);
1781 leftUpper = intervalsUpper[i2].
upper;
1787 while (i1 >= 0 && intervalsLower[i1].lower >= rightLower)
1794 rightLower, i1 + 1, leftUpper, i2 + 1);
1803 POSTGIS_DEBUG(4,
"no acceptable splits, trivial split");
1805 PG_RETURN_POINTER(v);
1816 POSTGIS_DEBUGF(4,
"split direction: %d", context.
dim);
1819 v->spl_left = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
1820 v->spl_right = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
1825 leftBox = palloc0(
sizeof(BOX2DF));
1826 rightBox = palloc0(
sizeof(BOX2DF));
1832 commonEntriesCount = 0;
1836 #define PLACE_LEFT(box, off) \
1838 if (v->spl_nleft > 0) \
1839 adjustBox(leftBox, box); \
1841 *leftBox = *(box); \
1842 v->spl_left[v->spl_nleft++] = off; \
1845 #define PLACE_RIGHT(box, off) \
1847 if (v->spl_nright > 0) \
1848 adjustBox(rightBox, box); \
1850 *rightBox = *(box); \
1851 v->spl_right[v->spl_nright++] = off; \
1858 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1866 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1867 if (context.
dim == 0)
1878 if (upper <= context.
leftUpper || isnan(upper))
1881 if (lower >= context.
rightLower || isnan(lower))
1884 commonEntries[commonEntriesCount++].
index = i;
1912 if (commonEntriesCount > 0)
1924 for (i = 0; i < commonEntriesCount; i++)
1926 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
1927 commonEntries[i].
index].key);
1940 for (i = 0; i < commonEntriesCount; i++)
1942 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
1943 commonEntries[i].
index].key);
1949 if (v->spl_nleft + (commonEntriesCount - i) <= m)
1951 else if (v->spl_nright + (commonEntriesCount - i) <= m)
1963 v->spl_ldatum = PointerGetDatum(leftBox);
1964 v->spl_rdatum = PointerGetDatum(rightBox);
1966 POSTGIS_DEBUG(4,
"[GIST] 'picksplit' completed");
1968 PG_RETURN_POINTER(v);
1978 ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1979 errmsg(
"function box2df_in not implemented")));
1980 PG_RETURN_POINTER(NULL);
1986 BOX2DF *box = (BOX2DF *) PG_GETARG_POINTER(0);
1988 PG_RETURN_CSTRING(result);
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
int gserialized_has_bbox(const GSERIALIZED *g)
Check if a GSERIALIZED has a bounding box without deserializing first.
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.
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)
Peak into a GSERIALIZED datum to find the bounding box.
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)
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 POSTGIS_FREE_IF_COPY_P(ptrsrc, ptrori)
static double distance(double x1, double y1, double x2, double y2)