PostGIS  2.5.7dev-r@@SVN_REVISION@@

◆ spheroid_direction()

double spheroid_direction ( const GEOGRAPHIC_POINT r,
const GEOGRAPHIC_POINT s,
const SPHEROID spheroid 
)

Computes the direction of the geodesic joining two points on the spheroid.

Based on Vincenty's formula for the geodetic inverse problem as described in "Geocentric Datum of Australia Technical Manual", Chapter 4. Tested against: http://mascot.gdbc.gov.bc.ca/mascot/util1a.html and http://www.ga.gov.au/nmd/geodesy/datums/vincenty_inverse.jsp

Parameters
r- location of first point
s- location of second point
Returns
azimuth of line joining r and s

Definition at line 287 of file lwspheroid.c.

288 {
289  int i = 0;
290  double lambda = s->lon - r->lon;
291  double omf = 1 - spheroid->f;
292  double u1 = atan(omf * tan(r->lat));
293  double cos_u1 = cos(u1);
294  double sin_u1 = sin(u1);
295  double u2 = atan(omf * tan(s->lat));
296  double cos_u2 = cos(u2);
297  double sin_u2 = sin(u2);
298 
299  double omega = lambda;
300  double alpha, sigma, sin_sigma, cos_sigma, cos2_sigma_m, sqr_sin_sigma, last_lambda;
301  double sin_alpha, cos_alphasq, C, alphaFD;
302  do
303  {
304  sqr_sin_sigma = POW2(cos_u2 * sin(lambda)) +
305  POW2((cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos(lambda)));
306  sin_sigma = sqrt(sqr_sin_sigma);
307  cos_sigma = sin_u1 * sin_u2 + cos_u1 * cos_u2 * cos(lambda);
308  sigma = atan2(sin_sigma, cos_sigma);
309  sin_alpha = cos_u1 * cos_u2 * sin(lambda) / sin(sigma);
310 
311  /* Numerical stability issue, ensure asin is not NaN */
312  if ( sin_alpha > 1.0 )
313  alpha = M_PI_2;
314  else if ( sin_alpha < -1.0 )
315  alpha = -1.0 * M_PI_2;
316  else
317  alpha = asin(sin_alpha);
318 
319  cos_alphasq = POW2(cos(alpha));
320  cos2_sigma_m = cos(sigma) - (2.0 * sin_u1 * sin_u2 / cos_alphasq);
321 
322  /* Numerical stability issue, cos2 is in range */
323  if ( cos2_sigma_m > 1.0 )
324  cos2_sigma_m = 1.0;
325  if ( cos2_sigma_m < -1.0 )
326  cos2_sigma_m = -1.0;
327 
328  C = (spheroid->f / 16.0) * cos_alphasq * (4.0 + spheroid->f * (4.0 - 3.0 * cos_alphasq));
329  last_lambda = lambda;
330  lambda = omega + (1.0 - C) * spheroid->f * sin(alpha) * (sigma + C * sin(sigma) *
331  (cos2_sigma_m + C * cos(sigma) * (-1.0 + 2.0 * POW2(cos2_sigma_m))));
332  i++;
333  }
334  while ( (i < 999) && (lambda != 0) && (fabs((last_lambda - lambda) / lambda) > 1.0e-9) );
335 
336  alphaFD = atan2((cos_u2 * sin(lambda)),
337  (cos_u1 * sin_u2 - sin_u1 * cos_u2 * cos(lambda)));
338  if (alphaFD < 0.0)
339  {
340  alphaFD = alphaFD + 2.0 * M_PI;
341  }
342  if (alphaFD > 2.0 * M_PI)
343  {
344  alphaFD = alphaFD - 2.0 * M_PI;
345  }
346  return alphaFD;
347 }
char * s
Definition: cu_in_wkt.c:23
char * r
Definition: cu_in_wkt.c:24
#define POW2(x)
Definition: lwgeodetic.h:47
double f
Definition: liblwgeom.h:318

References SPHEROID::f, POW2, r, and s.

Referenced by lwgeom_azumith_spheroid(), and ptarray_area_spheroid().

Here is the caller graph for this function: