1 #pragma once
2 /**
3  * \file NETGeographicLib/Gnomonic.h
4  * \brief Header for NETGeographicLib::Gnomonic class
5  *
6  * NETGeographicLib is copyright (c) Scott Heiman (2013)
7  * GeographicLib is Copyright (c) Charles Karney (2010-2012)
8  * <charles@karney.com> and licensed under the MIT/X11 License.
9  * For more information, see
10  * https://geographiclib.sourceforge.io/
11  **********************************************************************/
12 
13 namespace NETGeographicLib
14 {
15     ref class Geodesic;
16   /**
17    * \brief .NET wrapper for GeographicLib::Gnomonic.
18    *
19    * This class allows .NET applications to access GeographicLib::Gnomonic.
20    *
21    * %Gnomonic projection centered at an arbitrary position \e C on the
22    * ellipsoid.  This projection is derived in Section 8 of
23    * - C. F. F. Karney,
24    *   <a href="https://doi.org/10.1007/s00190-012-0578-z">
25    *   Algorithms for geodesics</a>,
26    *   J. Geodesy <b>87</b>, 43--55 (2013);
27    *   DOI: <a href="https://doi.org/10.1007/s00190-012-0578-z">
28    *   10.1007/s00190-012-0578-z</a>;
29    *   addenda: <a href="https://geographiclib.sourceforge.io/geod-addenda.html">
30    *   geod-addenda.html</a>.
31    * .
32    * The projection of \e P is defined as follows: compute the geodesic line
33    * from \e C to \e P; compute the reduced length \e m12, geodesic scale \e
34    * M12, and &rho; = <i>m12</i>/\e M12; finally \e x = &rho; sin \e azi1; \e
35    * y = &rho; cos \e azi1, where \e azi1 is the azimuth of the geodesic at \e
36    * C.  The Gnomonic::Forward and Gnomonic::Reverse methods also return the
37    * azimuth \e azi of the geodesic at \e P and reciprocal scale \e rk in the
38    * azimuthal direction.  The scale in the radial direction if
39    * 1/<i>rk</i><sup>2</sup>.
40    *
41    * For a sphere, &rho; is reduces to \e a tan(<i>s12</i>/<i>a</i>), where \e
42    * s12 is the length of the geodesic from \e C to \e P, and the gnomonic
43    * projection has the property that all geodesics appear as straight lines.
44    * For an ellipsoid, this property holds only for geodesics interesting the
45    * centers.  However geodesic segments close to the center are approximately
46    * straight.
47    *
48    * Consider a geodesic segment of length \e l.  Let \e T be the point on the
49    * geodesic (extended if necessary) closest to \e C the center of the
50    * projection and \e t be the distance \e CT.  To lowest order, the maximum
51    * deviation (as a true distance) of the corresponding gnomonic line segment
52    * (i.e., with the same end points) from the geodesic is<br>
53    * <br>
54    * (<i>K</i>(<i>T</i>) - <i>K</i>(<i>C</i>))
55    * <i>l</i><sup>2</sup> \e t / 32.<br>
56    * <br>
57    * where \e K is the Gaussian curvature.
58    *
59    * This result applies for any surface.  For an ellipsoid of revolution,
60    * consider all geodesics whose end points are within a distance \e r of \e
61    * C.  For a given \e r, the deviation is maximum when the latitude of \e C
62    * is 45&deg;, when endpoints are a distance \e r away, and when their
63    * azimuths from the center are &plusmn; 45&deg; or &plusmn; 135&deg;.
64    * To lowest order in \e r and the flattening \e f, the deviation is \e f
65    * (<i>r</i>/2<i>a</i>)<sup>3</sup> \e r.
66    *
67    * The conversions all take place using a Geodesic object (by default
68    * Geodesic::WGS84).  For more information on geodesics see \ref geodesic.
69    *
70    * <b>CAUTION:</b> The definition of this projection for a sphere is
71    * standard.  However, there is no standard for how it should be extended to
72    * an ellipsoid.  The choices are:
73    * - Declare that the projection is undefined for an ellipsoid.
74    * - Project to a tangent plane from the center of the ellipsoid.  This
75    *   causes great ellipses to appear as straight lines in the projection;
76    *   i.e., it generalizes the spherical great circle to a great ellipse.
77    *   This was proposed by independently by Bowring and Williams in 1997.
78    * - Project to the conformal sphere with the constant of integration chosen
79    *   so that the values of the latitude match for the center point and
80    *   perform a central projection onto the plane tangent to the conformal
81    *   sphere at the center point.  This causes normal sections through the
82    *   center point to appear as straight lines in the projection; i.e., it
83    *   generalizes the spherical great circle to a normal section.  This was
84    *   proposed by I. G. Letoval'tsev, Generalization of the %Gnomonic
85    *   Projection for a Spheroid and the Principal Geodetic Problems Involved
86    *   in the Alignment of Surface Routes, Geodesy and Aerophotography (5),
87    *   271--274 (1963).
88    * - The projection given here.  This causes geodesics close to the center
89    *   point to appear as straight lines in the projection; i.e., it
90    *   generalizes the spherical great circle to a geodesic.
91    *
92    * C# Example:
93    * \include example-Gnomonic.cs
94    * Managed C++ Example:
95    * \include example-Gnomonic.cpp
96    * Visual Basic Example:
97    * \include example-Gnomonic.vb
98    *
99    * <B>INTERFACE DIFFERENCES:</B><BR>
100    * A default constructor has been provided that assumes WGS84 parameters.
101    *
102    * The EquatorialRadius and Flattening functions are implemented as properties.
103    **********************************************************************/
104     public ref class Gnomonic
105     {
106         private:
107         // the pointer to the unmanaged GeographicLib::Gnomonic.
108         const GeographicLib::Gnomonic* m_pGnomonic;
109 
110         // The finalizer frees the unmanaged memory when the object is destroyed.
111         !Gnomonic(void);
112     public:
113         /**
114          * Constructor for Gnomonic.
115          *
116          * @param[in] earth the Geodesic object to use for geodesic calculations.
117          **********************************************************************/
118         Gnomonic( Geodesic^ earth );
119 
120         /**
121          * The default constructor assumes a WGS84 ellipsoid..
122          **********************************************************************/
123         Gnomonic();
124 
125         /**
126          * The destructor calls the finalizer
127          **********************************************************************/
~Gnomonic()128         ~Gnomonic()
129         { this->!Gnomonic(); }
130 
131         /**
132          * Forward projection, from geographic to gnomonic.
133          *
134          * @param[in] lat0 latitude of center point of projection (degrees).
135          * @param[in] lon0 longitude of center point of projection (degrees).
136          * @param[in] lat latitude of point (degrees).
137          * @param[in] lon longitude of point (degrees).
138          * @param[out] x easting of point (meters).
139          * @param[out] y northing of point (meters).
140          * @param[out] azi azimuth of geodesic at point (degrees).
141          * @param[out] rk reciprocal of azimuthal scale at point.
142          *
143          * \e lat0 and \e lat should be in the range [&minus;90&deg;, 90&deg;].
144          * The scale of the projection is 1/<i>rk</i><sup>2</sup> in the
145          * "radial" direction, \e azi clockwise from true north, and is 1/\e rk
146          * in the direction perpendicular to this.  If the point lies "over the
147          * horizon", i.e., if \e rk &le; 0, then NaNs are returned for \e x and
148          * \e y (the correct values are returned for \e azi and \e rk).  A call
149          * to Forward followed by a call to Reverse will return the original
150          * (\e lat, \e lon) (to within roundoff) provided the point in not over
151          * the horizon.
152          **********************************************************************/
153         void Forward(double lat0, double lon0, double lat, double lon,
154                      [System::Runtime::InteropServices::Out] double% x,
155                      [System::Runtime::InteropServices::Out] double% y,
156                      [System::Runtime::InteropServices::Out] double% azi,
157                      [System::Runtime::InteropServices::Out] double% rk);
158 
159         /**
160          * Reverse projection, from gnomonic to geographic.
161          *
162          * @param[in] lat0 latitude of center point of projection (degrees).
163          * @param[in] lon0 longitude of center point of projection (degrees).
164          * @param[in] x easting of point (meters).
165          * @param[in] y northing of point (meters).
166          * @param[out] lat latitude of point (degrees).
167          * @param[out] lon longitude of point (degrees).
168          * @param[out] azi azimuth of geodesic at point (degrees).
169          * @param[out] rk reciprocal of azimuthal scale at point.
170          *
171          * \e lat0 should be in the range [&minus;90&deg;, 90&deg;].  \e lat
172          * will be in the range [&minus;90&deg;, 90&deg;] and \e lon will be in
173          * the range [&minus;180&deg;, 180&deg;).  The scale of the projection
174          * is 1/\e rk<sup>2</sup> in the "radial" direction, \e azi clockwise
175          * from true north, and is 1/\e rk in the direction perpendicular to
176          * this.  Even though all inputs should return a valid \e lat and \e
177          * lon, it's possible that the procedure fails to converge for very
178          * large \e x or \e y; in this case NaNs are returned for all the
179          * output arguments.  A call to Reverse followed by a call to Forward
180          * will return the original (\e x, \e y) (to roundoff).
181          **********************************************************************/
182         void Reverse(double lat0, double lon0, double x, double y,
183                      [System::Runtime::InteropServices::Out] double% lat,
184                      [System::Runtime::InteropServices::Out] double% lon,
185                      [System::Runtime::InteropServices::Out] double% azi,
186                      [System::Runtime::InteropServices::Out] double% rk);
187 
188         /**
189          * Gnomonic::Forward without returning the azimuth and scale.
190          **********************************************************************/
191         void Forward(double lat0, double lon0, double lat, double lon,
192                      [System::Runtime::InteropServices::Out] double% x,
193                      [System::Runtime::InteropServices::Out] double% y);
194 
195         /**
196          * Gnomonic::Reverse without returning the azimuth and scale.
197          **********************************************************************/
198         void Reverse(double lat0, double lon0, double x, double y,
199                      [System::Runtime::InteropServices::Out] double% lat,
200                      [System::Runtime::InteropServices::Out] double% lon);
201 
202         /** \name Inspector functions
203          **********************************************************************/
204         ///@{
205         /**
206          * @return \e a the equatorial radius of the ellipsoid (meters).  This is
207          *   the value inherited from the Geodesic object used in the constructor.
208          **********************************************************************/
209         property double EquatorialRadius { double get(); }
210 
211         /**
212          * @return \e f the flattening of the ellipsoid.  This is the value
213          *   inherited from the Geodesic object used in the constructor.
214          **********************************************************************/
215         property double Flattening { double get(); }
216         ///@}
217     };
218 } // namespace NETGeographicLib
219