Accumulator.hpp   Accumulator.hpp 
skipping to change at line 47 skipping to change at line 47
* \include example-Accumulator.cpp * \include example-Accumulator.cpp
**********************************************************************/ **********************************************************************/
template<typename T = Math::real> template<typename T = Math::real>
class GEOGRAPHICLIB_EXPORT Accumulator { class GEOGRAPHICLIB_EXPORT Accumulator {
private: private:
// _s + _t accumulators for the sum. // _s + _t accumulators for the sum.
T _s, _t; T _s, _t;
// Same as Math::sum, but requires abs(u) >= abs(v). This isn't curren tly // Same as Math::sum, but requires abs(u) >= abs(v). This isn't curren tly
// used. // used.
static inline T fastsum(T u, T v, T& t) { static inline T fastsum(T u, T v, T& t) {
volatile T s = u + v; GEOGRAPHICLIB_VOLATILE T s = u + v;
volatile T vp = s - u; GEOGRAPHICLIB_VOLATILE T vp = s - u;
t = v - vp; t = v - vp;
return s; return s;
} }
void Add(T y) { void Add(T y) {
// Here's Shewchuk's solution... // Here's Shewchuk's solution...
T u; // hold exact sum as [s, t, u] T u; // hold exact sum as [s, t, u]
y = Math::sum(y, _t, u); // Accumulate starting at least significan t end y = Math::sum(y, _t, u); // Accumulate starting at least significan t end
_s = Math::sum(y, _s, _t); _s = Math::sum(y, _s, _t);
// Start is _s, _t decreasing and non-adjacent. Sum is now (s + t + u) // Start is _s, _t decreasing and non-adjacent. Sum is now (s + t + u)
// exactly with s, t, u non-adjacent and in decreasing order (except for // exactly with s, t, u non-adjacent and in decreasing order (except for
skipping to change at line 102 skipping to change at line 102
return a._s; return a._s;
} }
public: public:
/** /**
* Construct from a \e T. This is not declared explicit, so that you c an * Construct from a \e T. This is not declared explicit, so that you c an
* write <code>Accumulator<double> a = 5;</code>. * write <code>Accumulator<double> a = 5;</code>.
* *
* @param[in] y set \e sum = \e y. * @param[in] y set \e sum = \e y.
********************************************************************** / ********************************************************************** /
Accumulator(T y = T(0)) : _s(y), _t(0) { Accumulator(T y = T(0)) : _s(y), _t(0) {
STATIC_ASSERT(!std::numeric_limits<T>::is_integer, GEOGRAPHICLIB_STATIC_ASSERT(!std::numeric_limits<T>::is_integer,
"Accumulator type is not floating point"); "Accumulator type is not floating point")
;
} }
/** /**
* Set the accumulator to a number. * Set the accumulator to a number.
* *
* @param[in] y set \e sum = \e y. * @param[in] y set \e sum = \e y.
********************************************************************** / ********************************************************************** /
Accumulator& operator=(T y) { _s = y; _t = 0; return *this; } Accumulator& operator=(T y) { _s = y; _t = 0; return *this; }
/** /**
* Return the value held in the accumulator. * Return the value held in the accumulator.
* *
 End of changes. 2 change blocks. 
4 lines changed or deleted 5 lines changed or added


 AlbersEqualArea.hpp   AlbersEqualArea.hpp 
skipping to change at line 63 skipping to change at line 63
* Example of use: * Example of use:
* \include example-AlbersEqualArea.cpp * \include example-AlbersEqualArea.cpp
* *
* <a href="ConicProj.1.html">ConicProj</a> is a command-line utility * <a href="ConicProj.1.html">ConicProj</a> is a command-line utility
* providing access to the functionality of LambertConformalConic and * providing access to the functionality of LambertConformalConic and
* AlbersEqualArea. * AlbersEqualArea.
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT AlbersEqualArea { class GEOGRAPHICLIB_EXPORT AlbersEqualArea {
private: private:
typedef Math::real real; typedef Math::real real;
real eps_, epsx_, epsx2_, tol_, tol0_;
real _a, _f, _fm, _e2, _e, _e2m, _qZ, _qx; real _a, _f, _fm, _e2, _e, _e2m, _qZ, _qx;
real _sign, _lat0, _k0; real _sign, _lat0, _k0;
real _n0, _m02, _nrho0, _k2, _txi0, _scxi0, _sxi0; real _n0, _m02, _nrho0, _k2, _txi0, _scxi0, _sxi0;
static const real eps_;
static const real epsx_;
static const real epsx2_;
static const real tol_;
static const real tol0_;
static const real ahypover_;
static const int numit_ = 5; // Newton iterations in Reverse static const int numit_ = 5; // Newton iterations in Reverse
static const int numit0_ = 20; // Newton iterations in Init static const int numit0_ = 20; // Newton iterations in Init
static inline real hyp(real x) { return Math::hypot(real(1), x); } static inline real hyp(real x) { return Math::hypot(real(1), x); }
// atanh( e * x)/ e if f > 0 // atanh( e * x)/ e if f > 0
// atan (sqrt(-e2) * x)/sqrt(-e2) if f < 0 // atan (sqrt(-e2) * x)/sqrt(-e2) if f < 0
// x if f = 0 // x if f = 0
inline real atanhee(real x) const { inline real atanhee(real x) const {
using std::atan2; using std::abs;
return _f > 0 ? Math::atanh(_e * x)/_e : return _f > 0 ? Math::atanh(_e * x)/_e :
// We only invoke atanhee in txif for positive latitude. Then x is // We only invoke atanhee in txif for positive latitude. Then x is
// only negative for very prolate ellipsoids (_b/_a >= sqrt(2)) and we // only negative for very prolate ellipsoids (_b/_a >= sqrt(2)) and we
// still need to return a positive result in this case; hence the n eed // still need to return a positive result in this case; hence the n eed
// for the call to atan2. // for the call to atan2.
(_f < 0 ? (std::atan2(_e * std::abs(x), x < 0 ? -1 : 1)/_e) : x); (_f < 0 ? (atan2(_e * abs(x), x < 0 ? -1 : 1)/_e) : x);
} }
// return atanh(sqrt(x))/sqrt(x) - 1, accurate for small x // return atanh(sqrt(x))/sqrt(x) - 1, accurate for small x
static real atanhxm1(real x); static real atanhxm1(real x);
// Divided differences // Divided differences
// Definition: Df(x,y) = (f(x)-f(y))/(x-y) // Definition: Df(x,y) = (f(x)-f(y))/(x-y)
// See: // See:
// W. M. Kahan and R. J. Fateman, // W. M. Kahan and R. J. Fateman,
// Symbolic computation of divided differences, // Symbolic computation of divided differences,
// SIGSAM Bull. 33(3), 7-28 (1999) // SIGSAM Bull. 33(3), 7-28 (1999)
skipping to change at line 115 skipping to change at line 111
// sn(x) = x/sqrt(1+x^2): Dsn(x,y) = (x+y)/((sn(x)+sn(y))*(1+x^2)*(1+y^ 2)) // sn(x) = x/sqrt(1+x^2): Dsn(x,y) = (x+y)/((sn(x)+sn(y))*(1+x^2)*(1+y^ 2))
static inline real Dsn(real x, real y, real sx, real sy) { static inline real Dsn(real x, real y, real sx, real sy) {
// sx = x/hyp(x) // sx = x/hyp(x)
real t = x * y; real t = x * y;
return t > 0 ? (x + y) * Math::sq( (sx * sy)/t ) / (sx + sy) : return t > 0 ? (x + y) * Math::sq( (sx * sy)/t ) / (sx + sy) :
(x - y != 0 ? (sx - sy) / (x - y) : 1); (x - y != 0 ? (sx - sy) / (x - y) : 1);
} }
// Datanhee(x,y) = atanhee((x-y)/(1-e^2*x*y))/(x-y) // Datanhee(x,y) = atanhee((x-y)/(1-e^2*x*y))/(x-y)
inline real Datanhee(real x, real y) const { inline real Datanhee(real x, real y) const {
real t = x - y, d = 1 - _e2 * x * y; real t = x - y, d = 1 - _e2 * x * y;
return t != 0 ? atanhee(t / d) / t : 1 / d; return t ? atanhee(t / d) / t : 1 / d;
} }
// DDatanhee(x,y) = (Datanhee(1,y) - Datanhee(1,x))/(y-x) // DDatanhee(x,y) = (Datanhee(1,y) - Datanhee(1,x))/(y-x)
real DDatanhee(real x, real y) const; real DDatanhee(real x, real y) const;
void Init(real sphi1, real cphi1, real sphi2, real cphi2, real k1); void Init(real sphi1, real cphi1, real sphi2, real cphi2, real k1);
real txif(real tphi) const; real txif(real tphi) const;
real tphif(real txi) const; real tphif(real txi) const;
friend class Ellipsoid; // For access to txif, tphif, etc. friend class Ellipsoid; // For access to txif, tphif, etc.
public: public:
/** /**
* Constructor with a single standard parallel. * Constructor with a single standard parallel.
* *
* @param[in] a equatorial radius of ellipsoid (meters). * @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f.
* @param[in] stdlat standard parallel (degrees), the circle of tangenc y. * @param[in] stdlat standard parallel (degrees), the circle of tangenc y.
* @param[in] k0 azimuthal scale on the standard parallel. * @param[in] k0 azimuthal scale on the standard parallel.
* @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k0 i s * @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k0 is
* not positive. * not positive.
* @exception GeographicErr if \e stdlat is not in [&minus;90&deg;, * @exception GeographicErr if \e stdlat is not in [&minus;90&deg;,
* 90&deg;]. * 90&deg;].
********************************************************************** / ********************************************************************** /
AlbersEqualArea(real a, real f, real stdlat, real k0); AlbersEqualArea(real a, real f, real stdlat, real k0);
/** /**
* Constructor with two standard parallels. * Constructor with two standard parallels.
* *
* @param[in] a equatorial radius of ellipsoid (meters). * @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f.
* @param[in] stdlat1 first standard parallel (degrees). * @param[in] stdlat1 first standard parallel (degrees).
* @param[in] stdlat2 second standard parallel (degrees). * @param[in] stdlat2 second standard parallel (degrees).
* @param[in] k1 azimuthal scale on the standard parallels. * @param[in] k1 azimuthal scale on the standard parallels.
* @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k1 i s * @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k1 is
* not positive. * not positive.
* @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
* [&minus;90&deg;, 90&deg;], or if \e stdlat1 and \e stdlat2 are * [&minus;90&deg;, 90&deg;], or if \e stdlat1 and \e stdlat2 are
* opposite poles. * opposite poles.
********************************************************************** / ********************************************************************** /
AlbersEqualArea(real a, real f, real stdlat1, real stdlat2, real k1); AlbersEqualArea(real a, real f, real stdlat1, real stdlat2, real k1);
/** /**
* Constructor with two standard parallels specified by sines and cosin es. * Constructor with two standard parallels specified by sines and cosin es.
* *
* @param[in] a equatorial radius of ellipsoid (meters). * @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f.
* @param[in] sinlat1 sine of first standard parallel. * @param[in] sinlat1 sine of first standard parallel.
* @param[in] coslat1 cosine of first standard parallel. * @param[in] coslat1 cosine of first standard parallel.
* @param[in] sinlat2 sine of second standard parallel. * @param[in] sinlat2 sine of second standard parallel.
* @param[in] coslat2 cosine of second standard parallel. * @param[in] coslat2 cosine of second standard parallel.
* @param[in] k1 azimuthal scale on the standard parallels. * @param[in] k1 azimuthal scale on the standard parallels.
* @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k1 i s * @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k1 is
* not positive. * not positive.
* @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
* [&minus;90&deg;, 90&deg;], or if \e stdlat1 and \e stdlat2 are * [&minus;90&deg;, 90&deg;], or if \e stdlat1 and \e stdlat2 are
* opposite poles. * opposite poles.
* *
* This allows parallels close to the poles to be specified accurately. * This allows parallels close to the poles to be specified accurately.
* This routine computes the latitude of origin and the azimuthal scale at * This routine computes the latitude of origin and the azimuthal scale at
* this latitude. If \e dlat = abs(\e lat2 &minus; \e lat1) &le; 160&d eg;, * this latitude. If \e dlat = abs(\e lat2 &minus; \e lat1) &le; 160&d eg;,
* then the error in the latitude of origin is less than 4.5 &times; * then the error in the latitude of origin is less than 4.5 &times;
* 10<sup>&minus;14</sup>d;. * 10<sup>&minus;14</sup>d;.
skipping to change at line 311 skipping to change at line 307
* on the latitude of origin. * on the latitude of origin.
********************************************************************** / ********************************************************************** /
Math::real CentralScale() const { return _k0; } Math::real CentralScale() const { return _k0; }
///@} ///@}
/** /**
* A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e * A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e
* stdlat = 0, and \e k0 = 1. This degenerates to the cylindrical equa l * stdlat = 0, and \e k0 = 1. This degenerates to the cylindrical equa l
* area projection. * area projection.
********************************************************************** / ********************************************************************** /
static const AlbersEqualArea CylindricalEqualArea; static const AlbersEqualArea& CylindricalEqualArea();
/** /**
* A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e * A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e
* stdlat = 90&deg;, and \e k0 = 1. This degenerates to the * stdlat = 90&deg;, and \e k0 = 1. This degenerates to the
* Lambert azimuthal equal area projection. * Lambert azimuthal equal area projection.
********************************************************************** / ********************************************************************** /
static const AlbersEqualArea AzimuthalEqualAreaNorth; static const AlbersEqualArea& AzimuthalEqualAreaNorth();
/** /**
* A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e * A global instantiation of AlbersEqualArea with the WGS84 ellipsoid, \e
* stdlat = &minus;90&deg;, and \e k0 = 1. This degenerates to the * stdlat = &minus;90&deg;, and \e k0 = 1. This degenerates to the
* Lambert azimuthal equal area projection. * Lambert azimuthal equal area projection.
********************************************************************** / ********************************************************************** /
static const AlbersEqualArea AzimuthalEqualAreaSouth; static const AlbersEqualArea& AzimuthalEqualAreaSouth();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_ALBERSEQUALAREA_HPP #endif // GEOGRAPHICLIB_ALBERSEQUALAREA_HPP
 End of changes. 14 change blocks. 
23 lines changed or deleted 16 lines changed or added


 AzimuthalEquidistant.hpp   AzimuthalEquidistant.hpp 
skipping to change at line 32 skipping to change at line 32
* ellipsoid. For a point in projected space (\e x, \e y), the geodesic * ellipsoid. For a point in projected space (\e x, \e y), the geodesic
* distance from the center position is hypot(\e x, \e y) and the azimuth of * distance from the center position is hypot(\e x, \e y) and the azimuth of
* the geodesic from the center point is atan2(\e x, \e y). The Forward and * the geodesic from the center point is atan2(\e x, \e y). The Forward and
* Reverse methods also return the azimuth \e azi of the geodesic at (\e x, * Reverse methods also return the azimuth \e azi of the geodesic at (\e x,
* \e y) and reciprocal scale \e rk in the azimuthal direction which, * \e y) and reciprocal scale \e rk in the azimuthal direction which,
* together with the basic properties of the projection, serve to specify * together with the basic properties of the projection, serve to specify
* completely the local affine transformation between geographic and * completely the local affine transformation between geographic and
* projected coordinates. * projected coordinates.
* *
* The conversions all take place using a Geodesic object (by default * The conversions all take place using a Geodesic object (by default
* Geodesic::WGS84). For more information on geodesics see \ref geodesic . * Geodesic::WGS84()). For more information on geodesics see \ref geodes ic.
* *
* Example of use: * Example of use:
* \include example-AzimuthalEquidistant.cpp * \include example-AzimuthalEquidistant.cpp
* *
* <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utili ty * <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utili ty
* providing access to the functionality of AzimuthalEquidistant, Gnomoni c, * providing access to the functionality of AzimuthalEquidistant, Gnomoni c,
* and CassiniSoldner. * and CassiniSoldner.
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT AzimuthalEquidistant { class GEOGRAPHICLIB_EXPORT AzimuthalEquidistant {
private: private:
typedef Math::real real; typedef Math::real real;
real eps_;
Geodesic _earth; Geodesic _earth;
static const real eps_;
public: public:
/** /**
* Constructor for AzimuthalEquidistant. * Constructor for AzimuthalEquidistant.
* *
* @param[in] earth the Geodesic object to use for geodesic calculation s. * @param[in] earth the Geodesic object to use for geodesic calculation s.
* By default this uses the WGS84 ellipsoid. * By default this uses the WGS84 ellipsoid.
********************************************************************** / ********************************************************************** /
explicit AzimuthalEquidistant(const Geodesic& earth = Geodesic::WGS84) explicit AzimuthalEquidistant(const Geodesic& earth = Geodesic::WGS84()
: _earth(earth) {} );
/** /**
* Forward projection, from geographic to azimuthal equidistant. * Forward projection, from geographic to azimuthal equidistant.
* *
* @param[in] lat0 latitude of center point of projection (degrees). * @param[in] lat0 latitude of center point of projection (degrees).
* @param[in] lon0 longitude of center point of projection (degrees). * @param[in] lon0 longitude of center point of projection (degrees).
* @param[in] lat latitude of point (degrees). * @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees). * @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters). * @param[out] x easting of point (meters).
* @param[out] y northing of point (meters). * @param[out] y northing of point (meters).
 End of changes. 4 change blocks. 
4 lines changed or deleted 4 lines changed or added


 CassiniSoldner.hpp   CassiniSoldner.hpp 
skipping to change at line 52 skipping to change at line 52
* path. * path.
* *
* Because of the properties of geodesics, the (\e x, \e y) grid is * Because of the properties of geodesics, the (\e x, \e y) grid is
* orthogonal. The scale in the easting direction is unity. The scale, \e * orthogonal. The scale in the easting direction is unity. The scale, \e
* k, in the northing direction is unity on the central meridian and * k, in the northing direction is unity on the central meridian and
* increases away from the central meridian. The projection routines ret urn * increases away from the central meridian. The projection routines ret urn
* \e azi, the true bearing of the easting direction, and \e rk = 1/\e k, the * \e azi, the true bearing of the easting direction, and \e rk = 1/\e k, the
* reciprocal of the scale in the northing direction. * reciprocal of the scale in the northing direction.
* *
* The conversions all take place using a Geodesic object (by default * The conversions all take place using a Geodesic object (by default
* Geodesic::WGS84). For more information on geodesics see \ref geodesic . * Geodesic::WGS84()). For more information on geodesics see \ref geodes ic.
* The determination of (\e lat1, \e lon1) in the forward projection is b y * The determination of (\e lat1, \e lon1) in the forward projection is b y
* solving the inverse geodesic problem for (\e lat, \e lon) and its twin * solving the inverse geodesic problem for (\e lat, \e lon) and its twin
* obtained by reflection in the meridional plane. The scale is found by * obtained by reflection in the meridional plane. The scale is found by
* determining where two neighboring geodesics intersecting the central * determining where two neighboring geodesics intersecting the central
* meridian at \e lat1 and \e lat1 + \e dlat1 intersect and taking the ra tio * meridian at \e lat1 and \e lat1 + \e dlat1 intersect and taking the ra tio
* of the reduced lengths for the two geodesics between that point and, * of the reduced lengths for the two geodesics between that point and,
* respectively, (\e lat1, \e lon1) and (\e lat, \e lon). * respectively, (\e lat1, \e lon1) and (\e lat, \e lon).
* *
* Example of use: * Example of use:
* \include example-CassiniSoldner.cpp * \include example-CassiniSoldner.cpp
* *
* <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utili ty * <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utili ty
* providing access to the functionality of AzimuthalEquidistant, Gnomoni c, * providing access to the functionality of AzimuthalEquidistant, Gnomoni c,
* and CassiniSoldner. * and CassiniSoldner.
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT CassiniSoldner { class GEOGRAPHICLIB_EXPORT CassiniSoldner {
private: private:
typedef Math::real real; typedef Math::real real;
real eps1_, tiny_;
Geodesic _earth; Geodesic _earth;
GeodesicLine _meridian; GeodesicLine _meridian;
real _sbet0, _cbet0; real _sbet0, _cbet0;
static const real eps1_;
static const real tiny_;
static const unsigned maxit_ = 10; static const unsigned maxit_ = 10;
// The following private helper functions are copied from Geodesic. // The following private helper functions are copied from Geodesic.
static inline real AngRound(real x) { static inline real AngRound(real x) {
// The makes the smallest gap in x = 1/16 - nextafter(1/16, 0) = 1/2^ 57 // The makes the smallest gap in x = 1/16 - nextafter(1/16, 0) = 1/2^ 57
// for reals = 0.7 pm on the earth if x is an angle in degrees. (Thi s // for reals = 0.7 pm on the earth if x is an angle in degrees. (Thi s
// is about 1000 times more resolution than we get with angles around 90 // is about 1000 times more resolution than we get with angles around 90
// degrees.) We use this to avoid having to deal with near singular // degrees.) We use this to avoid having to deal with near singular
// cases when x is non-zero but tiny (e.g., 1.0e-200). // cases when x is non-zero but tiny (e.g., 1.0e-200).
using std::abs;
const real z = 1/real(16); const real z = 1/real(16);
volatile real y = std::abs(x); GEOGRAPHICLIB_VOLATILE real y = abs(x);
// The compiler mustn't "simplify" z - (z - y) to y // The compiler mustn't "simplify" z - (z - y) to y
y = y < z ? z - (z - y) : y; y = y < z ? z - (z - y) : y;
return x < 0 ? -y : y; return x < 0 ? -y : y;
} }
static inline void SinCosNorm(real& sinx, real& cosx) { static inline void SinCosNorm(real& sinx, real& cosx) {
real r = Math::hypot(sinx, cosx); real r = Math::hypot(sinx, cosx);
sinx /= r; sinx /= r;
cosx /= r; cosx /= r;
} }
public: public:
/** /**
* Constructor for CassiniSoldner. * Constructor for CassiniSoldner.
* *
* @param[in] earth the Geodesic object to use for geodesic calculation s. * @param[in] earth the Geodesic object to use for geodesic calculation s.
* By default this uses the WGS84 ellipsoid. * By default this uses the WGS84 ellipsoid.
* *
* This constructor makes an "uninitialized" object. Call Reset to set the * This constructor makes an "uninitialized" object. Call Reset to set the
* central latitude and longitude, prior to calling Forward and Reverse . * central latitude and longitude, prior to calling Forward and Reverse .
********************************************************************** / ********************************************************************** /
explicit CassiniSoldner(const Geodesic& earth = Geodesic::WGS84) explicit CassiniSoldner(const Geodesic& earth = Geodesic::WGS84());
: _earth(earth) {}
/** /**
* Constructor for CassiniSoldner specifying a center point. * Constructor for CassiniSoldner specifying a center point.
* *
* @param[in] lat0 latitude of center point of projection (degrees). * @param[in] lat0 latitude of center point of projection (degrees).
* @param[in] lon0 longitude of center point of projection (degrees). * @param[in] lon0 longitude of center point of projection (degrees).
* @param[in] earth the Geodesic object to use for geodesic calculation s. * @param[in] earth the Geodesic object to use for geodesic calculation s.
* By default this uses the WGS84 ellipsoid. * By default this uses the WGS84 ellipsoid.
* *
* \e lat0 should be in the range [&minus;90&deg;, 90&deg;] and \e * \e lat0 should be in the range [&minus;90&deg;, 90&deg;] and \e
* lon0 should be in the range [&minus;540&deg;, 540&deg;). * lon0 should be in the range [&minus;540&deg;, 540&deg;).
********************************************************************** / ********************************************************************** /
CassiniSoldner(real lat0, real lon0, CassiniSoldner(real lat0, real lon0,
const Geodesic& earth = Geodesic::WGS84) const Geodesic& earth = Geodesic::WGS84());
: _earth(earth) {
Reset(lat0, lon0);
}
/** /**
* Set the central point of the projection * Set the central point of the projection
* *
* @param[in] lat0 latitude of center point of projection (degrees). * @param[in] lat0 latitude of center point of projection (degrees).
* @param[in] lon0 longitude of center point of projection (degrees). * @param[in] lon0 longitude of center point of projection (degrees).
* *
* \e lat0 should be in the range [&minus;90&deg;, 90&deg;] and \e * \e lat0 should be in the range [&minus;90&deg;, 90&deg;] and \e
* lon0 should be in the range [&minus;540&deg;, 540&deg;). * lon0 should be in the range [&minus;540&deg;, 540&deg;).
********************************************************************** / ********************************************************************** /
 End of changes. 7 change blocks. 
10 lines changed or deleted 6 lines changed or added


 CircularEngine.hpp   CircularEngine.hpp 
skipping to change at line 70 skipping to change at line 70
bool _gradp; bool _gradp;
unsigned _norm; unsigned _norm;
real _a, _r, _u, _t; real _a, _r, _u, _t;
std::vector<real> _wc, _ws, _wrc, _wrs, _wtc, _wts; std::vector<real> _wc, _ws, _wrc, _wrs, _wtc, _wts;
real _q, _uq, _uq2; real _q, _uq, _uq2;
Math::real Value(bool gradp, real cl, real sl, Math::real Value(bool gradp, real cl, real sl,
real& gradx, real& grady, real& gradz) const; real& gradx, real& grady, real& gradz) const;
static inline void cossin(real x, real& cosx, real& sinx) { static inline void cossin(real x, real& cosx, real& sinx) {
using std::abs; using std::cos; using std::sin;
x = x >= 180 ? x - 360 : (x < -180 ? x + 360 : x); x = x >= 180 ? x - 360 : (x < -180 ? x + 360 : x);
real xi = x * Math::degree<real>(); real xi = x * Math::degree();
cosx = std::abs(x) == 90 ? 0 : cos(xi); cosx = abs(x) == 90 ? 0 : cos(xi);
sinx = x == -180 ? 0 : sin(xi); sinx = x == -180 ? 0 : sin(xi);
} }
friend class SphericalEngine; friend class SphericalEngine;
friend class GravityCircle; // Access to cossin friend class GravityCircle; // Access to cossin
friend class MagneticCircle; // Access to cossin friend class MagneticCircle; // Access to cossin
CircularEngine(int M, bool gradp, unsigned norm, CircularEngine(int M, bool gradp, unsigned norm,
real a, real r, real u, real t) real a, real r, real u, real t)
: _M(M) : _M(M)
, _gradp(gradp) , _gradp(gradp)
, _norm(norm) , _norm(norm)
 End of changes. 2 change blocks. 
3 lines changed or deleted 4 lines changed or added


 Config.h   Config.h 
#define GEOGRAPHICLIB_VERSION_MAJOR 1 #define GEOGRAPHICLIB_VERSION_MAJOR 1
#define GEOGRAPHICLIB_VERSION_MINOR 36 #define GEOGRAPHICLIB_VERSION_MINOR 37
#define GEOGRAPHICLIB_VERSION_PATCH 0 #define GEOGRAPHICLIB_VERSION_PATCH 0
#define HAVE_LONG_DOUBLE 1 #define GEOGRAPHICLIB_HAVE_LONG_DOUBLE 1
#define GEOGRAPHICLIB_VERSION_STRING "1.36" #define GEOGRAPHICLIB_VERSION_STRING "1.37"
/* # undef WORDS_BIGENDIAN */ /* # undef GEOGRAPHICLIB_WORDS_BIGENDIAN */
 End of changes. 2 change blocks. 
1 lines changed or deleted 1 lines changed or added


