ADD: new track message, Entity class and Position class

This commit is contained in:
Henry Winkel
2022-12-20 17:20:35 +01:00
parent 469ecfb099
commit 98ebb563a8
2114 changed files with 482360 additions and 24 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,505 @@
/**
* \file AuxLatitude.hpp
* \brief Header for the GeographicLib::AuxLatitude and GeographicLib::AuxAngle
* classes.
*
* \note This is just sample code. It is not part of GeographicLib itself.
*
* This file is an implementation of the methods described in
* - C. F. F. Karney,
* On auxiliary latitudes,
* Technical Report, SRI International, December 2022.
* https://arxiv.org/abs/2212.05818
* .
* Copyright (c) Charles Karney (2022) <charles@karney.com> and licensed under
* the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(AUXLATITUDE_HPP)
#define AUXLATITUDE_HPP 1
#include <GeographicLib/Math.hpp>
#if !defined(GEOGRAPHICLIB_AUXLATITUDE_ORDER)
/**
* The order of the series approximation used in AuxLatitude.
* GEOGRAPHICLIB_AUXLATITUDE_ORDER can be set to one of [4, 6, 8].
**********************************************************************/
# define GEOGRAPHICLIB_AUXLATITUDE_ORDER 6
#endif
namespace GeographicLib {
/**
* \brief An accurate representation of angles.
*
* \note This is just sample code. It is not part of GeographicLib itself.
*
* This class is an implementation of the methods described in
* - C. F. F. Karney,
* On auxiliary latitudes,
* Technical Report, SRI International, December 2022.
* https://arxiv.org/abs/2212.05818
*
* An angle is represented be the \e y and \e x coordinates of a point in the
* 2d plane. The two coordinates are proportional to the sine and cosine of
* the angle. This allows angles close to the cardinal points to be
* represented accurately. Only angles in [&minus;180&deg;, 180&deg;] can be
* represented. (A possible extension would be to keep count of the number
* of turns.)
*
* @tparam T the floating-point type to use for real numbers.
**********************************************************************/
template<typename T = double>
class AuxAngle {
public:
/**
* The floating-point type for real numbers. This just connects to the
* template parameters for the class.
**********************************************************************/
typedef T real;
/**
* The constructor.
*
* @param[in] y the \e y coordinate.
* @param[in] x the \e x coordinate.
*
* \note the \e y coordinate is specified \e first.
* \warning either \e x or \e y can be infinite, but not both.
*
* The defaults (\e x = 1 and \e y = 0) are such that
* + no arguments gives an angle of 0;
* + 1 argument specifies the tangent of the angle.
**********************************************************************/
AuxAngle(real y = 0, real x = 1) : _y(y), _x(x) {}
/**
* @return the \e y component. This is the sine of the angle if the
* AuxAngle has been normalized.
**********************************************************************/
real y() const { return _y; }
/**
* @return the \e x component. This is the cosine of the angle if the
* AuxAngle has been normalized.
**********************************************************************/
real x() const { return _x; }
/**
* @return a reference to the \e y component. This allows this component
* to be altered.
**********************************************************************/
real& y() { return _y; }
/**
* @return a reference to the \e x component. This allows this component
* to be altered.
**********************************************************************/
real& x() { return _x; }
/**
* @return the AuxAngle converted to the conventional angle measured in
* degrees.
**********************************************************************/
real degrees() const;
/**
* @return the AuxAngle converted to the conventional angle measured in
* radians.
**********************************************************************/
real radians() const;
/**
* @return the tangent of the angle.
**********************************************************************/
real tan() const { return _y / _x; }
/**
* @return a new normalized AuxAngle with the point lying on the unit
* circle and the \e y and \e x components are equal to the sine and
* cosine of the angle.
**********************************************************************/
AuxAngle normalized() const;
/**
* Normalize the AuxAngle in place so that the \e y and \e x components are
* equal to the sine and cosine of the angle.
**********************************************************************/
void normalize() { *this = normalized(); }
/**
* Set the quadrant for the AuxAngle.
*
* @param[in] p the AuxAngle from which the quadrant information is taken.
* @return the new AuxAngle in the same quadrant as \e p.
**********************************************************************/
AuxAngle copyquadrant(const AuxAngle& p) const;
/**
* Add an AuxAngle.
*
* @param[in] p the AuxAngle to be added.
* @return a reference to the new AuxAngle.
*
* The addition is done in place, altering the current AuxAngle.
*
* \warning Neither *this nor \e p should have an infinite component. If
* necessary, invoke AuxAngle::normalize on these angles first.
**********************************************************************/
AuxAngle& operator+=(const AuxAngle& p);
/**
* Convert degrees to an AuxAngle.
*
* @param[in] d the angle measured in degrees.
* @return the corresponding AuxAngle.
*
* This allows a new AuxAngle to be initialized as an angle in degrees with
* @code
* AuxAngle<real> phi = AuxAngle<real>::degrees(d);
* @endcode
* This is the so-called "named constructor" idiom.
**********************************************************************/
static AuxAngle degrees(real d);
/**
* Convert radians to an AuxAngle.
*
* @param[in] r the angle measured in radians.
* @return the corresponding AuxAngle.
*
* This allows a new AuxAngle to be initialized as an angle in radians with
* @code
* AuxAngle<real> phi = AuxAngle<real>::radians(r);
* @endcode
* This is the so-called "named constructor" idiom.
**********************************************************************/
static AuxAngle radians(real r);
/**
* @return a "NaN" AuxAngle.
**********************************************************************/
static AuxAngle NaN();
/**
* Compute the absolute error in another angle.
*
* @tparam T1 the floating-point type of the other angle.
* @param[in] p the other angle
* @return the absolute error between p and *this considered as angles in
* radians.
**********************************************************************/
template<typename T1>
real AbsError(const AuxAngle<T1>& p) const;
/**
* Compute the relative error in another angle.
*
* @tparam T1 the floating-point type of the other angle.
* @param[in] p the other angle
* @return the relative error between p.tan() and this->tan().
**********************************************************************/
template<typename T1>
real RelError(const AuxAngle<T1>& p) const;
private:
real _y, _x;
};
/// \cond SKIP
template<typename T>
inline AuxAngle<T> AuxAngle<T>::degrees(real d) {
real y, x;
Math::sincosd(d, y, x);
return AuxAngle(y, x);
}
template<typename T>
inline AuxAngle<T> AuxAngle<T>::radians(real r) {
using std::sin; using std::cos;
return AuxAngle(sin(r), cos(r));
}
template<typename T>
inline T AuxAngle<T>::degrees() const {
return Math::atan2d(_y, _x);
}
template<typename T>
inline T AuxAngle<T>::radians() const {
using std::atan2; return atan2(_y, _x);
}
template<typename T> template<typename T1>
inline T AuxAngle<T>::AbsError(const AuxAngle<T1>& p) const {
using std::fabs;
return fabs((AuxAngle(-T(p.y()), T(p.x())) += *this).radians());
}
template<typename T> template<typename T1>
inline T AuxAngle<T>::RelError(const AuxAngle<T1>& p) const {
using std::fabs;
return fabs((T(p.y()) / T(p.x()) - tan()) / tan());
}
/// \endcond
/**
* \brief Conversions between auxiliary latitudes.
*
* \note This is just sample code. It is not part of GeographicLib itself.
*
* This class is an implementation of the methods described in
* - C. F. F. Karney,
* On auxiliary latitudes,
* Technical Report, SRI International, December 2022.
* https://arxiv.org/abs/2212.05818
*
* The provides accurate conversions between geographic (\e phi, &phi;),
* parametric (\e beta, &beta;), geocentric (\e theta, &theta;), rectifying
* (\e mu, &mu;), conformal (\e chi, &chi;), and authalic (\e xi, &xi;)
* latitudes for an ellipsoid of revolution. A latitude is represented by an
* AuxAngle in order to maintain precision close to the poles.
*
* The class implements two methods for the conversion:
* - Direct evaluation of the defining equations, the \e exact method. These
* equations are formulated so as to preserve relative accuracy of the
* tangent of the latitude, ensuring high accuracy near the equator and the
* poles. Newton's method is used for those conversions that can't be
* expressed in closed form.
* - Expansions in powers of &e n, the third flattening, the \e series
* method. This delivers full accuracy for abs(\e f) &le; 1/150. Here, \e
* f is the flattening of the ellipsoid.
*
* The series method is the preferred method of conversion for any conversion
* involving &mu;, &chi;, or &xi;, with abs(\e f) &le; 1/150. The equations
* for the conversions between &phi;, &beta;, and &theta; are sufficiently
* simple that the exact method should be used for such conversions and also
* for conversions with with abs(\e f) &gt; 1/150.
*
* @tparam T the floating-point type to use.
*
* Example of use:
* \include example-AuxLatitude.cpp
*
* For more information on this projection, see \ref auxlat.
**********************************************************************/
template<typename T = double>
class AuxLatitude {
public:
/**
* The floating-point type for real numbers. This just connects to the
* template parameters for the class.
**********************************************************************/
typedef T real;
/**
* The type used to represent angles.
**********************************************************************/
typedef AuxAngle<real> angle;
/**
* The different auxiliary latitudes.
**********************************************************************/
enum aux {
/**
* Geographic latitude, \e phi, &phi;
* @hideinitializer
**********************************************************************/
GEOGRAPHIC = 0,
/**
* Parametric latitude, \e beta, &beta;
* @hideinitializer
**********************************************************************/
PARAMETRIC = 1,
/**
* %Geocentric latitude, \e theta, &theta;
* @hideinitializer
**********************************************************************/
GEOCENTRIC = 2,
/**
* Rectifying latitude, \e mu, &mu;
* @hideinitializer
**********************************************************************/
RECTIFYING = 3,
/**
* Conformal latitude, \e chi, &chi;
* @hideinitializer
**********************************************************************/
CONFORMAL = 4,
/**
* Authalic latitude, \e xi, &xi;
* @hideinitializer
**********************************************************************/
AUTHALIC = 5,
/**
* The total number of auxiliary latitudes
* @hideinitializer
**********************************************************************/
AUXNUMBER = 6,
/**
* An alias for GEOGRAPHIC
* @hideinitializer
**********************************************************************/
COMMON = GEOGRAPHIC,
/**
* An alias for GEOGRAPHIC
* @hideinitializer
**********************************************************************/
GEODETIC = GEOGRAPHIC,
/**
* An alias for PARAMETRIC
* @hideinitializer
**********************************************************************/
REDUCED = PARAMETRIC,
};
/**
* Constructor
*
* @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
* Negative \e f gives a prolate ellipsoid.
*
* \note the constructor does not precompute the coefficients for the
* Fourier series for the series conversions. These are computed and saved
* when first needed.
**********************************************************************/
AuxLatitude(real f);
/**
* Constructor
*
* @param[in] a equatorial radius.
* @param[in] b polar semi-axis.
*
* \note the constructor does not precompute the coefficients for the
* Fourier series for the series conversions. These are computed and saved
* when first needed.
**********************************************************************/
AuxLatitude(real a, real b);
/**
* Convert between any two auxiliary latitudes.
*
* @param[in] auxin an AuxLatitude::aux indicating the type of
* auxiliary latitude \e zeta.
* @param[in] auxout an AuxLatitude::aux indicating the type of
* auxiliary latitude \e eta.
* @param[in] zeta the input auxiliary latitude.
* @param[in] series if true use the Taylor series instead of the exact
* equations [default false].
* @return the output auxiliary latitude \e eta.
*
* With \e series = true, the Fourier coefficients for a specific \e auxin
* and \e auxout are computed and saved on the first call; the saved
* coefficients are used on subsequent calls. The series method is
* accurate for abs(\e f) &le; 1/150; for other \e f, the exact method
* should be used
**********************************************************************/
angle Convert(int auxin, int auxout, const angle& zeta,
bool series = false) const;
/**
* Convert geographic latitude to an auxiliary latitude \e eta.
*
* @param[in] auxout an AuxLatitude::aux indicating the auxiliary
* latitude returned.
* @param[in] phi the geographic latitude.
* @param[out] diff optional pointer to the derivative d tan(\e eta) / d
* tan(\e phi).
* @return the auxiliary latitude \e eta.
*
* This uses the exact equations.
**********************************************************************/
angle ToAuxiliary(int auxout, const angle& phi,
real* diff = nullptr) const;
/**
* Convert an auxiliary latitude \e zeta to geographic latitude.
*
* @param[in] auxin an AuxLatitude::aux indicating the type of
* auxiliary latitude \e zeta.
* @param[in] zeta the input auxiliary latitude.
* @param[out] niter optional pointer to the number of iterations.
* @return the geographic latitude \e phi.
*
* This uses the exact equations.
**********************************************************************/
angle FromAuxiliary(int auxin, const angle& zeta,
int* niter = nullptr) const;
/**
* @return \e f, the flattening of the ellipsoid.
**********************************************************************/
real Flattening() const { return _f; }
/**
* The order of the series expansions. This is set at compile time to
* either 4, 6, or 8, by the preprocessor macro
* GEOGRAPHICLIB_AUXLATITUDE_ORDER.
* @hideinitializer
**********************************************************************/
static const int Lmax = GEOGRAPHICLIB_AUXLATITUDE_ORDER;
private:
/**
* Convert geographic latitude to parametric latitude
*
* @param[in] phi geographic latitude.
* @param[out] diff optional pointer to the derivative d tan(\e beta) / d
* tan(\e phi).
* @return \e beta, the parametric latitude
**********************************************************************/
angle Parametric(const angle& phi, real* diff = nullptr) const;
/**
* Convert geographic latitude to geocentric latitude
*
* @param[in] phi geographic latitude.
* @param[out] diff optional pointer to the derivative d tan(\e theta) / d
* tan(\e phi).
* @return \e theta, the geocentric latitude.
**********************************************************************/
angle Geocentric(const angle& phi, real* diff = nullptr) const;
/**
* Convert geographic latitude to rectifying latitude
*
* @param[in] phi geographic latitude.
* @param[out] diff optional pointer to the derivative d tan(\e mu) / d
* tan(\e phi).
* @return \e mu, the rectifying latitude.
**********************************************************************/
angle Rectifying(const angle& phi, real* diff = nullptr) const;
/**
* Convert geographic latitude to conformal latitude
*
* @param[in] phi geographic latitude.
* @param[out] diff optional pointer to the derivative d tan(\e chi) / d
* tan(\e phi).
* @return \e chi, the conformal latitude.
**********************************************************************/
angle Conformal(const angle& phi, real* diff = nullptr) const;
/**
* Convert geographic latitude to authalic latitude
*
* @param[in] phi geographic latitude.
* @param[out] diff optional pointer to the derivative d tan(\e xi) / d
* tan(\e phi).
* @return \e xi, the authalic latitude.
**********************************************************************/
angle Authalic(const angle& phi, real* diff = nullptr) const;
// Maximum number of iterations for Newton's method
static const int numit_ = 1000;
real tol_, bmin_, bmax_; // Static consts for Newton's method
// Ellipsoid parameters
real _f, _fm1, _e2, _e2m1, _e12, _e12p1, _n, _e, _e1, _n2, _q;
// To hold computed Fourier coefficients
mutable real _c[Lmax * AUXNUMBER * AUXNUMBER];
// 1d index into AUXNUMBER x AUXNUMBER data
static int ind(int auxout, int auxin) {
return (auxout >= 0 && auxout < AUXNUMBER &&
auxin >= 0 && auxin < AUXNUMBER) ?
AUXNUMBER * auxout + auxin : -1;
}
// the function sqrt(1 + tphi^2), convert tan to sec
static real sc(real tphi)
{ using std::hypot; return hypot(real(1), tphi); }
// the function tphi / sqrt(1 + tphi^2), convert tan to sin
static real sn(real tphi) {
using std::isfinite; using std::isnan; using std::copysign;
return isfinite(tphi) || isnan(tphi) ? tphi / sc(tphi) :
copysign(real(1), tphi);
}
// The symmetric elliptic integral RD
static real RD(real x, real y, real z);
// The symmetric elliptic integral RF
static real RF(real x, real y, real z);
// the function atanh(e * sphi)/e; works for e^2 = 0 and e^2 < 0
real atanhee(real tphi) const;
// the function atanh(e * sphi)/e + sphi / (1 - (e * sphi)^2);
real q(real tphi) const;
// The divided difference of (q(1) - q(sphi)) / (1 - sphi)
real Dq(real tphi) const;
// Populate [_c[Lmax * k], _c[Lmax * (k + 1)])
void fillcoeff(int auxin, int auxout, int k) const;
// Clenshaw applied to sum(c[k] * sin( (2*k+2) * zeta), i, 0, K-1)
// if alt, use the Reinsch optimizations
static real Clenshaw(real szeta, real czeta, const real c[], int K,
bool alt = true);
};
} // namespace GeographicLib
#endif // AUXLATITUDE_HPP

