PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ gserialized_distance_nd()

Datum gserialized_distance_nd ( PG_FUNCTION_ARGS  )

Definition at line 808 of file gserialized_gist_nd.c.

809 {
810  char b1mem[GIDX_MAX_SIZE];
811  GIDX *b1 = (GIDX*)b1mem;
812  char b2mem[GIDX_MAX_SIZE];
813  GIDX *b2 = (GIDX*)b2mem;
814 
815 #if POSTGIS_PGSQL_VERSION < 95
816 
817  /* Centroid-to-centroid distance */
818  Datum gs1 = PG_GETARG_DATUM(0);
819  Datum gs2 = PG_GETARG_DATUM(1);
820  double box_distance = FLT_MAX;
821 
822  /* Must be able to build box for each argument (ie, not empty geometry). */
823  if ( (gserialized_datum_get_gidx_p(gs1, b1) == LW_SUCCESS) &&
824  (gserialized_datum_get_gidx_p(gs2, b2) == LW_SUCCESS) )
825  {
826  box_distance = gidx_distance_leaf_centroid(b1, b2);
827  POSTGIS_DEBUGF(3, "got boxes %s and %s", gidx_to_string(b1), gidx_to_string(b2));
828  }
829  PG_RETURN_FLOAT8(box_distance);
830 
831 #else /* POSTGIS_PGSQL_VERSION >= 96 */
832 
833  /* Feature-to-feature distance */
834  GSERIALIZED *geom1 = PG_GETARG_GSERIALIZED_P(0);
835  GSERIALIZED *geom2 = PG_GETARG_GSERIALIZED_P(1);
836  LWGEOM *lw1 = lwgeom_from_gserialized(geom1);
837  LWGEOM *lw2 = lwgeom_from_gserialized(geom2);
838  LWGEOM *closest;
839  double distance;
840 
841 
842  /* Find an exact shortest line w/ the dimensions we support */
843  if ( lwgeom_has_z(lw1) && lwgeom_has_z(lw2) )
844  {
845  closest = lwgeom_closest_line_3d(lw1, lw2);
846  distance = lwgeom_length(closest);
847  }
848  else
849  {
850  closest = lwgeom_closest_line(lw1, lw2);
851  distance = lwgeom_length_2d(closest);
852  }
853 
854  /* Un-sqrt the distance so we can add extra terms */
856 
857  /* Can only add the M term if both objects have M */
858  if ( lwgeom_has_m(lw1) && lwgeom_has_m(lw2) )
859  {
860  double m1 = 0, m2 = 0;
861  int usebox = false;
862 
863  if ( lwgeom_get_type(lw1) == POINTTYPE )
864  {
865  POINT4D p;
866  lwpoint_getPoint4d_p((LWPOINT*)lw1, &p);
867  m1 = p.m;
868  }
869  else if ( lwgeom_get_type(lw1) == LINETYPE )
870  {
871  LWPOINT *lwp1 = lwline_get_lwpoint(lwgeom_as_lwline(closest), 0);
872  m1 = lwgeom_interpolate_point(lw1, lwp1);
873  lwpoint_free(lwp1);
874  }
875  else
876  {
877  usebox = true;
878  }
879 
880  if ( lwgeom_get_type(lw2) == POINTTYPE )
881  {
882  POINT4D p;
883  lwpoint_getPoint4d_p((LWPOINT*)lw2, &p);
884  m2 = p.m;
885  }
886  else if ( lwgeom_get_type(lw2) == LINETYPE )
887  {
888  LWPOINT *lwp2 = lwline_get_lwpoint(lwgeom_as_lwline(closest), 1);
889  m2 = lwgeom_interpolate_point(lw2, lwp2);
890  lwpoint_free(lwp2);
891  }
892  else
893  {
894  usebox = true;
895  }
896 
897  if ( usebox )
898  {
899  double d;
900  gserialized_get_gidx_p(geom1, b1);
901  gserialized_get_gidx_p(geom2, b2);
902  d = gidx_distance_m(b1, b2);
903  distance += d*d;
904  }
905  else
906  {
907  distance += (m2-m1)*(m2-m1);
908  }
909  }
910 
911  lwgeom_free(closest);
912 
913  PG_FREE_IF_COPY(geom1, 0);
914  PG_FREE_IF_COPY(geom2, 1);
915  PG_RETURN_FLOAT8(sqrt(distance));
916 #endif /* POSTGIS_PGSQL_VERSION >= 96 */
917 }
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
static double gidx_distance_m(const GIDX *a, const GIDX *b)
int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out)
Definition: lwpoint.c:57
LWLINE * lwgeom_as_lwline(const LWGEOM *lwgeom)
Definition: lwgeom.c:170
void lwpoint_free(LWPOINT *pt)
Definition: lwpoint.c:213
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1144
#define LINETYPE
Definition: liblwgeom.h:86
double lwgeom_interpolate_point(const LWGEOM *lwin, const LWPOINT *lwpt)
Find the measure value at the location on the line closest to the point.
#define LW_SUCCESS
Definition: liblwgeom.h:80
uint32_t lwgeom_get_type(const LWGEOM *geom)
Return LWTYPE number.
Definition: lwgeom.c:923
double lwgeom_length(const LWGEOM *geom)
Definition: lwgeom.c:1939
int lwgeom_has_z(const LWGEOM *geom)
Return LW_TRUE if geometry has Z ordinates.
Definition: lwgeom.c:930
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:85
LWGEOM * lwgeom_closest_line(const LWGEOM *lw1, const LWGEOM *lw2)
Definition: measures.c:42
double lwgeom_length_2d(const LWGEOM *geom)
Definition: lwgeom.c:1961
int lwgeom_has_m(const LWGEOM *geom)
Return LW_TRUE if geometry has M ordinates.
Definition: lwgeom.c:937
LWGEOM * lwgeom_closest_line_3d(const LWGEOM *lw1, const LWGEOM *lw2)
Definition: measures3d.c:88
LWPOINT * lwline_get_lwpoint(const LWLINE *line, uint32_t where)
Returns freshly allocated LWPOINT that corresponds to the index where.
Definition: lwline.c:318
Datum distance(PG_FUNCTION_ARGS)
double m
Definition: liblwgeom.h:355

References distance(), gidx_distance_m(), LINETYPE, LW_SUCCESS, lwgeom_as_lwline(), lwgeom_closest_line(), lwgeom_closest_line_3d(), lwgeom_free(), lwgeom_from_gserialized(), lwgeom_get_type(), lwgeom_has_m(), lwgeom_has_z(), lwgeom_interpolate_point(), lwgeom_length(), lwgeom_length_2d(), lwline_get_lwpoint(), lwpoint_free(), lwpoint_getPoint4d_p(), POINT4D::m, and POINTTYPE.

Here is the call graph for this function: