geodesic.h 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781
  1. /**
  2. * \file geodesic.h
  3. * \brief Header for the geodesic routines in C
  4. *
  5. * This an implementation in C of the geodesic algorithms described in
  6. * - C. F. F. Karney,
  7. * <a href="https://dx.doi.org/10.1007/s00190-012-0578-z">
  8. * Algorithms for geodesics</a>,
  9. * J. Geodesy <b>87</b>, 43--55 (2013);
  10. * DOI: <a href="https://dx.doi.org/10.1007/s00190-012-0578-z">
  11. * 10.1007/s00190-012-0578-z</a>;
  12. * addenda: <a href="http://geographiclib.sf.net/geod-addenda.html">
  13. * geod-addenda.html</a>.
  14. * .
  15. * The principal advantages of these algorithms over previous ones (e.g.,
  16. * Vincenty, 1975) are
  17. * - accurate to round off for |<i>f</i>| &lt; 1/50;
  18. * - the solution of the inverse problem is always found;
  19. * - differential and integral properties of geodesics are computed.
  20. *
  21. * The shortest path between two points on the ellipsoid at (\e lat1, \e
  22. * lon1) and (\e lat2, \e lon2) is called the geodesic. Its length is
  23. * \e s12 and the geodesic from point 1 to point 2 has forward azimuths
  24. * \e azi1 and \e azi2 at the two end points.
  25. *
  26. * Traditionally two geodesic problems are considered:
  27. * - the direct problem -- given \e lat1, \e lon1, \e s12, and \e azi1,
  28. * determine \e lat2, \e lon2, and \e azi2. This is solved by the function
  29. * geod_direct().
  30. * - the inverse problem -- given \e lat1, \e lon1, and \e lat2, \e lon2,
  31. * determine \e s12, \e azi1, and \e azi2. This is solved by the function
  32. * geod_inverse().
  33. *
  34. * The ellipsoid is specified by its equatorial radius \e a (typically in
  35. * meters) and flattening \e f. The routines are accurate to round off with
  36. * double precision arithmetic provided that |<i>f</i>| &lt; 1/50; for the
  37. * WGS84 ellipsoid, the errors are less than 15 nanometers. (Reasonably
  38. * accurate results are obtained for |<i>f</i>| &lt; 1/5.) For a prolate
  39. * ellipsoid, specify \e f &lt; 0.
  40. *
  41. * The routines also calculate several other quantities of interest
  42. * - \e S12 is the area between the geodesic from point 1 to point 2 and the
  43. * equator; i.e., it is the area, measured counter-clockwise, of the
  44. * quadrilateral with corners (\e lat1,\e lon1), (0,\e lon1), (0,\e lon2),
  45. * and (\e lat2,\e lon2).
  46. * - \e m12, the reduced length of the geodesic is defined such that if
  47. * the initial azimuth is perturbed by \e dazi1 (radians) then the
  48. * second point is displaced by \e m12 \e dazi1 in the direction
  49. * perpendicular to the geodesic. On a curved surface the reduced
  50. * length obeys a symmetry relation, \e m12 + \e m21 = 0. On a flat
  51. * surface, we have \e m12 = \e s12.
  52. * - \e M12 and \e M21 are geodesic scales. If two geodesics are
  53. * parallel at point 1 and separated by a small distance \e dt, then
  54. * they are separated by a distance \e M12 \e dt at point 2. \e M21
  55. * is defined similarly (with the geodesics being parallel to one
  56. * another at point 2). On a flat surface, we have \e M12 = \e M21
  57. * = 1.
  58. * - \e a12 is the arc length on the auxiliary sphere. This is a
  59. * construct for converting the problem to one in spherical
  60. * trigonometry. \e a12 is measured in degrees. The spherical arc
  61. * length from one equator crossing to the next is always 180&deg;.
  62. *
  63. * If points 1, 2, and 3 lie on a single geodesic, then the following
  64. * addition rules hold:
  65. * - \e s13 = \e s12 + \e s23
  66. * - \e a13 = \e a12 + \e a23
  67. * - \e S13 = \e S12 + \e S23
  68. * - \e m13 = \e m12 \e M23 + \e m23 \e M21
  69. * - \e M13 = \e M12 \e M23 &minus; (1 &minus; \e M12 \e M21) \e
  70. * m23 / \e m12
  71. * - \e M31 = \e M32 \e M21 &minus; (1 &minus; \e M23 \e M32) \e
  72. * m12 / \e m23
  73. *
  74. * The shortest distance returned by the solution of the inverse problem is
  75. * (obviously) uniquely defined. However, in a few special cases there are
  76. * multiple azimuths which yield the same shortest distance. Here is a
  77. * catalog of those cases:
  78. * - \e lat1 = &minus;\e lat2 (with neither point at a pole). If \e azi1 =
  79. * \e azi2, the geodesic is unique. Otherwise there are two geodesics
  80. * and the second one is obtained by setting [\e azi1, \e azi2] = [\e
  81. * azi2, \e azi1], [\e M12, \e M21] = [\e M21, \e M12], \e S12 =
  82. * &minus;\e S12. (This occurs when the longitude difference is near
  83. * &plusmn;180&deg; for oblate ellipsoids.)
  84. * - \e lon2 = \e lon1 &plusmn; 180&deg; (with neither point at a pole).
  85. * If \e azi1 = 0&deg; or &plusmn;180&deg;, the geodesic is unique.
  86. * Otherwise there are two geodesics and the second one is obtained by
  87. * setting [\e azi1, \e azi2] = [&minus;\e azi1, &minus;\e azi2], \e S12
  88. * = &minus;\e S12. (This occurs when \e lat2 is near &minus;\e lat1 for
  89. * prolate ellipsoids.)
  90. * - Points 1 and 2 at opposite poles. There are infinitely many
  91. * geodesics which can be generated by setting [\e azi1, \e azi2] =
  92. * [\e azi1, \e azi2] + [\e d, &minus;\e d], for arbitrary \e d. (For
  93. * spheres, this prescription applies when points 1 and 2 are
  94. * antipodal.)
  95. * - \e s12 = 0 (coincident points). There are infinitely many geodesics
  96. * which can be generated by setting [\e azi1, \e azi2] = [\e azi1, \e
  97. * azi2] + [\e d, \e d], for arbitrary \e d.
  98. *
  99. * These routines are a simple transcription of the corresponding C++ classes
  100. * in <a href="http://geographiclib.sf.net"> GeographicLib</a>. The "class
  101. * data" is represented by the structs geod_geodesic, geod_geodesicline,
  102. * geod_polygon and pointers to these objects are passed as initial arguments
  103. * to the member functions. Most of the internal comments have been retained.
  104. * However, in the process of transcription some documentation has been lost
  105. * and the documentation for the C++ classes, GeographicLib::Geodesic,
  106. * GeographicLib::GeodesicLine, and GeographicLib::PolygonAreaT, should be
  107. * consulted. The C++ code remains the "reference implementation". Think
  108. * twice about restructuring the internals of the C code since this may make
  109. * porting fixes from the C++ code more difficult.
  110. *
  111. * Copyright (c) Charles Karney (2012-2014) <charles@karney.com> and licensed
  112. * under the MIT/X11 License. For more information, see
  113. * http://geographiclib.sourceforge.net/
  114. *
  115. * This library was distributed with
  116. * <a href="../index.html">GeographicLib</a> 1.40.
  117. **********************************************************************/
  118. #if !defined(GEODESIC_H)
  119. #define GEODESIC_H 1
  120. /**
  121. * The major version of the geodesic library. (This tracks the version of
  122. * GeographicLib.)
  123. **********************************************************************/
  124. #define GEODESIC_VERSION_MAJOR 1
  125. /**
  126. * The minor version of the geodesic library. (This tracks the version of
  127. * GeographicLib.)
  128. **********************************************************************/
  129. #define GEODESIC_VERSION_MINOR 40
  130. /**
  131. * The patch level of the geodesic library. (This tracks the version of
  132. * GeographicLib.)
  133. **********************************************************************/
  134. #define GEODESIC_VERSION_PATCH 0
  135. #if defined(__cplusplus)
  136. extern "C" {
  137. #endif
  138. /**
  139. * The struct containing information about the ellipsoid. This must be
  140. * initialized by geod_init() before use.
  141. **********************************************************************/
  142. struct geod_geodesic {
  143. double a; /**< the equatorial radius */
  144. double f; /**< the flattening */
  145. /**< @cond SKIP */
  146. double f1, e2, ep2, n, b, c2, etol2;
  147. double A3x[6], C3x[15], C4x[21];
  148. /**< @endcond */
  149. };
  150. /**
  151. * The struct containing information about a single geodesic. This must be
  152. * initialized by geod_lineinit() before use.
  153. **********************************************************************/
  154. struct geod_geodesicline {
  155. double lat1; /**< the starting latitude */
  156. double lon1; /**< the starting longitude */
  157. double azi1; /**< the starting azimuth */
  158. double a; /**< the equatorial radius */
  159. double f; /**< the flattening */
  160. /**< @cond SKIP */
  161. double b, c2, f1, salp0, calp0, k2,
  162. salp1, calp1, ssig1, csig1, dn1, stau1, ctau1, somg1, comg1,
  163. A1m1, A2m1, A3c, B11, B21, B31, A4, B41;
  164. double C1a[6+1], C1pa[6+1], C2a[6+1], C3a[6], C4a[6];
  165. /**< @endcond */
  166. unsigned caps; /**< the capabilities */
  167. };
  168. /**
  169. * The struct for accumulating information about a geodesic polygon. This is
  170. * used for computing the perimeter and area of a polygon. This must be
  171. * initialized by geod_polygon_init() before use.
  172. **********************************************************************/
  173. struct geod_polygon {
  174. double lat; /**< the current latitude */
  175. double lon; /**< the current longitude */
  176. /**< @cond SKIP */
  177. double lat0;
  178. double lon0;
  179. double A[2];
  180. double P[2];
  181. int polyline;
  182. int crossings;
  183. /**< @endcond */
  184. unsigned num; /**< the number of points so far */
  185. };
  186. /**
  187. * Initialize a geod_geodesic object.
  188. *
  189. * @param[out] g a pointer to the object to be initialized.
  190. * @param[in] a the equatorial radius (meters).
  191. * @param[in] f the flattening.
  192. **********************************************************************/
  193. void geod_init(struct geod_geodesic* g, double a, double f);
  194. /**
  195. * Initialize a geod_geodesicline object.
  196. *
  197. * @param[out] l a pointer to the object to be initialized.
  198. * @param[in] g a pointer to the geod_geodesic object specifying the
  199. * ellipsoid.
  200. * @param[in] lat1 latitude of point 1 (degrees).
  201. * @param[in] lon1 longitude of point 1 (degrees).
  202. * @param[in] azi1 azimuth at point 1 (degrees).
  203. * @param[in] caps bitor'ed combination of geod_mask() values specifying the
  204. * capabilities the geod_geodesicline object should possess, i.e., which
  205. * quantities can be returned in calls to geod_position() and
  206. * geod_genposition().
  207. *
  208. * \e g must have been initialized with a call to geod_init(). \e lat1
  209. * should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and \e azi1
  210. * should be in the range [&minus;540&deg;, 540&deg;).
  211. *
  212. * The geod_mask values are [see geod_mask()]:
  213. * - \e caps |= GEOD_LATITUDE for the latitude \e lat2; this is
  214. * added automatically,
  215. * - \e caps |= GEOD_LONGITUDE for the latitude \e lon2,
  216. * - \e caps |= GEOD_AZIMUTH for the latitude \e azi2; this is
  217. * added automatically,
  218. * - \e caps |= GEOD_DISTANCE for the distance \e s12,
  219. * - \e caps |= GEOD_REDUCEDLENGTH for the reduced length \e m12,
  220. * - \e caps |= GEOD_GEODESICSCALE for the geodesic scales \e M12
  221. * and \e M21,
  222. * - \e caps |= GEOD_AREA for the area \e S12,
  223. * - \e caps |= GEOD_DISTANCE_IN permits the length of the
  224. * geodesic to be given in terms of \e s12; without this capability the
  225. * length can only be specified in terms of arc length.
  226. * .
  227. * A value of \e caps = 0 is treated as GEOD_LATITUDE | GEOD_LONGITUDE |
  228. * GEOD_AZIMUTH | GEOD_DISTANCE_IN (to support the solution of the "standard"
  229. * direct problem).
  230. **********************************************************************/
  231. void geod_lineinit(struct geod_geodesicline* l,
  232. const struct geod_geodesic* g,
  233. double lat1, double lon1, double azi1, unsigned caps);
  234. /**
  235. * Solve the direct geodesic problem.
  236. *
  237. * @param[in] g a pointer to the geod_geodesic object specifying the
  238. * ellipsoid.
  239. * @param[in] lat1 latitude of point 1 (degrees).
  240. * @param[in] lon1 longitude of point 1 (degrees).
  241. * @param[in] azi1 azimuth at point 1 (degrees).
  242. * @param[in] s12 distance between point 1 and point 2 (meters); it can be
  243. * negative.
  244. * @param[out] plat2 pointer to the latitude of point 2 (degrees).
  245. * @param[out] plon2 pointer to the longitude of point 2 (degrees).
  246. * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees).
  247. *
  248. * \e g must have been initialized with a call to geod_init(). \e lat1
  249. * should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and \e azi1
  250. * should be in the range [&minus;540&deg;, 540&deg;). The values of \e lon2
  251. * and \e azi2 returned are in the range [&minus;180&deg;, 180&deg;). Any of
  252. * the "return" arguments \e plat2, etc., may be replaced by 0, if you do not
  253. * need some quantities computed.
  254. *
  255. * If either point is at a pole, the azimuth is defined by keeping the
  256. * longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;), and
  257. * taking the limit &epsilon; &rarr; 0+. An arc length greater that 180&deg;
  258. * signifies a geodesic which is not a shortest path. (For a prolate
  259. * ellipsoid, an additional condition is necessary for a shortest path: the
  260. * longitudinal extent must not exceed of 180&deg;.)
  261. *
  262. * Example, determine the point 10000 km NE of JFK:
  263. @code
  264. struct geod_geodesic g;
  265. double lat, lon;
  266. geod_init(&g, 6378137, 1/298.257223563);
  267. geod_direct(&g, 40.64, -73.78, 45.0, 10e6, &lat, &lon, 0);
  268. printf("%.5f %.5f\n", lat, lon);
  269. @endcode
  270. **********************************************************************/
  271. void geod_direct(const struct geod_geodesic* g,
  272. double lat1, double lon1, double azi1, double s12,
  273. double* plat2, double* plon2, double* pazi2);
  274. /**
  275. * Solve the inverse geodesic problem.
  276. *
  277. * @param[in] g a pointer to the geod_geodesic object specifying the
  278. * ellipsoid.
  279. * @param[in] lat1 latitude of point 1 (degrees).
  280. * @param[in] lon1 longitude of point 1 (degrees).
  281. * @param[in] lat2 latitude of point 2 (degrees).
  282. * @param[in] lon2 longitude of point 2 (degrees).
  283. * @param[out] ps12 pointer to the distance between point 1 and point 2
  284. * (meters).
  285. * @param[out] pazi1 pointer to the azimuth at point 1 (degrees).
  286. * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees).
  287. *
  288. * \e g must have been initialized with a call to geod_init(). \e lat1
  289. * and \e lat2 should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and
  290. * \e lon2 should be in the range [&minus;540&deg;, 540&deg;). The values of
  291. * \e azi1 and \e azi2 returned are in the range [&minus;180&deg;, 180&deg;).
  292. * Any of the "return" arguments \e ps12, etc., may be replaced by 0, if you
  293. * do not need some quantities computed.
  294. *
  295. * If either point is at a pole, the azimuth is defined by keeping the
  296. * longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;), and
  297. * taking the limit &epsilon; &rarr; 0+.
  298. *
  299. * The solution to the inverse problem is found using Newton's method. If
  300. * this fails to converge (this is very unlikely in geodetic applications
  301. * but does occur for very eccentric ellipsoids), then the bisection method
  302. * is used to refine the solution.
  303. *
  304. * Example, determine the distance between JFK and Singapore Changi Airport:
  305. @code
  306. struct geod_geodesic g;
  307. double s12;
  308. geod_init(&g, 6378137, 1/298.257223563);
  309. geod_inverse(&g, 40.64, -73.78, 1.36, 103.99, &s12, 0, 0);
  310. printf("%.3f\n", s12);
  311. @endcode
  312. **********************************************************************/
  313. void geod_inverse(const struct geod_geodesic* g,
  314. double lat1, double lon1, double lat2, double lon2,
  315. double* ps12, double* pazi1, double* pazi2);
  316. /**
  317. * Compute the position along a geod_geodesicline.
  318. *
  319. * @param[in] l a pointer to the geod_geodesicline object specifying the
  320. * geodesic line.
  321. * @param[in] s12 distance between point 1 and point 2 (meters); it can be
  322. * negative.
  323. * @param[out] plat2 pointer to the latitude of point 2 (degrees).
  324. * @param[out] plon2 pointer to the longitude of point 2 (degrees); requires
  325. * that \e l was initialized with \e caps |= GEOD_LONGITUDE.
  326. * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees).
  327. *
  328. * \e l must have been initialized with a call to geod_lineinit() with \e
  329. * caps |= GEOD_DISTANCE_IN. The values of \e lon2 and \e azi2 returned are
  330. * in the range [&minus;180&deg;, 180&deg;). Any of the "return" arguments
  331. * \e plat2, etc., may be replaced by 0, if you do not need some quantities
  332. * computed.
  333. *
  334. * Example, compute way points between JFK and Singapore Changi Airport
  335. * the "obvious" way using geod_direct():
  336. @code
  337. struct geod_geodesic g;
  338. double s12, azi1, lat[101],lon[101];
  339. int i;
  340. geod_init(&g, 6378137, 1/298.257223563);
  341. geod_inverse(&g, 40.64, -73.78, 1.36, 103.99, &s12, &azi1, 0);
  342. for (i = 0; i < 101; ++i) {
  343. geod_direct(&g, 40.64, -73.78, azi1, i * s12 * 0.01, lat + i, lon + i, 0);
  344. printf("%.5f %.5f\n", lat[i], lon[i]);
  345. }
  346. @endcode
  347. * A faster way using geod_position():
  348. @code
  349. struct geod_geodesic g;
  350. struct geod_geodesicline l;
  351. double s12, azi1, lat[101],lon[101];
  352. int i;
  353. geod_init(&g, 6378137, 1/298.257223563);
  354. geod_inverse(&g, 40.64, -73.78, 1.36, 103.99, &s12, &azi1, 0);
  355. geod_lineinit(&l, &g, 40.64, -73.78, azi1, 0);
  356. for (i = 0; i < 101; ++i) {
  357. geod_position(&l, i * s12 * 0.01, lat + i, lon + i, 0);
  358. printf("%.5f %.5f\n", lat[i], lon[i]);
  359. }
  360. @endcode
  361. **********************************************************************/
  362. void geod_position(const struct geod_geodesicline* l, double s12,
  363. double* plat2, double* plon2, double* pazi2);
  364. /**
  365. * The general direct geodesic problem.
  366. *
  367. * @param[in] g a pointer to the geod_geodesic object specifying the
  368. * ellipsoid.
  369. * @param[in] lat1 latitude of point 1 (degrees).
  370. * @param[in] lon1 longitude of point 1 (degrees).
  371. * @param[in] azi1 azimuth at point 1 (degrees).
  372. * @param[in] flags bitor'ed combination of geod_flags(); \e flags &
  373. * GEOD_ARCMODE determines the meaning of \e s12_a12 and \e flags &
  374. * GEOD_LONG_NOWRAP prevents the value of \e lon2 being wrapped into
  375. * the range [&minus;180&deg;, 180&deg;).
  376. * @param[in] s12_a12 if \e flags & GEOD_ARCMODE is 0, this is the distance
  377. * between point 1 and point 2 (meters); otherwise it is the arc length
  378. * between point 1 and point 2 (degrees); it can be negative.
  379. * @param[out] plat2 pointer to the latitude of point 2 (degrees).
  380. * @param[out] plon2 pointer to the longitude of point 2 (degrees).
  381. * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees).
  382. * @param[out] ps12 pointer to the distance between point 1 and point 2
  383. * (meters).
  384. * @param[out] pm12 pointer to the reduced length of geodesic (meters).
  385. * @param[out] pM12 pointer to the geodesic scale of point 2 relative to
  386. * point 1 (dimensionless).
  387. * @param[out] pM21 pointer to the geodesic scale of point 1 relative to
  388. * point 2 (dimensionless).
  389. * @param[out] pS12 pointer to the area under the geodesic
  390. * (meters<sup>2</sup>).
  391. * @return \e a12 arc length of between point 1 and point 2 (degrees).
  392. *
  393. * \e g must have been initialized with a call to geod_init(). \e lat1
  394. * should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and \e azi1
  395. * should be in the range [&minus;540&deg;, 540&deg;). The function
  396. * value \e a12 equals \e s12_a12 if \e flags & GEOD_ARCMODE. Any of the
  397. * "return" arguments \e plat2, etc., may be replaced by 0, if you do not
  398. * need some quantities computed.
  399. *
  400. * With \e flags & GEOD_LONG_NOWRAP bit set, the quantity \e lon2 &minus;
  401. * \e lon1 indicates how many times the geodesic wrapped around the
  402. * ellipsoid. Because \e lon2 might be outside the normal allowed range
  403. * for longitudes, [&minus;540&deg;, 540&deg;), be sure to normalize it,
  404. * e.g., with fmod(\e lon2, 360.0) before using it in subsequent
  405. * calculations
  406. **********************************************************************/
  407. double geod_gendirect(const struct geod_geodesic* g,
  408. double lat1, double lon1, double azi1,
  409. unsigned flags, double s12_a12,
  410. double* plat2, double* plon2, double* pazi2,
  411. double* ps12, double* pm12, double* pM12, double* pM21,
  412. double* pS12);
  413. /**
  414. * The general inverse geodesic calculation.
  415. *
  416. * @param[in] g a pointer to the geod_geodesic object specifying the
  417. * ellipsoid.
  418. * @param[in] lat1 latitude of point 1 (degrees).
  419. * @param[in] lon1 longitude of point 1 (degrees).
  420. * @param[in] lat2 latitude of point 2 (degrees).
  421. * @param[in] lon2 longitude of point 2 (degrees).
  422. * @param[out] ps12 pointer to the distance between point 1 and point 2
  423. * (meters).
  424. * @param[out] pazi1 pointer to the azimuth at point 1 (degrees).
  425. * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees).
  426. * @param[out] pm12 pointer to the reduced length of geodesic (meters).
  427. * @param[out] pM12 pointer to the geodesic scale of point 2 relative to
  428. * point 1 (dimensionless).
  429. * @param[out] pM21 pointer to the geodesic scale of point 1 relative to
  430. * point 2 (dimensionless).
  431. * @param[out] pS12 pointer to the area under the geodesic
  432. * (meters<sup>2</sup>).
  433. * @return \e a12 arc length of between point 1 and point 2 (degrees).
  434. *
  435. * \e g must have been initialized with a call to geod_init(). \e lat1
  436. * and \e lat2 should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and
  437. * \e lon2 should be in the range [&minus;540&deg;, 540&deg;). Any of the
  438. * "return" arguments \e ps12, etc., may be replaced by 0, if you do not need
  439. * some quantities computed.
  440. **********************************************************************/
  441. double geod_geninverse(const struct geod_geodesic* g,
  442. double lat1, double lon1, double lat2, double lon2,
  443. double* ps12, double* pazi1, double* pazi2,
  444. double* pm12, double* pM12, double* pM21,
  445. double* pS12);
  446. /**
  447. * The general position function.
  448. *
  449. * @param[in] l a pointer to the geod_geodesicline object specifying the
  450. * geodesic line.
  451. * @param[in] flags bitor'ed combination of geod_flags(); \e flags &
  452. * GEOD_ARCMODE determines the meaning of \e s12_a12 and \e flags &
  453. * GEOD_LONG_NOWRAP prevents the value of \e lon2 being wrapped into
  454. * the range [&minus;180&deg;, 180&deg;); if \e flags & GEOD_ARCMODE is
  455. * 0, then \e l must have been initialized with \e caps |=
  456. * GEOD_DISTANCE_IN.
  457. * @param[in] s12_a12 if \e flags & GEOD_ARCMODE is 0, this is the
  458. * distance between point 1 and point 2 (meters); otherwise it is the
  459. * arc length between point 1 and point 2 (degrees); it can be
  460. * negative.
  461. * @param[out] plat2 pointer to the latitude of point 2 (degrees).
  462. * @param[out] plon2 pointer to the longitude of point 2 (degrees); requires
  463. * that \e l was initialized with \e caps |= GEOD_LONGITUDE.
  464. * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees).
  465. * @param[out] ps12 pointer to the distance between point 1 and point 2
  466. * (meters); requires that \e l was initialized with \e caps |=
  467. * GEOD_DISTANCE.
  468. * @param[out] pm12 pointer to the reduced length of geodesic (meters);
  469. * requires that \e l was initialized with \e caps |= GEOD_REDUCEDLENGTH.
  470. * @param[out] pM12 pointer to the geodesic scale of point 2 relative to
  471. * point 1 (dimensionless); requires that \e l was initialized with \e caps
  472. * |= GEOD_GEODESICSCALE.
  473. * @param[out] pM21 pointer to the geodesic scale of point 1 relative to
  474. * point 2 (dimensionless); requires that \e l was initialized with \e caps
  475. * |= GEOD_GEODESICSCALE.
  476. * @param[out] pS12 pointer to the area under the geodesic
  477. * (meters<sup>2</sup>); requires that \e l was initialized with \e caps |=
  478. * GEOD_AREA.
  479. * @return \e a12 arc length of between point 1 and point 2 (degrees).
  480. *
  481. * \e l must have been initialized with a call to geod_lineinit() with \e
  482. * caps |= GEOD_DISTANCE_IN. The value \e azi2 returned is in the range
  483. * [&minus;180&deg;, 180&deg;). Any of the "return" arguments \e plat2,
  484. * etc., may be replaced by 0, if you do not need some quantities
  485. * computed. Requesting a value which \e l is not capable of computing
  486. * is not an error; the corresponding argument will not be altered.
  487. *
  488. * With \e flags & GEOD_LONG_NOWRAP bit set, the quantity \e lon2 &minus;
  489. * \e lon1 indicates how many times the geodesic wrapped around the
  490. * ellipsoid. Because \e lon2 might be outside the normal allowed range
  491. * for longitudes, [&minus;540&deg;, 540&deg;), be sure to normalize it,
  492. * e.g., with fmod(\e lon2, 360.0) before using it in subsequent
  493. * calculations
  494. *
  495. * Example, compute way points between JFK and Singapore Changi Airport
  496. * using geod_genposition(). In this example, the points are evenly space in
  497. * arc length (and so only approximately equally space in distance). This is
  498. * faster than using geod_position() would be appropriate if drawing the path
  499. * on a map.
  500. @code
  501. struct geod_geodesic g;
  502. struct geod_geodesicline l;
  503. double a12, azi1, lat[101], lon[101];
  504. int i;
  505. geod_init(&g, 6378137, 1/298.257223563);
  506. a12 = geod_geninverse(&g, 40.64, -73.78, 1.36, 103.99,
  507. 0, &azi1, 0, 0, 0, 0, 0);
  508. geod_lineinit(&l, &g, 40.64, -73.78, azi1, GEOD_LATITUDE | GEOD_LONGITUDE);
  509. for (i = 0; i < 101; ++i) {
  510. geod_genposition(&l, 1, i * a12 * 0.01,
  511. lat + i, lon + i, 0, 0, 0, 0, 0, 0);
  512. printf("%.5f %.5f\n", lat[i], lon[i]);
  513. }
  514. @endcode
  515. **********************************************************************/
  516. double geod_genposition(const struct geod_geodesicline* l,
  517. unsigned flags, double s12_a12,
  518. double* plat2, double* plon2, double* pazi2,
  519. double* ps12, double* pm12,
  520. double* pM12, double* pM21,
  521. double* pS12);
  522. /**
  523. * Initialize a geod_polygon object.
  524. *
  525. * @param[out] p a pointer to the object to be initialized.
  526. * @param[in] polylinep non-zero if a polyline instead of a polygon.
  527. *
  528. * If \e polylinep is zero, then the sequence of vertices and edges added by
  529. * geod_polygon_addpoint() and geod_polygon_addedge() define a polygon and
  530. * the perimeter and area are returned by geod_polygon_compute(). If \e
  531. * polylinep is non-zero, then the vertices and edges define a polyline and
  532. * only the perimeter is returned by geod_polygon_compute().
  533. *
  534. * The area and perimeter are accumulated at two times the standard floating
  535. * point precision to guard against the loss of accuracy with many-sided
  536. * polygons. At any point you can ask for the perimeter and area so far.
  537. *
  538. * An example of the use of this function is given in the documentation for
  539. * geod_polygon_compute().
  540. **********************************************************************/
  541. void geod_polygon_init(struct geod_polygon* p, int polylinep);
  542. /**
  543. * Add a point to the polygon or polyline.
  544. *
  545. * @param[in] g a pointer to the geod_geodesic object specifying the
  546. * ellipsoid.
  547. * @param[in,out] p a pointer to the geod_polygon object specifying the
  548. * polygon.
  549. * @param[in] lat the latitude of the point (degrees).
  550. * @param[in] lon the longitude of the point (degrees).
  551. *
  552. * \e g and \e p must have been initialized with calls to geod_init() and
  553. * geod_polygon_init(), respectively. The same \e g must be used for all the
  554. * points and edges in a polygon. \e lat should be in the range
  555. * [&minus;90&deg;, 90&deg;] and \e lon should be in the range
  556. * [&minus;540&deg;, 540&deg;).
  557. *
  558. * An example of the use of this function is given in the documentation for
  559. * geod_polygon_compute().
  560. **********************************************************************/
  561. void geod_polygon_addpoint(const struct geod_geodesic* g,
  562. struct geod_polygon* p,
  563. double lat, double lon);
  564. /**
  565. * Add an edge to the polygon or polyline.
  566. *
  567. * @param[in] g a pointer to the geod_geodesic object specifying the
  568. * ellipsoid.
  569. * @param[in,out] p a pointer to the geod_polygon object specifying the
  570. * polygon.
  571. * @param[in] azi azimuth at current point (degrees).
  572. * @param[in] s distance from current point to next point (meters).
  573. *
  574. * \e g and \e p must have been initialized with calls to geod_init() and
  575. * geod_polygon_init(), respectively. The same \e g must be used for all the
  576. * points and edges in a polygon. \e azi should be in the range
  577. * [&minus;540&deg;, 540&deg;). This does nothing if no points have been
  578. * added yet. The \e lat and \e lon fields of \e p give the location of
  579. * the new vertex.
  580. **********************************************************************/
  581. void geod_polygon_addedge(const struct geod_geodesic* g,
  582. struct geod_polygon* p,
  583. double azi, double s);
  584. /**
  585. * Return the results for a polygon.
  586. *
  587. * @param[in] g a pointer to the geod_geodesic object specifying the
  588. * ellipsoid.
  589. * @param[in] p a pointer to the geod_polygon object specifying the polygon.
  590. * @param[in] reverse if non-zero then clockwise (instead of
  591. * counter-clockwise) traversal counts as a positive area.
  592. * @param[in] sign if non-zero then return a signed result for the area if
  593. * the polygon is traversed in the "wrong" direction instead of returning
  594. * the area for the rest of the earth.
  595. * @param[out] pA pointer to the area of the polygon (meters<sup>2</sup>);
  596. * only set if \e polyline is non-zero in the call to geod_polygon_init().
  597. * @param[out] pP pointer to the perimeter of the polygon or length of the
  598. * polyline (meters).
  599. * @return the number of points.
  600. *
  601. * The area and perimeter are accumulated at two times the standard floating
  602. * point precision to guard against the loss of accuracy with many-sided
  603. * polygons. Only simple polygons (which are not self-intersecting) are
  604. * allowed. There's no need to "close" the polygon by repeating the first
  605. * vertex. Set \e pA or \e pP to zero, if you do not want the corresponding
  606. * quantity returned.
  607. *
  608. * Example, compute the perimeter and area of the geodesic triangle with
  609. * vertices (0&deg;N,0&deg;E), (0&deg;N,90&deg;E), (90&deg;N,0&deg;E).
  610. @code
  611. double A, P;
  612. int n;
  613. struct geod_geodesic g;
  614. struct geod_polygon p;
  615. geod_init(&g, 6378137, 1/298.257223563);
  616. geod_polygon_init(&p, 0);
  617. geod_polygon_addpoint(&g, &p, 0, 0);
  618. geod_polygon_addpoint(&g, &p, 0, 90);
  619. geod_polygon_addpoint(&g, &p, 90, 0);
  620. n = geod_polygon_compute(&g, &p, 0, 1, &A, &P);
  621. printf("%d %.8f %.3f\n", n, P, A);
  622. @endcode
  623. **********************************************************************/
  624. unsigned geod_polygon_compute(const struct geod_geodesic* g,
  625. const struct geod_polygon* p,
  626. int reverse, int sign,
  627. double* pA, double* pP);
  628. /**
  629. * Return the results assuming a tentative final test point is added;
  630. * however, the data for the test point is not saved. This lets you report a
  631. * running result for the perimeter and area as the user moves the mouse
  632. * cursor. Ordinary floating point arithmetic is used to accumulate the data
  633. * for the test point; thus the area and perimeter returned are less accurate
  634. * than if geod_polygon_addpoint() and geod_polygon_compute() are used.
  635. *
  636. * @param[in] g a pointer to the geod_geodesic object specifying the
  637. * ellipsoid.
  638. * @param[in] p a pointer to the geod_polygon object specifying the polygon.
  639. * @param[in] lat the latitude of the test point (degrees).
  640. * @param[in] lon the longitude of the test point (degrees).
  641. * @param[in] reverse if non-zero then clockwise (instead of
  642. * counter-clockwise) traversal counts as a positive area.
  643. * @param[in] sign if non-zero then return a signed result for the area if
  644. * the polygon is traversed in the "wrong" direction instead of returning
  645. * the area for the rest of the earth.
  646. * @param[out] pA pointer to the area of the polygon (meters<sup>2</sup>);
  647. * only set if \e polyline is non-zero in the call to geod_polygon_init().
  648. * @param[out] pP pointer to the perimeter of the polygon or length of the
  649. * polyline (meters).
  650. * @return the number of points.
  651. *
  652. * \e lat should be in the range [&minus;90&deg;, 90&deg;] and \e
  653. * lon should be in the range [&minus;540&deg;, 540&deg;).
  654. **********************************************************************/
  655. unsigned geod_polygon_testpoint(const struct geod_geodesic* g,
  656. const struct geod_polygon* p,
  657. double lat, double lon,
  658. int reverse, int sign,
  659. double* pA, double* pP);
  660. /**
  661. * Return the results assuming a tentative final test point is added via an
  662. * azimuth and distance; however, the data for the test point is not saved.
  663. * This lets you report a running result for the perimeter and area as the
  664. * user moves the mouse cursor. Ordinary floating point arithmetic is used
  665. * to accumulate the data for the test point; thus the area and perimeter
  666. * returned are less accurate than if geod_polygon_addedge() and
  667. * geod_polygon_compute() are used.
  668. *
  669. * @param[in] g a pointer to the geod_geodesic object specifying the
  670. * ellipsoid.
  671. * @param[in] p a pointer to the geod_polygon object specifying the polygon.
  672. * @param[in] azi azimuth at current point (degrees).
  673. * @param[in] s distance from current point to final test point (meters).
  674. * @param[in] reverse if non-zero then clockwise (instead of
  675. * counter-clockwise) traversal counts as a positive area.
  676. * @param[in] sign if non-zero then return a signed result for the area if
  677. * the polygon is traversed in the "wrong" direction instead of returning
  678. * the area for the rest of the earth.
  679. * @param[out] pA pointer to the area of the polygon (meters<sup>2</sup>);
  680. * only set if \e polyline is non-zero in the call to geod_polygon_init().
  681. * @param[out] pP pointer to the perimeter of the polygon or length of the
  682. * polyline (meters).
  683. * @return the number of points.
  684. *
  685. * \e azi should be in the range [&minus;540&deg;, 540&deg;).
  686. **********************************************************************/
  687. unsigned geod_polygon_testedge(const struct geod_geodesic* g,
  688. const struct geod_polygon* p,
  689. double azi, double s,
  690. int reverse, int sign,
  691. double* pA, double* pP);
  692. /**
  693. * A simple interface for computing the area of a geodesic polygon.
  694. *
  695. * @param[in] g a pointer to the geod_geodesic object specifying the
  696. * ellipsoid.
  697. * @param[in] lats an array of latitudes of the polygon vertices (degrees).
  698. * @param[in] lons an array of longitudes of the polygon vertices (degrees).
  699. * @param[in] n the number of vertices.
  700. * @param[out] pA pointer to the area of the polygon (meters<sup>2</sup>).
  701. * @param[out] pP pointer to the perimeter of the polygon (meters).
  702. *
  703. * \e lats should be in the range [&minus;90&deg;, 90&deg;]; \e lons should
  704. * be in the range [&minus;540&deg;, 540&deg;).
  705. *
  706. * Only simple polygons (which are not self-intersecting) are allowed.
  707. * There's no need to "close" the polygon by repeating the first vertex. The
  708. * area returned is signed with counter-clockwise traversal being treated as
  709. * positive.
  710. *
  711. * Example, compute the area of Antarctica:
  712. @code
  713. double
  714. lats[] = {-72.9, -71.9, -74.9, -74.3, -77.5, -77.4, -71.7, -65.9, -65.7,
  715. -66.6, -66.9, -69.8, -70.0, -71.0, -77.3, -77.9, -74.7},
  716. lons[] = {-74, -102, -102, -131, -163, 163, 172, 140, 113,
  717. 88, 59, 25, -4, -14, -33, -46, -61};
  718. struct geod_geodesic g;
  719. double A, P;
  720. geod_init(&g, 6378137, 1/298.257223563);
  721. geod_polygonarea(&g, lats, lons, (sizeof lats) / (sizeof lats[0]), &A, &P);
  722. printf("%.0f %.2f\n", A, P);
  723. @endcode
  724. **********************************************************************/
  725. void geod_polygonarea(const struct geod_geodesic* g,
  726. double lats[], double lons[], int n,
  727. double* pA, double* pP);
  728. /**
  729. * mask values for the \e caps argument to geod_lineinit().
  730. **********************************************************************/
  731. enum geod_mask {
  732. GEOD_NONE = 0U, /**< Calculate nothing */
  733. GEOD_LATITUDE = 1U<<7 | 0U, /**< Calculate latitude */
  734. GEOD_LONGITUDE = 1U<<8 | 1U<<3, /**< Calculate longitude */
  735. GEOD_AZIMUTH = 1U<<9 | 0U, /**< Calculate azimuth */
  736. GEOD_DISTANCE = 1U<<10 | 1U<<0, /**< Calculate distance */
  737. GEOD_DISTANCE_IN = 1U<<11 | 1U<<0 | 1U<<1, /**< Allow distance as input */
  738. GEOD_REDUCEDLENGTH= 1U<<12 | 1U<<0 | 1U<<2, /**< Calculate reduced length */
  739. GEOD_GEODESICSCALE= 1U<<13 | 1U<<0 | 1U<<2, /**< Calculate geodesic scale */
  740. GEOD_AREA = 1U<<14 | 1U<<4, /**< Calculate reduced length */
  741. GEOD_ALL = 0x7F80U| 0x1FU /**< Calculate everything */
  742. };
  743. /**
  744. * flag values for the \e flags argument to geod_gendirect() and
  745. * geod_genposition()
  746. **********************************************************************/
  747. enum geod_flags {
  748. GEOD_NOFLAGS = 0U, /**< No flags */
  749. GEOD_ARCMODE = 1U<<0, /**< Position given in terms of arc distance */
  750. GEOD_LONG_NOWRAP = 1U<<15 /**< Don't wrap longitude */
  751. };
  752. #if defined(__cplusplus)
  753. }
  754. #endif
  755. #endif