geodesic.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #include <math.h>
  2. #include <grass/gis.h>
  3. #include "pi.h"
  4. /*
  5. * This code is preliminary. I don't know if it is even
  6. * correct.
  7. */
  8. /*
  9. * From "Map Projections" by Peter Richardus and Ron K. Alder, 1972
  10. * (526.8 R39m in Map & Geography Library)
  11. * page 19, formula 2.17
  12. *
  13. * Formula is the equation of a geodesic from (lat1,lon1) to (lat2,lon2)
  14. * Input is lon, output is lat (all in degrees)
  15. *
  16. * Note formula only works if 0 < abs(lon2-lon1) < 180
  17. * If lon1 == lon2 then geodesic is the merdian lon1
  18. * (and the formula will fail)
  19. * if lon2-lon1=180 then the geodesic is either meridian lon1 or lon2
  20. */
  21. /* TODO:
  22. *
  23. * integrate code from raster/r.surf.idw/ll.c
  24. */
  25. #define SWAP(a,b) temp=a;a=b;b=temp
  26. static int adjust_lat(double *);
  27. static int adjust_lon(double *);
  28. static double A, B;
  29. int G_begin_geodesic_equation(double lon1, double lat1, double lon2,
  30. double lat2)
  31. {
  32. double sin21, tan1, tan2;
  33. adjust_lon(&lon1);
  34. adjust_lon(&lon2);
  35. adjust_lat(&lat1);
  36. adjust_lat(&lat2);
  37. if (lon1 > lon2) {
  38. register double temp;
  39. SWAP(lon1, lon2);
  40. SWAP(lat1, lat2);
  41. }
  42. if (lon1 == lon2) {
  43. A = B = 0.0;
  44. return 0;
  45. }
  46. lon1 = Radians(lon1);
  47. lon2 = Radians(lon2);
  48. lat1 = Radians(lat1);
  49. lat2 = Radians(lat2);
  50. sin21 = sin(lon2 - lon1);
  51. tan1 = tan(lat1);
  52. tan2 = tan(lat2);
  53. A = (tan2 * cos(lon1) - tan1 * cos(lon2)) / sin21;
  54. B = (tan2 * sin(lon1) - tan1 * sin(lon2)) / sin21;
  55. return 1;
  56. }
  57. /* only works if lon1 < lon < lon2 */
  58. double G_geodesic_lat_from_lon(double lon)
  59. {
  60. adjust_lon(&lon);
  61. lon = Radians(lon);
  62. return Degrees(atan(A * sin(lon) - B * cos(lon)));
  63. }
  64. static int adjust_lon(double *lon)
  65. {
  66. while (*lon > 180.0)
  67. *lon -= 360.0;
  68. while (*lon < -180.0)
  69. *lon += 360.0;
  70. return 0;
  71. }
  72. static int adjust_lat(double *lat)
  73. {
  74. if (*lat > 90.0)
  75. *lat = 90.0;
  76. if (*lat < -90.0)
  77. *lat = -90.0;
  78. return 0;
  79. }