43 #include "access/gist.h" 44 #include "access/itup.h" 45 #include "access/skey.h" 47 #include "../postgis_config.h" 50 #include "lwgeom_pg.h" 51 #include "gserialized_gist.h" 55 # ifdef HAVE_GNU_ISFINITE 58 # define isfinite finite 68 #define LIMIT_RATIO 0.1 74 #define KOROTKOV_SPLIT 1 79 #if POSTGIS_DEBUG_LEVEL > 0 80 static int g2d_counter_leaf = 0;
81 static int g2d_counter_internal = 0;
120 #if POSTGIS_PGSQL_VERSION > 94 140 return pstrdup(
"<NULLPTR>");
143 sprintf(rv,
"BOX2DF(%.12g %.12g, %.12g %.12g)", a->xmin, a->ymin, a->xmax, a->ymax);
150 BOX2DF *c = (BOX2DF*)palloc(
sizeof(BOX2DF));
151 memcpy((
void*)c, (
void*)b,
sizeof(BOX2DF));
152 POSTGIS_DEBUGF(5,
"copied box2df (%p) to box2df (%p)", b, c);
165 if (b_union->xmin > b_new->xmin || isnan(b_union->xmin))
166 b_union->xmin = b_new->xmin;
167 if (b_union->ymin > b_new->ymin || isnan(b_union->ymin))
168 b_union->ymin = b_new->ymin;
170 if (b_union->xmax < b_new->xmax || isnan(b_union->xmax))
171 b_union->xmax = b_new->xmax;
172 if (b_union->ymax < b_new->ymax || isnan(b_union->ymax))
173 b_union->ymax = b_new->ymax;
179 #if KOROTKOV_SPLIT < 1 180 static bool box2df_intersection(
const BOX2DF *a,
const BOX2DF *b, BOX2DF *n)
184 if( a == NULL || b == NULL || n == NULL )
187 n->xmax = Min(a->xmax, b->xmax);
188 n->ymax = Min(a->ymax, b->ymax);
189 n->xmin = Max(a->xmin, b->xmin);
190 n->ymin = Max(a->ymin, b->ymin);
194 if ( (n->xmax < n->xmin) || (n->ymax < n->ymin) )
208 if ( (a->xmax <= a->xmin) || (a->ymax <= a->ymin) )
210 result = (float) 0.0;
214 result = (((double) a->xmax)-((double) a->xmin)) * (((
double) a->ymax)-((
double) a->ymin));
225 return ((a->xmax) - (a->xmin)) + ((a->ymax) - (a->ymin));
232 POSTGIS_DEBUG(5,
"entered function");
234 if ( a == NULL && b == NULL )
236 elog(ERROR,
"box2df_union_size received two null arguments");
246 result = ((double)Max(a->xmax,b->xmax) - (double)Min(a->xmin,b->xmin)) *
247 ((
double)Max(a->ymax,b->ymax) - (double)Min(a->ymin,b->ymin));
259 POSTGIS_DEBUG(5,
"entered function");
261 if ( a == NULL && b == NULL )
263 elog(ERROR,
"box2df_union_edge received two null arguments");
273 result = (Max(a->xmax,b->xmax) - Min(a->xmin,b->xmin)) +
274 (Max(a->ymax,b->ymax) - Min(a->ymin,b->ymin));
301 if ( b->xmax < b->xmin )
307 if ( b->ymax < b->ymin )
318 if ( ! a || ! b )
return FALSE;
320 if ( (a->xmin > b->xmax) || (b->xmin > a->xmax) ||
321 (a->ymin > b->ymax) || (b->ymin > a->ymax) )
331 if ( ! a || ! b )
return FALSE;
333 if ( (a->xmin > b->xmin) || (a->xmax < b->xmax) ||
334 (a->ymin > b->ymin) || (a->ymax < b->ymax) )
344 if ( ! a || ! b )
return FALSE;
346 POSTGIS_DEBUG(5,
"entered function");
353 if ( (a->xmin != b->xmin) || (a->xmax != b->xmax) ||
354 (a->ymin != b->ymin) || (a->ymax != b->ymax) )
359 }
else if ( a || b ) {
370 if ( ! a || ! b )
return FALSE;
373 return a->xmax <= b->xmax;
378 if ( ! a || ! b )
return FALSE;
381 return a->xmax < b->xmin;
386 if ( ! a || ! b )
return FALSE;
389 return a->xmin > b->xmax;
394 if ( ! a || ! b )
return FALSE;
397 return a->xmin >= b->xmin;
402 if ( ! a || ! b )
return FALSE;
405 return a->ymax <= b->ymax;
410 if ( ! a || ! b )
return FALSE;
413 return a->ymax < b->ymin;
418 if ( ! a || ! b )
return FALSE;
421 return a->ymin > b->ymax;
426 if ( ! a || ! b )
return FALSE;
429 return a->ymin >= b->ymin;
438 double a_x = (a->xmax + a->xmin) / 2.0;
439 double a_y = (a->ymax + a->ymin) / 2.0;
440 double b_x = (b->xmax + b->xmin) / 2.0;
441 double b_y = (b->ymax + b->ymin) / 2.0;
444 return sqrt((a_x - b_x) * (a_x - b_x) + (a_y - b_y) * (a_y - b_y));
447 #if POSTGIS_PGSQL_VERSION < 95 452 static double box2df_distance_node_centroid(
const BOX2DF *node,
const BOX2DF *query)
459 q.xmin = q.xmax = (query->xmin + query->xmax) / 2.0;
460 q.ymin = q.ymax = (query->ymin + query->ymax) / 2.0;
469 if ( qx >= node->xmin && qx <= node->xmax )
471 if( qy > node->ymax )
473 else if ( qy < node->ymin )
478 else if ( qy >= node->ymin && qy <= node->ymax )
480 if ( qx > node->xmax )
482 else if ( qx < node->xmin )
490 if ( qx < node->xmin && qy < node->ymin )
492 d = (node->xmin - qx) * (node->xmin - qx) +
493 (node->ymin - qy) * (node->ymin - qy);
496 else if ( qx < node->xmin && qy > node->ymax )
498 d = (node->xmin - qx) * (node->xmin - qx) +
499 (node->ymax - qy) * (node->ymax - qy);
502 else if ( qx > node->xmax && qy > node->ymax )
504 d = (node->xmax - qx) * (node->xmax - qx) +
505 (node->ymax - qy) * (node->ymax - qy);
508 else if ( qx > node->xmin && qy < node->ymin )
510 d = (node->xmax - qx) * (node->xmax - qx) +
511 (node->ymin - qy) * (node->ymin - qy);
516 elog(ERROR,
"%s: reached unreachable code", __func__);
525 static inline double pt_distance(
double ax,
double ay,
double bx,
double by)
527 return sqrt((ax - bx) * (ax - bx) + (ay - by) * (ay - by));
542 return pt_distance(a->xmax, a->ymin, b->xmin, b->ymax);
544 return pt_distance(a->xmax, a->ymax, b->xmin, b->ymin);
546 return (
double)b->xmin - (double)a->xmax;
551 return pt_distance(a->xmin, a->ymin, b->xmax, b->ymax);
553 return pt_distance(a->xmin, a->ymax, b->xmax, b->ymin);
555 return (
double)a->xmin - (double)b->xmax;
560 return pt_distance(a->xmax, a->ymin, b->xmin, b->ymax);
562 return pt_distance(a->xmin, a->ymin, b->xmax, b->ymax);
564 return (
double)a->ymin - (double)b->ymax;
569 return pt_distance(a->xmax, a->ymax, b->xmin, b->ymin);
571 return pt_distance(a->xmin, a->ymax, b->xmax, b->ymin);
573 return (
double)b->ymin - (double)a->ymax;
593 POSTGIS_DEBUG(4,
"entered function");
599 if (VARATT_IS_EXTENDED(gsdatum))
601 gpart = (
GSERIALIZED*)PG_DETOAST_DATUM_SLICE(gsdatum, 0, 8 +
sizeof(BOX2DF));
608 flags = gpart->
flags;
610 POSTGIS_DEBUGF(4,
"got flags %d", gpart->
flags);
616 POSTGIS_DEBUG(4,
"copying box out of serialization");
617 memcpy(box2df, gpart->
data,
sizeof(BOX2DF));
630 POSTGIS_DEBUG(4,
"could not calculate bbox, returning failure");
631 POSTGIS_FREE_IF_COPY_P(gpart, gsdatum);
632 POSTGIS_FREE_IF_COPY_P(g, gsdatum);
635 POSTGIS_FREE_IF_COPY_P(g, gsdatum);
639 POSTGIS_FREE_IF_COPY_P(gpart, gsdatum);
657 BOX2DF b1, b2, *br1=NULL, *br2=NULL;
658 POSTGIS_DEBUG(3,
"entered function");
663 if ( predicate(br1, br2) )
671 #if POSTGIS_PGSQL_VERSION > 94 675 BOX2DF b2, *br2=NULL;
676 POSTGIS_DEBUG(3,
"entered function");
680 if ( predicate(br1, br2) )
695 POSTGIS_DEBUG(3,
"entered function");
697 PG_RETURN_BOOL(
TRUE);
699 PG_RETURN_BOOL(
FALSE);
705 if (
box2df_contains((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
706 PG_RETURN_BOOL(
TRUE);
708 PG_RETURN_BOOL(
FALSE);
714 POSTGIS_DEBUG(3,
"entered function");
716 PG_RETURN_BOOL(
TRUE);
718 PG_RETURN_BOOL(
FALSE);
724 if (
box2df_within((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
725 PG_RETURN_BOOL(
TRUE);
727 PG_RETURN_BOOL(
FALSE);
733 POSTGIS_DEBUG(3,
"entered function");
735 PG_RETURN_BOOL(
TRUE);
737 PG_RETURN_BOOL(
FALSE);
743 if (
box2df_overlaps((BOX2DF *)PG_GETARG_POINTER(0), (BOX2DF *)PG_GETARG_POINTER(1)))
744 PG_RETURN_BOOL(
TRUE);
746 PG_RETURN_BOOL(
FALSE);
758 Datum gs1 = PG_GETARG_DATUM(0);
759 Datum gs2 = PG_GETARG_DATUM(1);
761 POSTGIS_DEBUG(3,
"entered function");
769 PG_RETURN_FLOAT8(distance);
771 PG_RETURN_FLOAT8(FLT_MAX);
778 Datum gs1 = PG_GETARG_DATUM(0);
779 Datum gs2 = PG_GETARG_DATUM(1);
781 POSTGIS_DEBUG(3,
"entered function");
789 PG_RETURN_FLOAT8(distance);
791 PG_RETURN_FLOAT8(FLT_MAX);
798 PG_RETURN_BOOL(
TRUE);
800 PG_RETURN_BOOL(
FALSE);
806 POSTGIS_DEBUG(3,
"entered function");
808 PG_RETURN_BOOL(
TRUE);
810 PG_RETURN_BOOL(
FALSE);
816 POSTGIS_DEBUG(3,
"entered function");
818 PG_RETURN_BOOL(
TRUE);
820 PG_RETURN_BOOL(
FALSE);
827 PG_RETURN_BOOL(
TRUE);
829 PG_RETURN_BOOL(
FALSE);
836 PG_RETURN_BOOL(
TRUE);
838 PG_RETURN_BOOL(
FALSE);
845 PG_RETURN_BOOL(
TRUE);
847 PG_RETURN_BOOL(
FALSE);
854 PG_RETURN_BOOL(
TRUE);
856 PG_RETURN_BOOL(
FALSE);
863 PG_RETURN_BOOL(
TRUE);
865 PG_RETURN_BOOL(
FALSE);
872 PG_RETURN_BOOL(
TRUE);
874 PG_RETURN_BOOL(
FALSE);
881 PG_RETURN_BOOL(
TRUE);
883 PG_RETURN_BOOL(
FALSE);
890 PG_RETURN_BOOL(
TRUE);
892 PG_RETURN_BOOL(
FALSE);
899 PG_RETURN_BOOL(
TRUE);
901 PG_RETURN_BOOL(
FALSE);
918 GISTENTRY *entry_in = (GISTENTRY*)PG_GETARG_POINTER(0);
919 GISTENTRY *entry_out = NULL;
923 POSTGIS_DEBUG(4,
"[GIST] 'compress' function called");
929 if ( ! entry_in->leafkey )
931 POSTGIS_DEBUG(4,
"[GIST] non-leafkey entry, returning input unaltered");
932 PG_RETURN_POINTER(entry_in);
935 POSTGIS_DEBUG(4,
"[GIST] processing leafkey input");
936 entry_out = palloc(
sizeof(GISTENTRY));
942 if ( DatumGetPointer(entry_in->key) == NULL )
944 POSTGIS_DEBUG(4,
"[GIST] leafkey is null");
945 gistentryinit(*entry_out, (Datum) 0, entry_in->rel,
946 entry_in->page, entry_in->offset,
FALSE);
947 POSTGIS_DEBUG(4,
"[GIST] returning copy of input");
948 PG_RETURN_POINTER(entry_out);
957 POSTGIS_DEBUG(4,
"[GIST] empty geometry!");
958 PG_RETURN_POINTER(entry_in);
961 POSTGIS_DEBUGF(4,
"[GIST] got entry_in->key: %s",
box2df_to_string(&bbox_out));
964 if ( ! isfinite(bbox_out.xmax) || ! isfinite(bbox_out.xmin) ||
965 ! isfinite(bbox_out.ymax) || ! isfinite(bbox_out.ymin) )
967 POSTGIS_DEBUG(4,
"[GIST] infinite geometry!");
968 PG_RETURN_POINTER(entry_in);
975 gistentryinit(*entry_out, PointerGetDatum(
box2df_copy(&bbox_out)),
976 entry_in->rel, entry_in->page, entry_in->offset,
FALSE);
979 POSTGIS_DEBUG(4,
"[GIST] 'compress' function complete");
980 PG_RETURN_POINTER(entry_out);
991 POSTGIS_DEBUG(5,
"[GIST] 'decompress' function called");
993 PG_RETURN_POINTER(PG_GETARG_POINTER(0));
1005 POSTGIS_DEBUGF(4,
"[GIST] leaf consistent, strategy [%d], count[%i]",
1006 strategy, g2d_counter_leaf++);
1012 case RTOverlapStrategyNumber:
1015 case RTSameStrategyNumber:
1018 case RTContainsStrategyNumber:
1019 case RTOldContainsStrategyNumber:
1022 case RTContainedByStrategyNumber:
1023 case RTOldContainedByStrategyNumber:
1028 case RTAboveStrategyNumber:
1031 case RTBelowStrategyNumber:
1034 case RTRightStrategyNumber:
1037 case RTLeftStrategyNumber:
1042 case RTOverAboveStrategyNumber:
1045 case RTOverBelowStrategyNumber:
1048 case RTOverRightStrategyNumber:
1051 case RTOverLeftStrategyNumber:
1069 POSTGIS_DEBUGF(4,
"[GIST] internal consistent, strategy [%d], count[%i], query[%s], key[%s]",
1076 case RTOverlapStrategyNumber:
1079 case RTSameStrategyNumber:
1080 case RTContainsStrategyNumber:
1081 case RTOldContainsStrategyNumber:
1084 case RTContainedByStrategyNumber:
1085 case RTOldContainedByStrategyNumber:
1090 case RTAboveStrategyNumber:
1093 case RTBelowStrategyNumber:
1096 case RTRightStrategyNumber:
1099 case RTLeftStrategyNumber:
1104 case RTOverAboveStrategyNumber:
1107 case RTOverBelowStrategyNumber:
1110 case RTOverRightStrategyNumber:
1113 case RTOverLeftStrategyNumber:
1131 GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
1132 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
1134 BOX2DF query_gbox_index;
1138 bool *recheck = (
bool *) PG_GETARG_POINTER(4);
1145 POSTGIS_DEBUG(4,
"[GIST] 'consistent' function called");
1148 if ( DatumGetPointer(PG_GETARG_DATUM(1)) == NULL )
1150 POSTGIS_DEBUG(4,
"[GIST] null query pointer (!?!), returning false");
1151 PG_RETURN_BOOL(
FALSE);
1155 if ( DatumGetPointer(entry->key) == NULL )
1157 POSTGIS_DEBUG(4,
"[GIST] null index entry, returning false");
1158 PG_RETURN_BOOL(
FALSE);
1164 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1165 PG_RETURN_BOOL(
FALSE);
1169 if (GIST_LEAF(entry))
1172 (BOX2DF*)DatumGetPointer(entry->key),
1173 &query_gbox_index, strategy);
1178 (BOX2DF*)DatumGetPointer(entry->key),
1179 &query_gbox_index, strategy);
1182 PG_RETURN_BOOL(result);
1205 GISTENTRY *entry = (GISTENTRY*) PG_GETARG_POINTER(0);
1208 StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
1210 #if POSTGIS_PGSQL_VERSION >= 95 1211 bool *recheck = (
bool *) PG_GETARG_POINTER(4);
1214 POSTGIS_DEBUG(4,
"[GIST] 'distance' function called");
1218 if ( strategy != 13 && strategy != 14 ) {
1219 elog(ERROR,
"unrecognized strategy number: %d", strategy);
1220 PG_RETURN_FLOAT8(FLT_MAX);
1226 POSTGIS_DEBUG(4,
"[GIST] null query_gbox_index!");
1227 PG_RETURN_FLOAT8(FLT_MAX);
1231 entry_box = (BOX2DF*)DatumGetPointer(entry->key);
1233 #if POSTGIS_PGSQL_VERSION >= 95 1236 if ( strategy == 14 )
1241 else if ( strategy == 13 )
1248 if (GIST_LEAF(entry))
1253 elog(ERROR,
"%s: reached unreachable code", __func__);
1258 if ( strategy == 14 )
1261 PG_RETURN_FLOAT8(distance);
1265 if (GIST_LEAF(entry))
1273 distance = (double)box2df_distance_node_centroid(entry_box, &query_box);
1277 PG_RETURN_FLOAT8(distance);
1297 struct {
unsigned value:31, sign:1; } vbits;
1298 struct {
unsigned value:29, realm:2, sign:1; } rbits;
1302 a.rbits.value = a.vbits.value >> 2;
1303 a.rbits.realm = realm;
1315 GISTENTRY *origentry = (GISTENTRY*) PG_GETARG_POINTER(0);
1316 GISTENTRY *newentry = (GISTENTRY*) PG_GETARG_POINTER(1);
1317 float *result = (
float*) PG_GETARG_POINTER(2);
1318 BOX2DF *gbox_index_orig, *gbox_index_new;
1319 float size_union, size_orig, edge_union, edge_orig;
1321 POSTGIS_DEBUG(4,
"[GIST] 'penalty' function called");
1323 gbox_index_orig = (BOX2DF*)DatumGetPointer(origentry->key);
1324 gbox_index_new = (BOX2DF*)DatumGetPointer(newentry->key);
1327 if ( (gbox_index_orig == NULL) && (gbox_index_new == NULL) )
1329 POSTGIS_DEBUG(4,
"[GIST] both inputs NULL! returning penalty of zero");
1331 PG_RETURN_FLOAT8(*result);
1337 *result = size_union - size_orig;
1354 *result = edge_union - edge_orig;
1370 POSTGIS_DEBUGF(4,
"[GIST] 'penalty', union size (%.12f), original size (%.12f), penalty (%.12f)", size_union, size_orig, *result);
1372 PG_RETURN_POINTER(result);
1381 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1382 int *sizep = (
int *) PG_GETARG_POINTER(1);
1384 BOX2DF *box_cur, *box_union;
1386 POSTGIS_DEBUG(4,
"[GIST] 'union' function called");
1388 numranges = entryvec->n;
1390 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[0].key);
1394 for ( i = 1; i < numranges; i++ )
1396 box_cur = (BOX2DF*) DatumGetPointer(entryvec->vector[i].key);
1400 *sizep =
sizeof(BOX2DF);
1402 POSTGIS_DEBUGF(4,
"[GIST] 'union', numranges(%i), pageunion %s", numranges,
box2df_to_string(box_union));
1404 PG_RETURN_POINTER(box_union);
1414 BOX2DF *b1 = (BOX2DF*)PG_GETARG_POINTER(0);
1415 BOX2DF *b2 = (BOX2DF*)PG_GETARG_POINTER(1);
1416 bool *result = (
bool*)PG_GETARG_POINTER(2);
1418 POSTGIS_DEBUG(4,
"[GIST] 'same' function called");
1422 PG_RETURN_POINTER(result);
1425 #if KOROTKOV_SPLIT > 0 1432 if (b->xmax < addon->xmax || isnan(b->xmax))
1433 b->xmax = addon->xmax;
1434 if (b->xmin > addon->xmin || isnan(b->xmin))
1435 b->xmin = addon->xmin;
1436 if (b->ymax < addon->ymax || isnan(b->ymax))
1437 b->ymax = addon->ymax;
1438 if (b->ymin > addon->ymin || isnan(b->ymin))
1439 b->ymin = addon->ymin;
1451 BOX2DF *unionL = NULL,
1455 maxoff = entryvec->n - 1;
1457 nbytes = (maxoff + 2) *
sizeof(OffsetNumber);
1458 v->spl_left = (OffsetNumber *) palloc(nbytes);
1459 v->spl_right = (OffsetNumber *) palloc(nbytes);
1460 v->spl_nleft = v->spl_nright = 0;
1462 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1464 BOX2DF *
cur = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1466 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
1468 v->spl_left[v->spl_nleft] = i;
1471 unionL = (BOX2DF *) palloc(
sizeof(BOX2DF));
1481 v->spl_right[v->spl_nright] = i;
1484 unionR = (BOX2DF *) palloc(
sizeof(BOX2DF));
1494 if (v->spl_ldatum_exists)
1495 adjustBox(unionL, (BOX2DF *) DatumGetPointer(v->spl_ldatum));
1496 v->spl_ldatum = BoxPGetDatum(unionL);
1498 if (v->spl_rdatum_exists)
1499 adjustBox(unionR, (BOX2DF *) DatumGetPointer(v->spl_rdatum));
1500 v->spl_rdatum = BoxPGetDatum(unionR);
1502 v->spl_ldatum_exists = v->spl_rdatum_exists =
false;
1565 else if (isnan(lower2))
1571 if (lower1 < lower2)
1573 else if (lower1 > lower2)
1597 else if (isnan(upper2))
1603 if (upper1 < upper2)
1605 else if (upper1 > upper2)
1629 float rightLower,
int minLeftCount,
1630 float leftUpper,
int maxLeftCount)
1638 POSTGIS_DEBUGF(5,
"consider split: dimNum = %d, rightLower = %f, " 1639 "minLeftCount = %d, leftUpper = %f, maxLeftCount = %d ",
1640 dimNum, rightLower, minLeftCount, leftUpper, maxLeftCount);
1648 leftCount = minLeftCount;
1652 if (maxLeftCount <= context->entriesCount / 2)
1653 leftCount = maxLeftCount;
1663 ratio = ((float4) Min(leftCount, rightCount)) /
1668 bool selectthis =
false;
1682 overlap = (leftUpper - rightLower) / range;
1687 else if (context->
dim == dimNum)
1693 if (overlap < context->overlap ||
1694 (overlap == context->
overlap && ratio > context->
ratio))
1717 (range > context->
range &&
1725 context->
first =
false;
1726 context->
ratio = ratio;
1727 context->
range = range;
1731 context->
dim = dimNum;
1732 POSTGIS_DEBUG(5,
"split selected");
1746 union_width = Max(original->xmax, new->xmax) -
1747 Min(original->xmin, new->xmin);
1748 union_height = Max(original->ymax, new->ymax) -
1749 Min(original->ymin, new->ymin);
1750 return union_width * union_height - (original->xmax - original->xmin) *
1751 (original->ymax - original->ymin);
1763 if (delta1 < delta2)
1765 else if (delta1 > delta2)
1800 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
1801 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
1815 POSTGIS_DEBUG(3,
"[GIST] 'picksplit' entered");
1819 maxoff = entryvec->n - 1;
1820 nentries = context.
entriesCount = maxoff - FirstOffsetNumber + 1;
1829 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1831 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1832 if (i == FirstOffsetNumber)
1844 context.
first =
true;
1845 for (dim = 0; dim < 2; dim++)
1853 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
1855 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
1858 intervalsLower[i - FirstOffsetNumber].
lower = box->xmin;
1859 intervalsLower[i - FirstOffsetNumber].
upper = box->xmax;
1863 intervalsLower[i - FirstOffsetNumber].
lower = box->ymin;
1864 intervalsLower[i - FirstOffsetNumber].
upper = box->ymax;
1872 memcpy(intervalsUpper, intervalsLower,
1915 rightLower = intervalsLower[i1].
lower;
1916 leftUpper = intervalsUpper[i2].
lower;
1922 while (i1 < nentries && (rightLower == intervalsLower[i1].lower ||
1923 isnan(intervalsLower[i1].lower)))
1925 leftUpper = Max(leftUpper, intervalsLower[i1].upper);
1930 rightLower = intervalsLower[i1].
lower;
1936 while (i2 < nentries && intervalsUpper[i2].upper <= leftUpper)
1951 rightLower = intervalsLower[i1].
upper;
1952 leftUpper = intervalsUpper[i2].
upper;
1958 while (i2 >= 0 && (leftUpper == intervalsUpper[i2].upper ||
1959 isnan(intervalsUpper[i2].upper)))
1961 rightLower = Min(rightLower, intervalsUpper[i2].lower);
1966 leftUpper = intervalsUpper[i2].
upper;
1972 while (i1 >= 0 && intervalsLower[i1].lower >= rightLower)
1979 rightLower, i1 + 1, leftUpper, i2 + 1);
1988 POSTGIS_DEBUG(4,
"no acceptable splits, trivial split");
1990 PG_RETURN_POINTER(v);
2001 POSTGIS_DEBUGF(4,
"split direction: %d", context.
dim);
2004 v->spl_left = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
2005 v->spl_right = (OffsetNumber *) palloc(nentries *
sizeof(OffsetNumber));
2010 leftBox = palloc0(
sizeof(BOX2DF));
2011 rightBox = palloc0(
sizeof(BOX2DF));
2017 commonEntriesCount = 0;
2021 #define PLACE_LEFT(box, off) \ 2023 if (v->spl_nleft > 0) \ 2024 adjustBox(leftBox, box); \ 2026 *leftBox = *(box); \ 2027 v->spl_left[v->spl_nleft++] = off; \ 2030 #define PLACE_RIGHT(box, off) \ 2032 if (v->spl_nright > 0) \ 2033 adjustBox(rightBox, box); \ 2035 *rightBox = *(box); \ 2036 v->spl_right[v->spl_nright++] = off; \ 2043 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
2051 box = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
2052 if (context.
dim == 0)
2063 if (upper <= context.
leftUpper || isnan(upper))
2066 if (lower >= context.
rightLower || isnan(lower))
2069 commonEntries[commonEntriesCount++].
index = i;
2097 if (commonEntriesCount > 0)
2109 for (i = 0; i < commonEntriesCount; i++)
2111 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
2112 commonEntries[i].
index].key);
2126 for (i = 0; i < commonEntriesCount; i++)
2128 box = (BOX2DF *) DatumGetPointer(entryvec->vector[
2129 commonEntries[i].
index].key);
2135 if (v->spl_nleft + (commonEntriesCount - i) <= m)
2137 else if (v->spl_nright + (commonEntriesCount - i) <= m)
2149 v->spl_ldatum = PointerGetDatum(leftBox);
2150 v->spl_rdatum = PointerGetDatum(rightBox);
2152 POSTGIS_DEBUG(4,
"[GIST] 'picksplit' completed");
2154 PG_RETURN_POINTER(v);
2167 compare_KB(
const void* a,
const void* b)
2169 BOX2DF *abox = ((KBsort*)a)->key;
2170 BOX2DF *bbox = ((KBsort*)b)->key;
2171 float sa = (abox->xmax - abox->xmin) * (abox->ymax - abox->ymin);
2172 float sb = (bbox->xmax - bbox->xmin) * (bbox->ymax - bbox->ymin);
2174 if ( sa==sb )
return 0;
2175 return ( sa>sb ) ? 1 : -1;
2186 GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
2188 GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
2190 OffsetNumber *listL, *listR, *listB, *listT;
2191 BOX2DF *unionL, *unionR, *unionB, *unionT;
2192 int posL, posR, posB, posT;
2195 char direction =
' ';
2196 bool allisequal =
true;
2197 OffsetNumber maxoff;
2200 POSTGIS_DEBUG(3,
"[GIST] 'picksplit' entered");
2202 posL = posR = posB = posT = 0;
2204 maxoff = entryvec->n - 1;
2205 cur = (BOX2DF*) DatumGetPointer(entryvec->vector[FirstOffsetNumber].key);
2207 memcpy((
void *) &pageunion, (
void *) cur,
sizeof(BOX2DF));
2210 for (i = OffsetNumberNext(FirstOffsetNumber); i <= maxoff; i = OffsetNumberNext(i))
2212 cur = (BOX2DF *) DatumGetPointer(entryvec->vector[i].key);
2214 if ( allisequal ==
true && (
2215 pageunion.xmax != cur->xmax ||
2216 pageunion.ymax != cur->ymax ||
2217 pageunion.xmin != cur->xmin ||
2218 pageunion.ymin != cur->ymin
2222 if (pageunion.xmax < cur->xmax)
2223 pageunion.xmax = cur->xmax;
2224 if (pageunion.xmin > cur->xmin)
2225 pageunion.xmin = cur->xmin;
2226 if (pageunion.ymax < cur->ymax)
2227 pageunion.ymax = cur->ymax;
2228 if (pageunion.ymin > cur->ymin)
2229 pageunion.ymin = cur->ymin;
2234 nbytes = (maxoff + 2) *
sizeof(OffsetNumber);
2235 listL = (OffsetNumber *) palloc(nbytes);
2236 listR = (OffsetNumber *) palloc(nbytes);
2237 unionL = (BOX2DF *) palloc(
sizeof(BOX2DF));
2238 unionR = (BOX2DF *) palloc(
sizeof(BOX2DF));
2242 POSTGIS_DEBUG(4,
" AllIsEqual!");
2244 cur = (BOX2DF*) DatumGetPointer(entryvec->vector[OffsetNumberNext(FirstOffsetNumber)].key);
2247 if (memcmp((
void *) cur, (
void *) &pageunion,
sizeof(BOX2DF)) == 0)
2249 v->spl_left = listL;
2250 v->spl_right = listR;
2251 v->spl_nleft = v->spl_nright = 0;
2252 memcpy((
void *) unionL, (
void *) &pageunion,
sizeof(BOX2DF));
2253 memcpy((
void *) unionR, (
void *) &pageunion,
sizeof(BOX2DF));
2255 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
2257 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
2259 v->spl_left[v->spl_nleft] = i;
2264 v->spl_right[v->spl_nright] = i;
2268 v->spl_ldatum = PointerGetDatum(unionL);
2269 v->spl_rdatum = PointerGetDatum(unionR);
2271 PG_RETURN_POINTER(v);
2275 listB = (OffsetNumber *) palloc(nbytes);
2276 listT = (OffsetNumber *) palloc(nbytes);
2277 unionB = (BOX2DF *) palloc(
sizeof(BOX2DF));
2278 unionT = (BOX2DF *) palloc(
sizeof(BOX2DF));
2280 #define ADDLIST( list, unionD, pos, num ) do { \ 2282 if ( unionD->xmax < cur->xmax ) unionD->xmax = cur->xmax; \ 2283 if ( unionD->xmin > cur->xmin ) unionD->xmin = cur->xmin; \ 2284 if ( unionD->ymax < cur->ymax ) unionD->ymax = cur->ymax; \ 2285 if ( unionD->ymin > cur->ymin ) unionD->ymin = cur->ymin; \ 2287 memcpy( (void*)unionD, (void*) cur, sizeof( BOX2DF ) ); \ 2293 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
2295 cur = (BOX2DF*) DatumGetPointer(entryvec->vector[i].key);
2297 if (cur->xmin - pageunion.xmin < pageunion.xmax - cur->xmax)
2298 ADDLIST(listL, unionL, posL,i);
2300 ADDLIST(listR, unionR, posR,i);
2301 if (cur->ymin - pageunion.ymin < pageunion.ymax - cur->ymax)
2302 ADDLIST(listB, unionB, posB,i);
2304 ADDLIST(listT, unionT, posT,i);
2313 if ( (posR==0 || posL==0) && (posT==0 || posB==0) )
2315 KBsort *arr = (KBsort*)palloc(
sizeof(KBsort) * maxoff );
2316 posL = posR = posB = posT = 0;
2317 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
2319 arr[i-1].key = (BOX2DF*) DatumGetPointer(entryvec->vector[i].key);
2322 qsort( arr, maxoff,
sizeof(KBsort), compare_KB );
2323 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
2326 if (cur->xmin - pageunion.xmin < pageunion.xmax - cur->xmax)
2327 ADDLIST(listL, unionL, posL,arr[i-1].pos);
2328 else if ( cur->xmin - pageunion.xmin == pageunion.xmax - cur->xmax )
2331 ADDLIST(listR, unionR, posR,arr[i-1].pos);
2333 ADDLIST(listL, unionL, posL,arr[i-1].pos);
2336 ADDLIST(listR, unionR, posR,arr[i-1].pos);
2338 if (cur->ymin - pageunion.ymin < pageunion.ymax - cur->ymax)
2339 ADDLIST(listB, unionB, posB,arr[i-1].pos);
2340 else if ( cur->ymin - pageunion.ymin == pageunion.ymax - cur->ymax )
2343 ADDLIST(listT, unionT, posT,arr[i-1].pos);
2345 ADDLIST(listB, unionB, posB,arr[i-1].pos);
2348 ADDLIST(listT, unionT, posT,arr[i-1].pos);
2354 if (Max(posL, posR) < Max(posB, posT))
2356 else if (Max(posL, posR) > Max(posB, posT))
2360 float sizeLR, sizeBT;
2361 BOX2DF interLR, interBT;
2363 if ( box2df_intersection(unionL, unionR, &interLR) ==
FALSE )
2368 if ( box2df_intersection(unionB, unionT, &interBT) ==
FALSE )
2373 if (sizeLR < sizeBT)
2379 POSTGIS_DEBUGF(4,
"split direction '%c'", direction);
2381 if (direction ==
'x')
2388 v->spl_left = listL;
2389 v->spl_right = listR;
2390 v->spl_nleft = posL;
2391 v->spl_nright = posR;
2392 v->spl_ldatum = PointerGetDatum(unionL);
2393 v->spl_rdatum = PointerGetDatum(unionR);
2402 v->spl_left = listB;
2403 v->spl_right = listT;
2404 v->spl_nleft = posB;
2405 v->spl_nright = posT;
2406 v->spl_ldatum = PointerGetDatum(unionB);
2407 v->spl_rdatum = PointerGetDatum(unionT);
2410 POSTGIS_DEBUG(4,
"[GIST] 'picksplit' completed");
2412 PG_RETURN_POINTER(v);
2425 ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2426 errmsg(
"function box2df_in not implemented")));
2427 PG_RETURN_POINTER(NULL);
2433 BOX2DF *box = (BOX2DF *) PG_GETARG_POINTER(0);
2435 PG_RETURN_CSTRING(result);
int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *box)
Read the bounding box off a serialization and calculate one if it is not already there.
static float non_negative(float val)
Datum gserialized_above_2d(PG_FUNCTION_ARGS)
Datum gserialized_overabove_2d(PG_FUNCTION_ARGS)
static float box2df_union_edge(const BOX2DF *a, const BOX2DF *b)
static void box2df_validate(BOX2DF *b)
Datum gserialized_gist_penalty_2d(PG_FUNCTION_ARGS)
static BOX2DF * box2df_copy(BOX2DF *b)
static bool box2df_overlaps(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_gist_compress_2d(PG_FUNCTION_ARGS)
Datum gserialized_contains_box2df_box2df_2d(PG_FUNCTION_ARGS)
static bool box2df_left(const BOX2DF *a, const BOX2DF *b)
static void fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
static bool box2df_below(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_left_2d(PG_FUNCTION_ARGS)
static bool gserialized_gist_consistent_leaf_2d(BOX2DF *key, BOX2DF *query, StrategyNumber strategy)
static void g_box_consider_split(ConsiderSplitContext *context, int dimNum, float rightLower, int minLeftCount, float leftUpper, int maxLeftCount)
static int interval_cmp_lower(const void *i1, const void *i2)
static void adjustBox(BOX2DF *b, BOX2DF *addon)
static bool box2df_right(const BOX2DF *a, const BOX2DF *b)
float next_float_down(double d)
Datum gserialized_contains_box2df_geom_2d(PG_FUNCTION_ARGS)
static bool box2df_above(const BOX2DF *a, const BOX2DF *b)
static float box2df_size(const BOX2DF *a)
bool(* box2df_predicate)(const BOX2DF *a, const BOX2DF *b)
static bool box2df_within(const BOX2DF *a, const BOX2DF *b)
float next_float_up(double d)
static int box2df_from_gbox_p(GBOX *box, BOX2DF *a)
Datum gserialized_overlaps_2d(PG_FUNCTION_ARGS)
Datum gserialized_distance_centroid_2d(PG_FUNCTION_ARGS)
Datum gserialized_within_box2df_geom_2d(PG_FUNCTION_ARGS)
Datum gserialized_overbelow_2d(PG_FUNCTION_ARGS)
void gbox_init(GBOX *gbox)
Zero out all the entries in the GBOX.
Datum gserialized_within_box2df_box2df_2d(PG_FUNCTION_ARGS)
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.
#define FLAGS_GET_BBOX(flags)
static char * box2df_to_string(const BOX2DF *a)
#define LW_TRUE
Return types for functions with status returns.
Datum gserialized_below_2d(PG_FUNCTION_ARGS)
Datum gserialized_gist_same_2d(PG_FUNCTION_ARGS)
static void box2df_merge(BOX2DF *b_union, BOX2DF *b_new)
Datum gserialized_within_2d(PG_FUNCTION_ARGS)
int gserialized_datum_get_box2df_p(Datum gsdatum, BOX2DF *box2df)
Peak into a GSERIALIZED datum to find the bounding box.
Datum gserialized_overleft_2d(PG_FUNCTION_ARGS)
Datum gserialized_gist_consistent_2d(PG_FUNCTION_ARGS)
Datum box2df_out(PG_FUNCTION_ARGS)
Datum gserialized_overlaps_box2df_box2df_2d(PG_FUNCTION_ARGS)
static float pack_float(const float value, const int realm)
Datum gserialized_same_2d(PG_FUNCTION_ARGS)
static int interval_cmp_upper(const void *i1, const void *i2)
static double pt_distance(double ax, double ay, double bx, double by)
Datum distance(PG_FUNCTION_ARGS)
static bool box2df_overright(const BOX2DF *a, const BOX2DF *b)
static int common_entry_cmp(const void *i1, const void *i2)
Datum gserialized_gist_picksplit_2d(PG_FUNCTION_ARGS)
static bool box2df_overabove(const BOX2DF *a, const BOX2DF *b)
static bool box2df_overbelow(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_gist_decompress_2d(PG_FUNCTION_ARGS)
static bool box2df_overleft(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_overright_2d(PG_FUNCTION_ARGS)
bool box2df_contains(const BOX2DF *a, const BOX2DF *b)
#define PLACE_RIGHT(box, off)
static float box2df_union_size(const BOX2DF *a, const BOX2DF *b)
static int gserialized_datum_predicate_2d(Datum gs1, Datum gs2, box2df_predicate predicate)
Support function.
static int gserialized_datum_predicate_box2df_geom_2d(const BOX2DF *br1, Datum gs2, box2df_predicate predicate)
Datum gserialized_overlaps_box2df_geom_2d(PG_FUNCTION_ARGS)
static bool box2df_equals(const BOX2DF *a, const BOX2DF *b)
Datum gserialized_right_2d(PG_FUNCTION_ARGS)
Datum box2df_in(PG_FUNCTION_ARGS)
Datum gserialized_contains_2d(PG_FUNCTION_ARGS)
Datum gserialized_gist_union_2d(PG_FUNCTION_ARGS)
Datum gserialized_gist_distance_2d(PG_FUNCTION_ARGS)
#define PLACE_LEFT(box, off)
static bool gserialized_gist_consistent_internal_2d(BOX2DF *key, BOX2DF *query, StrategyNumber strategy)
static float box_penalty(BOX2DF *original, BOX2DF *new)
Datum gserialized_distance_box_2d(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(gserialized_contains_box2df_geom_2d)
This library is the generic geometry handling section of PostGIS.
static float box2df_edge(const BOX2DF *a)