geographiclib 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +12 -0
  3. data/LICENSE +24 -0
  4. data/ext/geographiclib/Accumulator.cpp +23 -0
  5. data/ext/geographiclib/AlbersEqualArea.cpp +445 -0
  6. data/ext/geographiclib/AzimuthalEquidistant.cpp +41 -0
  7. data/ext/geographiclib/CassiniSoldner.cpp +89 -0
  8. data/ext/geographiclib/CircularEngine.cpp +96 -0
  9. data/ext/geographiclib/DMS.cpp +381 -0
  10. data/ext/geographiclib/Ellipsoid.cpp +125 -0
  11. data/ext/geographiclib/EllipticFunction.cpp +512 -0
  12. data/ext/geographiclib/GARS.cpp +122 -0
  13. data/ext/geographiclib/GeoCoords.cpp +175 -0
  14. data/ext/geographiclib/Geocentric.cpp +172 -0
  15. data/ext/geographiclib/Geodesic.cpp +1908 -0
  16. data/ext/geographiclib/GeodesicExact.cpp +927 -0
  17. data/ext/geographiclib/GeodesicExactC4.cpp +7879 -0
  18. data/ext/geographiclib/GeodesicLine.cpp +321 -0
  19. data/ext/geographiclib/GeodesicLineExact.cpp +289 -0
  20. data/ext/geographiclib/GeographicLib/Accumulator.hpp +184 -0
  21. data/ext/geographiclib/GeographicLib/AlbersEqualArea.hpp +312 -0
  22. data/ext/geographiclib/GeographicLib/AzimuthalEquidistant.hpp +139 -0
  23. data/ext/geographiclib/GeographicLib/CassiniSoldner.hpp +204 -0
  24. data/ext/geographiclib/GeographicLib/CircularEngine.hpp +195 -0
  25. data/ext/geographiclib/GeographicLib/Config.h +12 -0
  26. data/ext/geographiclib/GeographicLib/Constants.hpp +387 -0
  27. data/ext/geographiclib/GeographicLib/DMS.hpp +370 -0
  28. data/ext/geographiclib/GeographicLib/Ellipsoid.hpp +534 -0
  29. data/ext/geographiclib/GeographicLib/EllipticFunction.hpp +692 -0
  30. data/ext/geographiclib/GeographicLib/GARS.hpp +143 -0
  31. data/ext/geographiclib/GeographicLib/GeoCoords.hpp +544 -0
  32. data/ext/geographiclib/GeographicLib/Geocentric.hpp +267 -0
  33. data/ext/geographiclib/GeographicLib/Geodesic.hpp +970 -0
  34. data/ext/geographiclib/GeographicLib/GeodesicExact.hpp +862 -0
  35. data/ext/geographiclib/GeographicLib/GeodesicLine.hpp +701 -0
  36. data/ext/geographiclib/GeographicLib/GeodesicLineExact.hpp +667 -0
  37. data/ext/geographiclib/GeographicLib/Geohash.hpp +180 -0
  38. data/ext/geographiclib/GeographicLib/Geoid.hpp +472 -0
  39. data/ext/geographiclib/GeographicLib/Georef.hpp +160 -0
  40. data/ext/geographiclib/GeographicLib/Gnomonic.hpp +206 -0
  41. data/ext/geographiclib/GeographicLib/GravityCircle.hpp +301 -0
  42. data/ext/geographiclib/GeographicLib/GravityModel.hpp +520 -0
  43. data/ext/geographiclib/GeographicLib/LambertConformalConic.hpp +313 -0
  44. data/ext/geographiclib/GeographicLib/LocalCartesian.hpp +236 -0
  45. data/ext/geographiclib/GeographicLib/MGRS.hpp +355 -0
  46. data/ext/geographiclib/GeographicLib/MagneticCircle.hpp +178 -0
  47. data/ext/geographiclib/GeographicLib/MagneticModel.hpp +347 -0
  48. data/ext/geographiclib/GeographicLib/Math.hpp +920 -0
  49. data/ext/geographiclib/GeographicLib/NormalGravity.hpp +350 -0
  50. data/ext/geographiclib/GeographicLib/OSGB.hpp +249 -0
  51. data/ext/geographiclib/GeographicLib/PolarStereographic.hpp +150 -0
  52. data/ext/geographiclib/GeographicLib/PolygonArea.hpp +288 -0
  53. data/ext/geographiclib/GeographicLib/Rhumb.hpp +589 -0
  54. data/ext/geographiclib/GeographicLib/SphericalEngine.hpp +376 -0
  55. data/ext/geographiclib/GeographicLib/SphericalHarmonic.hpp +354 -0
  56. data/ext/geographiclib/GeographicLib/SphericalHarmonic1.hpp +281 -0
  57. data/ext/geographiclib/GeographicLib/SphericalHarmonic2.hpp +315 -0
  58. data/ext/geographiclib/GeographicLib/TransverseMercator.hpp +196 -0
  59. data/ext/geographiclib/GeographicLib/TransverseMercatorExact.hpp +254 -0
  60. data/ext/geographiclib/GeographicLib/UTMUPS.hpp +421 -0
  61. data/ext/geographiclib/GeographicLib/Utility.hpp +612 -0
  62. data/ext/geographiclib/Geohash.cpp +102 -0
  63. data/ext/geographiclib/Geoid.cpp +509 -0
  64. data/ext/geographiclib/Georef.cpp +135 -0
  65. data/ext/geographiclib/Gnomonic.cpp +85 -0
  66. data/ext/geographiclib/GravityCircle.cpp +129 -0
  67. data/ext/geographiclib/GravityModel.cpp +360 -0
  68. data/ext/geographiclib/LambertConformalConic.cpp +456 -0
  69. data/ext/geographiclib/LocalCartesian.cpp +62 -0
  70. data/ext/geographiclib/MGRS.cpp +461 -0
  71. data/ext/geographiclib/MagneticCircle.cpp +52 -0
  72. data/ext/geographiclib/MagneticModel.cpp +269 -0
  73. data/ext/geographiclib/Math.cpp +63 -0
  74. data/ext/geographiclib/NormalGravity.cpp +262 -0
  75. data/ext/geographiclib/OSGB.cpp +167 -0
  76. data/ext/geographiclib/PolarStereographic.cpp +108 -0
  77. data/ext/geographiclib/PolygonArea.cpp +204 -0
  78. data/ext/geographiclib/Rhumb.cpp +383 -0
  79. data/ext/geographiclib/SphericalEngine.cpp +477 -0
  80. data/ext/geographiclib/TransverseMercator.cpp +603 -0
  81. data/ext/geographiclib/TransverseMercatorExact.cpp +464 -0
  82. data/ext/geographiclib/UTMUPS.cpp +296 -0
  83. data/ext/geographiclib/Utility.cpp +61 -0
  84. data/ext/geographiclib/extconf.rb +3 -0
  85. data/ext/geographiclib/geographiclib.cpp +62 -0
  86. data/lib/geographiclib.rb +20 -0
  87. metadata +140 -0
