@@ -36,6 +36,7 @@ PG_FUNCTION_INFO_V1(g_spherekey_penalty);
3636PG_FUNCTION_INFO_V1 (g_spherekey_picksplit );
3737PG_FUNCTION_INFO_V1 (g_spoint3_penalty );
3838PG_FUNCTION_INFO_V1 (g_spoint3_picksplit );
39+ PG_FUNCTION_INFO_V1 (g_spoint_distance );
3940PG_FUNCTION_INFO_V1 (g_spoint3_distance );
4041PG_FUNCTION_INFO_V1 (g_spoint3_fetch );
4142
@@ -681,6 +682,10 @@ g_spoint3_consistent(PG_FUNCTION_ARGS)
681682 PG_RETURN_BOOL (false);
682683}
683684
685+ static double distance_vector_point_3d (Vector3D * v , double x , double y , double z ) {
686+ 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
687+ }
688+
684689Datum
685690g_spoint3_distance (PG_FUNCTION_ARGS )
686691{
@@ -1672,6 +1677,127 @@ fallbackSplit(Box3D *boxes, OffsetNumber maxoff, GIST_SPLITVEC *v)
16721677 v -> spl_ldatum_exists = v -> spl_rdatum_exists = false;
16731678}
16741679
1680+
1681+ Datum
1682+ g_spoint_distance (PG_FUNCTION_ARGS )
1683+ {
1684+ GISTENTRY * entry = (GISTENTRY * ) PG_GETARG_POINTER (0 );
1685+ StrategyNumber strategy = (StrategyNumber ) PG_GETARG_UINT16 (2 );
1686+ Box3D * box = (Box3D * ) DatumGetPointer (entry -> key );
1687+ double retval ;
1688+ SPoint * point = (SPoint * ) PG_GETARG_POINTER (1 );
1689+ Vector3D v_point , v_low , v_high ;
1690+
1691+ switch (strategy )
1692+ {
1693+ case 17 :
1694+ // Prepare data for calculation
1695+ spoint_vector3d (& v_point , point );
1696+ v_low .x = (double )box -> low .coord [0 ] / MAXCVALUE ;
1697+ v_low .y = (double )box -> low .coord [1 ] / MAXCVALUE ;
1698+ v_low .z = (double )box -> low .coord [2 ] / MAXCVALUE ;
1699+ v_high .x = (double )box -> high .coord [0 ] / MAXCVALUE ;
1700+ v_high .y = (double )box -> high .coord [1 ] / MAXCVALUE ;
1701+ v_high .z = (double )box -> high .coord [2 ] / MAXCVALUE ;
1702+ // a box splits space into 27 subspaces (6+12+8+1) with different distance calculation
1703+ if (v_point .x < v_low .x ) {
1704+ if (v_point .y < v_low .y ) {
1705+ if (v_point .z < v_low .z ) {
1706+ retval = distance_vector_point_3d (& v_point , v_low .x , v_low .y , v_low .z ); //point2point distance
1707+ } else if (v_point .z < v_high .z ) {
1708+ retval = distance_vector_point_3d (& v_point , v_low .x , v_low .y , v_point .z ); //point2line distance
1709+ } else {
1710+ retval = distance_vector_point_3d (& v_point , v_low .x , v_low .y , v_high .z ); //point2point distance
1711+ }
1712+ } else if (v_point .y < v_high .y ) {
1713+ if (v_point .z < v_low .z ) {
1714+ retval = distance_vector_point_3d (& v_point , v_low .x , v_point .y , v_low .z ); //point2line distance
1715+ } else if (v_point .z < v_high .z ) {
1716+ retval = distance_vector_point_3d (& v_point , v_low .x , v_point .y , v_point .z ); //point2plane distance
1717+ } else {
1718+ retval = distance_vector_point_3d (& v_point , v_low .x , v_point .y , v_high .z ); //point2line distance
1719+ }
1720+ } else {
1721+ if (v_point .z < v_low .z ) {
1722+ retval = distance_vector_point_3d (& v_point , v_low .x , v_high .y , v_low .z ); //point2point distance
1723+ } else if (v_point .z < v_high .z ) {
1724+ retval = distance_vector_point_3d (& v_point , v_low .x , v_high .y , v_point .z ); //point2line distance
1725+ } else {
1726+ retval = distance_vector_point_3d (& v_point , v_low .x , v_high .y , v_high .z ); //point2point distance
1727+ }
1728+ }
1729+ } else if (v_point .x < v_high .x ) {
1730+ if (v_point .y < v_low .y ) {
1731+ if (v_point .z < v_low .z ) {
1732+ retval = distance_vector_point_3d (& v_point , v_point .x , v_low .y , v_low .z ); //p2line distance
1733+ } else if (v_point .z < v_high .z ) {
1734+ retval = distance_vector_point_3d (& v_point , v_point .x , v_low .y , v_point .z ); //point2plane distance
1735+ } else {
1736+ retval = distance_vector_point_3d (& v_point , v_point .x , v_low .y , v_high .z ); //point2line distance
1737+ }
1738+ } else if (v_point .y < v_high .y ) {
1739+ if (v_point .z < v_low .z ) {
1740+ retval = distance_vector_point_3d (& v_point , v_point .x , v_point .y , v_low .z ); //point2plane distance
1741+ } else if (v_point .z < v_high .z ) {
1742+ retval = 0 ; // inside cube
1743+ } else {
1744+ retval = distance_vector_point_3d (& v_point , v_point .x , v_point .y , v_high .z ); //point2plane distance
1745+ }
1746+ } else {
1747+ if (v_point .z < v_low .z ) {
1748+ retval = distance_vector_point_3d (& v_point , v_point .x , v_high .y , v_low .z ); //point2line distance
1749+ } else if (v_point .z < v_high .z ) {
1750+ retval = distance_vector_point_3d (& v_point , v_point .x , v_high .y , v_point .z ); //point2plane distance
1751+ } else {
1752+ retval = distance_vector_point_3d (& v_point , v_point .x , v_high .y , v_high .z ); //point2line distance
1753+ }
1754+ }
1755+ } else {
1756+ if (v_point .y < v_low .y ) {
1757+ if (v_point .z < v_low .z ) {
1758+ retval = distance_vector_point_3d (& v_point , v_high .x , v_low .y , v_low .z ); //p2p distance
1759+ } else if (v_point .z < v_high .z ) {
1760+ retval = distance_vector_point_3d (& v_point , v_high .x , v_low .y , v_point .z ); //point2line distance
1761+ } else {
1762+ retval = distance_vector_point_3d (& v_point , v_high .x , v_low .y , v_high .z ); //point2point distance
1763+ }
1764+ } else if (v_point .y < v_high .y ) {
1765+ if (v_point .z < v_low .z ) {
1766+ retval = distance_vector_point_3d (& v_point , v_high .x , v_point .y , v_low .z ); //point2line distance
1767+ } else if (v_point .z < v_high .z ) {
1768+ retval = distance_vector_point_3d (& v_point , v_high .x , v_point .y , v_point .z ); //point2plane distance
1769+ } else {
1770+ retval = distance_vector_point_3d (& v_point , v_high .x , v_point .y , v_high .z ); //point2line distance
1771+ }
1772+ } else {
1773+ if (v_point .z < v_low .z ) {
1774+ retval = distance_vector_point_3d (& v_point , v_high .x , v_high .y , v_low .z ); //point2point distance
1775+ } else if (v_point .z < v_high .z ) {
1776+ retval = distance_vector_point_3d (& v_point , v_high .x , v_high .y , v_point .z ); //point2line distance
1777+ } else {
1778+ retval = distance_vector_point_3d (& v_point , v_high .x , v_high .y , v_high .z ); //point2point distance
1779+ }
1780+ }
1781+ }
1782+
1783+ elog (DEBUG1 , "distance (%lg,%lg,%lg %lg,%lg,%lg) <-> (%lg,%lg) = %lg" ,
1784+ v_low .x , v_low .y , v_low .z ,
1785+ v_high .x , v_high .y , v_high .z ,
1786+ point -> lng , point -> lat ,
1787+ retval
1788+ );
1789+ break ;
1790+
1791+ default :
1792+ elog (ERROR , "unrecognized cube strategy number: %d" , strategy );
1793+ retval = 0 ; /* keep compiler quiet */
1794+ break ;
1795+ }
1796+ PG_RETURN_FLOAT8 (retval );
1797+ }
1798+
1799+
1800+
16751801/*
16761802 * Represents information about an entry that can be placed to either group
16771803 * without affecting overlap over selected axis ("common entry").
0 commit comments