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 ρ = <i>m12</i>/\e M12; finally \e x = ρ sin \e azi1; \e 35 * y = ρ 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, ρ 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°, when endpoints are a distance \e r away, and when their 63 * azimuths from the center are ± 45° or ± 135°. 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 [−90°, 90°]. 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 ≤ 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 [−90°, 90°]. \e lat 172 * will be in the range [−90°, 90°] and \e lon will be in 173 * the range [−180°, 180°). 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