@@ -0,0 +1,150 @@
1
+ /**
2
+ * \file PolarStereographic.hpp
3
+ * \brief Header for GeographicLib::PolarStereographic class
4
+ *
5
+ * Copyright (c) Charles Karney (2008-2015) <charles@karney.com> and licensed
6
+ * under the MIT/X11 License. For more information, see
7
+ * http://geographiclib.sourceforge.net/
8
+ **********************************************************************/
9
+
10
+ #if !defined(GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP)
11
+ #define GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP 1
12
+
13
+ #include <GeographicLib/Constants.hpp>
14
+
15
+ namespace GeographicLib {
16
+
17
+ /**
18
+ * \brief Polar stereographic projection
19
+ *
20
+ * Implementation taken from the report,
21
+ * - J. P. Snyder,
22
+ * <a href="http://pubs.er.usgs.gov/usgspubs/pp/pp1395"> Map Projections: A
23
+ * Working Manual</a>, USGS Professional Paper 1395 (1987),
24
+ * pp. 160--163.
25
+ *
26
+ * This is a straightforward implementation of the equations in Snyder except
27
+ * that Newton's method is used to invert the projection.
28
+ *
29
+ * Example of use:
30
+ * \include example-PolarStereographic.cpp
31
+ **********************************************************************/
32
+ class GEOGRAPHICLIB_EXPORT PolarStereographic {
33
+ private:
34
+ typedef Math::real real;
35
+ real _a, _f, _e2, _es, _e2m, _c;
36
+ real _k0;
37
+ public:
38
+
39
+ /**
40
+ * Constructor for a ellipsoid with
41
+ *
42
+ * @param[in] a equatorial radius (meters).
43
+ * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
44
+ * Negative \e f gives a prolate ellipsoid.
45
+ * @param[in] k0 central scale factor.
46
+ * @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k0 is
47
+ * not positive.
48
+ **********************************************************************/
49
+ PolarStereographic(real a, real f, real k0);
50
+
51
+ /**
52
+ * Set the scale for the projection.
53
+ *
54
+ * @param[in] lat (degrees) assuming \e northp = true.
55
+ * @param[in] k scale at latitude \e lat (default 1).
56
+ * @exception GeographicErr \e k is not positive.
57
+ * @exception GeographicErr if \e lat is not in (&minus;90&deg;,
58
+ * 90&deg;].
59
+ **********************************************************************/
60
+ void SetScale(real lat, real k = real(1));
61
+
62
+ /**
63
+ * Forward projection, from geographic to polar stereographic.
64
+ *
65
+ * @param[in] northp the pole which is the center of projection (true means
66
+ * north, false means south).
67
+ * @param[in] lat latitude of point (degrees).
68
+ * @param[in] lon longitude of point (degrees).
69
+ * @param[out] x easting of point (meters).
70
+ * @param[out] y northing of point (meters).
71
+ * @param[out] gamma meridian convergence at point (degrees).
72
+ * @param[out] k scale of projection at point.
73
+ *
74
+ * No false easting or northing is added. \e lat should be in the range
75
+ * (&minus;90&deg;, 90&deg;] for \e northp = true and in the range
76
+ * [&minus;90&deg;, 90&deg;) for \e northp = false.
77
+ **********************************************************************/
78
+ void Forward(bool northp, real lat, real lon,
79
+ real& x, real& y, real& gamma, real& k) const;
80
+
81
+ /**
82
+ * Reverse projection, from polar stereographic to geographic.
83
+ *
84
+ * @param[in] northp the pole which is the center of projection (true means
85
+ * north, false means south).
86
+ * @param[in] x easting of point (meters).
87
+ * @param[in] y northing of point (meters).
88
+ * @param[out] lat latitude of point (degrees).
89
+ * @param[out] lon longitude of point (degrees).
90
+ * @param[out] gamma meridian convergence at point (degrees).
91
+ * @param[out] k scale of projection at point.
92
+ *
93
+ * No false easting or northing is added. The value of \e lon returned is
94
+ * in the range [&minus;180&deg;, 180&deg;).
95
+ **********************************************************************/
96
+ void Reverse(bool northp, real x, real y,
97
+ real& lat, real& lon, real& gamma, real& k) const;
98
+
99
+ /**
100
+ * PolarStereographic::Forward without returning the convergence and scale.
101
+ **********************************************************************/
102
+ void Forward(bool northp, real lat, real lon,
103
+ real& x, real& y) const {
104
+ real gamma, k;
105
+ Forward(northp, lat, lon, x, y, gamma, k);
106
+ }
107
+
108
+ /**
109
+ * PolarStereographic::Reverse without returning the convergence and scale.
110
+ **********************************************************************/
111
+ void Reverse(bool northp, real x, real y,
112
+ real& lat, real& lon) const {
113
+ real gamma, k;
114
+ Reverse(northp, x, y, lat, lon, gamma, k);
115
+ }
116
+
117
+ /** \name Inspector functions
118
+ **********************************************************************/
119
+ ///@{
120
+ /**
121
+ * @return \e a the equatorial radius of the ellipsoid (meters). This is
122
+ * the value used in the constructor.
123
+ **********************************************************************/
124
+ Math::real MajorRadius() const { return _a; }
125
+
126
+ /**
127
+ * @return \e f the flattening of the ellipsoid. This is the value used in
128
+ * the constructor.
129
+ **********************************************************************/
130
+ Math::real Flattening() const { return _f; }
131
+
132
+ /**
133
+ * The central scale for the projection. This is the value of \e k0 used
134
+ * in the constructor and is the scale at the pole unless overridden by
135
+ * PolarStereographic::SetScale.
136
+ **********************************************************************/
137
+ Math::real CentralScale() const { return _k0; }
138
+ ///@}
139
+
140
+ /**
141
+ * A global instantiation of PolarStereographic with the WGS84 ellipsoid
142
+ * and the UPS scale factor. However, unlike UPS, no false easting or
143
+ * northing is added.
144
+ **********************************************************************/
145
+ static const PolarStereographic& UPS();
146
+ };
147
+
148
+ } // namespace GeographicLib
149
+
150
+ #endif // GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP
@@ -0,0 +1,288 @@
1
+ /**
2
+ * \file PolygonArea.hpp
3
+ * \brief Header for GeographicLib::PolygonAreaT class
4
+ *
5
+ * Copyright (c) Charles Karney (2010-2016) <charles@karney.com> and licensed
6
+ * under the MIT/X11 License. For more information, see
7
+ * http://geographiclib.sourceforge.net/
8
+ **********************************************************************/
9
+
10
+ #if !defined(GEOGRAPHICLIB_POLYGONAREA_HPP)
11
+ #define GEOGRAPHICLIB_POLYGONAREA_HPP 1
12
+
13
+ #include <GeographicLib/Geodesic.hpp>
14
+ #include <GeographicLib/GeodesicExact.hpp>
15
+ #include <GeographicLib/Rhumb.hpp>
16
+ #include <GeographicLib/Accumulator.hpp>
17
+
18
+ namespace GeographicLib {
19
+
20
+ /**
21
+ * \brief Polygon areas
22
+ *
23
+ * This computes the area of a polygon whose edges are geodesics using the
24
+ * method given in Section 6 of
25
+ * - C. F. F. Karney,
26
+ * <a href="https://dx.doi.org/10.1007/s00190-012-0578-z">
27
+ * Algorithms for geodesics</a>,
28
+ * J. Geodesy <b>87</b>, 43--55 (2013);
29
+ * DOI: <a href="https://dx.doi.org/10.1007/s00190-012-0578-z">
30
+ * 10.1007/s00190-012-0578-z</a>;
31
+ * addenda:
32
+ * <a href="http://geographiclib.sourceforge.net/geod-addenda.html">
33
+ * geod-addenda.html</a>.
34
+ *
35
+ * This class lets you add vertices and edges one at a time to the polygon.
36
+ * The sequence must start with a vertex and thereafter vertices and edges
37
+ * can be added in any order. Any vertex after the first creates a new edge
38
+ * which is the \e shortest geodesic from the previous vertex. In some
39
+ * cases there may be two or many such shortest geodesics and the area is
40
+ * then not uniquely defined. In this case, either add an intermediate
41
+ * vertex or add the edge \e as an edge (by defining its direction and
42
+ * length).
43
+ *
44
+ * The area and perimeter are accumulated at two times the standard floating
45
+ * point precision to guard against the loss of accuracy with many-sided
46
+ * polygons. At any point you can ask for the perimeter and area so far.
47
+ * There's an option to treat the points as defining a polyline instead of a
48
+ * polygon; in that case, only the perimeter is computed.
49
+ *
50
+ * This is a templated class to allow it to be used with Geodesic,
51
+ * GeodesicExact, and Rhumb. GeographicLib::PolygonArea,
52
+ * GeographicLib::PolygonAreaExact, and GeographicLib::PolygonAreaRhumb are
53
+ * typedefs for these cases.
54
+ *
55
+ * @tparam GeodType the geodesic class to use.
56
+ *
57
+ * Example of use:
58
+ * \include example-PolygonArea.cpp
59
+ *
60
+ * <a href="Planimeter.1.html">Planimeter</a> is a command-line utility
61
+ * providing access to the functionality of PolygonAreaT.
62
+ **********************************************************************/
63
+
64
+ template <class GeodType = Geodesic>
65
+ class PolygonAreaT {
66
+ private:
67
+ typedef Math::real real;
68
+ GeodType _earth;
69
+ real _area0; // Full ellipsoid area
70
+ bool _polyline; // Assume polyline (don't close and skip area)
71
+ unsigned _mask;
72
+ unsigned _num;
73
+ int _crossings;
74
+ Accumulator<> _areasum, _perimetersum;
75
+ real _lat0, _lon0, _lat1, _lon1;
76
+ static inline int transit(real lon1, real lon2) {
77
+ // Return 1 or -1 if crossing prime meridian in east or west direction.
78
+ // Otherwise return zero.
79
+ // Compute lon12 the same way as Geodesic::Inverse.
80
+ lon1 = Math::AngNormalize(lon1);
81
+ lon2 = Math::AngNormalize(lon2);
82
+ real lon12 = Math::AngDiff(lon1, lon2);
83
+ int cross =
84
+ lon1 < 0 && lon2 >= 0 && lon12 > 0 ? 1 :
85
+ (lon2 < 0 && lon1 >= 0 && lon12 < 0 ? -1 : 0);
86
+ return cross;
87
+ }
88
+ // an alternate version of transit to deal with longitudes in the direct
89
+ // problem.
90
+ static inline int transitdirect(real lon1, real lon2) {
91
+ // We want to compute exactly
92
+ // int(floor(lon2 / 360)) - int(floor(lon1 / 360))
93
+ // Since we only need the parity of the result we can use std::remquo;
94
+ // but this is buggy with g++ 4.8.3 (glibc version < 2.22), see
95
+ // https://sourceware.org/bugzilla/show_bug.cgi?id=17569
96
+ // and requires C++11. So instead we do
97
+ #if GEOGRAPHICLIB_CXX11_MATH && GEOGRAPHICLIB_PRECISION != 4
98
+ using std::remainder;
99
+ lon1 = remainder(lon1, real(720)); lon2 = remainder(lon2, real(720));
100
+ return ( (lon2 >= 0 && lon2 < 360 ? 0 : 1) -
101
+ (lon1 >= 0 && lon1 < 360 ? 0 : 1) );
102
+ #else
103
+ using std::fmod;
104
+ lon1 = fmod(lon1, real(720)); lon2 = fmod(lon2, real(720));
105
+ return ( ((lon2 >= 0 && lon2 < 360) || lon2 < -360 ? 0 : 1) -
106
+ ((lon1 >= 0 && lon1 < 360) || lon1 < -360 ? 0 : 1) );
107
+ #endif
108
+ }
109
+ public:
110
+
111
+ /**
112
+ * Constructor for PolygonAreaT.
113
+ *
114
+ * @param[in] earth the Geodesic object to use for geodesic calculations.
115
+ * @param[in] polyline if true that treat the points as defining a polyline
116
+ * instead of a polygon (default = false).
117
+ **********************************************************************/
118
+ PolygonAreaT(const GeodType& earth, bool polyline = false)
119
+ : _earth(earth)
120
+ , _area0(_earth.EllipsoidArea())
121
+ , _polyline(polyline)
122
+ , _mask(GeodType::LATITUDE | GeodType::LONGITUDE | GeodType::DISTANCE |
123
+ (_polyline ? GeodType::NONE :
124
+ GeodType::AREA | GeodType::LONG_UNROLL))
125
+ { Clear(); }
126
+
127
+ /**
128
+ * Clear PolygonAreaT, allowing a new polygon to be started.
129
+ **********************************************************************/
130
+ void Clear() {
131
+ _num = 0;
132
+ _crossings = 0;
133
+ _areasum = 0;
134
+ _perimetersum = 0;
135
+ _lat0 = _lon0 = _lat1 = _lon1 = Math::NaN();
136
+ }
137
+
138
+ /**
139
+ * Add a point to the polygon or polyline.
140
+ *
141
+ * @param[in] lat the latitude of the point (degrees).
142
+ * @param[in] lon the longitude of the point (degrees).
143
+ *
144
+ * \e lat should be in the range [&minus;90&deg;, 90&deg;].
145
+ **********************************************************************/
146
+ void AddPoint(real lat, real lon);
147
+
148
+ /**
149
+ * Add an edge to the polygon or polyline.
150
+ *
151
+ * @param[in] azi azimuth at current point (degrees).
152
+ * @param[in] s distance from current point to next point (meters).
153
+ *
154
+ * This does nothing if no points have been added yet. Use
155
+ * PolygonAreaT::CurrentPoint to determine the position of the new vertex.
156
+ **********************************************************************/
157
+ void AddEdge(real azi, real s);
158
+
159
+ /**
160
+ * Return the results so far.
161
+ *
162
+ * @param[in] reverse if true then clockwise (instead of counter-clockwise)
163
+ * traversal counts as a positive area.
164
+ * @param[in] sign if true then return a signed result for the area if
165
+ * the polygon is traversed in the "wrong" direction instead of returning
166
+ * the area for the rest of the earth.
167
+ * @param[out] perimeter the perimeter of the polygon or length of the
168
+ * polyline (meters).
169
+ * @param[out] area the area of the polygon (meters<sup>2</sup>); only set
170
+ * if \e polyline is false in the constructor.
171
+ * @return the number of points.
172
+ *
173
+ * More points can be added to the polygon after this call.
174
+ **********************************************************************/
175
+ unsigned Compute(bool reverse, bool sign,
176
+ real& perimeter, real& area) const;
177
+
178
+ /**
179
+ * Return the results assuming a tentative final test point is added;
180
+ * however, the data for the test point is not saved. This lets you report
181
+ * a running result for the perimeter and area as the user moves the mouse
182
+ * cursor. Ordinary floating point arithmetic is used to accumulate the
183
+ * data for the test point; thus the area and perimeter returned are less
184
+ * accurate than if PolygonAreaT::AddPoint and PolygonAreaT::Compute are
185
+ * used.
186
+ *
187
+ * @param[in] lat the latitude of the test point (degrees).
188
+ * @param[in] lon the longitude of the test point (degrees).
189
+ * @param[in] reverse if true then clockwise (instead of counter-clockwise)
190
+ * traversal counts as a positive area.
191
+ * @param[in] sign if true then return a signed result for the area if
192
+ * the polygon is traversed in the "wrong" direction instead of returning
193
+ * the area for the rest of the earth.
194
+ * @param[out] perimeter the approximate perimeter of the polygon or length
195
+ * of the polyline (meters).
196
+ * @param[out] area the approximate area of the polygon
197
+ * (meters<sup>2</sup>); only set if polyline is false in the
198
+ * constructor.
199
+ * @return the number of points.
200
+ *
201
+ * \e lat should be in the range [&minus;90&deg;, 90&deg;].
202
+ **********************************************************************/
203
+ unsigned TestPoint(real lat, real lon, bool reverse, bool sign,
204
+ real& perimeter, real& area) const;
205
+
206
+ /**
207
+ * Return the results assuming a tentative final test point is added via an
208
+ * azimuth and distance; however, the data for the test point is not saved.
209
+ * This lets you report a running result for the perimeter and area as the
210
+ * user moves the mouse cursor. Ordinary floating point arithmetic is used
211
+ * to accumulate the data for the test point; thus the area and perimeter
212
+ * returned are less accurate than if PolygonAreaT::AddEdge and
213
+ * PolygonAreaT::Compute are used.
214
+ *
215
+ * @param[in] azi azimuth at current point (degrees).
216
+ * @param[in] s distance from current point to final test point (meters).
217
+ * @param[in] reverse if true then clockwise (instead of counter-clockwise)
218
+ * traversal counts as a positive area.
219
+ * @param[in] sign if true then return a signed result for the area if
220
+ * the polygon is traversed in the "wrong" direction instead of returning
221
+ * the area for the rest of the earth.
222
+ * @param[out] perimeter the approximate perimeter of the polygon or length
223
+ * of the polyline (meters).
224
+ * @param[out] area the approximate area of the polygon
225
+ * (meters<sup>2</sup>); only set if polyline is false in the
226
+ * constructor.
227
+ * @return the number of points.
228
+ **********************************************************************/
229
+ unsigned TestEdge(real azi, real s, bool reverse, bool sign,
230
+ real& perimeter, real& area) const;
231
+
232
+ /** \name Inspector functions
233
+ **********************************************************************/
234
+ ///@{
235
+ /**
236
+ * @return \e a the equatorial radius of the ellipsoid (meters). This is
237
+ * the value inherited from the Geodesic object used in the constructor.
238
+ **********************************************************************/
239
+
240
+ Math::real MajorRadius() const { return _earth.MajorRadius(); }
241
+
242
+ /**
243
+ * @return \e f the flattening of the ellipsoid. This is the value
244
+ * inherited from the Geodesic object used in the constructor.
245
+ **********************************************************************/
246
+ Math::real Flattening() const { return _earth.Flattening(); }
247
+
248
+ /**
249
+ * Report the previous vertex added to the polygon or polyline.
250
+ *
251
+ * @param[out] lat the latitude of the point (degrees).
252
+ * @param[out] lon the longitude of the point (degrees).
253
+ *
254
+ * If no points have been added, then NaNs are returned. Otherwise, \e lon
255
+ * will be in the range [&minus;180&deg;, 180&deg;).
256
+ **********************************************************************/
257
+ void CurrentPoint(real& lat, real& lon) const
258
+ { lat = _lat1; lon = _lon1; }
259
+ ///@}
260
+ };
261
+
262
+ /**
263
+ * @relates PolygonAreaT
264
+ *
265
+ * Polygon areas using Geodesic. This should be used if the flattening is
266
+ * small.
267
+ **********************************************************************/
268
+ typedef PolygonAreaT<Geodesic> PolygonArea;
269
+
270
+ /**
271
+ * @relates PolygonAreaT
272
+ *
273
+ * Polygon areas using GeodesicExact. (But note that the implementation of
274
+ * areas in GeodesicExact uses a high order series and this is only accurate
275
+ * for modest flattenings.)
276
+ **********************************************************************/
277
+ typedef PolygonAreaT<GeodesicExact> PolygonAreaExact;
278
+
279
+ /**
280
+ * @relates PolygonAreaT
281
+ *
282
+ * Polygon areas using Rhumb.
283
+ **********************************************************************/
284
+ typedef PolygonAreaT<Rhumb> PolygonAreaRhumb;
285
+
286
+ } // namespace GeographicLib
287
+
288
+ #endif // GEOGRAPHICLIB_POLYGONAREA_HPP
@@ -0,0 +1,589 @@
1
+ /**
2
+ * \file Rhumb.hpp
3
+ * \brief Header for GeographicLib::Rhumb and GeographicLib::RhumbLine classes
4
+ *
5
+ * Copyright (c) Charles Karney (2014-2015) <charles@karney.com> and licensed
6
+ * under the MIT/X11 License. For more information, see
7
+ * http://geographiclib.sourceforge.net/
8
+ **********************************************************************/
9
+
10
+ #if !defined(GEOGRAPHICLIB_RHUMB_HPP)
11
+ #define GEOGRAPHICLIB_RHUMB_HPP 1
12
+
13
+ #include <GeographicLib/Constants.hpp>
14
+ #include <GeographicLib/Ellipsoid.hpp>
15
+
16
+ #if !defined(GEOGRAPHICLIB_RHUMBAREA_ORDER)
17
+ /**
18
+ * The order of the series approximation used in rhumb area calculations.
19
+ * GEOGRAPHICLIB_RHUMBAREA_ORDER can be set to any integer in [4, 8].
20
+ **********************************************************************/
21
+ # define GEOGRAPHICLIB_RHUMBAREA_ORDER \
22
+ (GEOGRAPHICLIB_PRECISION == 2 ? 6 : \
23
+ (GEOGRAPHICLIB_PRECISION == 1 ? 4 : 8))
24
+ #endif
25
+
26
+ namespace GeographicLib {
27
+
28
+ class RhumbLine;
29
+ template <class T> class PolygonAreaT;
30
+
31
+ /**
32
+ * \brief Solve of the direct and inverse rhumb problems.
33
+ *
34
+ * The path of constant azimuth between two points on a ellipsoid at (\e
35
+ * lat1, \e lon1) and (\e lat2, \e lon2) is called the rhumb line (also
36
+ * called the loxodrome). Its length is \e s12 and its azimuth is \e azi12.
37
+ * (The azimuth is the heading measured clockwise from north.)
38
+ *
39
+ * Given \e lat1, \e lon1, \e azi12, and \e s12, we can determine \e lat2,
40
+ * and \e lon2. This is the \e direct rhumb problem and its solution is
41
+ * given by the function Rhumb::Direct.
42
+ *
43
+ * Given \e lat1, \e lon1, \e lat2, and \e lon2, we can determine \e azi12
44
+ * and \e s12. This is the \e inverse rhumb problem, whose solution is given
45
+ * by Rhumb::Inverse. This finds the shortest such rhumb line, i.e., the one
46
+ * that wraps no more than half way around the earth. If the end points are
47
+ * on opposite meridians, there are two shortest rhumb lines and the
48
+ * east-going one is chosen.
49
+ *
50
+ * These routines also optionally calculate the area under the rhumb line, \e
51
+ * S12. This is the area, measured counter-clockwise, of the rhumb line
52
+ * quadrilateral with corners (<i>lat1</i>,<i>lon1</i>), (0,<i>lon1</i>),
53
+ * (0,<i>lon2</i>), and (<i>lat2</i>,<i>lon2</i>).
54
+ *
55
+ * Note that rhumb lines may be appreciably longer (up to 50%) than the
56
+ * corresponding Geodesic. For example the distance between London Heathrow
57
+ * and Tokyo Narita via the rhumb line is 11400 km which is 18% longer than
58
+ * the geodesic distance 9600 km.
59
+ *
60
+ * For more information on rhumb lines see \ref rhumb.
61
+ *
62
+ * Example of use:
63
+ * \include example-Rhumb.cpp
64
+ **********************************************************************/
65
+
66
+ class GEOGRAPHICLIB_EXPORT Rhumb {
67
+ private:
68
+ typedef Math::real real;
69
+ friend class RhumbLine;
70
+ template <class T> friend class PolygonAreaT;
71
+ Ellipsoid _ell;
72
+ bool _exact;
73
+ real _c2;
74
+ static const int tm_maxord = GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER;
75
+ static const int maxpow_ = GEOGRAPHICLIB_RHUMBAREA_ORDER;
76
+ // _R[0] unused
77
+ real _R[maxpow_ + 1];
78
+ static inline real gd(real x)
79
+ { using std::atan; using std::sinh; return atan(sinh(x)); }
80
+
81
+ // Use divided differences to determine (mu2 - mu1) / (psi2 - psi1)
82
+ // accurately
83
+ //
84
+ // Definition: Df(x,y,d) = (f(x) - f(y)) / (x - y)
85
+ // See:
86
+ // W. M. Kahan and R. J. Fateman,
87
+ // Symbolic computation of divided differences,
88
+ // SIGSAM Bull. 33(3), 7-28 (1999)
89
+ // https://dx.doi.org/10.1145/334714.334716
90
+ // http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf
91
+
92
+ static inline real Dlog(real x, real y) {
93
+ real t = x - y;
94
+ return t ? 2 * Math::atanh(t / (x + y)) / t : 1 / x;
95
+ }
96
+ // N.B., x and y are in degrees
97
+ static inline real Dtan(real x, real y) {
98
+ real d = x - y, tx = Math::tand(x), ty = Math::tand(y), txy = tx * ty;
99
+ return d ?
100
+ (2 * txy > -1 ? (1 + txy) * Math::tand(d) : tx - ty) /
101
+ (d * Math::degree()) :
102
+ 1 + txy;
103
+ }
104
+ static inline real Datan(real x, real y) {
105
+ using std::atan;
106
+ real d = x - y, xy = x * y;
107
+ return d ? (2 * xy > -1 ? atan( d / (1 + xy) ) : atan(x) - atan(y)) / d :
108
+ 1 / (1 + xy);
109
+ }
110
+ static inline real Dsin(real x, real y) {
111
+ using std::sin; using std::cos;
112
+ real d = (x - y) / 2;
113
+ return cos((x + y)/2) * (d ? sin(d) / d : 1);
114
+ }
115
+ static inline real Dsinh(real x, real y) {
116
+ using std::sinh; using std::cosh;
117
+ real d = (x - y) / 2;
118
+ return cosh((x + y) / 2) * (d ? sinh(d) / d : 1);
119
+ }
120
+ static inline real Dcosh(real x, real y) {
121
+ using std::sinh;
122
+ real d = (x - y) / 2;
123
+ return sinh((x + y) / 2) * (d ? sinh(d) / d : 1);
124
+ }
125
+ static inline real Dasinh(real x, real y) {
126
+ real d = x - y,
127
+ hx = Math::hypot(real(1), x), hy = Math::hypot(real(1), y);
128
+ return d ? Math::asinh(x*y > 0 ? d * (x + y) / (x*hy + y*hx) :
129
+ x*hy - y*hx) / d :
130
+ 1 / hx;
131
+ }
132
+ static inline real Dgd(real x, real y) {
133
+ using std::sinh;
134
+ return Datan(sinh(x), sinh(y)) * Dsinh(x, y);
135
+ }
136
+ // N.B., x and y are the tangents of the angles
137
+ static inline real Dgdinv(real x, real y)
138
+ { return Dasinh(x, y) / Datan(x, y); }
139
+ // Copied from LambertConformalConic...
140
+ // Deatanhe(x,y) = eatanhe((x-y)/(1-e^2*x*y))/(x-y)
141
+ inline real Deatanhe(real x, real y) const {
142
+ real t = x - y, d = 1 - _ell._e2 * x * y;
143
+ return t ? Math::eatanhe(t / d, _ell._es) / t : _ell._e2 / d;
144
+ }
145
+ // (E(x) - E(y)) / (x - y) -- E = incomplete elliptic integral of 2nd kind
146
+ real DE(real x, real y) const;
147
+ // (mux - muy) / (phix - phiy) using elliptic integrals
148
+ real DRectifying(real latx, real laty) const;
149
+ // (psix - psiy) / (phix - phiy)
150
+ real DIsometric(real latx, real laty) const;
151
+
152
+ // (sum(c[j]*sin(2*j*x),j=1..n) - sum(c[j]*sin(2*j*x),j=1..n)) / (x - y)
153
+ static real SinCosSeries(bool sinp,
154
+ real x, real y, const real c[], int n);
155
+ // (mux - muy) / (chix - chiy) using Krueger's series
156
+ real DConformalToRectifying(real chix, real chiy) const;
157
+ // (chix - chiy) / (mux - muy) using Krueger's series
158
+ real DRectifyingToConformal(real mux, real muy) const;
159
+
160
+ // (mux - muy) / (psix - psiy)
161
+ // N.B., psix and psiy are in degrees
162
+ real DIsometricToRectifying(real psix, real psiy) const;
163
+ // (psix - psiy) / (mux - muy)
164
+ real DRectifyingToIsometric(real mux, real muy) const;
165
+
166
+ real MeanSinXi(real psi1, real psi2) const;
167
+
168
+ // The following two functions (with lots of ignored arguments) mimic the
169
+ // interface to the corresponding Geodesic function. These are needed by
170
+ // PolygonAreaT.
171
+ void GenDirect(real lat1, real lon1, real azi12,
172
+ bool, real s12, unsigned outmask,
173
+ real& lat2, real& lon2, real&, real&, real&, real&, real&,
174
+ real& S12) const {
175
+ GenDirect(lat1, lon1, azi12, s12, outmask, lat2, lon2, S12);
176
+ }
177
+ void GenInverse(real lat1, real lon1, real lat2, real lon2,
178
+ unsigned outmask, real& s12, real& azi12,
179
+ real&, real& , real& , real& , real& S12) const {
180
+ GenInverse(lat1, lon1, lat2, lon2, outmask, s12, azi12, S12);
181
+ }
182
+ public:
183
+
184
+ /**
185
+ * Bit masks for what calculations to do. They specify which results to
186
+ * return in the general routines Rhumb::GenDirect and Rhumb::GenInverse
187
+ * routines. RhumbLine::mask is a duplication of this enum.
188
+ **********************************************************************/
189
+ enum mask {
190
+ /**
191
+ * No output.
192
+ * @hideinitializer
193
+ **********************************************************************/
194
+ NONE = 0U,
195
+ /**
196
+ * Calculate latitude \e lat2.
197
+ * @hideinitializer
198
+ **********************************************************************/
199
+ LATITUDE = 1U<<7,
200
+ /**
201
+ * Calculate longitude \e lon2.
202
+ * @hideinitializer
203
+ **********************************************************************/
204
+ LONGITUDE = 1U<<8,
205
+ /**
206
+ * Calculate azimuth \e azi12.
207
+ * @hideinitializer
208
+ **********************************************************************/
209
+ AZIMUTH = 1U<<9,
210
+ /**
211
+ * Calculate distance \e s12.
212
+ * @hideinitializer
213
+ **********************************************************************/
214
+ DISTANCE = 1U<<10,
215
+ /**
216
+ * Calculate area \e S12.
217
+ * @hideinitializer
218
+ **********************************************************************/
219
+ AREA = 1U<<14,
220
+ /**
221
+ * Unroll \e lon2 in the direct calculation.
222
+ * @hideinitializer
223
+ **********************************************************************/
224
+ LONG_UNROLL = 1U<<15,
225
+ /**
226
+ * Calculate everything. (LONG_UNROLL is not included in this mask.)
227
+ * @hideinitializer
228
+ **********************************************************************/
229
+ ALL = 0x7F80U,
230
+ };
231
+
232
+ /**
233
+ * Constructor for a ellipsoid with
234
+ *
235
+ * @param[in] a equatorial radius (meters).
236
+ * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
237
+ * Negative \e f gives a prolate ellipsoid.
238
+ * @param[in] exact if true (the default) use an addition theorem for
239
+ * elliptic integrals to compute divided differences; otherwise use
240
+ * series expansion (accurate for |<i>f</i>| < 0.01).
241
+ * @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
242
+ * positive.
243
+ *
244
+ * See \ref rhumb, for a detailed description of the \e exact parameter.
245
+ **********************************************************************/
246
+ Rhumb(real a, real f, bool exact = true);
247
+
248
+ /**
249
+ * Solve the direct rhumb problem returning also the area.
250
+ *
251
+ * @param[in] lat1 latitude of point 1 (degrees).
252
+ * @param[in] lon1 longitude of point 1 (degrees).
253
+ * @param[in] azi12 azimuth of the rhumb line (degrees).
254
+ * @param[in] s12 distance between point 1 and point 2 (meters); it can be
255
+ * negative.
256
+ * @param[out] lat2 latitude of point 2 (degrees).
257
+ * @param[out] lon2 longitude of point 2 (degrees).
258
+ * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
259
+ *
260
+ * \e lat1 should be in the range [&minus;90&deg;, 90&deg;]. The value of
261
+ * \e lon2 returned is in the range [&minus;180&deg;, 180&deg;).
262
+ *
263
+ * If point 1 is a pole, the cosine of its latitude is taken to be
264
+ * 1/&epsilon;<sup>2</sup> (where &epsilon; is 2<sup>-52</sup>). This
265
+ * position, which is extremely close to the actual pole, allows the
266
+ * calculation to be carried out in finite terms. If \e s12 is large
267
+ * enough that the rhumb line crosses a pole, the longitude of point 2
268
+ * is indeterminate (a NaN is returned for \e lon2 and \e S12).
269
+ **********************************************************************/
270
+ void Direct(real lat1, real lon1, real azi12, real s12,
271
+ real& lat2, real& lon2, real& S12) const {
272
+ GenDirect(lat1, lon1, azi12, s12,
273
+ LATITUDE | LONGITUDE | AREA, lat2, lon2, S12);
274
+ }
275
+
276
+ /**
277
+ * Solve the direct rhumb problem without the area.
278
+ **********************************************************************/
279
+ void Direct(real lat1, real lon1, real azi12, real s12,
280
+ real& lat2, real& lon2) const {
281
+ real t;
282
+ GenDirect(lat1, lon1, azi12, s12, LATITUDE | LONGITUDE, lat2, lon2, t);
283
+ }
284
+
285
+ /**
286
+ * The general direct rhumb problem. Rhumb::Direct is defined in terms
287
+ * of this function.
288
+ *
289
+ * @param[in] lat1 latitude of point 1 (degrees).
290
+ * @param[in] lon1 longitude of point 1 (degrees).
291
+ * @param[in] azi12 azimuth of the rhumb line (degrees).
292
+ * @param[in] s12 distance between point 1 and point 2 (meters); it can be
293
+ * negative.
294
+ * @param[in] outmask a bitor'ed combination of Rhumb::mask values
295
+ * specifying which of the following parameters should be set.
296
+ * @param[out] lat2 latitude of point 2 (degrees).
297
+ * @param[out] lon2 longitude of point 2 (degrees).
298
+ * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
299
+ *
300
+ * The Rhumb::mask values possible for \e outmask are
301
+ * - \e outmask |= Rhumb::LATITUDE for the latitude \e lat2;
302
+ * - \e outmask |= Rhumb::LONGITUDE for the latitude \e lon2;
303
+ * - \e outmask |= Rhumb::AREA for the area \e S12;
304
+ * - \e outmask |= Rhumb::ALL for all of the above;
305
+ * - \e outmask |= Rhumb::LONG_UNROLL to unroll \e lon2 instead of wrapping
306
+ * it into the range [&minus;180&deg;, 180&deg;).
307
+ * .
308
+ * With the Rhumb::LONG_UNROLL bit set, the quantity \e lon2 &minus;
309
+ * \e lon1 indicates how many times and in what sense the rhumb line
310
+ * encircles the ellipsoid.
311
+ **********************************************************************/
312
+ void GenDirect(real lat1, real lon1, real azi12, real s12, unsigned outmask,
313
+ real& lat2, real& lon2, real& S12) const;
314
+
315
+ /**
316
+ * Solve the inverse rhumb problem returning also the area.
317
+ *
318
+ * @param[in] lat1 latitude of point 1 (degrees).
319
+ * @param[in] lon1 longitude of point 1 (degrees).
320
+ * @param[in] lat2 latitude of point 2 (degrees).
321
+ * @param[in] lon2 longitude of point 2 (degrees).
322
+ * @param[out] s12 rhumb distance between point 1 and point 2 (meters).
323
+ * @param[out] azi12 azimuth of the rhumb line (degrees).
324
+ * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
325
+ *
326
+ * The shortest rhumb line is found. If the end points are on opposite
327
+ * meridians, there are two shortest rhumb lines and the east-going one is
328
+ * chosen. \e lat1 and \e lat2 should be in the range [&minus;90&deg;,
329
+ * 90&deg;]. The value of \e azi12 returned is in the range
330
+ * [&minus;180&deg;, 180&deg;).
331
+ *
332
+ * If either point is a pole, the cosine of its latitude is taken to be
333
+ * 1/&epsilon;<sup>2</sup> (where &epsilon; is 2<sup>-52</sup>). This
334
+ * position, which is extremely close to the actual pole, allows the
335
+ * calculation to be carried out in finite terms.
336
+ **********************************************************************/
337
+ void Inverse(real lat1, real lon1, real lat2, real lon2,
338
+ real& s12, real& azi12, real& S12) const {
339
+ GenInverse(lat1, lon1, lat2, lon2,
340
+ DISTANCE | AZIMUTH | AREA, s12, azi12, S12);
341
+ }
342
+
343
+ /**
344
+ * Solve the inverse rhumb problem without the area.
345
+ **********************************************************************/
346
+ void Inverse(real lat1, real lon1, real lat2, real lon2,
347
+ real& s12, real& azi12) const {
348
+ real t;
349
+ GenInverse(lat1, lon1, lat2, lon2, DISTANCE | AZIMUTH, s12, azi12, t);
350
+ }
351
+
352
+ /**
353
+ * The general inverse rhumb problem. Rhumb::Inverse is defined in terms
354
+ * of this function.
355
+ *
356
+ * @param[in] lat1 latitude of point 1 (degrees).
357
+ * @param[in] lon1 longitude of point 1 (degrees).
358
+ * @param[in] lat2 latitude of point 2 (degrees).
359
+ * @param[in] lon2 longitude of point 2 (degrees).
360
+ * @param[in] outmask a bitor'ed combination of Rhumb::mask values
361
+ * specifying which of the following parameters should be set.
362
+ * @param[out] s12 rhumb distance between point 1 and point 2 (meters).
363
+ * @param[out] azi12 azimuth of the rhumb line (degrees).
364
+ * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
365
+ *
366
+ * The Rhumb::mask values possible for \e outmask are
367
+ * - \e outmask |= Rhumb::DISTANCE for the latitude \e s12;
368
+ * - \e outmask |= Rhumb::AZIMUTH for the latitude \e azi12;
369
+ * - \e outmask |= Rhumb::AREA for the area \e S12;
370
+ * - \e outmask |= Rhumb::ALL for all of the above;
371
+ **********************************************************************/
372
+ void GenInverse(real lat1, real lon1, real lat2, real lon2,
373
+ unsigned outmask,
374
+ real& s12, real& azi12, real& S12) const;
375
+
376
+ /**
377
+ * Set up to compute several points on a single rhumb line.
378
+ *
379
+ * @param[in] lat1 latitude of point 1 (degrees).
380
+ * @param[in] lon1 longitude of point 1 (degrees).
381
+ * @param[in] azi12 azimuth of the rhumb line (degrees).
382
+ * @return a RhumbLine object.
383
+ *
384
+ * \e lat1 should be in the range [&minus;90&deg;, 90&deg;].
385
+ *
386
+ * If point 1 is a pole, the cosine of its latitude is taken to be
387
+ * 1/&epsilon;<sup>2</sup> (where &epsilon; is 2<sup>-52</sup>). This
388
+ * position, which is extremely close to the actual pole, allows the
389
+ * calculation to be carried out in finite terms.
390
+ **********************************************************************/
391
+ RhumbLine Line(real lat1, real lon1, real azi12) const;
392
+
393
+ /** \name Inspector functions.
394
+ **********************************************************************/
395
+ ///@{
396
+
397
+ /**
398
+ * @return \e a the equatorial radius of the ellipsoid (meters). This is
399
+ * the value used in the constructor.
400
+ **********************************************************************/
401
+ Math::real MajorRadius() const { return _ell.MajorRadius(); }
402
+
403
+ /**
404
+ * @return \e f the flattening of the ellipsoid. This is the
405
+ * value used in the constructor.
406
+ **********************************************************************/
407
+ Math::real Flattening() const { return _ell.Flattening(); }
408
+
409
+ Math::real EllipsoidArea() const { return _ell.Area(); }
410
+
411
+ /**
412
+ * A global instantiation of Rhumb with the parameters for the WGS84
413
+ * ellipsoid.
414
+ **********************************************************************/
415
+ static const Rhumb& WGS84();
416
+ };
417
+
418
+ /**
419
+ * \brief Find a sequence of points on a single rhumb line.
420
+ *
421
+ * RhumbLine facilitates the determination of a series of points on a single
422
+ * rhumb line. The starting point (\e lat1, \e lon1) and the azimuth \e
423
+ * azi12 are specified in the call to Rhumb::Line which returns a RhumbLine
424
+ * object. RhumbLine.Position returns the location of point 2 (and,
425
+ * optionally, the corresponding area, \e S12) a distance \e s12 along the
426
+ * rhumb line.
427
+ *
428
+ * There is no public constructor for this class. (Use Rhumb::Line to create
429
+ * an instance.) The Rhumb object used to create a RhumbLine must stay in
430
+ * scope as long as the RhumbLine.
431
+ *
432
+ * Example of use:
433
+ * \include example-RhumbLine.cpp
434
+ **********************************************************************/
435
+
436
+ class GEOGRAPHICLIB_EXPORT RhumbLine {
437
+ private:
438
+ typedef Math::real real;
439
+ friend class Rhumb;
440
+ const Rhumb& _rh;
441
+ bool _exact;
442
+ real _lat1, _lon1, _azi12, _salp, _calp, _mu1, _psi1, _r1;
443
+ RhumbLine& operator=(const RhumbLine&); // copy assignment not allowed
444
+ RhumbLine(const Rhumb& rh, real lat1, real lon1, real azi12,
445
+ bool exact);
446
+ public:
447
+
448
+ /**
449
+ * This is a duplication of Rhumb::mask.
450
+ **********************************************************************/
451
+ enum mask {
452
+ /**
453
+ * No output.
454
+ * @hideinitializer
455
+ **********************************************************************/
456
+ NONE = Rhumb::NONE,
457
+ /**
458
+ * Calculate latitude \e lat2.
459
+ * @hideinitializer
460
+ **********************************************************************/
461
+ LATITUDE = Rhumb::LATITUDE,
462
+ /**
463
+ * Calculate longitude \e lon2.
464
+ * @hideinitializer
465
+ **********************************************************************/
466
+ LONGITUDE = Rhumb::LONGITUDE,
467
+ /**
468
+ * Calculate azimuth \e azi12.
469
+ * @hideinitializer
470
+ **********************************************************************/
471
+ AZIMUTH = Rhumb::AZIMUTH,
472
+ /**
473
+ * Calculate distance \e s12.
474
+ * @hideinitializer
475
+ **********************************************************************/
476
+ DISTANCE = Rhumb::DISTANCE,
477
+ /**
478
+ * Calculate area \e S12.
479
+ * @hideinitializer
480
+ **********************************************************************/
481
+ AREA = Rhumb::AREA,
482
+ /**
483
+ * Unroll \e lon2 in the direct calculation.
484
+ * @hideinitializer
485
+ **********************************************************************/
486
+ LONG_UNROLL = Rhumb::LONG_UNROLL,
487
+ /**
488
+ * Calculate everything. (LONG_UNROLL is not included in this mask.)
489
+ * @hideinitializer
490
+ **********************************************************************/
491
+ ALL = Rhumb::ALL,
492
+ };
493
+
494
+ /**
495
+ * Compute the position of point 2 which is a distance \e s12 (meters) from
496
+ * point 1. The area is also computed.
497
+ *
498
+ * @param[in] s12 distance between point 1 and point 2 (meters); it can be
499
+ * negative.
500
+ * @param[out] lat2 latitude of point 2 (degrees).
501
+ * @param[out] lon2 longitude of point 2 (degrees).
502
+ * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
503
+ *
504
+ * The value of \e lon2 returned is in the range [&minus;180&deg;,
505
+ * 180&deg;).
506
+ *
507
+ * If \e s12 is large enough that the rhumb line crosses a pole, the
508
+ * longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and
509
+ * \e S12).
510
+ **********************************************************************/
511
+ void Position(real s12, real& lat2, real& lon2, real& S12) const {
512
+ GenPosition(s12, LATITUDE | LONGITUDE | AREA, lat2, lon2, S12);
513
+ }
514
+
515
+ /**
516
+ * Compute the position of point 2 which is a distance \e s12 (meters) from
517
+ * point 1. The area is not computed.
518
+ **********************************************************************/
519
+ void Position(real s12, real& lat2, real& lon2) const {
520
+ real t;
521
+ GenPosition(s12, LATITUDE | LONGITUDE, lat2, lon2, t);
522
+ }
523
+
524
+ /**
525
+ * The general position routine. RhumbLine::Position is defined in term so
526
+ * this function.
527
+ *
528
+ * @param[in] s12 distance between point 1 and point 2 (meters); it can be
529
+ * negative.
530
+ * @param[in] outmask a bitor'ed combination of RhumbLine::mask values
531
+ * specifying which of the following parameters should be set.
532
+ * @param[out] lat2 latitude of point 2 (degrees).
533
+ * @param[out] lon2 longitude of point 2 (degrees).
534
+ * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
535
+ *
536
+ * The RhumbLine::mask values possible for \e outmask are
537
+ * - \e outmask |= RhumbLine::LATITUDE for the latitude \e lat2;
538
+ * - \e outmask |= RhumbLine::LONGITUDE for the latitude \e lon2;
539
+ * - \e outmask |= RhumbLine::AREA for the area \e S12;
540
+ * - \e outmask |= RhumbLine::ALL for all of the above;
541
+ * - \e outmask |= RhumbLine::LONG_UNROLL to unroll \e lon2 instead of
542
+ * wrapping it into the range [&minus;180&deg;, 180&deg;).
543
+ * .
544
+ * With the RhumbLine::LONG_UNROLL bit set, the quantity \e lon2 &minus; \e
545
+ * lon1 indicates how many times and in what sense the rhumb line encircles
546
+ * the ellipsoid.
547
+ *
548
+ * If \e s12 is large enough that the rhumb line crosses a pole, the
549
+ * longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and
550
+ * \e S12).
551
+ **********************************************************************/
552
+ void GenPosition(real s12, unsigned outmask,
553
+ real& lat2, real& lon2, real& S12) const;
554
+
555
+ /** \name Inspector functions
556
+ **********************************************************************/
557
+ ///@{
558
+
559
+ /**
560
+ * @return \e lat1 the latitude of point 1 (degrees).
561
+ **********************************************************************/
562
+ Math::real Latitude() const { return _lat1; }
563
+
564
+ /**
565
+ * @return \e lon1 the longitude of point 1 (degrees).
566
+ **********************************************************************/
567
+ Math::real Longitude() const { return _lon1; }
568
+
569
+ /**
570
+ * @return \e azi12 the azimuth of the rhumb line (degrees).
571
+ **********************************************************************/
572
+ Math::real Azimuth() const { return _azi12; }
573
+
574
+ /**
575
+ * @return \e a the equatorial radius of the ellipsoid (meters). This is
576
+ * the value inherited from the Rhumb object used in the constructor.
577
+ **********************************************************************/
578
+ Math::real MajorRadius() const { return _rh.MajorRadius(); }
579
+
580
+ /**
581
+ * @return \e f the flattening of the ellipsoid. This is the value
582
+ * inherited from the Rhumb object used in the constructor.
583
+ **********************************************************************/
584
+ Math::real Flattening() const { return _rh.Flattening(); }
585
+ };
586
+
587
+ } // namespace GeographicLib
588
+
589
+ #endif // GEOGRAPHICLIB_RHUMB_HPP