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