View File

@@ -0,0 +1,169 @@
# This CMakeLists.txt is invoked in two different ways
# (1) With "add_subdirectory (examples)" from GeographicLib's top-level
# CMakeLists.txt. This mode of invocation is flagged by the variable
#
# CALLED_FROM_TOPLEVEL
#
# In this case, the only action taken is to install the examples and
# this CMakeLists.txt in ${EXAMPLEDIR}.
# (2) As an independent invocation of
#
# cmake -S <this-directory> -B <build-directory>
#
# In this case, find_package (GeographicLib) is called and the examples
# are compiled. This mode of invocation is triggered by the
# exampleprograms target in the top-level CMakeLists.txt. In this case,
# the current version of GeographicLib is found by specifying
#
# -D GeographicLib_DIR=${PROJECT_BINARY_DIR}
cmake_minimum_required (VERSION 3.13.0)
set (EXAMPLES0
example-Accumulator.cpp
example-AlbersEqualArea.cpp
example-AzimuthalEquidistant.cpp
example-CassiniSoldner.cpp
example-CircularEngine.cpp
example-Constants.cpp
example-DMS.cpp
example-DST.cpp
example-Ellipsoid.cpp
example-EllipticFunction.cpp
example-GARS.cpp
example-GeoCoords.cpp
example-Geocentric.cpp
example-Geodesic.cpp
example-Geodesic-small.cpp
example-GeodesicExact.cpp
example-GeodesicLine.cpp
example-GeodesicLineExact.cpp
example-GeographicErr.cpp
example-Geohash.cpp
example-Geoid.cpp
example-Georef.cpp
example-Gnomonic.cpp
example-GravityCircle.cpp
example-GravityModel.cpp
example-LambertConformalConic.cpp
example-LocalCartesian.cpp
example-MGRS.cpp
example-MagneticCircle.cpp
example-MagneticModel.cpp
example-Math.cpp
example-NearestNeighbor.cpp
example-NormalGravity.cpp
example-OSGB.cpp
example-PolarStereographic.cpp
example-PolygonArea.cpp
example-Rhumb.cpp
example-RhumbLine.cpp
example-SphericalEngine.cpp
example-SphericalHarmonic.cpp
example-SphericalHarmonic1.cpp
example-SphericalHarmonic2.cpp
example-TransverseMercator.cpp
example-TransverseMercatorExact.cpp
example-UTMUPS.cpp
example-Utility.cpp
)
set (EXAMPLES1
GeoidToGTX.cpp make-egmcof.cpp JacobiConformal.cpp example-AuxLatitude.cpp)
set (EXAMPLEHEADERS JacobiConformal.hpp AuxLatitude.cpp AuxLatitude.hpp)
if (CALLED_FROM_TOPLEVEL)
if (EXAMPLEDIR)
install (FILES CMakeLists.txt ${EXAMPLES0} ${EXAMPLES1} ${EXAMPLEHEADERS}
DESTINATION ${EXAMPLEDIR})
endif ()
# No more to do in add_subdirectory mode, so exit
return ()
endif ()
project (GeographicLib-examples)
# Set a default build type for single-configuration cmake generators if
# no build type is set.
if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
set (CMAKE_BUILD_TYPE Release)
endif ()
if (MSVC OR CMAKE_CONFIGURATION_TYPES)
# For multi-config systems and for Visual Studio, the debug version of
# the library is called Geographic_d.
set (CMAKE_DEBUG_POSTFIX "_d" CACHE STRING "The suffix for debug objects")
else ()
set (CMAKE_DEBUG_POSTFIX "" CACHE STRING "The suffix for debug objects")
endif ()
find_package (GeographicLib 2.0 REQUIRED)
include_directories (${GeographicLib_INCLUDE_DIRS})
option (USE_BOOST_FOR_EXAMPLES
"Look for Boost library when compiling examples" ON)
if (USE_BOOST_FOR_EXAMPLES)
# quad precision numbers appeared in Boost 1.54. Various
# workarounds stopped being needed with Boost 1.64.
find_package (Boost 1.64 COMPONENTS serialization)
elseif (GEOGRAPHICLIB_PRECISION EQUAL 4)
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
find_package (Boost 1.64)
endif ()
endif ()
# Compile a bunch of tiny example programs. These are built with the
# "exampleprograms" target. These are mainly for including as examples
# within the doxygen documentation; however, compiling them catches some
# obvious blunders.
if (NOT GEOGRAPHICLIB_PRECISION OR GEOGRAPHICLIB_PRECISION EQUAL 2)
# These examples all assume real = double, so check
# GEOGRAPHICLIB_PRECISION. Allow GEOGRAPHICLIB_PRECISION to be unset
# to accommodate lame FindGeographicLib.cmake.
set (EXAMPLE_SOURCES ${EXAMPLES0})
if (USE_BOOST_FOR_EXAMPLES AND Boost_FOUND)
add_definitions (-DGEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION=1)
include_directories ("${Boost_INCLUDE_DIRS}")
endif ()
else ()
set (EXAMPLE_SOURCES)
endif ()
set (EXAMPLE_SOURCES ${EXAMPLE_SOURCES} ${EXAMPLES1})
set (EXAMPLES)
foreach (EXAMPLE_SOURCE ${EXAMPLE_SOURCES})
get_filename_component (EXAMPLE ${EXAMPLE_SOURCE} NAME_WE)
set (EXAMPLES ${EXAMPLES} ${EXAMPLE})
if (EXAMPLE STREQUAL "JacobiConformal")
set (EXAMPLE_SOURCE ${EXAMPLE_SOURCE} JacobiConformal.hpp)
endif ()
if (EXAMPLE STREQUAL "example-AuxLatitude")
set (EXAMPLE_SOURCE ${EXAMPLE_SOURCE} AuxLatitude.cpp AuxLatitude.hpp)
endif ()
add_executable (${EXAMPLE} ${EXAMPLE_SOURCE})
target_link_libraries (${EXAMPLE}
${GeographicLib_LIBRARIES} ${GeographicLib_HIGHPREC_LIBRARIES})
endforeach ()
if (Boost_FOUND AND GEOGRAPHICLIB_PRECISION EQUAL 2)
target_link_libraries (example-NearestNeighbor ${Boost_LIBRARIES})
endif ()
find_package (OpenMP QUIET)
if (OPENMP_FOUND OR OpenMP_FOUND)
set_target_properties (GeoidToGTX PROPERTIES
COMPILE_FLAGS ${OpenMP_CXX_FLAGS})
if (NOT WIN32)
set_target_properties (GeoidToGTX PROPERTIES
LINK_FLAGS ${OpenMP_CXX_FLAGS})
endif ()
endif ()
if (MSVC OR CMAKE_CONFIGURATION_TYPES)
# Add _d suffix for your debug versions of the tools
set_target_properties (${EXAMPLES} PROPERTIES
DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
endif ()

View File

@@ -0,0 +1,111 @@
// Write out a gtx file of geoid heights above the ellipsoid. For egm2008 at
// 1' resolution this takes about 10 mins on a 8-processor Intel 3.0 GHz
// machine using OpenMP.
//
// For the format of gtx files, see
// https://vdatum.noaa.gov/docs/gtx_info.html#dev_gtx_binary
//
// data is binary big-endian:
// south latitude edge (degrees double)
// west longitude edge (degrees double)
// delta latitude (degrees double)
// delta longitude (degrees double)
// nlat = number of latitude rows (integer)
// nlong = number of longitude columns (integer)
// nlat * nlong geoid heights (meters float)
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#if defined(_OPENMP)
#define HAVE_OPENMP 1
#else
#define HAVE_OPENMP 0
#endif
#if HAVE_OPENMP
# include <omp.h>
#endif
#include <GeographicLib/GravityModel.hpp>
#include <GeographicLib/GravityCircle.hpp>
#include <GeographicLib/Utility.hpp>
using namespace std;
using namespace GeographicLib;
int main(int argc, const char* const argv[]) {
// Hardwired for 3 args:
// 1 = the gravity model (e.g., egm2008)
// 2 = intervals per degree
// 3 = output GTX file
if (argc != 4) {
cerr << "Usage: " << argv[0]
<< " gravity-model intervals-per-degree output.gtx\n";
return 1;
}
try {
// Will need to set the precision for each thread, so save return value
int ndigits = Utility::set_digits();
string model(argv[1]);
// Number of intervals per degree
int ndeg = Utility::val<int>(string(argv[2]));
string filename(argv[3]);
GravityModel g(model);
int
nlat = 180 * ndeg + 1,
nlon = 360 * ndeg;
Math::real
delta = 1 / Math::real(ndeg), // Grid spacing
latorg = -90,
lonorg = -180;
// Write results as floats in binary mode
ofstream file(filename.c_str(), ios::binary);
// Write header
{
Math::real transform[] = {latorg, lonorg, delta, delta};
unsigned sizes[] = {unsigned(nlat), unsigned(nlon)};
Utility::writearray<double, Math::real, true>(file, transform, 4);
Utility::writearray<unsigned, unsigned, true>(file, sizes, 2);
}
// Compute and store results for nbatch latitudes at a time
const int nbatch = 64;
vector< vector<float> > N(nbatch, vector<float>(nlon));
for (int ilat0 = 0; ilat0 < nlat; ilat0 += nbatch) { // Loop over batches
int nlat0 = min(nlat, ilat0 + nbatch);
#if HAVE_OPENMP
# pragma omp parallel for
#endif
for (int ilat = ilat0; ilat < nlat0; ++ilat) { // Loop over latitudes
Utility::set_digits(ndigits); // Set the precision
Math::real
lat = latorg + (ilat / ndeg) + delta * (ilat - ndeg * (ilat / ndeg)),
h = 0;
GravityCircle c(g.Circle(lat, h, GravityModel::GEOID_HEIGHT));
for (int ilon = 0; ilon < nlon; ++ilon) { // Loop over longitudes
Math::real lon = lonorg
+ (ilon / ndeg) + delta * (ilon - ndeg * (ilon / ndeg));
N[ilat - ilat0][ilon] = float(c.GeoidHeight(lon));
} // longitude loop
} // latitude loop -- end of parallel section
for (int ilat = ilat0; ilat < nlat0; ++ilat) // write out data
Utility::writearray<float, float, true>(file, N[ilat - ilat0]);
} // batch loop
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
catch (...) {
cerr << "Caught unknown exception\n";
return 1;
}
}

View File

@@ -0,0 +1,43 @@
// Example of using the GeographicLib::JacobiConformal class.
#include <iostream>
#include <iomanip>
#include <exception>
#include <GeographicLib/Utility.hpp>
#include "JacobiConformal.hpp"
using namespace std;
using namespace GeographicLib;
int main() {
try {
Utility::set_digits();
// These parameters were derived from the EGM2008 geoid; see 2011-07-04
// E-mail to PROJ.4 list, "Analyzing the bumps in the EGM2008 geoid". The
// longitude of the major axis is -15. These are close to the values given
// by Milan Bursa, Vladimira Fialova, "Parameters of the Earth's tri-axial
// level ellipsoid", Studia Geophysica et Geodaetica 37(1), 1-13 (1993):
//
// longitude of major axis = -14.93 +/- 0.05
// a = 6378171.36 +/- 0.30
// a/(a-c) = 297.7738 +/- 0.0003
// a/(a-b) = 91449 +/- 60
// which gives: a = 6378171.36, b = 6378101.61, c = 6356751.84
Math::real a = 6378137+35, b = 6378137-35, c = 6356752;
JacobiConformal jc(a, b, c, a-b, b-c);
cout << fixed << setprecision(1)
<< "Ellipsoid parameters: a = "
<< a << ", b = " << b << ", c = " << c << "\n"
<< setprecision(10)
<< "Quadrants: x = " << jc.x() << ", y = " << jc.y() << "\n";
cout << "Coordinates (angle x y) in degrees:\n";
for (int i = 0; i <= 90; i += 5) {
Math::real omg = i, bet = i;
cout << i << " " << jc.x(omg) << " " << jc.y(bet) << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,176 @@
/**
* \file JacobiConformal.hpp
* \brief Header for GeographicLib::JacobiConformal class
*
* \note This is just sample code. It is not part of GeographicLib
* itself.
*
* Copyright (c) Charles Karney (2014-2020) <charles@karney.com> and licensed
* under the MIT/X11 License. For more information, see
* https://geographiclib.sourceforge.io/
**********************************************************************/
#if !defined(GEOGRAPHICLIB_JACOBICONFORMAL_HPP)
#define GEOGRAPHICLIB_JACOBICONFORMAL_HPP 1
#include <GeographicLib/EllipticFunction.hpp>
namespace GeographicLib {
/**
* \brief Jacobi's conformal projection of a triaxial ellipsoid
*
* <b>NOTE:</b> This is just sample code. It is not part of GeographicLib
* itself.
*
* This is a conformal projection of the ellipsoid to a plane in which
* the grid lines are straight; see Jacobi,
* <a href="https://books.google.com/books?id=ryEOAAAAQAAJ&pg=PA212">
* Vorlesungen &uuml;ber Dynamik, &sect;28</a>. The constructor takes the
* semi-axes of the ellipsoid (which must be in order). Member functions map
* the ellipsoidal coordinates &omega; and &beta; separately to \e x and \e
* y. Jacobi's coordinates have been multiplied by
* (<i>a</i><sup>2</sup>&minus;<i>c</i><sup>2</sup>)<sup>1/2</sup> /
* (2<i>b</i>) so that the customary results are returned in the cases of
* a sphere or an ellipsoid of revolution.
*
* The ellipsoid is oriented so that the large principal ellipse, \f$Z=0\f$,
* is the equator, \f$\beta=0\f$, while the small principal ellipse,
* \f$Y=0\f$, is the prime meridian, \f$\omega=0\f$. The four umbilic
* points, \f$\left|\omega\right| = \left|\beta\right| = \frac12\pi\f$, lie
* on middle principal ellipse in the plane \f$X=0\f$.
*
* For more information on this projection, see \ref jacobi.
**********************************************************************/
class JacobiConformal {
typedef Math::real real;
real _a, _b, _c, _ab2, _bc2, _ac2;
EllipticFunction _ex, _ey;
static void norm(real& x, real& y) {
using std::hypot;
real z = hypot(x, y); x /= z; y /= z;
}
public:
/**
* Constructor for a trixial ellipsoid with semi-axes.
*
* @param[in] a the largest semi-axis.
* @param[in] b the middle semi-axis.
* @param[in] c the smallest semi-axis.
*
* The semi-axes must satisfy \e a &ge; \e b &ge; \e c > 0 and \e a >
* \e c. This form of the constructor cannot be used to specify a
* sphere (use the next constructor).
**********************************************************************/
JacobiConformal(real a, real b, real c)
: _a(a), _b(b), _c(c)
, _ab2((_a - _b) * (_a + _b))
, _bc2((_b - _c) * (_b + _c))
, _ac2((_a - _c) * (_a + _c))
, _ex(_ab2 / _ac2 * Math::sq(_c / _b), -_ab2 / Math::sq(_b),
_bc2 / _ac2 * Math::sq(_a / _b), Math::sq(_a / _b))
, _ey(_bc2 / _ac2 * Math::sq(_a / _b), +_bc2 / Math::sq(_b),
_ab2 / _ac2 * Math::sq(_c / _b), Math::sq(_c / _b))
{
using std::isfinite;
if (!(isfinite(_a) && _a >= _b && _b >= _c && _c > 0))
throw GeographicErr("JacobiConformal: axes are not in order");
if (!(_a > _c))
throw GeographicErr
("JacobiConformal: use alternate constructor for sphere");
}
/**
* Alternate constructor for a triaxial ellipsoid.
*
* @param[in] a the largest semi-axis.
* @param[in] b the middle semi-axis.
* @param[in] c the smallest semi-axis.
* @param[in] ab the relative magnitude of \e a &minus; \e b.
* @param[in] bc the relative magnitude of \e b &minus; \e c.
*
* This form can be used to specify a sphere. The semi-axes must
* satisfy \e a &ge; \e b &ge; c > 0. The ratio \e ab : \e bc must equal
* (<i>a</i>&minus;<i>b</i>) : (<i>b</i>&minus;<i>c</i>) with \e ab
* &ge; 0, \e bc &ge; 0, and \e ab + \e bc > 0.
**********************************************************************/
JacobiConformal(real a, real b, real c, real ab, real bc)
: _a(a), _b(b), _c(c)
, _ab2(ab * (_a + _b))
, _bc2(bc * (_b + _c))
, _ac2(_ab2 + _bc2)
, _ex(_ab2 / _ac2 * Math::sq(_c / _b),
-(_a - _b) * (_a + _b) / Math::sq(_b),
_bc2 / _ac2 * Math::sq(_a / _b), Math::sq(_a / _b))
, _ey(_bc2 / _ac2 * Math::sq(_a / _b),
+(_b - _c) * (_b + _c) / Math::sq(_b),
_ab2 / _ac2 * Math::sq(_c / _b), Math::sq(_c / _b))
{
using std::isfinite;
if (!(isfinite(_a) && _a >= _b && _b >= _c && _c > 0 &&
ab >= 0 && bc >= 0))
throw GeographicErr("JacobiConformal: axes are not in order");
if (!(ab + bc > 0 && isfinite(_ac2)))
throw GeographicErr("JacobiConformal: ab + bc must be positive");
}
/**
* @return the quadrant length in the \e x direction.
**********************************************************************/
Math::real x() const { return Math::sq(_a / _b) * _ex.Pi(); }
/**
* The \e x projection.
*
* @param[in] somg sin(&omega;).
* @param[in] comg cos(&omega;).
* @return \e x.
**********************************************************************/
Math::real x(real somg, real comg) const {
real somg1 = _b * somg, comg1 = _a * comg; norm(somg1, comg1);
return Math::sq(_a / _b)
* _ex.Pi(somg1, comg1, _ex.Delta(somg1, comg1));
}
/**
* The \e x projection.
*
* @param[in] omg &omega; (in degrees).
* @return \e x (in degrees).
*
* &omega; must be in [&minus;180&deg;, 180&deg;].
**********************************************************************/
Math::real x(real omg) const {
real somg, comg;
Math::sincosd(omg, somg, comg);
return x(somg, comg) / Math::degree();
}
/**
* @return the quadrant length in the \e y direction.
**********************************************************************/
Math::real y() const { return Math::sq(_c / _b) * _ey.Pi(); }
/**
* The \e y projection.
*
* @param[in] sbet sin(&beta;).
* @param[in] cbet cos(&beta;).
* @return \e y.
**********************************************************************/
Math::real y(real sbet, real cbet) const {
real sbet1 = _b * sbet, cbet1 = _c * cbet; norm(sbet1, cbet1);
return Math::sq(_c / _b)
* _ey.Pi(sbet1, cbet1, _ey.Delta(sbet1, cbet1));
}
/**
* The \e y projection.
*
* @param[in] bet &beta; (in degrees).
* @return \e y (in degrees).
*
* &beta; must be in (&minus;180&deg;, 180&deg;].
**********************************************************************/
Math::real y(real bet) const {
real sbet, cbet;
Math::sincosd(bet, sbet, cbet);
return y(sbet, cbet) / Math::degree();
}
};
} // namespace GeographicLib
#endif // GEOGRAPHICLIB_JACOBICONFORMAL_HPP

View File

@@ -0,0 +1,57 @@
#
# Makefile.am
#
# Copyright (C) 2011, Charles Karney <charles@karney.com>
EXAMPLE_FILES = \
example-Accumulator.cpp \
example-AlbersEqualArea.cpp \
example-AzimuthalEquidistant.cpp \
example-CassiniSoldner.cpp \
example-CircularEngine.cpp \
example-Constants.cpp \
example-DMS.cpp \
example-DST.cpp \
example-Ellipsoid.cpp \
example-EllipticFunction.cpp \
example-GARS.cpp \
example-GeoCoords.cpp \
example-Geocentric.cpp \
example-Geodesic.cpp \
example-Geodesic-small.cpp \
example-GeodesicExact.cpp \
example-GeodesicLine.cpp \
example-GeodesicLineExact.cpp \
example-GeographicErr.cpp \
example-Geohash.cpp \
example-Geoid.cpp \
example-Georef.cpp \
example-Gnomonic.cpp \
example-GravityCircle.cpp \
example-GravityModel.cpp \
example-LambertConformalConic.cpp \
example-LocalCartesian.cpp \
example-MGRS.cpp \
example-MagneticCircle.cpp \
example-MagneticModel.cpp \
example-Math.cpp \
example-NearestNeighbor.cpp \
example-NormalGravity.cpp \
example-OSGB.cpp \
example-PolarStereographic.cpp \
example-PolygonArea.cpp \
example-Rhumb.cpp \
example-RhumbLine.cpp \
example-SphericalEngine.cpp \
example-SphericalHarmonic.cpp \
example-SphericalHarmonic1.cpp \
example-SphericalHarmonic2.cpp \
example-TransverseMercator.cpp \
example-TransverseMercatorExact.cpp \
example-UTMUPS.cpp \
example-Utility.cpp \
GeoidToGTX.cpp \
JacobiConformal.cpp JacobiConformal.hpp \
make-egmcof.cpp
EXTRA_DIST = CMakeLists.txt $(EXAMPLE_FILES)

View File

@@ -0,0 +1,24 @@
// Example of using the GeographicLib::Accumulator class
#include <iostream>
#include <exception>
#include <GeographicLib/Accumulator.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
// Compare using Accumulator and ordinary summation for a sum of large and
// small terms.
double sum = 0;
Accumulator<> acc = 0;
sum += 1e20; sum += 1; sum += 2; sum += 100; sum += 5000; sum += -1e20;
acc += 1e20; acc += 1; acc += 2; acc += 100; acc += 5000; acc += -1e20;
cout << sum << " " << acc() << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,39 @@
// Example of using the GeographicLib::AlbersEqualArea class
#include <iostream>
#include <exception>
#include <GeographicLib/AlbersEqualArea.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
const double
a = Constants::WGS84_a(),
f = Constants::WGS84_f(),
lat1 = 40 + 58/60.0, lat2 = 39 + 56/60.0, // standard parallels
k1 = 1, // scale
lon0 = -77 - 45/60.0; // Central meridian
// Set up basic projection
const AlbersEqualArea albers(a, f, lat1, lat2, k1);
{
// Sample conversion from geodetic to Albers Equal Area
double lat = 39.95, lon = -75.17; // Philadelphia
double x, y;
albers.Forward(lon0, lat, lon, x, y);
cout << x << " " << y << "\n";
}
{
// Sample conversion from Albers Equal Area grid to geodetic
double x = 220e3, y = -53e3;
double lat, lon;
albers.Reverse(lon0, x, y, lat, lon);
cout << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,37 @@
// Example of using the GeographicLib::AuxLatitude class. See the paper
//
// - C. F. F. Karney,
// On auxiliary latitudes,
// Technical Report, SRI International, December 2022.
// https://arxiv.org/abs/2212.05818
#include <iostream>
#include <iomanip>
#include <exception>
#include "AuxLatitude.hpp"
using namespace std;
int main() {
try {
typedef GeographicLib::AuxLatitude<double> latitude;
typedef latitude::angle angle;
double a = 2, b = 1; // Equatorial radius and polar semi-axis
latitude aux(a, b);
bool series = false; // Don't use series method
int auxin = latitude::GEOGRAPHIC;
cout << setprecision(9) << fixed;
for (int l = 0; l <= 90; ++l) {
angle phi(angle::degrees(l));
for (int auxout = 0; auxout < latitude::AUXNUMBER; ++auxout) {
angle eta = aux.Convert(auxin, auxout, phi, series);
cout << (auxout ? " " : "") << eta.degrees();
}
cout << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,36 @@
// Example of using the GeographicLib::AzimuthalEquidistant class
#include <iostream>
#include <exception>
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/AzimuthalEquidistant.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Geodesic geod(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Geodesic& geod = Geodesic::WGS84();
const double lat0 = 48 + 50/60.0, lon0 = 2 + 20/60.0; // Paris
AzimuthalEquidistant proj(geod);
{
// Sample forward calculation
double lat = 50.9, lon = 1.8; // Calais
double x, y;
proj.Forward(lat0, lon0, lat, lon, x, y);
cout << x << " " << y << "\n";
}
{
// Sample reverse calculation
double x = -38e3, y = 230e3;
double lat, lon;
proj.Reverse(lat0, lon0, x, y, lat, lon);
cout << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,36 @@
// Example of using the GeographicLib::CassiniSoldner class
#include <iostream>
#include <exception>
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/CassiniSoldner.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Geodesic geod(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Geodesic& geod = Geodesic::WGS84();
const double lat0 = 48 + 50/60.0, lon0 = 2 + 20/60.0; // Paris
CassiniSoldner proj(lat0, lon0, geod);
{
// Sample forward calculation
double lat = 50.9, lon = 1.8; // Calais
double x, y;
proj.Forward(lat, lon, x, y);
cout << x << " " << y << "\n";
}
{
// Sample reverse calculation
double x = -38e3, y = 230e3;
double lat, lon;
proj.Reverse(x, y, lat, lon);
cout << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,35 @@
// Example of using the GeographicLib::CircularEngine class
#include <iostream>
#include <exception>
#include <vector>
#include <GeographicLib/CircularEngine.hpp>
#include <GeographicLib/SphericalHarmonic.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
// This computes the same value as example-SphericalHarmonic.cpp using a
// CircularEngine (which will be faster if many values on a circle of
// latitude are to be found).
try {
using std::hypot;
int N = 3; // The maxium degree
double ca[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; // cosine coefficients
vector<double> C(ca, ca + (N + 1) * (N + 2) / 2);
double sa[] = {6, 5, 4, 3, 2, 1}; // sine coefficients
vector<double> S(sa, sa + N * (N + 1) / 2);
double a = 1;
SphericalHarmonic h(C, S, N, a);
double x = 2, y = 3, z = 1, p = hypot(x, y);
CircularEngine circ = h.Circle(p, z, true);
double v, vx, vy, vz;
v = circ(x/p, y/p, vx, vy, vz);
cout << v << " " << vx << " " << vy << " " << vz << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,20 @@
// Example of using the GeographicLib::Constants class
#include <iostream>
#include <exception>
#include <GeographicLib/Constants.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
cout << "WGS84 parameters:\n"
<< "a = " << Constants::WGS84_a() << " m\n"
<< "f = 1/" << 1/Constants::WGS84_f() << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,29 @@
// Example of using the GeographicLib::DMS class
#include <iostream>
#include <string>
#include <exception>
#include <GeographicLib/DMS.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
{
string dms = "30d14'45.6\"S";
DMS::flag type;
double ang = DMS::Decode(dms, type);
cout << type << " " << ang << "\n";
}
{
double ang = -30.245715;
string dms = DMS::Encode(ang, 6, DMS::LATITUDE);
cout << dms << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,62 @@
// Example of using the GeographicLib::DST class
#include <iostream>
#include <exception>
#include <vector>
#include <GeographicLib/Math.hpp>
#include <GeographicLib/DST.hpp>
using namespace std;
using namespace GeographicLib;
class sawtooth {
private:
double _a;
public:
sawtooth(double a) : _a(a) {}
// only called for x in (0, pi/2]. DST assumes function is periodic, period
// 2*pi, is odd about 0, and is even about pi/2.
double operator()(double x) const { return _a * x; }
};
int main() {
try {
sawtooth f(Math::pi()/4);
DST dst;
int N = 5, K = 2*N;
vector<double> tx(N), txa(2*N);
dst.reset(N);
dst.transform(f, tx.data());
cout << "Transform of sawtooth based on " << N << " points\n"
<< "approx 1, -1/9, 1/25, -1/49, ...\n";
for (int i = 0; i < min(K,N); ++i) {
int j = (2*i+1)*(2*i+1)*(1-((i&1)<<1));
cout << i << " " << tx[i] << " " << tx[i]*j << "\n";
}
tx.resize(2*N);
dst.refine(f, tx.data());
cout << "Add another " << N << " points\n";
for (int i = 0; i < min(K,2*N); ++i) {
int j = (2*i+1)*(2*i+1)*(1-((i&1)<<1));
cout << i << " " << tx[i] << " " << tx[i]*j << "\n";
}
dst.reset(2*N);
dst.transform(f, txa.data());
cout << "Retransform of sawtooth based on " << 2*N << " points\n";
for (int i = 0; i < min(K,2*N); ++i) {
int j = (2*i+1)*(2*i+1)*(1-((i&1)<<1));
cout << i << " " << txa[i] << " " << txa[i]*j << "\n";
}
cout << "Table of values and integral\n";
for (int i = 0; i <= K; ++i) {
double x = i*Math::pi()/(2*K), sinx = sin(x), cosx = cos(x);
cout << x << " " << f(x) << " "
<< DST::eval(sinx, cosx, txa.data(), 2*N) << " "
<< DST::integral(sinx, cosx, txa.data(), 2*N) << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,42 @@
// Example of using the GeographicLib::Ellipsoid class
#include <iostream>
#include <iomanip>
#include <exception>
#include <GeographicLib/Ellipsoid.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Ellipsoid wgs84(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Ellipsoid& wgs84 = Ellipsoid::WGS84();
cout << "The latitude half way between the equator and the pole is "
<< wgs84.InverseRectifyingLatitude(45) << "\n";
cout << "Half the area of the ellipsoid lies between latitudes +/- "
<< wgs84.InverseAuthalicLatitude(30) << "\n";
cout << "The northernmost edge of a square Mercator map is at latitude "
<< wgs84.InverseIsometricLatitude(180) << "\n";
cout << "Table phi(deg) beta-phi xi-phi mu-phi chi-phi theta-phi (mins)\n"
<< fixed << setprecision(2);
for (int i = 0; i <= 90; i += 15) {
double phi = i,
bet = wgs84.ParametricLatitude(phi),
xi = wgs84.AuthalicLatitude(phi),
mu = wgs84.RectifyingLatitude(phi),
chi = wgs84.ConformalLatitude(phi),
theta = wgs84.GeocentricLatitude(phi);
cout << i << " "
<< (bet-phi)*60 << " "
<< (xi-phi)*60 << " "
<< (mu-phi)*60 << " "
<< (chi-phi)*60 << " "
<< (theta-phi)*60 << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,43 @@
// Example of using the GeographicLib::EllipticFunction class
#include <iostream>
#include <iomanip>
#include <exception>
#include <cmath>
#include <GeographicLib/Math.hpp>
#include <GeographicLib/EllipticFunction.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
EllipticFunction ell(0.1); // parameter m = 0.1
// See Abramowitz and Stegun, table 17.1
cout << ell.K() << " " << ell.E() << "\n";
double phi = 20, sn, cn;
Math::sincosd(phi, sn ,cn);
// See Abramowitz and Stegun, table 17.6 with
// alpha = asin(sqrt(m)) = 18.43 deg and phi = 20 deg
cout << ell.E(phi * Math::degree()) << " "
<< ell.E(sn, cn, ell.Delta(sn, cn))
<< "\n";
// See Carlson 1995, Sec 3.
cout << fixed << setprecision(16)
<< "RF(1,2,0) = " << EllipticFunction::RF(1,2) << "\n"
<< "RF(2,3,4) = " << EllipticFunction::RF(2,3,4) << "\n"
<< "RC(0,1/4) = " << EllipticFunction::RC(0,0.25) << "\n"
<< "RC(9/4,2) = " << EllipticFunction::RC(2.25,2) << "\n"
<< "RC(1/4,-2) = " << EllipticFunction::RC(0.25,-2) << "\n"
<< "RJ(0,1,2,3) = " << EllipticFunction::RJ(0,1,2,3) << "\n"
<< "RJ(2,3,4,5) = " << EllipticFunction::RJ(2,3,4,5) << "\n"
<< "RD(0,2,1) = " << EllipticFunction::RD(0,2,1) << "\n"
<< "RD(2,3,4) = " << EllipticFunction::RD(2,3,4) << "\n"
<< "RG(0,16,16) = " << EllipticFunction::RG(16,16) << "\n"
<< "RG(2,3,4) = " << EllipticFunction::RG(2,3,4) << "\n"
<< "RG(0,0.0796,4) = " << EllipticFunction::RG(0.0796,4) << "\n";
}
catch (const exception& e) {
cout << "Caught exception: " << e.what() << "\n";
}
}

View File

@@ -0,0 +1,39 @@
// Example of using the GeographicLib::GARS class
#include <iostream>
#include <iomanip>
#include <exception>
#include <string>
#include <GeographicLib/GARS.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
{
// Sample forward calculation
double lat = 57.64911, lon = 10.40744; // Jutland
string gars;
for (int prec = 0; prec <= 2; ++prec) {
GARS::Forward(lat, lon, prec, gars);
cout << prec << " " << gars << "\n";
}
}
{
// Sample reverse calculation
string gars = "381NH45";
double lat, lon;
cout << fixed;
for (int len = 5; len <= int(gars.size()); ++len) {
int prec;
GARS::Reverse(gars.substr(0, len), lat, lon, prec);
cout << prec << " " << lat << " " << lon << "\n";
}
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,26 @@
// Example of using the GeographicLib::GeoCoords class
#include <iostream>
#include <exception>
#include <GeographicLib/GeoCoords.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
// Miscellaneous conversions
double lat = 33.3, lon = 44.4;
GeoCoords c(lat, lon);
cout << c.MGRSRepresentation(-3) << "\n";
c.Reset("18TWN0050");
cout << c.DMSRepresentation() << "\n";
cout << c.Latitude() << " " << c.Longitude() << "\n";
c.Reset("1d38'W 55d30'N");
cout << c.GeoRepresentation() << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,36 @@
// Example of using the GeographicLib::Geocentric class
#include <iostream>
#include <exception>
#include <cmath>
#include <GeographicLib/Geocentric.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Geocentric earth(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Geocentric& earth = Geocentric::WGS84();
{
// Sample forward calculation
double lat = 27.99, lon = 86.93, h = 8820; // Mt Everest
double X, Y, Z;
earth.Forward(lat, lon, h, X, Y, Z);
cout << floor(X / 1000 + 0.5) << " "
<< floor(Y / 1000 + 0.5) << " "
<< floor(Z / 1000 + 0.5) << "\n";
}
{
// Sample reverse calculation
double X = 302e3, Y = 5636e3, Z = 2980e3;
double lat, lon, h;
earth.Reverse(X, Y, Z, lat, lon, h);
cout << lat << " " << lon << " " << h << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,18 @@
// Small example of using the GeographicLib::Geodesic class
#include <iostream>
#include <GeographicLib/Geodesic.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
const Geodesic& geod = Geodesic::WGS84();
// Distance from JFK to LHR
double
lat1 = 40.6, lon1 = -73.8, // JFK Airport
lat2 = 51.6, lon2 = -0.5; // LHR Airport
double s12;
geod.Inverse(lat1, lon1, lat2, lon2, s12);
cout << s12 / 1000 << " km\n";
}

View File

@@ -0,0 +1,36 @@
// Example of using the GeographicLib::Geodesic class
#include <iostream>
#include <exception>
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/Constants.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Geodesic geod(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Geodesic& geod = Geodesic::WGS84();
{
// Sample direct calculation, travelling about NE from JFK
double lat1 = 40.6, lon1 = -73.8, s12 = 5.5e6, azi1 = 51;
double lat2, lon2;
geod.Direct(lat1, lon1, azi1, s12, lat2, lon2);
cout << lat2 << " " << lon2 << "\n";
}
{
// Sample inverse calculation, JFK to LHR
double
lat1 = 40.6, lon1 = -73.8, // JFK Airport
lat2 = 51.6, lon2 = -0.5; // LHR Airport
double s12;
geod.Inverse(lat1, lon1, lat2, lon2, s12);
cout << s12 << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,36 @@
// Example of using the GeographicLib::GeodesicExact class
#include <iostream>
#include <exception>
#include <GeographicLib/GeodesicExact.hpp>
#include <GeographicLib/Constants.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
GeodesicExact geod(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const GeodesicExact& geod = GeodesicExact::WGS84();
{
// Sample direct calculation, travelling about NE from JFK
double lat1 = 40.6, lon1 = -73.8, s12 = 5.5e6, azi1 = 51;
double lat2, lon2;
geod.Direct(lat1, lon1, azi1, s12, lat2, lon2);
cout << lat2 << " " << lon2 << "\n";
}
{
// Sample inverse calculation, JFK to LHR
double
lat1 = 40.6, lon1 = -73.8, // JFK Airport
lat2 = 51.6, lon2 = -0.5; // LHR Airport
double s12;
geod.Inverse(lat1, lon1, lat2, lon2, s12);
cout << s12 << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,49 @@
// Example of using the GeographicLib::GeodesicLine class
#include <iostream>
#include <iomanip>
#include <exception>
#include <cmath>
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/GeodesicLine.hpp>
#include <GeographicLib/Constants.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
// Print waypoints between JFK and SIN
Geodesic geod(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Geodesic& geod = Geodesic::WGS84();
double
lat1 = 40.640, lon1 = -73.779, // JFK
lat2 = 1.359, lon2 = 103.989; // SIN
GeodesicLine line = geod.InverseLine(lat1, lon1, lat2, lon2);
double ds0 = 500e3; // Nominal distance between points = 500 km
int num = int(ceil(line.Distance() / ds0)); // The number of intervals
cout << fixed << setprecision(3);
{
// Use intervals of equal length
double ds = line.Distance() / num;
for (int i = 0; i <= num; ++i) {
double lat, lon;
line.Position(i * ds, lat, lon);
cout << i << " " << lat << " " << lon << "\n";
}
}
{
// Slightly faster, use intervals of equal arc length
double da = line.Arc() / num;
for (int i = 0; i <= num; ++i) {
double lat, lon;
line.ArcPosition(i * da, lat, lon);
cout << i << " " << lat << " " << lon << "\n";
}
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,49 @@
// Example of using the GeographicLib::GeodesicLineExact class
#include <iostream>
#include <iomanip>
#include <exception>
#include <cmath>
#include <GeographicLib/GeodesicExact.hpp>
#include <GeographicLib/GeodesicLineExact.hpp>
#include <GeographicLib/Constants.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
// Print waypoints between JFK and SIN
GeodesicExact geod(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const GeodesicExact& geod = GeodesicExact::WGS84();
double
lat1 = 40.640, lon1 = -73.779, // JFK
lat2 = 1.359, lon2 = 103.989; // SIN
GeodesicLineExact line = geod.InverseLine(lat1, lon1, lat2, lon2);
double ds0 = 500e3; // Nominal distance between points = 500 km
int num = int(ceil(line.Distance() / ds0)); // The number of intervals
cout << fixed << setprecision(3);
{
// Use intervals of equal length
double ds = line.Distance() / num;
for (int i = 0; i <= num; ++i) {
double lat, lon;
line.Position(i * ds, lat, lon);
cout << i << " " << lat << " " << lon << "\n";
}
}
{
// Slightly faster, use intervals of equal arc length
double da = line.Arc() / num;
for (int i = 0; i <= num; ++i) {
double lat, lon;
line.ArcPosition(i * da, lat, lon);
cout << i << " " << lat << " " << lon << "\n";
}
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,16 @@
// Example of using the GeographicLib::GeographicErr class
#include <iostream>
#include <GeographicLib/Constants.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
throw GeographicErr("Test throwing an exception");
}
catch (const GeographicErr& e) {
cout << "Caught exception: " << e.what() << "\n";
}
}

View File

@@ -0,0 +1,45 @@
// Example of using the GeographicLib::Geohash class
#include <iostream>
#include <iomanip>
#include <exception>
#include <string>
#include <GeographicLib/Geohash.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
{
// Sample forward calculation
double lat = 57.64911, lon = 10.40744; // Jutland (the wikipedia example)
string geohash;
int maxlen = Geohash::GeohashLength(1.0e-5);
for (int len = 0; len <= maxlen; ++len) {
Geohash::Forward(lat, lon, len, geohash);
cout << len << " " << geohash << "\n";
}
}
{
// Sample reverse calculation
string geohash = "u4pruydqqvj";
double lat, lon, latres, lonres;
cout << fixed;
for (unsigned i = 0; i <= geohash.length(); ++i) {
int len;
Geohash::Reverse(geohash.substr(0, i), lat, lon, len);
latres = Geohash::LatitudeResolution(len);
lonres = Geohash::LongitudeResolution(len);
cout << setprecision(max(0, Geohash::DecimalPrecision(len)))
<< len << " "
<< lat << "+/-" << latres/2 << " "
<< lon << "+/-" << lonres/2 << "\n";
}
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,27 @@
// Example of using the GeographicLib::Geoid class
// This requires that the egm96-5 geoid model be installed; see
// https://geographiclib.sourceforge.io/C++/doc/geoid.html#geoidinst
#include <iostream>
#include <exception>
#include <GeographicLib/Geoid.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Geoid egm96("egm96-5");
// Convert height above egm96 to height above the ellipsoid
double lat = 42, lon = -75, height_above_geoid = 20;
double
geoid_height = egm96(lat, lon),
height_above_ellipsoid = (height_above_geoid +
Geoid::GEOIDTOELLIPSOID * geoid_height);
cout << height_above_ellipsoid << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,41 @@
// Example of using the GeographicLib::GARS class
#include <iostream>
#include <iomanip>
#include <exception>
#include <string>
#include <GeographicLib/Georef.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
{
// Sample forward calculation
double lat = 57.64911, lon = 10.40744; // Jutland
string georef;
for (int prec = -1; prec <= 11; ++prec) {
Georef::Forward(lat, lon, prec, georef);
cout << prec << " " << georef << "\n";
}
}
{
// Sample reverse calculation
string georef = "NKLN2444638946";
double lat, lon;
int prec;
cout << fixed;
Georef::Reverse(georef.substr(0, 2), lat, lon, prec);
cout << prec << " " << lat << " " << lon << "\n";
Georef::Reverse(georef.substr(0, 4), lat, lon, prec);
cout << prec << " " << lat << " " << lon << "\n";
Georef::Reverse(georef, lat, lon, prec);
cout << prec << " " << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,36 @@
// Example of using the GeographicLib::Gnomonic class
#include <iostream>
#include <exception>
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/Gnomonic.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Geodesic geod(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Geodesic& geod = Geodesic::WGS84();
const double lat0 = 48 + 50/60.0, lon0 = 2 + 20/60.0; // Paris
Gnomonic proj(geod);
{
// Sample forward calculation
double lat = 50.9, lon = 1.8; // Calais
double x, y;
proj.Forward(lat0, lon0, lat, lon, x, y);
cout << x << " " << y << "\n";
}
{
// Sample reverse calculation
double x = -38e3, y = 230e3;
double lat, lon;
proj.Reverse(lat0, lon0, x, y, lat, lon);
cout << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,43 @@
// Example of using the GeographicLib::GravityCircle class
// This requires that the egm96 gravity model be installed; see
// https://geographiclib.sourceforge.io/C++/doc/gravity.html#gravityinst
#include <iostream>
#include <exception>
#include <GeographicLib/GravityModel.hpp>
#include <GeographicLib/GravityCircle.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
GravityModel grav("egm96");
double lat = 27.99, lon0 = 86.93, h = 8820; // Mt Everest
{
// Slow method of evaluating the values at several points on a circle of
// latitude.
for (int i = -5; i <= 5; ++i) {
double lon = lon0 + i * 0.2;
double gx, gy, gz;
grav.Gravity(lat, lon, h, gx, gy, gz);
cout << lon << " " << gx << " " << gy << " " << gz << "\n";
}
}
{
// Fast method of evaluating the values at several points on a circle of
// latitude using GravityCircle.
GravityCircle circ = grav.Circle(lat, h);
for (int i = -5; i <= 5; ++i) {
double lon = lon0 + i * 0.2;
double gx, gy, gz;
circ.Gravity(lon, gx, gy, gz);
cout << lon << " " << gx << " " << gy << " " << gz << "\n";
}
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,24 @@
// Example of using the GeographicLib::GravityModel class
// This requires that the egm96 gravity model be installed; see
// https://geographiclib.sourceforge.io/C++/doc/gravity.html#gravityinst
#include <iostream>
#include <exception>
#include <GeographicLib/GravityModel.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
GravityModel grav("egm96");
double lat = 27.99, lon = 86.93, h = 8820; // Mt Everest
double gx, gy, gz;
grav.Gravity(lat,lon, h, gx, gy, gz);
cout << gx << " " << gy << " " << gz << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,48 @@
// Example of using the GeographicLib::LambertConformalConic class
#include <iostream>
#include <exception>
#include <GeographicLib/LambertConformalConic.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
// Define the Pennsylvania South state coordinate system EPSG:3364
// https://www.spatialreference.org/ref/epsg/3364/
const double
a = Constants::WGS84_a(),
f = 1/298.257222101, // GRS80
lat1 = 40 + 58/60.0, lat2 = 39 + 56/60.0, // standard parallels
k1 = 1, // scale
lat0 = 39 + 20/60.0, lon0 =-77 - 45/60.0, // origin
fe = 600000, fn = 0; // false easting and northing
// Set up basic projection
const LambertConformalConic PASouth(a, f, lat1, lat2, k1);
double x0, y0;
// Transform origin point
PASouth.Forward(lon0, lat0, lon0, x0, y0);
x0 -= fe; y0 -= fn;
{
// Sample conversion from geodetic to PASouth grid
double lat = 39.95, lon = -75.17; // Philadelphia
double x, y;
PASouth.Forward(lon0, lat, lon, x, y);
x -= x0; y -= y0;
cout << x << " " << y << "\n";
}
{
// Sample conversion from PASouth grid to geodetic
double x = 820e3, y = 72e3;
double lat, lon;
x += x0; y += y0;
PASouth.Reverse(lon0, x, y, lat, lon);
cout << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,37 @@
// Example of using the GeographicLib::LocalCartesian class
#include <iostream>
#include <exception>
#include <cmath>
#include <GeographicLib/Geocentric.hpp>
#include <GeographicLib/LocalCartesian.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Geocentric earth(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Geocentric& earth = Geocentric::WGS84();
const double lat0 = 48 + 50/60.0, lon0 = 2 + 20/60.0; // Paris
LocalCartesian proj(lat0, lon0, 0, earth);
{
// Sample forward calculation
double lat = 50.9, lon = 1.8, h = 0; // Calais
double x, y, z;
proj.Forward(lat, lon, h, x, y, z);
cout << x << " " << y << " " << z << "\n";
}
{
// Sample reverse calculation
double x = -38e3, y = 230e3, z = -4e3;
double lat, lon, h;
proj.Reverse(x, y, z, lat, lon, h);
cout << lat << " " << lon << " " << h << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,42 @@
// Example of using the GeographicLib::MGRS class
#include <iostream>
#include <exception>
#include <string>
#include <GeographicLib/UTMUPS.hpp>
#include <GeographicLib/MGRS.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
// See also example-GeoCoords.cpp
{
// Sample forward calculation
double lat = 33.3, lon = 44.4; // Baghdad
int zone;
bool northp;
double x, y;
UTMUPS::Forward(lat, lon, zone, northp, x, y);
string mgrs;
MGRS::Forward(zone, northp, x, y, lat, 5, mgrs);
cout << mgrs << "\n";
}
{
// Sample reverse calculation
string mgrs = "38SMB4488";
int zone, prec;
bool northp;
double x, y;
MGRS::Reverse(mgrs, zone, northp, x, y, prec);
double lat, lon;
UTMUPS::Reverse(zone, northp, x, y, lat, lon);
cout << prec << " " << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,43 @@
// Example of using the GeographicLib::MagneticCircle class
// This requires that the wmm2010 magnetic model be installed; see
// https://geographiclib.sourceforge.io/C++/doc/magnetic.html#magneticinst
#include <iostream>
#include <exception>
#include <GeographicLib/MagneticModel.hpp>
#include <GeographicLib/MagneticCircle.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
MagneticModel mag("wmm2010");
double lat = 27.99, lon0 = 86.93, h = 8820, t = 2012; // Mt Everest
{
// Slow method of evaluating the values at several points on a circle of
// latitude.
for (int i = -5; i <= 5; ++i) {
double lon = lon0 + i * 0.2;
double Bx, By, Bz;
mag(t, lat, lon, h, Bx, By, Bz);
cout << lon << " " << Bx << " " << By << " " << Bz << "\n";
}
}
{
// Fast method of evaluating the values at several points on a circle of
// latitude using MagneticCircle.
MagneticCircle circ = mag.Circle(t, lat, h);
for (int i = -5; i <= 5; ++i) {
double lon = lon0 + i * 0.2;
double Bx, By, Bz;
circ(lon, Bx, By, Bz);
cout << lon << " " << Bx << " " << By << " " << Bz << "\n";
}
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,26 @@
// Example of using the GeographicLib::MagneticModel class
// This requires that the wmm2010 magnetic model be installed; see
// https://geographiclib.sourceforge.io/C++/doc/magnetic.html#magneticinst
#include <iostream>
#include <exception>
#include <GeographicLib/MagneticModel.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
MagneticModel mag("wmm2010");
double lat = 27.99, lon = 86.93, h = 8820, t = 2012; // Mt Everest
double Bx, By, Bz;
mag(t, lat,lon, h, Bx, By, Bz);
double H, F, D, I;
MagneticModel::FieldComponents(Bx, By, Bz, H, F, D, I);
cout << H << " " << F << " " << D << " " << I << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,18 @@
// Example of using the GeographicLib::Math class
#include <iostream>
#include <exception>
#include <GeographicLib/Math.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
cout << Math::pi() << " " << Math::sq(Math::pi()) << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,140 @@
// Example of using the GeographicLib::NearestNeighbor class. WARNING: this
// creates a file, pointset.xml or pointset.txt, in the current directory.
// Read lat/lon locations from locations.txt and lat/lon queries from
// queries.txt. For each query print to standard output: the index for the
// closest location and the distance to it. Print statistics to standard error
// at the end.
#include <iostream>
#include <exception>
#include <vector>
#include <fstream>
#include <string>
#if !defined(GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION)
#define GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION 0
#endif
#if GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION
// If Boost serialization is available, use it.
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#endif
#include <GeographicLib/NearestNeighbor.hpp>
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/DMS.hpp>
using namespace std;
using namespace GeographicLib;
// A structure to hold a geographic coordinate.
struct pos {
double _lat, _lon;
pos(double lat = 0, double lon = 0) : _lat(lat), _lon(lon) {}
};
// A class to compute the distance between 2 positions.
class DistanceCalculator {
private:
Geodesic _geod;
public:
explicit DistanceCalculator(const Geodesic& geod) : _geod(geod) {}
double operator() (const pos& a, const pos& b) const {
double d;
_geod.Inverse(a._lat, a._lon, b._lat, b._lon, d);
if ( !(d >= 0) )
// Catch illegal positions which result in d = NaN
throw GeographicErr("distance doesn't satisfy d >= 0");
return d;
}
};
int main() {
try {
// Read in locations
vector<pos> locs;
double lat, lon;
string sa, sb;
{
ifstream is("locations.txt");
if (!is.good())
throw GeographicErr("locations.txt not readable");
while (is >> sa >> sb) {
DMS::DecodeLatLon(sa, sb, lat, lon);
locs.push_back(pos(lat, lon));
}
if (locs.size() == 0)
throw GeographicErr("need at least one location");
}
// Define a distance function object
DistanceCalculator distance(Geodesic::WGS84());
// Create NearestNeighbor object
NearestNeighbor<double, pos, DistanceCalculator> pointset;
{
// Used saved object if it is available
#if GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION
ifstream is("pointset.xml");
if (is.good()) {
boost::archive::xml_iarchive ia(is);
ia >> BOOST_SERIALIZATION_NVP(pointset);
}
#else
ifstream is("pointset.txt");
if (is.good())
is >> pointset;
#endif
}
// Is the saved pointset up-to-date?
if (pointset.NumPoints() != int(locs.size())) {
// else initialize it
pointset.Initialize(locs, distance);
// and save it
#if GEOGRAPHICLIB_HAVE_BOOST_SERIALIZATION
ofstream os("pointset.xml");
if (!os.good())
throw GeographicErr("cannot write to pointset.xml");
boost::archive::xml_oarchive oa(os);
oa << BOOST_SERIALIZATION_NVP(pointset);
#else
ofstream os("pointset.txt");
if (!os.good())
throw GeographicErr("cannot write to pointset.txt");
os << pointset << "\n";
#endif
}
ifstream is("queries.txt");
double d;
int count = 0;
vector<int> k;
while (is >> sa >> sb) {
++count;
DMS::DecodeLatLon(sa, sb, lat, lon);
d = pointset.Search(locs, distance, pos(lat, lon), k);
if (k.size() != 1)
throw GeographicErr("unexpected number of results");
cout << k[0] << " " << d << "\n";
}
int setupcost, numsearches, searchcost, mincost, maxcost;
double mean, sd;
pointset.Statistics(setupcost, numsearches, searchcost,
mincost, maxcost, mean, sd);
int
totcost = setupcost + searchcost,
exhaustivecost = count * pointset.NumPoints();
cerr
<< "Number of distance calculations = " << totcost << "\n"
<< "With an exhaustive search = " << exhaustivecost << "\n"
<< "Ratio = " << double(totcost) / exhaustivecost << "\n"
<< "Efficiency improvement = "
<< 100 * (1 - double(totcost) / exhaustivecost) << "%\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,25 @@
// Example of using the GeographicLib::NormalGravity class
#include <iostream>
#include <exception>
#include <GeographicLib/NormalGravity.hpp>
#include <GeographicLib/Constants.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
NormalGravity grav(Constants::WGS84_a(), Constants::WGS84_GM(),
Constants::WGS84_omega(), Constants::WGS84_f());
// Alternatively: const NormalGravity& grav = NormalGravity::WGS84();
double lat = 27.99, h = 8820; // Mt Everest
double gammay, gammaz;
grav.Gravity(lat, h, gammay, gammaz);
cout << gammay << " " << gammaz << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,44 @@
// Example of using the GeographicLib::OSGB class
#include <iostream>
#include <iomanip>
#include <exception>
#include <string>
#include <GeographicLib/OSGB.hpp>
#include <GeographicLib/DMS.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
{
// Sample forward calculation from
// A guide to coordinate systems in Great Britain
double
lat = DMS::Decode(52,39,27.2531),
lon = DMS::Decode( 1,43, 4.5177);
double x, y;
OSGB::Forward(lat, lon, x, y);
string gridref;
OSGB::GridReference(x, y, 2, gridref);
cout << fixed << setprecision(3)
<< x << " " << y << " " << gridref << "\n";
}
{
// Sample reverse calculation
string gridref = "TG5113";
double x, y;
int prec;
OSGB::GridReference(gridref, x, y, prec);
double lat, lon;
OSGB::Reverse(x, y, lat, lon);
cout << fixed << setprecision(8)
<< prec << " " << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,37 @@
// Example of using the GeographicLib::PolarStereographic class
#include <iostream>
#include <iomanip>
#include <exception>
#include <GeographicLib/PolarStereographic.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
PolarStereographic proj(Constants::WGS84_a(), Constants::WGS84_f(),
Constants::UPS_k0());
// Alternatively:
// const PolarStereographic& proj = PolarStereographic::UPS();
bool northp = true;
{
// Sample forward calculation
double lat = 61.2, lon = -149.9; // Anchorage
double x, y;
proj.Forward(northp, lat, lon, x, y);
cout << x << " " << y << "\n";
}
{
// Sample reverse calculation
double x = -1637e3, y = 2824e3;
double lat, lon;
proj.Reverse(northp, x, y, lat, lon);
cout << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,40 @@
// Example of using the GeographicLib::PolygonArea class
#include <iostream>
#include <exception>
#include <GeographicLib/PolygonArea.hpp>
#include <GeographicLib/Geodesic.hpp>
#include <GeographicLib/Constants.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Geodesic geod(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Geodesic& geod = Geodesic::WGS84();
PolygonArea poly(geod);
poly.AddPoint( 52, 0); // London
poly.AddPoint( 41,-74); // New York
poly.AddPoint(-23,-43); // Rio de Janeiro
poly.AddPoint(-26, 28); // Johannesburg
double perimeter, area;
unsigned n = poly.Compute(false, true, perimeter, area);
cout << n << " " << perimeter << " " << area << "\n";
// This adds a test for a bug fix for AddEdge. (Implements the
// Planimeter29 test in geodtest.c.)
PolygonArea poly1(geod);
poly1.AddPoint(0,0);
poly1.AddEdge(90,1000);
poly1.AddEdge(0,1000);
poly1.AddEdge(-90,1000);
n = poly1.Compute(false, true, perimeter, area);
// The area should be 1e6. Prior to the fix it was 1e6 - A/2, where
// A = ellipsoid area.
cout << n << " " << perimeter << " " << area << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,36 @@
// Example of using the GeographicLib::Rhumb class
#include <iostream>
#include <exception>
#include <GeographicLib/Rhumb.hpp>
#include <GeographicLib/Constants.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Rhumb rhumb(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Rhumb& rhumb = Rhumb::WGS84();
{
// Sample direct calculation, travelling about NE from JFK
double lat1 = 40.6, lon1 = -73.8, s12 = 5.5e6, azi12 = 51;
double lat2, lon2;
rhumb.Direct(lat1, lon1, azi12, s12, lat2, lon2);
cout << lat2 << " " << lon2 << "\n";
}
{
// Sample inverse calculation, JFK to LHR
double
lat1 = 40.6, lon1 = -73.8, // JFK Airport
lat2 = 51.6, lon2 = -0.5; // LHR Airport
double s12, azi12;
rhumb.Inverse(lat1, lon1, lat2, lon2, s12, azi12);
cout << s12 << " " << azi12 << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,41 @@
// Example of using the GeographicLib::RhumbLine class
#include <iostream>
#include <iomanip>
#include <exception>
#include <cmath>
#include <GeographicLib/Rhumb.hpp>
#include <GeographicLib/Constants.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
// Print waypoints between JFK and SIN
Rhumb rhumb(Constants::WGS84_a(), Constants::WGS84_f());
// Alternatively: const Rhumb& rhumb = Rhumb::WGS84();
double
lat1 = 40.640, lon1 = -73.779, // JFK
lat2 = 1.359, lon2 = 103.989; // SIN
double s12, azi12;
rhumb.Inverse(lat1, lon1, lat2, lon2, s12, azi12);
RhumbLine line = rhumb.Line(lat1, lon1, azi12);
double ds0 = 500e3; // Nominal distance between points = 500 km
int num = int(ceil(s12 / ds0)); // The number of intervals
cout << fixed << setprecision(3);
{
// Use intervals of equal length
double ds = s12 / num;
for (int i = 0; i <= num; ++i) {
double lat, lon;
line.Position(i * ds, lat, lon);
cout << i << " " << lat << " " << lon << "\n";
}
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,32 @@
// Example of using the GeographicLib::SphericalEngine class
#include <iostream>
#include <exception>
#include <vector>
#include <GeographicLib/SphericalEngine.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
// See also example-SphericHarmonic.cpp
try {
int N = 3; // The maxium degree
double ca[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; // cosine coefficients
vector<double> C(ca, ca + (N + 1) * (N + 2) / 2);
double sa[] = {6, 5, 4, 3, 2, 1}; // sine coefficients
vector<double> S(sa, sa + N * (N + 1) / 2);
SphericalEngine::coeff c[1];
c[0] = SphericalEngine::coeff(C, S, N);
double f[] = {1};
double x = 2, y = 3, z = 1, a = 1;
double v, vx, vy, vz;
v = SphericalEngine::Value<true, SphericalEngine::FULL, 1>
(c, f, x, y, z, a, vx, vy, vz);
cout << v << " " << vx << " " << vy << " " << vz << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,29 @@
// Example of using the GeographicLib::SphericalHarmonic class
#include <iostream>
#include <exception>
#include <vector>
#include <GeographicLib/SphericalHarmonic.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
int N = 3; // The maxium degree
double ca[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; // cosine coefficients
vector<double> C(ca, ca + (N + 1) * (N + 2) / 2);
double sa[] = {6, 5, 4, 3, 2, 1}; // sine coefficients
vector<double> S(sa, sa + N * (N + 1) / 2);
double a = 1;
SphericalHarmonic h(C, S, N, a);
double x = 2, y = 3, z = 1;
double v, vx, vy, vz;
v = h(x, y, z, vx, vy, vz);
cout << v << " " << vx << " " << vy << " " << vz << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,33 @@
// Example of using the GeographicLib::SphericalHarmonic1 class
#include <iostream>
#include <exception>
#include <vector>
#include <GeographicLib/SphericalHarmonic1.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
int N = 3, N1 = 2; // The maxium degrees
double ca[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; // cosine coefficients
vector<double> C(ca, ca + (N + 1) * (N + 2) / 2);
double sa[] = {6, 5, 4, 3, 2, 1}; // sine coefficients
vector<double> S(sa, sa + N * (N + 1) / 2);
double cb[] = {1, 2, 3, 4, 5, 6};
vector<double> C1(cb, cb + (N1 + 1) * (N1 + 2) / 2);
double sb[] = {3, 2, 1};
vector<double> S1(sb, sb + N1 * (N1 + 1) / 2);
double a = 1;
SphericalHarmonic1 h(C, S, N, C1, S1, N1, a);
double tau = 0.1, x = 2, y = 3, z = 1;
double v, vx, vy, vz;
v = h(tau, x, y, z, vx, vy, vz);
cout << v << " " << vx << " " << vy << " " << vz << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,37 @@
// Example of using the GeographicLib::SphericalHarmonic2 class
#include <iostream>
#include <exception>
#include <vector>
#include <GeographicLib/SphericalHarmonic2.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
int N = 3, N1 = 2, N2 = 1; // The maxium degrees
double ca[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; // cosine coefficients
vector<double> C(ca, ca + (N + 1) * (N + 2) / 2);
double sa[] = {6, 5, 4, 3, 2, 1}; // sine coefficients
vector<double> S(sa, sa + N * (N + 1) / 2);
double cb[] = {1, 2, 3, 4, 5, 6};
vector<double> C1(cb, cb + (N1 + 1) * (N1 + 2) / 2);
double sb[] = {3, 2, 1};
vector<double> S1(sb, sb + N1 * (N1 + 1) / 2);
double cc[] = {2, 1};
vector<double> C2(cc, cc + (N2 + 1));
vector<double> S2;
double a = 1;
SphericalHarmonic2 h(C, S, N, N, N, C1, S1, N1, N1, N1,
C2, S2, N2, N2, 0, a);
double tau1 = 0.1, tau2 = 0.05, x = 2, y = 3, z = 1;
double v, vx, vy, vz;
v = h(tau1, tau2, x, y, z, vx, vy, vz);
cout << v << " " << vx << " " << vy << " " << vz << "\n";
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,63 @@
// Example of using the GeographicLib::TransverseMercator class
#include <iostream>
#include <iomanip>
#include <exception>
#include <GeographicLib/TransverseMercator.hpp>
using namespace std;
using namespace GeographicLib;
// Define a UTM projection for an arbitrary ellipsoid
class UTMalt {
private:
TransverseMercator _tm; // The projection
double _lon0; // Central longitude
double _falseeasting, _falsenorthing;
public:
UTMalt(double a, // equatorial radius
double f, // flattening
int zone, // the UTM zone + hemisphere
bool northp)
: _tm(a, f, Constants::UTM_k0())
, _lon0(6 * zone - 183)
, _falseeasting(5e5)
, _falsenorthing(northp ? 0 : 100e5) {
if (!(zone >= 1 && zone <= 60))
throw GeographicErr("zone not in [1,60]");
}
void Forward(double lat, double lon, double& x, double& y) {
_tm.Forward(_lon0, lat, lon, x, y);
x += _falseeasting;
y += _falsenorthing;
}
void Reverse(double x, double y, double& lat, double& lon) {
x -= _falseeasting;
y -= _falsenorthing;
_tm.Reverse(_lon0, x, y, lat, lon);
}
};
int main() {
try {
UTMalt tm(6378388, 1/297.0, 30, true); // International ellipsoid, zone 30n
{
// Sample forward calculation
double lat = 40.4, lon = -3.7; // Madrid
double x, y;
tm.Forward(lat, lon, x, y);
cout << fixed << setprecision(0) << x << " " << y << "\n";
}
{
// Sample reverse calculation
double x = 441e3, y = 4472e3;
double lat, lon;
tm.Reverse(x, y, lat, lon);
cout << fixed << setprecision(5) << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,37 @@
// Example of using the GeographicLib::TransverseMercatorExact class
#include <iostream>
#include <iomanip>
#include <exception>
#include <GeographicLib/TransverseMercatorExact.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
TransverseMercatorExact proj(Constants::WGS84_a(), Constants::WGS84_f(),
Constants::UTM_k0());
// Alternatively:
// const TransverseMercatorExact& proj = TransverseMercatorExact::UTM();
double lon0 = -75; // Central meridian for UTM zone 18
{
// Sample forward calculation
double lat = 40.3, lon = -74.7; // Princeton, NJ
double x, y;
proj.Forward(lon0, lat, lon, x, y);
cout << x << " " << y << "\n";
}
{
// Sample reverse calculation
double x = 25e3, y = 4461e3;
double lat, lon;
proj.Reverse(lon0, x, y, lat, lon);
cout << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,42 @@
// Example of using the GeographicLib::UTMUPS class
#include <iostream>
#include <iomanip>
#include <exception>
#include <string>
#include <GeographicLib/UTMUPS.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
// See also example-GeoCoords.cpp
{
// Sample forward calculation
double lat = 33.3, lon = 44.4; // Baghdad
int zone;
bool northp;
double x, y;
UTMUPS::Forward(lat, lon, zone, northp, x, y);
string zonestr = UTMUPS::EncodeZone(zone, northp);
cout << fixed << setprecision(2)
<< zonestr << " " << x << " " << y << "\n";
}
{
// Sample reverse calculation
string zonestr = "38n";
int zone;
bool northp;
UTMUPS::DecodeZone(zonestr, zone, northp);
double x = 444e3, y = 3688e3;
double lat, lon;
UTMUPS::Reverse(zone, northp, x, y, lat, lon);
cout << lat << " " << lon << "\n";
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,21 @@
// Example of using the GeographicLib::Utility class
#include <iostream>
#include <exception>
#include <GeographicLib/Utility.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
int
d1 = Utility::day(1939, 9, 3), // Britain declares war on Germany
d2 = Utility::day(1945, 8, 15); // Japan surrenders
cout << d2 - d1 << "\n"; // Length of Second World War for Britain
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
}

View File

@@ -0,0 +1,45 @@
// Write the coefficient files needed for approximating the normal gravity
// field with a GravityModel. WARNING: this creates files, wgs84.egm.cof and
// grs80.egm.cof, in the current directory.
#include <cmath>
#include <fstream>
#include <iostream>
#include <GeographicLib/NormalGravity.hpp>
#include <GeographicLib/Utility.hpp>
using namespace std;
using namespace GeographicLib;
int main() {
try {
Utility::set_digits();
const char* filenames[] = {"wgs84.egm.cof", "grs80.egm.cof"};
const char* ids[] = {"WGS1984A", "GRS1980A"};
for (int grs80 = 0; grs80 < 2; ++grs80) {
ofstream file(filenames[grs80], ios::binary);
Utility::writearray<char, char, false>(file, ids[grs80], 8);
const int N = 20, M = 0,
cnum = (M + 1) * (2 * N - M + 2) / 2; // cnum = N + 1
vector<int> num(2);
num[0] = N; num[1] = M;
Utility::writearray<int, int, false>(file, num);
vector<Math::real> c(cnum, 0);
const NormalGravity& earth(grs80 ? NormalGravity::GRS80() :
NormalGravity::WGS84());
for (int n = 2; n <= N; n += 2)
c[n] = - earth.DynamicalFormFactor(n) / sqrt(Math::real(2*n + 1));
Utility::writearray<double, Math::real, false>(file, c);
num[0] = num[1] = -1;
Utility::writearray<int, int, false>(file, num);
}
}
catch (const exception& e) {
cerr << "Caught exception: " << e.what() << "\n";
return 1;
}
catch (...) {
cerr << "Caught unknown exception\n";
return 1;
}
}