NETGeographicLib  1.38
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Pages
Geodesic.h
Go to the documentation of this file.
1 /**
2  * \file NETGeographicLib/Geodesic.h
3  * \brief Header for NETGeographicLib::Geodesic class
4  *
5  * NETGeographicLib is copyright (c) Scott Heiman (2013)
6  * GeographicLib is Copyright (c) Charles Karney (2010-2012)
7  * <charles@karney.com> and licensed under the MIT/X11 License.
8  * For more information, see
9  * http://geographiclib.sourceforge.net/
10  **********************************************************************/
11 #pragma once
12 #include "NETGeographicLib.h"
13 
14 namespace NETGeographicLib
15 {
16  ref class GeodesicLine;
17  /**
18  * \brief .NET wrapper for GeographicLib::Geodesic.
19  *
20  * This class allows .NET applications to access GeographicLib::Geodesic.
21  *
22  * The shortest path between two points on a ellipsoid at (\e lat1, \e lon1)
23  * and (\e lat2, \e lon2) is called the geodesic. Its length is \e s12 and
24  * the geodesic from point 1 to point 2 has azimuths \e azi1 and \e azi2 at
25  * the two end points. (The azimuth is the heading measured clockwise from
26  * north. \e azi2 is the "forward" azimuth, i.e., the heading that takes you
27  * beyond point 2 not back to point 1.)
28  *
29  * Given \e lat1, \e lon1, \e azi1, and \e s12, we can determine \e lat2, \e
30  * lon2, and \e azi2. This is the \e direct geodesic problem and its
31  * solution is given by the function Geodesic::Direct. (If \e s12 is
32  * sufficiently large that the geodesic wraps more than halfway around the
33  * earth, there will be another geodesic between the points with a smaller \e
34  * s12.)
35  *
36  * Given \e lat1, \e lon1, \e lat2, and \e lon2, we can determine \e azi1, \e
37  * azi2, and \e s12. This is the \e inverse geodesic problem, whose solution
38  * is given by Geodesic::Inverse. Usually, the solution to the inverse
39  * problem is unique. In cases where there are multiple solutions (all with
40  * the same \e s12, of course), all the solutions can be easily generated
41  * once a particular solution is provided.
42  *
43  * The standard way of specifying the direct problem is the specify the
44  * distance \e s12 to the second point. However it is sometimes useful
45  * instead to specify the arc length \e a12 (in degrees) on the auxiliary
46  * sphere. This is a mathematical construct used in solving the geodesic
47  * problems. The solution of the direct problem in this form is provided by
48  * Geodesic::ArcDirect. An arc length in excess of 180&deg; indicates that
49  * the geodesic is not a shortest path. In addition, the arc length between
50  * an equatorial crossing and the next extremum of latitude for a geodesic is
51  * 90&deg;.
52  *
53  * This class can also calculate several other quantities related to
54  * geodesics. These are:
55  * - <i>reduced length</i>. If we fix the first point and increase \e azi1
56  * by \e dazi1 (radians), the second point is displaced \e m12 \e dazi1 in
57  * the direction \e azi2 + 90&deg;. The quantity \e m12 is called
58  * the "reduced length" and is symmetric under interchange of the two
59  * points. On a curved surface the reduced length obeys a symmetry
60  * relation, \e m12 + \e m21 = 0. On a flat surface, we have \e m12 = \e
61  * s12. The ratio <i>s12</i>/\e m12 gives the azimuthal scale for an
62  * azimuthal equidistant projection.
63  * - <i>geodesic scale</i>. Consider a reference geodesic and a second
64  * geodesic parallel to this one at point 1 and separated by a small
65  * distance \e dt. The separation of the two geodesics at point 2 is \e
66  * M12 \e dt where \e M12 is called the "geodesic scale". \e M21 is
67  * defined similarly (with the geodesics being parallel at point 2). On a
68  * flat surface, we have \e M12 = \e M21 = 1. The quantity 1/\e M12 gives
69  * the scale of the Cassini-Soldner projection.
70 
71  * - <i>area</i>. The area between the geodesic from point 1 to point 2 and
72  * the equation is represented by \e S12; it is the area, measured
73  * counter-clockwise, of the geodesic quadrilateral with corners
74  * (<i>lat1</i>,<i>lon1</i>), (0,<i>lon1</i>), (0,<i>lon2</i>), and
75  * (<i>lat2</i>,<i>lon2</i>). It can be used to compute the area of any
76  * simple geodesic polygon.
77  *
78  * Overloaded versions of Geodesic::Direct, Geodesic::ArcDirect, and
79  * Geodesic::Inverse allow these quantities to be returned. In addition
80  * there are general functions Geodesic::GenDirect, and Geodesic::GenInverse
81  * which allow an arbitrary set of results to be computed. The quantities \e
82  * m12, \e M12, \e M21 which all specify the behavior of nearby geodesics
83  * obey addition rules. If points 1, 2, and 3 all lie on a single geodesic,
84  * then the following rules hold:
85  * - \e s13 = \e s12 + \e s23
86  * - \e a13 = \e a12 + \e a23
87  * - \e S13 = \e S12 + \e S23
88  * - \e m13 = \e m12 \e M23 + \e m23 \e M21
89  * - \e M13 = \e M12 \e M23 &minus; (1 &minus; \e M12 \e M21) \e m23 / \e m12
90  * - \e M31 = \e M32 \e M21 &minus; (1 &minus; \e M23 \e M32) \e m12 / \e m23
91  *
92  * Additional functionality is provided by the GeodesicLine class, which
93  * allows a sequence of points along a geodesic to be computed.
94  *
95  * The shortest distance returned by the solution of the inverse problem is
96  * (obviously) uniquely defined. However, in a few special cases there are
97  * multiple azimuths which yield the same shortest distance. Here is a
98  * catalog of those cases:
99  * - \e lat1 = &minus;\e lat2 (with neither at a pole). If \e azi1 = \e
100  * azi2, the geodesic is unique. Otherwise there are two geodesics and the
101  * second one is obtained by setting [\e azi1, \e azi2] = [\e azi2, \e
102  * azi1], [\e M12, \e M21] = [\e M21, \e M12], \e S12 = &minus;\e S12.
103  * (This occurs when the longitude difference is near &plusmn;180&deg; for
104  * oblate ellipsoids.)
105  * - \e lon2 = \e lon1 &plusmn; 180&deg; (with neither at a pole). If \e
106  * azi1 = 0&deg; or &plusmn;180&deg;, the geodesic is unique. Otherwise
107  * there are two geodesics and the second one is obtained by setting [\e
108  * azi1, \e azi2] = [&minus;\e azi1, &minus;\e azi2], \e S12 = &minus;\e
109  * S12. (This occurs when the \e lat2 is near &minus;\e lat1 for prolate
110  * ellipsoids.)
111  * - Points 1 and 2 at opposite poles. There are infinitely many geodesics
112  * which can be generated by setting [\e azi1, \e azi2] = [\e azi1, \e
113  * azi2] + [\e d, &minus;\e d], for arbitrary \e d. (For spheres, this
114  * prescription applies when points 1 and 2 are antipodal.)
115  * - s12 = 0 (coincident points). There are infinitely many geodesics which
116  * can be generated by setting [\e azi1, \e azi2] = [\e azi1, \e azi2] +
117  * [\e d, \e d], for arbitrary \e d.
118  *
119  * The calculations are accurate to better than 15 nm (15 nanometers) for the
120  * WGS84 ellipsoid. See Sec. 9 of
121  * <a href="http://arxiv.org/abs/1102.1215v1">arXiv:1102.1215v1</a> for
122  * details. The algorithms used by this class are based on series expansions
123  * using the flattening \e f as a small parameter. These are only accurate
124  * for |<i>f</i>| &lt; 0.02; however reasonably accurate results will be
125  * obtained for |<i>f</i>| &lt; 0.2. Here is a table of the approximate
126  * maximum error (expressed as a distance) for an ellipsoid with the same
127  * major radius as the WGS84 ellipsoid and different values of the
128  * flattening.<pre>
129  * |f| error
130  * 0.01 25 nm
131  * 0.02 30 nm
132  * 0.05 10 um
133  * 0.1 1.5 mm
134  * 0.2 300 mm
135  * </pre>
136  * For very eccentric ellipsoids, use GeodesicExact instead.
137  *
138  * The algorithms are described in
139  * - C. F. F. Karney,
140  * <a href="http://dx.doi.org/10.1007/s00190-012-0578-z">
141  * Algorithms for geodesics</a>,
142  * J. Geodesy <b>87</b>, 43--55 (2013);
143  * DOI: <a href="http://dx.doi.org/10.1007/s00190-012-0578-z">
144  * 10.1007/s00190-012-0578-z</a>;
145  * addenda: <a href="http://geographiclib.sf.net/geod-addenda.html">
146  * geod-addenda.html</a>.
147  * .
148  * For more information on geodesics see \ref geodesic.
149  *
150  * C# Example:
151  * \include example-Geodesic.cs
152  * Managed C++ Example:
153  * \include example-Geodesic.cpp
154  * Visual Basic Example:
155  * \include example-Geodesic.vb
156  *
157  * <B>INTERFACE DIFFERENCES:</B><BR>
158  * A default constructor has been provided that assumes WGS84 parameters.
159  *
160  * The MajorRadius, Flattening, and EllipsoidArea functions are
161  * implemented as properties.
162  *
163  * The GenDirect, GenInverse, and Line functions accept the
164  * "capabilities mask" as a NETGeographicLib::Mask rather than an
165  * unsigned.
166  **********************************************************************/
167  public ref class Geodesic
168  {
169  private:
170  // The pointer to the unmanaged GeographicLib::Geodesic.
171  const GeographicLib::Geodesic* m_pGeodesic;
172 
173  // Frees the unmanaged memory when this object is destroyed.
174  !Geodesic();
175  public:
176  /** \name Constructor
177  **********************************************************************/
178  ///@{
179  /**
180  * Constructor for a ellipsoid with
181  *
182  * @param[in] a equatorial radius (meters).
183  * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
184  * Negative \e f gives a prolate ellipsoid. If \e f > 1, set flattening
185  * to 1/\e f.
186  * @exception GeographicErr if \e a or (1 &minus; \e f ) \e a is not
187  * positive.
188  **********************************************************************/
189  Geodesic(double a, double f);
190 
191  /**
192  * Constructor for the WGS84 ellipsoid.
193  **********************************************************************/
194  Geodesic();
195  ///@}
196 
197  /**
198  * \brief the destructor calls the finalizer.
199  **********************************************************************/
200  ~Geodesic() { this->!Geodesic(); }
201 
202  /** \name Direct geodesic problem specified in terms of distance.
203  **********************************************************************/
204  ///@{
205  /**
206  * Solve the direct geodesic problem where the length of the geodesic
207  * is specified in terms of distance.
208  *
209  * @param[in] lat1 latitude of point 1 (degrees).
210  * @param[in] lon1 longitude of point 1 (degrees).
211  * @param[in] azi1 azimuth at point 1 (degrees).
212  * @param[in] s12 distance between point 1 and point 2 (meters); it can be
213  * negative.
214  * @param[out] lat2 latitude of point 2 (degrees).
215  * @param[out] lon2 longitude of point 2 (degrees).
216  * @param[out] azi2 (forward) azimuth at point 2 (degrees).
217  * @param[out] m12 reduced length of geodesic (meters).
218  * @param[out] M12 geodesic scale of point 2 relative to point 1
219  * (dimensionless).
220  * @param[out] M21 geodesic scale of point 1 relative to point 2
221  * (dimensionless).
222  * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
223  * @return \e a12 arc length of between point 1 and point 2 (degrees).
224  *
225  * \e lat1 should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and \e
226  * azi1 should be in the range [&minus;540&deg;, 540&deg;). The values of
227  * \e lon2 and \e azi2 returned are in the range [&minus;180&deg;,
228  * 180&deg;).
229  *
230  * If either point is at a pole, the azimuth is defined by keeping the
231  * longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
232  * and taking the limit &epsilon; &rarr; 0+. An arc length greater that
233  * 180&deg; signifies a geodesic which is not a shortest path. (For a
234  * prolate ellipsoid, an additional condition is necessary for a shortest
235  * path: the longitudinal extent must not exceed of 180&deg;.)
236  *
237  * The following functions are overloaded versions of Geodesic::Direct
238  * which omit some of the output parameters. Note, however, that the arc
239  * length is always computed and returned as the function value.
240  **********************************************************************/
241  double Direct(double lat1, double lon1, double azi1, double s12,
242  [System::Runtime::InteropServices::Out] double% lat2,
243  [System::Runtime::InteropServices::Out] double% lon2,
244  [System::Runtime::InteropServices::Out] double% azi2,
245  [System::Runtime::InteropServices::Out] double% m12,
246  [System::Runtime::InteropServices::Out] double% M12,
247  [System::Runtime::InteropServices::Out] double% M21,
248  [System::Runtime::InteropServices::Out] double% S12);
249 
250  /**
251  * See the documentation for Geodesic::Direct.
252  **********************************************************************/
253  double Direct(double lat1, double lon1, double azi1, double s12,
254  [System::Runtime::InteropServices::Out] double% lat2,
255  [System::Runtime::InteropServices::Out] double% lon2);
256 
257  /**
258  * See the documentation for Geodesic::Direct.
259  **********************************************************************/
260  double Direct(double lat1, double lon1, double azi1, double s12,
261  [System::Runtime::InteropServices::Out] double% lat2,
262  [System::Runtime::InteropServices::Out] double% lon2,
263  [System::Runtime::InteropServices::Out] double% azi2);
264 
265  /**
266  * See the documentation for Geodesic::Direct.
267  **********************************************************************/
268  double Direct(double lat1, double lon1, double azi1, double s12,
269  [System::Runtime::InteropServices::Out] double% lat2,
270  [System::Runtime::InteropServices::Out] double% lon2,
271  [System::Runtime::InteropServices::Out] double% azi2,
272  [System::Runtime::InteropServices::Out] double% m12);
273 
274  /**
275  * See the documentation for Geodesic::Direct.
276  **********************************************************************/
277  double Direct(double lat1, double lon1, double azi1, double s12,
278  [System::Runtime::InteropServices::Out] double% lat2,
279  [System::Runtime::InteropServices::Out] double% lon2,
280  [System::Runtime::InteropServices::Out] double% azi2,
281  [System::Runtime::InteropServices::Out] double% M12,
282  [System::Runtime::InteropServices::Out] double% M21);
283 
284  /**
285  * See the documentation for Geodesic::Direct.
286  **********************************************************************/
287  double Direct(double lat1, double lon1, double azi1, double s12,
288  [System::Runtime::InteropServices::Out] double% lat2,
289  [System::Runtime::InteropServices::Out] double% lon2,
290  [System::Runtime::InteropServices::Out] double% azi2,
291  [System::Runtime::InteropServices::Out] double% m12,
292  [System::Runtime::InteropServices::Out] double% M12,
293  [System::Runtime::InteropServices::Out] double% M21);
294  ///@}
295 
296  /** \name Direct geodesic problem specified in terms of arc length.
297  **********************************************************************/
298  ///@{
299  /**
300  * Solve the direct geodesic problem where the length of the geodesic
301  * is specified in terms of arc length.
302  *
303  * @param[in] lat1 latitude of point 1 (degrees).
304  * @param[in] lon1 longitude of point 1 (degrees).
305  * @param[in] azi1 azimuth at point 1 (degrees).
306  * @param[in] a12 arc length between point 1 and point 2 (degrees); it can
307  * be negative.
308  * @param[out] lat2 latitude of point 2 (degrees).
309  * @param[out] lon2 longitude of point 2 (degrees).
310  * @param[out] azi2 (forward) azimuth at point 2 (degrees).
311  * @param[out] s12 distance between point 1 and point 2 (meters).
312  * @param[out] m12 reduced length of geodesic (meters).
313  * @param[out] M12 geodesic scale of point 2 relative to point 1
314  * (dimensionless).
315  * @param[out] M21 geodesic scale of point 1 relative to point 2
316  * (dimensionless).
317  * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
318  *
319  * \e lat1 should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and \e
320  * azi1 should be in the range [&minus;540&deg;, 540&deg;). The values of
321  * \e lon2 and \e azi2 returned are in the range [&minus;180&deg;,
322  * 180&deg;).
323  *
324  * If either point is at a pole, the azimuth is defined by keeping the
325  * longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
326  * and taking the limit &epsilon; &rarr; 0+. An arc length greater that
327  * 180&deg; signifies a geodesic which is not a shortest path. (For a
328  * prolate ellipsoid, an additional condition is necessary for a shortest
329  * path: the longitudinal extent must not exceed of 180&deg;.)
330  *
331  * The following functions are overloaded versions of Geodesic::Direct
332  * which omit some of the output parameters.
333  **********************************************************************/
334  void ArcDirect(double lat1, double lon1, double azi1, double a12,
335  [System::Runtime::InteropServices::Out] double% lat2,
336  [System::Runtime::InteropServices::Out] double% lon2,
337  [System::Runtime::InteropServices::Out] double% azi2,
338  [System::Runtime::InteropServices::Out] double% s12,
339  [System::Runtime::InteropServices::Out] double% m12,
340  [System::Runtime::InteropServices::Out] double% M12,
341  [System::Runtime::InteropServices::Out] double% M21,
342  [System::Runtime::InteropServices::Out] double% S12);
343 
344  /**
345  * See the documentation for Geodesic::ArcDirect.
346  **********************************************************************/
347  void ArcDirect(double lat1, double lon1, double azi1, double a12,
348  [System::Runtime::InteropServices::Out] double% lat2,
349  [System::Runtime::InteropServices::Out] double% lon2);
350 
351  /**
352  * See the documentation for Geodesic::ArcDirect.
353  **********************************************************************/
354  void ArcDirect(double lat1, double lon1, double azi1, double a12,
355  [System::Runtime::InteropServices::Out] double% lat2,
356  [System::Runtime::InteropServices::Out] double% lon2,
357  [System::Runtime::InteropServices::Out] double% azi2);
358 
359  /**
360  * See the documentation for Geodesic::ArcDirect.
361  **********************************************************************/
362  void ArcDirect(double lat1, double lon1, double azi1, double a12,
363  [System::Runtime::InteropServices::Out] double% lat2,
364  [System::Runtime::InteropServices::Out] double% lon2,
365  [System::Runtime::InteropServices::Out] double% azi2,
366  [System::Runtime::InteropServices::Out] double% s12);
367 
368  /**
369  * See the documentation for Geodesic::ArcDirect.
370  **********************************************************************/
371  void ArcDirect(double lat1, double lon1, double azi1, double a12,
372  [System::Runtime::InteropServices::Out] double% lat2,
373  [System::Runtime::InteropServices::Out] double% lon2,
374  [System::Runtime::InteropServices::Out] double% azi2,
375  [System::Runtime::InteropServices::Out] double% s12,
376  [System::Runtime::InteropServices::Out] double% m12);
377 
378  /**
379  * See the documentation for Geodesic::ArcDirect.
380  **********************************************************************/
381  void ArcDirect(double lat1, double lon1, double azi1, double a12,
382  [System::Runtime::InteropServices::Out] double% lat2,
383  [System::Runtime::InteropServices::Out] double% lon2,
384  [System::Runtime::InteropServices::Out] double% azi2,
385  [System::Runtime::InteropServices::Out] double% s12,
386  [System::Runtime::InteropServices::Out] double% M12,
387  [System::Runtime::InteropServices::Out] double% M21);
388 
389  /**
390  * See the documentation for Geodesic::ArcDirect.
391  **********************************************************************/
392  void ArcDirect(double lat1, double lon1, double azi1, double a12,
393  [System::Runtime::InteropServices::Out] double% lat2,
394  [System::Runtime::InteropServices::Out] double% lon2,
395  [System::Runtime::InteropServices::Out] double% azi2,
396  [System::Runtime::InteropServices::Out] double% s12,
397  [System::Runtime::InteropServices::Out] double% m12,
398  [System::Runtime::InteropServices::Out] double% M12,
399  [System::Runtime::InteropServices::Out] double% M21);
400  ///@}
401 
402  /** \name General version of the direct geodesic solution.
403  **********************************************************************/
404  ///@{
405 
406  /**
407  * The general direct geodesic problem. Geodesic::Direct and
408  * Geodesic::ArcDirect are defined in terms of this function.
409  *
410  * @param[in] lat1 latitude of point 1 (degrees).
411  * @param[in] lon1 longitude of point 1 (degrees).
412  * @param[in] azi1 azimuth at point 1 (degrees).
413  * @param[in] arcmode boolean flag determining the meaning of the \e
414  * s12_a12.
415  * @param[in] s12_a12 if \e arcmode is false, this is the distance between
416  * point 1 and point 2 (meters); otherwise it is the arc length between
417  * point 1 and point 2 (degrees); it can be negative.
418  * @param[in] outmask a bitor'ed combination of NETGeographicLib::Mask values
419  * specifying which of the following parameters should be set.
420  * @param[out] lat2 latitude of point 2 (degrees).
421  * @param[out] lon2 longitude of point 2 (degrees).
422  * @param[out] azi2 (forward) azimuth at point 2 (degrees).
423  * @param[out] s12 distance between point 1 and point 2 (meters).
424  * @param[out] m12 reduced length of geodesic (meters).
425  * @param[out] M12 geodesic scale of point 2 relative to point 1
426  * (dimensionless).
427  * @param[out] M21 geodesic scale of point 1 relative to point 2
428  * (dimensionless).
429  * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
430  * @return \e a12 arc length of between point 1 and point 2 (degrees).
431  *
432  * The NETGeographicLib::Mask values possible for \e outmask are
433  * - \e outmask |= NETGeographicLib::Mask::LATITUDE for the latitude \e lat2;
434  * - \e outmask |= NETGeographicLib::Mask::LONGITUDE for the latitude \e lon2;
435  * - \e outmask |= NETGeographicLib::Mask::AZIMUTH for the latitude \e azi2;
436  * - \e outmask |= NETGeographicLib::Mask::DISTANCE for the distance \e s12;
437  * - \e outmask |= NETGeographicLib::Mask::REDUCEDLENGTH for the reduced length \e
438  * m12;
439  * - \e outmask |= NETGeographicLib::Mask::GEODESICSCALE for the geodesic scales \e
440  * M12 and \e M21;
441  * - \e outmask |= NETGeographicLib::Mask::AREA for the area \e S12;
442  * - \e outmask |= NETGeographicLib::Mask::ALL for all of the above.
443  * .
444  * The function value \e a12 is always computed and returned and this
445  * equals \e s12_a12 is \e arcmode is true. If \e outmask includes
446  * NETGeographicLib::Mask::DISTANCE and \e arcmode is false, then
447  * \e s12 = \e s12_a12. It is not necessary to include
448  * NETGeographicLib::Mask::DISTANCE_IN in \e outmask; this is
449  * automatically included is \e arcmode is false.
450  **********************************************************************/
451  double GenDirect(double lat1, double lon1, double azi1,
452  bool arcmode, double s12_a12,
453  NETGeographicLib::Mask outmask,
454  [System::Runtime::InteropServices::Out] double% lat2,
455  [System::Runtime::InteropServices::Out] double% lon2,
456  [System::Runtime::InteropServices::Out] double% azi2,
457  [System::Runtime::InteropServices::Out] double% s12,
458  [System::Runtime::InteropServices::Out] double% m12,
459  [System::Runtime::InteropServices::Out] double% M12,
460  [System::Runtime::InteropServices::Out] double% M21,
461  [System::Runtime::InteropServices::Out] double% S12);
462  ///@}
463 
464  /** \name Inverse geodesic problem.
465  **********************************************************************/
466  ///@{
467  /**
468  * Solve the inverse geodesic problem.
469  *
470  * @param[in] lat1 latitude of point 1 (degrees).
471  * @param[in] lon1 longitude of point 1 (degrees).
472  * @param[in] lat2 latitude of point 2 (degrees).
473  * @param[in] lon2 longitude of point 2 (degrees).
474  * @param[out] s12 distance between point 1 and point 2 (meters).
475  * @param[out] azi1 azimuth at point 1 (degrees).
476  * @param[out] azi2 (forward) azimuth at point 2 (degrees).
477  * @param[out] m12 reduced length of geodesic (meters).
478  * @param[out] M12 geodesic scale of point 2 relative to point 1
479  * (dimensionless).
480  * @param[out] M21 geodesic scale of point 1 relative to point 2
481  * (dimensionless).
482  * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
483  * @return \e a12 arc length of between point 1 and point 2 (degrees).
484  *
485  * \e lat1 and \e lat2 should be in the range [&minus;90&deg;, 90&deg;]; \e
486  * lon1 and \e lon2 should be in the range [&minus;540&deg;, 540&deg;).
487  * The values of \e azi1 and \e azi2 returned are in the range
488  * [&minus;180&deg;, 180&deg;).
489  *
490  * If either point is at a pole, the azimuth is defined by keeping the
491  * longitude fixed, writing \e lat = &plusmn;(90&deg; &minus; &epsilon;),
492  * and taking the limit &epsilon; &rarr; 0+.
493  *
494  * The solution to the inverse problem is found using Newton's method. If
495  * this fails to converge (this is very unlikely in geodetic applications
496  * but does occur for very eccentric ellipsoids), then the bisection method
497  * is used to refine the solution.
498  *
499  * The following functions are overloaded versions of Geodesic::Inverse
500  * which omit some of the output parameters. Note, however, that the arc
501  * length is always computed and returned as the function value.
502  **********************************************************************/
503  double Inverse(double lat1, double lon1, double lat2, double lon2,
504  [System::Runtime::InteropServices::Out] double% s12,
505  [System::Runtime::InteropServices::Out] double% azi1,
506  [System::Runtime::InteropServices::Out] double% azi2,
507  [System::Runtime::InteropServices::Out] double% m12,
508  [System::Runtime::InteropServices::Out] double% M12,
509  [System::Runtime::InteropServices::Out] double% M21,
510  [System::Runtime::InteropServices::Out] double% S12);
511 
512  /**
513  * See the documentation for Geodesic::Inverse.
514  **********************************************************************/
515  double Inverse(double lat1, double lon1, double lat2, double lon2,
516  [System::Runtime::InteropServices::Out] double% s12);
517 
518  /**
519  * See the documentation for Geodesic::Inverse.
520  **********************************************************************/
521  double Inverse(double lat1, double lon1, double lat2, double lon2,
522  [System::Runtime::InteropServices::Out] double% azi1,
523  [System::Runtime::InteropServices::Out] double% azi2);
524 
525  /**
526  * See the documentation for Geodesic::Inverse.
527  **********************************************************************/
528  double Inverse(double lat1, double lon1, double lat2, double lon2,
529  [System::Runtime::InteropServices::Out] double% s12,
530  [System::Runtime::InteropServices::Out] double% azi1,
531  [System::Runtime::InteropServices::Out] double% azi2);
532 
533  /**
534  * See the documentation for Geodesic::Inverse.
535  **********************************************************************/
536  double Inverse(double lat1, double lon1, double lat2, double lon2,
537  [System::Runtime::InteropServices::Out] double% s12,
538  [System::Runtime::InteropServices::Out] double% azi1,
539  [System::Runtime::InteropServices::Out] double% azi2,
540  [System::Runtime::InteropServices::Out] double% m12);
541 
542  /**
543  * See the documentation for Geodesic::Inverse.
544  **********************************************************************/
545  double Inverse(double lat1, double lon1, double lat2, double lon2,
546  [System::Runtime::InteropServices::Out] double% s12,
547  [System::Runtime::InteropServices::Out] double% azi1,
548  [System::Runtime::InteropServices::Out] double% azi2,
549  [System::Runtime::InteropServices::Out] double% M12,
550  [System::Runtime::InteropServices::Out] double% M21);
551 
552  /**
553  * See the documentation for Geodesic::Inverse.
554  **********************************************************************/
555  double Inverse(double lat1, double lon1, double lat2, double lon2,
556  [System::Runtime::InteropServices::Out] double% s12,
557  [System::Runtime::InteropServices::Out] double% azi1,
558  [System::Runtime::InteropServices::Out] double% azi2,
559  [System::Runtime::InteropServices::Out] double% m12,
560  [System::Runtime::InteropServices::Out] double% M12,
561  [System::Runtime::InteropServices::Out] double% M21);
562  ///@}
563 
564  /** \name General version of inverse geodesic solution.
565  **********************************************************************/
566  ///@{
567  /**
568  * The general inverse geodesic calculation. Geodesic::Inverse is defined
569  * in terms of this function.
570  *
571  * @param[in] lat1 latitude of point 1 (degrees).
572  * @param[in] lon1 longitude of point 1 (degrees).
573  * @param[in] lat2 latitude of point 2 (degrees).
574  * @param[in] lon2 longitude of point 2 (degrees).
575  * @param[in] outmask a bitor'ed combination of Geodesic::mask values
576  * specifying which of the following parameters should be set.
577  * @param[out] s12 distance between point 1 and point 2 (meters).
578  * @param[out] azi1 azimuth at point 1 (degrees).
579  * @param[out] azi2 (forward) azimuth at point 2 (degrees).
580  * @param[out] m12 reduced length of geodesic (meters).
581  * @param[out] M12 geodesic scale of point 2 relative to point 1
582  * (dimensionless).
583  * @param[out] M21 geodesic scale of point 1 relative to point 2
584  * (dimensionless).
585  * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
586  * @return \e a12 arc length of between point 1 and point 2 (degrees).
587  *
588  * The Geodesic::mask values possible for \e outmask are
589  * - \e outmask |= Geodesic::DISTANCE for the distance \e s12;
590  * - \e outmask |= Geodesic::AZIMUTH for the latitude \e azi2;
591  * - \e outmask |= Geodesic::REDUCEDLENGTH for the reduced length \e
592  * m12;
593  * - \e outmask |= Geodesic::GEODESICSCALE for the geodesic scales \e
594  * M12 and \e M21;
595  * - \e outmask |= Geodesic::AREA for the area \e S12;
596  * - \e outmask |= Geodesic::ALL for all of the above.
597  * .
598  * The arc length is always computed and returned as the function value.
599  **********************************************************************/
600  double GenInverse(double lat1, double lon1, double lat2, double lon2,
601  NETGeographicLib::Mask outmask,
602  [System::Runtime::InteropServices::Out] double% s12,
603  [System::Runtime::InteropServices::Out] double% azi1,
604  [System::Runtime::InteropServices::Out] double% azi2,
605  [System::Runtime::InteropServices::Out] double% m12,
606  [System::Runtime::InteropServices::Out] double% M12,
607  [System::Runtime::InteropServices::Out] double% M21,
608  [System::Runtime::InteropServices::Out] double% S12);
609  ///@}
610 
611  /** \name Interface to GeodesicLine.
612  **********************************************************************/
613  ///@{
614 
615  /**
616  * Set up to compute several points on a single geodesic.
617  *
618  * @param[in] lat1 latitude of point 1 (degrees).
619  * @param[in] lon1 longitude of point 1 (degrees).
620  * @param[in] azi1 azimuth at point 1 (degrees).
621  * @param[in] caps bitor'ed combination of NETGeographicLib::Mask values
622  * specifying the capabilities the GeodesicLine object should possess,
623  * i.e., which quantities can be returned in calls to
624  * GeodesicLine::Position.
625  * @return a GeodesicLine object.
626  *
627  * \e lat1 should be in the range [&minus;90&deg;, 90&deg;]; \e lon1 and \e
628  * azi1 should be in the range [&minus;540&deg;, 540&deg;).
629  *
630  * The NETGeographicLib::Mask values are
631  * - \e caps |= NETGeographicLib::Mask::LATITUDE for the latitude \e lat2; this is
632  * added automatically;
633  * - \e caps |= NETGeographicLib::Mask::LONGITUDE for the latitude \e lon2;
634  * - \e caps |= NETGeographicLib::Mask::AZIMUTH for the azimuth \e azi2; this is
635  * added automatically;
636  * - \e caps |= NETGeographicLib::Mask::DISTANCE for the distance \e s12;
637  * - \e caps |= NETGeographicLib::Mask::REDUCEDLENGTH for the reduced length \e m12;
638  * - \e caps |= NETGeographicLib::Mask::GEODESICSCALE for the geodesic scales \e M12
639  * and \e M21;
640  * - \e caps |= NETGeographicLib::Mask::AREA for the area \e S12;
641  * - \e caps |= NETGeographicLib::Mask::DISTANCE_IN permits the length of the
642  * geodesic to be given in terms of \e s12; without this capability the
643  * length can only be specified in terms of arc length;
644  * - \e caps |= NETGeographicLib::Mask::ALL for all of the above.
645  * .
646  *
647  * If the point is at a pole, the azimuth is defined by keeping \e lon1
648  * fixed, writing \e lat1 = &plusmn;(90 &minus; &epsilon;), and taking the
649  * limit &epsilon; &rarr; 0+.
650  **********************************************************************/
651  GeodesicLine^ Line(double lat1, double lon1, double azi1,
652  NETGeographicLib::Mask caps );
653 
654  ///@}
655 
656  /** \name Inspector functions.
657  **********************************************************************/
658  ///@{
659 
660  /**
661  * @return \e a the equatorial radius of the ellipsoid (meters). This is
662  * the value used in the constructor.
663  **********************************************************************/
664  property double MajorRadius { double get(); }
665 
666  /**
667  * @return \e f the flattening of the ellipsoid. This is the
668  * value used in the constructor.
669  **********************************************************************/
670  property double Flattening { double get(); }
671 
672  /**
673  * @return total area of ellipsoid in meters<sup>2</sup>. The area of a
674  * polygon encircling a pole can be found by adding
675  * Geodesic::EllipsoidArea()/2 to the sum of \e S12 for each side of the
676  * polygon.
677  **********************************************************************/
678  property double EllipsoidArea { double get(); }
679 
680  /**
681  * %return The unmanaged pointer to the GeographicLib::Geodesic.
682  *
683  * This function is for internal use only.
684  **********************************************************************/
685  System::IntPtr^ GetUnmanaged();
686  ///@}
687  };
688 } // namespace NETGeographicLib