rhumbline.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*!
  2. * \file lib/gis/rhumbline.c
  3. *
  4. * \brief GIS Library - Rhumbline calculation routines.
  5. *
  6. * From "Map Projections" by Peter Richardus and Ron K. Alder, 1972<br>
  7. * (526.8 R39m in Map & Geography Library)<br>
  8. * Page 20,21, formulas 2.21, 2.22
  9. *
  10. * Formula is the equation of a rhumbline from (lat1,lon1) to
  11. * (lat2,lon2). Input is lon, output is lat (all in degrees).
  12. *
  13. * <b>Note:</b> Formula only works if 0 < abs(lon2-lon1) < 180.
  14. * If lon1 == lon2 then rhumbline is the merdian lon1 (and the formula
  15. * will fail).
  16. * <br>
  17. * <b>WARNING:</b> This code is preliminary. It may not even be correct.
  18. *
  19. * (C) 2001-2014 by the GRASS Development Team
  20. *
  21. * This program is free software under the GNU General Public License
  22. * (>=v2). Read the file COPYING that comes with GRASS for details.
  23. *
  24. * \author GRASS GIS Development Team
  25. *
  26. * \date 1999-2014
  27. */
  28. #include <math.h>
  29. #include <grass/gis.h>
  30. #include "pi.h"
  31. static void adjust_lat(double *);
  32. #if 0
  33. static void adjust_lon(double *);
  34. #endif /* unused */
  35. static struct state {
  36. double TAN_A, TAN1, TAN2, L;
  37. int parallel;
  38. } state;
  39. static struct state *st = &state;
  40. /**
  41. * \brief Start rhumbline calculations.
  42. *
  43. * <b>Note:</b> This function must be called before other rhumbline
  44. * functions to initialize parameters.
  45. *
  46. * \param[in] lon1,lat1 longitude, latitude of first point
  47. * \param[in] lon2,lat2 longitude, latitude of second point
  48. * \return 1 on success
  49. * \return 0 on error
  50. */
  51. int G_begin_rhumbline_equation(double lon1, double lat1, double lon2,
  52. double lat2)
  53. {
  54. adjust_lat(&lat1);
  55. adjust_lat(&lat2);
  56. if (lon1 == lon2) {
  57. st->parallel = 1; /* a lie */
  58. st->L = lat1;
  59. return 0;
  60. }
  61. if (lat1 == lat2) {
  62. st->parallel = 1;
  63. st->L = lat1;
  64. return 1;
  65. }
  66. st->parallel = 0;
  67. lon1 = Radians(lon1);
  68. lon2 = Radians(lon2);
  69. lat1 = Radians(lat1);
  70. lat2 = Radians(lat2);
  71. st->TAN1 = tan(M_PI_4 + lat1 / 2.0);
  72. st->TAN2 = tan(M_PI_4 + lat2 / 2.0);
  73. st->TAN_A = (lon2 - lon1) / (log(st->TAN2) - log(st->TAN1));
  74. st->L = lon1;
  75. return 1;
  76. }
  77. /**
  78. * \brief Calculates rhumbline latitude.
  79. *
  80. * <b>Note:</b> Function only works if lon1 < lon < lon2.
  81. *
  82. * \param[in] lon longitude
  83. * \return double latitude in degrees
  84. */
  85. double G_rhumbline_lat_from_lon(double lon)
  86. {
  87. if (st->parallel)
  88. return st->L;
  89. lon = Radians(lon);
  90. return Degrees(2 * atan(exp((lon - st->L) / st->TAN_A) * st->TAN1) - M_PI_2);
  91. }
  92. #if 0
  93. static void adjust_lon(double *lon)
  94. {
  95. while (*lon > 180.0)
  96. *lon -= 360.0;
  97. while (*lon < -180.0)
  98. *lon += 360.0;
  99. }
  100. #endif /* unused */
  101. static void adjust_lat(double *lat)
  102. {
  103. if (*lat > 90.0)
  104. *lat = 90.0;
  105. if (*lat < -90.0)
  106. *lat = -90.0;
  107. }