geographiclib 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|