PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
earthdistance.c
Go to the documentation of this file.
1 /* contrib/earthdistance/earthdistance.c */
2 
3 #include "postgres.h"
4 
5 #include <math.h>
6 
7 #include "utils/geo_decls.h" /* for Point */
8 
9 #ifndef M_PI
10 #define M_PI 3.14159265358979323846
11 #endif
12 
14 
15 /* Earth's radius is in statute miles. */
16 static const double EARTH_RADIUS = 3958.747716;
17 static const double TWO_PI = 2.0 * M_PI;
18 
19 
20 /******************************************************
21  *
22  * degtorad - convert degrees to radians
23  *
24  * arg: double, angle in degrees
25  *
26  * returns: double, same angle in radians
27  ******************************************************/
28 
29 static double
31 {
32  return (degrees / 360.0) * TWO_PI;
33 }
34 
35 /******************************************************
36  *
37  * geo_distance_internal - distance between points
38  *
39  * args:
40  * a pair of points - for each point,
41  * x-coordinate is longitude in degrees west of Greenwich
42  * y-coordinate is latitude in degrees above equator
43  *
44  * returns: double
45  * distance between the points in miles on earth's surface
46  ******************************************************/
47 
48 static double
50 {
51  double long1,
52  lat1,
53  long2,
54  lat2;
55  double longdiff;
56  double sino;
57 
58  /* convert degrees to radians */
59 
60  long1 = degtorad(pt1->x);
61  lat1 = degtorad(pt1->y);
62 
63  long2 = degtorad(pt2->x);
64  lat2 = degtorad(pt2->y);
65 
66  /* compute difference in longitudes - want < 180 degrees */
67  longdiff = fabs(long1 - long2);
68  if (longdiff > M_PI)
69  longdiff = TWO_PI - longdiff;
70 
71  sino = sqrt(sin(fabs(lat1 - lat2) / 2.) * sin(fabs(lat1 - lat2) / 2.) +
72  cos(lat1) * cos(lat2) * sin(longdiff / 2.) * sin(longdiff / 2.));
73  if (sino > 1.)
74  sino = 1.;
75 
76  return 2. * EARTH_RADIUS * asin(sino);
77 }
78 
79 
80 /******************************************************
81  *
82  * geo_distance - distance between points
83  *
84  * args:
85  * a pair of points - for each point,
86  * x-coordinate is longitude in degrees west of Greenwich
87  * y-coordinate is latitude in degrees above equator
88  *
89  * returns: float8
90  * distance between the points in miles on earth's surface
91  ******************************************************/
92 
94 
95 Datum
97 {
98  Point *pt1 = PG_GETARG_POINT_P(0);
99  Point *pt2 = PG_GETARG_POINT_P(1);
100  float8 result;
101 
102  result = geo_distance_internal(pt1, pt2);
103  PG_RETURN_FLOAT8(result);
104 }
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:326
double y
Definition: geo_decls.h:60
double x
Definition: geo_decls.h:60
PG_FUNCTION_INFO_V1(geo_distance)
double float8
Definition: c.h:375
#define PG_GETARG_POINT_P(n)
Definition: geo_decls.h:139
Datum degrees(PG_FUNCTION_ARGS)
Definition: float.c:2374
uintptr_t Datum
Definition: postgres.h:372
static const double TWO_PI
Definition: earthdistance.c:17
static double geo_distance_internal(Point *pt1, Point *pt2)
Definition: earthdistance.c:49
Datum geo_distance(PG_FUNCTION_ARGS)
Definition: earthdistance.c:96
static double degtorad(double degrees)
Definition: earthdistance.c:30
static const double EARTH_RADIUS
Definition: earthdistance.c:16
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
#define M_PI
Definition: earthdistance.c:10
PG_MODULE_MAGIC
Definition: earthdistance.c:13