GeographicLib 2.1.2
Gnomonic.hpp
Go to the documentation of this file.
1/**
2 * \file Gnomonic.hpp
3 * \brief Header for GeographicLib::Gnomonic class
4 *
5 * Copyright (c) Charles Karney (2010-2022) <charles@karney.com> and licensed
6 * under the MIT/X11 License. For more information, see
7 * https://geographiclib.sourceforge.io/
8 **********************************************************************/
9
10#if !defined(GEOGRAPHICLIB_GNOMONIC_HPP)
11#define GEOGRAPHICLIB_GNOMONIC_HPP 1
12
16
17namespace GeographicLib {
18
19 /**
20 * \brief %Gnomonic projection
21 *
22 * %Gnomonic projection centered at an arbitrary position \e C on the
23 * ellipsoid. This projection is derived in Section 8 of
24 * - C. F. F. Karney,
25 * <a href="https://doi.org/10.1007/s00190-012-0578-z">
26 * Algorithms for geodesics</a>,
27 * J. Geodesy <b>87</b>, 43--55 (2013);
28 * DOI: <a href="https://doi.org/10.1007/s00190-012-0578-z">
29 * 10.1007/s00190-012-0578-z</a>;
30 * addenda:
31 * <a href="https://geographiclib.sourceforge.io/geod-addenda.html">
32 * geod-addenda.html</a>.
33 * .
34 * The projection of \e P is defined as follows: compute the geodesic line
35 * from \e C to \e P; compute the reduced length \e m12, geodesic scale \e
36 * M12, and &rho; = <i>m12</i>/\e M12; finally \e x = &rho; sin \e azi1; \e
37 * y = &rho; cos \e azi1, where \e azi1 is the azimuth of the geodesic at \e
38 * C. The Gnomonic::Forward and Gnomonic::Reverse methods also return the
39 * azimuth \e azi of the geodesic at \e P and reciprocal scale \e rk in the
40 * azimuthal direction. The scale in the radial direction if
41 * 1/<i>rk</i><sup>2</sup>.
42 *
43 * For a sphere, &rho; is reduces to \e a tan(<i>s12</i>/<i>a</i>), where \e
44 * s12 is the length of the geodesic from \e C to \e P, and the gnomonic
45 * projection has the property that all geodesics appear as straight lines.
46 * For an ellipsoid, this property holds only for geodesics interesting the
47 * centers. However geodesic segments close to the center are approximately
48 * straight.
49 *
50 * Consider a geodesic segment of length \e l. Let \e T be the point on the
51 * geodesic (extended if necessary) closest to \e C the center of the
52 * projection and \e t be the distance \e CT. To lowest order, the maximum
53 * deviation (as a true distance) of the corresponding gnomonic line segment
54 * (i.e., with the same end points) from the geodesic is<br>
55 * <br>
56 * (<i>K</i>(<i>T</i>) - <i>K</i>(<i>C</i>))
57 * <i>l</i><sup>2</sup> \e t / 32.<br>
58 * <br>
59 * where \e K is the Gaussian curvature.
60 *
61 * This result applies for any surface. For an ellipsoid of revolution,
62 * consider all geodesics whose end points are within a distance \e r of \e
63 * C. For a given \e r, the deviation is maximum when the latitude of \e C
64 * is 45&deg;, when endpoints are a distance \e r away, and when their
65 * azimuths from the center are &plusmn; 45&deg; or &plusmn; 135&deg;.
66 * To lowest order in \e r and the flattening \e f, the deviation is \e f
67 * (<i>r</i>/2<i>a</i>)<sup>3</sup> \e r.
68 *
69 * The conversions all take place using a Geodesic object (by default
70 * Geodesic::WGS84()). For more information on geodesics see \ref geodesic.
71 *
72 * \warning The definition of this projection for a sphere is
73 * standard. However, there is no standard for how it should be extended to
74 * an ellipsoid. The choices are:
75 * - Declare that the projection is undefined for an ellipsoid.
76 * - Project to a tangent plane from the center of the ellipsoid. This
77 * causes great ellipses to appear as straight lines in the projection;
78 * i.e., it generalizes the spherical great circle to a great ellipse.
79 * This was proposed by independently by Bowring and Williams in 1997.
80 * - Project to the conformal sphere with the constant of integration chosen
81 * so that the values of the latitude match for the center point and
82 * perform a central projection onto the plane tangent to the conformal
83 * sphere at the center point. This causes normal sections through the
84 * center point to appear as straight lines in the projection; i.e., it
85 * generalizes the spherical great circle to a normal section. This was
86 * proposed by I. G. Letoval'tsev, Generalization of the gnomonic
87 * projection for a spheroid and the principal geodetic problems involved
88 * in the alignment of surface routes, Geodesy and Aerophotography (5),
89 * 271--274 (1963).
90 * - The projection given here. This causes geodesics close to the center
91 * point to appear as straight lines in the projection; i.e., it
92 * generalizes the spherical great circle to a geodesic.
93 *
94 * Example of use:
95 * \include example-Gnomonic.cpp
96 *
97 * <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utility
98 * providing access to the functionality of AzimuthalEquidistant, Gnomonic,
99 * and CassiniSoldner.
100 **********************************************************************/
101
103 private:
104 typedef Math::real real;
105 real eps0_, eps_;
106 Geodesic _earth;
107 real _a, _f;
108 // numit_ increased from 10 to 20 to fix convergence failure with high
109 // precision (e.g., GEOGRAPHICLIB_DIGITS=2000) calculations. Reverse uses
110 // Newton's method which converges quadratically and so numit_ = 10 would
111 // normally be big enough. However, since the Geodesic class is based on a
112 // series it is of limited accuracy; in particular, the derivative rules
113 // used by Reverse only hold approximately. Consequently, after a few
114 // iterations, the convergence in the Reverse falls back to improvements in
115 // each step by a constant (albeit small) factor.
116 static const int numit_ = 20;
117 public:
118
119 /**
120 * Constructor for Gnomonic.
121 *
122 * @param[in] earth the Geodesic object to use for geodesic calculations.
123 * By default this uses the WGS84 ellipsoid.
124 **********************************************************************/
125 explicit Gnomonic(const Geodesic& earth = Geodesic::WGS84());
126
127 /**
128 * Forward projection, from geographic to gnomonic.
129 *
130 * @param[in] lat0 latitude of center point of projection (degrees).
131 * @param[in] lon0 longitude of center point of projection (degrees).
132 * @param[in] lat latitude of point (degrees).
133 * @param[in] lon longitude of point (degrees).
134 * @param[out] x easting of point (meters).
135 * @param[out] y northing of point (meters).
136 * @param[out] azi azimuth of geodesic at point (degrees).
137 * @param[out] rk reciprocal of azimuthal scale at point.
138 *
139 * \e lat0 and \e lat should be in the range [&minus;90&deg;, 90&deg;].
140 * The scale of the projection is 1/<i>rk</i><sup>2</sup> in the "radial"
141 * direction, \e azi clockwise from true north, and is 1/\e rk in the
142 * direction perpendicular to this. If the point lies "over the horizon",
143 * i.e., if \e rk &le; 0, then NaNs are returned for \e x and \e y (the
144 * correct values are returned for \e azi and \e rk). A call to Forward
145 * followed by a call to Reverse will return the original (\e lat, \e lon)
146 * (to within roundoff) provided the point in not over the horizon.
147 **********************************************************************/
148 void Forward(real lat0, real lon0, real lat, real lon,
149 real& x, real& y, real& azi, real& rk) const;
150
151 /**
152 * Reverse projection, from gnomonic to geographic.
153 *
154 * @param[in] lat0 latitude of center point of projection (degrees).
155 * @param[in] lon0 longitude of center point of projection (degrees).
156 * @param[in] x easting of point (meters).
157 * @param[in] y northing of point (meters).
158 * @param[out] lat latitude of point (degrees).
159 * @param[out] lon longitude of point (degrees).
160 * @param[out] azi azimuth of geodesic at point (degrees).
161 * @param[out] rk reciprocal of azimuthal scale at point.
162 *
163 * \e lat0 should be in the range [&minus;90&deg;, 90&deg;]. \e lat will
164 * be in the range [&minus;90&deg;, 90&deg;] and \e lon will be in the
165 * range [&minus;180&deg;, 180&deg;]. The scale of the projection is
166 * 1/<i>rk</i><sup>2</sup> in the "radial" direction, \e azi clockwise from
167 * true north, and is 1/\e rk in the direction perpendicular to this. Even
168 * though all inputs should return a valid \e lat and \e lon, it's possible
169 * that the procedure fails to converge for very large \e x or \e y; in
170 * this case NaNs are returned for all the output arguments. A call to
171 * Reverse followed by a call to Forward will return the original (\e x, \e
172 * y) (to roundoff).
173 **********************************************************************/
174 void Reverse(real lat0, real lon0, real x, real y,
175 real& lat, real& lon, real& azi, real& rk) const;
176
177 /**
178 * Gnomonic::Forward without returning the azimuth and scale.
179 **********************************************************************/
180 void Forward(real lat0, real lon0, real lat, real lon,
181 real& x, real& y) const {
182 real azi, rk;
183 Forward(lat0, lon0, lat, lon, x, y, azi, rk);
184 }
185
186 /**
187 * Gnomonic::Reverse without returning the azimuth and scale.
188 **********************************************************************/
189 void Reverse(real lat0, real lon0, real x, real y,
190 real& lat, real& lon) const {
191 real azi, rk;
192 Reverse(lat0, lon0, x, y, lat, lon, azi, rk);
193 }
194
195 /** \name Inspector functions
196 **********************************************************************/
197 ///@{
198 /**
199 * @return \e a the equatorial radius of the ellipsoid (meters). This is
200 * the value inherited from the Geodesic object used in the constructor.
201 **********************************************************************/
202 Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
203
204 /**
205 * @return \e f the flattening of the ellipsoid. This is the value
206 * inherited from the Geodesic object used in the constructor.
207 **********************************************************************/
208 Math::real Flattening() const { return _earth.Flattening(); }
209 ///@}
210
211 };
212
213} // namespace GeographicLib
214
215#endif // GEOGRAPHICLIB_GNOMONIC_HPP
Header for GeographicLib::Constants class.
#define GEOGRAPHICLIB_EXPORT
Definition: Constants.hpp:67
GeographicLib::Math::real real
Definition: GeodSolve.cpp:31
Header for GeographicLib::GeodesicLine class.
Header for GeographicLib::Geodesic class.
Geodesic calculations
Definition: Geodesic.hpp:172
Math::real Flattening() const
Definition: Geodesic.hpp:955
static const Geodesic & WGS84()
Definition: Geodesic.cpp:89
Math::real EquatorialRadius() const
Definition: Geodesic.hpp:949
Gnomonic projection
Definition: Gnomonic.hpp:102
Math::real EquatorialRadius() const
Definition: Gnomonic.hpp:202
void Forward(real lat0, real lon0, real lat, real lon, real &x, real &y) const
Definition: Gnomonic.hpp:180
void Reverse(real lat0, real lon0, real x, real y, real &lat, real &lon) const
Definition: Gnomonic.hpp:189
Math::real Flattening() const
Definition: Gnomonic.hpp:208
Namespace for GeographicLib.
Definition: Accumulator.cpp:12