@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/contrib/earthdistance/earthdistance.c,v 1.14 2008/04/20 01:05:52 tgl Exp $ */
/* $PostgreSQL: pgsql/contrib/earthdistance/earthdistance.c,v 1.15 2008/04/21 01:11:43 tgl Exp $ */
# include "postgres.h"
# include "postgres.h"
@ -17,10 +17,6 @@ PG_MODULE_MAGIC;
static const double EARTH_RADIUS = 3958.747716 ;
static const double EARTH_RADIUS = 3958.747716 ;
static const double TWO_PI = 2.0 * M_PI ;
static const double TWO_PI = 2.0 * M_PI ;
PG_FUNCTION_INFO_V1 ( geo_distance ) ;
Datum geo_distance ( PG_FUNCTION_ARGS ) ;
/******************************************************
/******************************************************
*
*
@ -37,26 +33,22 @@ degtorad(double degrees)
return ( degrees / 360.0 ) * TWO_PI ;
return ( degrees / 360.0 ) * TWO_PI ;
}
}
/******************************************************
/******************************************************
*
*
* geo_distance - distance between points
* geo_distance_internal - distance between points
*
*
* args :
* args :
* a pair of points - for each point ,
* a pair of points - for each point ,
* x - coordinate is longitude in degrees west of Greenwich
* x - coordinate is longitude in degrees west of Greenwich
* y - coordinate is latitude in degrees above equator
* y - coordinate is latitude in degrees above equator
*
*
* returns : float8
* returns : double
* distance between the points in miles on earth ' s surface
* distance between the points in miles on earth ' s surface
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
Datum
static double
geo_distance ( PG_FUNCTION_ARGS )
geo_distance_internal ( Point * pt1 , Point * pt2 )
{
{
Point * pt1 = PG_GETARG_POINT_P ( 0 ) ;
Point * pt2 = PG_GETARG_POINT_P ( 1 ) ;
float8 result ;
double long1 ,
double long1 ,
lat1 ,
lat1 ,
long2 ,
long2 ,
@ -81,7 +73,57 @@ geo_distance(PG_FUNCTION_ARGS)
cos ( lat1 ) * cos ( lat2 ) * sin ( longdiff / 2. ) * sin ( longdiff / 2. ) ) ;
cos ( lat1 ) * cos ( lat2 ) * sin ( longdiff / 2. ) * sin ( longdiff / 2. ) ) ;
if ( sino > 1. )
if ( sino > 1. )
sino = 1. ;
sino = 1. ;
result = 2. * EARTH_RADIUS * asin ( sino ) ;
return 2. * EARTH_RADIUS * asin ( sino ) ;
}
/******************************************************
*
* geo_distance - distance between points
*
* args :
* a pair of points - for each point ,
* x - coordinate is longitude in degrees west of Greenwich
* y - coordinate is latitude in degrees above equator
*
* returns : float8
* distance between the points in miles on earth ' s surface
*
* If float8 is passed - by - value , the oldstyle version - 0 calling convention
* is unportable , so we use version - 1. However , if it ' s passed - by - reference ,
* continue to use oldstyle . This is just because we ' d like earthdistance
* to serve as a canary for any unintentional breakage of version - 0 functions
* with float8 results .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef USE_FLOAT8_BYVAL
Datum geo_distance ( PG_FUNCTION_ARGS ) ;
PG_FUNCTION_INFO_V1 ( geo_distance ) ;
Datum
geo_distance ( PG_FUNCTION_ARGS )
{
Point * pt1 = PG_GETARG_POINT_P ( 0 ) ;
Point * pt2 = PG_GETARG_POINT_P ( 1 ) ;
float8 result ;
result = geo_distance_internal ( pt1 , pt2 ) ;
PG_RETURN_FLOAT8 ( result ) ;
PG_RETURN_FLOAT8 ( result ) ;
}
}
# else /* !USE_FLOAT8_BYVAL */
double * geo_distance ( Point * pt1 , Point * pt2 ) ;
double *
geo_distance ( Point * pt1 , Point * pt2 )
{
double * resultp = palloc ( sizeof ( double ) ) ;
* resultp = geo_distance_internal ( pt1 , pt2 ) ;
return resultp ;
}
# endif /* USE_FLOAT8_BYVAL */