diff --git a/doc/indices.sgm b/doc/indices.sgm
index c27ef5e..ea1086d 100644
--- a/doc/indices.sgm
+++ b/doc/indices.sgm
@@ -69,9 +69,9 @@
- GiST index can be used also for fast finding points closest to the given one
- when ordering by an expression with the <-> operator
- is used, as shown in an example below.
+ GiST index can be also used for quickly finding the points closest to the given one
+ when ordering by an expression with the <-> operator,
+ as shown in an example below.
BRIN indexing supports just spherical points (spoint)
@@ -112,6 +112,7 @@
+
diff --git a/pgs_gist.sql.in b/pgs_gist.sql.in
index 3ac9971..fcd4f11 100644
--- a/pgs_gist.sql.in
+++ b/pgs_gist.sql.in
@@ -117,7 +117,7 @@ CREATE OPERATOR CLASS spoint
OPERATOR 14 @ (spoint, spoly),
OPERATOR 15 @ (spoint, sellipse),
OPERATOR 16 @ (spoint, sbox),
- OPERATOR 17 <-> (spoint, spoint) FOR ORDER BY float_ops,
+ OPERATOR 17 <-> (spoint, spoint) FOR ORDER BY float_ops,
OPERATOR 37 <@ (spoint, scircle),
OPERATOR 38 <@ (spoint, sline),
OPERATOR 39 <@ (spoint, spath),
diff --git a/src/gist.c b/src/gist.c
index f373448..0fef2ac 100644
--- a/src/gist.c
+++ b/src/gist.c
@@ -511,7 +511,7 @@ g_spoint_consistent(PG_FUNCTION_ARGS)
SCK_INTERLEAVE(SELLIPSE, sphereellipse_gen_key, 0);
break;
case 42:
- SCK_INTERLEAVE(SBOX, spherebox_gen_key , 0);
+ SCK_INTERLEAVE(SBOX, spherebox_gen_key, 0);
break;
}
@@ -682,8 +682,11 @@ g_spoint3_consistent(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(false);
}
-static double distance_vector_point_3d (Vector3D* v, double x, double y, double z) {
- return acos ( (v->x * x + v->y * y + v->z * z) / sqrt( x*x + y*y + z*z ) ); // as v has length=1 by design
+static double
+distance_vector_point_3d(Vector3D *v, double x, double y, double z)
+{
+ /* as v has length = 1 by design */
+ return acos((v->x * x + v->y * y + v->z * z) / sqrt(x * x + y * y + z * z));
}
Datum
@@ -1683,121 +1686,218 @@ g_spoint_distance(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
- Box3D* box = (Box3D *) DatumGetPointer(entry->key);
+ Box3D *box = (Box3D *) DatumGetPointer(entry->key);
double retval;
SPoint *point = (SPoint *) PG_GETARG_POINTER(1);
- Vector3D v_point, v_low, v_high;
+ Vector3D v_point,
+ v_low,
+ v_high;
switch (strategy)
{
case 17:
- // Prepare data for calculation
+ /* Prepare data for calculation */
spoint_vector3d(&v_point, point);
- v_low.x = (double)box->low.coord[0] / MAXCVALUE;
- v_low.y = (double)box->low.coord[1] / MAXCVALUE;
- v_low.z = (double)box->low.coord[2] / MAXCVALUE;
- v_high.x = (double)box->high.coord[0] / MAXCVALUE;
- v_high.y = (double)box->high.coord[1] / MAXCVALUE;
- v_high.z = (double)box->high.coord[2] / MAXCVALUE;
- // a box splits space into 27 subspaces (6+12+8+1) with different distance calculation
- if(v_point.x < v_low.x) {
- if(v_point.y < v_low.y) {
- if(v_point.z < v_low.z) {
- retval = distance_vector_point_3d (&v_point, v_low.x, v_low.y, v_low.z); //point2point distance
- } else if (v_point.z < v_high.z) {
- retval = distance_vector_point_3d (&v_point, v_low.x, v_low.y, v_point.z); //point2line distance
- } else {
- retval = distance_vector_point_3d (&v_point, v_low.x, v_low.y, v_high.z); //point2point distance
- }
- } else if(v_point.y < v_high.y) {
- if(v_point.z < v_low.z) {
- retval = distance_vector_point_3d (&v_point, v_low.x, v_point.y , v_low.z); //point2line distance
- } else if (v_point.z < v_high.z) {
- retval = distance_vector_point_3d (&v_point, v_low.x, v_point.y , v_point.z); //point2plane distance
- } else {
- retval = distance_vector_point_3d (&v_point, v_low.x, v_point.y, v_high.z); //point2line distance
+ v_low.x = (double) box->low.coord[0] / MAXCVALUE;
+ v_low.y = (double) box->low.coord[1] / MAXCVALUE;
+ v_low.z = (double) box->low.coord[2] / MAXCVALUE;
+ v_high.x = (double) box->high.coord[0] / MAXCVALUE;
+ v_high.y = (double) box->high.coord[1] / MAXCVALUE;
+ v_high.z = (double) box->high.coord[2] / MAXCVALUE;
+
+ /*
+ * a box splits space into 27 subspaces (6+12+8+1) with different
+ * distance calculation
+ */
+ if (v_point.x < v_low.x)
+ {
+ if (v_point.y < v_low.y)
+ {
+ if (v_point.z < v_low.z)
+ {
+ /* point2point distance */
+ retval = distance_vector_point_3d(&v_point, v_low.x, v_low.y, v_low.z);
+ }
+ else if (v_point.z < v_high.z)
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_low.x, v_low.y, v_point.z);
+ }
+ else
+ {
+ /* point2point distance */
+ retval = distance_vector_point_3d(&v_point, v_low.x, v_low.y, v_high.z);
+ }
+ }
+ else if (v_point.y < v_high.y)
+ {
+ if (v_point.z < v_low.z)
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_low.x, v_point.y, v_low.z);
+ }
+ else if (v_point.z < v_high.z)
+ {
+ /* point2plane distance */
+ retval = distance_vector_point_3d(&v_point, v_low.x, v_point.y, v_point.z);
+ }
+ else
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_low.x, v_point.y, v_high.z);
+ }
+ }
+ else
+ {
+ if (v_point.z < v_low.z)
+ {
+ /* point2point distance */
+ retval = distance_vector_point_3d(&v_point, v_low.x, v_high.y, v_low.z);
+ }
+ else if (v_point.z < v_high.z)
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_low.x, v_high.y, v_point.z);
+ }
+ else
+ {
+ /* point2point distance */
+ retval = distance_vector_point_3d(&v_point, v_low.x, v_high.y, v_high.z);
+ }
+ }
+ }
+ else if (v_point.x < v_high.x)
+ {
+ if (v_point.y < v_low.y)
+ {
+ if (v_point.z < v_low.z)
+ {
+ /* p2line distance */
+ retval = distance_vector_point_3d(&v_point, v_point.x, v_low.y, v_low.z);
+ }
+ else if (v_point.z < v_high.z)
+ {
+ /* point2plane distance */
+ retval = distance_vector_point_3d(&v_point, v_point.x, v_low.y, v_point.z);
+ }
+ else
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_point.x, v_low.y, v_high.z);
}
- } else {
- if(v_point.z < v_low.z) {
- retval = distance_vector_point_3d (&v_point, v_low.x, v_high.y, v_low.z); //point2point distance
- } else if (v_point.z < v_high.z) {
- retval = distance_vector_point_3d (&v_point, v_low.x, v_high.y, v_point.z); //point2line distance
- } else {
- retval = distance_vector_point_3d (&v_point, v_low.x, v_high.y, v_high.z); //point2point distance
+ }
+ else if (v_point.y < v_high.y)
+ {
+ if (v_point.z < v_low.z)
+ {
+ /* point2plane distance */
+ retval = distance_vector_point_3d(&v_point, v_point.x, v_point.y, v_low.z);
+ }
+ else if (v_point.z < v_high.z)
+ {
+ /* inside cube */
+ retval = 0;
+ }
+ else
+ {
+ /* point2plane distance */
+ retval = distance_vector_point_3d(&v_point, v_point.x, v_point.y, v_high.z);
}
}
- } else if(v_point.x < v_high.x) {
- if(v_point.y < v_low.y) {
- if(v_point.z < v_low.z) {
- retval = distance_vector_point_3d (&v_point, v_point.x, v_low.y, v_low.z); //p2line distance
- } else if (v_point.z < v_high.z) {
- retval = distance_vector_point_3d (&v_point, v_point.x, v_low.y, v_point.z); //point2plane distance
- } else {
- retval = distance_vector_point_3d (&v_point, v_point.x, v_low.y, v_high.z); //point2line distance
- }
- } else if(v_point.y < v_high.y) {
- if(v_point.z < v_low.z) {
- retval = distance_vector_point_3d (&v_point, v_point.x, v_point.y , v_low.z); //point2plane distance
- } else if (v_point.z < v_high.z) {
- retval = 0; // inside cube
- } else {
- retval = distance_vector_point_3d (&v_point, v_point.x, v_point.y, v_high.z); //point2plane distance
+ else
+ {
+ if (v_point.z < v_low.z)
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_point.x, v_high.y, v_low.z);
+ }
+ else if (v_point.z < v_high.z)
+ {
+ /* point2plane distance */
+ retval = distance_vector_point_3d(&v_point, v_point.x, v_high.y, v_point.z);
}
- } else {
- if(v_point.z < v_low.z) {
- retval = distance_vector_point_3d (&v_point, v_point.x, v_high.y, v_low.z); //point2line distance
- } else if (v_point.z < v_high.z) {
- retval = distance_vector_point_3d (&v_point, v_point.x, v_high.y, v_point.z); //point2plane distance
- } else {
- retval = distance_vector_point_3d (&v_point, v_point.x, v_high.y, v_high.z); //point2line distance
+ else
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_point.x, v_high.y, v_high.z);
}
}
- } else {
- if(v_point.y < v_low.y) {
- if(v_point.z < v_low.z) {
- retval = distance_vector_point_3d (&v_point, v_high.x, v_low.y, v_low.z); //p2p distance
- } else if (v_point.z < v_high.z) {
- retval = distance_vector_point_3d (&v_point, v_high.x, v_low.y, v_point.z); //point2line distance
- } else {
- retval = distance_vector_point_3d (&v_point, v_high.x, v_low.y, v_high.z); //point2point distance
- }
- } else if(v_point.y < v_high.y) {
- if(v_point.z < v_low.z) {
- retval = distance_vector_point_3d (&v_point, v_high.x, v_point.y , v_low.z); //point2line distance
- } else if (v_point.z < v_high.z) {
- retval = distance_vector_point_3d (&v_point, v_high.x, v_point.y , v_point.z); //point2plane distance
- } else {
- retval = distance_vector_point_3d (&v_point, v_high.x, v_point.y, v_high.z); //point2line distance
+ }
+ else
+ {
+ if (v_point.y < v_low.y)
+ {
+ if (v_point.z < v_low.z)
+ {
+ /* p2p distance */
+ retval = distance_vector_point_3d(&v_point, v_high.x, v_low.y, v_low.z);
}
- } else {
- if(v_point.z < v_low.z) {
- retval = distance_vector_point_3d (&v_point, v_high.x, v_high.y, v_low.z); //point2point distance
- } else if (v_point.z < v_high.z) {
- retval = distance_vector_point_3d (&v_point, v_high.x, v_high.y, v_point.z); //point2line distance
- } else {
- retval = distance_vector_point_3d (&v_point, v_high.x, v_high.y, v_high.z); //point2point distance
+ else if (v_point.z < v_high.z)
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_high.x, v_low.y, v_point.z);
+ }
+ else
+ {
+ /* point2point distance */
+ retval = distance_vector_point_3d(&v_point, v_high.x, v_low.y, v_high.z);
+ }
+ }
+ else if (v_point.y < v_high.y)
+ {
+ if (v_point.z < v_low.z)
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_high.x, v_point.y, v_low.z);
+ }
+ else if (v_point.z < v_high.z)
+ {
+ /* point2plane distance */
+ retval = distance_vector_point_3d(&v_point, v_high.x, v_point.y, v_point.z);
+ }
+ else
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_high.x, v_point.y, v_high.z);
+ }
+ }
+ else
+ {
+ if (v_point.z < v_low.z)
+ {
+ /* point2point distance */
+ retval = distance_vector_point_3d(&v_point, v_high.x, v_high.y, v_low.z);
+ }
+ else if (v_point.z < v_high.z)
+ {
+ /* point2line distance */
+ retval = distance_vector_point_3d(&v_point, v_high.x, v_high.y, v_point.z);
+ }
+ else
+ {
+ /* point2point distance */
+ retval = distance_vector_point_3d(&v_point, v_high.x, v_high.y, v_high.z);
}
}
}
-
+
elog(DEBUG1, "distance (%lg,%lg,%lg %lg,%lg,%lg) <-> (%lg,%lg) = %lg",
- v_low.x, v_low.y, v_low.z,
- v_high.x, v_high.y, v_high.z,
- point->lng, point->lat,
- retval
- );
+ v_low.x, v_low.y, v_low.z,
+ v_high.x, v_high.y, v_high.z,
+ point->lng, point->lat,
+ retval
+ );
break;
default:
elog(ERROR, "unrecognized cube strategy number: %d", strategy);
- retval = 0; /* keep compiler quiet */
+ retval = 0; /* keep compiler quiet */
break;
}
+
PG_RETURN_FLOAT8(retval);
}
-
-
/*
* Represents information about an entry that can be placed to either group
* without affecting overlap over selected axis ("common entry").
@@ -2329,7 +2429,7 @@ do_picksplit(Box3D *boxes, OffsetNumber maxoff, GIST_SPLITVEC *v)
{
box = &boxes[i];
commonEntries[i].delta = fabs((unionSizeBox3D(leftBox, box) - leftBoxSize) -
- (unionSizeBox3D(rightBox, box) - rightBoxSize));
+ (unionSizeBox3D(rightBox, box) - rightBoxSize));
}
/*