geographiclib 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/AUTHORS +12 -0
- data/LICENSE +24 -0
- data/ext/geographiclib/Accumulator.cpp +23 -0
- data/ext/geographiclib/AlbersEqualArea.cpp +445 -0
- data/ext/geographiclib/AzimuthalEquidistant.cpp +41 -0
- data/ext/geographiclib/CassiniSoldner.cpp +89 -0
- data/ext/geographiclib/CircularEngine.cpp +96 -0
- data/ext/geographiclib/DMS.cpp +381 -0
- data/ext/geographiclib/Ellipsoid.cpp +125 -0
- data/ext/geographiclib/EllipticFunction.cpp +512 -0
- data/ext/geographiclib/GARS.cpp +122 -0
- data/ext/geographiclib/GeoCoords.cpp +175 -0
- data/ext/geographiclib/Geocentric.cpp +172 -0
- data/ext/geographiclib/Geodesic.cpp +1908 -0
- data/ext/geographiclib/GeodesicExact.cpp +927 -0
- data/ext/geographiclib/GeodesicExactC4.cpp +7879 -0
- data/ext/geographiclib/GeodesicLine.cpp +321 -0
- data/ext/geographiclib/GeodesicLineExact.cpp +289 -0
- data/ext/geographiclib/GeographicLib/Accumulator.hpp +184 -0
- data/ext/geographiclib/GeographicLib/AlbersEqualArea.hpp +312 -0
- data/ext/geographiclib/GeographicLib/AzimuthalEquidistant.hpp +139 -0
- data/ext/geographiclib/GeographicLib/CassiniSoldner.hpp +204 -0
- data/ext/geographiclib/GeographicLib/CircularEngine.hpp +195 -0
- data/ext/geographiclib/GeographicLib/Config.h +12 -0
- data/ext/geographiclib/GeographicLib/Constants.hpp +387 -0
- data/ext/geographiclib/GeographicLib/DMS.hpp +370 -0
- data/ext/geographiclib/GeographicLib/Ellipsoid.hpp +534 -0
- data/ext/geographiclib/GeographicLib/EllipticFunction.hpp +692 -0
- data/ext/geographiclib/GeographicLib/GARS.hpp +143 -0
- data/ext/geographiclib/GeographicLib/GeoCoords.hpp +544 -0
- data/ext/geographiclib/GeographicLib/Geocentric.hpp +267 -0
- data/ext/geographiclib/GeographicLib/Geodesic.hpp +970 -0
- data/ext/geographiclib/GeographicLib/GeodesicExact.hpp +862 -0
- data/ext/geographiclib/GeographicLib/GeodesicLine.hpp +701 -0
- data/ext/geographiclib/GeographicLib/GeodesicLineExact.hpp +667 -0
- data/ext/geographiclib/GeographicLib/Geohash.hpp +180 -0
- data/ext/geographiclib/GeographicLib/Geoid.hpp +472 -0
- data/ext/geographiclib/GeographicLib/Georef.hpp +160 -0
- data/ext/geographiclib/GeographicLib/Gnomonic.hpp +206 -0
- data/ext/geographiclib/GeographicLib/GravityCircle.hpp +301 -0
- data/ext/geographiclib/GeographicLib/GravityModel.hpp +520 -0
- data/ext/geographiclib/GeographicLib/LambertConformalConic.hpp +313 -0
- data/ext/geographiclib/GeographicLib/LocalCartesian.hpp +236 -0
- data/ext/geographiclib/GeographicLib/MGRS.hpp +355 -0
- data/ext/geographiclib/GeographicLib/MagneticCircle.hpp +178 -0
- data/ext/geographiclib/GeographicLib/MagneticModel.hpp +347 -0
- data/ext/geographiclib/GeographicLib/Math.hpp +920 -0
- data/ext/geographiclib/GeographicLib/NormalGravity.hpp +350 -0
- data/ext/geographiclib/GeographicLib/OSGB.hpp +249 -0
- data/ext/geographiclib/GeographicLib/PolarStereographic.hpp +150 -0
- data/ext/geographiclib/GeographicLib/PolygonArea.hpp +288 -0
- data/ext/geographiclib/GeographicLib/Rhumb.hpp +589 -0
- data/ext/geographiclib/GeographicLib/SphericalEngine.hpp +376 -0
- data/ext/geographiclib/GeographicLib/SphericalHarmonic.hpp +354 -0
- data/ext/geographiclib/GeographicLib/SphericalHarmonic1.hpp +281 -0
- data/ext/geographiclib/GeographicLib/SphericalHarmonic2.hpp +315 -0
- data/ext/geographiclib/GeographicLib/TransverseMercator.hpp +196 -0
- data/ext/geographiclib/GeographicLib/TransverseMercatorExact.hpp +254 -0
- data/ext/geographiclib/GeographicLib/UTMUPS.hpp +421 -0
- data/ext/geographiclib/GeographicLib/Utility.hpp +612 -0
- data/ext/geographiclib/Geohash.cpp +102 -0
- data/ext/geographiclib/Geoid.cpp +509 -0
- data/ext/geographiclib/Georef.cpp +135 -0
- data/ext/geographiclib/Gnomonic.cpp +85 -0
- data/ext/geographiclib/GravityCircle.cpp +129 -0
- data/ext/geographiclib/GravityModel.cpp +360 -0
- data/ext/geographiclib/LambertConformalConic.cpp +456 -0
- data/ext/geographiclib/LocalCartesian.cpp +62 -0
- data/ext/geographiclib/MGRS.cpp +461 -0
- data/ext/geographiclib/MagneticCircle.cpp +52 -0
- data/ext/geographiclib/MagneticModel.cpp +269 -0
- data/ext/geographiclib/Math.cpp +63 -0
- data/ext/geographiclib/NormalGravity.cpp +262 -0
- data/ext/geographiclib/OSGB.cpp +167 -0
- data/ext/geographiclib/PolarStereographic.cpp +108 -0
- data/ext/geographiclib/PolygonArea.cpp +204 -0
- data/ext/geographiclib/Rhumb.cpp +383 -0
- data/ext/geographiclib/SphericalEngine.cpp +477 -0
- data/ext/geographiclib/TransverseMercator.cpp +603 -0
- data/ext/geographiclib/TransverseMercatorExact.cpp +464 -0
- data/ext/geographiclib/UTMUPS.cpp +296 -0
- data/ext/geographiclib/Utility.cpp +61 -0
- data/ext/geographiclib/extconf.rb +3 -0
- data/ext/geographiclib/geographiclib.cpp +62 -0
- data/lib/geographiclib.rb +20 -0
- 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 − \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 (−90°,
|
58
|
+
* 90°].
|
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
|
+
* (−90°, 90°] for \e northp = true and in the range
|
76
|
+
* [−90°, 90°) 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 [−180°, 180°).
|
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 [−90°, 90°].
|
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 [−90°, 90°].
|
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 [−180°, 180°).
|
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 − \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 [−90°, 90°]. The value of
|
261
|
+
* \e lon2 returned is in the range [−180°, 180°).
|
262
|
+
*
|
263
|
+
* If point 1 is a pole, the cosine of its latitude is taken to be
|
264
|
+
* 1/ε<sup>2</sup> (where ε 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 [−180°, 180°).
|
307
|
+
* .
|
308
|
+
* With the Rhumb::LONG_UNROLL bit set, the quantity \e lon2 −
|
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 [−90°,
|
329
|
+
* 90°]. The value of \e azi12 returned is in the range
|
330
|
+
* [−180°, 180°).
|
331
|
+
*
|
332
|
+
* If either point is a pole, the cosine of its latitude is taken to be
|
333
|
+
* 1/ε<sup>2</sup> (where ε 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 [−90°, 90°].
|
385
|
+
*
|
386
|
+
* If point 1 is a pole, the cosine of its latitude is taken to be
|
387
|
+
* 1/ε<sup>2</sup> (where ε 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 [−180°,
|
505
|
+
* 180°).
|
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 [−180°, 180°).
|
543
|
+
* .
|
544
|
+
* With the RhumbLine::LONG_UNROLL bit set, the quantity \e lon2 − \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
|