LCOV - code coverage report
Current view: top level - contrib/earthdistance - earthdistance.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 20 22 90.9 %
Date: 2024-11-21 08:14:44 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : /* X/Open (XSI) requires <math.h> to provide M_PI, but core POSIX does not */
      10             : #ifndef M_PI
      11             : #define M_PI 3.14159265358979323846
      12             : #endif
      13             : 
      14           2 : PG_MODULE_MAGIC;
      15             : 
      16             : /* Earth's radius is in statute miles. */
      17             : static const double EARTH_RADIUS = 3958.747716;
      18             : static const double TWO_PI = 2.0 * M_PI;
      19             : 
      20             : 
      21             : /******************************************************
      22             :  *
      23             :  * degtorad - convert degrees to radians
      24             :  *
      25             :  * arg: double, angle in degrees
      26             :  *
      27             :  * returns: double, same angle in radians
      28             :  ******************************************************/
      29             : 
      30             : static double
      31         192 : degtorad(double degrees)
      32             : {
      33         192 :     return (degrees / 360.0) * TWO_PI;
      34             : }
      35             : 
      36             : /******************************************************
      37             :  *
      38             :  * geo_distance_internal - distance between points
      39             :  *
      40             :  * args:
      41             :  *   a pair of points - for each point,
      42             :  *     x-coordinate is longitude in degrees west of Greenwich
      43             :  *     y-coordinate is latitude in degrees above equator
      44             :  *
      45             :  * returns: double
      46             :  *   distance between the points in miles on earth's surface
      47             :  ******************************************************/
      48             : 
      49             : static double
      50          48 : geo_distance_internal(Point *pt1, Point *pt2)
      51             : {
      52             :     double      long1,
      53             :                 lat1,
      54             :                 long2,
      55             :                 lat2;
      56             :     double      longdiff;
      57             :     double      sino;
      58             : 
      59             :     /* convert degrees to radians */
      60             : 
      61          48 :     long1 = degtorad(pt1->x);
      62          48 :     lat1 = degtorad(pt1->y);
      63             : 
      64          48 :     long2 = degtorad(pt2->x);
      65          48 :     lat2 = degtorad(pt2->y);
      66             : 
      67             :     /* compute difference in longitudes - want < 180 degrees */
      68          48 :     longdiff = fabs(long1 - long2);
      69          48 :     if (longdiff > M_PI)
      70           0 :         longdiff = TWO_PI - longdiff;
      71             : 
      72          48 :     sino = sqrt(sin(fabs(lat1 - lat2) / 2.) * sin(fabs(lat1 - lat2) / 2.) +
      73          48 :                 cos(lat1) * cos(lat2) * sin(longdiff / 2.) * sin(longdiff / 2.));
      74          48 :     if (sino > 1.)
      75           0 :         sino = 1.;
      76             : 
      77          48 :     return 2. * EARTH_RADIUS * asin(sino);
      78             : }
      79             : 
      80             : 
      81             : /******************************************************
      82             :  *
      83             :  * geo_distance - distance between points
      84             :  *
      85             :  * args:
      86             :  *   a pair of points - for each point,
      87             :  *     x-coordinate is longitude in degrees west of Greenwich
      88             :  *     y-coordinate is latitude in degrees above equator
      89             :  *
      90             :  * returns: float8
      91             :  *   distance between the points in miles on earth's surface
      92             :  ******************************************************/
      93             : 
      94           4 : PG_FUNCTION_INFO_V1(geo_distance);
      95             : 
      96             : Datum
      97          48 : geo_distance(PG_FUNCTION_ARGS)
      98             : {
      99          48 :     Point      *pt1 = PG_GETARG_POINT_P(0);
     100          48 :     Point      *pt2 = PG_GETARG_POINT_P(1);
     101             :     float8      result;
     102             : 
     103          48 :     result = geo_distance_internal(pt1, pt2);
     104          48 :     PG_RETURN_FLOAT8(result);
     105             : }

Generated by: LCOV version 1.14