CassiniSoldner.hpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /**
  2. * \file CassiniSoldner.hpp
  3. * \brief Header for GeographicLib::CassiniSoldner class
  4. *
  5. * Copyright (c) Charles Karney (2009-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_CASSINISOLDNER_HPP)
  10. #define GEOGRAPHICLIB_CASSINISOLDNER_HPP 1
  11. #include <GeographicLib/Geodesic.hpp>
  12. #include <GeographicLib/GeodesicLine.hpp>
  13. #include <GeographicLib/Constants.hpp>
  14. namespace GeographicLib {
  15. /**
  16. * \brief Cassini-Soldner projection
  17. *
  18. * Cassini-Soldner projection centered at an arbitrary position, \e lat0, \e
  19. * lon0, on the ellipsoid. This projection is a transverse cylindrical
  20. * equidistant projection. The projection from (\e lat, \e lon) to easting
  21. * and northing (\e x, \e y) is defined by geodesics as follows. Go north
  22. * along a geodesic a distance \e y from the central point; then turn
  23. * clockwise 90&deg; and go a distance \e x along a geodesic.
  24. * (Although the initial heading is north, this changes to south if the pole
  25. * is crossed.) This procedure uniquely defines the reverse projection. The
  26. * forward projection is constructed as follows. Find the point (\e lat1, \e
  27. * lon1) on the meridian closest to (\e lat, \e lon). Here we consider the
  28. * full meridian so that \e lon1 may be either \e lon0 or \e lon0 +
  29. * 180&deg;. \e x is the geodesic distance from (\e lat1, \e lon1) to
  30. * (\e lat, \e lon), appropriately signed according to which side of the
  31. * central meridian (\e lat, \e lon) lies. \e y is the shortest distance
  32. * along the meridian from (\e lat0, \e lon0) to (\e lat1, \e lon1), again,
  33. * appropriately signed according to the initial heading. [Note that, in the
  34. * case of prolate ellipsoids, the shortest meridional path from (\e lat0, \e
  35. * lon0) to (\e lat1, \e lon1) may not be the shortest path.] This procedure
  36. * uniquely defines the forward projection except for a small class of points
  37. * for which there may be two equally short routes for either leg of the
  38. * path.
  39. *
  40. * Because of the properties of geodesics, the (\e x, \e y) grid is
  41. * orthogonal. The scale in the easting direction is unity. The scale, \e
  42. * k, in the northing direction is unity on the central meridian and
  43. * increases away from the central meridian. The projection routines return
  44. * \e azi, the true bearing of the easting direction, and \e rk = 1/\e k, the
  45. * reciprocal of the scale in the northing direction.
  46. *
  47. * The conversions all take place using a Geodesic object (by default
  48. * Geodesic::WGS84()). For more information on geodesics see \ref geodesic.
  49. * The determination of (\e lat1, \e lon1) in the forward projection is by
  50. * solving the inverse geodesic problem for (\e lat, \e lon) and its twin
  51. * obtained by reflection in the meridional plane. The scale is found by
  52. * determining where two neighboring geodesics intersecting the central
  53. * meridian at \e lat1 and \e lat1 + \e dlat1 intersect and taking the ratio
  54. * of the reduced lengths for the two geodesics between that point and,
  55. * respectively, (\e lat1, \e lon1) and (\e lat, \e lon).
  56. *
  57. * Example of use:
  58. * \include example-CassiniSoldner.cpp
  59. *
  60. * <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utility
  61. * providing access to the functionality of AzimuthalEquidistant, Gnomonic,
  62. * and CassiniSoldner.
  63. **********************************************************************/
  64. class GEOGRAPHICLIB_EXPORT CassiniSoldner {
  65. private:
  66. typedef Math::real real;
  67. Geodesic _earth;
  68. GeodesicLine _meridian;
  69. real _sbet0, _cbet0;
  70. static const unsigned maxit_ = 10;
  71. public:
  72. /**
  73. * Constructor for CassiniSoldner.
  74. *
  75. * @param[in] earth the Geodesic object to use for geodesic calculations.
  76. * By default this uses the WGS84 ellipsoid.
  77. *
  78. * This constructor makes an "uninitialized" object. Call Reset to set the
  79. * central latitude and longitude, prior to calling Forward and Reverse.
  80. **********************************************************************/
  81. explicit CassiniSoldner(const Geodesic& earth = Geodesic::WGS84());
  82. /**
  83. * Constructor for CassiniSoldner specifying a center point.
  84. *
  85. * @param[in] lat0 latitude of center point of projection (degrees).
  86. * @param[in] lon0 longitude of center point of projection (degrees).
  87. * @param[in] earth the Geodesic object to use for geodesic calculations.
  88. * By default this uses the WGS84 ellipsoid.
  89. *
  90. * \e lat0 should be in the range [&minus;90&deg;, 90&deg;].
  91. **********************************************************************/
  92. CassiniSoldner(real lat0, real lon0,
  93. const Geodesic& earth = Geodesic::WGS84());
  94. /**
  95. * Set the central point of the projection
  96. *
  97. * @param[in] lat0 latitude of center point of projection (degrees).
  98. * @param[in] lon0 longitude of center point of projection (degrees).
  99. *
  100. * \e lat0 should be in the range [&minus;90&deg;, 90&deg;].
  101. **********************************************************************/
  102. void Reset(real lat0, real lon0);
  103. /**
  104. * Forward projection, from geographic to Cassini-Soldner.
  105. *
  106. * @param[in] lat latitude of point (degrees).
  107. * @param[in] lon longitude of point (degrees).
  108. * @param[out] x easting of point (meters).
  109. * @param[out] y northing of point (meters).
  110. * @param[out] azi azimuth of easting direction at point (degrees).
  111. * @param[out] rk reciprocal of azimuthal northing scale at point.
  112. *
  113. * \e lat should be in the range [&minus;90&deg;, 90&deg;]. A call to
  114. * Forward followed by a call to Reverse will return the original (\e lat,
  115. * \e lon) (to within roundoff). The routine does nothing if the origin
  116. * has not been set.
  117. **********************************************************************/
  118. void Forward(real lat, real lon,
  119. real& x, real& y, real& azi, real& rk) const;
  120. /**
  121. * Reverse projection, from Cassini-Soldner to geographic.
  122. *
  123. * @param[in] x easting of point (meters).
  124. * @param[in] y northing of point (meters).
  125. * @param[out] lat latitude of point (degrees).
  126. * @param[out] lon longitude of point (degrees).
  127. * @param[out] azi azimuth of easting direction at point (degrees).
  128. * @param[out] rk reciprocal of azimuthal northing scale at point.
  129. *
  130. * A call to Reverse followed by a call to Forward will return the original
  131. * (\e x, \e y) (to within roundoff), provided that \e x and \e y are
  132. * sufficiently small not to "wrap around" the earth. The routine does
  133. * nothing if the origin has not been set.
  134. **********************************************************************/
  135. void Reverse(real x, real y,
  136. real& lat, real& lon, real& azi, real& rk) const;
  137. /**
  138. * CassiniSoldner::Forward without returning the azimuth and scale.
  139. **********************************************************************/
  140. void Forward(real lat, real lon,
  141. real& x, real& y) const {
  142. real azi, rk;
  143. Forward(lat, lon, x, y, azi, rk);
  144. }
  145. /**
  146. * CassiniSoldner::Reverse without returning the azimuth and scale.
  147. **********************************************************************/
  148. void Reverse(real x, real y,
  149. real& lat, real& lon) const {
  150. real azi, rk;
  151. Reverse(x, y, lat, lon, azi, rk);
  152. }
  153. /** \name Inspector functions
  154. **********************************************************************/
  155. ///@{
  156. /**
  157. * @return true if the object has been initialized.
  158. **********************************************************************/
  159. bool Init() const { return _meridian.Init(); }
  160. /**
  161. * @return \e lat0 the latitude of origin (degrees).
  162. **********************************************************************/
  163. Math::real LatitudeOrigin() const
  164. { return _meridian.Latitude(); }
  165. /**
  166. * @return \e lon0 the longitude of origin (degrees).
  167. **********************************************************************/
  168. Math::real LongitudeOrigin() const
  169. { return _meridian.Longitude(); }
  170. /**
  171. * @return \e a the equatorial radius of the ellipsoid (meters). This is
  172. * the value inherited from the Geodesic object used in the constructor.
  173. **********************************************************************/
  174. Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
  175. /**
  176. * @return \e f the flattening of the ellipsoid. This is the value
  177. * inherited from the Geodesic object used in the constructor.
  178. **********************************************************************/
  179. Math::real Flattening() const { return _earth.Flattening(); }
  180. /**
  181. * \deprecated An old name for EquatorialRadius().
  182. **********************************************************************/
  183. GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
  184. Math::real MajorRadius() const { return EquatorialRadius(); }
  185. ///@}
  186. };
  187. } // namespace GeographicLib
  188. #endif // GEOGRAPHICLIB_CASSINISOLDNER_HPP