Datum spgist_geom_leaf_consistent(PG_FUNCTION_ARGS) { spgLeafConsistentIn *in = (spgLeafConsistentIn *) PG_GETARG_POINTER(0); spgLeafConsistentOut *out = (spgLeafConsistentOut *) PG_GETARG_POINTER(1); bool res; int i; BOX2DF datum; BOX2DF *datum_p = &datum; gserialized_datum_get_box2df_p(in->leafDatum, datum_p); /* all tests are exact */ out->recheck = false; /* leafDatum is what it is... */ out->leafValue = in->leafDatum; /* Perform the required comparison(s) */ res = true; for (i = 0; i < in->nkeys; i++) { BOX2DF query; BOX2DF *query_p = &query; gserialized_datum_get_box2df_p(in->scankeys[i].sk_argument, query_p); switch (in->scankeys[i].sk_strategy) { case RTLeftStrategyNumber: res = (bool) box2df_left(datum_p, query_p); break; case RTRightStrategyNumber: res = (bool) box2df_right(datum_p, query_p); break; case RTSameStrategyNumber: res = (bool) box2df_equals(datum_p, query_p); break; case RTBelowStrategyNumber: res = (bool) box2df_below(datum_p, query_p); break; case RTAboveStrategyNumber: res = (bool) box2df_above(datum_p, query_p); break; case RTContainedByStrategyNumber: res = (bool) box2df_contains(query_p, datum_p); break; default: elog(ERROR, "unrecognized strategy number: %d", in->scankeys[i].sk_strategy); break; } if (!res) break; } PG_RETURN_BOOL(res); }
/** * Calculate the box->box distance. */ static double box2df_distance(const BOX2DF *a, const BOX2DF *b) { /* Check for overlap */ if ( box2df_overlaps(a, b) ) return 0.0; if ( box2df_left(a, b) ) { if ( box2df_above(a, b) ) return pt_distance(a->xmax, a->ymin, b->xmin, b->ymax); if ( box2df_below(a, b) ) return pt_distance(a->xmax, a->ymax, b->xmin, b->ymin); else return b->xmin - a->xmax; } if ( box2df_right(a, b) ) { if ( box2df_above(a, b) ) return pt_distance(a->xmin, a->ymin, b->xmax, b->ymax); if ( box2df_below(a, b) ) return pt_distance(a->xmin, a->ymax, b->xmax, b->ymin); else return a->xmin - b->xmax; } if ( box2df_above(a, b) ) { if ( box2df_left(a, b) ) return pt_distance(a->xmax, a->ymin, b->xmin, b->ymax); if ( box2df_right(a, b) ) return pt_distance(a->xmin, a->ymin, b->xmax, b->ymax); else return a->ymin - b->ymax; } if ( box2df_below(a, b) ) { if ( box2df_left(a, b) ) return pt_distance(a->xmax, a->ymax, b->xmin, b->ymin); if ( box2df_right(a, b) ) return pt_distance(a->xmin, a->ymax, b->xmax, b->ymin); else return b->ymin - a->ymax; } return MAXFLOAT; }
static inline bool gserialized_gist_consistent_leaf_2d(BOX2DF *key, BOX2DF *query, StrategyNumber strategy) { bool retval; switch (strategy) { /* Basic overlaps */ case RTOverlapStrategyNumber: retval = (bool) box2df_overlaps(key, query); break; case RTSameStrategyNumber: retval = (bool) box2df_equals(key, query); break; case RTContainsStrategyNumber: case RTOldContainsStrategyNumber: retval = (bool) box2df_contains(key, query); break; case RTContainedByStrategyNumber: case RTOldContainedByStrategyNumber: retval = (bool) box2df_contains(query, key); break; /* To one side */ case RTAboveStrategyNumber: retval = (bool) box2df_above(key, query); break; case RTBelowStrategyNumber: retval = (bool) box2df_below(key, query); break; case RTRightStrategyNumber: retval = (bool) box2df_right(key, query); break; case RTLeftStrategyNumber: retval = (bool) box2df_left(key, query); break; /* Overlapping to one side */ case RTOverAboveStrategyNumber: retval = (bool) box2df_overabove(key, query); break; case RTOverBelowStrategyNumber: retval = (bool) box2df_overbelow(key, query); break; case RTOverRightStrategyNumber: retval = (bool) box2df_overright(key, query); break; case RTOverLeftStrategyNumber: retval = (bool) box2df_overleft(key, query); break; default: retval = FALSE; } return (retval); }
Datum spgist_geom_inner_consistent(PG_FUNCTION_ARGS) { spgInnerConsistentIn *in = (spgInnerConsistentIn *) PG_GETARG_POINTER(0); spgInnerConsistentOut *out = (spgInnerConsistentOut *) PG_GETARG_POINTER(1); BOX2DF *centroidbox_p; int which; int i; if (in->allTheSame) { /* Report that all nodes should be visited */ out->nNodes = in->nNodes; out->nodeNumbers = (int *) palloc(sizeof(int) * in->nNodes); for (i = 0; i < in->nNodes; i++) out->nodeNumbers[i] = i; PG_RETURN_VOID(); } Assert(in->hasPrefix); centroidbox_p = (BOX2DF *)in->prefixDatum; Assert(in->nNodes == 4); /* "which" is a bitmask of quadrants that satisfy all constraints */ which = (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4); for (i = 0; i < in->nkeys; i++) { BOX2DF box; BOX2DF *box_p = &box; gserialized_datum_get_box2df_p(in->scankeys[i].sk_argument, box_p); switch (in->scankeys[i].sk_strategy) { case RTLeftStrategyNumber: if (box2df_left(box_p, centroidbox_p)) which &= (1 << 3) | (1 << 4); break; case RTRightStrategyNumber: if (box2df_right(box_p, centroidbox_p)) which &= (1 << 1) | (1 << 2); break; /* case RTSameStrategyNumber: */ /* which &= (1 << getQuadrant(centroidbox_p, box_p)); */ /* break; */ case RTBelowStrategyNumber: if (box2df_below(centroidbox_p, box_p)) which &= (1 << 2) | (1 << 3); break; case RTAboveStrategyNumber: if (box2df_above(centroidbox_p, box_p)) which &= (1 << 1) | (1 << 4); break; case RTContainedByStrategyNumber: if (box2df_contains(box_p, centroidbox_p)) { /* centroid is in box, so all quadrants are OK */ } else { /* identify quadrant(s) containing all corners of box */ POINT2D p; BOX2DF b; BOX2DF *b_p = &b; int r = 0; b_p->xmin = b_p->xmax = box_p->xmin; b_p->ymin = b_p->ymax = box_p->ymin; r |= 1 << getQuadrant(centroidbox_p, b_p); b_p->xmin = b_p->xmax = box_p->xmax; b_p->ymin = b_p->ymax = box_p->ymin; r |= 1 << getQuadrant(centroidbox_p, b_p); b_p->xmin = b_p->xmax = box_p->xmax; b_p->ymin = b_p->ymax = box_p->ymax; r |= 1 << getQuadrant(centroidbox_p, b_p); b_p->xmin = b_p->xmax = box_p->xmin; b_p->ymin = b_p->ymax = box_p->ymax; r |= 1 << getQuadrant(centroidbox_p, b_p); which &= r; } break; default: elog(ERROR, "unrecognized strategy number: %d", in->scankeys[i].sk_strategy); break; } if (which == 0) break; /* no need to consider remaining conditions */ } /* We must descend into the quadrant(s) identified by which */ out->nodeNumbers = (int *) palloc(sizeof(int) * 4); out->nNodes = 0; for (i = 1; i <= 4; i++) { if (which & (1 << i)) out->nodeNumbers[out->nNodes++] = i - 1; } PG_RETURN_VOID(); }