 Constants.hpp   Constants.hpp 
skipping to change at line 16 skipping to change at line 16
* under the MIT/X11 License. For more information, see * under the MIT/X11 License. For more information, see
* http://geographiclib.sourceforge.net/ * http://geographiclib.sourceforge.net/
**********************************************************************/ **********************************************************************/
#if !defined(GEOGRAPHICLIB_CONSTANTS_HPP) #if !defined(GEOGRAPHICLIB_CONSTANTS_HPP)
#define GEOGRAPHICLIB_CONSTANTS_HPP 1 #define GEOGRAPHICLIB_CONSTANTS_HPP 1
#include <GeographicLib/Config.h> #include <GeographicLib/Config.h>
/** /**
* @relates GeographicLib::Constants
* Pack the version components into a single integer.
**********************************************************************/
#define GEOGRAPHICLIB_VERSION_NUM(a,b,c) ((((a) * 10000 + (b)) * 100) + (c)
)
/**
* @relates GeographicLib::Constants
* The version of GeographicLib as a single integer, packed as MMmmmmpp whe
re
* MM is the major version, mmmm is the minor version, and pp is the patch
* level.
**********************************************************************/
#define GEOGRAPHICLIB_VERSION \
GEOGRAPHICLIB_VERSION_NUM(GEOGRAPHICLIB_VERSION_MAJOR, \
GEOGRAPHICLIB_VERSION_MINOR, \
GEOGRAPHICLIB_VERSION_PATCH)
/**
* @relates GeographicLib::Constants
* A compile-time assert. Use C++11 static_assert, if available. * A compile-time assert. Use C++11 static_assert, if available.
**********************************************************************/ **********************************************************************/
#if !defined(STATIC_ASSERT) #if !defined(GEOGRAPHICLIB_STATIC_ASSERT)
# if __cplusplus >= 201103 # if __cplusplus >= 201103
# define STATIC_ASSERT static_assert # define GEOGRAPHICLIB_STATIC_ASSERT static_assert
# elif defined(__GXX_EXPERIMENTAL_CXX0X__) # elif defined(__GXX_EXPERIMENTAL_CXX0X__)
# define STATIC_ASSERT static_assert # define GEOGRAPHICLIB_STATIC_ASSERT static_assert
# elif defined(_MSC_VER) && _MSC_VER >= 1600 # elif defined(_MSC_VER) && _MSC_VER >= 1600
// For reference, here is a table of Visual Studio and _MSC_VER // For reference, here is a table of Visual Studio and _MSC_VER
// correspondences: // correspondences:
// //
// _MSC_VER Visual Studio // _MSC_VER Visual Studio
// 1300 vc7 // 1300 vc7
// 1311 vc7.1 (2003) // 1311 vc7.1 (2003)
// 1400 vc8 (2005) // 1400 vc8 (2005)
// 1500 vc9 (2008) // 1500 vc9 (2008)
// 1600 vc10 (2010) // 1600 vc10 (2010)
// 1700 vc11 (2012) // 1700 vc11 (2012)
// 1800 vc12 (2013) // 1800 vc12 (2013)
# define STATIC_ASSERT static_assert # define GEOGRAPHICLIB_STATIC_ASSERT static_assert
# else # else
# define STATIC_ASSERT(cond,reason) \ # define GEOGRAPHICLIB_STATIC_ASSERT(cond,reason) \
{ enum{ STATIC_ASSERT_ENUM = 1/int(cond) }; } { enum{ GEOGRAPHICLIB_STATIC_ASSERT_ENUM = 1/int(cond) }; }
# endif # endif
#endif #endif
#if defined(_MSC_VER) && defined(GEOGRAPHICLIB_SHARED_LIB) && \ #if defined(_MSC_VER) && defined(GEOGRAPHICLIB_SHARED_LIB) && \
GEOGRAPHICLIB_SHARED_LIB GEOGRAPHICLIB_SHARED_LIB
# if GEOGRAPHICLIB_SHARED_LIB > 1 # if GEOGRAPHICLIB_SHARED_LIB > 1
# error GEOGRAPHICLIB_SHARED_LIB must be 0 or 1 # error GEOGRAPHICLIB_SHARED_LIB must be 0 or 1
# elif defined(GeographicLib_EXPORTS) # elif defined(GeographicLib_EXPORTS)
# define GEOGRAPHICLIB_EXPORT __declspec(dllexport) # define GEOGRAPHICLIB_EXPORT __declspec(dllexport)
# else # else
skipping to change at line 86 skipping to change at line 104
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT Constants { class GEOGRAPHICLIB_EXPORT Constants {
private: private:
typedef Math::real real; typedef Math::real real;
Constants(); // Disable constructor Constants(); // Disable constructor
public: public:
/** /**
* A synonym for Math::degree<real>(). * A synonym for Math::degree<real>().
********************************************************************** / ********************************************************************** /
static inline Math::real degree() { return Math::degree<real>(); } static inline Math::real degree() { return Math::degree(); }
/** /**
* @return the number of radians in an arcminute. * @return the number of radians in an arcminute.
********************************************************************** / ********************************************************************** /
static inline Math::real arcminute() static inline Math::real arcminute()
{ return Math::degree<real>() / 60; } { return Math::degree() / 60; }
/** /**
* @return the number of radians in an arcsecond. * @return the number of radians in an arcsecond.
********************************************************************** / ********************************************************************** /
static inline Math::real arcsecond() static inline Math::real arcsecond()
{ return Math::degree<real>() / 3600; } { return Math::degree() / 3600; }
/** \name Ellipsoid parameters /** \name Ellipsoid parameters
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the equatorial radius of WGS84 ellipsoid (6378137 m). * @return the equatorial radius of WGS84 ellipsoid (6378137 m).
********************************************************************** / ********************************************************************** /
template<typename T> static inline T WGS84_a() template<typename T> static inline T WGS84_a()
{ return T(6378137) * meter<T>(); } { return 6378137 * meter<T>(); }
/** /**
* A synonym for WGS84_a<real>(). * A synonym for WGS84_a<real>().
********************************************************************** / ********************************************************************** /
static inline Math::real WGS84_a() { return WGS84_a<real>(); } static inline Math::real WGS84_a() { return WGS84_a<real>(); }
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the flattening of WGS84 ellipsoid (1/298.257223563). * @return the flattening of WGS84 ellipsoid (1/298.257223563).
********************************************************************** / ********************************************************************** /
template<typename T> static inline T WGS84_f() template<typename T> static inline T WGS84_f()
{ return T(1) / ( T(298) + T(257223563) / T(1000000000) ); } { return 1 / ( T(298257223563LL) / 1000000000 ); }
/** /**
* A synonym for WGS84_f<real>(). * A synonym for WGS84_f<real>().
********************************************************************** / ********************************************************************** /
static inline Math::real WGS84_f() { return WGS84_f<real>(); } static inline Math::real WGS84_f() { return WGS84_f<real>(); }
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the gravitational constant of the WGS84 ellipsoid, \e GM, in * @return the gravitational constant of the WGS84 ellipsoid, \e GM, in
* m<sup>3</sup> s<sup>&minus;2</sup>. * m<sup>3</sup> s<sup>&minus;2</sup>.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T WGS84_GM() template<typename T> static inline T WGS84_GM()
{ return T(3986004) * T(100000000) + T(41800000); } { return T(3986004) * 100000000 + 41800000; }
/**
* A synonym for WGS84_GM<real>().
**********************************************************************
/
static inline Math::real WGS84_GM() { return WGS84_GM<real>(); }
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the angular velocity of the WGS84 ellipsoid, &omega;, in rad * @return the angular velocity of the WGS84 ellipsoid, &omega;, in rad
* s<sup>&minus;1</sup>. * s<sup>&minus;1</sup>.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T WGS84_omega() template<typename T> static inline T WGS84_omega()
{ return T(7292115) / (T(1000000) * T(100000)); } { return 7292115 / (T(1000000) * 100000); }
/**
* A synonym for WGS84_omega<real>().
**********************************************************************
/
static inline Math::real WGS84_omega() { return WGS84_omega<real>(); }
/// \cond SKIP /// \cond SKIP
/** /**
* <b>DEPRECATED</b> * <b>DEPRECATED</b>
* @return the reciprocal flattening of WGS84 ellipsoid. * @return the reciprocal flattening of WGS84 ellipsoid.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T WGS84_r() template<typename T> static inline T WGS84_r()
{ return 1/WGS84_f<T>(); } { return 1/WGS84_f<T>(); }
/** /**
* <b>DEPRECATED</b> * <b>DEPRECATED</b>
* A synonym for WGS84_r<real>(). * A synonym for WGS84_r<real>().
********************************************************************** / ********************************************************************** /
static inline Math::real WGS84_r() { return WGS84_r<real>(); } static inline Math::real WGS84_r() { return WGS84_r<real>(); }
/// \endcond /// \endcond
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the equatorial radius of GRS80 ellipsoid, \e a, in m. * @return the equatorial radius of GRS80 ellipsoid, \e a, in m.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T GRS80_a() template<typename T> static inline T GRS80_a()
{ return T(6378137); } { return 6378137 * meter<T>(); }
/**
* A synonym for GRS80_a<real>().
**********************************************************************
/
static inline Math::real GRS80_a() { return GRS80_a<real>(); }
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the gravitational constant of the GRS80 ellipsoid, \e GM, in * @return the gravitational constant of the GRS80 ellipsoid, \e GM, in
* m<sup>3</sup> s<sup>&minus;2</sup>. * m<sup>3</sup> s<sup>&minus;2</sup>.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T GRS80_GM() template<typename T> static inline T GRS80_GM()
{ return T(3986005) * T(100000000); } { return T(3986005) * 100000000; }
/**
* A synonym for GRS80_GM<real>().
**********************************************************************
/
static inline Math::real GRS80_GM() { return GRS80_GM<real>(); }
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the angular velocity of the GRS80 ellipsoid, &omega;, in rad * @return the angular velocity of the GRS80 ellipsoid, &omega;, in rad
* s<sup>&minus;1</sup>. * s<sup>&minus;1</sup>.
* *
* This is about 2 &pi; 366.25 / (365.25 &times; 24 &times; 3600) rad * This is about 2 &pi; 366.25 / (365.25 &times; 24 &times; 3600) rad
* s<sup>&minus;1</sup>. 365.25 is the number of days in a Julian year and * s<sup>&minus;1</sup>. 365.25 is the number of days in a Julian year and
* 365.35/366.25 converts from solar days to sidereal days. Using the * 365.35/366.25 converts from solar days to sidereal days. Using the
* number of days in a Gregorian year (365.2425) results in a worse * number of days in a Gregorian year (365.2425) results in a worse
* approximation (because the Gregorian year includes the precession of the * approximation (because the Gregorian year includes the precession of the
* earth's axis). * earth's axis).
********************************************************************** / ********************************************************************** /
template<typename T> static inline T GRS80_omega() template<typename T> static inline T GRS80_omega()
{ return T(7292115) / (T(1000000) * T(100000)); } { return 7292115 / (T(1000000) * 100000); }
/**
* A synonym for GRS80_omega<real>().
**********************************************************************
/
static inline Math::real GRS80_omega() { return GRS80_omega<real>(); }
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the dynamical form factor of the GRS80 ellipsoid, * @return the dynamical form factor of the GRS80 ellipsoid,
* <i>J</i><sub>2</sub>. * <i>J</i><sub>2</sub>.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T GRS80_J2() template<typename T> static inline T GRS80_J2()
{ return T(108263) / T(100000000); } { return T(108263) / 100000000; }
/**
* A synonym for GRS80_J2<real>().
**********************************************************************
/
static inline Math::real GRS80_J2() { return GRS80_J2<real>(); }
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the central scale factor for UTM (0.9996). * @return the central scale factor for UTM (0.9996).
********************************************************************** / ********************************************************************** /
template<typename T> static inline T UTM_k0() template<typename T> static inline T UTM_k0()
{return T(9996) / T(10000); } {return T(9996) / 10000; }
/** /**
* A synonym for UTM_k0<real>(). * A synonym for UTM_k0<real>().
********************************************************************** / ********************************************************************** /
static inline Math::real UTM_k0() { return UTM_k0<real>(); } static inline Math::real UTM_k0() { return UTM_k0<real>(); }
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the central scale factor for UPS (0.994). * @return the central scale factor for UPS (0.994).
********************************************************************** / ********************************************************************** /
template<typename T> static inline T UPS_k0() template<typename T> static inline T UPS_k0()
{ return T(994) / T(1000); } { return T(994) / 1000; }
/** /**
* A synonym for UPS_k0<real>(). * A synonym for UPS_k0<real>().
********************************************************************** / ********************************************************************** /
static inline Math::real UPS_k0() { return UPS_k0<real>(); } static inline Math::real UPS_k0() { return UPS_k0<real>(); }
///@} ///@}
/** \name SI units /** \name SI units
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
skipping to change at line 269 skipping to change at line 311
{ return nauticalmile() * nauticalmile(); } { return nauticalmile() * nauticalmile(); }
///@} ///@}
/** \name Anachronistic British units /** \name Anachronistic British units
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* @return the number of meters in an international foot. * @return the number of meters in an international foot.
********************************************************************** / ********************************************************************** /
static inline Math::real foot() static inline Math::real foot()
{ return real(0.0254L) * 12 * meter<real>(); } { return real(254 * 12) / 10000 * meter<real>(); }
/** /**
* @return the number of meters in a yard. * @return the number of meters in a yard.
********************************************************************** / ********************************************************************** /
static inline Math::real yard() { return 3 * foot(); } static inline Math::real yard() { return 3 * foot(); }
/** /**
* @return the number of meters in a fathom. * @return the number of meters in a fathom.
********************************************************************** / ********************************************************************** /
static inline Math::real fathom() { return 2 * yard(); } static inline Math::real fathom() { return 2 * yard(); }
/** /**
* @return the number of meters in a chain. * @return the number of meters in a chain.
skipping to change at line 307 skipping to change at line 349
static inline Math::real square_mile() { return mile() * mile(); } static inline Math::real square_mile() { return mile() * mile(); }
///@} ///@}
/** \name Anachronistic US units /** \name Anachronistic US units
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* @return the number of meters in a US survey foot. * @return the number of meters in a US survey foot.
********************************************************************** / ********************************************************************** /
static inline Math::real surveyfoot() static inline Math::real surveyfoot()
{ return real(1200) / real(3937) * meter<real>(); } { return real(1200) / 3937 * meter<real>(); }
///@} ///@}
}; };
/** /**
* \brief Exception handling for %GeographicLib * \brief Exception handling for %GeographicLib
* *
* A class to handle exceptions. It's derived from std::runtime_error so it * A class to handle exceptions. It's derived from std::runtime_error so it
* can be caught by the usual catch clauses. * can be caught by the usual catch clauses.
* *
* Example of use: * Example of use:
 End of changes. 21 change blocks. 
21 lines changed or deleted 71 lines changed or added


 DMS.hpp   DMS.hpp 
skipping to change at line 189 skipping to change at line 189
static Math::real Decode(const std::string& dms, flag& ind); static Math::real Decode(const std::string& dms, flag& ind);
/** /**
* Convert DMS to an angle. * Convert DMS to an angle.
* *
* @param[in] d degrees. * @param[in] d degrees.
* @param[in] m arc minutes. * @param[in] m arc minutes.
* @param[in] s arc seconds. * @param[in] s arc seconds.
* @return angle (degrees) * @return angle (degrees)
* *
* This does not propagate the sign on \e d to the other components, so * This does not propagate the sign on \e d to the other components,
* -3d20' would need to be represented as - DMS::Decode(3.0, 20.0) or * so -3d20' would need to be represented as - DMS::Decode(3.0, 20.0) o
r
* DMS::Decode(-3.0, -20.0). * DMS::Decode(-3.0, -20.0).
********************************************************************** / ********************************************************************** /
static Math::real Decode(real d, real m = 0, real s = 0) static Math::real Decode(real d, real m = 0, real s = 0)
{ return d + (m + s/real(60))/real(60); } { return d + (m + s / 60) / 60; }
/// \cond SKIP /// \cond SKIP
/** /**
* <b>DEPRECATED</b> (use Utility::num, instead). * <b>DEPRECATED</b> (use Utility::num, instead).
* Convert a string to a real number. * Convert a string to a real number.
* *
* @param[in] str string input. * @param[in] str string input.
* @exception GeographicErr if \e str is malformed. * @exception GeographicErr if \e str is malformed.
* @return decoded number. * @return decoded number.
********************************************************************** / ********************************************************************** /
skipping to change at line 329 skipping to change at line 329
* @return formatted string * @return formatted string
* *
* \e prec indicates the precision relative to 1 degree, e.g., \e prec = 3 * \e prec indicates the precision relative to 1 degree, e.g., \e prec = 3
* gives a result accurate to 0.1' and \e prec = 4 gives a result accur ate * gives a result accurate to 0.1' and \e prec = 4 gives a result accur ate
* to 1&quot;. \e ind is interpreted as in DMS::Encode with the additi onal * to 1&quot;. \e ind is interpreted as in DMS::Encode with the additi onal
* facility that DMS::NUMBER represents \e angle as a number in fixed * facility that DMS::NUMBER represents \e angle as a number in fixed
* format with precision \e prec. * format with precision \e prec.
********************************************************************** / ********************************************************************** /
static std::string Encode(real angle, unsigned prec, flag ind = NONE, static std::string Encode(real angle, unsigned prec, flag ind = NONE,
char dmssep = char(0)) { char dmssep = char(0)) {
return ind == NUMBER ? Utility::str<real>(angle, int(prec)) : return ind == NUMBER ? Utility::str(angle, int(prec)) :
Encode(angle, Encode(angle,
prec < 2 ? DEGREE : (prec < 4 ? MINUTE : SECOND), prec < 2 ? DEGREE : (prec < 4 ? MINUTE : SECOND),
prec < 2 ? prec : (prec < 4 ? prec - 2 : prec - 4), prec < 2 ? prec : (prec < 4 ? prec - 2 : prec - 4),
ind, dmssep); ind, dmssep);
} }
/** /**
* Split angle into degrees and minutes * Split angle into degrees and minutes
* *
* @param[in] ang angle (degrees) * @param[in] ang angle (degrees)
 End of changes. 3 change blocks. 
4 lines changed or deleted 5 lines changed or added


 Ellipsoid.hpp   Ellipsoid.hpp 
skipping to change at line 43 skipping to change at line 43
* should be limited to &minus;3 < \e f < 3/4 (i.e., 1/4 < b/a < 4). * should be limited to &minus;3 < \e f < 3/4 (i.e., 1/4 < b/a < 4).
* *
* Example of use: * Example of use:
* \include example-Ellipsoid.cpp * \include example-Ellipsoid.cpp
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT Ellipsoid { class GEOGRAPHICLIB_EXPORT Ellipsoid {
private: private:
typedef Math::real real; typedef Math::real real;
static const int numit_ = 10; static const int numit_ = 10;
static const real stol_; real stol_;
real _a, _f, _f1, _f12, _e2, _e12, _n, _b; real _a, _f, _f1, _f12, _e2, _e, _e12, _n, _b;
TransverseMercator _tm; TransverseMercator _tm;
EllipticFunction _ell; EllipticFunction _ell;
AlbersEqualArea _au; AlbersEqualArea _au;
static real tand(real x) { static inline real tand(real x) {
using std::abs; using std::tan;
return return
std::abs(x) == real(90) ? (x < 0 ? abs(x) == real(90) ? (x < 0 ?
- TransverseMercator::overflow_ - TransverseMercator::overflow()
: TransverseMercator::overflow_) : : TransverseMercator::overflow()) :
std::tan(x * Math::degree<real>()); tan(x * Math::degree());
} }
static real atand(real x) static inline real atand(real x)
{ return std::atan(x) / Math::degree<real>(); } { using std::atan; return atan(x) / Math::degree(); }
// These are the alpha and beta coefficients in the Krueger series from
// TransverseMercator. Thy are used by RhumbSolve to compute
// (psi2-psi1)/(mu2-mu1).
const Math::real* ConformalToRectifyingCoeffs() const { return _tm._alp
; }
const Math::real* RectifyingToConformalCoeffs() const { return _tm._bet
; }
friend class Rhumb; friend class RhumbLine;
public: public:
/** \name Constructor /** \name Constructor
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* Constructor for a ellipsoid with * Constructor for a ellipsoid with
* *
* @param[in] a equatorial radius (meters). * @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f. * @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
* @exception GeographicErr if \e a or (1 &minus; \e f ) \e a is not
* positive. * positive.
********************************************************************** / ********************************************************************** /
Ellipsoid(real a, real f); Ellipsoid(real a, real f);
///@} ///@}
/** \name %Ellipsoid dimensions. /** \name %Ellipsoid dimensions.
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
skipping to change at line 111 skipping to change at line 118
* with the same area is sqrt(\e A / (4&pi;)). * with the same area is sqrt(\e A / (4&pi;)).
********************************************************************** / ********************************************************************** /
Math::real Area() const; Math::real Area() const;
/** /**
* @return \e V the total volume of the ellipsoid (meters<sup>3</sup>). * @return \e V the total volume of the ellipsoid (meters<sup>3</sup>).
* For a sphere \e V = (4&pi; / 3) <i>a</i><sup>3</sup>. The radius of * For a sphere \e V = (4&pi; / 3) <i>a</i><sup>3</sup>. The radius of
* a sphere with the same volume is cbrt(\e V / (4&pi;/3)). * a sphere with the same volume is cbrt(\e V / (4&pi;/3)).
********************************************************************** / ********************************************************************** /
Math::real Volume() const Math::real Volume() const
{ return (4 * Math::pi<real>()) * Math::sq(_a) * _b / 3; } { return (4 * Math::pi()) * Math::sq(_a) * _b / 3; }
///@} ///@}
/** \name %Ellipsoid shape /** \name %Ellipsoid shape
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* @return \e f = (\e a &minus; \e b) / \e a, the flattening of the * @return \e f = (\e a &minus; \e b) / \e a, the flattening of the
* ellipsoid. This is the value used in the constructor. This is ze ro, * ellipsoid. This is the value used in the constructor. This is ze ro,
* positive, or negative for a sphere, oblate ellipsoid, or prolate * positive, or negative for a sphere, oblate ellipsoid, or prolate
skipping to change at line 313 skipping to change at line 320
/** /**
* @param[in] phi the geographic latitude (degrees). * @param[in] phi the geographic latitude (degrees).
* @return &psi; the isometric latitude (degrees). * @return &psi; the isometric latitude (degrees).
* *
* The isometric latitude gives the mapping of the ellipsoid to a plane * The isometric latitude gives the mapping of the ellipsoid to a plane
* which which is conformal (angles are preserved) and in which the equ ator * which which is conformal (angles are preserved) and in which the equ ator
* of the ellipsoid maps to a straight line of constant scale; this map ping * of the ellipsoid maps to a straight line of constant scale; this map ping
* defines the Mercator projection. For a sphere &psi; = * defines the Mercator projection. For a sphere &psi; =
* sinh<sup>&minus;1</sup> tan &phi;. * sinh<sup>&minus;1</sup> tan &phi;.
* *
* &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the * &phi; must lie in the range [&minus;90&deg;, 90&deg;]; the result is
* result is undefined if this condition does not hold. * undefined if this condition does not hold. The value returned for &
phi;
* = &plusmn;90&deg; is some (positive or negative) large but finite va
lue,
* such that InverseIsometricLatitude returns the original value of &ph
i;.
********************************************************************** / ********************************************************************** /
Math::real IsometricLatitude(real phi) const; Math::real IsometricLatitude(real phi) const;
/** /**
* @param[in] psi the isometric latitude (degrees). * @param[in] psi the isometric latitude (degrees).
* @return &phi; the geographic latitude (degrees). * @return &phi; the geographic latitude (degrees).
* *
* The returned value &phi; lies in [&minus;90&deg;, 90&deg;]. * The returned value &phi; lies in [&minus;90&deg;, 90&deg;]. For a
* sphere &phi; = tan<sup>&minus;1</sup> sinh &psi;.
********************************************************************** / ********************************************************************** /
Math::real InverseIsometricLatitude(real psi) const; Math::real InverseIsometricLatitude(real psi) const;
///@} ///@}
/** \name Other quantities. /** \name Other quantities.
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* @param[in] phi the geographic latitude (degrees). * @param[in] phi the geographic latitude (degrees).
skipping to change at line 463 skipping to change at line 473
/** /**
* @param[in] e2 = <i>e</i><sup>2</sup> = (<i>a</i><sup>2</sup> &minus; * @param[in] e2 = <i>e</i><sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / <i>a</i><sup>2</sup>, the eccentricity * <i>b</i><sup>2</sup>) / <i>a</i><sup>2</sup>, the eccentricity
* squared. * squared.
* @return \e f = (\e a &minus; \e b) / \e a, the flattening. * @return \e f = (\e a &minus; \e b) / \e a, the flattening.
* *
* <i>e</i><sup>2</sup> should lie in (&minus;&infin;, 1). * <i>e</i><sup>2</sup> should lie in (&minus;&infin;, 1).
* The returned value \e f lies in (&minus;&infin;, 1). * The returned value \e f lies in (&minus;&infin;, 1).
********************************************************************** / ********************************************************************** /
static Math::real EccentricitySqToFlattening(real e2) static Math::real EccentricitySqToFlattening(real e2)
{ return e2 / (std::sqrt(1 - e2) + 1); } { using std::sqrt; return e2 / (sqrt(1 - e2) + 1); }
/** /**
* @param[in] f = (\e a &minus; \e b) / \e a, the flattening. * @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
* @return <i>e</i><sup>2</sup> = (<i>a</i><sup>2</sup> &minus; * @return <i>e</i><sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / <i>a</i><sup>2</sup>, the eccentricity * <i>b</i><sup>2</sup>) / <i>a</i><sup>2</sup>, the eccentricity
* squared. * squared.
* *
* \e f should lie in (&minus;&infin;, 1). * \e f should lie in (&minus;&infin;, 1).
* The returned value <i>e</i><sup>2</sup> lies in (&minus;&infin;, 1). * The returned value <i>e</i><sup>2</sup> lies in (&minus;&infin;, 1).
********************************************************************** / ********************************************************************** /
skipping to change at line 487 skipping to change at line 497
/** /**
* @param[in] ep2 = <i>e'</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &min us; * @param[in] ep2 = <i>e'</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &min us;
* <i>b</i><sup>2</sup>) / <i>b</i><sup>2</sup>, the second eccentric ity * <i>b</i><sup>2</sup>) / <i>b</i><sup>2</sup>, the second eccentric ity
* squared. * squared.
* @return \e f = (\e a &minus; \e b) / \e a, the flattening. * @return \e f = (\e a &minus; \e b) / \e a, the flattening.
* *
* <i>e'</i> <sup>2</sup> should lie in (&minus;1, &infin;). * <i>e'</i> <sup>2</sup> should lie in (&minus;1, &infin;).
* The returned value \e f lies in (&minus;&infin;, 1). * The returned value \e f lies in (&minus;&infin;, 1).
********************************************************************** / ********************************************************************** /
static Math::real SecondEccentricitySqToFlattening(real ep2) static Math::real SecondEccentricitySqToFlattening(real ep2)
{ return ep2 / (std::sqrt(1 + ep2) + 1 + ep2); } { using std::sqrt; return ep2 / (sqrt(1 + ep2) + 1 + ep2); }
/** /**
* @param[in] f = (\e a &minus; \e b) / \e a, the flattening. * @param[in] f = (\e a &minus; \e b) / \e a, the flattening.
* @return <i>e'</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus; * @return <i>e'</i> <sup>2</sup> = (<i>a</i><sup>2</sup> &minus;
* <i>b</i><sup>2</sup>) / <i>b</i><sup>2</sup>, the second eccentric ity * <i>b</i><sup>2</sup>) / <i>b</i><sup>2</sup>, the second eccentric ity
* squared. * squared.
* *
* \e f should lie in (&minus;&infin;, 1). * \e f should lie in (&minus;&infin;, 1).
* The returned value <i>e'</i> <sup>2</sup> lies in (&minus;1, &infin; ). * The returned value <i>e'</i> <sup>2</sup> lies in (&minus;1, &infin; ).
********************************************************************** / ********************************************************************** /
skipping to change at line 531 skipping to change at line 541
********************************************************************** / ********************************************************************** /
static Math::real FlatteningToThirdEccentricitySq(real f) static Math::real FlatteningToThirdEccentricitySq(real f)
{ return f * (2 - f) / (1 + Math::sq(1 - f)); } { return f * (2 - f) / (1 + Math::sq(1 - f)); }
///@} ///@}
/** /**
* A global instantiation of Ellipsoid with the parameters for the WGS8 4 * A global instantiation of Ellipsoid with the parameters for the WGS8 4
* ellipsoid. * ellipsoid.
********************************************************************** / ********************************************************************** /
static const Ellipsoid WGS84; static const Ellipsoid& WGS84();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_ELLIPSOID_HPP #endif // GEOGRAPHICLIB_ELLIPSOID_HPP
 End of changes. 12 change blocks. 
21 lines changed or deleted 34 lines changed or added


 EllipticFunction.hpp   EllipticFunction.hpp 
skipping to change at line 65 skipping to change at line 65
* 78--90 (1965). * 78--90 (1965).
* . * .
* The notation follows http://dlmf.nist.gov/19 and http://dlmf.nist.gov/ 22 * The notation follows http://dlmf.nist.gov/19 and http://dlmf.nist.gov/ 22
* *
* Example of use: * Example of use:
* \include example-EllipticFunction.cpp * \include example-EllipticFunction.cpp
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT EllipticFunction { class GEOGRAPHICLIB_EXPORT EllipticFunction {
private: private:
typedef Math::real real; typedef Math::real real;
static const real tol_;
static const real tolRF_;
static const real tolRD_;
static const real tolRG0_;
static const real tolJAC_;
enum { num_ = 13 }; // Max depth required for sncndn. Probably 5 is en ough. enum { num_ = 13 }; // Max depth required for sncndn. Probably 5 is en ough.
real _k2, _kp2, _alpha2, _alphap2, _eps; real _k2, _kp2, _alpha2, _alphap2, _eps;
mutable bool _init; real _Kc, _Ec, _Dc, _Pic, _Gc, _Hc;
mutable real _Kc, _Ec, _Dc, _Pic, _Gc, _Hc;
bool Init() const;
public: public:
/** \name Constructor /** \name Constructor
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* Constructor specifying the modulus and parameter. * Constructor specifying the modulus and parameter.
* *
* @param[in] k2 the square of the modulus <i>k</i><sup>2</sup>. * @param[in] k2 the square of the modulus <i>k</i><sup>2</sup>.
* <i>k</i><sup>2</sup> must lie in (-&infin;, 1). (No checking is * <i>k</i><sup>2</sup> must lie in (-&infin;, 1). (No checking is
* done.) * done.)
* @param[in] alpha2 the parameter &alpha;<sup>2</sup>. * @param[in] alpha2 the parameter &alpha;<sup>2</sup>.
* &alpha;<sup>2</sup> must lie in (-&infin;, 1). (No checking is do ne.) * &alpha;<sup>2</sup> must lie in (-&infin;, 1). (No checking is do ne.)
* *
* If only elliptic integrals of the first and second kinds are needed, * If only elliptic integrals of the first and second kinds are needed,
* then set &alpha;<sup>2</sup> = 0 (the default value); in this case, we * then set &alpha;<sup>2</sup> = 0 (the default value); in this case, we
* have &Pi;(&phi;, 0, \e k) = \e F(&phi;, \e k), \e G(&phi;, 0, \e k) = \e * have &Pi;(&phi;, 0, \e k) = \e F(&phi;, \e k), \e G(&phi;, 0, \e k) = \e
* E(&phi;, \e k), and \e H(&phi;, 0, \e k) = \e F(&phi;, \e k) - \e * E(&phi;, \e k), and \e H(&phi;, 0, \e k) = \e F(&phi;, \e k) - \e
* D(&phi;, \e k). * D(&phi;, \e k).
********************************************************************** / ********************************************************************** /
EllipticFunction(real k2 = 0, real alpha2 = 0); EllipticFunction(real k2 = 0, real alpha2 = 0)
{ Reset(k2, alpha2); }
/** /**
* Constructor specifying the modulus and parameter and their complemen ts. * Constructor specifying the modulus and parameter and their complemen ts.
* *
* @param[in] k2 the square of the modulus <i>k</i><sup>2</sup>. * @param[in] k2 the square of the modulus <i>k</i><sup>2</sup>.
* <i>k</i><sup>2</sup> must lie in (-&infin;, 1). (No checking is * <i>k</i><sup>2</sup> must lie in (-&infin;, 1). (No checking is
* done.) * done.)
* @param[in] alpha2 the parameter &alpha;<sup>2</sup>. * @param[in] alpha2 the parameter &alpha;<sup>2</sup>.
* &alpha;<sup>2</sup> must lie in (-&infin;, 1). (No checking is do ne.) * &alpha;<sup>2</sup> must lie in (-&infin;, 1). (No checking is do ne.)
* @param[in] kp2 the complementary modulus squared <i>k'</i><sup>2</su p> = * @param[in] kp2 the complementary modulus squared <i>k'</i><sup>2</su p> =
* 1 &minus; <i>k</i><sup>2</sup>. * 1 &minus; <i>k</i><sup>2</sup>.
* @param[in] alphap2 the complementary parameter &alpha;'<sup>2</sup> = 1 * @param[in] alphap2 the complementary parameter &alpha;'<sup>2</sup> = 1
* &minus; &alpha;<sup>2</sup>. * &minus; &alpha;<sup>2</sup>.
* *
* The arguments must satisfy \e k2 + \e kp2 = 1 and \e alpha2 + \e alp hap2 * The arguments must satisfy \e k2 + \e kp2 = 1 and \e alpha2 + \e alp hap2
* = 1. (No checking is done that these conditions are met.) This * = 1. (No checking is done that these conditions are met.) This
* constructor is provided to enable accuracy to be maintained, e.g., w hen * constructor is provided to enable accuracy to be maintained, e.g., w hen
* \e k is very close to unity. * \e k is very close to unity.
********************************************************************** / ********************************************************************** /
EllipticFunction(real k2, real alpha2, real kp2, real alphap2); EllipticFunction(real k2, real alpha2, real kp2, real alphap2)
{ Reset(k2, alpha2, kp2, alphap2); }
/** /**
* Reset the modulus and parameter. * Reset the modulus and parameter.
* *
* @param[in] k2 the new value of square of the modulus * @param[in] k2 the new value of square of the modulus
* <i>k</i><sup>2</sup> which must lie in (-&infin;, 1). (No checkin g is * <i>k</i><sup>2</sup> which must lie in (-&infin;, 1). (No checkin g is
* done.) * done.)
* @param[in] alpha2 the new value of parameter &alpha;<sup>2</sup>. * @param[in] alpha2 the new value of parameter &alpha;<sup>2</sup>.
* &alpha;<sup>2</sup> must lie in (-&infin;, 1). (No checking is do ne.) * &alpha;<sup>2</sup> must lie in (-&infin;, 1). (No checking is do ne.)
********************************************************************** / ********************************************************************** /
skipping to change at line 205 skipping to change at line 200
/** /**
* The complete integral of the first kind. * The complete integral of the first kind.
* *
* @return \e K(\e k). * @return \e K(\e k).
* *
* \e K(\e k) is defined in http://dlmf.nist.gov/19.2.E4 * \e K(\e k) is defined in http://dlmf.nist.gov/19.2.E4
* \f[ * \f[
* K(k) = \int_0^{\pi/2} \frac1{\sqrt{1-k^2\sin^2\phi}}\,d\phi. * K(k) = \int_0^{\pi/2} \frac1{\sqrt{1-k^2\sin^2\phi}}\,d\phi.
* \f] * \f]
********************************************************************** / ********************************************************************** /
Math::real K() const { _init || Init(); return _Kc; } Math::real K() const { return _Kc; }
/** /**
* The complete integral of the second kind. * The complete integral of the second kind.
* *
* @return \e E(\e k) * @return \e E(\e k)
* *
* \e E(\e k) is defined in http://dlmf.nist.gov/19.2.E5 * \e E(\e k) is defined in http://dlmf.nist.gov/19.2.E5
* \f[ * \f[
* E(k) = \int_0^{\pi/2} \sqrt{1-k^2\sin^2\phi}\,d\phi. * E(k) = \int_0^{\pi/2} \sqrt{1-k^2\sin^2\phi}\,d\phi.
* \f] * \f]
********************************************************************** / ********************************************************************** /
Math::real E() const { _init || Init(); return _Ec; } Math::real E() const { return _Ec; }
/** /**
* Jahnke's complete integral. * Jahnke's complete integral.
* *
* @return \e D(\e k). * @return \e D(\e k).
* *
* \e D(\e k) is defined in http://dlmf.nist.gov/19.2.E6 * \e D(\e k) is defined in http://dlmf.nist.gov/19.2.E6
* \f[ * \f[
* D(k) = \int_0^{\pi/2} \frac{\sin^2\phi}{\sqrt{1-k^2\sin^2\phi}}\,d \phi. * D(k) = \int_0^{\pi/2} \frac{\sin^2\phi}{\sqrt{1-k^2\sin^2\phi}}\,d \phi.
* \f] * \f]
********************************************************************** / ********************************************************************** /
Math::real D() const { _init || Init(); return _Dc; } Math::real D() const { return _Dc; }
/** /**
* The difference between the complete integrals of the first and secon d * The difference between the complete integrals of the first and secon d
* kinds. * kinds.
* *
* @return \e K(\e k) &minus; \e E(\e k). * @return \e K(\e k) &minus; \e E(\e k).
********************************************************************** / ********************************************************************** /
Math::real KE() const { _init || Init(); return _k2 * _Dc; } Math::real KE() const { return _k2 * _Dc; }
/** /**
* The complete integral of the third kind. * The complete integral of the third kind.
* *
* @return &Pi;(&alpha;<sup>2</sup>, \e k) * @return &Pi;(&alpha;<sup>2</sup>, \e k)
* *
* &Pi;(&alpha;<sup>2</sup>, \e k) is defined in * &Pi;(&alpha;<sup>2</sup>, \e k) is defined in
* http://dlmf.nist.gov/19.2.E7 * http://dlmf.nist.gov/19.2.E7
* \f[ * \f[
* \Pi(\alpha^2, k) = \int_0^{\pi/2} * \Pi(\alpha^2, k) = \int_0^{\pi/2}
* \frac1{\sqrt{1-k^2\sin^2\phi}(1 - \alpha^2\sin^2\phi_)}\,d\phi. * \frac1{\sqrt{1-k^2\sin^2\phi}(1 - \alpha^2\sin^2\phi_)}\,d\phi.
* \f] * \f]
********************************************************************** / ********************************************************************** /
Math::real Pi() const { _init || Init(); return _Pic; } Math::real Pi() const { return _Pic; }
/** /**
* Legendre's complete geodesic longitude integral. * Legendre's complete geodesic longitude integral.
* *
* @return \e G(&alpha;<sup>2</sup>, \e k) * @return \e G(&alpha;<sup>2</sup>, \e k)
* *
* \e G(&alpha;<sup>2</sup>, \e k) is given by * \e G(&alpha;<sup>2</sup>, \e k) is given by
* \f[ * \f[
* G(\alpha^2, k) = \int_0^{\pi/2} * G(\alpha^2, k) = \int_0^{\pi/2}
* \frac{\sqrt{1-k^2\sin^2\phi}}{1 - \alpha^2\sin^2\phi}\,d\phi. * \frac{\sqrt{1-k^2\sin^2\phi}}{1 - \alpha^2\sin^2\phi}\,d\phi.
* \f] * \f]
********************************************************************** / ********************************************************************** /
Math::real G() const { _init || Init(); return _Gc; } Math::real G() const { return _Gc; }
/** /**
* Cayley's complete geodesic longitude difference integral. * Cayley's complete geodesic longitude difference integral.
* *
* @return \e H(&alpha;<sup>2</sup>, \e k) * @return \e H(&alpha;<sup>2</sup>, \e k)
* *
* \e H(&alpha;<sup>2</sup>, \e k) is given by * \e H(&alpha;<sup>2</sup>, \e k) is given by
* \f[ * \f[
* H(\alpha^2, k) = \int_0^{\pi/2} * H(\alpha^2, k) = \int_0^{\pi/2}
* \frac{\cos^2\phi}{(1-\alpha^2\sin^2\phi)\sqrt{1-k^2\sin^2\phi}} * \frac{\cos^2\phi}{(1-\alpha^2\sin^2\phi)\sqrt{1-k^2\sin^2\phi}}
* \,d\phi. * \,d\phi.
* \f] * \f]
********************************************************************** / ********************************************************************** /
Math::real H() const { _init || Init(); return _Hc; } Math::real H() const { return _Hc; }
///@} ///@}
/** \name Incomplete elliptic integrals. /** \name Incomplete elliptic integrals.
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* The incomplete integral of the first kind. * The incomplete integral of the first kind.
* *
* @param[in] phi * @param[in] phi
* @return \e F(&phi;, \e k). * @return \e F(&phi;, \e k).
skipping to change at line 597 skipping to change at line 592
void sncndn(real x, real& sn, real& cn, real& dn) const; void sncndn(real x, real& sn, real& cn, real& dn) const;
/** /**
* The &Delta; amplitude function. * The &Delta; amplitude function.
* *
* @param[in] sn sin&phi; * @param[in] sn sin&phi;
* @param[in] cn cos&phi; * @param[in] cn cos&phi;
* @return &Delta; = sqrt(1 &minus; <i>k</i><sup>2</sup> * @return &Delta; = sqrt(1 &minus; <i>k</i><sup>2</sup>
* sin<sup>2</sup>&phi;) * sin<sup>2</sup>&phi;)
********************************************************************** / ********************************************************************** /
Math::real Delta(real sn, real cn) const Math::real Delta(real sn, real cn) const {
{ return std::sqrt(_k2 < 0 ? 1 - _k2 * sn*sn : _kp2 + _k2 * cn*cn); } using std::sqrt;
return sqrt(_k2 < 0 ? 1 - _k2 * sn*sn : _kp2 + _k2 * cn*cn);
}
///@} ///@}
/** \name Symmetric elliptic integrals. /** \name Symmetric elliptic integrals.
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* Symmetric integral of the first kind <i>R<sub>F</sub></i>. * Symmetric integral of the first kind <i>R</i><sub><i>F</i></sub>.
* *
* @param[in] x * @param[in] x
* @param[in] y * @param[in] y
* @param[in] z * @param[in] z
* @return <i>R<sub>F</sub></i>(\e x, \e y, \e z) * @return <i>R</i><sub><i>F</i></sub>(\e x, \e y, \e z)
* *
* <i>R<sub>F</sub></i> is defined in http://dlmf.nist.gov/19.16.E1 * <i>R</i><sub><i>F</i></sub> is defined in http://dlmf.nist.gov/19.16 .E1
* \f[ R_F(x, y, z) = \frac12 * \f[ R_F(x, y, z) = \frac12
* \int_0^\infty\frac1{\sqrt{(t + x) (t + y) (t + z)}}\, dt \f] * \int_0^\infty\frac1{\sqrt{(t + x) (t + y) (t + z)}}\, dt \f]
* If one of the arguments is zero, it is more efficient to call the * If one of the arguments is zero, it is more efficient to call the
* two-argument version of this function with the non-zero arguments. * two-argument version of this function with the non-zero arguments.
********************************************************************** / ********************************************************************** /
static real RF(real x, real y, real z); static real RF(real x, real y, real z);
/** /**
* Complete symmetric integral of the first kind, <i>R<sub>F</sub></i> * Complete symmetric integral of the first kind,
with * <i>R</i><sub><i>F</i></sub> with one argument zero.
* one argument zero.
* *
* @param[in] x * @param[in] x
* @param[in] y * @param[in] y
* @return <i>R<sub>F</sub></i>(\e x, \e y, 0) * @return <i>R</i><sub><i>F</i></sub>(\e x, \e y, 0)
********************************************************************** / ********************************************************************** /
static real RF(real x, real y); static real RF(real x, real y);
/** /**
* Degenerate symmetric integral of the first kind <i>R<sub>C</sub></i> * Degenerate symmetric integral of the first kind
. * <i>R</i><sub><i>C</i></sub>.
* *
* @param[in] x * @param[in] x
* @param[in] y * @param[in] y
* @return <i>R<sub>C</sub></i>(\e x, \e y) = <i>R<sub>F</sub></i>(\e x * @return <i>R</i><sub><i>C</i></sub>(\e x, \e y) =
, \e * <i>R</i><sub><i>F</i></sub>(\e x, \e y, \e y)
* y, \e y)
* *
* <i>R<sub>C</sub></i> is defined in http://dlmf.nist.gov/19.2.E17 * <i>R</i><sub><i>C</i></sub> is defined in http://dlmf.nist.gov/19.2. E17
* \f[ R_C(x, y) = \frac12 * \f[ R_C(x, y) = \frac12
* \int_0^\infty\frac1{\sqrt{t + x}(t + y)}\,dt \f] * \int_0^\infty\frac1{\sqrt{t + x}(t + y)}\,dt \f]
********************************************************************** / ********************************************************************** /
static real RC(real x, real y); static real RC(real x, real y);
/** /**
* Symmetric integral of the second kind <i>R<sub>G</sub></i>. * Symmetric integral of the second kind <i>R</i><sub><i>G</i></sub>.
* *
* @param[in] x * @param[in] x
* @param[in] y * @param[in] y
* @param[in] z * @param[in] z
* @return <i>R<sub>G</sub></i>(\e x, \e y, \e z) * @return <i>R</i><sub><i>G</i></sub>(\e x, \e y, \e z)
* *
* <i>R<sub>G</sub></i> is defined in Carlson, eq 1.5 * <i>R</i><sub><i>G</i></sub> is defined in Carlson, eq 1.5
* \f[ R_G(x, y, z) = \frac14 * \f[ R_G(x, y, z) = \frac14
* \int_0^\infty[(t + x) (t + y) (t + z)]^{-1/2} * \int_0^\infty[(t + x) (t + y) (t + z)]^{-1/2}
* \biggl( * \biggl(
* \frac x{t + x} + \frac y{t + y} + \frac z{t + z} * \frac x{t + x} + \frac y{t + y} + \frac z{t + z}
* \biggr)t\,dt \f] * \biggr)t\,dt \f]
* See also http://dlmf.nist.gov/19.16.E3. * See also http://dlmf.nist.gov/19.16.E3.
* If one of the arguments is zero, it is more efficient to call the * If one of the arguments is zero, it is more efficient to call the
* two-argument version of this function with the non-zero arguments. * two-argument version of this function with the non-zero arguments.
********************************************************************** / ********************************************************************** /
static real RG(real x, real y, real z); static real RG(real x, real y, real z);
/** /**
* Complete symmetric integral of the second kind, <i>R<sub>G</sub></i> * Complete symmetric integral of the second kind,
* with one argument zero. * <i>R</i><sub><i>G</i></sub> with one argument zero.
* *
* @param[in] x * @param[in] x
* @param[in] y * @param[in] y
* @return <i>R<sub>G</sub></i>(\e x, \e y, 0) * @return <i>R</i><sub><i>G</i></sub>(\e x, \e y, 0)
********************************************************************** / ********************************************************************** /
static real RG(real x, real y); static real RG(real x, real y);
/** /**
* Symmetric integral of the third kind <i>R<sub>J</sub></i>. * Symmetric integral of the third kind <i>R</i><sub><i>J</i></sub>.
* *
* @param[in] x * @param[in] x
* @param[in] y * @param[in] y
* @param[in] z * @param[in] z
* @param[in] p * @param[in] p
* @return <i>R<sub>J</sub></i>(\e x, \e y, \e z, \e p) * @return <i>R</i><sub><i>J</i></sub>(\e x, \e y, \e z, \e p)
* *
* <i>R<sub>J</sub></i> is defined in http://dlmf.nist.gov/19.16.E2 * <i>R</i><sub><i>J</i></sub> is defined in http://dlmf.nist.gov/19.16 .E2
* \f[ R_J(x, y, z, p) = \frac32 * \f[ R_J(x, y, z, p) = \frac32
* \int_0^\infty[(t + x) (t + y) (t + z)]^{-1/2} (t + p)^{-1}\, d t \f] * \int_0^\infty[(t + x) (t + y) (t + z)]^{-1/2} (t + p)^{-1}\, d t \f]
********************************************************************** / ********************************************************************** /
static real RJ(real x, real y, real z, real p); static real RJ(real x, real y, real z, real p);
/** /**
* Degenerate symmetric integral of the third kind <i>R<sub>D</sub></i> * Degenerate symmetric integral of the third kind
. * <i>R</i><sub><i>D</i></sub>.
* *
* @param[in] x * @param[in] x
* @param[in] y * @param[in] y
* @param[in] z * @param[in] z
* @return <i>R<sub>D</sub></i>(\e x, \e y, \e z) = <i>R<sub>J</sub></i * @return <i>R</i><sub><i>D</i></sub>(\e x, \e y, \e z) =
>(\e * <i>R</i><sub><i>J</i></sub>(\e x, \e y, \e z, \e z)
* x, \e y, \e z, \e z)
* *
* <i>R<sub>D</sub></i> is defined in http://dlmf.nist.gov/19.16.E5 * <i>R</i><sub><i>D</i></sub> is defined in http://dlmf.nist.gov/19.16 .E5
* \f[ R_D(x, y, z) = \frac32 * \f[ R_D(x, y, z) = \frac32
* \int_0^\infty[(t + x) (t + y)]^{-1/2} (t + z)^{-3/2}\, dt \f] * \int_0^\infty[(t + x) (t + y)]^{-1/2} (t + z)^{-3/2}\, dt \f]
********************************************************************** / ********************************************************************** /
static real RD(real x, real y, real z); static real RD(real x, real y, real z);
///@} ///@}
}; };
} // namespace GeographicLib } // namespace GeographicLib
 End of changes. 31 change blocks. 
47 lines changed or deleted 41 lines changed or added


 GeoCoords.hpp   GeoCoords.hpp 
skipping to change at line 112 skipping to change at line 112
* -# "Lat Long" or "Long Lat" * -# "Lat Long" or "Long Lat"
* -# "Zone Easting Northing" or "Easting Northing Zone" * -# "Zone Easting Northing" or "Easting Northing Zone"
* *
* The following inputs are approximately the same (Ar Ramadi Bridge, I raq) * The following inputs are approximately the same (Ar Ramadi Bridge, I raq)
* - Latitude and Longitude * - Latitude and Longitude
* - 33.44 43.27 * - 33.44 43.27
* - N33d26.4' E43d16.2' * - N33d26.4' E43d16.2'
* - 43d16'12&quot;E 33d26'24&quot;N * - 43d16'12&quot;E 33d26'24&quot;N
* - 43:16:12E 33:26:24 * - 43:16:12E 33:26:24
* - MGRS * - MGRS
* - 38SLC301 * - 38SLC30
* - 38SLC391014 * - 38SLC391014
* - 38SLC3918701405 * - 38SLC3918701405
* - 37SHT9708 * - 37SHT9708
* - UTM * - UTM
* - 38n 339188 3701405 * - 38n 339188 3701405
* - 897039 3708229 37n * - 897039 3708229 37n
* *
* <b>Latitude and Longitude parsing</b>: Latitude precedes longitude, * <b>Latitude and Longitude parsing</b>: Latitude precedes longitude,
* unless a N, S, E, W hemisphere designator is used on one or both * unless a N, S, E, W hemisphere designator is used on one or both
* coordinates. If \e swaplatlong = true (default is false), then * coordinates. If \e swaplatlong = true (default is false), then
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 Geocentric.hpp   Geocentric.hpp 
skipping to change at line 46 skipping to change at line 46
* Several changes have been made to ensure that the method returns accur ate * Several changes have been made to ensure that the method returns accur ate
* results for all finite inputs (even if \e h is infinite). The changes are * results for all finite inputs (even if \e h is infinite). The changes are
* described in Appendix B of * described in Appendix B of
* - C. F. F. Karney, * - C. F. F. Karney,
* <a href="http://arxiv.org/abs/1102.1215v1">Geodesics * <a href="http://arxiv.org/abs/1102.1215v1">Geodesics
* on an ellipsoid of revolution</a>, * on an ellipsoid of revolution</a>,
* Feb. 2011; * Feb. 2011;
* preprint * preprint
* <a href="http://arxiv.org/abs/1102.1215v1">arxiv:1102.1215v1</a>. * <a href="http://arxiv.org/abs/1102.1215v1">arxiv:1102.1215v1</a>.
* . * .
* Vermeille similarly updated his method in
* - H. Vermeille,
* <a href="http://dx.doi.org/10.1007/s00190-010-0419-x">
* An analytical method to transform geocentric into
* geodetic coordinates</a>, J. Geodesy 85, 105--117 (2011).
* .
* See \ref geocentric for more information. * See \ref geocentric for more information.
* *
* The errors in these routines are close to round-off. Specifically, fo r * The errors in these routines are close to round-off. Specifically, fo r
* points within 5000 km of the surface of the ellipsoid (either inside o r * points within 5000 km of the surface of the ellipsoid (either inside o r
* outside the ellipsoid), the error is bounded by 7 nm (7 nanometers) fo r * outside the ellipsoid), the error is bounded by 7 nm (7 nanometers) fo r
* the WGS84 ellipsoid. See \ref geocentric for further information on t he * the WGS84 ellipsoid. See \ref geocentric for further information on t he
* errors. * errors.
* *
* Example of use: * Example of use:
* \include example-Geocentric.cpp * \include example-Geocentric.cpp
skipping to change at line 106 skipping to change at line 112
void IntReverse(real X, real Y, real Z, real& lat, real& lon, real& h, void IntReverse(real X, real Y, real Z, real& lat, real& lon, real& h,
real M[dim2_]) const; real M[dim2_]) const;
public: public:
/** /**
* Constructor for a ellipsoid with * Constructor for a ellipsoid with
* *
* @param[in] a equatorial radius (meters). * @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f. * @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
* @exception GeographicErr if \e a or (1 &minus; \e f ) \e a is not
* positive. * positive.
********************************************************************** / ********************************************************************** /
Geocentric(real a, real f); Geocentric(real a, real f);
/** /**
* A default constructor (for use by NormalGravity). * A default constructor (for use by NormalGravity).
********************************************************************** / ********************************************************************** /
Geocentric() : _a(-1) {} Geocentric() : _a(-1) {}
/** /**
skipping to change at line 219 skipping to change at line 225
* matrix in row-major order. * matrix in row-major order.
* *
* Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
* express \e v as \e column vectors in one of two ways * express \e v as \e column vectors in one of two ways
* - in east, north, up coordinates (where the components are relative to a * - in east, north, up coordinates (where the components are relative to a
* local coordinate system at (\e lat, \e lon, \e h)); call this * local coordinate system at (\e lat, \e lon, \e h)); call this
* representation \e v1. * representation \e v1.
* - in geocentric \e X, \e Y, \e Z coordinates; call this representati on * - in geocentric \e X, \e Y, \e Z coordinates; call this representati on
* \e v0. * \e v0.
* . * .
* Then we have \e v1 = \e M<sup>T</sup> &sdot; \e v0, where \e * Then we have \e v1 = <i>M</i><sup>T</sup> &sdot; \e v0, where
* M<sup>T</sup> is the transpose of \e M. * <i>M</i><sup>T</sup> is the transpose of \e M.
********************************************************************** / ********************************************************************** /
void Reverse(real X, real Y, real Z, real& lat, real& lon, real& h, void Reverse(real X, real Y, real Z, real& lat, real& lon, real& h,
std::vector<real>& M) std::vector<real>& M)
const { const {
if (!Init()) if (!Init())
return; return;
if (M.end() == M.begin() + dim2_) { if (M.end() == M.begin() + dim2_) {
real t[dim2_]; real t[dim2_];
IntReverse(X, Y, Z, lat, lon, h, t); IntReverse(X, Y, Z, lat, lon, h, t);
std::copy(t, t + dim2_, M.begin()); std::copy(t, t + dim2_, M.begin());
skipping to change at line 247 skipping to change at line 253
///@{ ///@{
/** /**
* @return true if the object has been initialized. * @return true if the object has been initialized.
********************************************************************** / ********************************************************************** /
bool Init() const { return _a > 0; } bool Init() const { return _a > 0; }
/** /**
* @return \e a the equatorial radius of the ellipsoid (meters). This is * @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor. * the value used in the constructor.
********************************************************************** / ********************************************************************** /
Math::real MajorRadius() const Math::real MajorRadius() const
{ return Init() ? _a : Math::NaN<real>(); } { return Init() ? _a : Math::NaN(); }
/** /**
* @return \e f the flattening of the ellipsoid. This is the * @return \e f the flattening of the ellipsoid. This is the
* value used in the constructor. * value used in the constructor.
********************************************************************** / ********************************************************************** /
Math::real Flattening() const Math::real Flattening() const
{ return Init() ? _f : Math::NaN<real>(); } { return Init() ? _f : Math::NaN(); }
///@} ///@}
/// \cond SKIP /// \cond SKIP
/** /**
* <b>DEPRECATED</b> * <b>DEPRECATED</b>
* @return \e r the inverse flattening of the ellipsoid. * @return \e r the inverse flattening of the ellipsoid.
********************************************************************** / ********************************************************************** /
Math::real InverseFlattening() const Math::real InverseFlattening() const
{ return Init() ? 1/_f : Math::NaN<real>(); } { return Init() ? 1/_f : Math::NaN(); }
/// \endcond /// \endcond
/** /**
* A global instantiation of Geocentric with the parameters for the WGS 84 * A global instantiation of Geocentric with the parameters for the WGS 84
* ellipsoid. * ellipsoid.
********************************************************************** / ********************************************************************** /
static const Geocentric WGS84; static const Geocentric& WGS84();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_GEOCENTRIC_HPP #endif // GEOGRAPHICLIB_GEOCENTRIC_HPP
 End of changes. 7 change blocks. 
10 lines changed or deleted 15 lines changed or added


 Geodesic.hpp   Geodesic.hpp 
skipping to change at line 18 skipping to change at line 18
**********************************************************************/ **********************************************************************/
#if !defined(GEOGRAPHICLIB_GEODESIC_HPP) #if !defined(GEOGRAPHICLIB_GEODESIC_HPP)
#define GEOGRAPHICLIB_GEODESIC_HPP 1 #define GEOGRAPHICLIB_GEODESIC_HPP 1
#include <GeographicLib/Constants.hpp> #include <GeographicLib/Constants.hpp>
#if !defined(GEOGRAPHICLIB_GEODESIC_ORDER) #if !defined(GEOGRAPHICLIB_GEODESIC_ORDER)
/** /**
* The order of the expansions used by Geodesic. * The order of the expansions used by Geodesic.
* GEOGRAPHICLIB_GEODESIC_ORDER can be set to any integer in [0, 8].
**********************************************************************/ **********************************************************************/
# define GEOGRAPHICLIB_GEODESIC_ORDER \ # define GEOGRAPHICLIB_GEODESIC_ORDER \
(GEOGRAPHICLIB_PRECISION == 2 ? 6 : (GEOGRAPHICLIB_PRECISION == 1 ? 3 : 7 (GEOGRAPHICLIB_PRECISION == 2 ? 6 : \
)) (GEOGRAPHICLIB_PRECISION == 1 ? 3 : \
(GEOGRAPHICLIB_PRECISION == 3 ? 7 : 8)))
#endif #endif
namespace GeographicLib { namespace GeographicLib {
class GeodesicLine; class GeodesicLine;
/** /**
* \brief %Geodesic calculations * \brief %Geodesic calculations
* *
* The shortest path between two points on a ellipsoid at (\e lat1, \e lo n1) * The shortest path between two points on a ellipsoid at (\e lat1, \e lo n1)
skipping to change at line 185 skipping to change at line 188
static const int nC1p_ = GEOGRAPHICLIB_GEODESIC_ORDER; static const int nC1p_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nA2_ = GEOGRAPHICLIB_GEODESIC_ORDER; static const int nA2_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nC2_ = GEOGRAPHICLIB_GEODESIC_ORDER; static const int nC2_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nA3_ = GEOGRAPHICLIB_GEODESIC_ORDER; static const int nA3_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nA3x_ = nA3_; static const int nA3x_ = nA3_;
static const int nC3_ = GEOGRAPHICLIB_GEODESIC_ORDER; static const int nC3_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nC3x_ = (nC3_ * (nC3_ - 1)) / 2; static const int nC3x_ = (nC3_ * (nC3_ - 1)) / 2;
static const int nC4_ = GEOGRAPHICLIB_GEODESIC_ORDER; static const int nC4_ = GEOGRAPHICLIB_GEODESIC_ORDER;
static const int nC4x_ = (nC4_ * (nC4_ + 1)) / 2; static const int nC4x_ = (nC4_ * (nC4_ + 1)) / 2;
static const unsigned maxit1_ = 20; static const unsigned maxit1_ = 20;
static const unsigned maxit2_ = maxit1_ + unsigned maxit2_;
std::numeric_limits<real>::digits + 10; real tiny_, tol0_, tol1_, tol2_, tolb_, xthresh_;
static const real tiny_;
static const real tol0_;
static const real tol1_;
static const real tol2_;
static const real tolb_;
static const real xthresh_;
enum captype { enum captype {
CAP_NONE = 0U, CAP_NONE = 0U,
CAP_C1 = 1U<<0, CAP_C1 = 1U<<0,
CAP_C1p = 1U<<1, CAP_C1p = 1U<<1,
CAP_C2 = 1U<<2, CAP_C2 = 1U<<2,
CAP_C3 = 1U<<3, CAP_C3 = 1U<<3,
CAP_C4 = 1U<<4, CAP_C4 = 1U<<4,
CAP_ALL = 0x1FU, CAP_ALL = 0x1FU,
OUT_ALL = 0x7F80U, OUT_ALL = 0x7F80U,
}; };
static real SinCosSeries(bool sinp, static real SinCosSeries(bool sinp,
real sinx, real cosx, const real c[], int n) real sinx, real cosx, const real c[], int n);
;
static inline real AngRound(real x) { static inline real AngRound(real x) {
// The makes the smallest gap in x = 1/16 - nextafter(1/16, 0) = 1/2^ 57 // The makes the smallest gap in x = 1/16 - nextafter(1/16, 0) = 1/2^ 57
// for reals = 0.7 pm on the earth if x is an angle in degrees. (Thi s // for reals = 0.7 pm on the earth if x is an angle in degrees. (Thi s
// is about 1000 times more resolution than we get with angles around 90 // is about 1000 times more resolution than we get with angles around 90
// degrees.) We use this to avoid having to deal with near singular // degrees.) We use this to avoid having to deal with near singular
// cases when x is non-zero but tiny (e.g., 1.0e-200). // cases when x is non-zero but tiny (e.g., 1.0e-200).
using std::abs;
const real z = 1/real(16); const real z = 1/real(16);
volatile real y = std::abs(x); GEOGRAPHICLIB_VOLATILE real y = abs(x);
// The compiler mustn't "simplify" z - (z - y) to y // The compiler mustn't "simplify" z - (z - y) to y
y = y < z ? z - (z - y) : y; y = y < z ? z - (z - y) : y;
return x < 0 ? -y : y; return x < 0 ? -y : y;
} }
static inline void SinCosNorm(real& sinx, real& cosx) { static inline void SinCosNorm(real& sinx, real& cosx) {
real r = Math::hypot(sinx, cosx); real r = Math::hypot(sinx, cosx);
sinx /= r; sinx /= r;
cosx /= r; cosx /= r;
} }
static real Astroid(real x, real y); static real Astroid(real x, real y);
skipping to change at line 343 skipping to change at line 339
}; };
/** \name Constructor /** \name Constructor
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* Constructor for a ellipsoid with * Constructor for a ellipsoid with
* *
* @param[in] a equatorial radius (meters). * @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f. * @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
* @exception GeographicErr if \e a or (1 &minus; \e f ) \e a is not
* positive. * positive.
********************************************************************** / ********************************************************************** /
Geodesic(real a, real f); Geodesic(real a, real f);
///@} ///@}
/** \name Direct geodesic problem specified in terms of distance. /** \name Direct geodesic problem specified in terms of distance.
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* Solve the direct geodesic problem where the length of the geodesic * Solve the direct geodesic problem where the length of the geodesic
skipping to change at line 882 skipping to change at line 878
Math::real InverseFlattening() const { return 1/_f; } Math::real InverseFlattening() const { return 1/_f; }
/// \endcond /// \endcond
/** /**
* @return total area of ellipsoid in meters<sup>2</sup>. The area of a * @return total area of ellipsoid in meters<sup>2</sup>. The area of a
* polygon encircling a pole can be found by adding * polygon encircling a pole can be found by adding
* Geodesic::EllipsoidArea()/2 to the sum of \e S12 for each side of the * Geodesic::EllipsoidArea()/2 to the sum of \e S12 for each side of the
* polygon. * polygon.
********************************************************************** / ********************************************************************** /
Math::real EllipsoidArea() const Math::real EllipsoidArea() const
{ return 4 * Math::pi<real>() * _c2; } { return 4 * Math::pi() * _c2; }
///@} ///@}
/** /**
* A global instantiation of Geodesic with the parameters for the WGS84 * A global instantiation of Geodesic with the parameters for the WGS84
* ellipsoid. * ellipsoid.
********************************************************************** / ********************************************************************** /
static const Geodesic WGS84; static const Geodesic& WGS84();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_GEODESIC_HPP #endif // GEOGRAPHICLIB_GEODESIC_HPP
 End of changes. 9 change blocks. 
20 lines changed or deleted 14 lines changed or added


 GeodesicExact.hpp   GeodesicExact.hpp 
skipping to change at line 35 skipping to change at line 35
class GeodesicLineExact; class GeodesicLineExact;
/** /**
* \brief Exact geodesic calculations * \brief Exact geodesic calculations
* *
* The equations for geodesics on an ellipsoid can be expressed in terms of * The equations for geodesics on an ellipsoid can be expressed in terms of
* incomplete elliptic integrals. The Geodesic class expands these integ rals * incomplete elliptic integrals. The Geodesic class expands these integ rals
* in a series in the flattening \e f and this provides an accurate solut ion * in a series in the flattening \e f and this provides an accurate solut ion
* for \e f &isin; [-0.01, 0.01]. The GeodesicExact class computes the * for \e f &isin; [-0.01, 0.01]. The GeodesicExact class computes the
* ellitpic integrals directly and so provides a solution which is valid for * ellitpic integrals directly and so provides a solution which is valid for
* all \e f. However, in practice, its use should be limited to about \e * all \e f. However, in practice, its use should be limited to about
* b/\e a &isin; [0.01, 100] or \e f &isin; [-99, 0.99]. * <i>b</i>/\e a &isin; [0.01, 100] or \e f &isin; [-99, 0.99].
* *
* For the WGS84 ellipsoid, these classes are 2--3 times \e slower than t he * For the WGS84 ellipsoid, these classes are 2--3 times \e slower than t he
* series solution and 2--3 times \e less \e accurate (because it's less easy * series solution and 2--3 times \e less \e accurate (because it's less easy
* to control round-off errors with the elliptic integral formulation); i .e., * to control round-off errors with the elliptic integral formulation); i .e.,
* the error is about 40 nm (40 nanometers) instead of 15 nm. However th e * the error is about 40 nm (40 nanometers) instead of 15 nm. However th e
* error in the series solution scales as <i>f</i><sup>7</sup> while the * error in the series solution scales as <i>f</i><sup>7</sup> while the
* error in the elliptic integral solution depends weakly on \e f. If th e * error in the elliptic integral solution depends weakly on \e f. If th e
* quarter meridian distance is 10000 km and the ratio \e b/\e a = 1 &min * quarter meridian distance is 10000 km and the ratio <i>b</i>/\e a = 1
us; * &minus; \e f is varied then the approximate maximum error (expressed a
* \e f is varied then the approximate maximum error (expressed as a s a
* distance) is <pre> * distance) is <pre>
* 1 - f error (nm) * 1 - f error (nm)
* 1/128 387 * 1/128 387
* 1/64 345 * 1/64 345
* 1/32 269 * 1/32 269
* 1/16 210 * 1/16 210
* 1/8 115 * 1/8 115
* 1/4 69 * 1/4 69
* 1/2 36 * 1/2 36
* 1 15 * 1 15
* 2 25 * 2 25
* 4 96 * 4 96
* 8 318 * 8 318
* 16 985 * 16 985
* 32 2352 * 32 2352
* 64 6008 * 64 6008
* 128 19024 * 128 19024
* </pre> * </pre>
* *
* The computation of the area in these classes is via a 30th order serie s. * The computation of the area in these classes is via a 30th order serie s.
* This gives accurate results for \e b/\e a &isin; [1/2, 2]; the accurac * This gives accurate results for <i>b</i>/\e a &isin; [1/2, 2]; the
y is * accuracy is about 8 decimal digits for <i>b</i>/\e a &isin; [1/4, 4].
* about 8 decimal digits for \e b/\e a &isin; [1/4, 4].
* *
* See \ref geodellip for the formulation. See the documentation on the * See \ref geodellip for the formulation. See the documentation on the
* Geodesic class for additional information on the geodesic problems. * Geodesic class for additional information on the geodesic problems.
* *
* Example of use: * Example of use:
* \include example-GeodesicExact.cpp * \include example-GeodesicExact.cpp
* *
* <a href="GeodSolve.1.html">GeodSolve</a> is a command-line utility * <a href="GeodSolve.1.html">GeodSolve</a> is a command-line utility
* providing access to the functionality of GeodesicExact and * providing access to the functionality of GeodesicExact and
* GeodesicLineExact (via the -E option). * GeodesicLineExact (via the -E option).
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT GeodesicExact { class GEOGRAPHICLIB_EXPORT GeodesicExact {
private: private:
typedef Math::real real; typedef Math::real real;
friend class GeodesicLineExact; friend class GeodesicLineExact;
static const int nC4_ = GEOGRAPHICLIB_GEODESICEXACT_ORDER; static const int nC4_ = GEOGRAPHICLIB_GEODESICEXACT_ORDER;
static const int nC4x_ = (nC4_ * (nC4_ + 1)) / 2; static const int nC4x_ = (nC4_ * (nC4_ + 1)) / 2;
static const unsigned maxit1_ = 20; static const unsigned maxit1_ = 20;
static const unsigned maxit2_ = maxit1_ + unsigned maxit2_;
std::numeric_limits<real>::digits + 10; real tiny_, tol0_, tol1_, tol2_, tolb_, xthresh_;
static const real tiny_;
static const real tol0_;
static const real tol1_;
static const real tol2_;
static const real tolb_;
static const real xthresh_;
enum captype { enum captype {
CAP_NONE = 0U, CAP_NONE = 0U,
CAP_E = 1U<<0, CAP_E = 1U<<0,
// Skip 1U<<1 for compatibility with Geodesic (not required) // Skip 1U<<1 for compatibility with Geodesic (not required)
CAP_D = 1U<<2, CAP_D = 1U<<2,
CAP_H = 1U<<3, CAP_H = 1U<<3,
CAP_C4 = 1U<<4, CAP_C4 = 1U<<4,
CAP_ALL = 0x1FU, CAP_ALL = 0x1FU,
OUT_ALL = 0x7F80U, OUT_ALL = 0x7F80U,
}; };
static real CosSeries(real sinx, real cosx, const real c[], int n) static real CosSeries(real sinx, real cosx, const real c[], int n);
;
static inline real AngRound(real x) { static inline real AngRound(real x) {
// The makes the smallest gap in x = 1/16 - nextafter(1/16, 0) = 1/2^ 57 // The makes the smallest gap in x = 1/16 - nextafter(1/16, 0) = 1/2^ 57
// for reals = 0.7 pm on the earth if x is an angle in degrees. (Thi s // for reals = 0.7 pm on the earth if x is an angle in degrees. (Thi s
// is about 1000 times more resolution than we get with angles around 90 // is about 1000 times more resolution than we get with angles around 90
// degrees.) We use this to avoid having to deal with near singular // degrees.) We use this to avoid having to deal with near singular
// cases when x is non-zero but tiny (e.g., 1.0e-200). // cases when x is non-zero but tiny (e.g., 1.0e-200).
using std::abs;
const real z = 1/real(16); const real z = 1/real(16);
volatile real y = std::abs(x); GEOGRAPHICLIB_VOLATILE real y = abs(x);
// The compiler mustn't "simplify" z - (z - y) to y // The compiler mustn't "simplify" z - (z - y) to y
y = y < z ? z - (z - y) : y; y = y < z ? z - (z - y) : y;
return x < 0 ? -y : y; return x < 0 ? -y : y;
} }
static inline void SinCosNorm(real& sinx, real& cosx) { static inline void SinCosNorm(real& sinx, real& cosx) {
real r = Math::hypot(sinx, cosx); real r = Math::hypot(sinx, cosx);
sinx /= r; sinx /= r;
cosx /= r; cosx /= r;
} }
static real Astroid(real x, real y); static real Astroid(real x, real y);
skipping to change at line 151 skipping to change at line 144
real sbet2, real cbet2, real dn2, real sbet2, real cbet2, real dn2,
real lam12, real lam12,
real& salp1, real& calp1, real& salp1, real& calp1,
real& salp2, real& calp2, real& dnm) const; real& salp2, real& calp2, real& dnm) const;
real Lambda12(real sbet1, real cbet1, real dn1, real Lambda12(real sbet1, real cbet1, real dn1,
real sbet2, real cbet2, real dn2, real sbet2, real cbet2, real dn2,
real salp1, real calp1, real salp1, real calp1,
real& salp2, real& calp2, real& sig12, real& salp2, real& calp2, real& sig12,
real& ssig1, real& csig1, real& ssig2, real& csig2, real& ssig1, real& csig1, real& ssig2, real& csig2,
EllipticFunction& E, EllipticFunction& E,
real& omg12, bool diffp, real& dlam12) real& omg12, bool diffp, real& dlam12) const;
const;
// These are Maxima generated functions to provide series approximation s to // These are Maxima generated functions to provide series approximation s to
// the integrals for the area. // the integrals for the area.
void C4coeff(); void C4coeff();
void C4f(real k2, real c[]) const; void C4f(real k2, real c[]) const;
// Large coefficients are split so that lo contains the low 52 bits and
hi
// the rest. This choice avoids double rounding with doubles and highe
r
// precision types. float coefficients will suffer double rounding;
// however the accuracy is already lousy for floats.
static Math::real inline reale(long long hi, long long lo) {
using std::ldexp;
return ldexp(real(hi), 52) + lo;
}
static const Math::real* rawC4coeff();
public: public:
/** /**
* Bit masks for what calculations to do. These masks do double duty. * Bit masks for what calculations to do. These masks do double duty.
* They signify to the GeodesicLineExact::GeodesicLineExact constructor and * They signify to the GeodesicLineExact::GeodesicLineExact constructor and
* to GeodesicExact::Line what capabilities should be included in the * to GeodesicExact::Line what capabilities should be included in the
* GeodesicLineExact object. They also specify which results to return in * GeodesicLineExact object. They also specify which results to return in
* the general routines GeodesicExact::GenDirect and * the general routines GeodesicExact::GenDirect and
* GeodesicExact::GenInverse routines. GeodesicLineExact::mask is a * GeodesicExact::GenInverse routines. GeodesicLineExact::mask is a
skipping to change at line 235 skipping to change at line 236
}; };
/** \name Constructor /** \name Constructor
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* Constructor for a ellipsoid with * Constructor for a ellipsoid with
* *
* @param[in] a equatorial radius (meters). * @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f. * @exception GeographicErr if \e a or (1 &minus; \e f) \e a is not
* @exception GeographicErr if \e a or (1 &minus; \e f ) \e a is not
* positive. * positive.
********************************************************************** / ********************************************************************** /
GeodesicExact(real a, real f); GeodesicExact(real a, real f);
///@} ///@}
/** \name Direct geodesic problem specified in terms of distance. /** \name Direct geodesic problem specified in terms of distance.
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* Perform the direct geodesic calculation where the length of the geod esic * Perform the direct geodesic calculation where the length of the geod esic
skipping to change at line 770 skipping to change at line 771
Math::real InverseFlattening() const { return 1/_f; } Math::real InverseFlattening() const { return 1/_f; }
/// \endcond /// \endcond
/** /**
* @return total area of ellipsoid in meters<sup>2</sup>. The area of a * @return total area of ellipsoid in meters<sup>2</sup>. The area of a
* polygon encircling a pole can be found by adding * polygon encircling a pole can be found by adding
* GeodesicExact::EllipsoidArea()/2 to the sum of \e S12 for each sid e of * GeodesicExact::EllipsoidArea()/2 to the sum of \e S12 for each sid e of
* the polygon. * the polygon.
********************************************************************** / ********************************************************************** /
Math::real EllipsoidArea() const Math::real EllipsoidArea() const
{ return 4 * Math::pi<real>() * _c2; } { return 4 * Math::pi() * _c2; }
///@} ///@}
/** /**
* A global instantiation of GeodesicExact with the parameters for the WGS84 * A global instantiation of GeodesicExact with the parameters for the WGS84
* ellipsoid. * ellipsoid.
********************************************************************** / ********************************************************************** /
static const GeodesicExact WGS84; static const GeodesicExact& WGS84();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_GEODESICEXACT_HPP #endif // GEOGRAPHICLIB_GEODESICEXACT_HPP
 End of changes. 12 change blocks. 
28 lines changed or deleted 29 lines changed or added


 GeodesicLine.hpp   GeodesicLine.hpp 
skipping to change at line 69 skipping to change at line 69
class GEOGRAPHICLIB_EXPORT GeodesicLine { class GEOGRAPHICLIB_EXPORT GeodesicLine {
private: private:
typedef Math::real real; typedef Math::real real;
friend class Geodesic; friend class Geodesic;
static const int nC1_ = Geodesic::nC1_; static const int nC1_ = Geodesic::nC1_;
static const int nC1p_ = Geodesic::nC1p_; static const int nC1p_ = Geodesic::nC1p_;
static const int nC2_ = Geodesic::nC2_; static const int nC2_ = Geodesic::nC2_;
static const int nC3_ = Geodesic::nC3_; static const int nC3_ = Geodesic::nC3_;
static const int nC4_ = Geodesic::nC4_; static const int nC4_ = Geodesic::nC4_;
real tiny_;
real _lat1, _lon1, _azi1; real _lat1, _lon1, _azi1;
real _a, _f, _b, _c2, _f1, _salp0, _calp0, _k2, real _a, _f, _b, _c2, _f1, _salp0, _calp0, _k2,
_salp1, _calp1, _ssig1, _csig1, _dn1, _stau1, _ctau1, _somg1, _comg1, _salp1, _calp1, _ssig1, _csig1, _dn1, _stau1, _ctau1, _somg1, _comg1,
_A1m1, _A2m1, _A3c, _B11, _B21, _B31, _A4, _B41; _A1m1, _A2m1, _A3c, _B11, _B21, _B31, _A4, _B41;
// index zero elements of _C1a, _C1pa, _C2a, _C3a are unused // index zero elements of _C1a, _C1pa, _C2a, _C3a are unused
real _C1a[nC1_ + 1], _C1pa[nC1p_ + 1], _C2a[nC2_ + 1], _C3a[nC3_], real _C1a[nC1_ + 1], _C1pa[nC1p_ + 1], _C2a[nC2_ + 1], _C3a[nC3_],
_C4a[nC4_]; // all the elements of _C4a are used _C4a[nC4_]; // all the elements of _C4a are used
unsigned _caps; unsigned _caps;
enum captype { enum captype {
skipping to change at line 197 skipping to change at line 198
* length can only be specified in terms of arc length; * length can only be specified in terms of arc length;
* - \e caps |= GeodesicLine::ALL for all of the above. * - \e caps |= GeodesicLine::ALL for all of the above.
* . * .
* The default value of \e caps is GeodesicLine::ALL. * The default value of \e caps is GeodesicLine::ALL.
* *
* If the point is at a pole, the azimuth is defined by keeping \e lon1 * If the point is at a pole, the azimuth is defined by keeping \e lon1
* fixed, writing \e lat1 = &plusmn;(90&deg; &minus; &epsilon;), and ta king * fixed, writing \e lat1 = &plusmn;(90&deg; &minus; &epsilon;), and ta king
* the limit &epsilon; &rarr; 0+. * the limit &epsilon; &rarr; 0+.
********************************************************************** / ********************************************************************** /
GeodesicLine(const Geodesic& g, real lat1, real lon1, real azi1, GeodesicLine(const Geodesic& g, real lat1, real lon1, real azi1,
unsigned caps = ALL) unsigned caps = ALL);
;
/** /**
* A default constructor. If GeodesicLine::Position is called on the * A default constructor. If GeodesicLine::Position is called on the
* resulting object, it returns immediately (without doing any * resulting object, it returns immediately (without doing any
* calculations). The object can be set with a call to Geodesic::Line. * calculations). The object can be set with a call to Geodesic::Line.
* Use Init() to test whether object is still in this uninitialized sta te. * Use Init() to test whether object is still in this uninitialized sta te.
********************************************************************** / ********************************************************************** /
GeodesicLine() : _caps(0U) {} GeodesicLine() : _caps(0U) {}
///@} ///@}
skipping to change at line 523 skipping to change at line 523
/** /**
* @return true if the object has been initialized. * @return true if the object has been initialized.
********************************************************************** / ********************************************************************** /
bool Init() const { return _caps != 0U; } bool Init() const { return _caps != 0U; }
/** /**
* @return \e lat1 the latitude of point 1 (degrees). * @return \e lat1 the latitude of point 1 (degrees).
********************************************************************** / ********************************************************************** /
Math::real Latitude() const Math::real Latitude() const
{ return Init() ? _lat1 : Math::NaN<real>(); } { return Init() ? _lat1 : Math::NaN(); }
/** /**
* @return \e lon1 the longitude of point 1 (degrees). * @return \e lon1 the longitude of point 1 (degrees).
********************************************************************** / ********************************************************************** /
Math::real Longitude() const Math::real Longitude() const
{ return Init() ? _lon1 : Math::NaN<real>(); } { return Init() ? _lon1 : Math::NaN(); }
/** /**
* @return \e azi1 the azimuth (degrees) of the geodesic line at point 1. * @return \e azi1 the azimuth (degrees) of the geodesic line at point 1.
********************************************************************** / ********************************************************************** /
Math::real Azimuth() const Math::real Azimuth() const
{ return Init() ? _azi1 : Math::NaN<real>(); } { return Init() ? _azi1 : Math::NaN(); }
/** /**
* @return \e azi0 the azimuth (degrees) of the geodesic line as it cro sses * @return \e azi0 the azimuth (degrees) of the geodesic line as it cro sses
* the equator in a northward direction. * the equator in a northward direction.
********************************************************************** / ********************************************************************** /
Math::real EquatorialAzimuth() const { Math::real EquatorialAzimuth() const {
using std::atan2;
return Init() ? return Init() ?
atan2(_salp0, _calp0) / Math::degree<real>() : Math::NaN<real>(); atan2(_salp0, _calp0) / Math::degree() : Math::NaN();
} }
/** /**
* @return \e a1 the arc length (degrees) between the northward equator ial * @return \e a1 the arc length (degrees) between the northward equator ial
* crossing and point 1. * crossing and point 1.
********************************************************************** / ********************************************************************** /
Math::real EquatorialArc() const { Math::real EquatorialArc() const {
using std::atan2;
return Init() ? return Init() ?
atan2(_ssig1, _csig1) / Math::degree<real>() : Math::NaN<real>(); atan2(_ssig1, _csig1) / Math::degree() : Math::NaN();
} }
/** /**
* @return \e a the equatorial radius of the ellipsoid (meters). This is * @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the Geodesic object used in the construct or. * the value inherited from the Geodesic object used in the construct or.
********************************************************************** / ********************************************************************** /
Math::real MajorRadius() const Math::real MajorRadius() const
{ return Init() ? _a : Math::NaN<real>(); } { return Init() ? _a : Math::NaN(); }
/** /**
* @return \e f the flattening of the ellipsoid. This is the value * @return \e f the flattening of the ellipsoid. This is the value
* inherited from the Geodesic object used in the constructor. * inherited from the Geodesic object used in the constructor.
********************************************************************** / ********************************************************************** /
Math::real Flattening() const Math::real Flattening() const
{ return Init() ? _f : Math::NaN<real>(); } { return Init() ? _f : Math::NaN(); }
/// \cond SKIP /// \cond SKIP
/** /**
* <b>DEPRECATED</b> * <b>DEPRECATED</b>
* @return \e r the inverse flattening of the ellipsoid. * @return \e r the inverse flattening of the ellipsoid.
********************************************************************** / ********************************************************************** /
Math::real InverseFlattening() const Math::real InverseFlattening() const
{ return Init() ? 1/_f : Math::NaN<real>(); } { return Init() ? 1/_f : Math::NaN(); }
/// \endcond /// \endcond
/** /**
* @return \e caps the computational capabilities that this object was * @return \e caps the computational capabilities that this object was
* constructed with. LATITUDE and AZIMUTH are always included. * constructed with. LATITUDE and AZIMUTH are always included.
********************************************************************** / ********************************************************************** /
unsigned Capabilities() const { return _caps; } unsigned Capabilities() const { return _caps; }
/** /**
* @param[in] testcaps a set of bitor'ed GeodesicLine::mask values. * @param[in] testcaps a set of bitor'ed GeodesicLine::mask values.
 End of changes. 12 change blocks. 
10 lines changed or deleted 12 lines changed or added


 GeodesicLineExact.hpp   GeodesicLineExact.hpp 
skipping to change at line 41 skipping to change at line 41
* providing access to the functionality of GeodesicExact and * providing access to the functionality of GeodesicExact and
* GeodesicLineExact (via the -E option). * GeodesicLineExact (via the -E option).
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT GeodesicLineExact { class GEOGRAPHICLIB_EXPORT GeodesicLineExact {
private: private:
typedef Math::real real; typedef Math::real real;
friend class GeodesicExact; friend class GeodesicExact;
static const int nC4_ = GeodesicExact::nC4_; static const int nC4_ = GeodesicExact::nC4_;
real tiny_;
real _lat1, _lon1, _azi1; real _lat1, _lon1, _azi1;
real _a, _f, _b, _c2, _f1, _e2, _salp0, _calp0, _k2, real _a, _f, _b, _c2, _f1, _e2, _salp0, _calp0, _k2,
_salp1, _calp1, _ssig1, _csig1, _dn1, _stau1, _ctau1, _salp1, _calp1, _ssig1, _csig1, _dn1, _stau1, _ctau1,
_somg1, _comg1, _cchi1, _somg1, _comg1, _cchi1,
_A4, _B41, _E0, _D0, _H0, _E1, _D1, _H1; _A4, _B41, _E0, _D0, _H0, _E1, _D1, _H1;
real _C4a[nC4_]; // all the elements of _C4a are used real _C4a[nC4_]; // all the elements of _C4a are used
EllipticFunction _E; EllipticFunction _E;
unsigned _caps; unsigned _caps;
enum captype { enum captype {
skipping to change at line 170 skipping to change at line 171
* length can only be specified in terms of arc length; * length can only be specified in terms of arc length;
* - \e caps |= GeodesicLineExact::ALL for all of the above. * - \e caps |= GeodesicLineExact::ALL for all of the above.
* . * .
* The default value of \e caps is GeodesicLineExact::ALL. * The default value of \e caps is GeodesicLineExact::ALL.
* *
* If the point is at a pole, the azimuth is defined by keeping \e lon1 * If the point is at a pole, the azimuth is defined by keeping \e lon1
* fixed, writing \e lat1 = &plusmn;(90&deg; &minus; &epsilon;), and ta king * fixed, writing \e lat1 = &plusmn;(90&deg; &minus; &epsilon;), and ta king
* the limit &epsilon; &rarr; 0+. * the limit &epsilon; &rarr; 0+.
********************************************************************** / ********************************************************************** /
GeodesicLineExact(const GeodesicExact& g, real lat1, real lon1, real az i1, GeodesicLineExact(const GeodesicExact& g, real lat1, real lon1, real az i1,
unsigned caps = ALL) unsigned caps = ALL);
;
/** /**
* A default constructor. If GeodesicLineExact::Position is called on the * A default constructor. If GeodesicLineExact::Position is called on the
* resulting object, it returns immediately (without doing any * resulting object, it returns immediately (without doing any
* calculations). The object can be set with a call to * calculations). The object can be set with a call to
* GeodesicExact::Line. Use Init() to test whether object is still in this * GeodesicExact::Line. Use Init() to test whether object is still in this
* uninitialized state. * uninitialized state.
********************************************************************** / ********************************************************************** /
GeodesicLineExact() : _caps(0U) {} GeodesicLineExact() : _caps(0U) {}
///@} ///@}
skipping to change at line 497 skipping to change at line 497
/** /**
* @return true if the object has been initialized. * @return true if the object has been initialized.
********************************************************************** / ********************************************************************** /
bool Init() const { return _caps != 0U; } bool Init() const { return _caps != 0U; }
/** /**
* @return \e lat1 the latitude of point 1 (degrees). * @return \e lat1 the latitude of point 1 (degrees).
********************************************************************** / ********************************************************************** /
Math::real Latitude() const Math::real Latitude() const
{ return Init() ? _lat1 : Math::NaN<real>(); } { return Init() ? _lat1 : Math::NaN(); }
/** /**
* @return \e lon1 the longitude of point 1 (degrees). * @return \e lon1 the longitude of point 1 (degrees).
********************************************************************** / ********************************************************************** /
Math::real Longitude() const Math::real Longitude() const
{ return Init() ? _lon1 : Math::NaN<real>(); } { return Init() ? _lon1 : Math::NaN(); }
/** /**
* @return \e azi1 the azimuth (degrees) of the geodesic line at point 1. * @return \e azi1 the azimuth (degrees) of the geodesic line at point 1.
********************************************************************** / ********************************************************************** /
Math::real Azimuth() const Math::real Azimuth() const
{ return Init() ? _azi1 : Math::NaN<real>(); } { return Init() ? _azi1 : Math::NaN(); }
/** /**
* @return \e azi0 the azimuth (degrees) of the geodesic line as it cro sses * @return \e azi0 the azimuth (degrees) of the geodesic line as it cro sses
* the equator in a northward direction. * the equator in a northward direction.
********************************************************************** / ********************************************************************** /
Math::real EquatorialAzimuth() const { Math::real EquatorialAzimuth() const {
using std::atan2;
return Init() ? return Init() ?
atan2(_salp0, _calp0) / Math::degree<real>() : Math::NaN<real>(); atan2(_salp0, _calp0) / Math::degree() : Math::NaN();
} }
/** /**
* @return \e a1 the arc length (degrees) between the northward equator ial * @return \e a1 the arc length (degrees) between the northward equator ial
* crossing and point 1. * crossing and point 1.
********************************************************************** / ********************************************************************** /
Math::real EquatorialArc() const { Math::real EquatorialArc() const {
using std::atan2;
return Init() ? return Init() ?
atan2(_ssig1, _csig1) / Math::degree<real>() : Math::NaN<real>(); atan2(_ssig1, _csig1) / Math::degree() : Math::NaN();
} }
/** /**
* @return \e a the equatorial radius of the ellipsoid (meters). This is * @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the GeodesicExact object used in the * the value inherited from the GeodesicExact object used in the
* constructor. * constructor.
********************************************************************** / ********************************************************************** /
Math::real MajorRadius() const Math::real MajorRadius() const
{ return Init() ? _a : Math::NaN<real>(); } { return Init() ? _a : Math::NaN(); }
/** /**
* @return \e f the flattening of the ellipsoid. This is the value * @return \e f the flattening of the ellipsoid. This is the value
* inherited from the GeodesicExact object used in the constructor. * inherited from the GeodesicExact object used in the constructor.
********************************************************************** / ********************************************************************** /
Math::real Flattening() const Math::real Flattening() const
{ return Init() ? _f : Math::NaN<real>(); } { return Init() ? _f : Math::NaN(); }
/// \cond SKIP /// \cond SKIP
/** /**
* <b>DEPRECATED</b> * <b>DEPRECATED</b>
* @return \e r the inverse flattening of the ellipsoid. * @return \e r the inverse flattening of the ellipsoid.
********************************************************************** / ********************************************************************** /
Math::real InverseFlattening() const Math::real InverseFlattening() const
{ return Init() ? 1/_f : Math::NaN<real>(); } { return Init() ? 1/_f : Math::NaN(); }
/// \endcond /// \endcond
/** /**
* @return \e caps the computational capabilities that this object was * @return \e caps the computational capabilities that this object was
* constructed with. LATITUDE and AZIMUTH are always included. * constructed with. LATITUDE and AZIMUTH are always included.
********************************************************************** / ********************************************************************** /
unsigned Capabilities() const { return _caps; } unsigned Capabilities() const { return _caps; }
/** /**
* @param[in] testcaps a set of bitor'ed GeodesicLineExact::mask values . * @param[in] testcaps a set of bitor'ed GeodesicLineExact::mask values .
 End of changes. 12 change blocks. 
10 lines changed or deleted 12 lines changed or added


 Geohash.hpp   Geohash.hpp 
skipping to change at line 45 skipping to change at line 45
* Example of use: * Example of use:
* \include example-Geohash.cpp * \include example-Geohash.cpp
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT Geohash { class GEOGRAPHICLIB_EXPORT Geohash {
private: private:
typedef Math::real real; typedef Math::real real;
static const int maxlen_ = 18; static const int maxlen_ = 18;
static const unsigned long long mask_ = 1ULL << 45; static const unsigned long long mask_ = 1ULL << 45;
static const int decprec_[]; static const int decprec_[];
static const real loneps_; static inline real shift() {
using std::pow; static const real shift = pow(real(2), 45);
return shift;
}
static inline real loneps() {
static const real loneps = 180 / shift();
return loneps;
}
static inline real lateps() {
static const real lateps = 90 / shift();
return lateps;
}
static const real lateps_; static const real lateps_;
static const real shift_;
static const std::string lcdigits_; static const std::string lcdigits_;
static const std::string ucdigits_; static const std::string ucdigits_;
Geohash(); // Disable constructor Geohash(); // Disable constructor
public: public:
/** /**
* Convert from geographic coordinates to a geohash. * Convert from geographic coordinates to a geohash.
* *
* @param[in] lat latitude of point (degrees). * @param[in] lat latitude of point (degrees).
skipping to change at line 129 skipping to change at line 139
/** /**
* The geohash length required to meet a given geographic resolution. * The geohash length required to meet a given geographic resolution.
* *
* @param[in] res the minimum of resolution in latitude and longitude * @param[in] res the minimum of resolution in latitude and longitude
* (degrees). * (degrees).
* @return geohash length. * @return geohash length.
* *
* The returned length is in the range [0, 18]. * The returned length is in the range [0, 18].
********************************************************************** / ********************************************************************** /
static int GeohashLength(real res) { static int GeohashLength(real res) {
res = std::abs(res); using std::abs;
res = abs(res);
for (int len = 0; len < maxlen_; ++len) for (int len = 0; len < maxlen_; ++len)
if (LongitudeResolution(len) <= res) if (LongitudeResolution(len) <= res)
return len; return len;
return maxlen_; return maxlen_;
} }
/** /**
* The geohash length required to meet a given geographic resolution. * The geohash length required to meet a given geographic resolution.
* *
* @param[in] latres the resolution in latitude (degrees). * @param[in] latres the resolution in latitude (degrees).
* @param[in] lonres the resolution in longitude (degrees). * @param[in] lonres the resolution in longitude (degrees).
* @return geohash length. * @return geohash length.
* *
* The returned length is in the range [0, 18]. * The returned length is in the range [0, 18].
********************************************************************** / ********************************************************************** /
static int GeohashLength(real latres, real lonres) { static int GeohashLength(real latres, real lonres) {
latres = std::abs(latres); using std::abs;
lonres = std::abs(lonres); latres = abs(latres);
lonres = abs(lonres);
for (int len = 0; len < maxlen_; ++len) for (int len = 0; len < maxlen_; ++len)
if (LatitudeResolution(len) <= latres && if (LatitudeResolution(len) <= latres &&
LongitudeResolution(len) <= lonres) LongitudeResolution(len) <= lonres)
return len; return len;
return maxlen_; return maxlen_;
} }
/** /**
* The decimal geographic precision required to match a given geohash * The decimal geographic precision required to match a given geohash
* length. This is the number of digits needed after decimal point in a * length. This is the number of digits needed after decimal point in a
* decimal degrees representation. * decimal degrees representation.
* *
* @param[in] len the length of the geohash. * @param[in] len the length of the geohash.
* @return the decimal precision (may be negative). * @return the decimal precision (may be negative).
* *
* Internally, \e len is first put in the range [0, 18]. The returned * Internally, \e len is first put in the range [0, 18]. The returned
* decimal precision is in the range [&minus;2, 12]. * decimal precision is in the range [&minus;2, 12].
********************************************************************** / ********************************************************************** /
static int DecimalPrecision(int len) { static int DecimalPrecision(int len) {
return -int(std::floor(std::log(LatitudeResolution(len))/ using std::floor; using std::log;
std::log(Math::real(10)))); return -int(floor(log(LatitudeResolution(len))/log(Math::real(10))));
} }
}; };
} // namespace GeographicLib } // namespace GeographicLib
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning (pop) # pragma warning (pop)
#endif #endif
 End of changes. 5 change blocks. 
7 lines changed or deleted 19 lines changed or added


 Geoid.hpp   Geoid.hpp 
skipping to change at line 23 skipping to change at line 23
#include <vector> #include <vector>
#include <fstream> #include <fstream>
#include <GeographicLib/Constants.hpp> #include <GeographicLib/Constants.hpp>
#if defined(_MSC_VER) #if defined(_MSC_VER)
// Squelch warnings about dll vs vector and constant conditional expression s // Squelch warnings about dll vs vector and constant conditional expression s
# pragma warning (push) # pragma warning (push)
# pragma warning (disable: 4251 4127) # pragma warning (disable: 4251 4127)
#endif #endif
#if !defined(PGM_PIXEL_WIDTH) #if !defined(GEOGRAPHICLIB_GEOID_PGM_PIXEL_WIDTH)
/** /**
* The size of the pixel data in the pgm data files for the geoids. 2 is t he * The size of the pixel data in the pgm data files for the geoids. 2 is t he
* standard size corresponding to a maxval 2<sup>16</sup>&minus;1. Setting it * standard size corresponding to a maxval 2<sup>16</sup>&minus;1. Setting it
* to 4 uses a maxval of 2<sup>32</sup>&minus;1 and changes the extension f or * to 4 uses a maxval of 2<sup>32</sup>&minus;1 and changes the extension f or
* the data files from .pgm to .pgm4. Note that the format of these pgm4 f iles * the data files from .pgm to .pgm4. Note that the format of these pgm4 f iles
* is a non-standard extension of the pgm format. * is a non-standard extension of the pgm format.
**********************************************************************/ **********************************************************************/
# define PGM_PIXEL_WIDTH 2 # define GEOGRAPHICLIB_GEOID_PGM_PIXEL_WIDTH 2
#endif #endif
namespace GeographicLib { namespace GeographicLib {
/** /**
* \brief Looking up the height of the geoid * \brief Looking up the height of the geoid
* *
* This class evaluated the height of one of the standard geoids, EGM84, * This class evaluated the height of one of the standard geoids, EGM84,
* EGM96, or EGM2008 by bilinear or cubic interpolation into a rectangula r * EGM96, or EGM2008 by bilinear or cubic interpolation into a rectangula r
* grid of data. These geoid models are documented in * grid of data. These geoid models are documented in
skipping to change at line 86 skipping to change at line 86
* Example of use: * Example of use:
* \include example-Geoid.cpp * \include example-Geoid.cpp
* *
* <a href="GeoidEval.1.html">GeoidEval</a> is a command-line utility * <a href="GeoidEval.1.html">GeoidEval</a> is a command-line utility
* providing access to the functionality of Geoid. * providing access to the functionality of Geoid.
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT Geoid { class GEOGRAPHICLIB_EXPORT Geoid {
private: private:
typedef Math::real real; typedef Math::real real;
#if PGM_PIXEL_WIDTH != 4 #if GEOGRAPHICLIB_GEOID_PGM_PIXEL_WIDTH != 4
typedef unsigned short pixel_t; typedef unsigned short pixel_t;
static const unsigned pixel_size_ = 2; static const unsigned pixel_size_ = 2;
static const unsigned pixel_max_ = 0xffffu; static const unsigned pixel_max_ = 0xffffu;
#else #else
typedef unsigned pixel_t; typedef unsigned pixel_t;
static const unsigned pixel_size_ = 4; static const unsigned pixel_size_ = 4;
static const unsigned pixel_max_ = 0xffffffffu; static const unsigned pixel_max_ = 0xffffffffu;
#endif #endif
static const unsigned stencilsize_ = 12; static const unsigned stencilsize_ = 12;
static const unsigned nterms_ = ((3 + 1) * (3 + 2))/2; // for a cubic f it static const unsigned nterms_ = ((3 + 1) * (3 + 2))/2; // for a cubic f it
static const real c0_; static const int c0_;
static const real c0n_; static const int c0n_;
static const real c0s_; static const int c0s_;
static const real c3_[stencilsize_ * nterms_]; static const int c3_[stencilsize_ * nterms_];
static const real c3n_[stencilsize_ * nterms_]; static const int c3n_[stencilsize_ * nterms_];
static const real c3s_[stencilsize_ * nterms_]; static const int c3s_[stencilsize_ * nterms_];
std::string _name, _dir, _filename; std::string _name, _dir, _filename;
const bool _cubic; const bool _cubic;
const real _a, _e2, _degree, _eps; const real _a, _e2, _degree, _eps;
mutable std::ifstream _file; mutable std::ifstream _file;
real _rlonres, _rlatres; real _rlonres, _rlatres;
std::string _description, _datetime; std::string _description, _datetime;
real _offset, _scale, _maxerror, _rmserror; real _offset, _scale, _maxerror, _rmserror;
int _width, _height; int _width, _height;
unsigned long long _datastart, _swidth; unsigned long long _datastart, _swidth;
skipping to change at line 460 skipping to change at line 460
return _cache ? 90 - ( _yoffset + _ysize - 1 - _cubic) / _rlatres : 0 ; return _cache ? 90 - ( _yoffset + _ysize - 1 - _cubic) / _rlatres : 0 ;
} }
/** /**
* @return \e a the equatorial radius of the WGS84 ellipsoid (meters). * @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
* *
* (The WGS84 value is returned because the supported geoid models are all * (The WGS84 value is returned because the supported geoid models are all
* based on this ellipsoid.) * based on this ellipsoid.)
********************************************************************** / ********************************************************************** /
Math::real MajorRadius() const Math::real MajorRadius() const
{ return Constants::WGS84_a<real>(); } { return Constants::WGS84_a(); }
/** /**
* @return \e f the flattening of the WGS84 ellipsoid. * @return \e f the flattening of the WGS84 ellipsoid.
* *
* (The WGS84 value is returned because the supported geoid models are all * (The WGS84 value is returned because the supported geoid models are all
* based on this ellipsoid.) * based on this ellipsoid.)
********************************************************************** / ********************************************************************** /
Math::real Flattening() const { return Constants::WGS84_f<real>(); } Math::real Flattening() const { return Constants::WGS84_f(); }
///@} ///@}
/// \cond SKIP /// \cond SKIP
/** /**
* <b>DEPRECATED</b> * <b>DEPRECATED</b>
* @return \e r the inverse flattening of the WGS84 ellipsoid. * @return \e r the inverse flattening of the WGS84 ellipsoid.
********************************************************************** / ********************************************************************** /
Math::real InverseFlattening() const Math::real InverseFlattening() const
{ return 1/Constants::WGS84_f<real>(); } { return 1/Constants::WGS84_f(); }
/// \endcond /// \endcond
/** /**
* @return the default path for geoid data files. * @return the default path for geoid data files.
* *
* This is the value of the environment variable GEOID_PATH, if set; * This is the value of the environment variable GEOGRAPHICLIB_GEOID_PA
* otherwise, it is $GEOGRAPHICLIB_DATA/geoids if the environment varia TH,
ble * if set; otherwise, it is $GEOGRAPHICLIB_DATA/geoids if the environme
* GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default nt
* (/usr/local/share/GeographicLib/geoids on non-Windows systems and * variable GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time
* C:/Documents and Settings/All Users/Application * default (/usr/local/share/GeographicLib/geoids on non-Windows system
* Data/GeographicLib/geoids on Windows systems). s
* and C:/ProgramData/GeographicLib/geoids on Windows systems).
********************************************************************** / ********************************************************************** /
static std::string DefaultGeoidPath(); static std::string DefaultGeoidPath();
/** /**
* @return the default name for the geoid. * @return the default name for the geoid.
* *
* This is the value of the environment variable GEOID_NAME, if set, * This is the value of the environment variable GEOGRAPHICLIB_GEOID_NA
* otherwise, it is "egm96-5". The Geoid class does not use this funct ME,
ion; * if set; otherwise, it is "egm96-5". The Geoid class does not use th
* it is just provided as a convenience for a calling program when is
* constructing a Geoid object. * function; it is just provided as a convenience for a calling program
* when constructing a Geoid object.
********************************************************************** / ********************************************************************** /
static std::string DefaultGeoidName(); static std::string DefaultGeoidName();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning (pop) # pragma warning (pop)
#endif #endif
 End of changes. 9 change blocks. 
24 lines changed or deleted 26 lines changed or added


 Gnomonic.hpp   Gnomonic.hpp 
skipping to change at line 69 skipping to change at line 69
* *
* This result applies for any surface. For an ellipsoid of revolution, * This result applies for any surface. For an ellipsoid of revolution,
* consider all geodesics whose end points are within a distance \e r of \e * consider all geodesics whose end points are within a distance \e r of \e
* C. For a given \e r, the deviation is maximum when the latitude of \e C * C. For a given \e r, the deviation is maximum when the latitude of \e C
* is 45&deg;, when endpoints are a distance \e r away, and when their * is 45&deg;, when endpoints are a distance \e r away, and when their
* azimuths from the center are &plusmn; 45&deg; or &plusmn; 135&deg;. * azimuths from the center are &plusmn; 45&deg; or &plusmn; 135&deg;.
* To lowest order in \e r and the flattening \e f, the deviation is \e f * To lowest order in \e r and the flattening \e f, the deviation is \e f
* (<i>r</i>/2<i>a</i>)<sup>3</sup> \e r. * (<i>r</i>/2<i>a</i>)<sup>3</sup> \e r.
* *
* The conversions all take place using a Geodesic object (by default * The conversions all take place using a Geodesic object (by default
* Geodesic::WGS84). For more information on geodesics see \ref geodesic . * Geodesic::WGS84()). For more information on geodesics see \ref geodes ic.
* *
* <b>CAUTION:</b> The definition of this projection for a sphere is * <b>CAUTION:</b> The definition of this projection for a sphere is
* standard. However, there is no standard for how it should be extended to * standard. However, there is no standard for how it should be extended to
* an ellipsoid. The choices are: * an ellipsoid. The choices are:
* - Declare that the projection is undefined for an ellipsoid. * - Declare that the projection is undefined for an ellipsoid.
* - Project to a tangent plane from the center of the ellipsoid. This * - Project to a tangent plane from the center of the ellipsoid. This
* causes great ellipses to appear as straight lines in the projection; * causes great ellipses to appear as straight lines in the projection;
* i.e., it generalizes the spherical great circle to a great ellipse. * i.e., it generalizes the spherical great circle to a great ellipse.
* This was proposed by independently by Bowring and Williams in 1997. * This was proposed by independently by Bowring and Williams in 1997.
* - Project to the conformal sphere with the constant of integration cho sen * - Project to the conformal sphere with the constant of integration cho sen
skipping to change at line 104 skipping to change at line 104
* \include example-Gnomonic.cpp * \include example-Gnomonic.cpp
* *
* <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utili ty * <a href="GeodesicProj.1.html">GeodesicProj</a> is a command-line utili ty
* providing access to the functionality of AzimuthalEquidistant, Gnomoni c, * providing access to the functionality of AzimuthalEquidistant, Gnomoni c,
* and CassiniSoldner. * and CassiniSoldner.
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT Gnomonic { class GEOGRAPHICLIB_EXPORT Gnomonic {
private: private:
typedef Math::real real; typedef Math::real real;
real eps0_, eps_;
Geodesic _earth; Geodesic _earth;
real _a, _f; real _a, _f;
static const real eps0_;
static const real eps_;
static const int numit_ = 10; static const int numit_ = 10;
public: public:
/** /**
* Constructor for Gnomonic. * Constructor for Gnomonic.
* *
* @param[in] earth the Geodesic object to use for geodesic calculation s. * @param[in] earth the Geodesic object to use for geodesic calculation s.
* By default this uses the WGS84 ellipsoid. * By default this uses the WGS84 ellipsoid.
********************************************************************** / ********************************************************************** /
explicit Gnomonic(const Geodesic& earth = Geodesic::WGS84) explicit Gnomonic(const Geodesic& earth = Geodesic::WGS84());
: _earth(earth)
, _a(_earth.MajorRadius())
, _f(_earth.Flattening())
{}
/** /**
* Forward projection, from geographic to gnomonic. * Forward projection, from geographic to gnomonic.
* *
* @param[in] lat0 latitude of center point of projection (degrees). * @param[in] lat0 latitude of center point of projection (degrees).
* @param[in] lon0 longitude of center point of projection (degrees). * @param[in] lon0 longitude of center point of projection (degrees).
* @param[in] lat latitude of point (degrees). * @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees). * @param[in] lon longitude of point (degrees).
* @param[out] x easting of point (meters). * @param[out] x easting of point (meters).
* @param[out] y northing of point (meters). * @param[out] y northing of point (meters).
skipping to change at line 164 skipping to change at line 159
* @param[in] y northing of point (meters). * @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees). * @param[out] lat latitude of point (degrees).
* @param[out] lon longitude of point (degrees). * @param[out] lon longitude of point (degrees).
* @param[out] azi azimuth of geodesic at point (degrees). * @param[out] azi azimuth of geodesic at point (degrees).
* @param[out] rk reciprocal of azimuthal scale at point. * @param[out] rk reciprocal of azimuthal scale at point.
* *
* \e lat0 should be in the range [&minus;90&deg;, 90&deg;] and \e * \e lat0 should be in the range [&minus;90&deg;, 90&deg;] and \e
* lon0 should be in the range [&minus;540&deg;, 540&deg;). \e lat * lon0 should be in the range [&minus;540&deg;, 540&deg;). \e lat
* will be in the range [&minus;90&deg;, 90&deg;] and \e lon will * will be in the range [&minus;90&deg;, 90&deg;] and \e lon will
* be in the range [&minus;180&deg;, 180&deg;). The scale of the * be in the range [&minus;180&deg;, 180&deg;). The scale of the
* projection is 1/\e rk<sup>2</sup> in the "radial" direction, \e azi * projection is 1/<i>rk</i><sup>2</sup> in the "radial" direction, \e azi
* clockwise from true north, and is 1/\e rk in the direction perpendic ular * clockwise from true north, and is 1/\e rk in the direction perpendic ular
* to this. Even though all inputs should return a valid \e lat and \e * to this. Even though all inputs should return a valid \e lat and \e
* lon, it's possible that the procedure fails to converge for very lar ge * lon, it's possible that the procedure fails to converge for very lar ge
* \e x or \e y; in this case NaNs are returned for all the output * \e x or \e y; in this case NaNs are returned for all the output
* arguments. A call to Reverse followed by a call to Forward will ret urn * arguments. A call to Reverse followed by a call to Forward will ret urn
* the original (\e x, \e y) (to roundoff). * the original (\e x, \e y) (to roundoff).
********************************************************************** / ********************************************************************** /
void Reverse(real lat0, real lon0, real x, real y, void Reverse(real lat0, real lon0, real x, real y,
real& lat, real& lon, real& azi, real& rk) const; real& lat, real& lon, real& azi, real& rk) const;
 End of changes. 5 change blocks. 
9 lines changed or deleted 4 lines changed or added


 GravityCircle.hpp   GravityCircle.hpp 
skipping to change at line 262 skipping to change at line 262
* @return true if the object has been initialized. * @return true if the object has been initialized.
********************************************************************** / ********************************************************************** /
bool Init() const { return _a > 0; } bool Init() const { return _a > 0; }
/** /**
* @return \e a the equatorial radius of the ellipsoid (meters). This is * @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the GravityModel object used in the * the value inherited from the GravityModel object used in the
* constructor. * constructor.
********************************************************************** / ********************************************************************** /
Math::real MajorRadius() const Math::real MajorRadius() const
{ return Init() ? _a : Math::NaN<real>(); } { return Init() ? _a : Math::NaN(); }
/** /**
* @return \e f the flattening of the ellipsoid. This is the value * @return \e f the flattening of the ellipsoid. This is the value
* inherited from the GravityModel object used in the constructor. * inherited from the GravityModel object used in the constructor.
********************************************************************** / ********************************************************************** /
Math::real Flattening() const Math::real Flattening() const
{ return Init() ? _f : Math::NaN<real>(); } { return Init() ? _f : Math::NaN(); }
/** /**
* @return the latitude of the circle (degrees). * @return the latitude of the circle (degrees).
********************************************************************** / ********************************************************************** /
Math::real Latitude() const Math::real Latitude() const
{ return Init() ? _lat : Math::NaN<real>(); } { return Init() ? _lat : Math::NaN(); }
/** /**
* @return the height of the circle (meters). * @return the height of the circle (meters).
********************************************************************** / ********************************************************************** /
Math::real Height() const Math::real Height() const
{ return Init() ? _h : Math::NaN<real>(); } { return Init() ? _h : Math::NaN(); }
/** /**
* @return \e caps the computational capabilities that this object was * @return \e caps the computational capabilities that this object was
* constructed with. * constructed with.
********************************************************************** / ********************************************************************** /
unsigned Capabilities() const { return _caps; } unsigned Capabilities() const { return _caps; }
/** /**
* @param[in] testcaps a set of bitor'ed GeodesicLine::mask values. * @param[in] testcaps a set of bitor'ed GeodesicLine::mask values.
* @return true if the GeodesicLine object has all these capabilities. * @return true if the GeodesicLine object has all these capabilities.
 End of changes. 4 change blocks. 
4 lines changed or deleted 4 lines changed or added


 GravityModel.hpp   GravityModel.hpp 
skipping to change at line 54 skipping to change at line 54
* - <i>V</i><sub>0</sub> = normal gravitation potential; * - <i>V</i><sub>0</sub> = normal gravitation potential;
* - \e U = <i>V</i><sub>0</sub> + &Phi; = total normal potential; * - \e U = <i>V</i><sub>0</sub> + &Phi; = total normal potential;
* - \e T = \e W &minus; \e U = \e V &minus; <i>V</i><sub>0</sub> = anoma lous * - \e T = \e W &minus; \e U = \e V &minus; <i>V</i><sub>0</sub> = anoma lous
* or disturbing potential; * or disturbing potential;
* - <b>g</b> = &nabla;\e W = <b>&gamma;</b> + <b>&delta;</b>; * - <b>g</b> = &nabla;\e W = <b>&gamma;</b> + <b>&delta;</b>;
* - <b>f</b> = &nabla;&Phi;; * - <b>f</b> = &nabla;&Phi;;
* - <b>&Gamma;</b> = &nabla;<i>V</i><sub>0</sub>; * - <b>&Gamma;</b> = &nabla;<i>V</i><sub>0</sub>;
* - <b>&gamma;</b> = &nabla;\e U; * - <b>&gamma;</b> = &nabla;\e U;
* - <b>&delta;</b> = &nabla;\e T = gravity disturbance vector * - <b>&delta;</b> = &nabla;\e T = gravity disturbance vector
* = <b>g</b><sub><i>P</i></sub> &minus; <b>&gamma;</b><sub><i>P</i></s ub>; * = <b>g</b><sub><i>P</i></sub> &minus; <b>&gamma;</b><sub><i>P</i></s ub>;
* - &delta;\e g = gravity disturbance = \e g<sub><i>P</i></sub> &minus; * - &delta;\e g = gravity disturbance = <i>g</i><sub><i>P</i></sub> &min us;
* &gamma;<sub><i>P</i></sub>; * &gamma;<sub><i>P</i></sub>;
* - &Delta;<b>g</b> = gravity anomaly vector = <b>g</b><sub><i>P</i></su b> * - &Delta;<b>g</b> = gravity anomaly vector = <b>g</b><sub><i>P</i></su b>
* &minus; <b>&gamma;</b><sub><i>Q</i></sub>; here the line \e PQ is * &minus; <b>&gamma;</b><sub><i>Q</i></sub>; here the line \e PQ is
* perpendicular to ellipsoid and the potential at \e P equals the norm al * perpendicular to ellipsoid and the potential at \e P equals the norm al
* potential at \e Q; * potential at \e Q;
* - &Delta;\e g = gravity anomaly = \e g<sub><i>P</i></sub> &minus; * - &Delta;\e g = gravity anomaly = <i>g</i><sub><i>P</i></sub> &minus;
* &gamma;<sub><i>Q</i></sub>; * &gamma;<sub><i>Q</i></sub>;
* - (&xi;, &eta;) deflection of the vertical, the difference in * - (&xi;, &eta;) deflection of the vertical, the difference in
* directions of <b>g</b><sub><i>P</i></sub> and * directions of <b>g</b><sub><i>P</i></sub> and
* <b>&gamma;</b><sub><i>Q</i></sub>, &xi; = NS, &eta; = EW. * <b>&gamma;</b><sub><i>Q</i></sub>, &xi; = NS, &eta; = EW.
* - \e X, \e Y, \e Z, geocentric coordinates; * - \e X, \e Y, \e Z, geocentric coordinates;
* - \e x, \e y, \e z, local cartesian coordinates used to denote the eas t, * - \e x, \e y, \e z, local cartesian coordinates used to denote the eas t,
* north and up directions. * north and up directions.
* *
* See \ref gravity for details of how to install the gravity model and t he * See \ref gravity for details of how to install the gravity model and t he
* data format. * data format.
skipping to change at line 493 skipping to change at line 493
/** /**
* @return \e f the flattening of the ellipsoid. * @return \e f the flattening of the ellipsoid.
********************************************************************** / ********************************************************************** /
Math::real Flattening() const { return _earth.Flattening(); } Math::real Flattening() const { return _earth.Flattening(); }
///@} ///@}
/** /**
* @return the default path for gravity model data files. * @return the default path for gravity model data files.
* *
* This is the value of the environment variable GRAVITY_PATH, if set; * This is the value of the environment variable
* otherwise, it is $GEOGRAPHICLIB_DATA/gravity if the environment vari * GEOGRAPHICLIB_GRAVITY_PATH, if set; otherwise, it is
able * $GEOGRAPHICLIB_DATA/gravity if the environment variable
* GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default * GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default
* (/usr/local/share/GeographicLib/gravity on non-Windows systems and * (/usr/local/share/GeographicLib/gravity on non-Windows systems and
* C:/Documents and Settings/All Users/Application * C:/ProgramData/GeographicLib/gravity on Windows systems).
* Data/GeographicLib/gravity on Windows systems).
********************************************************************** / ********************************************************************** /
static std::string DefaultGravityPath(); static std::string DefaultGravityPath();
/** /**
* @return the default name for the gravity model. * @return the default name for the gravity model.
* *
* This is the value of the environment variable GRAVITY_NAME, if set, * This is the value of the environment variable
* otherwise, it is "egm96". The GravityModel class does not use * GEOGRAPHICLIB_GRAVITY_NAME, if set; otherwise, it is "egm96". The
* this function; it is just provided as a convenience for a calling * GravityModel class does not use this function; it is just provided a
* program when constructing a GravityModel object. s a
* convenience for a calling program when constructing a GravityModel
* object.
********************************************************************** / ********************************************************************** /
static std::string DefaultGravityName(); static std::string DefaultGravityName();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning (pop) # pragma warning (pop)
#endif #endif
 End of changes. 5 change blocks. 
11 lines changed or deleted 12 lines changed or added


 LambertConformalConic.hpp   LambertConformalConic.hpp 
skipping to change at line 60 skipping to change at line 60
* EPSG:3364</a>) is obtained by: * EPSG:3364</a>) is obtained by:
* \include example-LambertConformalConic.cpp * \include example-LambertConformalConic.cpp
* *
* <a href="ConicProj.1.html">ConicProj</a> is a command-line utility * <a href="ConicProj.1.html">ConicProj</a> is a command-line utility
* providing access to the functionality of LambertConformalConic and * providing access to the functionality of LambertConformalConic and
* AlbersEqualArea. * AlbersEqualArea.
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT LambertConformalConic { class GEOGRAPHICLIB_EXPORT LambertConformalConic {
private: private:
typedef Math::real real; typedef Math::real real;
real eps_, epsx_, tol_, ahypover_;
real _a, _f, _fm, _e2, _e, _e2m; real _a, _f, _fm, _e2, _e, _e2m;
real _sign, _n, _nc, _t0nm1, _scale, _lat0, _k0; real _sign, _n, _nc, _t0nm1, _scale, _lat0, _k0;
real _scbet0, _tchi0, _scchi0, _psi0, _nrho0, _drhomax; real _scbet0, _tchi0, _scchi0, _psi0, _nrho0, _drhomax;
static const real eps_;
static const real epsx_;
static const real tol_;
static const real ahypover_;
static const int numit_ = 5; static const int numit_ = 5;
static inline real hyp(real x) { return Math::hypot(real(1), x); } static inline real hyp(real x) { return Math::hypot(real(1), x); }
// e * atanh(e * x) = log( ((1 + e*x)/(1 - e*x))^(e/2) ) if f >= 0 // e * atanh(e * x) = log( ((1 + e*x)/(1 - e*x))^(e/2) ) if f >= 0
// - sqrt(-e2) * atan( sqrt(-e2) * x) if f < 0 // - sqrt(-e2) * atan( sqrt(-e2) * x) if f < 0
inline real eatanhe(real x) const inline real eatanhe(real x) const {
{ return _f >= 0 ? _e * Math::atanh(_e * x) : - _e * std::atan(_e * x); using std::atan;
} return _f >= 0 ? _e * Math::atanh(_e * x) : - _e * atan(_e * x);
}
// Divided differences // Divided differences
// Definition: Df(x,y) = (f(x)-f(y))/(x-y) // Definition: Df(x,y) = (f(x)-f(y))/(x-y)
// See: // See:
// W. M. Kahan and R. J. Fateman, // W. M. Kahan and R. J. Fateman,
// Symbolic computation of divided differences, // Symbolic computation of divided differences,
// SIGSAM Bull. 33(3), 7-28 (1999) // SIGSAM Bull. 33(3), 7-28 (1999)
// http://dx.doi.org/10.1145/334714.334716 // http://dx.doi.org/10.1145/334714.334716
// http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf // http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf
// //
// General rules // General rules
skipping to change at line 103 skipping to change at line 102
// sn(x) = x/sqrt(1+x^2): Dsn(x,y) = (x+y)/((sn(x)+sn(y))*(1+x^2)*(1+y^ 2)) // sn(x) = x/sqrt(1+x^2): Dsn(x,y) = (x+y)/((sn(x)+sn(y))*(1+x^2)*(1+y^ 2))
static inline real Dsn(real x, real y, real sx, real sy) { static inline real Dsn(real x, real y, real sx, real sy) {
// sx = x/hyp(x) // sx = x/hyp(x)
real t = x * y; real t = x * y;
return t > 0 ? (x + y) * Math::sq( (sx * sy)/t ) / (sx + sy) : return t > 0 ? (x + y) * Math::sq( (sx * sy)/t ) / (sx + sy) :
(x - y != 0 ? (sx - sy) / (x - y) : 1); (x - y != 0 ? (sx - sy) / (x - y) : 1);
} }
// Dlog1p(x,y) = log1p((x-y)/(1+y)/(x-y) // Dlog1p(x,y) = log1p((x-y)/(1+y)/(x-y)
static inline real Dlog1p(real x, real y) { static inline real Dlog1p(real x, real y) {
real t = x - y; if (t < 0) { t = -t; y = x; } real t = x - y; if (t < 0) { t = -t; y = x; }
return t != 0 ? Math::log1p(t / (1 + y)) / t : 1 / (1 + x); return t ? Math::log1p(t / (1 + y)) / t : 1 / (1 + x);
} }
// Dexp(x,y) = exp((x+y)/2) * 2*sinh((x-y)/2)/(x-y) // Dexp(x,y) = exp((x+y)/2) * 2*sinh((x-y)/2)/(x-y)
static inline real Dexp(real x, real y) { static inline real Dexp(real x, real y) {
using std::sinh; using std::exp;
real t = (x - y)/2; real t = (x - y)/2;
return (t != 0 ? sinh(t)/t : real(1)) * exp((x + y)/2); return (t ? sinh(t)/t : 1) * exp((x + y)/2);
} }
// Dsinh(x,y) = 2*sinh((x-y)/2)/(x-y) * cosh((x+y)/2) // Dsinh(x,y) = 2*sinh((x-y)/2)/(x-y) * cosh((x+y)/2)
// cosh((x+y)/2) = (c+sinh(x)*sinh(y)/c)/2 // cosh((x+y)/2) = (c+sinh(x)*sinh(y)/c)/2
// c=sqrt((1+cosh(x))*(1+cosh(y))) // c=sqrt((1+cosh(x))*(1+cosh(y)))
// cosh((x+y)/2) = sqrt( (sinh(x)*sinh(y) + cosh(x)*cosh(y) + 1)/2 ) // cosh((x+y)/2) = sqrt( (sinh(x)*sinh(y) + cosh(x)*cosh(y) + 1)/2 )
static inline real Dsinh(real x, real y, real sx, real sy, real cx, rea l cy) static inline real Dsinh(real x, real y, real sx, real sy, real cx, rea l cy)
// sx = sinh(x), cx = cosh(x) // sx = sinh(x), cx = cosh(x)
{ {
// real t = (x - y)/2, c = sqrt((1 + cx) * (1 + cy)); // real t = (x - y)/2, c = sqrt((1 + cx) * (1 + cy));
// return (t != 0 ? sinh(t)/t : real(1)) * (c + sx * sy / c) /2; // return (t ? sinh(t)/t : real(1)) * (c + sx * sy / c) /2;
using std::sinh; using std::sqrt;
real t = (x - y)/2; real t = (x - y)/2;
return (t != 0 ? sinh(t)/t : real(1)) * sqrt((sx * sy + cx * cy + 1) /2); return (t ? sinh(t)/t : 1) * sqrt((sx * sy + cx * cy + 1) /2);
} }
// Dasinh(x,y) = asinh((x-y)*(x+y)/(x*sqrt(1+y^2)+y*sqrt(1+x^2)))/(x-y) // Dasinh(x,y) = asinh((x-y)*(x+y)/(x*sqrt(1+y^2)+y*sqrt(1+x^2)))/(x-y)
// = asinh((x*sqrt(1+y^2)-y*sqrt(1+x^2)))/(x-y) // = asinh((x*sqrt(1+y^2)-y*sqrt(1+x^2)))/(x-y)
static inline real Dasinh(real x, real y, real hx, real hy) { static inline real Dasinh(real x, real y, real hx, real hy) {
// hx = hyp(x) // hx = hyp(x)
real t = x - y; real t = x - y;
return t != 0 ? return t ?
Math::asinh(x*y > 0 ? t * (x+y) / (x*hy + y*hx) : x*hy - y*hx) / t : Math::asinh(x*y > 0 ? t * (x+y) / (x*hy + y*hx) : x*hy - y*hx) / t :
1/hx; 1/hx;
} }
// Deatanhe(x,y) = eatanhe((x-y)/(1-e^2*x*y))/(x-y) // Deatanhe(x,y) = eatanhe((x-y)/(1-e^2*x*y))/(x-y)
inline real Deatanhe(real x, real y) const { inline real Deatanhe(real x, real y) const {
real t = x - y, d = 1 - _e2 * x * y; real t = x - y, d = 1 - _e2 * x * y;
return t != 0 ? eatanhe(t / d) / t : _e2 / d; return t ? eatanhe(t / d) / t : _e2 / d;
} }
void Init(real sphi1, real cphi1, real sphi2, real cphi2, real k1); void Init(real sphi1, real cphi1, real sphi2, real cphi2, real k1);
public: public:
/** /**
* Constructor with a single standard parallel. * Constructor with a single standard parallel.
* *
* @param[in] a equatorial radius of ellipsoid (meters). * @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f.
* @param[in] stdlat standard parallel (degrees), the circle of tangenc y. * @param[in] stdlat standard parallel (degrees), the circle of tangenc y.
* @param[in] k0 scale on the standard parallel. * @param[in] k0 scale on the standard parallel.
* @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k0 i s * @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k0 is
* not positive. * not positive.
* @exception GeographicErr if \e stdlat is not in [&minus;90&deg;, * @exception GeographicErr if \e stdlat is not in [&minus;90&deg;,
* 90&deg;]. * 90&deg;].
********************************************************************** / ********************************************************************** /
LambertConformalConic(real a, real f, real stdlat, real k0); LambertConformalConic(real a, real f, real stdlat, real k0);
/** /**
* Constructor with two standard parallels. * Constructor with two standard parallels.
* *
* @param[in] a equatorial radius of ellipsoid (meters). * @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f.
* @param[in] stdlat1 first standard parallel (degrees). * @param[in] stdlat1 first standard parallel (degrees).
* @param[in] stdlat2 second standard parallel (degrees). * @param[in] stdlat2 second standard parallel (degrees).
* @param[in] k1 scale on the standard parallels. * @param[in] k1 scale on the standard parallels.
* @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k1 i s * @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k1 is
* not positive. * not positive.
* @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
* [&minus;90&deg;, 90&deg;], or if either \e stdlat1 or \e * [&minus;90&deg;, 90&deg;], or if either \e stdlat1 or \e
* stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2. * stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2.
********************************************************************** / ********************************************************************** /
LambertConformalConic(real a, real f, real stdlat1, real stdlat2, real k1); LambertConformalConic(real a, real f, real stdlat1, real stdlat2, real k1);
/** /**
* Constructor with two standard parallels specified by sines and cosin es. * Constructor with two standard parallels specified by sines and cosin es.
* *
* @param[in] a equatorial radius of ellipsoid (meters). * @param[in] a equatorial radius of ellipsoid (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f.
* @param[in] sinlat1 sine of first standard parallel. * @param[in] sinlat1 sine of first standard parallel.
* @param[in] coslat1 cosine of first standard parallel. * @param[in] coslat1 cosine of first standard parallel.
* @param[in] sinlat2 sine of second standard parallel. * @param[in] sinlat2 sine of second standard parallel.
* @param[in] coslat2 cosine of second standard parallel. * @param[in] coslat2 cosine of second standard parallel.
* @param[in] k1 scale on the standard parallels. * @param[in] k1 scale on the standard parallels.
* @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k1 i s * @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k1 is
* not positive. * not positive.
* @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
* [&minus;90&deg;, 90&deg;], or if either \e stdlat1 or \e * [&minus;90&deg;, 90&deg;], or if either \e stdlat1 or \e
* stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2. * stdlat2 is a pole and \e stdlat1 is not equal \e stdlat2.
* *
* This allows parallels close to the poles to be specified accurately. * This allows parallels close to the poles to be specified accurately.
* This routine computes the latitude of origin and the scale at this * This routine computes the latitude of origin and the scale at this
* latitude. In the case where \e lat1 and \e lat2 are different, the * latitude. In the case where \e lat1 and \e lat2 are different, the
* errors in this routines are as follows: if \e dlat = abs(\e lat2 &mi nus; * errors in this routines are as follows: if \e dlat = abs(\e lat2 &mi nus;
* \e lat1) &le; 160&deg; and max(abs(\e lat1), abs(\e lat2)) &le; 90 * \e lat1) &le; 160&deg; and max(abs(\e lat1), abs(\e lat2)) &le; 90
skipping to change at line 327 skipping to change at line 328
* latitude of origin. * latitude of origin.
********************************************************************** / ********************************************************************** /
Math::real CentralScale() const { return _k0; } Math::real CentralScale() const { return _k0; }
///@} ///@}
/** /**
* A global instantiation of LambertConformalConic with the WGS84 * A global instantiation of LambertConformalConic with the WGS84
* ellipsoid, \e stdlat = 0, and \e k0 = 1. This degenerates to the * ellipsoid, \e stdlat = 0, and \e k0 = 1. This degenerates to the
* Mercator projection. * Mercator projection.
********************************************************************** / ********************************************************************** /
static const LambertConformalConic Mercator; static const LambertConformalConic& Mercator();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_LAMBERTCONFORMALCONIC_HPP #endif // GEOGRAPHICLIB_LAMBERTCONFORMALCONIC_HPP
 End of changes. 18 change blocks. 
28 lines changed or deleted 25 lines changed or added


 LocalCartesian.hpp   LocalCartesian.hpp 
skipping to change at line 29 skipping to change at line 29
* \brief Local cartesian coordinates * \brief Local cartesian coordinates
* *
* Convert between geodetic coordinates latitude = \e lat, longitude = \e * Convert between geodetic coordinates latitude = \e lat, longitude = \e
* lon, height = \e h (measured vertically from the surface of the ellips oid) * lon, height = \e h (measured vertically from the surface of the ellips oid)
* to local cartesian coordinates (\e x, \e y, \e z). The origin of loca l * to local cartesian coordinates (\e x, \e y, \e z). The origin of loca l
* cartesian coordinate system is at \e lat = \e lat0, \e lon = \e lon0, \e h * cartesian coordinate system is at \e lat = \e lat0, \e lon = \e lon0, \e h
* = \e h0. The \e z axis is normal to the ellipsoid; the \e y axis point s * = \e h0. The \e z axis is normal to the ellipsoid; the \e y axis point s
* due north. The plane \e z = - \e h0 is tangent to the ellipsoid. * due north. The plane \e z = - \e h0 is tangent to the ellipsoid.
* *
* The conversions all take place via geocentric coordinates using a * The conversions all take place via geocentric coordinates using a
* Geocentric object (by default Geocentric::WGS84). * Geocentric object (by default Geocentric::WGS84()).
* *
* Example of use: * Example of use:
* \include example-LocalCartesian.cpp * \include example-LocalCartesian.cpp
* *
* <a href="CartConvert.1.html">CartConvert</a> is a command-line utility * <a href="CartConvert.1.html">CartConvert</a> is a command-line utility
* providing access to the functionality of Geocentric and LocalCartesian . * providing access to the functionality of Geocentric and LocalCartesian .
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT LocalCartesian { class GEOGRAPHICLIB_EXPORT LocalCartesian {
private: private:
skipping to change at line 60 skipping to change at line 60
void MatrixMultiply(real M[dim2_]) const; void MatrixMultiply(real M[dim2_]) const;
public: public:
/** /**
* Constructor setting the origin. * Constructor setting the origin.
* *
* @param[in] lat0 latitude at origin (degrees). * @param[in] lat0 latitude at origin (degrees).
* @param[in] lon0 longitude at origin (degrees). * @param[in] lon0 longitude at origin (degrees).
* @param[in] h0 height above ellipsoid at origin (meters); default 0. * @param[in] h0 height above ellipsoid at origin (meters); default 0.
* @param[in] earth Geocentric object for the transformation; default * @param[in] earth Geocentric object for the transformation; default
* Geocentric::WGS84. * Geocentric::WGS84().
* *
* \e lat0 should be in the range [&minus;90&deg;, 90&deg;]; \e * \e lat0 should be in the range [&minus;90&deg;, 90&deg;]; \e
* lon0 should be in the range [&minus;540&deg;, 540&deg;). * lon0 should be in the range [&minus;540&deg;, 540&deg;).
********************************************************************** / ********************************************************************** /
LocalCartesian(real lat0, real lon0, real h0 = 0, LocalCartesian(real lat0, real lon0, real h0 = 0,
const Geocentric& earth = Geocentric::WGS84) const Geocentric& earth = Geocentric::WGS84())
: _earth(earth) : _earth(earth)
{ Reset(lat0, lon0, h0); } { Reset(lat0, lon0, h0); }
/** /**
* Default constructor. * Default constructor.
* *
* @param[in] earth Geocentric object for the transformation; default * @param[in] earth Geocentric object for the transformation; default
* Geocentric::WGS84. * Geocentric::WGS84().
* *
* Sets \e lat0 = 0, \e lon0 = 0, \e h0 = 0. * Sets \e lat0 = 0, \e lon0 = 0, \e h0 = 0.
********************************************************************** / ********************************************************************** /
explicit LocalCartesian(const Geocentric& earth = Geocentric::WGS84) explicit LocalCartesian(const Geocentric& earth = Geocentric::WGS84())
: _earth(earth) : _earth(earth)
{ Reset(real(0), real(0), real(0)); } { Reset(real(0), real(0), real(0)); }
/** /**
* Reset the origin. * Reset the origin.
* *
* @param[in] lat0 latitude at origin (degrees). * @param[in] lat0 latitude at origin (degrees).
* @param[in] lon0 longitude at origin (degrees). * @param[in] lon0 longitude at origin (degrees).
* @param[in] h0 height above ellipsoid at origin (meters); default 0. * @param[in] h0 height above ellipsoid at origin (meters); default 0.
* *
skipping to change at line 190 skipping to change at line 190
* *
* Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
* express \e v as \e column vectors in one of two ways * express \e v as \e column vectors in one of two ways
* - in east, north, up coordinates (where the components are relative to a * - in east, north, up coordinates (where the components are relative to a
* local coordinate system at (\e lat, \e lon, \e h)); call this * local coordinate system at (\e lat, \e lon, \e h)); call this
* representation \e v1. * representation \e v1.
* - in \e x, \e y, \e z coordinates (where the components are relative to * - in \e x, \e y, \e z coordinates (where the components are relative to
* the local coordinate system at (\e lat0, \e lon0, \e h0)); call th is * the local coordinate system at (\e lat0, \e lon0, \e h0)); call th is
* representation \e v0. * representation \e v0.
* . * .
* Then we have \e v1 = \e M<sup>T</sup> &sdot; \e v0, where \e * Then we have \e v1 = <i>M</i><sup>T</sup> &sdot; \e v0, where
* M<sup>T</sup> is the transpose of \e M. * <i>M</i><sup>T</sup> is the transpose of \e M.
********************************************************************** / ********************************************************************** /
void Reverse(real x, real y, real z, real& lat, real& lon, real& h, void Reverse(real x, real y, real z, real& lat, real& lon, real& h,
std::vector<real>& M) std::vector<real>& M)
const { const {
if (M.end() == M.begin() + dim2_) { if (M.end() == M.begin() + dim2_) {
real t[dim2_]; real t[dim2_];
IntReverse(x, y, z, lat, lon, h, t); IntReverse(x, y, z, lat, lon, h, t);
std::copy(t, t + dim2_, M.begin()); std::copy(t, t + dim2_, M.begin());
} else } else
IntReverse(x, y, z, lat, lon, h, NULL); IntReverse(x, y, z, lat, lon, h, NULL);
 End of changes. 6 change blocks. 
7 lines changed or deleted 7 lines changed or added


 MGRS.hpp   MGRS.hpp 
skipping to change at line 34 skipping to change at line 34
/** /**
* \brief Convert between UTM/UPS and %MGRS * \brief Convert between UTM/UPS and %MGRS
* *
* MGRS is defined in Chapter 3 of * MGRS is defined in Chapter 3 of
* - J. W. Hager, L. L. Fry, S. S. Jacks, D. R. Hill, * - J. W. Hager, L. L. Fry, S. S. Jacks, D. R. Hill,
* <a href="http://earth-info.nga.mil/GandG/publications/tm8358.1/pdf/T M8358_1.pdf"> * <a href="http://earth-info.nga.mil/GandG/publications/tm8358.1/pdf/T M8358_1.pdf">
* Datums, Ellipsoids, Grids, and Grid Reference Systems</a>, * Datums, Ellipsoids, Grids, and Grid Reference Systems</a>,
* Defense Mapping Agency, Technical Manual TM8358.1 (1990). * Defense Mapping Agency, Technical Manual TM8358.1 (1990).
* . * .
* This document has been updated by the two NGA documents * This document has been updated by the two NGA documents
* - <a href="https://nsgreg.nga.mil/doc/view?i=4057"> Universal Grids an * - <a href="http://earth-info.nga.mil/GandG/publications/NGA_STND_0037_
d 2_0_0_GRIDS/NGA.STND.0037_2.0.0_GRIDS.pdf">
* Grid Reference Systems</a>, NGA.STND.0037_2.0.0_GRIDS (2014). * Universal Grids and Grid Reference Systems</a>,
* - <a href="https://nsgreg.nga.mil/doc/view?i=4056"> The Universal Grid * NGA.STND.0037_2.0.0_GRIDS (2014).
s * - <a href="http://earth-info.nga.mil/GandG/publications/NGA_SIG_0012_2
* and the Transverse Mercator and Polar Stereographic Map Projections< _0_0_UTMUPS/NGA.SIG.0012_2.0.0_UTMUPS.pdf">
/a>, * The Universal Grids and the Transverse Mercator and Polar Stereograp
* NGA.SIG.0012_2.0.0_UTMUPS (2014). hic
* Map Projections</a>, NGA.SIG.0012_2.0.0_UTMUPS (2014).
* *
* This implementation has the following properties: * This implementation has the following properties:
* - The conversions are closed, i.e., output from Forward is legal input for * - The conversions are closed, i.e., output from Forward is legal input for
* Reverse and vice versa. Conversion in both directions preserve the * Reverse and vice versa. Conversion in both directions preserve the
* UTM/UPS selection and the UTM zone. * UTM/UPS selection and the UTM zone.
* - Forward followed by Reverse and vice versa is approximately the * - Forward followed by Reverse and vice versa is approximately the
* identity. (This is affected in predictable ways by errors in * identity. (This is affected in predictable ways by errors in
* determining the latitude band and by loss of precision in the MGRS * determining the latitude band and by loss of precision in the MGRS
* coordinates.) * coordinates.)
* - All MGRS coordinates truncate to legal 100 km blocks. All MGRS * - All MGRS coordinates truncate to legal 100 km blocks. All MGRS
skipping to change at line 71 skipping to change at line 72
* - Inconsistent rules are used to determine the whether a particular MG RS * - Inconsistent rules are used to determine the whether a particular MG RS
* coordinate is legal. A more systematic approach is taken here. * coordinate is legal. A more systematic approach is taken here.
* - The underlying projections are not very accurately implemented. * - The underlying projections are not very accurately implemented.
* *
* Example of use: * Example of use:
* \include example-MGRS.cpp * \include example-MGRS.cpp
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT MGRS { class GEOGRAPHICLIB_EXPORT MGRS {
private: private:
typedef Math::real real; typedef Math::real real;
// The smallest length s.t., 1.0e7 - eps_ < 1.0e7 (approx 1.9 nm) // The smallest length s.t., 1.0e7 - eps() < 1.0e7 (approx 1.9 nm)
static const real eps_; static inline real eps() {
// The smallest angle s.t., 90 - eps_ < 90 (approx 50e-12 arcsec) using std::pow;
static const real angeps_; // 25 = ceil(log_2(2e7)) -- use half circumference here because
// northing 195e5 is a legal in the "southern" hemisphere.
static const real eps = pow(real(0.5), Math::digits() - 25);
return eps;
}
// The smallest angle s.t., 90 - angeps() < 90 (approx 50e-12 arcsec)
static inline real angeps() {
using std::pow;
// 7 = ceil(log_2(90))
static const real angeps = pow(real(0.5), Math::digits() - 7);
return angeps;
}
static const std::string hemispheres_; static const std::string hemispheres_;
static const std::string utmcols_[3]; static const std::string utmcols_[3];
static const std::string utmrow_; static const std::string utmrow_;
static const std::string upscols_[4]; static const std::string upscols_[4];
static const std::string upsrows_[2]; static const std::string upsrows_[2];
static const std::string latband_; static const std::string latband_;
static const std::string upsband_; static const std::string upsband_;
static const std::string digits_; static const std::string digits_;
static const int mineasting_[4]; static const int mineasting_[4];
skipping to change at line 106 skipping to change at line 118
// Maximum precision is um // Maximum precision is um
maxprec_ = 5 + 6, maxprec_ = 5 + 6,
}; };
static void CheckCoords(bool utmp, bool& northp, real& x, real& y); static void CheckCoords(bool utmp, bool& northp, real& x, real& y);
static int UTMRow(int iband, int icol, int irow); static int UTMRow(int iband, int icol, int irow);
friend class UTMUPS; // UTMUPS::StandardZone calls LatitudeBand friend class UTMUPS; // UTMUPS::StandardZone calls LatitudeBand
// Return latitude band number [-10, 10) for the given latitude (degree s). // Return latitude band number [-10, 10) for the given latitude (degree s).
// The bands are reckoned in include their southern edges. // The bands are reckoned in include their southern edges.
static int LatitudeBand(real lat) { static int LatitudeBand(real lat) {
int ilat = int(std::floor(lat)); using std::floor;
int ilat = int(floor(lat));
return (std::max)(-10, (std::min)(9, (ilat + 80)/8 - 10)); return (std::max)(-10, (std::min)(9, (ilat + 80)/8 - 10));
} }
// Return approximate latitude band number [-10, 10) for the given nort hing // Return approximate latitude band number [-10, 10) for the given nort hing
// (meters). With this rule, each 100km tile would have a unique band // (meters). With this rule, each 100km tile would have a unique band
// letter corresponding to the latitude at the center of the tile. Thi s // letter corresponding to the latitude at the center of the tile. Thi s
// function isn't currently used. // function isn't currently used.
static int ApproxLatitudeBand(real y) { static int ApproxLatitudeBand(real y) {
// northing at tile center in units of tile = 100km // northing at tile center in units of tile = 100km
real ya = std::floor( (std::min)(real(88), std::abs(y/tile_)) ) + using std::floor; using std::abs;
real ya = floor( (std::min)(real(88), abs(y/tile_)) ) +
real(0.5); real(0.5);
// convert to lat (mult by 90/100) and then to band (divide by 8) // convert to lat (mult by 90/100) and then to band (divide by 8)
// the +1 fine tunes the boundary between bands 3 and 4 // the +1 fine tunes the boundary between bands 3 and 4
int b = int(std::floor( ((ya * 9 + 1) / 10) / 8 )); int b = int(floor( ((ya * 9 + 1) / 10) / 8 ));
// For the northern hemisphere we have // For the northern hemisphere we have
// band rows num // band rows num
// N 0 0:8 9 // N 0 0:8 9
// P 1 9:17 9 // P 1 9:17 9
// Q 2 18:26 9 // Q 2 18:26 9
// R 3 27:34 8 // R 3 27:34 8
// S 4 35:43 9 // S 4 35:43 9
// T 5 44:52 9 // T 5 44:52 9
// U 6 53:61 9 // U 6 53:61 9
// V 7 62:70 9 // V 7 62:70 9
 End of changes. 5 change blocks. 
15 lines changed or deleted 29 lines changed or added


 MagneticCircle.hpp   MagneticCircle.hpp 
skipping to change at line 128 skipping to change at line 128
/** /**
* @return true if the object has been initialized. * @return true if the object has been initialized.
********************************************************************** / ********************************************************************** /
bool Init() const { return _a > 0; } bool Init() const { return _a > 0; }
/** /**
* @return \e a the equatorial radius of the ellipsoid (meters). This is * @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value inherited from the MagneticModel object used in the * the value inherited from the MagneticModel object used in the
* constructor. * constructor.
********************************************************************** / ********************************************************************** /
Math::real MajorRadius() const Math::real MajorRadius() const
{ return Init() ? _a : Math::NaN<real>(); } { return Init() ? _a : Math::NaN(); }
/** /**
* @return \e f the flattening of the ellipsoid. This is the value * @return \e f the flattening of the ellipsoid. This is the value
* inherited from the MagneticModel object used in the constructor. * inherited from the MagneticModel object used in the constructor.
********************************************************************** / ********************************************************************** /
Math::real Flattening() const Math::real Flattening() const
{ return Init() ? _f : Math::NaN<real>(); } { return Init() ? _f : Math::NaN(); }
/** /**
* @return the latitude of the circle (degrees). * @return the latitude of the circle (degrees).
********************************************************************** / ********************************************************************** /
Math::real Latitude() const Math::real Latitude() const
{ return Init() ? _lat : Math::NaN<real>(); } { return Init() ? _lat : Math::NaN(); }
/** /**
* @return the height of the circle (meters). * @return the height of the circle (meters).
********************************************************************** / ********************************************************************** /
Math::real Height() const Math::real Height() const
{ return Init() ? _h : Math::NaN<real>(); } { return Init() ? _h : Math::NaN(); }
/** /**
* @return the time (fractional years). * @return the time (fractional years).
********************************************************************** / ********************************************************************** /
Math::real Time() const Math::real Time() const
{ return Init() ? _t : Math::NaN<real>(); } { return Init() ? _t : Math::NaN(); }
///@} ///@}
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_MAGNETICCIRCLE_HPP #endif // GEOGRAPHICLIB_MAGNETICCIRCLE_HPP
 End of changes. 5 change blocks. 
5 lines changed or deleted 5 lines changed or added


 MagneticModel.hpp   MagneticModel.hpp 
skipping to change at line 89 skipping to change at line 89
/** \name Setting up the magnetic model /** \name Setting up the magnetic model
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* Construct a magnetic model. * Construct a magnetic model.
* *
* @param[in] name the name of the model. * @param[in] name the name of the model.
* @param[in] path (optional) directory for data file. * @param[in] path (optional) directory for data file.
* @param[in] earth (optional) Geocentric object for converting * @param[in] earth (optional) Geocentric object for converting
* coordinates; default Geocentric::WGS84. * coordinates; default Geocentric::WGS84().
* @exception GeographicErr if the data file cannot be found, is * @exception GeographicErr if the data file cannot be found, is
* unreadable, or is corrupt. * unreadable, or is corrupt.
* @exception std::bad_alloc if the memory necessary for storing the mo del * @exception std::bad_alloc if the memory necessary for storing the mo del
* can't be allocated. * can't be allocated.
* *
* A filename is formed by appending ".wmm" (World Magnetic Model) to t he * A filename is formed by appending ".wmm" (World Magnetic Model) to t he
* name. If \e path is specified (and is non-empty), then the file is * name. If \e path is specified (and is non-empty), then the file is
* loaded from directory, \e path. Otherwise the path is given by the * loaded from directory, \e path. Otherwise the path is given by the
* DefaultMagneticPath(). * DefaultMagneticPath().
* *
skipping to change at line 112 skipping to change at line 112
* from a file obtained by appending ".cof" to metadata file (so the * from a file obtained by appending ".cof" to metadata file (so the
* filename ends in ".wwm.cof"). * filename ends in ".wwm.cof").
* *
* The model is not tied to a particular ellipsoidal model of the earth . * The model is not tied to a particular ellipsoidal model of the earth .
* The final earth argument to the constructor specifies an ellipsoid t o * The final earth argument to the constructor specifies an ellipsoid t o
* allow geodetic coordinates to the transformed into the spherical * allow geodetic coordinates to the transformed into the spherical
* coordinates used in the spherical harmonic sum. * coordinates used in the spherical harmonic sum.
********************************************************************** / ********************************************************************** /
explicit MagneticModel(const std::string& name, explicit MagneticModel(const std::string& name,
const std::string& path = "", const std::string& path = "",
const Geocentric& earth = Geocentric::WGS84); const Geocentric& earth = Geocentric::WGS84());
///@} ///@}
/** \name Compute the magnetic field /** \name Compute the magnetic field
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* Evaluate the components of the geomagnetic field. * Evaluate the components of the geomagnetic field.
* *
* @param[in] t the time (years). * @param[in] t the time (years).
* @param[in] lat latitude of the point (degrees). * @param[in] lat latitude of the point (degrees).
skipping to change at line 317 skipping to change at line 317
/** /**
* @return \e f the flattening of the ellipsoid. This is the value * @return \e f the flattening of the ellipsoid. This is the value
* inherited from the Geocentric object used in the constructor. * inherited from the Geocentric object used in the constructor.
********************************************************************** / ********************************************************************** /
Math::real Flattening() const { return _earth.Flattening(); } Math::real Flattening() const { return _earth.Flattening(); }
///@} ///@}
/** /**
* @return the default path for magnetic model data files. * @return the default path for magnetic model data files.
* *
* This is the value of the environment variable MAGNETIC_PATH, if set; * This is the value of the environment variable
* otherwise, it is $GEOGRAPHICLIB_DATA/magnetic if the environment * GEOGRAPHICLIB_MAGNETIC_PATH, if set; otherwise, it is
* variable GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time * $GEOGRAPHICLIB_DATA/magnetic if the environment variable
* default (/usr/local/share/GeographicLib/magnetic on non-Windows syst * GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default
ems * (/usr/local/share/GeographicLib/magnetic on non-Windows systems and
* and C:/Documents and Settings/All Users/Application * C:/ProgramData/GeographicLib/magnetic on Windows systems).
* Data/GeographicLib/magnetic on Windows systems).
********************************************************************** / ********************************************************************** /
static std::string DefaultMagneticPath(); static std::string DefaultMagneticPath();
/** /**
* @return the default name for the magnetic model. * @return the default name for the magnetic model.
* *
* This is the value of the environment variable MAGNETIC_NAME, if set, * This is the value of the environment variable
* otherwise, it is "wmm2010". The MagneticModel class does not use th * GEOGRAPHICLIB_MAGNETIC_NAME, if set; otherwise, it is "wmm2010". Th
is e
* function; it is just provided as a convenience for a calling program * MagneticModel class does not use this function; it is just provided
* when constructing a MagneticModel object. as a
* convenience for a calling program when constructing a MagneticModel
* object.
********************************************************************** / ********************************************************************** /
static std::string DefaultMagneticName(); static std::string DefaultMagneticName();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning (pop) # pragma warning (pop)
#endif #endif
 End of changes. 4 change blocks. 
14 lines changed or deleted 15 lines changed or added


 Math.hpp   Math.hpp 
skipping to change at line 20 skipping to change at line 20
// Constants.hpp includes Math.hpp. Place this include outside Math.hpp's // Constants.hpp includes Math.hpp. Place this include outside Math.hpp's
// include guard to enforce this ordering. // include guard to enforce this ordering.
#include <GeographicLib/Constants.hpp> #include <GeographicLib/Constants.hpp>
#if !defined(GEOGRAPHICLIB_MATH_HPP) #if !defined(GEOGRAPHICLIB_MATH_HPP)
#define GEOGRAPHICLIB_MATH_HPP 1 #define GEOGRAPHICLIB_MATH_HPP 1
/** /**
* Are C++11 math functions available? * Are C++11 math functions available?
**********************************************************************/ **********************************************************************/
#if !defined(GEOGRAPHICLIB_CPLUSPLUS11_MATH) #if !defined(GEOGRAPHICLIB_CXX11_MATH)
// Recent versions of g++ -std=c++11 (4.7 and later?) set __cplusplus to 20 1103 // Recent versions of g++ -std=c++11 (4.7 and later?) set __cplusplus to 20 1103
// and support the new C++11 mathematical functions, std::atanh, etc. Howe ver // and support the new C++11 mathematical functions, std::atanh, etc. Howe ver
// the Android toolchain, which uses g++ -std=c++11 (4.8 as of 2014-03-11, // the Android toolchain, which uses g++ -std=c++11 (4.8 as of 2014-03-11,
// according to Pullan Lu), does not support std::atanh. Android toolchain s // according to Pullan Lu), does not support std::atanh. Android toolchain s
// might define __ANDROID__ or ANDROID; so need to check both. // might define __ANDROID__ or ANDROID; so need to check both.
# if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 7 \ # if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 7 \
&& __cplusplus >= 201103 && !(defined(__ANDROID__) || defined(ANDROID)) && __cplusplus >= 201103 && \
# define GEOGRAPHICLIB_CPLUSPLUS11_MATH 1 !(defined(__ANDROID__) || defined(ANDROID) || defined(__CYGWIN__))
# define GEOGRAPHICLIB_CXX11_MATH 1
// Visual C++ 12 supports these functions // Visual C++ 12 supports these functions
# elif defined(_MSC_VER) && _MSC_VER >= 1800 # elif defined(_MSC_VER) && _MSC_VER >= 1800
# define GEOGRAPHICLIB_CPLUSPLUS11_MATH 1 # define GEOGRAPHICLIB_CXX11_MATH 1
# else # else
# define GEOGRAPHICLIB_CPLUSPLUS11_MATH 0 # define GEOGRAPHICLIB_CXX11_MATH 0
# endif # endif
#endif #endif
#if !defined(WORDS_BIGENDIAN) #if !defined(GEOGRAPHICLIB_WORDS_BIGENDIAN)
# define WORDS_BIGENDIAN 0 # define GEOGRAPHICLIB_WORDS_BIGENDIAN 0
#endif #endif
#if !defined(HAVE_LONG_DOUBLE) #if !defined(GEOGRAPHICLIB_HAVE_LONG_DOUBLE)
# define HAVE_LONG_DOUBLE 0 # define GEOGRAPHICLIB_HAVE_LONG_DOUBLE 0
#endif #endif
#if !defined(GEOGRAPHICLIB_PRECISION) #if !defined(GEOGRAPHICLIB_PRECISION)
/** /**
* The precision of floating point numbers used in %GeographicLib. 1 means * The precision of floating point numbers used in %GeographicLib. 1 means
* float (single precision); 2 (the default) means double; 3 means long dou ble; * float (single precision); 2 (the default) means double; 3 means long dou ble;
* 4 is reserved for quadruple precision. Nearly all the testing has been * 4 is reserved for quadruple precision. Nearly all the testing has been
* carried out with doubles and that's the recommended configuration. In o rder * carried out with doubles and that's the recommended configuration. In o rder
* for long double to be used, HAVE_LONG_DOUBLE needs to be defined. Note * for long double to be used, GEOGRAPHICLIB_HAVE_LONG_DOUBLE needs to be
that * defined. Note that with Microsoft Visual Studio, long double is the sam
* with Microsoft Visual Studio, long double is the same as double. e as
* double.
**********************************************************************/ **********************************************************************/
# define GEOGRAPHICLIB_PRECISION 2 # define GEOGRAPHICLIB_PRECISION 2
#endif #endif
#include <cmath> #include <cmath>
#include <algorithm> #include <algorithm>
#include <limits> #include <limits>
#if defined(_LIBCPP_VERSION)
#include <type_traits> #if GEOGRAPHICLIB_PRECISION == 4
#include <boost/multiprecision/float128.hpp>
#include <boost/math/special_functions/hypot.hpp>
#include <boost/math/special_functions/expm1.hpp>
#include <boost/math/special_functions/log1p.hpp>
#include <boost/math/special_functions/atanh.hpp>
#include <boost/math/special_functions/asinh.hpp>
#include <boost/math/special_functions/cbrt.hpp>
#elif GEOGRAPHICLIB_PRECISION == 5
#include <mpreal.h>
#endif
#if GEOGRAPHICLIB_PRECISION > 3
// volatile keyword makes no sense for multiprec types
#define GEOGRAPHICLIB_VOLATILE
// Signal a convergence failure with multiprec types by throwing an excepti
on
// at loop exit.
#define GEOGRAPHICLIB_PANIC \
(throw GeographicLib::GeographicErr("Convergence failure"), false)
#else
#define GEOGRAPHICLIB_VOLATILE volatile
// Ignore convergence failures with standard floating points types by allow
ing
// loop to exit cleanly.
#define GEOGRAPHICLIB_PANIC false
#endif #endif
namespace GeographicLib { namespace GeographicLib {
/** /**
* \brief Mathematical functions needed by %GeographicLib * \brief Mathematical functions needed by %GeographicLib
* *
* Define mathematical functions in order to localize system dependencies and * Define mathematical functions in order to localize system dependencies and
* to provide generic versions of the functions. In addition define a re al * to provide generic versions of the functions. In addition define a re al
* type to be used by %GeographicLib. * type to be used by %GeographicLib.
* *
* Example of use: * Example of use:
* \include example-Math.cpp * \include example-Math.cpp
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT Math { class GEOGRAPHICLIB_EXPORT Math {
private: private:
void dummy() { void dummy() {
STATIC_ASSERT(GEOGRAPHICLIB_PRECISION >= 1 && GEOGRAPHICLIB_STATIC_ASSERT(GEOGRAPHICLIB_PRECISION >= 1 &&
GEOGRAPHICLIB_PRECISION <= 3, GEOGRAPHICLIB_PRECISION <= 5,
"Bad value of precision"); "Bad value of precision");
} }
Math(); // Disable constructor Math(); // Disable constructor
public: public:
#if HAVE_LONG_DOUBLE #if GEOGRAPHICLIB_HAVE_LONG_DOUBLE
/** /**
* The extended precision type for real numbers, used for some testing. * The extended precision type for real numbers, used for some testing.
* This is long double on computers with this type; otherwise it is dou ble. * This is long double on computers with this type; otherwise it is dou ble.
********************************************************************** / ********************************************************************** /
typedef long double extended; typedef long double extended;
#else #else
typedef double extended; typedef double extended;
#endif #endif
#if GEOGRAPHICLIB_PRECISION == 2 #if GEOGRAPHICLIB_PRECISION == 2
skipping to change at line 108 skipping to change at line 133
* The real type for %GeographicLib. Nearly all the testing has been do ne * The real type for %GeographicLib. Nearly all the testing has been do ne
* with \e real = double. However, the algorithms should also work wit h * with \e real = double. However, the algorithms should also work wit h
* float and long double (where available). (<b>CAUTION</b>: reasonabl e * float and long double (where available). (<b>CAUTION</b>: reasonabl e
* accuracy typically cannot be obtained using floats.) * accuracy typically cannot be obtained using floats.)
********************************************************************** / ********************************************************************** /
typedef double real; typedef double real;
#elif GEOGRAPHICLIB_PRECISION == 1 #elif GEOGRAPHICLIB_PRECISION == 1
typedef float real; typedef float real;
#elif GEOGRAPHICLIB_PRECISION == 3 #elif GEOGRAPHICLIB_PRECISION == 3
typedef extended real; typedef extended real;
#elif GEOGRAPHICLIB_PRECISION == 4
typedef boost::multiprecision::float128 real;
#elif GEOGRAPHICLIB_PRECISION == 5
typedef mpfr::mpreal real;
#else #else
typedef double real; typedef double real;
#endif #endif
/** /**
* @return the number of bits of precision in a real number.
**********************************************************************
/
static inline int digits() {
#if GEOGRAPHICLIB_PRECISION != 5
return std::numeric_limits<real>::digits;
#else
return std::numeric_limits<real>::digits();
#endif
}
/**
* Set the binary precision of a real number.
*
* @param[in] ndigits the number of bits of precision.
* @return the resulting number of bits of precision.
*
* This only has an effect when GEOGRAPHICLIB_PRECISION == 5.
**********************************************************************
/
static inline int set_digits(int ndigits) {
#if GEOGRAPHICLIB_PRECISION != 5
(void)ndigits;
#else
mpfr::mpreal::set_default_prec(ndigits >= 2 ? ndigits : 2);
#endif
return digits();
}
/**
* @return the number of decimal digits of precision in a real number.
**********************************************************************
/
static inline int digits10() {
#if GEOGRAPHICLIB_PRECISION != 5
return std::numeric_limits<real>::digits10;
#else
return std::numeric_limits<real>::digits10();
#endif
}
/**
* Number of additional decimal digits of precision for real relative t
o
* double (0 for float).
**********************************************************************
/
static inline int extra_digits() {
return
digits10() > std::numeric_limits<double>::digits10 ?
digits10() - std::numeric_limits<double>::digits10 : 0;
}
#if GEOGRAPHICLIB_PRECISION <= 3
/**
* Number of additional decimal digits of precision of real relative to * Number of additional decimal digits of precision of real relative to
* double (0 for float). * double (0 for float).
*
* <b>DEPRECATED</b>: use extra_digits() instead
********************************************************************** / ********************************************************************** /
static const int extradigits = static const int extradigits =
std::numeric_limits<real>::digits10 > std::numeric_limits<real>::digits10 >
std::numeric_limits<double>::digits10 ? std::numeric_limits<double>::digits10 ?
std::numeric_limits<real>::digits10 - std::numeric_limits<real>::digits10 -
std::numeric_limits<double>::digits10 : 0; std::numeric_limits<double>::digits10 : 0;
#endif
/** /**
* true if the machine is big-endian. * true if the machine is big-endian.
********************************************************************** / ********************************************************************** /
static const bool bigendian = WORDS_BIGENDIAN; static const bool bigendian = GEOGRAPHICLIB_WORDS_BIGENDIAN;
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return &pi;. * @return &pi;.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T pi() template<typename T> static inline T pi() {
{ return std::atan2(T(0), -T(1)); } using std::atan2;
static const T pi = atan2(T(0), T(-1));
return pi;
}
/** /**
* A synonym for pi<real>(). * A synonym for pi<real>().
********************************************************************** / ********************************************************************** /
static inline real pi() { return pi<real>(); } static inline real pi() { return pi<real>(); }
/** /**
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return the number of radians in a degree. * @return the number of radians in a degree.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T degree() template<typename T> static inline T degree() {
{ return pi<T>() / T(180); } static const T degree = pi<T>() / 180;
return degree;
}
/** /**
* A synonym for degree<real>(). * A synonym for degree<real>().
********************************************************************** / ********************************************************************** /
static inline real degree() { return degree<real>(); } static inline real degree() { return degree<real>(); }
/** /**
* Square a number. * Square a number.
* *
* @tparam T the type of the argument and the returned value. * @tparam T the type of the argument and the returned value.
* @param[in] x * @param[in] x
* @return <i>x</i><sup>2</sup>. * @return <i>x</i><sup>2</sup>.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T sq(T x) template<typename T> static inline T sq(T x)
{ return x * x; } { return x * x; }
#if defined(DOXYGEN)
/** /**
* The hypotenuse function avoiding underflow and overflow. * The hypotenuse function avoiding underflow and overflow.
* *
* @tparam T the type of the arguments and the returned value. * @tparam T the type of the arguments and the returned value.
* @param[in] x * @param[in] x
* @param[in] y * @param[in] y
* @return sqrt(<i>x</i><sup>2</sup> + <i>y</i><sup>2</sup>). * @return sqrt(<i>x</i><sup>2</sup> + <i>y</i><sup>2</sup>).
********************************************************************** / ********************************************************************** /
template<typename T> static inline T hypot(T x, T y) { template<typename T> static inline T hypot(T x, T y) {
x = std::abs(x); y = std::abs(y); #if GEOGRAPHICLIB_CXX11_MATH
T a = (std::max)(x, y), b = (std::min)(x, y) / (a ? a : 1); using std::hypot; return hypot(x, y);
return a * std::sqrt(1 + b * b); #else
using std::abs; using std::sqrt;
x = abs(x); y = abs(y);
if (x < y) std::swap(x, y); // Now x >= y >= 0
y /= (x ? x : 1);
return x * sqrt(1 + y * y);
// For an alternative (square-root free) method see // For an alternative (square-root free) method see
// C. Moler and D. Morrision (1983) http://dx.doi.org/10.1147/rd.276. 0577 // C. Moler and D. Morrision (1983) http://dx.doi.org/10.1147/rd.276. 0577
// and A. A. Dubrulle (1983) http://dx.doi.org/10.1147/rd.276.0582 // and A. A. Dubrulle (1983) http://dx.doi.org/10.1147/rd.276.0582
}
#elif GEOGRAPHICLIB_CPLUSPLUS11_MATH || (defined(_MSC_VER) && _MSC_VER >= 1
700)
template<typename T> static inline T hypot(T x, T y)
{ return std::hypot(x, y); }
# if HAVE_LONG_DOUBLE && defined(_MSC_VER) && _MSC_VER == 1700
// Visual C++ 11 doesn't have a long double overload for std::hypot --
// reported to MS on 2013-07-18
// http://connect.microsoft.com/VisualStudio/feedback/details/794416
// (Visual C++ 12 is OK) Suppress the resulting "loss of data warning"
with
static inline long double hypot(long double x, long double y)
{ return std::hypot(double(x), double(y)); }
# endif
#elif defined(_MSC_VER)
static inline double hypot(double x, double y)
{ return _hypot(x, y); }
# if _MSC_VER < 1400
// Visual C++ 7.1/VS .NET 2003 does not have _hypotf()
static inline float hypot(float x, float y)
{ return float(_hypot(x, y)); }
# else
static inline float hypot(float x, float y)
{ return _hypotf(x, y); }
# endif
# if HAVE_LONG_DOUBLE
static inline long double hypot(long double x, long double y)
{ return _hypot(double(x), double(y)); } // Suppress loss of data warni
ng
# endif
#else
// Use overloading to define generic versions
static inline double hypot(double x, double y)
{ return ::hypot(x, y); }
static inline float hypot(float x, float y)
{ return ::hypotf(x, y); }
# if HAVE_LONG_DOUBLE
static inline long double hypot(long double x, long double y)
{ return ::hypotl(x, y); }
# endif
#endif #endif
}
#if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MA TH)
/** /**
* exp(\e x) &minus; 1 accurate near \e x = 0. This is taken from * exp(\e x) &minus; 1 accurate near \e x = 0.
* N. J. Higham, Accuracy and Stability of Numerical Algorithms, 2nd
* Edition (SIAM, 2002), Sec 1.14.1, p 19.
* *
* @tparam T the type of the argument and the returned value. * @tparam T the type of the argument and the returned value.
* @param[in] x * @param[in] x
* @return exp(\e x) &minus; 1. * @return exp(\e x) &minus; 1.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T expm1(T x) { template<typename T> static inline T expm1(T x) {
#if GEOGRAPHICLIB_CXX11_MATH
using std::expm1; return expm1(x);
#else
using std::exp; using std::abs; using std::log;
volatile T volatile T
y = std::exp(x), y = exp(x),
z = y - 1; z = y - 1;
// The reasoning here is similar to that for log1p. The expression // The reasoning here is similar to that for log1p. The expression
// mathematically reduces to exp(x) - 1, and the factor z/log(y) = (y - // mathematically reduces to exp(x) - 1, and the factor z/log(y) = (y -
// 1)/log(y) is a slowly varying quantity near y = 1 and is accuratel y // 1)/log(y) is a slowly varying quantity near y = 1 and is accuratel y
// computed. // computed.
return std::abs(x) > 1 ? z : (z == 0 ? x : x * z / std::log(y)); return abs(x) > 1 ? z : (z == 0 ? x : x * z / log(y));
}
#elif GEOGRAPHICLIB_CPLUSPLUS11_MATH
template<typename T> static inline T expm1(T x)
{ return std::expm1(x); }
#else
static inline double expm1(double x) { return ::expm1(x); }
static inline float expm1(float x) { return ::expm1f(x); }
# if HAVE_LONG_DOUBLE
static inline long double expm1(long double x)
{ return ::expm1l(x); }
# endif
#endif #endif
}
#if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MA TH)
/** /**
* log(1 + \e x) accurate near \e x = 0. * log(1 + \e x) accurate near \e x = 0.
* *
* This is taken from D. Goldberg,
* <a href="http://dx.doi.org/10.1145/103162.103163">What every compute
r
* scientist should know about floating-point arithmetic</a> (1991),
* Theorem 4. See also, Higham (op. cit.), Answer to Problem 1.5, p 52
8.
*
* @tparam T the type of the argument and the returned value. * @tparam T the type of the argument and the returned value.
* @param[in] x * @param[in] x
* @return log(1 + \e x). * @return log(1 + \e x).
********************************************************************** / ********************************************************************** /
template<typename T> static inline T log1p(T x) { template<typename T> static inline T log1p(T x) {
#if GEOGRAPHICLIB_CXX11_MATH
using std::log1p; return log1p(x);
#else
using std::log;
volatile T volatile T
y = 1 + x, y = 1 + x,
z = y - 1; z = y - 1;
// Here's the explanation for this magic: y = 1 + z, exactly, and z // Here's the explanation for this magic: y = 1 + z, exactly, and z
// approx x, thus log(y)/z (which is nearly constant near z = 0) retu rns // approx x, thus log(y)/z (which is nearly constant near z = 0) retu rns
// a good approximation to the true log(1 + x)/x. The multiplication x * // a good approximation to the true log(1 + x)/x. The multiplication x *
// (log(y)/z) introduces little additional error. // (log(y)/z) introduces little additional error.
return z == 0 ? x : x * std::log(y) / z; return z == 0 ? x : x * log(y) / z;
}
#elif GEOGRAPHICLIB_CPLUSPLUS11_MATH
template<typename T> static inline T log1p(T x)
{ return std::log1p(x); }
#else
static inline double log1p(double x) { return ::log1p(x); }
static inline float log1p(float x) { return ::log1pf(x); }
# if HAVE_LONG_DOUBLE
static inline long double log1p(long double x)
{ return ::log1pl(x); }
# endif
#endif #endif
}
#if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MA TH)
/** /**
* The inverse hyperbolic sine function. This is defined in terms of * The inverse hyperbolic sine function.
* Math::log1p(\e x) in order to maintain accuracy near \e x = 0. In
* addition, the odd parity of the function is enforced.
* *
* @tparam T the type of the argument and the returned value. * @tparam T the type of the argument and the returned value.
* @param[in] x * @param[in] x
* @return asinh(\e x). * @return asinh(\e x).
********************************************************************** / ********************************************************************** /
template<typename T> static inline T asinh(T x) { template<typename T> static inline T asinh(T x) {
T y = std::abs(x); // Enforce odd parity #if GEOGRAPHICLIB_CXX11_MATH
using std::asinh; return asinh(x);
#else
using std::abs; T y = abs(x); // Enforce odd parity
y = log1p(y * (1 + y/(hypot(T(1), y) + 1))); y = log1p(y * (1 + y/(hypot(T(1), y) + 1)));
return x < 0 ? -y : y; return x < 0 ? -y : y;
}
#elif GEOGRAPHICLIB_CPLUSPLUS11_MATH
template<typename T> static inline T asinh(T x)
{ return std::asinh(x); }
#else
static inline double asinh(double x) { return ::asinh(x); }
static inline float asinh(float x) { return ::asinhf(x); }
# if HAVE_LONG_DOUBLE
static inline long double asinh(long double x)
{ return ::asinhl(x); }
# endif
#endif #endif
}
#if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MA TH)
/** /**
* The inverse hyperbolic tangent function. This is defined in terms o * The inverse hyperbolic tangent function.
f
* Math::log1p(\e x) in order to maintain accuracy near \e x = 0. In
* addition, the odd parity of the function is enforced.
* *
* @tparam T the type of the argument and the returned value. * @tparam T the type of the argument and the returned value.
* @param[in] x * @param[in] x
* @return atanh(\e x). * @return atanh(\e x).
********************************************************************** / ********************************************************************** /
template<typename T> static inline T atanh(T x) { template<typename T> static inline T atanh(T x) {
T y = std::abs(x); // Enforce odd parity #if GEOGRAPHICLIB_CXX11_MATH
using std::atanh; return atanh(x);
#else
using std::abs; T y = abs(x); // Enforce odd parity
y = log1p(2 * y/(1 - y))/2; y = log1p(2 * y/(1 - y))/2;
return x < 0 ? -y : y; return x < 0 ? -y : y;
}
#elif GEOGRAPHICLIB_CPLUSPLUS11_MATH
template<typename T> static inline T atanh(T x)
{ return std::atanh(x); }
#else
static inline double atanh(double x) { return ::atanh(x); }
static inline float atanh(float x) { return ::atanhf(x); }
# if HAVE_LONG_DOUBLE
static inline long double atanh(long double x)
{ return ::atanhl(x); }
# endif
#endif #endif
}
#if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MA TH)
/** /**
* The cube root function. * The cube root function.
* *
* @tparam T the type of the argument and the returned value. * @tparam T the type of the argument and the returned value.
* @param[in] x * @param[in] x
* @return the real cube root of \e x. * @return the real cube root of \e x.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T cbrt(T x) { template<typename T> static inline T cbrt(T x) {
T y = std::pow(std::abs(x), 1/T(3)); // Return the real cube root #if GEOGRAPHICLIB_CXX11_MATH
using std::cbrt; return cbrt(x);
#else
using std::abs; using std::pow;
T y = pow(abs(x), 1/T(3)); // Return the real cube root
return x < 0 ? -y : y; return x < 0 ? -y : y;
}
#elif GEOGRAPHICLIB_CPLUSPLUS11_MATH
template<typename T> static inline T cbrt(T x)
{ return std::cbrt(x); }
#else
static inline double cbrt(double x) { return ::cbrt(x); }
static inline float cbrt(float x) { return ::cbrtf(x); }
# if HAVE_LONG_DOUBLE
static inline long double cbrt(long double x) { return ::cbrtl(x); }
# endif
#endif #endif
}
/** /**
* The error-free sum of two numbers. * The error-free sum of two numbers.
* *
* @tparam T the type of the argument and the returned value. * @tparam T the type of the argument and the returned value.
* @param[in] u * @param[in] u
* @param[in] v * @param[in] v
* @param[out] t the exact error given by (\e u + \e v) - \e s. * @param[out] t the exact error given by (\e u + \e v) - \e s.
* @return \e s = round(\e u + \e v). * @return \e s = round(\e u + \e v).
* *
* See D. E. Knuth, TAOCP, Vol 2, 4.2.2, Theorem B. (Note that \e t ca n be * See D. E. Knuth, TAOCP, Vol 2, 4.2.2, Theorem B. (Note that \e t ca n be
* the same as one of the first two arguments.) * the same as one of the first two arguments.)
********************************************************************** / ********************************************************************** /
template<typename T> static inline T sum(T u, T v, T& t) { template<typename T> static inline T sum(T u, T v, T& t) {
volatile T s = u + v; GEOGRAPHICLIB_VOLATILE T s = u + v;
volatile T up = s - v; GEOGRAPHICLIB_VOLATILE T up = s - v;
volatile T vpp = s - up; GEOGRAPHICLIB_VOLATILE T vpp = s - up;
up -= u; up -= u;
vpp -= v; vpp -= v;
t = -(up + vpp); t = -(up + vpp);
// u + v = s + t // u + v = s + t
// = round(u + v) + t // = round(u + v) + t
return s; return s;
} }
/** /**
* Normalize an angle (restricted input range). * Normalize an angle (restricted input range).
skipping to change at line 404 skipping to change at line 412
/** /**
* Normalize an arbitrary angle. * Normalize an arbitrary angle.
* *
* @tparam T the type of the argument and returned value. * @tparam T the type of the argument and returned value.
* @param[in] x the angle in degrees. * @param[in] x the angle in degrees.
* @return the angle reduced to the range [&minus;180&deg;, 180&deg;). * @return the angle reduced to the range [&minus;180&deg;, 180&deg;).
* *
* The range of \e x is unrestricted. * The range of \e x is unrestricted.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T AngNormalize2(T x) template<typename T> static inline T AngNormalize2(T x)
{ return AngNormalize<T>(std::fmod(x, T(360))); } { using std::fmod; return AngNormalize<T>(fmod(x, T(360))); }
/** /**
* Difference of two angles reduced to [&minus;180&deg;, 180&deg;] * Difference of two angles reduced to [&minus;180&deg;, 180&deg;]
* *
* @tparam T the type of the arguments and returned value. * @tparam T the type of the arguments and returned value.
* @param[in] x the first angle in degrees. * @param[in] x the first angle in degrees.
* @param[in] y the second angle in degrees. * @param[in] y the second angle in degrees.
* @return \e y &minus; \e x, reduced to the range [&minus;180&deg;, * @return \e y &minus; \e x, reduced to the range [&minus;180&deg;,
* 180&deg;]. * 180&deg;].
* *
skipping to change at line 430 skipping to change at line 438
********************************************************************** / ********************************************************************** /
template<typename T> static inline T AngDiff(T x, T y) { template<typename T> static inline T AngDiff(T x, T y) {
T t, d = sum(-x, y, t); T t, d = sum(-x, y, t);
if ((d - T(180)) + t > T(0)) // y - x > 180 if ((d - T(180)) + t > T(0)) // y - x > 180
d -= T(360); // exact d -= T(360); // exact
else if ((d + T(180)) + t <= T(0)) // y - x <= -180 else if ((d + T(180)) + t <= T(0)) // y - x <= -180
d += T(360); // exact d += T(360); // exact
return d + t; return d + t;
} }
#if defined(DOXYGEN)
/** /**
* Test for finiteness. * Test for finiteness.
* *
* @tparam T the type of the argument. * @tparam T the type of the argument.
* @param[in] x * @param[in] x
* @return true if number is finite, false if NaN or infinite. * @return true if number is finite, false if NaN or infinite.
********************************************************************** / ********************************************************************** /
template<typename T> static inline bool isfinite(T x) { template<typename T> static inline bool isfinite(T x) {
return std::abs(x) <= (std::numeric_limits<T>::max)(); #if GEOGRAPHICLIB_CXX11_MATH
} using std::isfinite; return isfinite(x);
#elif (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MATH)
template<typename T> static inline bool isfinite(T x) {
return _finite(double(x)) != 0;
}
#elif defined(_LIBCPP_VERSION)
// libc++ implements std::isfinite() as a template that only allows
// floating-point types. isfinite is invoked by Utility::str to format
// numbers conveniently and this allows integer arguments, so we need t
o
// allow Math::isfinite to work on integers.
template<typename T> static inline
typename std::enable_if<std::is_floating_point<T>::value, bool>::type
isfinite(T x) {
return std::isfinite(x);
}
template<typename T> static inline
typename std::enable_if<!std::is_floating_point<T>::value, bool>::type
isfinite(T /*x*/) {
return true;
}
#else #else
template<typename T> static inline bool isfinite(T x) { using std::abs;
return std::isfinite(x); return abs(x) <= (std::numeric_limits<T>::max)();
}
#endif #endif
}
/** /**
* The NaN (not a number) * The NaN (not a number)
* *
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return NaN if available, otherwise return the max real of type T. * @return NaN if available, otherwise return the max real of type T.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T NaN() { template<typename T> static inline T NaN() {
return std::numeric_limits<T>::has_quiet_NaN ? return std::numeric_limits<T>::has_quiet_NaN ?
std::numeric_limits<T>::quiet_NaN() : std::numeric_limits<T>::quiet_NaN() :
skipping to change at line 490 skipping to change at line 478
static inline real NaN() { return NaN<real>(); } static inline real NaN() { return NaN<real>(); }
/** /**
* Test for NaN. * Test for NaN.
* *
* @tparam T the type of the argument. * @tparam T the type of the argument.
* @param[in] x * @param[in] x
* @return true if argument is a NaN. * @return true if argument is a NaN.
********************************************************************** / ********************************************************************** /
template<typename T> static inline bool isnan(T x) { template<typename T> static inline bool isnan(T x) {
#if defined(DOXYGEN) || (defined(_MSC_VER) && !GEOGRAPHICLIB_CPLUSPLUS11_MA #if GEOGRAPHICLIB_CXX11_MATH
TH) using std::isnan; return isnan(x);
return x != x;
#else #else
return std::isnan(x); return x != x;
#endif #endif
} }
/** /**
* Infinity * Infinity
* *
* @tparam T the type of the returned value. * @tparam T the type of the returned value.
* @return infinity if available, otherwise return the max real. * @return infinity if available, otherwise return the max real.
********************************************************************** / ********************************************************************** /
template<typename T> static inline T infinity() { template<typename T> static inline T infinity() {
skipping to change at line 530 skipping to change at line 518
template<typename T> static inline T swab(T x) { template<typename T> static inline T swab(T x) {
union { union {
T r; T r;
unsigned char c[sizeof(T)]; unsigned char c[sizeof(T)];
} b; } b;
b.r = x; b.r = x;
for (int i = sizeof(T)/2; i--; ) for (int i = sizeof(T)/2; i--; )
std::swap(b.c[i], b.c[sizeof(T) - 1 - i]); std::swap(b.c[i], b.c[sizeof(T) - 1 - i]);
return b.r; return b.r;
} }
#if GEOGRAPHICLIB_PRECISION == 4
typedef boost::math::policies::policy
< boost::math::policies::domain_error
<boost::math::policies::errno_on_error>,
boost::math::policies::pole_error
<boost::math::policies::errno_on_error>,
boost::math::policies::overflow_error
<boost::math::policies::errno_on_error>,
boost::math::policies::evaluation_error
<boost::math::policies::errno_on_error> >
boost_special_functions_policy;
static inline real hypot(real x, real y)
{ return boost::math::hypot(x, y, boost_special_functions_policy()); }
static inline real expm1(real x)
{ return boost::math::expm1(x, boost_special_functions_policy()); }
static inline real log1p(real x)
{ return boost::math::log1p(x, boost_special_functions_policy()); }
static inline real asinh(real x)
{ return boost::math::asinh(x, boost_special_functions_policy()); }
static inline real atanh(real x)
{ return boost::math::atanh(x, boost_special_functions_policy()); }
static inline real cbrt(real x)
{ return boost::math::cbrt(x, boost_special_functions_policy()); }
static inline bool isnan(real x) { return boost::math::isnan(x); }
static inline bool isfinite(real x) { return boost::math::isfinite(x);
}
#endif
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_MATH_HPP #endif // GEOGRAPHICLIB_MATH_HPP
 End of changes. 55 change blocks. 
183 lines changed or deleted 206 lines changed or added


 NormalGravity.hpp   NormalGravity.hpp 
/** /**
* \file NormalGravity.hpp * \file NormalGravity.hpp
* \brief Header for GeographicLib::NormalGravity class * \brief Header for GeographicLib::NormalGravity class
* *
* Copyright (c) Charles Karney (2011) <charles@karney.com> and licensed un * Copyright (c) Charles Karney (2011-2014) <charles@karney.com> and licens
der ed
* the MIT/X11 License. For more information, see * under the MIT/X11 License. For more information, see
* http://geographiclib.sourceforge.net/ * http://geographiclib.sourceforge.net/
**********************************************************************/ **********************************************************************/
#if !defined(GEOGRAPHICLIB_NORMALGRAVITY_HPP) #if !defined(GEOGRAPHICLIB_NORMALGRAVITY_HPP)
#define GEOGRAPHICLIB_NORMALGRAVITY_HPP 1 #define GEOGRAPHICLIB_NORMALGRAVITY_HPP 1
#include <GeographicLib/Constants.hpp> #include <GeographicLib/Constants.hpp>
#include <GeographicLib/Geocentric.hpp> #include <GeographicLib/Geocentric.hpp>
namespace GeographicLib { namespace GeographicLib {
skipping to change at line 68 skipping to change at line 68
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT NormalGravity { class GEOGRAPHICLIB_EXPORT NormalGravity {
private: private:
static const int maxit_ = 10; static const int maxit_ = 10;
typedef Math::real real; typedef Math::real real;
friend class GravityModel; friend class GravityModel;
real _a, _GM, _omega, _f, _J2, _omega2, _aomega2; real _a, _GM, _omega, _f, _J2, _omega2, _aomega2;
real _e2, _ep2, _b, _E, _U0, _gammae, _gammap, _q0, _m, _k, _fstar; real _e2, _ep2, _b, _E, _U0, _gammae, _gammap, _q0, _m, _k, _fstar;
Geocentric _earth; Geocentric _earth;
static Math::real qf(real ep2); // (atan(y)-(y-y^3/3))/y^5 (y = sqrt(x)) = 1/5-y/7+y^2/9-y^3/11...
static Math::real qpf(real ep2); static real atan5(real x);
Math::real Jn(int n) const; // (atan(y)-(y-y^3/3+y^5/5))/y^7 (y = sqrt(x)) = -1/7+x/9-x^2/11+x^3/13
...
static real atan7(real x);
static real qf(real ep2);
static real dq(real ep2);
static real qpf(real ep2);
real Jn(int n) const;
public: public:
/** \name Setting up the normal gravity /** \name Setting up the normal gravity
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* Constructor for the normal gravity. * Constructor for the normal gravity.
* *
* @param[in] a equatorial radius (meters). * @param[in] a equatorial radius (meters).
* @param[in] GM mass constant of the ellipsoid * @param[in] GM mass constant of the ellipsoid
* (meters<sup>3</sup>/seconds<sup>2</sup>); this is the product of \ e G * (meters<sup>3</sup>/seconds<sup>2</sup>); this is the product of \ e G
* the gravitational constant and \e M the mass of the earth (usually * the gravitational constant and \e M the mass of the earth (usually
* including the mass of the earth's atmosphere). * including the mass of the earth's atmosphere).
* @param[in] omega the angular velocity (rad s<sup>&minus;1</sup>). * @param[in] omega the angular velocity (rad s<sup>&minus;1</sup>).
* @param[in] f the flattening of the ellipsoid. * @param[in] f the flattening of the ellipsoid.
* @param[in] J2 dynamical form factor. * @param[in] J2 the dynamical form factor.
* @exception if \e a is not positive or the other constants are * @exception if \e a is not positive or the other constants are
* inconsistent (see below). * inconsistent (see below).
* *
* Exactly one of \e f and \e J2 should be positive and this will be us * If \e omega is non-zero, then exactly one of \e f and \e J2 should b
ed e
* to define the ellipsoid. The shape of the ellipsoid can be given in * positive and this will be used to define the ellipsoid. The shape o
one f
* of two ways: * the ellipsoid can be given in one of two ways:
* - geometrically, the ellipsoid is defined by the flattening \e f = ( \e a * - geometrically, the ellipsoid is defined by the flattening \e f = ( \e a
* &minus; \e b) / \e a, where \e a and \e b are the equatorial radiu s * &minus; \e b) / \e a, where \e a and \e b are the equatorial radiu s
* and the polar semi-axis. * and the polar semi-axis.
* - physically, the ellipsoid is defined by the dynamical form factor * - physically, the ellipsoid is defined by the dynamical form factor
* <i>J</i><sub>2</sub> = (\e C &minus; \e A) / <i>Ma</i><sup>2</sup> , * <i>J</i><sub>2</sub> = (\e C &minus; \e A) / <i>Ma</i><sup>2</sup> ,
* where \e A and \e C are the equatorial and polar moments of inerti a * where \e A and \e C are the equatorial and polar moments of inerti a
* and \e M is the mass of the earth. * and \e M is the mass of the earth.
* .
* If \e omega, \e f, and \e J2 are all zero, then the ellipsoid become
s a
* sphere.
********************************************************************** / ********************************************************************** /
NormalGravity(real a, real GM, real omega, real f, real J2); NormalGravity(real a, real GM, real omega, real f, real J2);
/** /**
* A default constructor for the normal gravity. This sets up an * A default constructor for the normal gravity. This sets up an
* uninitialized object and is used by GravityModel which constructs th is * uninitialized object and is used by GravityModel which constructs th is
* object before it has read in the parameters for the reference ellips oid. * object before it has read in the parameters for the reference ellips oid.
********************************************************************** / ********************************************************************** /
NormalGravity() : _a(-1) {} NormalGravity() : _a(-1) {}
///@} ///@}
skipping to change at line 228 skipping to change at line 236
/** /**
* @return true if the object has been initialized. * @return true if the object has been initialized.
********************************************************************** / ********************************************************************** /
bool Init() const { return _a > 0; } bool Init() const { return _a > 0; }
/** /**
* @return \e a the equatorial radius of the ellipsoid (meters). This is * @return \e a the equatorial radius of the ellipsoid (meters). This is
* the value used in the constructor. * the value used in the constructor.
********************************************************************** / ********************************************************************** /
Math::real MajorRadius() const Math::real MajorRadius() const
{ return Init() ? _a : Math::NaN<real>(); } { return Init() ? _a : Math::NaN(); }
/** /**
* @return \e GM the mass constant of the ellipsoid * @return \e GM the mass constant of the ellipsoid
* (m<sup>3</sup> s<sup>&minus;2</sup>). This is the value used in t he * (m<sup>3</sup> s<sup>&minus;2</sup>). This is the value used in t he
* constructor. * constructor.
********************************************************************** / ********************************************************************** /
Math::real MassConstant() const Math::real MassConstant() const
{ return Init() ? _GM : Math::NaN<real>(); } { return Init() ? _GM : Math::NaN(); }
/** /**
* @return \e J<sub>n</sub> the dynamical form factors of the ellipsoid * @return <i>J</i><sub><i>n</i></sub> the dynamical form factors of th
. e
* ellipsoid.
* *
* If \e n = 2 (the default), this is the value of <i>J</i><sub>2</sub> * If \e n = 2 (the default), this is the value of <i>J</i><sub>2</sub>
* used in the constructor. Otherwise it is the zonal coefficient of t he * used in the constructor. Otherwise it is the zonal coefficient of t he
* Legendre harmonic sum of the normal gravitational potential. Note t hat * Legendre harmonic sum of the normal gravitational potential. Note t hat
* \e J<sub>n</sub> = 0 if \e n is odd. In most gravity applications, * <i>J</i><sub><i>n</i></sub> = 0 if \e n is odd. In most gravity
* fully normalized Legendre functions are used and the corresponding * applications, fully normalized Legendre functions are used and the
* coefficient is <i>C</i><sub><i>n</i>0</sub> = &minus;\e J<sub>n</sub * corresponding coefficient is <i>C</i><sub><i>n</i>0</sub> =
> / * &minus;<i>J</i><sub><i>n</i></sub> / sqrt(2 \e n + 1).
* sqrt(2 \e n + 1).
********************************************************************** / ********************************************************************** /
Math::real DynamicalFormFactor(int n = 2) const Math::real DynamicalFormFactor(int n = 2) const
{ return Init() ? ( n == 2 ? _J2 : Jn(n)) : Math::NaN<real>(); } { return Init() ? ( n == 2 ? _J2 : Jn(n)) : Math::NaN(); }
/** /**
* @return &omega; the angular velocity of the ellipsoid (rad * @return &omega; the angular velocity of the ellipsoid (rad
* s<sup>&minus;1</sup>). This is the value used in the constructor. * s<sup>&minus;1</sup>). This is the value used in the constructor.
********************************************************************** / ********************************************************************** /
Math::real AngularVelocity() const Math::real AngularVelocity() const
{ return Init() ? _omega : Math::NaN<real>(); } { return Init() ? _omega : Math::NaN(); }
/** /**
* @return <i>f</i> the flattening of the ellipsoid (\e a &minus; \e b) /\e * @return <i>f</i> the flattening of the ellipsoid (\e a &minus; \e b) /\e
* a. * a.
********************************************************************** / ********************************************************************** /
Math::real Flattening() const Math::real Flattening() const
{ return Init() ? _f : Math::NaN<real>(); } { return Init() ? _f : Math::NaN(); }
/** /**
* @return &gamma;<sub>e</sub> the normal gravity at equator (m * @return &gamma;<sub>e</sub> the normal gravity at equator (m
* s<sup>&minus;2</sup>). * s<sup>&minus;2</sup>).
********************************************************************** / ********************************************************************** /
Math::real EquatorialGravity() const Math::real EquatorialGravity() const
{ return Init() ? _gammae : Math::NaN<real>(); } { return Init() ? _gammae : Math::NaN(); }
/** /**
* @return &gamma;<sub>p</sub> the normal gravity at poles (m * @return &gamma;<sub>p</sub> the normal gravity at poles (m
* s<sup>&minus;2</sup>). * s<sup>&minus;2</sup>).
********************************************************************** / ********************************************************************** /
Math::real PolarGravity() const Math::real PolarGravity() const
{ return Init() ? _gammap : Math::NaN<real>(); } { return Init() ? _gammap : Math::NaN(); }
/** /**
* @return <i>f*</i> the gravity flattening (&gamma;<sub>p</sub> &minus ; * @return <i>f*</i> the gravity flattening (&gamma;<sub>p</sub> &minus ;
* &gamma;<sub>e</sub>) / &gamma;<sub>e</sub>. * &gamma;<sub>e</sub>) / &gamma;<sub>e</sub>.
********************************************************************** / ********************************************************************** /
Math::real GravityFlattening() const Math::real GravityFlattening() const
{ return Init() ? _fstar : Math::NaN<real>(); } { return Init() ? _fstar : Math::NaN(); }
/** /**
* @return <i>U</i><sub>0</sub> the constant normal potential for the * @return <i>U</i><sub>0</sub> the constant normal potential for the
* surface of the ellipsoid (m<sup>2</sup> s<sup>&minus;2</sup>). * surface of the ellipsoid (m<sup>2</sup> s<sup>&minus;2</sup>).
********************************************************************** / ********************************************************************** /
Math::real SurfacePotential() const Math::real SurfacePotential() const
{ return Init() ? _U0 : Math::NaN<real>(); } { return Init() ? _U0 : Math::NaN(); }
/** /**
* @return the Geocentric object used by this instance. * @return the Geocentric object used by this instance.
********************************************************************** / ********************************************************************** /
const Geocentric& Earth() const { return _earth; } const Geocentric& Earth() const { return _earth; }
///@} ///@}
/** /**
* A global instantiation of NormalGravity for the WGS84 ellipsoid. * A global instantiation of NormalGravity for the WGS84 ellipsoid.
********************************************************************** / ********************************************************************** /
static const NormalGravity WGS84; static const NormalGravity& WGS84();
/** /**
* A global instantiation of NormalGravity for the GRS80 ellipsoid. * A global instantiation of NormalGravity for the GRS80 ellipsoid.
********************************************************************** / ********************************************************************** /
static const NormalGravity GRS80; static const NormalGravity& GRS80();
/**
* Compute the flattening from the dynamical form factor.
*
* @param[in] a equatorial radius (meters).
* @param[in] GM mass constant of the ellipsoid
* (meters<sup>3</sup>/seconds<sup>2</sup>); this is the product of \
e G
* the gravitational constant and \e M the mass of the earth (usually
* including the mass of the earth's atmosphere).
* @param[in] omega the angular velocity (rad s<sup>&minus;1</sup>).
* @param[in] J2 the dynamical form factor.
* @return \e f the flattening of the ellipsoid.
**********************************************************************
/
static Math::real J2ToFlattening(real a, real GM, real omega, real J2);
/**
* Compute the dynamical form factor from the flattening.
*
* @param[in] a equatorial radius (meters).
* @param[in] GM mass constant of the ellipsoid
* (meters<sup>3</sup>/seconds<sup>2</sup>); this is the product of \
e G
* the gravitational constant and \e M the mass of the earth (usually
* including the mass of the earth's atmosphere).
* @param[in] omega the angular velocity (rad s<sup>&minus;1</sup>).
* @param[in] f the flattening of the ellipsoid.
* @return \e J2 the dynamical form factor.
**********************************************************************
/
static Math::real FlatteningToJ2(real a, real GM, real omega, real f);
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_NORMALGRAVITY_HPP #endif // GEOGRAPHICLIB_NORMALGRAVITY_HPP
 End of changes. 18 change blocks. 
30 lines changed or deleted 72 lines changed or added


 OSGB.hpp   OSGB.hpp 
skipping to change at line 49 skipping to change at line 49
* datum (and vice versa). * datum (and vice versa).
* *
* Example of use: * Example of use:
* \include example-OSGB.cpp * \include example-OSGB.cpp
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT OSGB { class GEOGRAPHICLIB_EXPORT OSGB {
private: private:
typedef Math::real real; typedef Math::real real;
static const std::string letters_; static const std::string letters_;
static const std::string digits_; static const std::string digits_;
static const TransverseMercator OSGBTM_; static const TransverseMercator& OSGBTM();
static real northoffset_; static real northoffset_;
static bool init_; static bool init_;
enum { enum {
base_ = 10, base_ = 10,
tile_ = 100000, tile_ = 100000,
tilelevel_ = 5, tilelevel_ = 5,
tilegrid_ = 5, tilegrid_ = 5,
tileoffx_ = 2 * tilegrid_, tileoffx_ = 2 * tilegrid_,
tileoffy_ = 1 * tilegrid_, tileoffy_ = 1 * tilegrid_,
minx_ = - tileoffx_ * tile_, minx_ = - tileoffx_ * tile_,
skipping to change at line 86 skipping to change at line 86
* @param[out] x easting of point (meters). * @param[out] x easting of point (meters).
* @param[out] y northing of point (meters). * @param[out] y northing of point (meters).
* @param[out] gamma meridian convergence at point (degrees). * @param[out] gamma meridian convergence at point (degrees).
* @param[out] k scale of projection at point. * @param[out] k scale of projection at point.
* *
* \e lat should be in the range [&minus;90&deg;, 90&deg;]; \e lon * \e lat should be in the range [&minus;90&deg;, 90&deg;]; \e lon
* should be in the range [&minus;540&deg;, 540&deg;). * should be in the range [&minus;540&deg;, 540&deg;).
********************************************************************** / ********************************************************************** /
static void Forward(real lat, real lon, static void Forward(real lat, real lon,
real& x, real& y, real& gamma, real& k) { real& x, real& y, real& gamma, real& k) {
OSGBTM_.Forward(OriginLongitude(), lat, lon, x, y, gamma, k); OSGBTM().Forward(OriginLongitude(), lat, lon, x, y, gamma, k);
x += FalseEasting(); x += FalseEasting();
y += computenorthoffset(); y += computenorthoffset();
} }
/** /**
* Reverse projection, from OSGB coordinates to geographic. * Reverse projection, from OSGB coordinates to geographic.
* *
* @param[in] x easting of point (meters). * @param[in] x easting of point (meters).
* @param[in] y northing of point (meters). * @param[in] y northing of point (meters).
* @param[out] lat latitude of point (degrees). * @param[out] lat latitude of point (degrees).
skipping to change at line 109 skipping to change at line 109
* @param[out] k scale of projection at point. * @param[out] k scale of projection at point.
* *
* The value of \e lon returned is in the range [&minus;180&deg;, * The value of \e lon returned is in the range [&minus;180&deg;,
* 180&deg;). * 180&deg;).
********************************************************************** / ********************************************************************** /
static void Reverse(real x, real y, static void Reverse(real x, real y,
real& lat, real& lon, real& gamma, real& k) { real& lat, real& lon, real& gamma, real& k) {
x -= FalseEasting(); x -= FalseEasting();
y -= computenorthoffset(); y -= computenorthoffset();
OSGBTM_.Reverse(OriginLongitude(), x, y, lat, lon, gamma, k); OSGBTM().Reverse(OriginLongitude(), x, y, lat, lon, gamma, k);
} }
/** /**
* OSGB::Forward without returning the convergence and scale. * OSGB::Forward without returning the convergence and scale.
********************************************************************** / ********************************************************************** /
static void Forward(real lat, real lon, real& x, real& y) { static void Forward(real lat, real lon, real& x, real& y) {
real gamma, k; real gamma, k;
Forward(lat, lon, x, y, gamma, k); Forward(lat, lon, x, y, gamma, k);
} }
skipping to change at line 185 skipping to change at line 185
/** \name Inspector functions /** \name Inspector functions
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* @return \e a the equatorial radius of the Airy 1830 ellipsoid (meter s). * @return \e a the equatorial radius of the Airy 1830 ellipsoid (meter s).
* *
* This is 20923713 ft converted to meters using the rule 1 ft = * This is 20923713 ft converted to meters using the rule 1 ft =
* 10<sup>9.48401603&minus;10</sup> m. (The Airy 1830 value is returne d * 10<sup>9.48401603&minus;10</sup> m. (The Airy 1830 value is returne d
* because the OSGB projection is based on this ellipsoid.) * because the OSGB projection is based on this ellipsoid.)
********************************************************************** / ********************************************************************** /
static Math::real MajorRadius() static Math::real MajorRadius() {
// result is about 6377563.3960320664406 m // result is about 6377563.3960320664406 m
{ return real(20923713) * std::pow(real(10), real(0.48401603L) - 1); } using std::pow;
return pow(real(10), real(48401603 - 100000000) / 100000000)
* 20923713;
}
/** /**
* @return \e f the inverse flattening of the Airy 1830 ellipsoid. * @return \e f the inverse flattening of the Airy 1830 ellipsoid.
* *
* For the Airy 1830 ellipsoid, \e a = 20923713 ft and \e b = 20853810 ft; * For the Airy 1830 ellipsoid, \e a = 20923713 ft and \e b = 20853810 ft;
* thus the flattening = (20923713 &minus; 20853810)/20923713 = * thus the flattening = (20923713 &minus; 20853810)/20923713 =
* 7767/2324857 = 1/299.32496459... (The Airy 1830 value is returned * 7767/2324857 = 1/299.32496459... (The Airy 1830 value is returned
* because the OSGB projection is based on this ellipsoid.) * because the OSGB projection is based on this ellipsoid.)
********************************************************************** / ********************************************************************** /
static Math::real Flattening() static Math::real Flattening()
{ return real(20923713 - 20853810) / real(20923713); } { return real(20923713 - 20853810) / 20923713; }
/// \cond SKIP /// \cond SKIP
/** /**
* <b>DEPRECATED</b> * <b>DEPRECATED</b>
* @return \e r the inverse flattening of the Airy 1830 ellipsoid. * @return \e r the inverse flattening of the Airy 1830 ellipsoid.
********************************************************************** / ********************************************************************** /
static Math::real InverseFlattening() { return 1/Flattening(); } static Math::real InverseFlattening() { return 1/Flattening(); }
/// \endcond /// \endcond
/** /**
* @return \e k0 central scale for the OSGB projection (0.9996012717... ). * @return \e k0 central scale for the OSGB projection (0.9996012717... ).
* *
* C. J. Mugnier, Grids &amp; Datums, PE&amp;RS, Oct. 2003, states that * C. J. Mugnier, Grids &amp; Datums, PE&amp;RS, Oct. 2003, states that
* this is defined as 10<sup>9.9998268&minus;10</sup>. * this is defined as 10<sup>9.9998268&minus;10</sup>.
********************************************************************** / ********************************************************************** /
static Math::real CentralScale() static Math::real CentralScale() {
{ return std::pow(real(10), real(9998268 - 10000000) / real(10000000)); using std::pow;
} return pow(real(10), real(9998268 - 10000000) / 10000000);
}
/** /**
* @return latitude of the origin for the OSGB projection (49 degrees). * @return latitude of the origin for the OSGB projection (49 degrees).
********************************************************************** / ********************************************************************** /
static Math::real OriginLatitude() { return real(49); } static Math::real OriginLatitude() { return real(49); }
/** /**
* @return longitude of the origin for the OSGB projection (&minus;2 * @return longitude of the origin for the OSGB projection (&minus;2
* degrees). * degrees).
********************************************************************** / ********************************************************************** /
 End of changes. 7 change blocks. 
9 lines changed or deleted 13 lines changed or added


 PolarStereographic.hpp   PolarStereographic.hpp 
skipping to change at line 35 skipping to change at line 35
* *
* This is a straightforward implementation of the equations in Snyder ex cept * This is a straightforward implementation of the equations in Snyder ex cept
* that Newton's method is used to invert the projection. * that Newton's method is used to invert the projection.
* *
* Example of use: * Example of use:
* \include example-PolarStereographic.cpp * \include example-PolarStereographic.cpp
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT PolarStereographic { class GEOGRAPHICLIB_EXPORT PolarStereographic {
private: private:
typedef Math::real real; typedef Math::real real;
real tol_;
// _Cx used to be _C but g++ 3.4 has a macro of that name // _Cx used to be _C but g++ 3.4 has a macro of that name
real _a, _f, _e2, _e, _e2m, _Cx, _c; real _a, _f, _e2, _e, _e2m, _Cx, _c;
real _k0; real _k0;
static const real tol_;
static const real overflow_;
static const int numit_ = 5; static const int numit_ = 5;
static inline real overflow() {
// Overflow value s.t. atan(overflow_) = pi/2
static const real
overflow = 1 / Math::sq(std::numeric_limits<real>::epsilon());
return overflow;
}
// tan(x) for x in [-pi/2, pi/2] ensuring that the sign is right // tan(x) for x in [-pi/2, pi/2] ensuring that the sign is right
static inline real tanx(real x) { static inline real tanx(real x) {
real t = std::tan(x); using std::tan;
real t = tan(x);
// Write the tests this way to ensure that tanx(NaN()) is NaN() // Write the tests this way to ensure that tanx(NaN()) is NaN()
return x >= 0 ? (!(t < 0) ? t : overflow_) : (!(t >= 0) ? t : -overfl return x >= 0 ?
ow_); (!(t < 0) ? t : overflow()) :
(!(t >= 0) ? t : -overflow());
} }
// Return e * atanh(e * x) for f >= 0, else return // Return e * atanh(e * x) for f >= 0, else return
// - sqrt(-e2) * atan( sqrt(-e2) * x) for f < 0 // - sqrt(-e2) * atan( sqrt(-e2) * x) for f < 0
inline real eatanhe(real x) const inline real eatanhe(real x) const {
{ return _f >= 0 ? _e * Math::atanh(_e * x) : - _e * std::atan(_e * x); using std::atan;
} return _f >= 0 ? _e * Math::atanh(_e * x) : - _e * atan(_e * x);
}
public: public:
/** /**
* Constructor for a ellipsoid with * Constructor for a ellipsoid with
* *
* @param[in] a equatorial radius (meters). * @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f.
* @param[in] k0 central scale factor. * @param[in] k0 central scale factor.
* @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k0 i s * @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k0 is
* not positive. * not positive.
********************************************************************** / ********************************************************************** /
PolarStereographic(real a, real f, real k0); PolarStereographic(real a, real f, real k0);
/** /**
* Set the scale for the projection. * Set the scale for the projection.
* *
* @param[in] lat (degrees) assuming \e northp = true. * @param[in] lat (degrees) assuming \e northp = true.
* @param[in] k scale at latitude \e lat (default 1). * @param[in] k scale at latitude \e lat (default 1).
* @exception GeographicErr \e k is not positive. * @exception GeographicErr \e k is not positive.
skipping to change at line 169 skipping to change at line 179
* PolarStereographic::SetScale. * PolarStereographic::SetScale.
********************************************************************** / ********************************************************************** /
Math::real CentralScale() const { return _k0; } Math::real CentralScale() const { return _k0; }
///@} ///@}
/** /**
* A global instantiation of PolarStereographic with the WGS84 ellipsoi d * A global instantiation of PolarStereographic with the WGS84 ellipsoi d
* and the UPS scale factor. However, unlike UPS, no false easting or * and the UPS scale factor. However, unlike UPS, no false easting or
* northing is added. * northing is added.
********************************************************************** / ********************************************************************** /
static const PolarStereographic UPS; static const PolarStereographic& UPS();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP #endif // GEOGRAPHICLIB_POLARSTEREOGRAPHIC_HPP
 End of changes. 9 change blocks. 
13 lines changed or deleted 20 lines changed or added


 PolygonArea.hpp   PolygonArea.hpp 
/** /**
* \file PolygonArea.hpp * \file PolygonArea.hpp
* \brief Header for GeographicLib::PolygonArea class * \brief Header for GeographicLib::PolygonArea class
* *
* Copyright (c) Charles Karney (2010-2011) <charles@karney.com> and licens ed * Copyright (c) Charles Karney (2010-2014) <charles@karney.com> and licens ed
* under the MIT/X11 License. For more information, see * under the MIT/X11 License. For more information, see
* http://geographiclib.sourceforge.net/ * http://geographiclib.sourceforge.net/
**********************************************************************/ **********************************************************************/
#if !defined(GEOGRAPHICLIB_POLYGONAREA_HPP) #if !defined(GEOGRAPHICLIB_POLYGONAREA_HPP)
#define GEOGRAPHICLIB_POLYGONAREA_HPP 1 #define GEOGRAPHICLIB_POLYGONAREA_HPP 1
#include <GeographicLib/Geodesic.hpp> #include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/Constants.hpp> #include <GeographicLib/GeodesicExact.hpp>
#include <GeographicLib/Accumulator.hpp> #include <GeographicLib/Accumulator.hpp>
namespace GeographicLib { namespace GeographicLib {
/** /**
* \brief Polygon areas * \brief Polygon areas
* *
* This computes the area of a polygon whose edges are geodesics using th e * This computes the area of a polygon whose edges are geodesics using th e
* method given in Section 6 of * method given in Section 6 of
* - C. F. F. Karney, * - C. F. F. Karney,
skipping to change at line 48 skipping to change at line 48
* then not uniquely defined. In this case, either add an intermediate * then not uniquely defined. In this case, either add an intermediate
* vertex or add the edge ''as'' an edge (by defining its direction and * vertex or add the edge ''as'' an edge (by defining its direction and
* length). * length).
* *
* The area and perimeter are accumulated in two times the standard float ing * The area and perimeter are accumulated in two times the standard float ing
* point precision to guard against the loss of accuracy with many-sided * point precision to guard against the loss of accuracy with many-sided
* polygons. At any point you can ask for the perimeter and area so far. * polygons. At any point you can ask for the perimeter and area so far.
* There's an option to treat the points as defining a polyline instead o f a * There's an option to treat the points as defining a polyline instead o f a
* polygon; in that case, only the perimeter is computed. * polygon; in that case, only the perimeter is computed.
* *
* This is a templated class to allow it to be used with either Geodesic
and
* GeodesicExact. GeographicLib::PolygonArea and
* GeographicLib::PolygonAreaExact are typedefs for these two cases.
*
* @tparam GeodType the geodesic class to use.
*
* Example of use: * Example of use:
* \include example-PolygonArea.cpp * \include example-PolygonArea.cpp
* *
* <a href="Planimeter.1.html">Planimeter</a> is a command-line utility * <a href="Planimeter.1.html">Planimeter</a> is a command-line utility
* providing access to the functionality of PolygonArea. * providing access to the functionality of PolygonArea.
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT PolygonArea { template <class GeodType = Geodesic>
class PolygonAreaT {
private: private:
typedef Math::real real; typedef Math::real real;
Geodesic _earth; GeodType _earth;
real _area0; // Full ellipsoid area real _area0; // Full ellipsoid area
bool _polyline; // Assume polyline (don't close and skip ar ea) bool _polyline; // Assume polyline (don't close and skip ar ea)
unsigned _mask; unsigned _mask;
unsigned _num; unsigned _num;
int _crossings; int _crossings;
Accumulator<real> _areasum, _perimetersum; Accumulator<> _areasum, _perimetersum;
real _lat0, _lon0, _lat1, _lon1; real _lat0, _lon0, _lat1, _lon1;
static inline int transit(real lon1, real lon2) { static inline int transit(real lon1, real lon2) {
// Return 1 or -1 if crossing prime meridian in east or west directio n. // Return 1 or -1 if crossing prime meridian in east or west directio n.
// Otherwise return zero. // Otherwise return zero.
// Compute lon12 the same way as Geodesic::Inverse. // Compute lon12 the same way as Geodesic::Inverse.
lon1 = Math::AngNormalize(lon1); lon1 = Math::AngNormalize(lon1);
lon2 = Math::AngNormalize(lon2); lon2 = Math::AngNormalize(lon2);
real lon12 = Math::AngDiff(lon1, lon2); real lon12 = Math::AngDiff(lon1, lon2);
int cross = int cross =
lon1 < 0 && lon2 >= 0 && lon12 > 0 ? 1 : lon1 < 0 && lon2 >= 0 && lon12 > 0 ? 1 :
(lon2 < 0 && lon1 >= 0 && lon12 < 0 ? -1 : 0); (lon2 < 0 && lon1 >= 0 && lon12 < 0 ? -1 : 0);
return cross; return cross;
} }
public: public:
/** /**
* Constructor for PolygonArea. * Constructor for PolygonAreaT.
* *
* @param[in] earth the Geodesic object to use for geodesic calculation s. * @param[in] earth the Geodesic object to use for geodesic calculation s.
* By default this uses the WGS84 ellipsoid.
* @param[in] polyline if true that treat the points as defining a poly line * @param[in] polyline if true that treat the points as defining a poly line
* instead of a polygon (default = false). * instead of a polygon (default = false).
********************************************************************** / ********************************************************************** /
PolygonArea(const Geodesic& earth, bool polyline = false) PolygonAreaT(const GeodType& earth, bool polyline = false)
: _earth(earth) : _earth(earth)
, _area0(_earth.EllipsoidArea()) , _area0(_earth.EllipsoidArea())
, _polyline(polyline) , _polyline(polyline)
, _mask(Geodesic::LATITUDE | Geodesic::LONGITUDE | Geodesic::DISTANCE , _mask(GeodType::LATITUDE | GeodType::LONGITUDE | GeodType::DISTANCE
| |
(_polyline ? Geodesic::NONE : Geodesic::AREA)) (_polyline ? GeodType::NONE : GeodType::AREA))
{ Clear(); } { Clear(); }
/** /**
* Clear PolygonArea, allowing a new polygon to be started. * Clear PolygonAreaT, allowing a new polygon to be started.
********************************************************************** / ********************************************************************** /
void Clear() { void Clear() {
_num = 0; _num = 0;
_crossings = 0; _crossings = 0;
_areasum = 0; _areasum = 0;
_perimetersum = 0; _perimetersum = 0;
_lat0 = _lon0 = _lat1 = _lon1 = Math::NaN<real>(); _lat0 = _lon0 = _lat1 = _lon1 = Math::NaN();
} }
/** /**
* Add a point to the polygon or polyline. * Add a point to the polygon or polyline.
* *
* @param[in] lat the latitude of the point (degrees). * @param[in] lat the latitude of the point (degrees).
* @param[in] lon the longitude of the point (degrees). * @param[in] lon the longitude of the point (degrees).
* *
* \e lat should be in the range [&minus;90&deg;, 90&deg;] and \e * \e lat should be in the range [&minus;90&deg;, 90&deg;] and \e
* lon should be in the range [&minus;540&deg;, 540&deg;). * lon should be in the range [&minus;540&deg;, 540&deg;).
********************************************************************** / ********************************************************************** /
void AddPoint(real lat, real lon); void AddPoint(real lat, real lon);
/** /**
* Add an edge to the polygon or polyline. * Add an edge to the polygon or polyline.
* *
* @param[in] azi azimuth at current point (degrees). * @param[in] azi azimuth at current point (degrees).
* @param[in] s distance from current point to next point (meters). * @param[in] s distance from current point to next point (meters).
* *
* \e azi should be in the range [&minus;540&deg;, 540&deg;). This doe s * \e azi should be in the range [&minus;540&deg;, 540&deg;). This doe s
* nothing if no points have been added yet. Use PolygonArea::CurrentP oint * nothing if no points have been added yet. Use PolygonAreaT::Current Point
* to determine the position of the new vertex. * to determine the position of the new vertex.
********************************************************************** / ********************************************************************** /
void AddEdge(real azi, real s); void AddEdge(real azi, real s);
/** /**
* Return the results so far. * Return the results so far.
* *
* @param[in] reverse if true then clockwise (instead of counter-clockw ise) * @param[in] reverse if true then clockwise (instead of counter-clockw ise)
* traversal counts as a positive area. * traversal counts as a positive area.
* @param[in] sign if true then return a signed result for the area if * @param[in] sign if true then return a signed result for the area if
skipping to change at line 153 skipping to change at line 159
********************************************************************** / ********************************************************************** /
unsigned Compute(bool reverse, bool sign, unsigned Compute(bool reverse, bool sign,
real& perimeter, real& area) const; real& perimeter, real& area) const;
/** /**
* Return the results assuming a tentative final test point is added; * Return the results assuming a tentative final test point is added;
* however, the data for the test point is not saved. This lets you re port * however, the data for the test point is not saved. This lets you re port
* a running result for the perimeter and area as the user moves the mo use * a running result for the perimeter and area as the user moves the mo use
* cursor. Ordinary floating point arithmetic is used to accumulate th e * cursor. Ordinary floating point arithmetic is used to accumulate th e
* data for the test point; thus the area and perimeter returned are le ss * data for the test point; thus the area and perimeter returned are le ss
* accurate than if PolygonArea::AddPoint and PolygonArea::Compute are * accurate than if PolygonAreaT::AddPoint and PolygonAreaT::Compute ar e
* used. * used.
* *
* @param[in] lat the latitude of the test point (degrees). * @param[in] lat the latitude of the test point (degrees).
* @param[in] lon the longitude of the test point (degrees). * @param[in] lon the longitude of the test point (degrees).
* @param[in] reverse if true then clockwise (instead of counter-clockw ise) * @param[in] reverse if true then clockwise (instead of counter-clockw ise)
* traversal counts as a positive area. * traversal counts as a positive area.
* @param[in] sign if true then return a signed result for the area if * @param[in] sign if true then return a signed result for the area if
* the polygon is traversed in the "wrong" direction instead of retur ning * the polygon is traversed in the "wrong" direction instead of retur ning
* the area for the rest of the earth. * the area for the rest of the earth.
* @param[out] perimeter the approximate perimeter of the polygon or le ngth * @param[out] perimeter the approximate perimeter of the polygon or le ngth
skipping to change at line 182 skipping to change at line 188
********************************************************************** / ********************************************************************** /
unsigned TestPoint(real lat, real lon, bool reverse, bool sign, unsigned TestPoint(real lat, real lon, bool reverse, bool sign,
real& perimeter, real& area) const; real& perimeter, real& area) const;
/** /**
* Return the results assuming a tentative final test point is added vi a an * Return the results assuming a tentative final test point is added vi a an
* azimuth and distance; however, the data for the test point is not sa ved. * azimuth and distance; however, the data for the test point is not sa ved.
* This lets you report a running result for the perimeter and area as the * This lets you report a running result for the perimeter and area as the
* user moves the mouse cursor. Ordinary floating point arithmetic is used * user moves the mouse cursor. Ordinary floating point arithmetic is used
* to accumulate the data for the test point; thus the area and perimet er * to accumulate the data for the test point; thus the area and perimet er
* returned are less accurate than if PolygonArea::AddEdge and * returned are less accurate than if PolygonAreaT::AddEdge and
* PolygonArea::Compute are used. * PolygonAreaT::Compute are used.
* *
* @param[in] azi azimuth at current point (degrees). * @param[in] azi azimuth at current point (degrees).
* @param[in] s distance from current point to final test point (meters ). * @param[in] s distance from current point to final test point (meters ).
* @param[in] reverse if true then clockwise (instead of counter-clockw ise) * @param[in] reverse if true then clockwise (instead of counter-clockw ise)
* traversal counts as a positive area. * traversal counts as a positive area.
* @param[in] sign if true then return a signed result for the area if * @param[in] sign if true then return a signed result for the area if
* the polygon is traversed in the "wrong" direction instead of retur ning * the polygon is traversed in the "wrong" direction instead of retur ning
* the area for the rest of the earth. * the area for the rest of the earth.
* @param[out] perimeter the approximate perimeter of the polygon or le ngth * @param[out] perimeter the approximate perimeter of the polygon or le ngth
* of the polyline (meters). * of the polyline (meters).
skipping to change at line 207 skipping to change at line 213
* @return the number of points. * @return the number of points.
* *
* \e azi should be in the range [&minus;540&deg;, 540&deg;). * \e azi should be in the range [&minus;540&deg;, 540&deg;).
********************************************************************** / ********************************************************************** /
unsigned TestEdge(real azi, real s, bool reverse, bool sign, unsigned TestEdge(real azi, real s, bool reverse, bool sign,
real& perimeter, real& area) const; real& perimeter, real& area) const;
/// \cond SKIP /// \cond SKIP
/** /**
* <b>DEPRECATED</b> * <b>DEPRECATED</b>
* The old name for PolygonArea::TestPoint. * The old name for PolygonAreaT::TestPoint.
********************************************************************** / ********************************************************************** /
unsigned TestCompute(real lat, real lon, bool reverse, bool sign, unsigned TestCompute(real lat, real lon, bool reverse, bool sign,
real& perimeter, real& area) const { real& perimeter, real& area) const {
return TestPoint(lat, lon, reverse, sign, perimeter, area); return TestPoint(lat, lon, reverse, sign, perimeter, area);
} }
/// \endcond /// \endcond
/** \name Inspector functions /** \name Inspector functions
********************************************************************** / ********************************************************************** /
///@{ ///@{
skipping to change at line 245 skipping to change at line 251
* @param[out] lon the longitude of the point (degrees). * @param[out] lon the longitude of the point (degrees).
* *
* If no points have been added, then NaNs are returned. Otherwise, \e lon * If no points have been added, then NaNs are returned. Otherwise, \e lon
* will be in the range [&minus;180&deg;, 180&deg;). * will be in the range [&minus;180&deg;, 180&deg;).
********************************************************************** / ********************************************************************** /
void CurrentPoint(real& lat, real& lon) const void CurrentPoint(real& lat, real& lon) const
{ lat = _lat1; lon = _lon1; } { lat = _lat1; lon = _lon1; }
///@} ///@}
}; };
/**
* @relates PolygonAreaT
*
* Polygon areas using Geodesic. This should be used if the flattening i
s
* small.
**********************************************************************/
typedef PolygonAreaT<Geodesic> PolygonArea;
/**
* @relates PolygonAreaT
*
* Polygon areas using GeodesicExact. (But note that the implementation
of
* areas in GeodesicExact uses a high order series and this is only accur
ate
* for modest flattenings.)
**********************************************************************/
typedef PolygonAreaT<GeodesicExact> PolygonAreaExact;
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_POLYGONAREA_HPP #endif // GEOGRAPHICLIB_POLYGONAREA_HPP
 End of changes. 17 change blocks. 
18 lines changed or deleted 45 lines changed or added


 SphericalEngine.hpp   SphericalEngine.hpp 
skipping to change at line 48 skipping to change at line 48
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT SphericalEngine { class GEOGRAPHICLIB_EXPORT SphericalEngine {
private: private:
typedef Math::real real; typedef Math::real real;
// A table of the square roots of integers // A table of the square roots of integers
static std::vector<real> root_; static std::vector<real> root_;
friend class CircularEngine; // CircularEngine needs access to root_, s cale_ friend class CircularEngine; // CircularEngine needs access to root_, s cale_
// An internal scaling of the coefficients to avoid overflow in // An internal scaling of the coefficients to avoid overflow in
// intermediate calculations. // intermediate calculations.
static const real scale_; static real scale() {
using std::pow;
return pow(real(std::numeric_limits<real>::radix),
-3 * (std::numeric_limits<real>::max_exponent < (1<<14) ?
std::numeric_limits<real>::max_exponent : (1<<14)) /
5);
}
// Move latitudes near the pole off the axis by this amount. // Move latitudes near the pole off the axis by this amount.
static const real eps_; static real eps() {
using std::sqrt;
return std::numeric_limits<real>::epsilon() *
sqrt(std::numeric_limits<real>::epsilon());
}
static const std::vector<real> Z_; static const std::vector<real> Z_;
SphericalEngine(); // Disable constructor SphericalEngine(); // Disable constructor
public: public:
/** /**
* Supported normalizations for associated Legendre polynomials. * Supported normalizations for associated Legendre polynomials.
********************************************************************** / ********************************************************************** /
enum normalization { enum normalization {
/** /**
* Fully normalized associated Legendre polynomials. See * Fully normalized associated Legendre polynomials. See
* SphericalHarmonic::FULL for documentation. * SphericalHarmonic::FULL for documentation.
 End of changes. 2 change blocks. 
2 lines changed or deleted 12 lines changed or added


 SphericalHarmonic.hpp   SphericalHarmonic.hpp 
skipping to change at line 35 skipping to change at line 35
V(x, y, z) = sum(n = 0..N)[ q^(n+1) * sum(m = 0..n)[ V(x, y, z) = sum(n = 0..N)[ q^(n+1) * sum(m = 0..n)[
(C[n,m] * cos(m*lambda) + S[n,m] * sin(m*lambda)) * (C[n,m] * cos(m*lambda) + S[n,m] * sin(m*lambda)) *
P[n,m](cos(theta)) ] ] P[n,m](cos(theta)) ] ]
\endverbatim \endverbatim
* where * where
* - <i>p</i><sup>2</sup> = <i>x</i><sup>2</sup> + <i>y</i><sup>2</sup>, * - <i>p</i><sup>2</sup> = <i>x</i><sup>2</sup> + <i>y</i><sup>2</sup>,
* - <i>r</i><sup>2</sup> = <i>p</i><sup>2</sup> + <i>z</i><sup>2</sup>, * - <i>r</i><sup>2</sup> = <i>p</i><sup>2</sup> + <i>z</i><sup>2</sup>,
* - \e q = <i>a</i>/<i>r</i>, * - \e q = <i>a</i>/<i>r</i>,
* - &theta; = atan2(\e p, \e z) = the spherical \e colatitude, * - &theta; = atan2(\e p, \e z) = the spherical \e colatitude,
* - &lambda; = atan2(\e y, \e x) = the longitude. * - &lambda; = atan2(\e y, \e x) = the longitude.
* - P<sub>\e nm</sub>(\e t) is the associated Legendre polynomial of deg * - P<sub><i>nm</i></sub>(\e t) is the associated Legendre polynomial of
ree * degree \e n and order \e m.
* \e n and order \e m.
* *
* Two normalizations are supported for P<sub>\e nm</sub> * Two normalizations are supported for P<sub><i>nm</i></sub>
* - fully normalized denoted by SphericalHarmonic::FULL. * - fully normalized denoted by SphericalHarmonic::FULL.
* - Schmidt semi-normalized denoted by SphericalHarmonic::SCHMIDT. * - Schmidt semi-normalized denoted by SphericalHarmonic::SCHMIDT.
* *
* Clenshaw summation is used for the sums over both \e n and \e m. This * Clenshaw summation is used for the sums over both \e n and \e m. This
* allows the computation to be carried out without the need for any * allows the computation to be carried out without the need for any
* temporary arrays. See SphericalEngine.cpp for more information on the * temporary arrays. See SphericalEngine.cpp for more information on the
* implementation. * implementation.
* *
* References: * References:
* - C. W. Clenshaw, A note on the summation of Chebyshev series, * - C. W. Clenshaw, A note on the summation of Chebyshev series,
skipping to change at line 74 skipping to change at line 74
class GEOGRAPHICLIB_EXPORT SphericalHarmonic { class GEOGRAPHICLIB_EXPORT SphericalHarmonic {
public: public:
/** /**
* Supported normalizations for the associated Legendre polynomials. * Supported normalizations for the associated Legendre polynomials.
********************************************************************** / ********************************************************************** /
enum normalization { enum normalization {
/** /**
* Fully normalized associated Legendre polynomials. * Fully normalized associated Legendre polynomials.
* *
* These are defined by <i>P</i><sub><i>nm</i></sub><sup>full</sup>(\ * These are defined by
e z) * <i>P</i><sub><i>nm</i></sub><sup>full</sup>(\e z)
* = (&minus;1)<sup><i>m</i></sup> sqrt(\e k (2\e n + 1) (\e n &minus * = (&minus;1)<sup><i>m</i></sup>
; \e * sqrt(\e k (2\e n + 1) (\e n &minus; \e m)! / (\e n + \e m)!)
* m)! / (\e n + \e m)!)
* <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z), where * <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z), where
* <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z) is Ferrers * <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z) is Ferrers
* function (also known as the Legendre function on the cut or the * function (also known as the Legendre function on the cut or the
* associated Legendre polynomial) http://dlmf.nist.gov/14.7.E10 and \e k * associated Legendre polynomial) http://dlmf.nist.gov/14.7.E10 and \e k
* = 1 for \e m = 0 and \e k = 2 otherwise. * = 1 for \e m = 0 and \e k = 2 otherwise.
* *
* The mean squared value of * The mean squared value of
* <i>P</i><sub><i>nm</i></sub><sup>full</sup>(cos&theta;) * <i>P</i><sub><i>nm</i></sub><sup>full</sup>(cos&theta;)
* cos(<i>m</i>&lambda;) and * cos(<i>m</i>&lambda;) and
* <i>P</i><sub><i>nm</i></sub><sup>full</sup>(cos&theta;) * <i>P</i><sub><i>nm</i></sub><sup>full</sup>(cos&theta;)
* sin(<i>m</i>&lambda;) over the sphere is 1. * sin(<i>m</i>&lambda;) over the sphere is 1.
* *
* @hideinitializer * @hideinitializer
******************************************************************** **/ ******************************************************************** **/
FULL = SphericalEngine::FULL, FULL = SphericalEngine::FULL,
/** /**
* Schmidt semi-normalized associated Legendre polynomials. * Schmidt semi-normalized associated Legendre polynomials.
* *
* These are defined by <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup * These are defined by
>(\e * <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(\e z)
* z) = (&minus;1)<sup><i>m</i></sup> sqrt(\e k (\e n &minus; \e m)! * = (&minus;1)<sup><i>m</i></sup>
/ * sqrt(\e k (\e n &minus; \e m)! / (\e n + \e m)!)
* (\e n + \e m)!) <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e * <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z), where
z), * <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z) is Ferrers
* where <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z) is Ferr
ers
* function (also known as the Legendre function on the cut or the * function (also known as the Legendre function on the cut or the
* associated Legendre polynomial) http://dlmf.nist.gov/14.7.E10 and \e k * associated Legendre polynomial) http://dlmf.nist.gov/14.7.E10 and \e k
* = 1 for \e m = 0 and \e k = 2 otherwise. * = 1 for \e m = 0 and \e k = 2 otherwise.
* *
* The mean squared value of * The mean squared value of
* <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(cos&theta;) * <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(cos&theta;)
* cos(<i>m</i>&lambda;) and * cos(<i>m</i>&lambda;) and
* <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(cos&theta;) * <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(cos&theta;)
* sin(<i>m</i>&lambda;) over the sphere is 1/(2\e n + 1). * sin(<i>m</i>&lambda;) over the sphere is 1/(2\e n + 1).
* *
skipping to change at line 129 skipping to change at line 132
private: private:
typedef Math::real real; typedef Math::real real;
SphericalEngine::coeff _c[1]; SphericalEngine::coeff _c[1];
real _a; real _a;
unsigned _norm; unsigned _norm;
public: public:
/** /**
* Constructor with a full set of coefficients specified. * Constructor with a full set of coefficients specified.
* *
* @param[in] C the coefficients \e C<sub>\e nm</sub>. * @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients \e S<sub>\e nm</sub>. * @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the maximum degree and order of the sum * @param[in] N the maximum degree and order of the sum
* @param[in] a the reference radius appearing in the definition of the * @param[in] a the reference radius appearing in the definition of the
* sum. * sum.
* @param[in] norm the normalization for the associated Legendre * @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic::full (the default) or * polynomials, either SphericalHarmonic::full (the default) or
* SphericalHarmonic::schmidt. * SphericalHarmonic::schmidt.
* @exception GeographicErr if \e N does not satisfy \e N &ge; &minus;1 . * @exception GeographicErr if \e N does not satisfy \e N &ge; &minus;1 .
* @exception GeographicErr if \e C or \e S is not big enough to hold t he * @exception GeographicErr if \e C or \e S is not big enough to hold t he
* coefficients. * coefficients.
* *
* The coefficients \e C<sub>\e nm</sub> and \e S<sub>\e nm</sub> are * The coefficients <i>C</i><sub><i>nm</i></sub> and
* stored in the one-dimensional vectors \e C and \e S which must conta * <i>S</i><sub><i>nm</i></sub> are stored in the one-dimensional vecto
in rs
* (\e N + 1)(\e N + 2)/2 and N (\e N + 1)/2 elements, respectively, st * \e C and \e S which must contain (\e N + 1)(\e N + 2)/2 and \e N (\e
ored N +
* in "column-major" order. Thus for \e N = 3, the order would be: * 1)/2 elements, respectively, stored in "column-major" order. Thus f
or
* \e N = 3, the order would be:
* <i>C</i><sub>00</sub>, * <i>C</i><sub>00</sub>,
* <i>C</i><sub>10</sub>, * <i>C</i><sub>10</sub>,
* <i>C</i><sub>20</sub>, * <i>C</i><sub>20</sub>,
* <i>C</i><sub>30</sub>, * <i>C</i><sub>30</sub>,
* <i>C</i><sub>11</sub>, * <i>C</i><sub>11</sub>,
* <i>C</i><sub>21</sub>, * <i>C</i><sub>21</sub>,
* <i>C</i><sub>31</sub>, * <i>C</i><sub>31</sub>,
* <i>C</i><sub>22</sub>, * <i>C</i><sub>22</sub>,
* <i>C</i><sub>32</sub>, * <i>C</i><sub>32</sub>,
* <i>C</i><sub>33</sub>. * <i>C</i><sub>33</sub>.
skipping to change at line 174 skipping to change at line 178
SphericalHarmonic(const std::vector<real>& C, SphericalHarmonic(const std::vector<real>& C,
const std::vector<real>& S, const std::vector<real>& S,
int N, real a, unsigned norm = FULL) int N, real a, unsigned norm = FULL)
: _a(a) : _a(a)
, _norm(norm) , _norm(norm)
{ _c[0] = SphericalEngine::coeff(C, S, N); } { _c[0] = SphericalEngine::coeff(C, S, N); }
/** /**
* Constructor with a subset of coefficients specified. * Constructor with a subset of coefficients specified.
* *
* @param[in] C the coefficients \e C<sub>\e nm</sub>. * @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients \e S<sub>\e nm</sub>. * @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the degree used to determine the layout of \e C and \e S. * @param[in] N the degree used to determine the layout of \e C and \e S.
* @param[in] nmx the maximum degree used in the sum. The sum over \e n is * @param[in] nmx the maximum degree used in the sum. The sum over \e n is
* from 0 thru \e nmx. * from 0 thru \e nmx.
* @param[in] mmx the maximum order used in the sum. The sum over \e m is * @param[in] mmx the maximum order used in the sum. The sum over \e m is
* from 0 thru min(\e n, \e mmx). * from 0 thru min(\e n, \e mmx).
* @param[in] a the reference radius appearing in the definition of the * @param[in] a the reference radius appearing in the definition of the
* sum. * sum.
* @param[in] norm the normalization for the associated Legendre * @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic::FULL (the default) or * polynomials, either SphericalHarmonic::FULL (the default) or
* SphericalHarmonic::SCHMIDT. * SphericalHarmonic::SCHMIDT.
 End of changes. 7 change blocks. 
27 lines changed or deleted 25 lines changed or added


 SphericalHarmonic1.hpp   SphericalHarmonic1.hpp 
skipping to change at line 24 skipping to change at line 24
#include <GeographicLib/Constants.hpp> #include <GeographicLib/Constants.hpp>
#include <GeographicLib/SphericalEngine.hpp> #include <GeographicLib/SphericalEngine.hpp>
#include <GeographicLib/CircularEngine.hpp> #include <GeographicLib/CircularEngine.hpp>
namespace GeographicLib { namespace GeographicLib {
/** /**
* \brief Spherical harmonic series with a correction to the coefficients * \brief Spherical harmonic series with a correction to the coefficients
* *
* This classes is similar to SphericalHarmonic, except that the coeffici ents * This classes is similar to SphericalHarmonic, except that the coeffici ents
* \e C<sub>\e nm</sub> are replaced by \e C<sub>\e nm</sub> + \e tau * <i>C</i><sub><i>nm</i></sub> are replaced by
* C'<sub>\e nm</sub> (and similarly for \e S<sub>\e nm</sub>). * <i>C</i><sub><i>nm</i></sub> + \e tau <i>C'</i><sub><i>nm</i></sub> (a
nd
* similarly for <i>S</i><sub><i>nm</i></sub>).
* *
* Example of use: * Example of use:
* \include example-SphericalHarmonic1.cpp * \include example-SphericalHarmonic1.cpp
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT SphericalHarmonic1 { class GEOGRAPHICLIB_EXPORT SphericalHarmonic1 {
public: public:
/** /**
* Supported normalizations for associate Legendre polynomials. * Supported normalizations for associate Legendre polynomials.
********************************************************************** / ********************************************************************** /
skipping to change at line 68 skipping to change at line 69
private: private:
typedef Math::real real; typedef Math::real real;
SphericalEngine::coeff _c[2]; SphericalEngine::coeff _c[2];
real _a; real _a;
unsigned _norm; unsigned _norm;
public: public:
/** /**
* Constructor with a full set of coefficients specified. * Constructor with a full set of coefficients specified.
* *
* @param[in] C the coefficients \e C<sub>\e nm</sub>. * @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients \e S<sub>\e nm</sub>. * @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the maximum degree and order of the sum * @param[in] N the maximum degree and order of the sum
* @param[in] C1 the coefficients \e C'<sub>\e nm</sub>. * @param[in] C1 the coefficients <i>C'</i><sub><i>nm</i></sub>.
* @param[in] S1 the coefficients \e S'<sub>\e nm</sub>. * @param[in] S1 the coefficients <i>S'</i><sub><i>nm</i></sub>.
* @param[in] N1 the maximum degree and order of the correction * @param[in] N1 the maximum degree and order of the correction
* coefficients \e C'<sub>\e nm</sub> and \e S'<sub>\e nm</sub>. * coefficients <i>C'</i><sub><i>nm</i></sub> and
* <i>S'</i><sub><i>nm</i></sub>.
* @param[in] a the reference radius appearing in the definition of the * @param[in] a the reference radius appearing in the definition of the
* sum. * sum.
* @param[in] norm the normalization for the associated Legendre * @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic1::FULL (the default) or * polynomials, either SphericalHarmonic1::FULL (the default) or
* SphericalHarmonic1::SCHMIDT. * SphericalHarmonic1::SCHMIDT.
* @exception GeographicErr if \e N and \e N1 do not satisfy \e N &ge; * @exception GeographicErr if \e N and \e N1 do not satisfy \e N &ge;
* \e N1 &ge; &minus;1. * \e N1 &ge; &minus;1.
* @exception GeographicErr if any of the vectors of coefficients is no t * @exception GeographicErr if any of the vectors of coefficients is no t
* large enough. * large enough.
* *
skipping to change at line 109 skipping to change at line 111
, _norm(norm) { , _norm(norm) {
if (!(N1 <= N)) if (!(N1 <= N))
throw GeographicErr("N1 cannot be larger that N"); throw GeographicErr("N1 cannot be larger that N");
_c[0] = SphericalEngine::coeff(C, S, N); _c[0] = SphericalEngine::coeff(C, S, N);
_c[1] = SphericalEngine::coeff(C1, S1, N1); _c[1] = SphericalEngine::coeff(C1, S1, N1);
} }
/** /**
* Constructor with a subset of coefficients specified. * Constructor with a subset of coefficients specified.
* *
* @param[in] C the coefficients \e C<sub>\e nm</sub>. * @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients \e S<sub>\e nm</sub>. * @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the degree used to determine the layout of \e C and \e S. * @param[in] N the degree used to determine the layout of \e C and \e S.
* @param[in] nmx the maximum degree used in the sum. The sum over \e n is * @param[in] nmx the maximum degree used in the sum. The sum over \e n is
* from 0 thru \e nmx. * from 0 thru \e nmx.
* @param[in] mmx the maximum order used in the sum. The sum over \e m is * @param[in] mmx the maximum order used in the sum. The sum over \e m is
* from 0 thru min(\e n, \e mmx). * from 0 thru min(\e n, \e mmx).
* @param[in] C1 the coefficients \e C'<sub>\e nm</sub>. * @param[in] C1 the coefficients <i>C'</i><sub><i>nm</i></sub>.
* @param[in] S1 the coefficients \e S'<sub>\e nm</sub>. * @param[in] S1 the coefficients <i>S'</i><sub><i>nm</i></sub>.
* @param[in] N1 the degree used to determine the layout of \e C' and \ e * @param[in] N1 the degree used to determine the layout of \e C' and \ e
* S'. * S'.
* @param[in] nmx1 the maximum degree used for \e C' and \e S'. * @param[in] nmx1 the maximum degree used for \e C' and \e S'.
* @param[in] mmx1 the maximum order used for \e C' and \e S'. * @param[in] mmx1 the maximum order used for \e C' and \e S'.
* @param[in] a the reference radius appearing in the definition of the * @param[in] a the reference radius appearing in the definition of the
* sum. * sum.
* @param[in] norm the normalization for the associated Legendre * @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic1::FULL (the default) or * polynomials, either SphericalHarmonic1::FULL (the default) or
* SphericalHarmonic1::SCHMIDT. * SphericalHarmonic1::SCHMIDT.
* @exception GeographicErr if the parameters do not satisfy \e N &ge; \e * @exception GeographicErr if the parameters do not satisfy \e N &ge; \e
 End of changes. 6 change blocks. 
11 lines changed or deleted 14 lines changed or added


 SphericalHarmonic2.hpp   SphericalHarmonic2.hpp 
skipping to change at line 24 skipping to change at line 24
#include <GeographicLib/Constants.hpp> #include <GeographicLib/Constants.hpp>
#include <GeographicLib/SphericalEngine.hpp> #include <GeographicLib/SphericalEngine.hpp>
#include <GeographicLib/CircularEngine.hpp> #include <GeographicLib/CircularEngine.hpp>
namespace GeographicLib { namespace GeographicLib {
/** /**
* \brief Spherical harmonic series with two corrections to the coefficie nts * \brief Spherical harmonic series with two corrections to the coefficie nts
* *
* This classes is similar to SphericalHarmonic, except that the coeffici ents * This classes is similar to SphericalHarmonic, except that the coeffici ents
* \e C<sub>\e nm</sub> are replaced by \e C<sub>\e nm</sub> + \e tau' * <i>C</i><sub><i>nm</i></sub> are replaced by
* C'<sub>\e nm</sub> + \e tau'' C''<sub>\e nm</sub> (and similarly for \ * <i>C</i><sub><i>nm</i></sub> + \e tau' <i>C'</i><sub><i>nm</i></sub> +
e \e
* S<sub>\e nm</sub>). * tau'' <i>C''</i><sub><i>nm</i></sub> (and similarly for
* <i>S</i><sub><i>nm</i></sub>).
* *
* Example of use: * Example of use:
* \include example-SphericalHarmonic2.cpp * \include example-SphericalHarmonic2.cpp
**********************************************************************/ **********************************************************************/
// Don't include the GEOGRPAHIC_EXPORT because this header-only class isn 't // Don't include the GEOGRPAHIC_EXPORT because this header-only class isn 't
// used by any other classes in the library. // used by any other classes in the library.
class /*GEOGRAPHICLIB_EXPORT*/ SphericalHarmonic2 { class /*GEOGRAPHICLIB_EXPORT*/ SphericalHarmonic2 {
public: public:
/** /**
skipping to change at line 71 skipping to change at line 72
private: private:
typedef Math::real real; typedef Math::real real;
SphericalEngine::coeff _c[3]; SphericalEngine::coeff _c[3];
real _a; real _a;
unsigned _norm; unsigned _norm;
public: public:
/** /**
* Constructor with a full set of coefficients specified. * Constructor with a full set of coefficients specified.
* *
* @param[in] C the coefficients \e C<sub>\e nm</sub>. * @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients \e S<sub>\e nm</sub>. * @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the maximum degree and order of the sum * @param[in] N the maximum degree and order of the sum
* @param[in] C1 the coefficients \e C'<sub>\e nm</sub>. * @param[in] C1 the coefficients <i>C'</i><sub><i>nm</i></sub>.
* @param[in] S1 the coefficients \e S'<sub>\e nm</sub>. * @param[in] S1 the coefficients <i>S'</i><sub><i>nm</i></sub>.
* @param[in] N1 the maximum degree and order of the first correction * @param[in] N1 the maximum degree and order of the first correction
* coefficients \e C'<sub>\e nm</sub> and \e S'<sub>\e nm</sub>. * coefficients <i>C'</i><sub><i>nm</i></sub> and
* @param[in] C2 the coefficients \e C''<sub>\e nm</sub>. * <i>S'</i><sub><i>nm</i></sub>.
* @param[in] S2 the coefficients \e S''<sub>\e nm</sub>. * @param[in] C2 the coefficients <i>C''</i><sub><i>nm</i></sub>.
* @param[in] S2 the coefficients <i>S''</i><sub><i>nm</i></sub>.
* @param[in] N2 the maximum degree and order of the second correction * @param[in] N2 the maximum degree and order of the second correction
* coefficients \e C'<sub>\e nm</sub> and \e S'<sub>\e nm</sub>. * coefficients <i>C'</i><sub><i>nm</i></sub> and
* <i>S'</i><sub><i>nm</i></sub>.
* @param[in] a the reference radius appearing in the definition of the * @param[in] a the reference radius appearing in the definition of the
* sum. * sum.
* @param[in] norm the normalization for the associated Legendre * @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic2::FULL (the default) or * polynomials, either SphericalHarmonic2::FULL (the default) or
* SphericalHarmonic2::SCHMIDT. * SphericalHarmonic2::SCHMIDT.
* @exception GeographicErr if \e N and \e N1 do not satisfy \e N &ge; * @exception GeographicErr if \e N and \e N1 do not satisfy \e N &ge;
* \e N1 &ge; &minus;1, and similarly for \e N2. * \e N1 &ge; &minus;1, and similarly for \e N2.
* @exception GeographicErr if any of the vectors of coefficients is no t * @exception GeographicErr if any of the vectors of coefficients is no t
* large enough. * large enough.
* *
skipping to change at line 121 skipping to change at line 124
if (!(N1 <= N && N2 <= N)) if (!(N1 <= N && N2 <= N))
throw GeographicErr("N1 and N2 cannot be larger that N"); throw GeographicErr("N1 and N2 cannot be larger that N");
_c[0] = SphericalEngine::coeff(C, S, N); _c[0] = SphericalEngine::coeff(C, S, N);
_c[1] = SphericalEngine::coeff(C1, S1, N1); _c[1] = SphericalEngine::coeff(C1, S1, N1);
_c[2] = SphericalEngine::coeff(C2, S2, N2); _c[2] = SphericalEngine::coeff(C2, S2, N2);
} }
/** /**
* Constructor with a subset of coefficients specified. * Constructor with a subset of coefficients specified.
* *
* @param[in] C the coefficients \e C<sub>\e nm</sub>. * @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
* @param[in] S the coefficients \e S<sub>\e nm</sub>. * @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
* @param[in] N the degree used to determine the layout of \e C and \e S. * @param[in] N the degree used to determine the layout of \e C and \e S.
* @param[in] nmx the maximum degree used in the sum. The sum over \e n is * @param[in] nmx the maximum degree used in the sum. The sum over \e n is
* from 0 thru \e nmx. * from 0 thru \e nmx.
* @param[in] mmx the maximum order used in the sum. The sum over \e m is * @param[in] mmx the maximum order used in the sum. The sum over \e m is
* from 0 thru min(\e n, \e mmx). * from 0 thru min(\e n, \e mmx).
* @param[in] C1 the coefficients \e C'<sub>\e nm</sub>. * @param[in] C1 the coefficients <i>C'</i><sub><i>nm</i></sub>.
* @param[in] S1 the coefficients \e S'<sub>\e nm</sub>. * @param[in] S1 the coefficients <i>S'</i><sub><i>nm</i></sub>.
* @param[in] N1 the degree used to determine the layout of \e C' and \ e * @param[in] N1 the degree used to determine the layout of \e C' and \ e
* S'. * S'.
* @param[in] nmx1 the maximum degree used for \e C' and \e S'. * @param[in] nmx1 the maximum degree used for \e C' and \e S'.
* @param[in] mmx1 the maximum order used for \e C' and \e S'. * @param[in] mmx1 the maximum order used for \e C' and \e S'.
* @param[in] C2 the coefficients \e C''<sub>\e nm</sub>. * @param[in] C2 the coefficients <i>C''</i><sub><i>nm</i></sub>.
* @param[in] S2 the coefficients \e S''<sub>\e nm</sub>. * @param[in] S2 the coefficients <i>S''</i><sub><i>nm</i></sub>.
* @param[in] N2 the degree used to determine the layout of \e C'' and \e * @param[in] N2 the degree used to determine the layout of \e C'' and \e
* S''. * S''.
* @param[in] nmx2 the maximum degree used for \e C'' and \e S''. * @param[in] nmx2 the maximum degree used for \e C'' and \e S''.
* @param[in] mmx2 the maximum order used for \e C'' and \e S''. * @param[in] mmx2 the maximum order used for \e C'' and \e S''.
* @param[in] a the reference radius appearing in the definition of the * @param[in] a the reference radius appearing in the definition of the
* sum. * sum.
* @param[in] norm the normalization for the associated Legendre * @param[in] norm the normalization for the associated Legendre
* polynomials, either SphericalHarmonic2::FULL (the default) or * polynomials, either SphericalHarmonic2::FULL (the default) or
* SphericalHarmonic2::SCHMIDT. * SphericalHarmonic2::SCHMIDT.
* @exception GeographicErr if the parameters do not satisfy \e N &ge; \e * @exception GeographicErr if the parameters do not satisfy \e N &ge; \e
 End of changes. 8 change blocks. 
18 lines changed or deleted 21 lines changed or added


 TransverseMercator.hpp   TransverseMercator.hpp 
skipping to change at line 21 skipping to change at line 21
#define GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP 1 #define GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP 1
#include <GeographicLib/Constants.hpp> #include <GeographicLib/Constants.hpp>
#if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER) #if !defined(GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER)
/** /**
* The order of the series approximation used in TransverseMercator. * The order of the series approximation used in TransverseMercator.
* GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER can be set to any integer in [4, 8]. * GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER can be set to any integer in [4, 8].
**********************************************************************/ **********************************************************************/
# define GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER \ # define GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER \
(GEOGRAPHICLIB_PRECISION == 2 ? 6 : (GEOGRAPHICLIB_PRECISION == 1 ? 4 : 8 (GEOGRAPHICLIB_PRECISION == 2 ? 6 : \
)) (GEOGRAPHICLIB_PRECISION == 1 ? 4 : 8))
#endif #endif
namespace GeographicLib { namespace GeographicLib {
/** /**
* \brief Transverse Mercator projection * \brief Transverse Mercator projection
* *
* This uses Kr&uuml;ger's method which evaluates the projection and its * This uses Kr&uuml;ger's method which evaluates the projection and its
* inverse in terms of a series. See * inverse in terms of a series. See
* - L. Kr&uuml;ger, * - L. Kr&uuml;ger,
skipping to change at line 83 skipping to change at line 84
* *
* <a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a> is a * <a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a> is a
* command-line utility providing access to the functionality of * command-line utility providing access to the functionality of
* TransverseMercator and TransverseMercatorExact. * TransverseMercator and TransverseMercatorExact.
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT TransverseMercator { class GEOGRAPHICLIB_EXPORT TransverseMercator {
private: private:
typedef Math::real real; typedef Math::real real;
static const int maxpow_ = GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER; static const int maxpow_ = GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER;
static const real tol_;
static const real overflow_;
static const int numit_ = 5; static const int numit_ = 5;
real tol_;
real _a, _f, _k0, _e2, _e, _e2m, _c, _n; real _a, _f, _k0, _e2, _e, _e2m, _c, _n;
// _alp[0] and _bet[0] unused // _alp[0] and _bet[0] unused
real _a1, _b1, _alp[maxpow_ + 1], _bet[maxpow_ + 1]; real _a1, _b1, _alp[maxpow_ + 1], _bet[maxpow_ + 1];
static inline real overflow() {
// Overflow value s.t. atan(overflow_) = pi/2
static const real
overflow = 1 / Math::sq(std::numeric_limits<real>::epsilon());
return overflow;
}
// tan(x) for x in [-pi/2, pi/2] ensuring that the sign is right // tan(x) for x in [-pi/2, pi/2] ensuring that the sign is right
static inline real tanx(real x) { static inline real tanx(real x) {
real t = std::tan(x); using std::tan;
real t = tan(x);
// Write the tests this way to ensure that tanx(NaN()) is NaN() // Write the tests this way to ensure that tanx(NaN()) is NaN()
return x >= 0 ? (!(t < 0) ? t : overflow_) : (!(t >= 0) ? t : -overfl return x >= 0 ?
ow_); (!(t < 0) ? t : overflow()) :
(!(t >= 0) ? t : -overflow());
} }
// Return e * atanh(e * x) for f >= 0, else return // Return e * atanh(e * x) for f >= 0, else return
// - sqrt(-e2) * atan( sqrt(-e2) * x) for f < 0 // - sqrt(-e2) * atan( sqrt(-e2) * x) for f < 0
inline real eatanhe(real x) const inline real eatanhe(real x) const {
{ return _f >= 0 ? _e * Math::atanh(_e * x) : - _e * std::atan(_e * x); using std::atan;
} return _f >= 0 ? _e * Math::atanh(_e * x) : - _e * atan(_e * x);
}
real taupf(real tau) const; real taupf(real tau) const;
real tauf(real taup) const; real tauf(real taup) const;
friend class Ellipsoid; // For access to taupf, tauf. friend class Ellipsoid; // For access to taupf, tauf.
public: public:
/** /**
* Constructor for a ellipsoid with * Constructor for a ellipsoid with
* *
* @param[in] a equatorial radius (meters). * @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re. * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphe re.
* Negative \e f gives a prolate ellipsoid. If \e f > 1, set flatten * Negative \e f gives a prolate ellipsoid. If \e f &gt; 1, set
ing * flattening to 1/\e f.
* to 1/\e f.
* @param[in] k0 central scale factor. * @param[in] k0 central scale factor.
* @exception GeographicErr if \e a, (1 &minus; \e f ) \e a, or \e k0 i s * @exception GeographicErr if \e a, (1 &minus; \e f) \e a, or \e k0 is
* not positive. * not positive.
********************************************************************** / ********************************************************************** /
TransverseMercator(real a, real f, real k0); TransverseMercator(real a, real f, real k0);
/** /**
* Forward projection, from geographic to transverse Mercator. * Forward projection, from geographic to transverse Mercator.
* *
* @param[in] lon0 central meridian of the projection (degrees). * @param[in] lon0 central meridian of the projection (degrees).
* @param[in] lat latitude of point (degrees). * @param[in] lat latitude of point (degrees).
* @param[in] lon longitude of point (degrees). * @param[in] lon longitude of point (degrees).
skipping to change at line 207 skipping to change at line 218
* k0 used in the constructor and is the scale on the central meridia n. * k0 used in the constructor and is the scale on the central meridia n.
********************************************************************** / ********************************************************************** /
Math::real CentralScale() const { return _k0; } Math::real CentralScale() const { return _k0; }
///@} ///@}
/** /**
* A global instantiation of TransverseMercator with the WGS84 ellipsoi d * A global instantiation of TransverseMercator with the WGS84 ellipsoi d
* and the UTM scale factor. However, unlike UTM, no false easting or * and the UTM scale factor. However, unlike UTM, no false easting or
* northing is added. * northing is added.
********************************************************************** / ********************************************************************** /
static const TransverseMercator UTM; static const TransverseMercator& UTM();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP #endif // GEOGRAPHICLIB_TRANSVERSEMERCATOR_HPP
 End of changes. 10 change blocks. 
15 lines changed or deleted 22 lines changed or added


 TransverseMercatorExact.hpp   TransverseMercatorExact.hpp 
skipping to change at line 82 skipping to change at line 82
* \include example-TransverseMercatorExact.cpp * \include example-TransverseMercatorExact.cpp
* *
* <a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a> is a * <a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a> is a
* command-line utility providing access to the functionality of * command-line utility providing access to the functionality of
* TransverseMercator and TransverseMercatorExact. * TransverseMercator and TransverseMercatorExact.
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT TransverseMercatorExact { class GEOGRAPHICLIB_EXPORT TransverseMercatorExact {
private: private:
typedef Math::real real; typedef Math::real real;
static const real tol_;
static const real tol1_;
static const real tol2_;
static const real taytol_;
static const real overflow_;
static const int numit_ = 10; static const int numit_ = 10;
real tol_, tol1_, tol2_, taytol_;
real _a, _f, _k0, _mu, _mv, _e; real _a, _f, _k0, _mu, _mv, _e;
bool _extendp; bool _extendp;
EllipticFunction _Eu, _Ev; EllipticFunction _Eu, _Ev;
static inline real overflow() {
// Overflow value s.t. atan(overflow_) = pi/2
static const real
overflow = 1 / Math::sq(std::numeric_limits<real>::epsilon());
return overflow;
}
// tan(x) for x in [-pi/2, pi/2] ensuring that the sign is right // tan(x) for x in [-pi/2, pi/2] ensuring that the sign is right
static inline real tanx(real x) { static inline real tanx(real x) {
real t = std::tan(x); using std::tan;
real t = tan(x);
// Write the tests this way to ensure that tanx(NaN()) is NaN() // Write the tests this way to ensure that tanx(NaN()) is NaN()
return x >= 0 ? (!(t < 0) ? t : overflow_) : (!(t >= 0) ? t : -overfl return x >= 0 ?
ow_); (!(t < 0) ? t : overflow()) :
(!(t >= 0) ? t : -overflow());
} }
real taup(real tau) const; real taup(real tau) const;
real taupinv(real taup) const; real taupinv(real taup) const;
void zeta(real u, real snu, real cnu, real dnu, void zeta(real u, real snu, real cnu, real dnu,
real v, real snv, real cnv, real dnv, real v, real snv, real cnv, real dnv,
real& taup, real& lam) const; real& taup, real& lam) const;
void dwdzeta(real u, real snu, real cnu, real dnu, void dwdzeta(real u, real snu, real cnu, real dnu,
skipping to change at line 134 skipping to change at line 139
real snu, real cnu, real dnu, real snu, real cnu, real dnu,
real snv, real cnv, real dnv, real snv, real cnv, real dnv,
real& gamma, real& k) const; real& gamma, real& k) const;
public: public:
/** /**
* Constructor for a ellipsoid with * Constructor for a ellipsoid with
* *
* @param[in] a equatorial radius (meters). * @param[in] a equatorial radius (meters).
* @param[in] f flattening of ellipsoid. If \e f > 1, set flattening * @param[in] f flattening of ellipsoid. If \e f > 1, set flattenin g
* to 1/\e f. * to 1/\e f.
* @param[in] k0 central scale factor. * @param[in] k0 central scale factor.
* @param[in] extendp use extended domain. * @param[in] extendp use extended domain.
* @exception GeographicErr if \e a, \e f, or \e k0 is not positive. * @exception GeographicErr if \e a, \e f, or \e k0 is not positive.
* *
* The transverse Mercator projection has a branch point singularity at \e * The transverse Mercator projection has a branch point singularity at \e
* lat = 0 and \e lon &minus; \e lon0 = 90 (1 &minus; \e e) or (for * lat = 0 and \e lon &minus; \e lon0 = 90 (1 &minus; \e e) or (for
* TransverseMercatorExact::UTM) x = 18381 km, y = 0m. The \e extendp * TransverseMercatorExact::UTM) x = 18381 km, y = 0m. The \e extendp
* argument governs where the branch cut is placed. With \e extendp = * argument governs where the branch cut is placed. With \e extendp =
* false, the "standard" convention is followed, namely the cut is plac ed * false, the "standard" convention is followed, namely the cut is plac ed
skipping to change at line 273 skipping to change at line 278
* k0 used in the constructor and is the scale on the central meridia n. * k0 used in the constructor and is the scale on the central meridia n.
********************************************************************** / ********************************************************************** /
Math::real CentralScale() const { return _k0; } Math::real CentralScale() const { return _k0; }
///@} ///@}
/** /**
* A global instantiation of TransverseMercatorExact with the WGS84 * A global instantiation of TransverseMercatorExact with the WGS84
* ellipsoid and the UTM scale factor. However, unlike UTM, no false * ellipsoid and the UTM scale factor. However, unlike UTM, no false
* easting or northing is added. * easting or northing is added.
********************************************************************** / ********************************************************************** /
static const TransverseMercatorExact UTM; static const TransverseMercatorExact& UTM();
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP #endif // GEOGRAPHICLIB_TRANSVERSEMERCATOREXACT_HPP
 End of changes. 7 change blocks. 
10 lines changed or deleted 14 lines changed or added


 UTMUPS.hpp   UTMUPS.hpp 
skipping to change at line 33 skipping to change at line 33
* The Universal Grids: Universal Transverse Mercator (UTM) and Univers al * The Universal Grids: Universal Transverse Mercator (UTM) and Univers al
* Polar Stereographic (UPS)</a>, Defense Mapping Agency, Technical Man ual * Polar Stereographic (UPS)</a>, Defense Mapping Agency, Technical Man ual
* TM8358.2 (1989). * TM8358.2 (1989).
* . * .
* Section 2-3 defines UTM and section 3-2.4 defines UPS. This document also * Section 2-3 defines UTM and section 3-2.4 defines UPS. This document also
* includes approximate algorithms for the computation of the underlying * includes approximate algorithms for the computation of the underlying
* transverse Mercator and polar stereographic projections. Here we * transverse Mercator and polar stereographic projections. Here we
* substitute much more accurate algorithms given by * substitute much more accurate algorithms given by
* GeographicLib:TransverseMercator and GeographicLib:PolarStereographic. * GeographicLib:TransverseMercator and GeographicLib:PolarStereographic.
* These are the algorithms recommended by the NGA document * These are the algorithms recommended by the NGA document
* - <a href="https://nsgreg.nga.mil/doc/view?i=4056"> The Universal Grid * - <a href="http://earth-info.nga.mil/GandG/publications/NGA_SIG_0012_2
s _0_0_UTMUPS/NGA.SIG.0012_2.0.0_UTMUPS.pdf">
* and the Transverse Mercator and Polar Stereographic Map Projections< * The Universal Grids and the Transverse Mercator and Polar Stereograp
/a>, hic
* NGA.SIG.0012_2.0.0_UTMUPS (2014). * Map Projections</a>, NGA.SIG.0012_2.0.0_UTMUPS (2014).
* *
* In this implementation, the conversions are closed, i.e., output from * In this implementation, the conversions are closed, i.e., output from
* Forward is legal input for Reverse and vice versa. The error is about 5nm * Forward is legal input for Reverse and vice versa. The error is about 5nm
* in each direction. However, the conversion from legal UTM/UPS coordin ates * in each direction. However, the conversion from legal UTM/UPS coordin ates
* to geographic coordinates and back might throw an error if the initial * to geographic coordinates and back might throw an error if the initial
* point is within 5nm of the edge of the allowed range for the UTM/UPS * point is within 5nm of the edge of the allowed range for the UTM/UPS
* coordinates. * coordinates.
* *
* The simplest way to guarantee the closed property is to define allowed * The simplest way to guarantee the closed property is to define allowed
* ranges for the eastings and northings for UTM and UPS coordinates. Th e * ranges for the eastings and northings for UTM and UPS coordinates. Th e
skipping to change at line 78 skipping to change at line 78
* hemisphere. In addition EncodeZone accepts an optional final argument \e * hemisphere. In addition EncodeZone accepts an optional final argument \e
* abbrev, which, if false, results in the hemisphere being spelled out a s in * abbrev, which, if false, results in the hemisphere being spelled out a s in
* "38north". * "38north".
* *
* Example of use: * Example of use:
* \include example-UTMUPS.cpp * \include example-UTMUPS.cpp
**********************************************************************/ **********************************************************************/
class GEOGRAPHICLIB_EXPORT UTMUPS { class GEOGRAPHICLIB_EXPORT UTMUPS {
private: private:
typedef Math::real real; typedef Math::real real;
static const real falseeasting_[4]; static const int falseeasting_[4];
static const real falsenorthing_[4]; static const int falsenorthing_[4];
static const real mineasting_[4]; static const int mineasting_[4];
static const real maxeasting_[4]; static const int maxeasting_[4];
static const real minnorthing_[4]; static const int minnorthing_[4];
static const real maxnorthing_[4]; static const int maxnorthing_[4];
static const int epsg01N = 32601; // EPSG code for UTM 01N static const int epsg01N = 32601; // EPSG code for UTM 01N
static const int epsg60N = 32660; // EPSG code for UTM 60N static const int epsg60N = 32660; // EPSG code for UTM 60N
static const int epsgN = 32661; // EPSG code for UPS N static const int epsgN = 32661; // EPSG code for UPS N
static const int epsg01S = 32701; // EPSG code for UTM 01S static const int epsg01S = 32701; // EPSG code for UTM 01S
static const int epsg60S = 32760; // EPSG code for UTM 60S static const int epsg60S = 32760; // EPSG code for UTM 60S
static const int epsgS = 32761; // EPSG code for UPS S static const int epsgS = 32761; // EPSG code for UPS S
static real CentralMeridian(int zone) static real CentralMeridian(int zone)
{ return real(6 * zone - 183); } { return real(6 * zone - 183); }
static void CheckLatLon(real lat, real lon); static void CheckLatLon(real lat, real lon);
// Throw an error if easting or northing are outside standard ranges. If // Throw an error if easting or northing are outside standard ranges. If
skipping to change at line 408 skipping to change at line 408
/** \name Inspector functions /** \name Inspector functions
********************************************************************** / ********************************************************************** /
///@{ ///@{
/** /**
* @return \e a the equatorial radius of the WGS84 ellipsoid (meters). * @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
* *
* (The WGS84 value is returned because the UTM and UPS projections are * (The WGS84 value is returned because the UTM and UPS projections are
* based on this ellipsoid.) * based on this ellipsoid.)
********************************************************************** / ********************************************************************** /
static Math::real MajorRadius() static Math::real MajorRadius()
{ return Constants::WGS84_a<real>(); } { return Constants::WGS84_a(); }
/** /**
* @return \e f the flattening of the WGS84 ellipsoid. * @return \e f the flattening of the WGS84 ellipsoid.
* *
* (The WGS84 value is returned because the UTM and UPS projections are * (The WGS84 value is returned because the UTM and UPS projections are
* based on this ellipsoid.) * based on this ellipsoid.)
********************************************************************** / ********************************************************************** /
static Math::real Flattening() static Math::real Flattening()
{ return Constants::WGS84_f<real>(); } { return Constants::WGS84_f(); }
///@} ///@}
/// \cond SKIP /// \cond SKIP
/** /**
* <b>DEPRECATED</b> * <b>DEPRECATED</b>
* @return \e r the inverse flattening of the WGS84 ellipsoid. * @return \e r the inverse flattening of the WGS84 ellipsoid.
********************************************************************** / ********************************************************************** /
static Math::real InverseFlattening() static Math::real InverseFlattening()
{ return 1/Constants::WGS84_f<real>(); } { return 1/Constants::WGS84_f(); }
/// \endcond /// \endcond
}; };
} // namespace GeographicLib } // namespace GeographicLib
#endif // GEOGRAPHICLIB_UTMUPS_HPP #endif // GEOGRAPHICLIB_UTMUPS_HPP
 End of changes. 5 change blocks. 
14 lines changed or deleted 14 lines changed or added


 Utility.hpp   Utility.hpp 
skipping to change at line 267 skipping to change at line 267
* @tparam T the type of the argument. * @tparam T the type of the argument.
* @param[in] x the value to be converted. * @param[in] x the value to be converted.
* @param[in] p the precision used (default &minus;1). * @param[in] p the precision used (default &minus;1).
* @exception std::bad_alloc if memory for the string can't be allocate d. * @exception std::bad_alloc if memory for the string can't be allocate d.
* @return the string representation. * @return the string representation.
* *
* If \e p &ge; 0, then the number fixed format is used with p bits of * If \e p &ge; 0, then the number fixed format is used with p bits of
* precision. With p < 0, there is no manipulation of the format. * precision. With p < 0, there is no manipulation of the format.
********************************************************************** / ********************************************************************** /
template<typename T> static std::string str(T x, int p = -1) { template<typename T> static std::string str(T x, int p = -1) {
if (!std::numeric_limits<T>::is_integer && !Math::isfinite<T>(x)) std::ostringstream s;
if (p >= 0) s << std::fixed << std::setprecision(p);
s << x; return s.str();
}
/**
* Convert a Math::real object to a string.
*
* @param[in] x the value to be converted.
* @param[in] p the precision used (default &minus;1).
* @exception std::bad_alloc if memory for the string can't be allocate
d.
* @return the string representation.
*
* If \e p &ge; 0, then the number fixed format is used with p bits of
* precision. With p < 0, there is no manipulation of the format. Thi
s is
* an overload of str<T> which deals with inf and nan.
**********************************************************************
/
static std::string str(Math::real x, int p = -1) {
if (!Math::isfinite(x))
return x < 0 ? std::string("-inf") : return x < 0 ? std::string("-inf") :
(x > 0 ? std::string("inf") : std::string("nan")); (x > 0 ? std::string("inf") : std::string("nan"));
std::ostringstream s; std::ostringstream s;
if (p >= 0) s << std::fixed << std::setprecision(p); if (p >= 0) s << std::fixed << std::setprecision(p);
s << x; return s.str(); s << x; return s.str();
} }
/** /**
* Convert a string to an object of type T. * Convert a string to an object of type T.
* *
skipping to change at line 385 skipping to change at line 403
* @tparam bigendp true if the external storage format is big-endian. * @tparam bigendp true if the external storage format is big-endian.
* @param[in] str the input stream containing the data of type ExtT * @param[in] str the input stream containing the data of type ExtT
* (external). * (external).
* @param[out] array the output array of type IntT (internal). * @param[out] array the output array of type IntT (internal).
* @param[in] num the size of the array. * @param[in] num the size of the array.
* @exception GeographicErr if the data cannot be read. * @exception GeographicErr if the data cannot be read.
********************************************************************** / ********************************************************************** /
template<typename ExtT, typename IntT, bool bigendp> template<typename ExtT, typename IntT, bool bigendp>
static inline void readarray(std::istream& str, static inline void readarray(std::istream& str,
IntT array[], size_t num) { IntT array[], size_t num) {
#if GEOGRAPHICLIB_PRECISION < 4
if (sizeof(IntT) == sizeof(ExtT) && if (sizeof(IntT) == sizeof(ExtT) &&
std::numeric_limits<IntT>::is_integer == std::numeric_limits<IntT>::is_integer ==
std::numeric_limits<ExtT>::is_integer) { std::numeric_limits<ExtT>::is_integer)
// Data is compatible (aside from the issue of endian-ness). {
str.read(reinterpret_cast<char *>(array), num * sizeof(ExtT)); // Data is compatible (aside from the issue of endian-ness).
if (!str.good()) str.read(reinterpret_cast<char *>(array), num * sizeof(ExtT));
throw GeographicErr("Failure reading data");
if (bigendp != Math::bigendian) { // endian mismatch -> swap bytes
for (size_t i = num; i--;)
array[i] = Math::swab<IntT>(array[i]);
}
} else {
const int bufsize = 1024; // read this many values at a time
ExtT buffer[bufsize]; // temporary buffer
int k = int(num); // data values left to read
int i = 0; // index into output array
while (k) {
int n = (std::min)(k, bufsize);
str.read(reinterpret_cast<char *>(buffer), n * sizeof(ExtT));
if (!str.good()) if (!str.good())
throw GeographicErr("Failure reading data"); throw GeographicErr("Failure reading data");
for (int j = 0; j < n; ++j) if (bigendp != Math::bigendian) { // endian mismatch -> swap byte
// fix endian-ness and cast to IntT s
array[i++] = IntT(bigendp == Math::bigendian ? buffer[j] : for (size_t i = num; i--;)
Math::swab<ExtT>(buffer[j])); array[i] = Math::swab<IntT>(array[i]);
k -= n; }
}
else
#endif
{
const int bufsize = 1024; // read this many values at a time
ExtT buffer[bufsize]; // temporary buffer
int k = int(num); // data values left to read
int i = 0; // index into output array
while (k) {
int n = (std::min)(k, bufsize);
str.read(reinterpret_cast<char *>(buffer), n * sizeof(ExtT));
if (!str.good())
throw GeographicErr("Failure reading data");
for (int j = 0; j < n; ++j)
// fix endian-ness and cast to IntT
array[i++] = IntT(bigendp == Math::bigendian ? buffer[j] :
Math::swab<ExtT>(buffer[j]));
k -= n;
}
} }
}
return; return;
} }
/** /**
* Read data of type ExtT from a binary stream to a vector array of typ e * Read data of type ExtT from a binary stream to a vector array of typ e
* IntT. The data in the file is in (bigendp ? big : little)-endian * IntT. The data in the file is in (bigendp ? big : little)-endian
* format. * format.
* *
* @tparam ExtT the type of the objects in the binary stream (external) . * @tparam ExtT the type of the objects in the binary stream (external) .
* @tparam IntT the type of the objects in the array (internal). * @tparam IntT the type of the objects in the array (internal).
skipping to change at line 449 skipping to change at line 472
* @tparam ExtT the type of the objects in the binary stream (external) . * @tparam ExtT the type of the objects in the binary stream (external) .
* @tparam IntT the type of the objects in the array (internal). * @tparam IntT the type of the objects in the array (internal).
* @tparam bigendp true if the external storage format is big-endian. * @tparam bigendp true if the external storage format is big-endian.
* @param[out] str the output stream for the data of type ExtT (externa l). * @param[out] str the output stream for the data of type ExtT (externa l).
* @param[in] array the input array of type IntT (internal). * @param[in] array the input array of type IntT (internal).
* @param[in] num the size of the array. * @param[in] num the size of the array.
* @exception GeographicErr if the data cannot be written. * @exception GeographicErr if the data cannot be written.
********************************************************************** / ********************************************************************** /
template<typename ExtT, typename IntT, bool bigendp> template<typename ExtT, typename IntT, bool bigendp>
static inline void writearray(std::ostream& str, static inline void writearray(std::ostream& str,
const IntT array[], size_t num) { const IntT array[], size_t num) {
#if GEOGRAPHICLIB_PRECISION < 4
if (sizeof(IntT) == sizeof(ExtT) && if (sizeof(IntT) == sizeof(ExtT) &&
std::numeric_limits<IntT>::is_integer == std::numeric_limits<IntT>::is_integer ==
std::numeric_limits<ExtT>::is_integer && std::numeric_limits<ExtT>::is_integer &&
bigendp == Math::bigendian) { bigendp == Math::bigendian)
// Data is compatible (including endian-ness). {
str.write(reinterpret_cast<const char *>(array), num * sizeof(ExtT) // Data is compatible (including endian-ness).
); str.write(reinterpret_cast<const char *>(array), num * sizeof(Ext
if (!str.good()) T));
throw GeographicErr("Failure writing data");
} else {
const int bufsize = 1024; // write this many values at a time
ExtT buffer[bufsize]; // temporary buffer
int k = int(num); // data values left to write
int i = 0; // index into output array
while (k) {
int n = (std::min)(k, bufsize);
for (int j = 0; j < n; ++j)
// cast to ExtT and fix endian-ness
buffer[j] = bigendp == Math::bigendian ? ExtT(array[i++]) :
Math::swab<ExtT>(ExtT(array[i++]));
str.write(reinterpret_cast<const char *>(buffer), n * sizeof(ExtT
));
if (!str.good()) if (!str.good())
throw GeographicErr("Failure writing data"); throw GeographicErr("Failure writing data");
k -= n;
} }
} else
#endif
{
const int bufsize = 1024; // write this many values at a time
ExtT buffer[bufsize]; // temporary buffer
int k = int(num); // data values left to write
int i = 0; // index into output array
while (k) {
int n = (std::min)(k, bufsize);
for (int j = 0; j < n; ++j)
// cast to ExtT and fix endian-ness
buffer[j] = bigendp == Math::bigendian ? ExtT(array[i++]) :
Math::swab<ExtT>(ExtT(array[i++]));
str.write(reinterpret_cast<const char *>(buffer), n * sizeof(Ex
tT));
if (!str.good())
throw GeographicErr("Failure writing data");
k -= n;
}
}
return; return;
} }
/** /**
* Write data in an array of type IntT as type ExtT to a binary stream. * Write data in an array of type IntT as type ExtT to a binary stream.
* The data in the file is in (bigendp ? big : little)-endian format. * The data in the file is in (bigendp ? big : little)-endian format.
* *
* @tparam ExtT the type of the objects in the binary stream (external) . * @tparam ExtT the type of the objects in the binary stream (external) .
* @tparam IntT the type of the objects in the array (internal). * @tparam IntT the type of the objects in the array (internal).
* @tparam bigendp true if the external storage format is big-endian. * @tparam bigendp true if the external storage format is big-endian.
skipping to change at line 505 skipping to change at line 533
/** /**
* Parse a KEY VALUE line. * Parse a KEY VALUE line.
* *
* @param[in] line the input line. * @param[in] line the input line.
* @param[out] key the key. * @param[out] key the key.
* @param[out] val the value. * @param[out] val the value.
* @exception std::bad_alloc if memory for the internal strings can't b e * @exception std::bad_alloc if memory for the internal strings can't b e
* allocated. * allocated.
* @return whether a key was found. * @return whether a key was found.
* *
* A # character and everything after it are discarded. If the results is * A # character and everything after it are discarded. If the result is
* just white space, the routine returns false (and \e key and \e val a re * just white space, the routine returns false (and \e key and \e val a re
* not set). Otherwise the first token is taken to be the key and the rest * not set). Otherwise the first token is taken to be the key and the rest
* of the line (trimmed of leading and trailing white space) is the val ue. * of the line (trimmed of leading and trailing white space) is the val ue.
********************************************************************** / ********************************************************************** /
static bool ParseLine(const std::string& line, static bool ParseLine(const std::string& line,
std::string& key, std::string& val); std::string& key, std::string& val);
/**
* Set the binary precision of a real number.
*
* @param[in] ndigits the number of bits of precision. If ndigits is 0
* (the default), then determine the precision from the environment
* variable GEOGRAPHICLIB_DIGITS. If this is undefined, use ndigits
=
* 256 (i.e., about 77 decimal digits).
* @return the resulting number of bits of precision.
*
* This only has an effect when GEOGRAPHICLIB_PRECISION == 5.
**********************************************************************
/
static int set_digits(int ndigits = 0);
}; };
} // namespace GeographicLib } // namespace GeographicLib
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning (pop) # pragma warning (pop)
#endif #endif
#endif // GEOGRAPHICLIB_UTILITY_HPP #endif // GEOGRAPHICLIB_UTILITY_HPP
 End of changes. 11 change blocks. 
47 lines changed or deleted 94 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/