LocalCartesian.hpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /**
  2. * \file LocalCartesian.hpp
  3. * \brief Header for GeographicLib::LocalCartesian class
  4. *
  5. * Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
  6. * under the MIT/X11 License. For more information, see
  7. * https://geographiclib.sourceforge.io/
  8. **********************************************************************/
  9. #if !defined(GEOGRAPHICLIB_LOCALCARTESIAN_HPP)
  10. #define GEOGRAPHICLIB_LOCALCARTESIAN_HPP 1
  11. #include <GeographicLib/Geocentric.hpp>
  12. #include <GeographicLib/Constants.hpp>
  13. namespace GeographicLib {
  14. /**
  15. * \brief Local cartesian coordinates
  16. *
  17. * Convert between geodetic coordinates latitude = \e lat, longitude = \e
  18. * lon, height = \e h (measured vertically from the surface of the ellipsoid)
  19. * to local cartesian coordinates (\e x, \e y, \e z). The origin of local
  20. * cartesian coordinate system is at \e lat = \e lat0, \e lon = \e lon0, \e h
  21. * = \e h0. The \e z axis is normal to the ellipsoid; the \e y axis points
  22. * due north. The plane \e z = - \e h0 is tangent to the ellipsoid.
  23. *
  24. * The conversions all take place via geocentric coordinates using a
  25. * Geocentric object (by default Geocentric::WGS84()).
  26. *
  27. * Example of use:
  28. * \include example-LocalCartesian.cpp
  29. *
  30. * <a href="CartConvert.1.html">CartConvert</a> is a command-line utility
  31. * providing access to the functionality of Geocentric and LocalCartesian.
  32. **********************************************************************/
  33. class GEOGRAPHICLIB_EXPORT LocalCartesian {
  34. private:
  35. typedef Math::real real;
  36. static const size_t dim_ = 3;
  37. static const size_t dim2_ = dim_ * dim_;
  38. Geocentric _earth;
  39. real _lat0, _lon0, _h0;
  40. real _x0, _y0, _z0, _r[dim2_];
  41. void IntForward(real lat, real lon, real h, real& x, real& y, real& z,
  42. real M[dim2_]) const;
  43. void IntReverse(real x, real y, real z, real& lat, real& lon, real& h,
  44. real M[dim2_]) const;
  45. void MatrixMultiply(real M[dim2_]) const;
  46. public:
  47. /**
  48. * Constructor setting the origin.
  49. *
  50. * @param[in] lat0 latitude at origin (degrees).
  51. * @param[in] lon0 longitude at origin (degrees).
  52. * @param[in] h0 height above ellipsoid at origin (meters); default 0.
  53. * @param[in] earth Geocentric object for the transformation; default
  54. * Geocentric::WGS84().
  55. *
  56. * \e lat0 should be in the range [&minus;90&deg;, 90&deg;].
  57. **********************************************************************/
  58. LocalCartesian(real lat0, real lon0, real h0 = 0,
  59. const Geocentric& earth = Geocentric::WGS84())
  60. : _earth(earth)
  61. { Reset(lat0, lon0, h0); }
  62. /**
  63. * Default constructor.
  64. *
  65. * @param[in] earth Geocentric object for the transformation; default
  66. * Geocentric::WGS84().
  67. *
  68. * Sets \e lat0 = 0, \e lon0 = 0, \e h0 = 0.
  69. **********************************************************************/
  70. explicit LocalCartesian(const Geocentric& earth = Geocentric::WGS84())
  71. : _earth(earth)
  72. { Reset(real(0), real(0), real(0)); }
  73. /**
  74. * Reset the origin.
  75. *
  76. * @param[in] lat0 latitude at origin (degrees).
  77. * @param[in] lon0 longitude at origin (degrees).
  78. * @param[in] h0 height above ellipsoid at origin (meters); default 0.
  79. *
  80. * \e lat0 should be in the range [&minus;90&deg;, 90&deg;].
  81. **********************************************************************/
  82. void Reset(real lat0, real lon0, real h0 = 0);
  83. /**
  84. * Convert from geodetic to local cartesian coordinates.
  85. *
  86. * @param[in] lat latitude of point (degrees).
  87. * @param[in] lon longitude of point (degrees).
  88. * @param[in] h height of point above the ellipsoid (meters).
  89. * @param[out] x local cartesian coordinate (meters).
  90. * @param[out] y local cartesian coordinate (meters).
  91. * @param[out] z local cartesian coordinate (meters).
  92. *
  93. * \e lat should be in the range [&minus;90&deg;, 90&deg;].
  94. **********************************************************************/
  95. void Forward(real lat, real lon, real h, real& x, real& y, real& z)
  96. const {
  97. IntForward(lat, lon, h, x, y, z, NULL);
  98. }
  99. /**
  100. * Convert from geodetic to local cartesian coordinates and return rotation
  101. * matrix.
  102. *
  103. * @param[in] lat latitude of point (degrees).
  104. * @param[in] lon longitude of point (degrees).
  105. * @param[in] h height of point above the ellipsoid (meters).
  106. * @param[out] x local cartesian coordinate (meters).
  107. * @param[out] y local cartesian coordinate (meters).
  108. * @param[out] z local cartesian coordinate (meters).
  109. * @param[out] M if the length of the vector is 9, fill with the rotation
  110. * matrix in row-major order.
  111. *
  112. * \e lat should be in the range [&minus;90&deg;, 90&deg;].
  113. *
  114. * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
  115. * express \e v as \e column vectors in one of two ways
  116. * - in east, north, up coordinates (where the components are relative to a
  117. * local coordinate system at (\e lat, \e lon, \e h)); call this
  118. * representation \e v1.
  119. * - in \e x, \e y, \e z coordinates (where the components are relative to
  120. * the local coordinate system at (\e lat0, \e lon0, \e h0)); call this
  121. * representation \e v0.
  122. * .
  123. * Then we have \e v0 = \e M &sdot; \e v1.
  124. **********************************************************************/
  125. void Forward(real lat, real lon, real h, real& x, real& y, real& z,
  126. std::vector<real>& M)
  127. const {
  128. if (M.end() == M.begin() + dim2_) {
  129. real t[dim2_];
  130. IntForward(lat, lon, h, x, y, z, t);
  131. std::copy(t, t + dim2_, M.begin());
  132. } else
  133. IntForward(lat, lon, h, x, y, z, NULL);
  134. }
  135. /**
  136. * Convert from local cartesian to geodetic coordinates.
  137. *
  138. * @param[in] x local cartesian coordinate (meters).
  139. * @param[in] y local cartesian coordinate (meters).
  140. * @param[in] z local cartesian coordinate (meters).
  141. * @param[out] lat latitude of point (degrees).
  142. * @param[out] lon longitude of point (degrees).
  143. * @param[out] h height of point above the ellipsoid (meters).
  144. *
  145. * In general, there are multiple solutions and the result which minimizes
  146. * |<i>h</i> |is returned, i.e., (<i>lat</i>, <i>lon</i>) corresponds to
  147. * the closest point on the ellipsoid. The value of \e lon returned is in
  148. * the range [&minus;180&deg;, 180&deg;].
  149. **********************************************************************/
  150. void Reverse(real x, real y, real z, real& lat, real& lon, real& h)
  151. const {
  152. IntReverse(x, y, z, lat, lon, h, NULL);
  153. }
  154. /**
  155. * Convert from local cartesian to geodetic coordinates and return rotation
  156. * matrix.
  157. *
  158. * @param[in] x local cartesian coordinate (meters).
  159. * @param[in] y local cartesian coordinate (meters).
  160. * @param[in] z local cartesian coordinate (meters).
  161. * @param[out] lat latitude of point (degrees).
  162. * @param[out] lon longitude of point (degrees).
  163. * @param[out] h height of point above the ellipsoid (meters).
  164. * @param[out] M if the length of the vector is 9, fill with the rotation
  165. * matrix in row-major order.
  166. *
  167. * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
  168. * express \e v as \e column vectors in one of two ways
  169. * - in east, north, up coordinates (where the components are relative to a
  170. * local coordinate system at (\e lat, \e lon, \e h)); call this
  171. * representation \e v1.
  172. * - in \e x, \e y, \e z coordinates (where the components are relative to
  173. * the local coordinate system at (\e lat0, \e lon0, \e h0)); call this
  174. * representation \e v0.
  175. * .
  176. * Then we have \e v1 = <i>M</i><sup>T</sup> &sdot; \e v0, where
  177. * <i>M</i><sup>T</sup> is the transpose of \e M.
  178. **********************************************************************/
  179. void Reverse(real x, real y, real z, real& lat, real& lon, real& h,
  180. std::vector<real>& M)
  181. const {
  182. if (M.end() == M.begin() + dim2_) {
  183. real t[dim2_];
  184. IntReverse(x, y, z, lat, lon, h, t);
  185. std::copy(t, t + dim2_, M.begin());
  186. } else
  187. IntReverse(x, y, z, lat, lon, h, NULL);
  188. }
  189. /** \name Inspector functions
  190. **********************************************************************/
  191. ///@{
  192. /**
  193. * @return latitude of the origin (degrees).
  194. **********************************************************************/
  195. Math::real LatitudeOrigin() const { return _lat0; }
  196. /**
  197. * @return longitude of the origin (degrees).
  198. **********************************************************************/
  199. Math::real LongitudeOrigin() const { return _lon0; }
  200. /**
  201. * @return height of the origin (meters).
  202. **********************************************************************/
  203. Math::real HeightOrigin() const { return _h0; }
  204. /**
  205. * @return \e a the equatorial radius of the ellipsoid (meters). This is
  206. * the value of \e a inherited from the Geocentric object used in the
  207. * constructor.
  208. **********************************************************************/
  209. Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
  210. /**
  211. * @return \e f the flattening of the ellipsoid. This is the value
  212. * inherited from the Geocentric object used in the constructor.
  213. **********************************************************************/
  214. Math::real Flattening() const { return _earth.Flattening(); }
  215. /**
  216. * \deprecated An old name for EquatorialRadius().
  217. **********************************************************************/
  218. GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
  219. Math::real MajorRadius() const { return EquatorialRadius(); }
  220. ///@}
  221. };
  222. } // namespace GeographicLib
  223. #endif // GEOGRAPHICLIB_LOCALCARTESIAN_HPP