123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- /**
- * \file LocalCartesian.hpp
- * \brief Header for GeographicLib::LocalCartesian class
- *
- * Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
- * under the MIT/X11 License. For more information, see
- * https://geographiclib.sourceforge.io/
- **********************************************************************/
- #if !defined(GEOGRAPHICLIB_LOCALCARTESIAN_HPP)
- #define GEOGRAPHICLIB_LOCALCARTESIAN_HPP 1
- #include <GeographicLib/Geocentric.hpp>
- #include <GeographicLib/Constants.hpp>
- namespace GeographicLib {
- /**
- * \brief Local cartesian coordinates
- *
- * Convert between geodetic coordinates latitude = \e lat, longitude = \e
- * lon, height = \e h (measured vertically from the surface of the ellipsoid)
- * to local cartesian coordinates (\e x, \e y, \e z). The origin of local
- * cartesian coordinate system is at \e lat = \e lat0, \e lon = \e lon0, \e h
- * = \e h0. The \e z axis is normal to the ellipsoid; the \e y axis points
- * due north. The plane \e z = - \e h0 is tangent to the ellipsoid.
- *
- * The conversions all take place via geocentric coordinates using a
- * Geocentric object (by default Geocentric::WGS84()).
- *
- * Example of use:
- * \include example-LocalCartesian.cpp
- *
- * <a href="CartConvert.1.html">CartConvert</a> is a command-line utility
- * providing access to the functionality of Geocentric and LocalCartesian.
- **********************************************************************/
- class GEOGRAPHICLIB_EXPORT LocalCartesian {
- private:
- typedef Math::real real;
- static const size_t dim_ = 3;
- static const size_t dim2_ = dim_ * dim_;
- Geocentric _earth;
- real _lat0, _lon0, _h0;
- real _x0, _y0, _z0, _r[dim2_];
- void IntForward(real lat, real lon, real h, real& x, real& y, real& z,
- real M[dim2_]) const;
- void IntReverse(real x, real y, real z, real& lat, real& lon, real& h,
- real M[dim2_]) const;
- void MatrixMultiply(real M[dim2_]) const;
- public:
- /**
- * Constructor setting the origin.
- *
- * @param[in] lat0 latitude at origin (degrees).
- * @param[in] lon0 longitude at origin (degrees).
- * @param[in] h0 height above ellipsoid at origin (meters); default 0.
- * @param[in] earth Geocentric object for the transformation; default
- * Geocentric::WGS84().
- *
- * \e lat0 should be in the range [−90°, 90°].
- **********************************************************************/
- LocalCartesian(real lat0, real lon0, real h0 = 0,
- const Geocentric& earth = Geocentric::WGS84())
- : _earth(earth)
- { Reset(lat0, lon0, h0); }
- /**
- * Default constructor.
- *
- * @param[in] earth Geocentric object for the transformation; default
- * Geocentric::WGS84().
- *
- * Sets \e lat0 = 0, \e lon0 = 0, \e h0 = 0.
- **********************************************************************/
- explicit LocalCartesian(const Geocentric& earth = Geocentric::WGS84())
- : _earth(earth)
- { Reset(real(0), real(0), real(0)); }
- /**
- * Reset the origin.
- *
- * @param[in] lat0 latitude at origin (degrees).
- * @param[in] lon0 longitude at origin (degrees).
- * @param[in] h0 height above ellipsoid at origin (meters); default 0.
- *
- * \e lat0 should be in the range [−90°, 90°].
- **********************************************************************/
- void Reset(real lat0, real lon0, real h0 = 0);
- /**
- * Convert from geodetic to local cartesian coordinates.
- *
- * @param[in] lat latitude of point (degrees).
- * @param[in] lon longitude of point (degrees).
- * @param[in] h height of point above the ellipsoid (meters).
- * @param[out] x local cartesian coordinate (meters).
- * @param[out] y local cartesian coordinate (meters).
- * @param[out] z local cartesian coordinate (meters).
- *
- * \e lat should be in the range [−90°, 90°].
- **********************************************************************/
- void Forward(real lat, real lon, real h, real& x, real& y, real& z)
- const {
- IntForward(lat, lon, h, x, y, z, NULL);
- }
- /**
- * Convert from geodetic to local cartesian coordinates and return rotation
- * matrix.
- *
- * @param[in] lat latitude of point (degrees).
- * @param[in] lon longitude of point (degrees).
- * @param[in] h height of point above the ellipsoid (meters).
- * @param[out] x local cartesian coordinate (meters).
- * @param[out] y local cartesian coordinate (meters).
- * @param[out] z local cartesian coordinate (meters).
- * @param[out] M if the length of the vector is 9, fill with the rotation
- * matrix in row-major order.
- *
- * \e lat should be in the range [−90°, 90°].
- *
- * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
- * express \e v as \e column vectors in one of two ways
- * - in east, north, up coordinates (where the components are relative to a
- * local coordinate system at (\e lat, \e lon, \e h)); call this
- * representation \e v1.
- * - in \e x, \e y, \e z coordinates (where the components are relative to
- * the local coordinate system at (\e lat0, \e lon0, \e h0)); call this
- * representation \e v0.
- * .
- * Then we have \e v0 = \e M ⋅ \e v1.
- **********************************************************************/
- void Forward(real lat, real lon, real h, real& x, real& y, real& z,
- std::vector<real>& M)
- const {
- if (M.end() == M.begin() + dim2_) {
- real t[dim2_];
- IntForward(lat, lon, h, x, y, z, t);
- std::copy(t, t + dim2_, M.begin());
- } else
- IntForward(lat, lon, h, x, y, z, NULL);
- }
- /**
- * Convert from local cartesian to geodetic coordinates.
- *
- * @param[in] x local cartesian coordinate (meters).
- * @param[in] y local cartesian coordinate (meters).
- * @param[in] z local cartesian coordinate (meters).
- * @param[out] lat latitude of point (degrees).
- * @param[out] lon longitude of point (degrees).
- * @param[out] h height of point above the ellipsoid (meters).
- *
- * In general, there are multiple solutions and the result which minimizes
- * |<i>h</i> |is returned, i.e., (<i>lat</i>, <i>lon</i>) corresponds to
- * the closest point on the ellipsoid. The value of \e lon returned is in
- * the range [−180°, 180°].
- **********************************************************************/
- void Reverse(real x, real y, real z, real& lat, real& lon, real& h)
- const {
- IntReverse(x, y, z, lat, lon, h, NULL);
- }
- /**
- * Convert from local cartesian to geodetic coordinates and return rotation
- * matrix.
- *
- * @param[in] x local cartesian coordinate (meters).
- * @param[in] y local cartesian coordinate (meters).
- * @param[in] z local cartesian coordinate (meters).
- * @param[out] lat latitude of point (degrees).
- * @param[out] lon longitude of point (degrees).
- * @param[out] h height of point above the ellipsoid (meters).
- * @param[out] M if the length of the vector is 9, fill with the rotation
- * matrix in row-major order.
- *
- * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
- * express \e v as \e column vectors in one of two ways
- * - in east, north, up coordinates (where the components are relative to a
- * local coordinate system at (\e lat, \e lon, \e h)); call this
- * representation \e v1.
- * - in \e x, \e y, \e z coordinates (where the components are relative to
- * the local coordinate system at (\e lat0, \e lon0, \e h0)); call this
- * representation \e v0.
- * .
- * Then we have \e v1 = <i>M</i><sup>T</sup> ⋅ \e v0, where
- * <i>M</i><sup>T</sup> is the transpose of \e M.
- **********************************************************************/
- void Reverse(real x, real y, real z, real& lat, real& lon, real& h,
- std::vector<real>& M)
- const {
- if (M.end() == M.begin() + dim2_) {
- real t[dim2_];
- IntReverse(x, y, z, lat, lon, h, t);
- std::copy(t, t + dim2_, M.begin());
- } else
- IntReverse(x, y, z, lat, lon, h, NULL);
- }
- /** \name Inspector functions
- **********************************************************************/
- ///@{
- /**
- * @return latitude of the origin (degrees).
- **********************************************************************/
- Math::real LatitudeOrigin() const { return _lat0; }
- /**
- * @return longitude of the origin (degrees).
- **********************************************************************/
- Math::real LongitudeOrigin() const { return _lon0; }
- /**
- * @return height of the origin (meters).
- **********************************************************************/
- Math::real HeightOrigin() const { return _h0; }
- /**
- * @return \e a the equatorial radius of the ellipsoid (meters). This is
- * the value of \e a inherited from the Geocentric object used in the
- * constructor.
- **********************************************************************/
- Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
- /**
- * @return \e f the flattening of the ellipsoid. This is the value
- * inherited from the Geocentric object used in the constructor.
- **********************************************************************/
- Math::real Flattening() const { return _earth.Flattening(); }
- /**
- * \deprecated An old name for EquatorialRadius().
- **********************************************************************/
- GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
- Math::real MajorRadius() const { return EquatorialRadius(); }
- ///@}
- };
- } // namespace GeographicLib
- #endif // GEOGRAPHICLIB_LOCALCARTESIAN_HPP
|