9281 lines
428 KiB
Plaintext
9281 lines
428 KiB
Plaintext
// -*- text -*-
|
||
/**
|
||
* \file GeographicLib.dox
|
||
* \brief Documentation for GeographicLib
|
||
*
|
||
* Written by Charles Karney <charles@karney.com> and licensed under the
|
||
* MIT/X11 License. For more information, see
|
||
* https://geographiclib.sourceforge.io/
|
||
**********************************************************************/
|
||
namespace GeographicLib {
|
||
/**
|
||
\mainpage GeographicLib library
|
||
\author Charles F. F. Karney (charles@karney.com)
|
||
\version @PROJECT_VERSION@
|
||
\date 2022-12-13
|
||
|
||
\section abstract Abstract
|
||
|
||
GeographicLib is a small C++ library for
|
||
|
||
- geodesic and rhumb line calculations;
|
||
- conversions between geographic, UTM, UPS, MGRS, geocentric, and local
|
||
cartesian coordinates;
|
||
- gravity (e.g., EGM2008) and geomagnetic field (e.g., WMM2020)
|
||
calculations.
|
||
|
||
The emphasis is on returning accurate results with errors close to
|
||
round-off (about 5--15 nanometers). Accurate algorithms for \ref
|
||
geodesic and \ref transversemercator have been developed for this
|
||
library. The functionality of the library can be accessed from user
|
||
code or from the \ref utilities provided.
|
||
|
||
It is licensed under the MIT License; see
|
||
<a href="../../LICENSE.txt">LICENSE.txt</a>.
|
||
|
||
This library is <i>not</i> a general purpose projection library nor does
|
||
it perform datum conversions; instead use
|
||
<a href="https://proj.org">PROJ</a>.
|
||
|
||
<b>NOTE:</b> Starting with version 2.0, this library *only* includes the
|
||
C++ implementation. If you're interested in the
|
||
[C](../../C/doc/index.html),
|
||
[Fortran](../../Fortran/doc/index.html),
|
||
[Python](../../Python/doc/index.html),
|
||
[Octave/MATLAB](https://github.com/geographiclib/geographiclib-octave#readme),
|
||
[Java](../../Java/doc/index.html), or
|
||
[JavaScript](../../JavaScript/doc/index.html)
|
||
implementations, go
|
||
[here](../../doc/library.html#languages) on the main [GeographicLib web
|
||
page](../../index.html).
|
||
|
||
\section links Links
|
||
|
||
- Library documentation (all versions):
|
||
<a href="../">https://geographiclib.sourceforge.io/C++</a>
|
||
- Git repository: https://github.com/geographiclib/geographiclib
|
||
- Releases are on the `release` branch, and specific
|
||
releases are tagged as, e.g., `r1.52`,
|
||
`r2.0`, etc. This is the appropriate branch
|
||
for most *users* of GeographicLib.
|
||
- The main branch is `main` and most development is done on the
|
||
`devel` branch. These branches are for the *developers* of
|
||
GeographicLib. Tags `v1.52`, `v2.0`, etc., are aligned with the
|
||
corresponding release tags `r1.52`, `r2.0`, etc.
|
||
- Source distribution:
|
||
https://sourceforge.net/projects/geographiclib/files/distrib-C++
|
||
- Main GeographicLib web page:
|
||
<a href="../../index.html">https://geographiclib.sourceforge.io</a>
|
||
- SourceForge project page: https://sourceforge.net/projects/geographiclib
|
||
- The library has been implemented in a few other
|
||
<a href="../../doc/library.html#languages">languages</a>.
|
||
|
||
\section citint Citing GeographicLib
|
||
|
||
When citing GeographicLib, use (adjust the version number and date as
|
||
appropriate)
|
||
- C. F. F. Karney, GeographicLib, Version @PROJECT_VERSION@ (2022-05-06),
|
||
https://geographiclib.sourceforge.io/C++/@PROJECT_VERSION@
|
||
|
||
\section contents Contents
|
||
- \ref intro
|
||
- \ref install
|
||
- \ref start
|
||
- \ref utilities
|
||
- \ref organization
|
||
- \ref other
|
||
- \ref geoid
|
||
- \ref gravity
|
||
- \ref normalgravity
|
||
- \ref magnetic
|
||
- \ref geodesic
|
||
- \ref nearest
|
||
- \ref triaxial
|
||
- \ref jacobi
|
||
- \ref rhumb
|
||
- \ref greatellipse
|
||
- \ref transversemercator
|
||
- \ref geocentric
|
||
- \ref auxlat
|
||
- \ref highprec
|
||
- \ref changes
|
||
|
||
<center>
|
||
Forward to \ref intro.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page intro Introduction
|
||
|
||
<center>
|
||
Forward to \ref install. Up to \ref contents.
|
||
</center>
|
||
|
||
GeographicLib offers a C++ interfaces to a small (but important!) set
|
||
of geographic transformations. It grew out of a desire to improve on
|
||
the GEOTRANS
|
||
package for transforming between geographic and MGRS coordinates. At
|
||
present, GeographicLib provides UTM, UPS, MGRS, geocentric, and local
|
||
cartesian projections, gravity and geomagnetic models, and classes for
|
||
geodesic calculations.
|
||
|
||
The goals of GeographicLib are:
|
||
- Accuracy. In most applications the accuracy is close to round-off,
|
||
about 5 nm (5 nanometers). Even though in many geographic
|
||
applications 1 cm is considered "accurate enough", there is little
|
||
penalty in providing much better accuracy. In situations where a
|
||
faster approximate algorithm is necessary, GeographicLib offers an
|
||
accurate benchmark to guide the development.
|
||
- Completeness. For each of the projections included, an attempt is
|
||
made to provide a complete solution. For example,
|
||
Geodesic::Inverse works for anti-podal points.
|
||
Similarly, Geocentric::Reverse will return accurate
|
||
geodetic coordinates even for points close to the center of the
|
||
earth.
|
||
- C++ interface. For the projection methods, this allows encapsulation
|
||
of the ellipsoid parameters.
|
||
- Emphasis on projections necessary for analyzing military data.
|
||
- Uniform treatment of UTM/UPS. The UTMUPS class treats
|
||
UPS as zone 0. This simplifies conversions between UTM and UPS
|
||
coordinates, etc.
|
||
- Well defined and stable conventions for the conversion between
|
||
UTM/UPS to MGRS coordinates.
|
||
- Detailed internal documentation on the algorithms. For the most part
|
||
GeographicLib uses published algorithms and references are given. If
|
||
changes have been made (usually to improve the numerical accuracy),
|
||
these are described in the code.
|
||
|
||
Various \ref utilities are provided with the library. These illustrate
|
||
the use of the library and are useful in their own right. This library
|
||
and the utilities have been tested with C++11 compliant versions of g++
|
||
under Linux, with Apple LLVM 7.0.2 under Mac OS X, and with MS Visual
|
||
Studio 14 (2015), 15 (2017), and 16 (2019) compiled for 32 bit and 64
|
||
bit on Windows.
|
||
|
||
The section \ref geodesic documents the method of solving the geodesic
|
||
problem.
|
||
|
||
The section \ref transversemercator documents various properties of this
|
||
projection.
|
||
|
||
The bulk of the testing has used geographically relevant values of the
|
||
flattening. Thus, you can expect close to full accuracy for −0.01
|
||
≤ \e f ≤ 0.01 (but note that TransverseMercatorExact is restricted
|
||
to \e f > 0). However, reasonably accurate results can be expected if
|
||
−0.1 ≤ \e f ≤ 0.1. Outside this range, you should attempt
|
||
to verify the accuracy of the routines independently. Two types of
|
||
problems may occur with larger values of <i>f</i>:
|
||
- Some classes, specifically Geodesic, GeodesicLine, and
|
||
TransverseMercator, use series expansions using \e f as a small
|
||
parameter. The accuracy of these routines will degrade as \e f
|
||
becomes large.
|
||
- Even when exact formulas are used, many of the classes need to invert
|
||
the exact formulas (e.g., to invert a projection), typically, using
|
||
Newton's method. This usually provides an essentially exact
|
||
inversion. However, the choice of starting guess and the exit
|
||
conditions have been tuned to cover small values of \e f and the
|
||
inversion may be incorrect if \e f is large.
|
||
|
||
Undoubtedly, bugs lurk in this code and in the documentation. Please
|
||
report any you find to charles@karney.com.
|
||
|
||
<center>
|
||
Forward to \ref install. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page install Installing GeographicLib
|
||
|
||
<center>
|
||
Back to \ref intro. Forward to \ref start. Up to \ref contents.
|
||
</center>
|
||
|
||
GeographicLib has been developed under Linux with the g++ compiler,
|
||
under Mac OS X with Xcode, and under Windows with Visual Studio 2015 and
|
||
later. It should compile on any systems with a C++11 compliant
|
||
compiler. First download one of
|
||
- <a href="https://sourceforge.net/projects/geographiclib/files/distrib-C++/GeographicLib-@PROJECT_FULLVERSION@.tar.gz">
|
||
GeographicLib-@PROJECT_VERSION@.tar.gz</a> tar'ed sources
|
||
- <a href="https://sourceforge.net/projects/geographiclib/files/distrib-C++/GeographicLib-@PROJECT_FULLVERSION@.zip">
|
||
GeographicLib-@PROJECT_VERSION@.zip</a> zipped sources
|
||
- <a href="https://sourceforge.net/projects/geographiclib/files/distrib-C++/GeographicLib-@PROJECT_FULLVERSION@-win32.exe">
|
||
GeographicLib-@PROJECT_VERSION@-win32.exe</a> 32-bit binary installer for Windows
|
||
- <a href="https://sourceforge.net/projects/geographiclib/files/distrib-C++/GeographicLib-@PROJECT_FULLVERSION@-win64.exe">
|
||
GeographicLib-@PROJECT_VERSION@-win64.exe</a> 64-bit binary installer for Windows
|
||
.
|
||
Then pick one of the first five options below:
|
||
- \ref cmake. This is the preferred installation method as it will work
|
||
on the widest range of platforms. However it requires that you have
|
||
<a href="https://www.cmake.org">cmake</a> installed.
|
||
- \ref autoconf. This method works for most Unix-like systems,
|
||
including Linux and Mac OS X.
|
||
- \ref binaryinst. Use this installation method if you only need to use
|
||
the \ref utilities supplied with GeographicLib.
|
||
- \ref maintainer. This describes addition tasks of interest only to
|
||
the maintainers of this code.
|
||
.
|
||
This section documents only how to install the <i>software</i>. If you
|
||
wish to use GeographicLib to evaluate geoid heights or the earth's
|
||
gravitational or magnetic fields, then you must also install the
|
||
relevant data files. See \ref geoidinst, \ref gravityinst, and \ref
|
||
magneticinst for instructions.
|
||
|
||
The first two installation methods use two important techniques which
|
||
make software maintenance simpler
|
||
- <b>Out-of-source builds:</b> This means that you create a separate
|
||
directory for compiling the code. In the description here the
|
||
directories are called BUILD and are located in the top-level of the
|
||
source tree. You might want to use a suffix to denote the type of
|
||
build, e.g., BUILD-vc14 for Visual Studio 14 (2015), or BUILD-shared
|
||
for a build which creates a shared library. The advantages of
|
||
out-of-source builds are:
|
||
- You don't mess up the source tree, so it's easy to "clean up".
|
||
Indeed the source tree might be on a read-only file system.
|
||
- Builds for multiple platforms or compilers don't interfere with each
|
||
other.
|
||
- <b>The library is installed:</b> After compilation, there is a
|
||
separate <i>install</i> step which copies the headers, libraries,
|
||
tools, and documentation to a "central" location. You may at this
|
||
point delete the source and build directories. If you have
|
||
administrative privileges, you can install GeographicLib for the use
|
||
of all users (e.g., in /usr/local). Otherwise, you can install it for
|
||
your personal use (e.g., in $HOME/packages).
|
||
|
||
\section cmake Installation with cmake
|
||
|
||
This is the recommended method of installation; however it requires that
|
||
<a href="https://www.cmake.org">cmake</a>, version 3.7.0 or later, be
|
||
installed on your system. This permits GeographicLib to be built either
|
||
as a shared or a static library on a wide variety of systems. cmake can
|
||
also determine the capabilities of your system and adjust the
|
||
compilation of the libraries and examples appropriately.
|
||
|
||
cmake is available for most computer platforms. On Linux systems cmake
|
||
will typically be one of the standard packages and can be installed by a
|
||
command like
|
||
\verbatim
|
||
yum install cmake \endverbatim
|
||
(executed as root). The minimum version of cmake supported for building
|
||
GeographicLib is 3.7.0 (which was released on 2016-11-11).
|
||
|
||
On other systems, download a binary installer from https://www.cmake.org
|
||
click on download, and save and run the appropriate installer. Run the
|
||
cmake command with no arguments to get help. Other useful tools are
|
||
ccmake and cmake-gui which offer curses and graphical interfaces to
|
||
cmake. Building under cmake depends on whether it is targeting an IDE
|
||
(interactive development environment) or generating Unix-style
|
||
makefiles. The instructions below have been tested with makefiles and
|
||
g++ on Linux and with the Visual Studio IDE on Windows. It is known to
|
||
work also for Visual Studio 2017 Build Tools.
|
||
|
||
Here are the steps to compile and install GeographicLib:
|
||
- Unpack the source, running one of \verbatim
|
||
tar xfpz GeographicLib-@PROJECT_VERSION@.tar.gz
|
||
unzip -q GeographicLib-@PROJECT_VERSION@.zip \endverbatim
|
||
then enter the directory created with \verbatim
|
||
cd GeographicLib-@PROJECT_VERSION@ \endverbatim
|
||
- Create a separate build directory and enter it, for example, \verbatim
|
||
mkdir BUILD
|
||
cd BUILD \endverbatim
|
||
- Run cmake, pointing it to the source directory (..). On Linux, Unix,
|
||
and MacOSX systems, the command is \verbatim
|
||
cmake .. \endverbatim
|
||
For Windows, the command is typically something like \verbatim
|
||
cmake -G "Visual Studio 14" -A win32 \
|
||
-D CMAKE_INSTALL_PREFIX="C:/Program Files (x86)/GeographicLib-@PROJECT_VERSION@" \
|
||
..
|
||
cmake -G "Visual Studio 14" -A x64 \
|
||
-D CMAKE_INSTALL_PREFIX="C:/Program Files/GeographicLib-@PROJECT_VERSION@" \
|
||
..\endverbatim
|
||
The definitions of CMAKE_INSTALL_PREFIX point to system directories.
|
||
You might instead prefer to install to a user directory such as
|
||
<code>C:/Users/jsmith/projects/GeographicLib-@PROJECT_VERSION@</code>.
|
||
The settings given above are recommended to ensure that packages that
|
||
use GeographicLib use the version compiled with the right compiler.
|
||
If you need to rerun cmake, use \verbatim
|
||
cmake . \endverbatim
|
||
possibly including some options via <code>-D</code> (see the next step).
|
||
- cmake allows you to configure how GeographicLib is built and installed by
|
||
supplying options, for example `\verbatim
|
||
cmake -D CMAKE_INSTALL_PREFIX=/tmp/geographic . \endverbatim
|
||
The options you might need to change are
|
||
- <code>CMAKE_INSTALL_PREFIX</code> (default: <code>/usr/local</code>
|
||
on non-Windows systems, <code>C:/Program Files/GeographicLib</code>
|
||
on Windows systems) specifies where the library will be installed.
|
||
For Windows systems, you might want to use a prefix which includes
|
||
the compiler version, in order to keep the libraries built with
|
||
different versions of the compiler in distinct locations. If you
|
||
just want to try the library to see if it suits your needs, pick,
|
||
for example, `CMAKE_INSTALL_PREFIX=/tmp/geographic`. Where under
|
||
`CMAKE_INSTALL_PREFIX` the various components of the library are
|
||
installed is governed by the following variables (a value of an
|
||
empty string or "OFF" disables installation):
|
||
- `INCDIR` header files (the `GeographicLib` subdirectory is used)
|
||
- `BINDIR` tools
|
||
- `SBINDIR` admin tools
|
||
- `LIBDIR` libraries
|
||
- `DLLDIR` dlls
|
||
- `MANDIR` the man pages (the `man1` and `man8` subdirectories are used)
|
||
- `CMAKEDIR` cmake configs
|
||
- `PKGDIR` package config
|
||
- `DOCDIR` documentation
|
||
- `EXAMPLEDIR` examples
|
||
- <code>GEOGRAPHICLIB_DATA</code> (default:
|
||
/usr/local/share/GeographicLib for non-Windows systems,
|
||
C:/ProgramData/GeographicLib for Windows systems) specifies the default
|
||
location for the various datasets for use by Geoid,
|
||
GravityModel, and MagneticModel.
|
||
See \ref geoidinst, \ref gravityinst, and \ref magneticinst for more
|
||
information.
|
||
- <code>BUILD_SHARED_LIBS</code> (default ON) and
|
||
<code>BUILD_BOTH_LIBS</code> (default OFF) specify the types of
|
||
libraries to build. If `BUILD_BOTH_LIBS` is set, then both shared
|
||
and static libraries are building. Otherwise a single library is
|
||
built with the type determined by `BUILD_SHARED_LIBS`
|
||
- <code>CMAKE_BUILD_TYPE</code> (default: Release). This
|
||
flags only affects non-IDE compile environments (like make + g++).
|
||
The default is actually blank, but this is treated as
|
||
Release. Choose one of
|
||
\verbatim
|
||
Debug
|
||
Release
|
||
RelWithDebInfo
|
||
MinSizeRel
|
||
\endverbatim
|
||
(With IDE compile environments, you get to select the build type in
|
||
the IDE.)
|
||
- <code>BUILD_DOCUMENTATION</code> (default: OFF). If set to
|
||
ON, then html documentation is created from the source files,
|
||
provided a sufficiently recent version of doxygen can be found.
|
||
Otherwise, the html documentation will redirect to the appropriate
|
||
version of the online documentation.
|
||
- <code>GEOGRAPHICLIB_PRECISION</code> specifies the precision to be
|
||
used for "real" (i.e., floating point) numbers. See \ref highprec
|
||
for additional information about using quad and arbitrary precision.
|
||
Nearly all the testing has been carried out with doubles and that's
|
||
the recommended configuration. In particular you should avoid
|
||
"installing" the library with a precision different from double.
|
||
Here are the possible values
|
||
-# float (24-bit precision); typically this is far to inaccurate
|
||
for geodetic applications.
|
||
-# double precision (53-bit precision, the default).
|
||
-# long double (64-bit precision); this does not apply for Visual
|
||
Studio (long double is the same as double with that compiler).
|
||
-# quad precision (113-bit precision).
|
||
-# arbitrary precision.
|
||
- <code>USE_BOOST_FOR_EXAMPLES</code> (default: OFF). If set to ON,
|
||
then the Boost library is searched for in order to build the
|
||
NearestNeighbor example.
|
||
- <code>APPLE_MULTIPLE_ARCHITECTURES</code> (default: OFF). If set to
|
||
ON, build for i386 and x86_64 and Mac OS X systems. Otherwise,
|
||
build for the default architecture.
|
||
- <code>CONVERT_WARNINGS_TO_ERRORS</code> (default: OFF). If set to
|
||
ON, then compiler warnings are treated as errors.
|
||
.
|
||
- Build and install the software. In non-IDE environments, run
|
||
\verbatim
|
||
make # compile the library and utilities
|
||
make test # run some tests
|
||
make install # as root, if CMAKE_INSTALL_PREFIX is a system directory
|
||
\endverbatim
|
||
Possible additional targets are \verbatim
|
||
make dist
|
||
make exampleprograms \endverbatim
|
||
On IDE environments, run your IDE (e.g., Visual Studio), load
|
||
GeographicLib.sln, pick the build type (e.g., Release), and select
|
||
"Build Solution". If this succeeds, select "RUN_TESTS" to build;
|
||
finally, select "INSTALL" to install (RUN_TESTS and INSTALL are in
|
||
the CMakePredefinedTargets folder). Alternatively (for example, if
|
||
you are using the Visual Studio 2017 Build Tools), you run the Visual
|
||
Studio compiler from the command line with \verbatim
|
||
cmake --build . --config Release --target ALL_BUILD
|
||
cmake --build . --config Release --target RUN_TESTS
|
||
cmake --build . --config Release --target INSTALL \endverbatim
|
||
For maximum flexibility, it's a good idea to build and install both
|
||
the Debug and Release versions of the library (in that order). The
|
||
installation directories will then contain the release versions of the
|
||
tools and <i>both</i> versions (debug and release) of the libraries.
|
||
If you use cmake to configure and build your programs, then the right
|
||
version of the library (debug vs. release) will automatically be used.
|
||
- The headers, library, and utilities are installed in the
|
||
`include/GeographicLib`, `lib`, and `bin` directories under
|
||
<code>CMAKE_INSTALL_PREFIX</code>. (dll dynamic libraries are
|
||
installed in `bin`.) For documentation, open in a web browser
|
||
<a href="index.html">`share/doc/GeographicLib/html/index.html`</a>.
|
||
- With cmake 3.13 and later, cmake can create the build directory for
|
||
you. This allows you to configure and run the build on Windows with
|
||
\verbatim
|
||
cmake -G "Visual Studio 14" -A x64 -S . -B BUILD
|
||
cmake --build BUILD --config Release --target ALL_BUILD \endverbatim
|
||
or on Linux with \verbatim
|
||
cmake -S . -B BUILD
|
||
make -C BUILD -j4 \endverbatim
|
||
|
||
\section autoconf Installation using the autoconfigure tools
|
||
|
||
The method works on most Unix-like systems including Linux and Mac OS X.
|
||
Here are the steps to compile and install GeographicLib:
|
||
- Unpack the source, running \verbatim
|
||
tar xfpz GeographicLib-@PROJECT_VERSION@.tar.gz \endverbatim
|
||
then enter the directory created \verbatim
|
||
cd GeographicLib-@PROJECT_VERSION@ \endverbatim
|
||
- Create a separate build directory and enter it, for example, \verbatim
|
||
mkdir BUILD
|
||
cd BUILD \endverbatim
|
||
- Configure the software, specifying the path of the source directory,
|
||
with \verbatim
|
||
../configure \endverbatim
|
||
- By default GeographicLib will be installed under /usr/local.
|
||
You can change this with, for example \verbatim
|
||
../configure --prefix=/tmp/geographic \endverbatim
|
||
- Compile and install the software with \verbatim
|
||
make
|
||
make install \endverbatim
|
||
- The headers, library, and utilities are installed in the
|
||
include/GeographicLib, lib, and bin directories under
|
||
<code>prefix</code>. For documentation, open <a href="index.html">
|
||
`share/doc/GeographicLib/html/index.html`</a> in a web browser.
|
||
|
||
\section binaryinst Using a binary installer
|
||
|
||
Binary installers are available for some platforms
|
||
|
||
\subsection binaryinstwin Windows
|
||
|
||
Use this method if you only need to use the GeographicLib utilities.
|
||
The header files and static and shared versions of library are also
|
||
provided; these can only be used by Visual Studio 14 2015 or later
|
||
(2017, 2019, or 2022) (in either release or debug mode). However, if
|
||
you plan to use the library, it may be advisable to build it with the
|
||
compiler you are using for your own code using \ref cmake.
|
||
|
||
Download and run
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/distrib-C++/GeographicLib-@PROJECT_VERSION@-win32.exe">
|
||
GeographicLib-@PROJECT_VERSION@-win32.exe</a> or
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/distrib-C++/GeographicLib-@PROJECT_VERSION@-win64.exe">
|
||
GeographicLib-@PROJECT_VERSION@-win64.exe</a>:
|
||
- read the MIT/X11 License agreement,
|
||
- select whether you want your PATH modified,
|
||
- select the installation folder, by default
|
||
`C:\\Program Files\\GeographicLib-@PROJECT_VERSION@` or
|
||
`C:\\Program Files (x86)\\GeographicLib-@PROJECT_VERSION@`,
|
||
- select the start menu folder,
|
||
- and install.
|
||
.
|
||
(Note that the default installation folder adheres the the convention
|
||
given in \ref cmake.) The start menu will now include links to the
|
||
documentation for the library and for the utilities (and a link for
|
||
uninstalling the library). If you ask for your PATH to be modified, it
|
||
will include
|
||
<code>C:/Program FilesGeographicLib-@PROJECT_VERSION@/bin</code>
|
||
where the utilities are installed. The headers and library are
|
||
installed in the `include/GeographicLib` and `lib` folders. The libraries
|
||
were built using using Visual Studio 14 2015 in release and debug modes.
|
||
The utilities were linked against the release-mode shared library.
|
||
|
||
\subsection binaryinstosx MacOSX
|
||
|
||
GeographicLib is available as Homebrew package
|
||
[geographiclib](https://formulae.brew.sh/formula/geographiclib). Follow
|
||
the directions on https://brew.sh/ for installing this package manager.
|
||
Then type \verbatim
|
||
brew install geographiclib \endverbatim
|
||
Now links to GeographicLib are installed under /usr/local.
|
||
|
||
\subsection binaryinstlin Linux
|
||
|
||
Some Linux distributions, Fedora, Debian, and Ubuntu, offer
|
||
GeographicLib as a standard package. Typically these will be one or two
|
||
versions behind the latest. It's also available with the follow package
|
||
managers
|
||
- Homebrew package [geographiclib](
|
||
https://formulae.brew.sh/formula/geographiclib) (also for MacOSX)
|
||
- conda-forge package [geographiclib-cpp](
|
||
https://anaconda.org/conda-forge/geographiclib-cpp) (also for MacOSX
|
||
and Windows)
|
||
- vcpkg package [geographiclib](https://vcpkg.info/port/geographiclib)
|
||
(also for MacOSX and Windows)
|
||
|
||
\section maintainer Maintainer tasks
|
||
|
||
Some aspects of library maintenance are covered in [HOWTO-RELEASE.txt](
|
||
https://github.com/geographiclib/geographiclib/blob/main/HOWTO-RELEASE.txt).
|
||
|
||
Check the code out of git with \verbatim
|
||
git clone git@github.com:geographiclib/geographiclib.git
|
||
\endverbatim
|
||
There are three branches in the git repository:
|
||
- <b>main</b>: the main branch for code maintenance. Releases are
|
||
tagged on this branch as, e.g., v@PROJECT_VERSION@.
|
||
- <b>devel</b>: the development branch; changes made here are merged
|
||
into main.
|
||
- <b>release</b>: the release branch created by unpacking the source
|
||
releases (git is \e not used to merge changes from the other
|
||
branches into this branch). This differs from the main branch in that
|
||
some administrative files are excluded while some intermediate files
|
||
are included (in order to aid building on as many platforms as
|
||
possible). Releases are tagged on this branch as, e.g.,
|
||
r@PROJECT_VERSION@.
|
||
.
|
||
The autoconf configuration script and the formatted man pages are not
|
||
checked into main branch of the repository. In order to create these,
|
||
configure with cmake and run \verbatim
|
||
make dist \endverbatim
|
||
which will copy the man pages from the build directory back into the
|
||
source tree and package the resulting source tree for distribution as
|
||
\verbatim
|
||
GeographicLib-@PROJECT_VERSION@.tar.gz
|
||
GeographicLib-@PROJECT_VERSION@.zip \endverbatim
|
||
Finally, \verbatim
|
||
make package \endverbatim
|
||
or building PACKAGE in Visual Studio will create a binary installer for
|
||
GeographicLib. For Windows, this requires in the installation of
|
||
<a href="https://nsis.sourceforge.io">NSIS</a>. On Windows, you should
|
||
configure GeographicLib with <code>PACKAGE_DEBUG_LIBS</code>=ON, build both
|
||
Release and Debug versions of the library and finally build PACKAGE in
|
||
Release mode. This will get the release and debug versions of the
|
||
library included in the package. For example, the 64-bit binary
|
||
installer is created with \verbatim
|
||
cmake -G "Visual Studio 14" -A x64 \
|
||
-D BUILD_BOTH_LIBS=ON \
|
||
-D PACKAGE_DEBUG_LIBS=ON \
|
||
..
|
||
cmake --build . --config Debug --target ALL_BUILD
|
||
cmake --build . --config Release --target ALL_BUILD
|
||
cmake --build . --config Release --target PACKAGE \endverbatim
|
||
|
||
Prior to making a release, the script
|
||
<code>develop/test-distribution.sh</code> is run on a Fedora system. This
|
||
checked that the library compiles correctly is multiple configurations.
|
||
In addition it creates a directory and scripts for checking the
|
||
compilation on Windows.
|
||
|
||
The following Fedora packages are required by
|
||
<code>tests/test-distribution.sh</code>
|
||
- cmake
|
||
- automake
|
||
- autoconf-archive
|
||
- libtool
|
||
- gcc-c++
|
||
- ccache
|
||
- doxygen
|
||
- boost-devel
|
||
- mpfr-devel
|
||
- mpreal.h, version 3.6.9 with PR #15, from
|
||
https://github.com/advanpix/mpreal and installed in the
|
||
<code>include/</code> directory.
|
||
|
||
For all the tests to be run, the following datasets need to be installed
|
||
- geoid models: `egm96-5`
|
||
- magnetic models: `wmm2010` `emm2015`
|
||
- gravity models: `egm2008` `grs80`
|
||
|
||
<center>
|
||
Back to \ref intro. Forward to \ref start. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page start Getting started
|
||
|
||
<center>
|
||
Back to \ref install. Forward to \ref utilities. Up to \ref contents.
|
||
</center>
|
||
|
||
Much (but not all!) of the useful functionality of GeographicLib is
|
||
available via simple command line utilities. Interfaces to some of them
|
||
are available via the web. See \ref utilities for documentation on
|
||
these.
|
||
|
||
In order to use GeographicLib from C++ code, you will need to
|
||
- Include the header files for the GeographicLib classes in your code.
|
||
E.g., \code
|
||
#include <GeographicLib/LambertConformalConic.hpp> \endcode
|
||
- Include the GeographicLib:: namespace prefix to the GeographicLib classes,
|
||
or include \code
|
||
using namespace GeographicLib; \endcode
|
||
in your code.
|
||
- Build your code with cmake. In brief, the necessary steps are:
|
||
- include in your CMakeLists.txt files \verbatim
|
||
find_package (GeographicLib REQUIRED)
|
||
include_directories (${GeographicLib_INCLUDE_DIRS})
|
||
add_executable (program source1.cpp source2.cpp)
|
||
target_link_libraries (program ${GeographicLib_LIBRARIES}) \endverbatim
|
||
- configure your package, e.g., with \verbatim
|
||
mkdir BUILD
|
||
cd BUILD
|
||
cmake -G "Visual Studio 14" -A x64 \
|
||
-D CMAKE_PREFIX_PATH="C:/Program Files" \
|
||
-D CMAKE_INSTALL_PREFIX="C:/Program Files/testgeog" \
|
||
.. \endverbatim
|
||
Note that you almost always want to configure and build your code
|
||
somewhere other than the source directory (in this case, we use the
|
||
BUILD subdirectory). Also, on Windows, make sure that the version
|
||
of Visual Studio (14 in the example above) architecture (x64 in the
|
||
example above) is compatible with that used to build GeographicLib.
|
||
In this example, it's not necessary to specify
|
||
<code>CMAKE_PREFIX_PATH</code>, because <code>C:/Program
|
||
Files</code> is one of the system paths which is searched
|
||
automatically.
|
||
- build your package. On Linux and MacOS this usually involves just
|
||
running make. On Windows, you can load the solution file created by
|
||
cmake into Visual Studio; alternatively, you can get cmake to run
|
||
build your code with \verbatim
|
||
cmake --build . --config Release --target ALL_BUILD \endverbatim
|
||
You might also want to install your package (using "make install" or
|
||
build the "INSTALL" target with the command above).
|
||
With cmake 3.13 and later, cmake can create the build directory for
|
||
you. This allows you to configure and run the build on Windows with
|
||
\verbatim
|
||
cmake -G "Visual Studio 14" -A x64 \
|
||
-D CMAKE_PREFIX_PATH="C:/Program Files" \
|
||
-D CMAKE_INSTALL_PREFIX="C:/Program Files/testgeog" \
|
||
-S . -B BUILD
|
||
cmake --build BUILD --config Release --target ALL_BUILD \endverbatim
|
||
or on Linux with \verbatim
|
||
cmake -D CMAKE_INSTALL_PREFIX="/tmp/testgeog" \
|
||
-S . -B BUILD
|
||
make -C BUILD -j4 \endverbatim
|
||
|
||
NOTE: The inclusion of \verbatim
|
||
include_directories (${GeographicLib_INCLUDE_DIRS}) \endverbatim
|
||
is only necessary if `find_package` found GeographicLib via the
|
||
`FindGeographicLib.cmake` "module". However, it's OK to include this
|
||
line even for "config" lookups.
|
||
|
||
The most import step in using cmake is the `find_package` command. The cmake
|
||
documentation describes the locations searched by find_package (the
|
||
appropriate rule for GeographicLib are those for "Config" mode lookups).
|
||
In brief, the locations that are searched are (from least specific to
|
||
most specific, i.e., in <i>reverse</i> order) are
|
||
- under the system paths, i.e., locations such as <code>C:/Program
|
||
Files</code> and <code>/usr/local</code>);
|
||
- frequently, it's necessary to search within a "package directory"
|
||
(or set of directories) for external dependencies; this is given by
|
||
a (semicolon separated) list of directories specified by the cmake
|
||
variable <code>CMAKE_PREFIX_PATH</code> (illustrated above);
|
||
- the package directory for GeographicLib can be overridden with the
|
||
<i>environment variable</i> <code>GeographicLib_DIR</code> (which is the
|
||
directory under which GeographicLib is installed);
|
||
- finally, if you need to point to a particular build of GeographicLib,
|
||
define the <i>cmake variable</i> <code>GeographicLib_DIR</code>, which
|
||
specifies the absolute path of the directory containing the
|
||
configuration file <code>geographiclib-config.cmake</code> (for
|
||
debugging this may be the top-level <i>build</i> directory, as
|
||
opposed to <i>installation</i> directory, for GeographicLib).
|
||
.
|
||
Typically, specifying nothing or <code>CMAKE_PREFIX_PATH</code>
|
||
suffices. However the two <code>GeographicLib_DIR</code> variables allow
|
||
for a specific version to be chosen. On Windows systems (with Visual
|
||
Studio), find_package will only find versions of GeographicLib built with
|
||
the right version of the compiler. (If you used a non-cmake method of
|
||
installing GeographicLib, you can try copying cmake/FindGeographicLib.cmake
|
||
to somewhere in your <code>CMAKE_MODULE_PATH</code> in order for
|
||
find_package to work. However, this method has not been thoroughly
|
||
tested.)
|
||
|
||
If GeographicLib is not found, check the values of
|
||
<code>GeographicLib_CONSIDERED_CONFIGS</code> and
|
||
<code>GeographicLib_CONSIDERED_VERSIONS</code>; these list the
|
||
configuration files and corresponding versions which were considered
|
||
by find_package.
|
||
|
||
If GeographicLib is found, then the following cmake variables are set:
|
||
- <code>GeographicLib_FOUND</code> = 1
|
||
- <code>GeographicLib_VERSION</code> = @PROJECT_VERSION@
|
||
- <code>GeographicLib_INCLUDE_DIRS</code>
|
||
- <code>GeographicLib_LIBRARIES</code> = one of the following two:
|
||
- <code>GeographicLib_SHARED_LIBRARIES</code> = GeographicLib::GeographicLib_SHARED
|
||
- <code>GeographicLib_STATIC_LIBRARIES</code> = GeographicLib::GeographicLib_STATIC
|
||
- <code>GeographicLib_LIBRARY_DIRS</code>
|
||
- <code>GeographicLib_BINARY_DIRS</code>
|
||
- <code>GEOGRAPHICLIB_DATA</code> = value of this compile-time parameter
|
||
- <code>GEOGRAPHICLIB_PRECISION</code> = value of this compile-time
|
||
parameter (usually 2). You can set this parameter before calling
|
||
`find_package` and only versions with a matching value of
|
||
`GEOGRAPHICLIB_PRECISION` will be found.
|
||
.
|
||
Either of <code>GeographicLib_SHARED_LIBRARIES</code> or
|
||
<code>GeographicLib_STATIC_LIBRARIES</code> may be empty, if that version
|
||
of the library is unavailable. If you require a specific version,
|
||
SHARED or STATIC, of the library, add a <code>COMPONENTS</code> clause
|
||
to find_package, e.g.,
|
||
\verbatim
|
||
find_package (GeographicLib 2.0 REQUIRED COMPONENTS SHARED) \endverbatim
|
||
causes only packages which include the shared library to be found. If
|
||
the package includes both versions of the library, then
|
||
<code>GeographicLib_LIBRARIES</code> is set to the shared version,
|
||
unless you include \verbatim
|
||
set (GeographicLib_USE_STATIC_LIBS ON) \endverbatim
|
||
<i>before</i> the find_package command. You can check whether
|
||
<code>GeographicLib_LIBRARIES</code> refers to the shared or static
|
||
library with \verbatim
|
||
get_target_property (_LIBTYPE ${GeographicLib_LIBRARIES} TYPE) \endverbatim
|
||
which results in <code>_LIBTYPE</code> being set to
|
||
<code>SHARED_LIBRARY</code> or <code>STATIC_LIBRARY</code>.
|
||
On Windows, cmake takes care of linking to the release or debug
|
||
version of the library as appropriate. (This assumes that the Release
|
||
and Debug versions of the libraries were built and installed. This is
|
||
true for the Windows binary installer for GeographicLib version 1.34 and
|
||
later.)
|
||
|
||
You can also use the pkg-config utility to specify compile and link
|
||
flags. This requires that pkg-config be installed and that it's
|
||
configured to search, e.g., /usr/local/lib/pgkconfig; if not, define
|
||
the environment variable <code>PKG_CONFIG_PATH</code> to include
|
||
this directory. The compile and link steps under Linux would
|
||
typically be
|
||
\verbatim
|
||
g++ -c -g -O3 `pkg-config --cflags geographiclib` testprogram.cpp
|
||
g++ -g -o testprogram testprogram.o `pkg-config --libs geographiclib`
|
||
\endverbatim
|
||
|
||
Here is a very simple test code, which uses the Geodesic
|
||
class:
|
||
\include example-Geodesic-small.cpp
|
||
This example is <code>examples/example-Geodesic-small.cpp</code>. If you
|
||
compile, link, and run it according to the instructions above, it should
|
||
print out \verbatim
|
||
5551.76 km \endverbatim
|
||
Here is a complete CMakeList.txt files you can use to build this test
|
||
code using the installed library: \verbatim
|
||
project (geodesictest)
|
||
cmake_minimum_required (VERSION 3.1.0)
|
||
|
||
find_package (GeographicLib REQUIRED)
|
||
include_directories (${GeographicLib_INCLUDE_DIRS})
|
||
|
||
if (NOT MSVC)
|
||
set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||
endif ()
|
||
|
||
add_executable (${PROJECT_NAME} example-Geodesic-small.cpp)
|
||
target_link_libraries (${PROJECT_NAME} ${GeographicLib_LIBRARIES})
|
||
|
||
if (MSVC)
|
||
get_target_property (_LIBTYPE ${GeographicLib_LIBRARIES} TYPE)
|
||
if (_LIBTYPE STREQUAL "SHARED_LIBRARY")
|
||
# On Windows systems, copy the shared library to build directory
|
||
add_custom_command (TARGET ${PROJECT_NAME} POST_BUILD
|
||
COMMAND ${CMAKE_COMMAND} -E
|
||
copy $<TARGET_FILE:${GeographicLib_LIBRARIES}> ${CMAKE_CFG_INTDIR}
|
||
COMMENT "Copying shared library for GeographicLib")
|
||
endif ()
|
||
endif () \endverbatim
|
||
|
||
The next steps are:
|
||
- Learn about and run the \ref utilities.
|
||
- Read the section, \ref organization, for an overview of the library.
|
||
- Browse the <a href="annotated.html">Class List</a> for full documentation
|
||
on the classes in the library.
|
||
- Look at the example code in the examples directory. Each file
|
||
provides a very simple standalone example of using one GeographicLib
|
||
class. These are included in the descriptions of the classes.
|
||
- Look at the source code for the utilities in the tools directory for
|
||
more examples of using GeographicLib from C++ code, e.g.,
|
||
GeodesicProj.cpp is a program to performing various geodesic
|
||
projections.
|
||
|
||
Here's a list of some of the abbreviations used here with links to the
|
||
corresponding Wikipedia articles:
|
||
- <a href="https://en.wikipedia.org/wiki/WGS84">
|
||
WGS84</a>, World Geodetic System 1984.
|
||
- <a href="https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system">
|
||
UTM</a>, Universal Transverse Mercator coordinate system.
|
||
- <a href="https://en.wikipedia.org/wiki/Universal_Polar_Stereographic">
|
||
UPS</a>, Universal Polar Stereographic coordinate system.
|
||
- <a href="https://en.wikipedia.org/wiki/Military_grid_reference_system">
|
||
MGRS</a>, Military Grid Reference System.
|
||
- <a href="https://en.wikipedia.org/wiki/Geoid">
|
||
EGM</a>, Earth Gravity Model.
|
||
- <a href="https://en.wikipedia.org/wiki/World_Magnetic_Model">
|
||
WMM</a>, World Magnetic Model.
|
||
- <a href="https://en.wikipedia.org/wiki/IGRF">
|
||
IGRF</a>, International Geomagnetic Reference Field.
|
||
|
||
<center>
|
||
Back to \ref install. Forward to \ref utilities. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page utilities Utility programs
|
||
|
||
<center>
|
||
Back to \ref start. Forward to \ref organization. Up to \ref contents.
|
||
</center>
|
||
|
||
Various utility programs are provided with GeographicLib. These should
|
||
be installed in a directory included in your PATH (e.g.,
|
||
/usr/local/bin). These programs are wrapper programs that invoke
|
||
the underlying functionality provided by the library.
|
||
|
||
The utilities are
|
||
- <a href="GeoConvert.1.html">
|
||
<b>GeoConvert</b></a>: convert geographic coordinates using
|
||
GeoCoords. See \ref GeoConvert.cpp.
|
||
- <a href="GeodSolve.1.html">
|
||
<b>GeodSolve</b></a>: perform geodesic calculations using
|
||
Geodesic and GeodesicLine. See \ref GeodSolve.cpp.
|
||
- <a href="Planimeter.1.html">
|
||
<b>Planimeter</b></a>: compute the area of geodesic polygons using
|
||
PolygonAreaT. See \ref Planimeter.cpp.
|
||
- <a href="TransverseMercatorProj.1.html">
|
||
<b>TransverseMercatorProj</b></a>: convert between geographic
|
||
and transverse Mercator. This is for testing
|
||
TransverseMercatorExact and
|
||
TransverseMercator. See \ref TransverseMercatorProj.cpp.
|
||
- <a href="CartConvert.1.html">
|
||
<b>CartConvert</b></a>: convert geodetic coordinates to geocentric or
|
||
local cartesian using Geocentric and
|
||
LocalCartesian. See \ref CartConvert.cpp.
|
||
- <a href="GeodesicProj.1.html">
|
||
<b>GeodesicProj</b></a>: perform projections based on geodesics
|
||
using AzimuthalEquidistant, Gnomonic,
|
||
and CassiniSoldner. See \ref GeodesicProj.cpp.
|
||
- <a href="ConicProj.1.html">
|
||
<b>ConicProj</b></a>: perform conic projections using
|
||
LambertConformalConic and
|
||
AlbersEqualArea. See \ref ConicProj.cpp.
|
||
- <a href="GeoidEval.1.html">
|
||
<b>GeoidEval</b></a>: look up geoid heights using
|
||
Geoid. See \ref GeoidEval.cpp.
|
||
- <a href="Gravity.1.html">
|
||
<b>Gravity</b></a>: compute the earth's gravitational field using
|
||
GravityModel and GravityCircle. See \ref Gravity.cpp.
|
||
- <a href="MagneticField.1.html">
|
||
<b>MagneticField</b></a>: compute the earth's magnetic field using
|
||
MagneticModel and MagneticCircle. See \ref MagneticField.cpp.
|
||
- <a href="RhumbSolve.1.html">
|
||
<b>RhumbSolve</b></a>: perform rhumb line calculations using Rhumb
|
||
and RhumbLine. See \ref RhumbSolve.cpp.
|
||
.
|
||
The documentation for these utilities is in the form of man pages. This
|
||
documentation can be accessed by clicking on the utility name in the
|
||
list above, running the man command on Unix-like systems, or by invoking
|
||
the utility with the <code>\--help</code> option. A brief summary of
|
||
usage is given by invoking the utility with the <code>-h</code> option.
|
||
The version of the utility is given by the <code>\--version</code>
|
||
option.
|
||
|
||
The utilities all accept data on standard input, transform it in some
|
||
way, and print the results on standard output. This makes the utilities
|
||
easy to use within scripts to transform tabular data; however they can
|
||
also be used interactively, often with the input supplied via a pipe,
|
||
e.g.,
|
||
- echo 38SMB4488 | GeoConvert -d
|
||
|
||
Online versions of four of these utilities are provided:
|
||
- <a href="https://geographiclib.sourceforge.io/cgi-bin/GeoConvert">GeoConvert</a>
|
||
- <a href="https://geographiclib.sourceforge.io/cgi-bin/GeodSolve">GeodSolve</a>
|
||
- <a href="https://geographiclib.sourceforge.io/cgi-bin/Planimeter">Planimeter</a>
|
||
- <a href="https://geographiclib.sourceforge.io/cgi-bin/GeoidEval">GeoidEval</a>
|
||
- <a href="https://geographiclib.sourceforge.io/cgi-bin/RhumbSolve">RhumbSolve</a>
|
||
|
||
<center>
|
||
Back to \ref start. Forward to \ref organization. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page organization Code organization
|
||
|
||
<center>
|
||
Back to \ref utilities. Forward to \ref other. Up to \ref contents.
|
||
</center>
|
||
|
||
Here is a brief description of the relationship between the various
|
||
components of GeographicLib. All of these are defined in the
|
||
GeographicLib namespace.
|
||
|
||
TransverseMercator, PolarStereographic, LambertConformalConic, and
|
||
AlbersEqualArea provide the basic projections. The constructors for
|
||
these classes specify the ellipsoid and the forward and reverse
|
||
projections are implemented as const member functions.
|
||
TransverseMercator uses Krüger's series which have been extended to
|
||
sixth order in the square of the eccentricity. PolarStereographic,
|
||
LambertConformalConic, and AlbersEqualArea use the exact formulas for
|
||
the projections (e.g., from Snyder).
|
||
|
||
TransverseMercator::UTM and PolarStereographic::UPS are const static
|
||
instantiations specific for the WGS84 ellipsoid with the UTM and UPS
|
||
scale factors. (These do \e not add the standard false eastings or
|
||
false northings for UTM and UPS.) Similarly
|
||
LambertConformalConic::Mercator is a const static instantiation of this
|
||
projection for a WGS84 ellipsoid and a standard parallel of 0 (which
|
||
gives the Mercator projection). AlbersEqualArea::CylindricalEqualArea,
|
||
AzimuthalEqualAreaNorth, and AzimuthalEqualAreaSouth, likewise provide
|
||
special cases of the equal area projection.
|
||
|
||
UTMUPS uses TransverseMercator::UTM and PolarStereographic::UPS to
|
||
perform the UTM and UPS projections. The class offers a uniform
|
||
interface to UTM and UPS by treating UPS as UTM zone 0. This class
|
||
stores no internal state and the forward and reverse projections are
|
||
provided via static member functions. The forward projection offers the
|
||
ability to override the standard UTM/UPS choice and the UTM zone.
|
||
|
||
MGRS transforms between UTM/UPS coordinates and MGRS.
|
||
UPS coordinates are handled as UTM zone 0. This class stores no
|
||
internal state and the forward (UTM/UPS to MGRS) and reverse (MGRS to
|
||
UTM/UPS) conversions are provided via static member functions.
|
||
|
||
GeoCoords holds a single geographic location which may be
|
||
specified as latitude and longitude, UTM or UPS, or MGRS. Member
|
||
functions are provided to convert between coordinate systems and to
|
||
provide formatted representations of them.
|
||
<a href="GeoConvert.1.html">GeoConvert</a> is a simple command line
|
||
utility to provide access to the GeoCoords class.
|
||
|
||
TransverseMercatorExact is a drop in replacement for TransverseMercator
|
||
which uses the exact formulas, based on elliptic functions, for the
|
||
projection as given by Lee.
|
||
<a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a> is a
|
||
simple command line utility to test to the TransverseMercator and
|
||
TransverseMercatorExact.
|
||
|
||
Geodesic and GeodesicLine perform geodesic calculations. The
|
||
constructor for Geodesic specifies the ellipsoid and the direct and
|
||
inverse calculations are implemented as const member functions.
|
||
Geocentric::WGS84 is a const static instantiation of Geodesic specific
|
||
for the WGS84 ellipsoid. In order to perform a series of direct
|
||
geodesic calculations on a single line, the GeodesicLine class can be
|
||
used. This packages all the information needed to specify a geodesic.
|
||
A const member function returns the coordinates a specified distance
|
||
from the starting point. <a href="GeodSolve.1.html">GeodSolve</a> is a
|
||
simple command line utility to perform geodesic calculations.
|
||
PolygonAreaT is a class which compute the area of geodesic polygons
|
||
using the Geodesic class and <a href="Planimeter.1.html">Planimeter</a>
|
||
is a command line utility for the same purpose. AzimuthalEquidistant,
|
||
CassiniSoldner, and Gnomonic are projections based on the Geodesic
|
||
class. <a href="GeodesicProj.1.html">GeodesicProj</a> is a command line
|
||
utility to exercise these projections.
|
||
|
||
GeodesicExact and GeodesicLineExact are drop in replacements for
|
||
Geodesic and GeodesicLine in which the solution is given in terms of
|
||
elliptic integrals (computed by EllipticFunction). These classes should
|
||
be used if the absolute value of the flattening exceeds 0.02. The -E
|
||
option to <a href="GeodSolve.1.html">GeodSolve</a> uses these classes.
|
||
|
||
NearestNeighbor is a header-only class for efficiently \ref nearest of a
|
||
collection of points where the distance function obeys the triangle
|
||
inequality. The geodesic distance obeys this condition.
|
||
|
||
Geocentric and LocalCartesian convert between
|
||
geodetic and geocentric or a local cartesian system. The constructor for
|
||
specifies the ellipsoid and the forward and reverse projections are
|
||
implemented as const member functions. Geocentric::WGS84 is a
|
||
const static instantiation of Geocentric specific for the WGS84 ellipsoid.
|
||
<a href="CartConvert.1.html">CartConvert</a> is a simple command line
|
||
utility to provide access to these classes.
|
||
|
||
Geoid evaluates geoid heights by interpolation. This is
|
||
provided by the operator() member function.
|
||
<a href="GeoidEval.1.html">GeoidEval</a> is a simple command line
|
||
utility to provide access to this class. This class requires
|
||
installation of data files for the various geoid models; see \ref
|
||
geoidinst for details.
|
||
|
||
Ellipsoid is a class which performs latitude
|
||
conversions and returns various properties of the ellipsoid.
|
||
|
||
GravityModel evaluates the earth's gravitational field using a
|
||
particular gravity model. Various member functions return the
|
||
gravitational field, the gravity disturbance, the gravity anomaly, and
|
||
the geoid height <a href="Gravity.1.html">Gravity</a> is a simple
|
||
command line utility to provide access to this class. If the field
|
||
several points on a circle of latitude are sought then use
|
||
GravityModel::Circle to return a GravityCircle object whose member
|
||
functions performs the calculations efficiently. (This is particularly
|
||
important for high degree models such as EGM2008.) These classes
|
||
requires installation of data files for the various gravity models; see
|
||
\ref gravityinst for details. NormalGravity computes the gravity of the
|
||
so-called level ellipsoid.
|
||
|
||
MagneticModel evaluates the earth's magnetic field using a particular
|
||
magnetic model. The field is provided by the operator() member
|
||
function. <a href="MagneticField.1.html">MagneticField</a> is a simple
|
||
command line utility to provide access to this class. If the field
|
||
several points on a circle of latitude are sought then use
|
||
MagneticModel::Circle to return a MagneticCircle object whose operator()
|
||
member function performs the calculation efficiently. (This is
|
||
particularly important for high degree models such as emm2010.) These
|
||
classes requires installation of data files for the various magnetic
|
||
models; see \ref magneticinst for details.
|
||
|
||
Constants, Math, Utility, DMS, are general utility class which are used
|
||
internally by the library; in addition EllipticFunction is used by
|
||
TransverseMercatorExact, Ellipsoid, and GeodesicExact, and
|
||
GeodesicLineExact; Accumulator is used by PolygonAreaT, and
|
||
SphericalEngine, CircularEngine, SphericalHarmonic, SphericalHarmonic1,
|
||
and SphericalHarmonic2 facilitate the summation of spherical harmonic
|
||
series which is needed by and MagneticModel and MagneticCircle. One
|
||
important definition is Math::real which is the type used for real
|
||
numbers. This allows the library to be easily switched to using floats,
|
||
doubles, or long doubles. However all the testing has been with real
|
||
set to double and the library should be installed in this way.
|
||
|
||
GeographicLib uniformly represents all angle-like variables (latitude,
|
||
longitude, azimuth) in terms of degrees. To convert from degrees to
|
||
radians, multiple the quantity by Math::degree(). To convert from
|
||
radians to degrees , divide the quantity by Math::degree().
|
||
|
||
In general, the constructors for the classes in GeographicLib check
|
||
their arguments and throw GeographicErr exceptions with a
|
||
explanatory message if these are illegal. The member functions, e.g.,
|
||
the projections implemented by TransverseMercator and
|
||
PolarStereographic, the solutions to the geodesic problem, etc.,
|
||
typically do <i>not</i> check their arguments; the calling program
|
||
should ensure that the arguments are legitimate. However, the functions
|
||
implemented by UTMUPS, MGRS, and GeoCoords do check their arguments and
|
||
may throw GeographicErr exceptions. Similarly Geoid may
|
||
throw exceptions on file errors. If a function does throw an exception,
|
||
then the function arguments used for return values will not have been
|
||
altered.
|
||
|
||
GeographicLib attempts to act sensibly with NaNs. NaNs in constructors
|
||
typically throw errors (an exception is GeodesicLine). However, calling
|
||
the class functions with NaNs as arguments is not an error; NaNs are
|
||
returned as appropriate. "INV" is treated as an invalid zone
|
||
designation by UTMUPS. "INVALID" is the corresponding invalid MGRS
|
||
string (and similarly for GARS, Geohash, and Georef strings). NaNs
|
||
allow the projection of polylines which are separated by NaNs; in this
|
||
format they can be easily plotted in MATLAB.
|
||
|
||
A note about portability. For the most part, the code uses standard C++
|
||
and should be able to be deployed on any system with a modern C++
|
||
compiler. System dependencies come into
|
||
- Math -- GeographicLib needs to define functions such
|
||
as atanh for systems that lack them. The system dependence will
|
||
disappear with the adoption of C++11 because the needed functions are
|
||
part of that standard.
|
||
- use of long double -- the type is used only for testing. On systems
|
||
which lack this data type the cmake and autoconf configuration
|
||
methods should detect its absence and omit the code that depends on
|
||
it.
|
||
- Geoid, GravityModel, and
|
||
MagneticModel -- these class uses system-dependent
|
||
default paths for looking up the respective datasets. It also relies
|
||
on getenv to find the value of the environment variables.
|
||
- Utility::readarray reads numerical data from binary
|
||
files. This assumes that floating point numbers are in IEEE format.
|
||
It attempts to handled the "endianness" of the target platform using
|
||
the GEOGRAPHICLIB_WORDS_BIGENDIAN macro (which sets the compile-time
|
||
constant Math::bigendian).
|
||
|
||
An attempt is made to maintain backward compatibility with GeographicLib
|
||
(especially at the level of your source code). Sometimes it's necessary
|
||
to take actions that depend on what version of GeographicLib is being
|
||
used; for example, you may want to use a new feature of GeographicLib,
|
||
but want your code still to work with older versions. In that case, you
|
||
can test the values of the macros `GEOGRAPHICLIB_VERSION_MAJOR`,
|
||
`GEOGRAPHICLIB_VERSION_MINOR`, and `GEOGRAPHICLIB_VERSION_PATCH`; these
|
||
expand to numbers (and the last one is usually 0); these macros appeared
|
||
starting in version 1.31. There's also a macro
|
||
`GEOGRAPHICLIB_VERSION_STRING` which expands to, e.g.,
|
||
"@PROJECT_VERSION@"; this macro has been defined since version 1.9.
|
||
Since version 1.37, there's also been a macro `GEOGRAPHICLIB_VERSION`
|
||
which encodes the version as a single number, e.g, 1003900. Do not rely
|
||
on this particular packing; instead use the macro
|
||
GEOGRAPHICLIB_VERSION_NUM(a,b,c) which allows you to compare versions
|
||
with, e.g.,
|
||
\code
|
||
#if GEOGRAPHICLIB_VERSION >= GEOGRAPHICLIB_VERSION_NUM(1,37,0)
|
||
...
|
||
#endif \endcode
|
||
|
||
<center>
|
||
Back to \ref utilities. Forward to \ref other. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page other GeographicLib in other languages
|
||
|
||
<center>
|
||
Back to \ref organization. Forward to \ref geoid. Up to \ref contents.
|
||
</center>
|
||
|
||
Jump to
|
||
- \ref implement.
|
||
- \ref wrappers.
|
||
- \ref maxima.
|
||
|
||
\section implement Implementations in other languages
|
||
|
||
Various subsets of GeographicLib have been implemented in other
|
||
languages:
|
||
[C](../../C/doc/index.html),
|
||
[Fortran](../../Fortran/doc/index.html),
|
||
[Python](../../Python/doc/index.html),
|
||
[Octave/MATLAB](https://github.com/geographiclib/geographiclib-octave#readme),
|
||
[Java](../../Java/doc/index.html), and
|
||
[JavaScript](../../JavaScript/doc/index.html).
|
||
These are described [here](../../doc/library.html#languages) on the main
|
||
[GeographicLib web page](../../index.html).
|
||
|
||
For the most part, these implementations focus on the geodesic
|
||
capabilities of GeographicLib, i.e., the classes Geodesic, GeodesicLine,
|
||
and PolygonAreaT. The exceptions are
|
||
- The [Java package GeographicLib-Java](
|
||
https://search.maven.org/artifact/net.sf.geographiclib/GeographicLib-Java)
|
||
includes an implementation of the Gnomonic projection
|
||
- The [Octave/MATLAB package
|
||
geographiclib](https://github.com/geographiclib/geographiclib-octave#readme)
|
||
also includes implementations of TransverseMercator,
|
||
PolarStereographic, AzimuthalEquidistant, CassiniSoldner, Gnomonic,
|
||
UTMUPS, MGRS, Geoid, Geocentric, LocalCartesian. In addition this
|
||
package includes calculations for \ref greatellipse.
|
||
|
||
\section wrappers Using wrappers to invoke GeographicLib
|
||
|
||
Alternatively, it is possible to call the C++ library directly from
|
||
certain other languages. Examples of this idiom are given in the
|
||
[`wrapper`](https://github.com/geographiclib/geographiclib/blob/main/wrapper)
|
||
directory in the source distribution.
|
||
|
||
- The C example in [`wrapper/c`](
|
||
https://github.com/geographiclib/geographiclib/blob/main/wrapper/c)
|
||
gives a small example, which converts heights above the geoid to
|
||
heights above the ellipsoid.
|
||
|
||
- For JavaScript, [`wrapper/javascript`](
|
||
https://github.com/geographiclib/geographiclib/blob/main/wrapper/javascript),
|
||
there is a minimal description of translating C++ source code to
|
||
JavaScript.
|
||
|
||
- The Python example in [`wrapper/python`](
|
||
https://github.com/geographiclib/geographiclib/blob/main/wrapper/python)
|
||
showns how to convert heights above the geoid to heights above the
|
||
ellipsoid using `boost-python`. An alternation is to use
|
||
[Cython](https::/cython.org).
|
||
|
||
- It is also possible to call the C++ version of GeographicLib directly
|
||
from Octave or MATLAB. The example in [`wrapper/octave`](
|
||
https://github.com/geographiclib/geographiclib/blob/main/wrapper/octave)
|
||
solves the inverse geodesic problem for ellipsoids with arbitrary
|
||
flattening.
|
||
|
||
- The Excel example in [`wrapper/excel`](
|
||
https://github.com/geographiclib/geographiclib/blob/main/wrapper/excel)
|
||
shows how to call the C++ library from Visual Basic which, in turn,
|
||
allows the functionality to be exposed in Excel. Here computations
|
||
involving geodesics and rhumb are illustrated. At present this works
|
||
only on Windows systems.
|
||
|
||
\section maxima Maxima routines
|
||
|
||
Maxima is a free computer algebra system which can be downloaded from
|
||
https://maxima.sourceforge.io. Maxima was used to generate the series used by
|
||
TransverseMercator (<a href="tmseries.mac"> tmseries.mac</a>), Geodesic
|
||
(<a href="geod.mac"> geod.mac</a>), Rhumb (<a href="rhumbarea.mac">
|
||
rhumbarea.mac</a>), \ref gearea (<a href="gearea.mac"> gearea.mac</a>),
|
||
the relation between \ref auxlat (<a href="auxlat.mac"> auxlat.mac</a>),
|
||
and to generate accurate data for testing (<a href="tm.mac"> tm.mac</a>
|
||
and <a href="geodesic.mac"> geodesic.mac</a>). The latter uses Maxima's
|
||
bigfloat arithmetic together with series extended to high order or
|
||
solutions in terms of elliptic integrals (<a href="ellint.mac">
|
||
ellint.mac</a>). These files contain brief instructions on how to use
|
||
them.
|
||
|
||
<center>
|
||
Back to \ref organization. Forward to \ref geoid. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page geoid Geoid height
|
||
|
||
<center>
|
||
Back to \ref other. Forward to \ref gravity. Up to \ref contents.
|
||
</center>
|
||
|
||
The gravitational equipotential surface approximately coinciding with
|
||
mean sea level is called the geoid. The Geoid class and
|
||
the <a href="GeoidEval.1.html">GeoidEval</a> utility evaluate the height
|
||
of the geoid above the WGS84 ellipsoid. This can be used to convert
|
||
heights above mean sea level to heights above the WGS84 ellipsoid.
|
||
Because the normal to the ellipsoid differs from the normal to the geoid
|
||
(the direction of a plumb line) there is a slight ambiguity in the
|
||
measurement of heights; however for heights up to 10 km this ambiguity
|
||
is only 1 mm.
|
||
|
||
The geoid is usually approximated by an "earth gravity model" (EGM).
|
||
The models published by the NGA are:
|
||
- <b>EGM84</b>:
|
||
https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm84
|
||
- <b>EGM96</b>:
|
||
https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm96
|
||
- <b>EGM2008</b>:
|
||
https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm2008
|
||
.
|
||
Geoid offers a uniform way to handle all 3 geoids models at a variety of
|
||
grid resolutions. (In contrast, the software tools that NGA offers are
|
||
different for each geoid model, and the interpolation programs are
|
||
different for each grid resolution. In addition these tools are written
|
||
in Fortran with is nowadays difficult to integrate with other software.)
|
||
|
||
The height of the geoid above the ellipsoid, \e N, is sometimes called
|
||
the geoid undulation. It can be used to convert a height above the
|
||
ellipsoid, \e h, to the corresponding height above the geoid (the
|
||
orthometric height, roughly the height above mean sea level), \e H,
|
||
using the relations
|
||
|
||
\e h = \e N + \e H; \e H = −\e N + \e h.
|
||
|
||
Unlike other components of GeographicLib, there is a appreciable error
|
||
in the results obtained (at best, the RMS error is 1 mm). However the
|
||
class provides methods to report the maximum and RMS errors in the
|
||
results. The class also returns the gradient of the geoid. This can be
|
||
used to estimate the direction of a plumb line relative to the WGS84
|
||
ellipsoid.
|
||
|
||
The GravityModel class calculates geoid heights using the
|
||
underlying gravity model. This is slower then Geoid but
|
||
considerably more accurate. This class also can accurately compute all
|
||
the components of the acceleration due to gravity (and hence the
|
||
direction of plumb line).
|
||
|
||
Go to
|
||
- \ref geoidinst
|
||
- \ref geoidformat
|
||
- \ref geoidinterp
|
||
- \ref geoidcache
|
||
- \ref testgeoid
|
||
|
||
\section geoidinst Installing the geoid datasets
|
||
|
||
The geoid heights are computed using interpolation into a rectangular
|
||
grid. The grids are read from data files which have been are computed
|
||
using the NGA synthesis programs in the case of the EGM84 and EGM96
|
||
models and using the NGA binary gridded data files in the case of
|
||
EGM2008. These data files are available for download:
|
||
<center>
|
||
<table>
|
||
<caption>Available geoid data files</caption>
|
||
<tr>
|
||
<th rowspan="2">name <th rowspan="2">geoid <th rowspan="2">grid
|
||
<th rowspan="2">size\n(MB)
|
||
<th colspan="3"><center>Download Links (size, MB)</center></th>
|
||
<tr>
|
||
<th>tar file</th>
|
||
<th>Windows\n installer</th>
|
||
<th>zip file</th>
|
||
<tr>
|
||
<td>egm84-30
|
||
<td>EGM84
|
||
<td><center>30'</center>
|
||
<td><center>0.6</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm84-30.tar.bz2">
|
||
link</a> (0.5)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm84-30.exe">
|
||
link</a> (0.8)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm84-30.zip">
|
||
link</a> (0.5)</center>
|
||
<tr>
|
||
<td>egm84-15
|
||
<td>EGM84
|
||
<td><center>15'</center>
|
||
<td><center>2.1</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm84-15.tar.bz2">
|
||
link</a> (1.5)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm84-15.exe">
|
||
link</a> (1.9)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm84-15.zip">
|
||
link</a> (2.0)</center>
|
||
<tr>
|
||
<td>egm96-15
|
||
<td>EGM96
|
||
<td><center>15'</center>
|
||
<td><center>2.1</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm96-15.tar.bz2">
|
||
link</a> (1.5)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm96-15.exe">
|
||
link</a> (1.9)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm96-15.zip">
|
||
link</a> (2.0)</center>
|
||
<tr>
|
||
<td>egm96-5
|
||
<td>EGM96
|
||
<td><center>5'</center>
|
||
<td><center> 19</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm96-5.tar.bz2">
|
||
link</a> (11)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm96-5.exe">
|
||
link</a> (11)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm96-5.zip">
|
||
link</a> (17)</center>
|
||
<tr>
|
||
<td>egm2008-5
|
||
<td>EGM2008
|
||
<td><center>5'</center>
|
||
<td><center> 19</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm2008-5.tar.bz2">
|
||
link</a> (11)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm2008-5.exe">
|
||
link</a> (11)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm2008-5.zip">
|
||
link</a> (17)</center>
|
||
<tr>
|
||
<td>egm2008-2_5
|
||
<td>EGM2008
|
||
<td><center>2.5'</center>
|
||
<td><center> 75</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm2008-2_5.tar.bz2">
|
||
link</a> (35)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm2008-2_5.exe">
|
||
link</a> (33)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm2008-2_5.zip">
|
||
link</a> (65)</center>
|
||
<tr>
|
||
<td>egm2008-1
|
||
<td>EGM2008
|
||
<td><center>1'</center>
|
||
<td><center>470</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm2008-1.tar.bz2">
|
||
link</a> (170)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm2008-1.exe">
|
||
link</a> (130)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/geoids-distrib/egm2008-1.zip">
|
||
link</a> (390)</center>
|
||
</table>
|
||
</center>
|
||
The "size" column is the size of the uncompressed data and it also
|
||
gives the memory requirements for caching the entire dataset using the
|
||
Geoid::CacheAll method.
|
||
At a minimum you should install egm96-5 and either egm2008-1 or
|
||
egm2008-2_5. Many applications use the EGM96 geoid, however the use of
|
||
EGM2008 is growing. (EGM84 is rarely used now.)
|
||
|
||
For Linux and Unix systems, GeographicLib provides a shell script
|
||
geographiclib-get-geoids (typically installed in /usr/local/sbin) which
|
||
automates the process of downloading and installing the geoid data. For
|
||
example
|
||
\verbatim
|
||
geographiclib-get-geoids best # to install egm84-15, egm96-5, egm2008-1
|
||
geographiclib-get-geoids -h # for help
|
||
\endverbatim
|
||
This script should be run as a user with write access to the
|
||
installation directory, which is typically
|
||
/usr/local/share/GeographicLib (this can be overridden with the -p
|
||
flag), and the data will then be placed in the "geoids" subdirectory.
|
||
|
||
Windows users should download and run the Windows installers. These
|
||
will prompt for an installation directory with the default being
|
||
\verbatim
|
||
C:/ProgramData/GeographicLib
|
||
\endverbatim
|
||
(which you probably should not change) and the data is installed in the
|
||
"geoids" sub-directory. (The second directory name is an alternate name
|
||
that Windows 7 uses for the "Application Data" directory.)
|
||
|
||
Otherwise download \e either the tar.bz2 file \e or the zip file (they
|
||
have the same contents). If possible use the tar.bz2 files, since these
|
||
are compressed about 2 times better than the zip file. To unpack these,
|
||
run, for example
|
||
\verbatim
|
||
mkdir -p /usr/local/share/GeographicLib
|
||
tar xofjC egm96-5.tar.bz2 /usr/local/share/GeographicLib
|
||
tar xofjC egm2008-2_5.tar.bz2 /usr/local/share/GeographicLib
|
||
etc.
|
||
\endverbatim
|
||
and, again, the data will be placed in the "geoids" subdirectory.
|
||
|
||
However you install the geoid data, all the datasets should
|
||
be installed in the same directory. Geoid and
|
||
<a href="GeoidEval.1.html">GeoidEval</a> uses a compile time default to
|
||
locate the datasets. This is
|
||
- /usr/local/share/GeographicLib/geoids, for non-Windows systems
|
||
- C:/ProgramData/GeographicLib/geoids, for Windows systems
|
||
.
|
||
consistent with the examples above. This may be overridden at run-time
|
||
by defining the GEOGRAPHICLIB_GEOID_PATH or the GEOGRAPHICLIB_DATA
|
||
environment variables; see Geoid::DefaultGeoidPath() for
|
||
details. Finally, the path may be set using the optional second
|
||
argument to the Geoid constructor or with the "-d" flag
|
||
to <a href="GeoidEval.1.html">GeoidEval</a>. Supplying the "-h" flag to
|
||
<a href="GeoidEval.1.html">GeoidEval</a> reports the default geoid path
|
||
for that utility. The "-v" flag causes GeoidEval to report the full
|
||
path name of the data file it uses.
|
||
|
||
\section geoidformat The format of the geoid data files
|
||
|
||
The gridded data used by the Geoid class is stored in
|
||
16-bit PGM files. Thus the data for egm96-5 might be stored in the file
|
||
- /usr/local/share/GeographicLib/geoids/egm96-5.pgm
|
||
.
|
||
PGM simple graphic format with the following properties
|
||
- it is well documented
|
||
<a href="http://netpbm.sourceforge.net/doc/pgm.html">here</a>;
|
||
- there are no separate "little-endian" and "big-endian" versions;
|
||
- it uses 1 or 2 bytes per pixel;
|
||
- pixels can be randomly accessed;
|
||
- comments can be added to the file header;
|
||
- it is sufficiently simple that it can be easily read without using the
|
||
<a href="http://netpbm.sourceforge.net/doc/libnetpbm.html">libnetpbm</a>
|
||
library (and thus we avoid adding a software dependency to
|
||
GeographicLib).
|
||
.
|
||
The major drawback of this format is that since there are only 65535
|
||
possible pixel values, the height must be quantized to 3 mm. However,
|
||
the resulting quantization error (up to 1.5 mm) is typically smaller
|
||
than the linear interpolation errors. The comments in the header for
|
||
egm96-5 are
|
||
\verbatim
|
||
# Geoid file in PGM format for the GeographicLib::Geoid class
|
||
# Description WGS84 EGM96, 5-minute grid
|
||
# URL https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm96
|
||
# DateTime 2009-08-29 18:45:03
|
||
# MaxBilinearError 0.140
|
||
# RMSBilinearError 0.005
|
||
# MaxCubicError 0.003
|
||
# RMSCubicError 0.001
|
||
# Offset -108
|
||
# Scale 0.003
|
||
# Origin 90N 0E
|
||
# AREA_OR_POINT Point
|
||
# Vertical_Datum WGS84
|
||
\endverbatim
|
||
Of these lines, the Scale and Offset lines are required and define the
|
||
conversion from pixel value to height (in meters) using \e height =
|
||
\e offset + \e scale \e pixel. The Geoid constructor also reads the
|
||
Description, DateTime, and error lines (if present) and stores the
|
||
resulting data so that it can be returned by
|
||
Geoid::Description, Geoid::DateTime,
|
||
Geoid::MaxError, and Geoid::RMSError
|
||
methods. The other lines serve as additional documentation but are not
|
||
used by this class. Accompanying egm96-5.pgm (and similarly with the
|
||
other geoid data files) are two files egm96-5.wld and
|
||
egm96-5.pgm.aux.xml. The first is an ESRI "world" file and the second
|
||
supplies complete projection metadata for use by
|
||
<a href="http://www.gdal.org">GDAL</a>. Neither of these files is read
|
||
by Geoid.
|
||
|
||
You can use gdal_translate to convert the data files to a standard
|
||
GeoTiff, e.g., with
|
||
\verbatim
|
||
gdal_translate -ot Float32 -scale 0 65000 -108 87 egm96-5.pgm egm96-5.tif
|
||
\endverbatim
|
||
The arguments to -scale here are specific to the Offset and Scale
|
||
parameters used in the pgm file (note 65000 * 0.003 − 108 = 87).
|
||
You can check these by running <a href="GeoidEval.1.html">GeoidEval</a>
|
||
with the "-v" option.
|
||
|
||
Here is a sample script which uses GDAL to create a 1-degree
|
||
squared grid of geoid heights at 3" resolution (matching DTED1) by
|
||
bilinear interpolation.
|
||
\verbatim
|
||
#! /bin/sh
|
||
lat=37
|
||
lon=067
|
||
res=3 # resolution in seconds
|
||
TEMP=`mktemp junkXXXXXXXXXX` # temporary file for GDAL
|
||
gdalwarp -q -te `echo $lon $lat $res | awk '{
|
||
lon = $1; lat = $2; res = $3;
|
||
printf "%.14f %.14f %.14f %.14f",
|
||
lon -0.5*res/3600, lat -0.5*res/3600,
|
||
lon+1+0.5*res/3600, lat+1+0.5*res/3600;
|
||
}'` -ts $((3600/res+1)) $((3600/res+1)) -r bilinear egm96-5.tif $TEMP
|
||
gdal_translate -quiet \
|
||
-mo AREA_OR_POINT=Point \
|
||
-mo Description="WGS84 EGM96, $res-second grid" \
|
||
-mo Vertical_Datum=WGS84 \
|
||
-mo Tie_Point_Location=pixel_corner \
|
||
$TEMP e$lon-n$lat.tif
|
||
rm -f $TEMP
|
||
\endverbatim
|
||
|
||
Because the pgm files are uncompressed, they can take up a lot of disk
|
||
space. Some compressed formats compress in tiles and so might be
|
||
compatible with the requirement that the data can be randomly accessed.
|
||
In particular gdal_translate can be used to convert the pgm files to
|
||
compressed tiff files with
|
||
\verbatim
|
||
gdal_translate -co COMPRESS=LZW -co PREDICTOR=2 -co TILED=YES \
|
||
–a_offset -108 -a_scale 0.003 \
|
||
egmyy-g.pgm egmyy-g.tif
|
||
\endverbatim
|
||
(The <code>-a_offset</code> and <code>-a_scale</code> options were
|
||
introduced in gdal_translate version 2.3.) The resulting files sizes
|
||
are
|
||
\verbatim
|
||
pgm tif
|
||
egm84-30 0.6 MB 0.5 MB
|
||
egm84-15 2.1 MB 1.4 MB
|
||
egm96-15 2.1 MB 1.5 MB
|
||
egm96-5 19 MB 8.5 MB
|
||
egm2008-5 19 MB 9.8 MB
|
||
egm2008-2_5 75 MB 28 MB
|
||
egm2008-1 470 MB 97 MB
|
||
\endverbatim
|
||
Currently, there are no plans for GeographicLib to support this
|
||
compressed format.
|
||
|
||
The Geoid class only handles world-wide geoid models. The pgm provides
|
||
geoid height postings on grid of points with uniform spacing in latitude
|
||
(row) and longitude (column). If the dimensions of the pgm file are
|
||
\e h × \e w, then latitude (resp. longitude) spacing is
|
||
−180°/(\e h − 1) (resp. 360°/\e w), with the (0,0)
|
||
pixel given the value at φ = 90°, λ = 0°. Models
|
||
covering a limited area will need to be "inserted" into a world-wide
|
||
grid before being accessible to the Geoid class.
|
||
|
||
\section geoidinterp Interpolating the geoid data
|
||
|
||
Geoid evaluates the geoid height using bilinear or cubic
|
||
interpolation.
|
||
|
||
The bilinear interpolation is based on the values at the 4 corners of
|
||
the enclosing cell. The interpolated height is a continuous function of
|
||
position; however the gradient has discontinuities are cell boundaries.
|
||
The quantization of the data files exacerbates the errors in the
|
||
gradients.
|
||
|
||
The cubic interpolation is a least-squares fit to the values on a
|
||
12-point stencil with weights as follows:
|
||
\verbatim
|
||
. 1 1 .
|
||
1 2 2 1
|
||
1 2 2 1
|
||
. 1 1 .
|
||
\endverbatim
|
||
The cubic is constrained to be independent of longitude when evaluating
|
||
the height at one of the poles. Cubic interpolation is considerably
|
||
more accurate than bilinear interpolation; however, in this
|
||
implementation there are small discontinuities in the heights are cell
|
||
boundaries. The over-constrained cubic fit slightly reduces the
|
||
quantization errors on average.
|
||
|
||
The algorithm for the least squares fit is taken from, F. H. Lesh,
|
||
<a href="https://doi.org/10.1145/368424.368443">Multi-dimensional
|
||
least-squares polynomial curve fitting</a>, CACM 2, 29--30 (1959).
|
||
This algorithm is not part of Geoid; instead it is implemented as
|
||
<a href="https://en.wikipedia.org/wiki/Maxima_(software)">Maxima</a>
|
||
code which is used to precompute the matrices to convert the function
|
||
values on the stencil into the coefficients from the cubic polynomial.
|
||
This code is included as a comment in Geoid.cpp.
|
||
|
||
The interpolation methods are quick and give good accuracy. Here is a
|
||
summary of the combined quantization and interpolation errors for the
|
||
heights.
|
||
<center><table>
|
||
<caption>Interpolation and quantization errors for geoid heights</caption>
|
||
<tr>
|
||
<th rowspan="2">name
|
||
<th rowspan="2">geoid
|
||
<th rowspan="2">grid
|
||
<th colspan="2"><center>bilinear error</center></th>
|
||
<th colspan="2"><center>cubic error</center></th>
|
||
<tr>
|
||
<th><center>max</center><th><center>rms</center>
|
||
<th><center>max</center><th><center>rms</center>
|
||
<tr>
|
||
<td>egm84-30 <td>EGM84 <td><center>30' </center>
|
||
<td><center>1.546 m</center><td><center>70 mm</center>
|
||
<td><center>0.274 m</center><td><center>14 mm</center>
|
||
<tr>
|
||
<td>egm84-15 <td>EGM84 <td><center>15' </center>
|
||
<td><center>0.413 m</center><td><center>18 mm</center>
|
||
<td><center>0.021 m</center><td><center>1.2 mm</center>
|
||
<tr>
|
||
<td>egm96-15 <td>EGM96 <td><center>15' </center>
|
||
<td><center>1.152 m</center><td><center>40 mm</center>
|
||
<td><center>0.169 m</center><td><center>7.0 mm</center>
|
||
<tr>
|
||
<td>egm96-5 <td>EGM96 <td><center> 5' </center>
|
||
<td><center>0.140 m</center><td><center>4.6 mm</center>
|
||
<td><center>0.0032 m</center><td><center>0.7 mm</center>
|
||
<tr>
|
||
<td>egm2008-5 <td>EGM2008<td><center> 5' </center>
|
||
<td><center>0.478 m</center><td><center>12 mm</center>
|
||
<td><center>0.294 m</center><td><center>4.5 mm</center>
|
||
<tr>
|
||
<td>egm2008-2_5<td>EGM2008<td><center> 2.5'</center>
|
||
<td><center>0.135 m</center><td><center>3.2 mm</center>
|
||
<td><center>0.031 m</center><td><center>0.8 mm</center>
|
||
<tr>
|
||
<td>egm2008-1 <td>EGM2008<td><center> 1' </center>
|
||
<td><center>0.025 m</center><td><center>0.8 mm</center>
|
||
<td><center>0.0022 m</center><td><center>0.7 mm</center>
|
||
</table></center>
|
||
The errors are with respect to the specific NGA earth gravity model
|
||
(not to any "real" geoid). The RMS values are obtained using 5 million
|
||
uniformly distributed random points. The maximum values are obtained by
|
||
evaluating the errors using a different grid with points at the
|
||
centers of the original grid. (The RMS difference between EGM96 and
|
||
EGM2008 is about 0.5 m. The RMS difference between EGM84 and EGM96 is
|
||
about 1.5 m.)
|
||
|
||
The errors in the table above include the quantization errors that arise
|
||
because the height data that Geoid uses are quantized to
|
||
3 mm. If, instead, Geoid were to use data files without
|
||
such quantization artifacts, the overall error would be reduced <i>but
|
||
only modestly</i> as shown in the following table, where only the
|
||
changed rows are included and where the changed entries are given in
|
||
bold:
|
||
<center><table>
|
||
<caption>Interpolation (only!) errors for geoid heights</caption>
|
||
<tr>
|
||
<th rowspan="2">name
|
||
<th rowspan="2">geoid
|
||
<th rowspan="2">grid
|
||
<th colspan="2"><center>bilinear error</center></th>
|
||
<th colspan="2"><center>cubic error</center></th>
|
||
<tr>
|
||
<th><center>max</center><th><center>rms</center>
|
||
<th><center>max</center><th><center>rms</center>
|
||
<tr>
|
||
<td>egm96-5 <td>EGM96 <td><center> 5' </center>
|
||
<td><center>0.140 m</center><td><center>4.6 mm</center>
|
||
<td><center><b>0.0026 m</b></center><td><center><b>0.1 mm</b></center>
|
||
<tr>
|
||
<td>egm2008-2_5<td>EGM2008<td><center> 2.5'</center>
|
||
<td><center>0.135 m</center><td><center>3.2 mm</center>
|
||
<td><center>0.031 m</center><td><center><b>0.4 mm</b></center>
|
||
<tr>
|
||
<td>egm2008-1 <td>EGM2008<td><center> 1' </center>
|
||
<td><center>0.025 m</center><td><center><b>0.6 mm</b></center>
|
||
<td><center><b>0.0010 m</b></center><td><center><b>0.011 mm</b></center>
|
||
</table></center>
|
||
|
||
\section geoidcache Caching the geoid data
|
||
|
||
A simple way of calling Geoid is as follows
|
||
\code
|
||
#include <GeographicLib/Geoid.hpp>
|
||
#include <iostream>
|
||
...
|
||
GeographicLib::Geoid g("egm96-5");
|
||
double lat, lon;
|
||
while (std::cin >> lat >> lon)
|
||
std::cout << g(lat, lon) << "\n";
|
||
...
|
||
\endcode
|
||
|
||
The first call to g(lat, lon) causes the data for the stencil points (4
|
||
points for bilinear interpolation and 12 for cubic interpolation) to be
|
||
read and the interpolated value returned. A simple 0th-order caching
|
||
scheme is provided by default, so that, if the second and subsequent
|
||
points falls within the same grid cell, the data values are not reread
|
||
from the file. This is adequate for most interactive use and also
|
||
minimizes disk accesses for the case when a continuous track is being
|
||
followed.
|
||
|
||
If a large quantity of geoid calculations are needed, the calculation
|
||
can be sped up by preloading the data for a rectangular block with
|
||
Geoid::CacheArea or the entire dataset with
|
||
Geoid::CacheAll. If the requested points lie within the
|
||
cached area, the cached data values are used; otherwise the data is read
|
||
from disk as before. Caching all the data is a reasonable choice for
|
||
the 5' grids and coarser. Caching all the data for the 1' grid will
|
||
require 0.5 GB of RAM and should only be used on systems with sufficient
|
||
memory.
|
||
|
||
The use of caching does not affect the values returned. Because of the
|
||
caching and the random file access, this class is \e not normally thread
|
||
safe; i.e., a single instantiation cannot be safely used by multiple
|
||
threads. If multiple threads need to calculate geoid heights, there are
|
||
two alternatives:
|
||
- they should all construct thread-local instantiations.
|
||
- Geoid should be constructed with \e threadsafe = true.
|
||
This causes all the data to be read at the time of construction (and
|
||
if this fails, an exception is thrown), the data file to be closed
|
||
and the single-cell caching to be turned off. The resulting object
|
||
may then be shared safely between threads.
|
||
|
||
\section testgeoid Test data for geoids
|
||
|
||
A test set for the geoid models is available at
|
||
- <a href="https://sourceforge.net/projects/geographiclib/files/testdata/GeoidHeights.dat.gz">
|
||
GeoidHeights.dat.gz</a>
|
||
.
|
||
This is about 11 MB (compressed). This test set consists of a set of
|
||
500000 geographic coordinates together with the corresponding geoid
|
||
heights according to various earth gravity models.
|
||
|
||
Each line of the test set gives 5 space delimited numbers
|
||
- latitude (degrees, exact)
|
||
- longitude (degrees, exact)
|
||
- EGM84 height (meters, accurate to 1 μm)
|
||
- EGM96 height (meters, accurate to 1 μm)
|
||
- EGM2008 height (meters, accurate to 1 μm)
|
||
.
|
||
The latitude and longitude are all multiples of 10<sup>−6</sup>
|
||
deg and should be regarded as exact. The geoid heights are computed
|
||
using the harmonic NGA synthesis programs, where the programs were
|
||
compiled (with gfortran) and run under Linux. In the case of the
|
||
EGM2008 program, a <code>SAVE</code> statement needed to be added to
|
||
subroutine <code>latf</code>, in order for the program to compile
|
||
correctly with a stack-based compiler. Similarly the EGM96 code
|
||
requires a <code>SAVE</code> statement in subroutine
|
||
<code>legfdn</code>.
|
||
|
||
<center>
|
||
Back to \ref other. Forward to \ref gravity. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page gravity Gravity models
|
||
|
||
<center>
|
||
Back to \ref geoid. Forward to \ref normalgravity. Up to \ref contents.
|
||
</center>
|
||
|
||
GeographicLib can compute the earth's gravitational field with an earth
|
||
gravity model using the GravityModel and GravityCircle classes and with
|
||
the <a href="Gravity.1.html">Gravity</a> utility. These models expand
|
||
the gravitational potential of the earth as sum of spherical harmonics.
|
||
The models also specify a reference ellipsoid, relative to which geoid
|
||
heights and gravity disturbances are measured. Underlying all these
|
||
models is <i>normal gravity</i> which is the exact solution for an
|
||
idealized rotating ellipsoidal body. This is implemented with the
|
||
NormalGravity class and some notes on are provided in section \ref
|
||
normalgravity
|
||
|
||
Go to
|
||
- \ref gravityinst
|
||
- \ref gravityformat
|
||
- \ref gravitynga
|
||
- \ref gravitygeoid
|
||
- \ref gravityatmos
|
||
- \ref gravityparallel
|
||
- \ref normalgravity (now on its own page)
|
||
|
||
The supported models are
|
||
- <b>egm84</b>, the
|
||
<a href="https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm84">
|
||
Earth Gravity Model 1984</a>, which includes terms up to degree 180.
|
||
- <b>egm96</b>, the
|
||
<a href="https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm96">
|
||
Earth Gravity Model 1996</a>, which includes terms up to degree 360.
|
||
- <b>egm2008</b>, the
|
||
<a href="https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm2008">
|
||
Earth Gravity Model 2008</a>, which includes terms up to degree 2190.
|
||
See also <a href="https://doi.org/10.1029/2011JB008916"> Pavlis et
|
||
al. (2012)</a>
|
||
- <b>wgs84</b>, the
|
||
<a href="https://web.archive.org/web/20161214054445/http://earth-info.nga.mil/GandG/publications/tr8350.2/tr8350_2.html">
|
||
WGS84 Reference Ellipsoid</a>. This is just reproduces the normal
|
||
gravitational field for the reference ellipsoid. This includes the
|
||
zonal coefficients up to order 20. Usually NormalGravity::WGS84()
|
||
should be used instead.
|
||
- <b>grs80</b>, the
|
||
GRS80 Reference Ellipsoid. This is just reproduces the normal
|
||
gravitational field for the GRS80 ellipsoid. This includes the
|
||
zonal coefficients up to order 20. Usually NormalGravity::GRS80()
|
||
should be used instead.
|
||
|
||
See
|
||
- W. A. Heiskanen and H. Moritz, Physical Geodesy (Freeman, San
|
||
Francisco, 1967).
|
||
.
|
||
for more information.
|
||
|
||
<b>Acknowledgment:</b> I would like to thank Mathieu Peyréga for
|
||
sharing EGM_Geoid_CalculatorClass from his Geo library with me. His
|
||
implementation was the first I could easily understand and he and I
|
||
together worked through some of the issues with overflow and underflow
|
||
the occur while performing high-degree spherical harmonic sums.
|
||
|
||
\section gravityinst Installing the gravity models
|
||
|
||
These gravity models are available for download:
|
||
<center>
|
||
<table>
|
||
<caption>Available gravity models</caption>
|
||
<tr>
|
||
<th rowspan="2">name <th rowspan="2">max\n degree
|
||
<th rowspan="2">size\n(kB)
|
||
<th colspan="3"><center>Download Links (size, kB)</center></th>
|
||
<tr>
|
||
<th>tar file</th>
|
||
<th>Windows\n installer</th>
|
||
<th>zip file</th>
|
||
<tr>
|
||
<td>egm84
|
||
<td><center>180</center>
|
||
<td><center>27</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/egm84.tar.bz2">
|
||
link</a> (26)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/egm84.exe">
|
||
link</a> (55)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/egm84.zip">
|
||
link</a> (26)</center>
|
||
<tr>
|
||
<td>egm96
|
||
<td><center>360</center>
|
||
<td><center>2100</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/egm96.tar.bz2">
|
||
link</a> (2100)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/egm96.exe">
|
||
link</a> (2300)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/egm96.zip">
|
||
link</a> (2100)</center>
|
||
<tr>
|
||
<td>egm2008
|
||
<td><center>2190</center>
|
||
<td><center>76000</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/egm2008.tar.bz2">
|
||
link</a> (75000)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/egm2008.exe">
|
||
link</a> (72000)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/egm2008.zip">
|
||
link</a> (73000)</center>
|
||
<tr>
|
||
<td>wgs84
|
||
<td><center>20</center>
|
||
<td><center>1</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/wgs84.tar.bz2">
|
||
link</a> (1)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/wgs84.exe">
|
||
link</a> (30)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/gravity-distrib/wgs84.zip">
|
||
link</a> (1)</center>
|
||
</table>
|
||
</center>
|
||
The "size" column is the size of the uncompressed data.
|
||
|
||
For Linux and Unix systems, GeographicLib provides a shell script
|
||
geographiclib-get-gravity (typically installed in /usr/local/sbin)
|
||
which automates the process of downloading and installing the gravity
|
||
models. For example
|
||
\verbatim
|
||
geographiclib-get-gravity all # to install egm84, egm96, egm2008, wgs84
|
||
geographiclib-get-gravity -h # for help
|
||
\endverbatim
|
||
This script should be run as a user with write access to the
|
||
installation directory, which is typically
|
||
/usr/local/share/GeographicLib (this can be overridden with the -p
|
||
flag), and the data will then be placed in the "gravity" subdirectory.
|
||
|
||
Windows users should download and run the Windows installers. These
|
||
will prompt for an installation directory with the default being
|
||
\verbatim
|
||
C:/ProgramData/GeographicLib
|
||
\endverbatim
|
||
(which you probably should not change) and the data is installed in the
|
||
"gravity" sub-directory. (The second directory name is an alternate name
|
||
that Windows 7 uses for the "Application Data" directory.)
|
||
|
||
Otherwise download \e either the tar.bz2 file \e or the zip file (they
|
||
have the same contents). To unpack these, run, for example
|
||
\verbatim
|
||
mkdir -p /usr/local/share/GeographicLib
|
||
tar xofjC egm96.tar.bz2 /usr/local/share/GeographicLib
|
||
tar xofjC egm2008.tar.bz2 /usr/local/share/GeographicLib
|
||
etc.
|
||
\endverbatim
|
||
and, again, the data will be placed in the "gravity" subdirectory.
|
||
|
||
However you install the gravity models, all the datasets should be
|
||
installed in the same directory. GravityModel and
|
||
<a href="Gravity.1.html">Gravity</a> uses a compile time default to
|
||
locate the datasets. This is
|
||
- /usr/local/share/GeographicLib/gravity, for non-Windows systems
|
||
- C:/ProgramData/GeographicLib/gravity, for Windows systems
|
||
.
|
||
consistent with the examples above. This may be overridden at run-time
|
||
by defining the GEOGRAPHICLIB_GRAVITY_PATH or the GEOGRAPHICLIB_DATA
|
||
environment variables; see
|
||
GravityModel::DefaultGravityPath() for details. Finally,
|
||
the path may be set using the optional second argument to the
|
||
GravityModel constructor or with the "-d" flag to
|
||
<a href="Gravity.1.html">Gravity</a>. Supplying the "-h" flag to
|
||
<a href="Gravity.1.html">Gravity</a> reports the default path for
|
||
gravity models for that utility. The "-v" flag causes Gravity to report
|
||
the full path name of the data file it uses.
|
||
|
||
\section gravityformat The format of the gravity model files
|
||
|
||
The constructor for GravityModel reads a file called
|
||
NAME.egm which specifies various properties for the gravity model. It
|
||
then opens a binary file NAME.egm.cof to obtain the coefficients of the
|
||
spherical harmonic sum.
|
||
|
||
The first line of the .egm file must consist of "EGMF-v" where EGMF
|
||
stands for "Earth Gravity Model Format" and v is the version number of
|
||
the format (currently "1").
|
||
|
||
The rest of the File is read a line at a time. A # character and
|
||
everything after it are discarded. If the result is just white space it
|
||
is discarded. The remaining lines are of the form "KEY WHITESPACE
|
||
VALUE". In general, the KEY and the VALUE are case-sensitive.
|
||
|
||
GravityModel only pays attention to the following
|
||
keywords
|
||
- keywords that affect the field calculation, namely:
|
||
- <b>ModelRadius</b> (required), the normalizing radius for the model
|
||
in meters.
|
||
- <b>ReferenceRadius</b> (required), the equatorial radius \e a for
|
||
the reference ellipsoid meters.
|
||
- <b>ModelMass</b> (required), the mass constant \e GM for the model
|
||
in meters<sup>3</sup>/seconds<sup>2</sup>.
|
||
- <b>ReferenceMass</b> (required), the mass constant \e GM for the
|
||
reference ellipsoid in meters<sup>3</sup>/seconds<sup>2</sup>.
|
||
- <b>AngularVelocity</b> (required), the angular velocity ω for
|
||
the model \e and the reference ellipsoid in rad
|
||
seconds<sup>−1</sup>.
|
||
- <b>Flattening</b>, the flattening of the reference ellipsoid; this
|
||
can be given a fraction, e.g., 1/298.257223563. One of
|
||
<b>Flattening</b> and <b>DynamicalFormFactor</b> is required.
|
||
- <b>DynamicalFormFactor</b>, the dynamical form factor
|
||
<i>J</i><sub>2</sub> for the reference ellipsoid. One of
|
||
<b>Flattening</b> and <b>DynamicalFormFactor</b> is required.
|
||
- <b>HeightOffset</b> (default 0), the constant height offset
|
||
(meters) added to obtain the geoid height.
|
||
- <b>CorrectionMultiplier</b> (default 1), the multiplier for the
|
||
"zeta-to-N" correction terms for the geoid height to convert them
|
||
to meters.
|
||
- <b>Normalization</b> (default full), the normalization used for the
|
||
associated Legendre functions (full or schmidt).
|
||
- <b>ID</b> (required), 8 printable characters which serve as a
|
||
signature for the .egm.cof file (they must appear as the first 8
|
||
bytes of this file).
|
||
.
|
||
The parameters <b>ModelRadius</b>, <b>ModelMass</b>, and
|
||
<b>AngularVelocity</b> apply to the gravity model, while
|
||
<b>ReferenceRadius</b>, <b>ReferenceMass</b>, <b>AngularVelocity</b>,
|
||
and either <b>Flattening</b> or <b>DynamicalFormFactor</b>
|
||
characterize the reference ellipsoid. <b>AngularVelocity</b>
|
||
(because it can be measured precisely) is the same for the gravity
|
||
model and the reference ellipsoid. <b>ModelRadius</b> is merely a
|
||
scaling parameter for the gravity model and there's no requirement
|
||
that it be close to the equatorial radius of the earth (although
|
||
that's typically how it is chosen). <b>ModelMass</b> and
|
||
<b>ReferenceMass</b> need not be the same and, indeed, they are
|
||
slightly difference for egm2008. As a result the disturbing
|
||
potential \e T has a 1/\e r dependence at large distances.
|
||
- keywords that store data that the user can query:
|
||
- <b>Name</b>, the name of the model.
|
||
- <b>Description</b>, a more descriptive name of the model.
|
||
- <b>ReleaseDate</b>, when the model was created.
|
||
- keywords that are examined to verify that their values are valid:
|
||
- <b>ByteOrder</b> (default little), the order of bytes in the
|
||
.egm.cof file. Only little endian is supported at present.
|
||
.
|
||
Other keywords are ignored.
|
||
|
||
The coefficient file NAME.egm.cof is a binary file in little endian
|
||
order. The first 8 bytes of this file must match the ID given in
|
||
NAME.egm. This is followed by 2 sets of spherical harmonic
|
||
coefficients. The first of these gives the gravity potential and the
|
||
second gives the zeta-to-N corrections to the geoid height. The format
|
||
for each set of coefficients is:
|
||
- \e N, the maximum degree of the sum stored as a 4-byte signed integer.
|
||
This must satisfy \e N ≥ −1.
|
||
- \e M, the maximum order of the sum stored as a 4-byte signed integer.
|
||
This must satisfy \e N ≥ \e M ≥ −1.
|
||
- <i>C</i><sub><i>nm</i></sub>, the coefficients of the cosine
|
||
coefficients of the sum in column (i.e., \e m) major order. There
|
||
are (\e M + 1) (2\e N - \e M + 2) / 2 elements which are stored as
|
||
IEEE doubles (8 bytes). For example for \e N = \e M = 3, there are
|
||
10 coefficients arranged as
|
||
<i>C</i><sub>00</sub>,
|
||
<i>C</i><sub>10</sub>,
|
||
<i>C</i><sub>20</sub>,
|
||
<i>C</i><sub>30</sub>,
|
||
<i>C</i><sub>11</sub>,
|
||
<i>C</i><sub>21</sub>,
|
||
<i>C</i><sub>31</sub>,
|
||
<i>C</i><sub>22</sub>,
|
||
<i>C</i><sub>32</sub>,
|
||
<i>C</i><sub>33</sub>.
|
||
- <i>S</i><sub><i>nm</i></sub>, the coefficients of the sine
|
||
coefficients of the sum in column (i.e., \e m) major order starting
|
||
at \e m = 1. There are \e M (2\e N - \e M + 1) / 2 elements which
|
||
are stored as IEEE doubles (8 bytes). For example for \e N = \e M =
|
||
3, there are 6 coefficients arranged as
|
||
<i>S</i><sub>11</sub>,
|
||
<i>S</i><sub>21</sub>,
|
||
<i>S</i><sub>31</sub>,
|
||
<i>S</i><sub>22</sub>,
|
||
<i>S</i><sub>32</sub>,
|
||
<i>S</i><sub>33</sub>.
|
||
.
|
||
Although the coefficient file is in little endian order, GeographicLib
|
||
can read it on big endian machines. It can only be read on machines
|
||
which store doubles in IEEE format.
|
||
|
||
As an illustration, here is egm2008.egm:
|
||
\verbatim
|
||
EGMF-1
|
||
# An Earth Gravity Model (Format 1) file. For documentation on the
|
||
# format of this file see
|
||
# https://geographiclib.sourceforge.io/C++/doc/gravity.html#gravityformat
|
||
Name egm2008
|
||
Publisher National Geospatial Intelligence Agency
|
||
Description Earth Gravity Model 2008
|
||
URL https://earth-info.nga.mil/index.php?dir=wgs84&action=wgs84#tab_egm2008
|
||
ReleaseDate 2008-06-01
|
||
ConversionDate 2011-11-19
|
||
DataVersion 1
|
||
ModelRadius 6378136.3
|
||
ModelMass 3986004.415e8
|
||
AngularVelocity 7292115e-11
|
||
ReferenceRadius 6378137
|
||
ReferenceMass 3986004.418e8
|
||
Flattening 1/298.257223563
|
||
HeightOffset -0.41
|
||
|
||
# Gravitational and correction coefficients taken from
|
||
# EGM2008_to2190_TideFree and Zeta-to-N_to2160_egm2008 from
|
||
# the egm2008 distribution.
|
||
ID EGM2008A
|
||
\endverbatim
|
||
|
||
The code to produce the coefficient files for the wgs84 and grs80 models
|
||
is
|
||
\include make-egmcof.cpp
|
||
|
||
\section gravitynga Comments on the NGA harmonic synthesis code
|
||
|
||
GravityModel attempts to reproduce the results of NGA's
|
||
harmonic synthesis code for EGM2008, hsynth_WGS84.f. Listed here are
|
||
issues that I encountered using the NGA code:
|
||
-# A compiler which allocates local variables on the stack produces an
|
||
executable with just returns NaNs. The problem here is a missing
|
||
<code>SAVE</code> statement in subroutine <code>latf</code>.
|
||
-# Because the model and references masses for egm2008 differ (by about
|
||
1 part in 10<sup>9</sup>), there should be a 1/\e r contribution to
|
||
the disturbing potential \e T. However, this term is set to zero in
|
||
hsynth_WGS84 (effectively altering the normal potential). This
|
||
shifts the surface \e W = <i>U</i><sub>0</sub> outward by about
|
||
5 mm. Note too that the reference ellipsoid is no longer a
|
||
level surface of the effective normal potential.
|
||
-# Subroutine <code>radgrav</code> computes the ellipsoidal coordinate
|
||
β incorrectly. This leads to small errors in the deflection
|
||
of the vertical, ξ and η, when the height above the
|
||
ellipsoid, \e h, is non-zero (about 10<sup>−7</sup> arcsec at
|
||
\e h = 400 km).
|
||
-# There are several expressions which will return inaccurate results
|
||
due to cancellation. For example, subroutine <code>grs</code>
|
||
computes the flattening using \e f = 1 − sqrt(1 −
|
||
<i>e</i><sup>2</sup>). Much better is to use \e f =
|
||
<i>e</i><sup>2</sup>/(1 + sqrt(1 − <i>e</i><sup>2</sup>)). The
|
||
expressions for \e q and \e q' in <code>grs</code> and
|
||
<code>radgrav</code> suffer from similar problems. The resulting
|
||
errors are tiny (about 50 pm in the geoid height); however, given
|
||
that's there's essentially no cost to using more accurate
|
||
expressions, it's preferable to do so.
|
||
-# hsynth_WGS84 returns an "undefined" value for \e xi and \e eta at the
|
||
poles. Better would be to return the value obtained by taking the
|
||
limit \e lat → ± 90°.
|
||
.
|
||
Issues 1--4 have been reported to the authors of hsynth_WGS84.
|
||
Issue 1 is peculiar to Fortran and is not encountered in C++ code and
|
||
GravityModel corrects issues 3--5. On issue 2,
|
||
GravityModel neglects the 1/\e r term in \e T in
|
||
GravityModel::GeoidHeight and
|
||
GravityModel::SphericalAnomaly in order to produce
|
||
results which match NGA's for these quantities. On the other hand,
|
||
GravityModel::Disturbance and
|
||
GravityModel::T <i>do</i> include this term.
|
||
|
||
\section gravitygeoid Details of the geoid height and anomaly calculations
|
||
|
||
Ideally, the geoid represents a surface of constant gravitational
|
||
potential which approximates mean sea level. In reality some
|
||
approximations are taken in determining this surface. The steps taking
|
||
by GravityModel in computing the geoid height are
|
||
described here (in the context of EGM2008). This mimics NGA's code
|
||
hsynth_WGS84 closely because most users of EGM2008 use the gridded data
|
||
generated by this code (e.g., Geoid) and it is desirable
|
||
to use a consistent definition of the geoid height.
|
||
- The model potential is band limited; the minimum wavelength that is
|
||
represented is 360°/2160 = 10' (i.e., about 10NM or
|
||
18.5km). The maximum degree for the spherical harmonic sum is 2190;
|
||
however the model was derived using ellipsoidal harmonics of degree
|
||
and order 2160 and the degree was increased to 2190 in order to
|
||
capture the ellipsoidal harmonics faithfully with spherical
|
||
harmonics.
|
||
- The 1/\e r term is omitted from the \e T (this is issue 2 in \ref
|
||
gravitynga). This moves the equipotential surface by about 5mm.
|
||
- The surface \e W = <i>U</i><sub>0</sub> is determined by Bruns'
|
||
formula, which is roughly equivalent to a single iteration of
|
||
Newton's method. The RMS error in this approximation is about 1.5mm
|
||
with a maximum error of about 10 mm.
|
||
- The model potential is only valid above the earth's surface. A
|
||
correction therefore needs to be included where the geoid lies
|
||
beneath the terrain. This is NGA's "zeta-to-N" correction, which is
|
||
represented by a spherical harmonic sum of degree and order 2160 (and
|
||
so it misses short wavelength terrain variations). In addition, it
|
||
entails estimating the isostatic equilibrium of the earth's crust.
|
||
The correction lies in the range [−5.05 m, 0.05 m],
|
||
however for 99.9% of the earth's surface the correction is less than
|
||
10 mm in magnitude.
|
||
- The resulting surface lies above the observed mean sea level,
|
||
so −0.41m is added to the geoid height. (Better would be to change
|
||
the potential used to define the geoid; but this would only change
|
||
the result by about 2mm.)
|
||
.
|
||
A useful discussion of the problems with defining a geoid is given by
|
||
Dru A. Smith in
|
||
<a href="https://www.ngs.noaa.gov/PUBS_LIB/EGM96_GEOID_PAPER/egm96_geoid_paper.html">
|
||
There is no such thing as "The" EGM96 geoid: Subtle points on the use of
|
||
a global geopotential model</a>, IGeS Bulletin No. 8, International
|
||
Geoid Service, Milan, Italy, pp. 17--28 (1998).
|
||
|
||
GravityModel::GeoidHeight reproduces the results of the
|
||
several NGA codes for harmonic synthesis with the following maximum
|
||
discrepancies:
|
||
- egm84 = 1.1mm. This is probably due to inconsistent parameters for the
|
||
reference ellipsoid in the NGA code. (In particular, the value of
|
||
mass constant excludes the atmosphere; however, it's not clear
|
||
whether the other parameters have been correspondingly adjusted.)
|
||
Note that geoid heights predicted by egm84 differ from those of more
|
||
recent gravity models by about 1 meter.
|
||
- egm96 = 23nm.
|
||
- egm2008 = 78pm. After addressing some of the issues alluded to in
|
||
issue 4 in \ref gravitynga, the maximum discrepancy becomes 23pm.
|
||
|
||
The formula for the gravity anomaly vector involves computing gravity
|
||
and normal gravity at two different points (with the displacement
|
||
between the points unknown <i>ab initio</i>). Since the gravity anomaly
|
||
is already a small quantity it is sometimes acceptable to employ
|
||
approximations that change the quantities by \e O(\e f). The NGA code
|
||
uses the spherical approximation described by Heiskanen and Moritz,
|
||
Sec. 2-14 and GravityModel::SphericalAnomaly uses the
|
||
same approximation for compatibility. In this approximation, the
|
||
gravity disturbance <b>delta</b> = <b>grad</b> \e T is calculated.
|
||
Here, \e T once again excludes the 1/\e r term (this is issue 2 in \ref
|
||
gravitynga and is consistent with the computation of the geoid height).
|
||
Note that <b>delta</b> compares the gravity and the normal gravity at
|
||
the \e same point; the gravity anomaly vector is then found by
|
||
estimating the gradient of the normal gravity in the limit that the
|
||
earth is spherically symmetric. <b>delta</b> is expressed in \e
|
||
spherical coordinates as \e deltax, \e deltay, \e deltaz where, for
|
||
example, \e deltaz is the \e radial component of <b>delta</b> (not the
|
||
component perpendicular to the ellipsoid) and \e deltay is similarly
|
||
slightly different from the usual northerly component. The components
|
||
of the anomaly are then given by
|
||
- gravity anomaly, \e Dg01 = \e deltaz − 2<i>T</i>/\e R, where \e R
|
||
distance to the center of the earth;
|
||
- northerly component of the deflection of the vertical, \e xi = −
|
||
<i>deltay</i>/\e gamma, where \e gamma is the magnitude of the normal
|
||
gravity;
|
||
- easterly component of the deflection of the vertical, \e eta = −
|
||
<i>deltax</i>/\e gamma.
|
||
.
|
||
NormalGravity computes the normal gravity accurately and
|
||
avoids issue 3 of \ref gravitynga. Thus while
|
||
GravityModel::SphericalAnomaly reproduces the results for
|
||
\e xi and \e eta at \e h = 0, there is a slight discrepancy if \e h is
|
||
non-zero.
|
||
|
||
\section gravityatmos The effect of the mass of the atmosphere
|
||
|
||
All of the supported models use WGS84 for the reference ellipsoid. This
|
||
has (see
|
||
<a href="https://web.archive.org/web/20161214054445/https://earth-info.nga.mil/GandG/publications/tr8350.2/wgs84fin.pdf">
|
||
TR8350.2</a>, table 3.1)
|
||
- \e a = 6378137 m
|
||
- \e f = 1/298.257223563
|
||
- ω = 7292115 × 10<sup>−11</sup> rad
|
||
s<sup>−1</sup>
|
||
- \e GM = 3986004.418 × 10<sup>8</sup> m<sup>3</sup>
|
||
s<sup>−2</sup>.
|
||
.
|
||
The value of \e GM includes the mass of the atmosphere and so strictly
|
||
only applies above the earth's atmosphere. Near the surface of the
|
||
earth, the value of \e g will be less (in absolute value) than the value
|
||
predicted by these models by about δ\e g = (4π<i>G</i>/\e
|
||
g) \e A = 8.552 × 10<sup>−11</sup> \e
|
||
A m<sup>2</sup>/kg, where \e G is the gravitational constant, \e g
|
||
is the earth's gravity, and \e A is the pressure of the atmosphere. At
|
||
sea level we have \e A = 101.3 kPa, and δ\e g =
|
||
8.7 × 10<sup>−6</sup> m s<sup>−2</sup>,
|
||
approximately. (In other words the effect is about 1 part in a
|
||
million; by way of comparison, buoyancy effects are about 100 times
|
||
larger.)
|
||
|
||
\section gravityparallel Geoid heights on a multi-processor system
|
||
|
||
The egm2008 model includes many terms (over 2 million spherical
|
||
harmonics). For that reason computations using this model may be slow;
|
||
for example it takes about 78 ms to compute the geoid height at a single
|
||
point. There are two ways to speed up this computation:
|
||
- Use a GravityCircle to compute the geoid height at
|
||
several points on a circle of latitude. This reduces the cost per
|
||
point to about 92 μs (a reduction by a factor of over 800).
|
||
- Compute the values on several circles of latitude in parallel. One
|
||
of the simplest ways of doing this is with
|
||
<a href="https://www.openmp.org"> OpenMP</a>; on an 8-processor system,
|
||
this can speed up the computation by another factor of 8.
|
||
.
|
||
Both of these techniques are illustrated by the following code,
|
||
which computes a table of geoid heights on
|
||
a regular grid and writes on the result in a
|
||
<a href="https://vdatum.noaa.gov/docs/gtx_info.html#dev_gtx_binary">.gtx</a>
|
||
file. On an 8-processor Intel 3.0 GHz machine using OpenMP
|
||
(-DHAVE_OPENMP=1), it takes about 10 minutes of elapsed time to compute
|
||
the geoid height for EGM2008 on a 1' grid. (Without these
|
||
optimizations, the computation would have taken about 50 days!)
|
||
\include GeoidToGTX.cpp
|
||
|
||
cmake will add in support for OpenMP for
|
||
<code>examples/GeoidToGTX.cpp</code>, if it is available.
|
||
|
||
<center>
|
||
Back to \ref geoid. Forward to \ref normalgravity. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page normalgravity Normal gravity
|
||
|
||
<center>
|
||
Back to \ref gravity. Forward to \ref magnetic. Up to \ref contents.
|
||
</center>
|
||
|
||
The NormalGravity class computes "normal gravity" which refers to the
|
||
exact (classical) solution of an idealised system consisting of an
|
||
ellipsoid of revolution with the following properties:
|
||
- \e M the mass interior to the ellipsoid,
|
||
- \e a the equatorial radius,
|
||
- \e b the polar semi-axis,
|
||
- ω the rotation rate about the polar axis.
|
||
.
|
||
(N.B. The mass always appears in the combination \e GM, with units
|
||
m<sup>3</sup>/s<sup>2</sup>, where \e G is the gravtitational constant.)
|
||
The distribution of the mass \e M within the ellipsoid is such that the
|
||
surface of the ellipsoid is at a constant normal potential where the
|
||
normal potential is the sum of the gravitational potential (due to the
|
||
gravitational attraction) and the centrifugal potential (due to the
|
||
rotation). The resulting field exterior to the ellipsoid is called
|
||
<i>normal gravity</i> and was found by Somigliana (1929). Because the
|
||
potential is constant on the ellipsoid it is sometimes referred to as
|
||
the <i>level ellipsoid</i>.
|
||
|
||
Go to
|
||
- \ref normalgravcoords
|
||
- \ref normalgravpot
|
||
- \ref normalgravmass
|
||
- \ref normalgravsurf
|
||
- \ref normalgravmean
|
||
- \ref normalgravj2
|
||
|
||
References:
|
||
- C. Somigliana, Teoria generale del campo gravitazionale dell'ellissoide
|
||
di rotazione, Mem. Soc. Astron. Ital, <b>4</b>, 541--599 (1929).
|
||
- W. A. Heiskanen and H. Moritz, Physical Geodesy (Freeman, San
|
||
Francisco, 1967), Secs. 1-19, 2-7, 2-8 (2-9, 2-10), 6-2 (6-3).
|
||
- B. Hofmann-Wellenhof, H. Moritz, Physical Geodesy (Second edition,
|
||
Springer, 2006). https://doi.org/10.1007/978-3-211-33545-1
|
||
- H. Moritz, Geodetic Reference System 1980, J. Geodesy 54(3), 395--405
|
||
(1980). https://doi.org/10.1007/BF02521480
|
||
- H. Moritz, The Figure of the Earth (Wichmann, 1990).
|
||
- M. Chasles, Solution nouvelle du problème de l’attraction d’un
|
||
ellipsoïde hétérogène sur un point
|
||
exterieur, Jour. Liouville 5, 465--488 (1840), Note 2.
|
||
http://sites.mathdoc.fr/JMPA/PDF/JMPA_1840_1_5_A41_0.pdf
|
||
|
||
\section normalgravcoords Ellipsoidal coordinates
|
||
|
||
Two set of formulas are presented: those of Heiskanen and Moritz (1967)
|
||
which are applicable to an oblate ellipsoid and a second set where the
|
||
variables are distinguished with primes which apply to a prolate
|
||
ellipsoid. The primes are omitted from those variables which are the
|
||
same in the two cases. In the text, the parenthetical "alt." clauses
|
||
apply to prolate ellipsoids.
|
||
|
||
Cylindrical coordinates \f$ R,Z \f$ are expressed in terms of
|
||
ellipsoidal coordinates
|
||
\f[
|
||
\begin{align}
|
||
R &= \sqrt{u^2 + E^2} \cos\beta = u' \cos\beta,\\
|
||
Z &= u \sin\beta = \sqrt{u'^2 + E'^2} \sin\beta,
|
||
\end{align}
|
||
\f]
|
||
where
|
||
\f[
|
||
\begin{align}
|
||
E^2 = a^2 - b^2,&{} \qquad u^2 = u'^2 + E'^2,\\
|
||
E'^2 = b^2 - a^2,&{} \qquad u'^2 = u^2 + E^2.
|
||
\end{align}
|
||
\f]
|
||
Surfaces of constant \f$ u \f$ (or \f$ u' \f$) are confocal ellipsoids.
|
||
The surface \f$ u = 0 \f$ (alt. \f$ u' = 0 \f$) corresponds to the
|
||
focal disc of diameter \f$ 2E \f$ (alt. focal rod of length
|
||
\f$ 2E' \f$). The level ellipsoid is given by \f$ u = b \f$
|
||
(alt. \f$ u' = a \f$). On the level ellipsoid, \f$ \beta \f$ is the
|
||
familiar parametric latitude.
|
||
|
||
In writing the potential and the gravity, it is useful to introduce the
|
||
functions
|
||
\f[
|
||
\begin{align}
|
||
Q(z) &= \frac1{2z^3}
|
||
\biggl[\biggl(1 + \frac3{z^2}\biggr)\tan^{-1}z - \frac3z\biggr],\\
|
||
Q'(z') &= \frac{(1+z'^2)^{3/2}}{2z'^3}
|
||
\biggl[\biggl(2 + \frac3{z'^2}\biggr)\sinh^{-1}z' -
|
||
\frac{3\sqrt{1+z'^2}}{z'}\biggr],\\
|
||
H(z) &= \biggl(3Q(z)+z\frac{dQ(z)}{dz}\biggr)(1+z^2)\\
|
||
&= \frac1{z^4}\biggl[3(1+z^2)
|
||
\biggl(1-\frac{\tan^{-1}z}z\biggr)-z^2\biggr],\\
|
||
H'(z') &= \frac{3Q'(z')}{1+z'^2}+z'\frac{dQ'(z')}{dz'}\\
|
||
&= \frac{1+z'^2}{z'^4}
|
||
\biggl[3\biggl(1-\frac{\sqrt{1+z'^2}\sinh^{-1}z'}{z'}\biggr)
|
||
+z'^2\biggr].
|
||
\end{align}
|
||
\f]
|
||
The function arguments are \f$ z = E/u \f$
|
||
(alt. \f$ z' = E'/u' \f$) and the unprimed and primed quantities are
|
||
related by
|
||
\f[
|
||
\begin{align}
|
||
Q'(z') = Q(z),&{} \qquad H'(z') = H(z),\\
|
||
z'^2 = -\frac{z^2}{1 + z^2},&{} \qquad z^2 = -\frac{z'^2}{1 + z'^2}.
|
||
\end{align}
|
||
\f]
|
||
The functions \f$ q(u) \f$ and \f$ q'(u) \f$ used by Heiskanen and
|
||
Moritz are given by
|
||
\f[
|
||
q(u) = \frac{E^3}{u^3}Q\biggl(\frac Eu\biggr),\qquad
|
||
q'(u) = \frac{E^2}{u^2}H\biggl(\frac Eu\biggr).
|
||
\f]
|
||
The functions \f$ Q(z) \f$, \f$ Q'(z') \f$, \f$ H(z) \f$, and
|
||
\f$ H'(z') \f$ are more convenient for use in numerical codes because
|
||
they are finite in the spherical limit \f$ E \rightarrow 0 \f$, i.e.,
|
||
\f$ Q(0) = Q'(0) = \frac2{15} \f$, and \f$ H(0) = H'(0) = \frac25 \f$.
|
||
|
||
\section normalgravpot The normal potential
|
||
|
||
The normal potential is the sum of three components, a mass term, a
|
||
quadrupole term and a centrifugal term,
|
||
\f[ U = U_m + U_q + U_r. \f]
|
||
The mass term is
|
||
\f[ U_m = \frac {GM}E \tan^{-1}\frac Eu
|
||
= \frac {GM}{E'} \sinh^{-1}\frac{E'}{u'}; \f]
|
||
the quadrupole term is
|
||
\f[
|
||
\begin{align}
|
||
U_q &= \frac{\omega^2}2 \frac{a^2 b^3}{u^3} \frac{Q(E/u)}{Q(E/b)}
|
||
\biggl(\sin^2\beta-\frac13\biggr)\\
|
||
&= \frac{\omega^2}2 \frac{a^2 b^3}{(u'^2+E'^2)^{3/2}}
|
||
\frac{Q'(E'/u')}{Q'(E'/a)}
|
||
\biggl(\sin^2\beta-\frac13\biggr);
|
||
\end{align}
|
||
\f]
|
||
finally, the rotational term is
|
||
\f[
|
||
U_r = \frac{\omega^2}2 R^2
|
||
= \frac{\omega^2}2 (u^2 + E^2) \cos^2\beta
|
||
= \frac{\omega^2}2 u'^2 \cos^2\beta.
|
||
\f]
|
||
|
||
\f$ U_m \f$ and \f$ U_q \f$ are both gravitational potentials (due to
|
||
mass within the ellipsoid). The total mass contributing to \f$ U_m \f$
|
||
is \f$ M \f$; the total mass contributing to \f$ U_q \f$ vanishes (far
|
||
from the ellipsoid, the \f$ U_q \f$ decays inversely as the cube of the
|
||
distance).
|
||
|
||
\f$ U_m \f$ and \f$ U_q + U_r \f$ are separately both constant on the
|
||
level ellipsoid. \f$ U_m \f$ is the normal potential for a massive
|
||
non-rotating ellipsoid. \f$ U_q + U_r \f$ is the potential for a
|
||
massless rotating ellipsoid. Combining all the terms, \f$ U \f$ is the
|
||
normal potential for a massive rotating ellipsoid.
|
||
|
||
The figure shows normal gravity for the case \f$ GM = 1 \f$,
|
||
\f$ a = 1 \f$, \f$ b = 0.8 \f$, \f$ \omega = 0.3 \f$. The level
|
||
ellipsoid is shown in red. Contours of constant gravity potential are
|
||
shown in blue; the contour spacing is constant outside the ellipsoid and
|
||
equal to 1/20 of the difference between the potentials on the ellipsoid
|
||
and at the geostationary point (\f$ R = 2.2536 \f$, \f$ Z = 0 \f$);
|
||
inside the ellipsoid the contour spacing is 5 times greater. The green
|
||
lines are stream lines for the gravity; these are spaced at intervals of
|
||
10° in parametric latitude on the surface of the ellipsoid. The
|
||
normal gravity is continued into the level ellipsoid under the
|
||
assumption that the mass is concentrated on the focal disc, shown in
|
||
black.
|
||
|
||
\image html normal-gravity-potential-1.svg "Normal gravity"
|
||
|
||
\section normalgravmass The mass distribution
|
||
|
||
Typically, the normal potential, \f$ U \f$, is only of interest for
|
||
outside the ellipsoid \f$ u \ge b \f$ (alt. \f$ u' \ge a \f$). In
|
||
planetary applications, an open problem is finding a mass distribution
|
||
which is in hydrostatic equilibrium (the mass density is non-negative
|
||
and a non-decreasing function of the potential interior to the
|
||
ellipsoid).
|
||
|
||
However it is possible to give singular mass distributions consistent
|
||
with the normal potential.
|
||
|
||
For a non-rotating body, the potential \f$ U = U_m \f$ is generated by a
|
||
sandwiching the mass \f$ M \f$ uniformly between the level ellipsoid
|
||
with semi-axes \f$ a \f$ and \f$ b \f$ and a close <i>similar</i>
|
||
ellipsoid with semi-axes \f$ (1-\epsilon)a \f$ and
|
||
\f$ (1-\epsilon)b \f$. Chasles (1840) extends a theorem of Newton to
|
||
show that the field interior to such an ellipsoidal shell vanishes.
|
||
Thus the potential on the ellipsoid is constant, i.e., it is indeed a
|
||
level ellipsoid. This result also holds for a non-rotating triaxial
|
||
ellipsoid.
|
||
|
||
Observing that \f$ U_m \f$ and \f$ U_q \f$ as defined above obey
|
||
\f$ \nabla^2 U_m = \nabla^2 U_q = 0 \f$ everywhere for \f$ u > 0 \f$
|
||
(alt. \f$ u' > 0 \f$), we see that these potentials correspond to
|
||
masses concentrated at \f$ u = 0 \f$ (alt. \f$ u' = 0 \f$).
|
||
|
||
In the oblate case, \f$ U_m \f$ is generated by a massive disc at
|
||
\f$ Z = 0 \f$, \f$ R < E \f$, with mass density (mass per unit area) \f$
|
||
\rho_m \f$ and moments of inertia about the equatorial (resp. polar)
|
||
axis of \f$ A_m \f$ (resp. \f$ C_m \f$) given by
|
||
\f[
|
||
\begin{align}
|
||
\rho_m &= \frac M{2\pi E\sqrt{E^2 - R^2}},\\
|
||
A_m &= \frac {ME^2}3, \\
|
||
C_m &= \frac {2ME^2}3, \\
|
||
C_m-A_m &= \frac {ME^2}3.
|
||
\end{align}
|
||
\f]
|
||
This mass distribution is the same as that produced by projecting a
|
||
uniform spherical shell of mass \f$ M \f$ and radius \f$ E \f$ onto the
|
||
equatorial plane.
|
||
|
||
In the prolate case, \f$ U_m \f$ is generated by a massive rod at \f$ R
|
||
= 0 \f$, \f$ Z < E' \f$ and now the mass density \f$ \rho'_m \f$ has
|
||
units mass per unit length,
|
||
\f[
|
||
\begin{align}
|
||
\rho'_m &= \frac M{2E'},\\
|
||
A_m &= \frac {ME'^2}3, \\
|
||
C_m &= 0, \\
|
||
C_m-A_m &= -\frac {ME'^2}3.
|
||
\end{align}
|
||
\f]
|
||
This mass distribution is the same as that produced by projecting a
|
||
uniform spherical shell of mass \f$ M \f$ and radius \f$ E' \f$ onto the
|
||
polar axis.
|
||
|
||
Similarly, \f$ U_q \f$ is generated in the oblate case by
|
||
\f[
|
||
\begin{align}
|
||
\rho_q &= \frac{a^2 b^3 \omega^2}G
|
||
\frac{2E^2 - 3R^2}{6\pi E^5 \sqrt{E^2 - R^2} Q(E/b)}, \\
|
||
A_q &= -\frac{a^2 b^3 \omega^2}G \frac2{45\,Q(E/b)}, \\
|
||
C_q &= -\frac{a^2 b^3 \omega^2}G \frac4{45\,Q(E/b)}, \\
|
||
C_q-A_q &= -\frac{a^2 b^3 \omega^2}G \frac2{45\,Q(E/b)}.
|
||
\end{align}
|
||
\f]
|
||
The corresponding results for a prolate ellipsoid are
|
||
\f[
|
||
\begin{align}
|
||
\rho_q' &= \frac{a^2 b^3 \omega^2}G
|
||
\frac{3Z^2 - E'^2}{12\,E'^5 Q'(E'/a)}, \\
|
||
A_q &= \frac{a^2 b^3 \omega^2}G \frac2{45\,Q'(E'/a)}, \\
|
||
C_q &= 0, \\
|
||
C_q-A_q &= -\frac{a^2 b^3 \omega^2}G \frac2{45\,Q'(E'/a)}.
|
||
\end{align}
|
||
\f]
|
||
|
||
Summing up the mass and quadrupole terms, we have
|
||
\f[
|
||
\begin{align}
|
||
A &= A_m + A_q, \\
|
||
C &= C_m + C_q, \\
|
||
J_2 & = \frac{C - A}{Ma^2},
|
||
\end{align}
|
||
\f]
|
||
where \f$ J_2 \f$ is the <i>dynamical form factor</i>.
|
||
|
||
\section normalgravsurf The surface gravity
|
||
|
||
Each term in the potential contributes to the gravity on the surface of
|
||
the ellipsoid
|
||
\f[
|
||
\gamma = \gamma_m + \gamma_q + \gamma_r;
|
||
\f]
|
||
These are the components of gravity normal to the ellipsoid and, by
|
||
convention, \f$ \gamma \f$ is positive downwards. The tangential
|
||
components of the total gravity and that due to \f$ U_m \f$ vanish.
|
||
Those tangential components of the gravity due to \f$ U_q \f$ and \f$
|
||
U_r \f$ cancel one another.
|
||
|
||
The gravity \f$ \gamma \f$ has the following dependence on latitude
|
||
\f[
|
||
\begin{align}
|
||
\gamma &= \frac{b\gamma_a\cos^2\beta + a\gamma_b\sin^2\beta}
|
||
{\sqrt{b^2\cos^2\beta + a^2\sin^2\beta}}\\
|
||
&= \frac{a\gamma_a\cos^2\phi + b\gamma_b\sin^2\phi}
|
||
{\sqrt{a^2\cos^2\phi + b^2\sin^2\phi}},
|
||
\end{align}
|
||
\f]
|
||
and the individual components, \f$ \gamma_m \f$, \f$ \gamma_q \f$, and
|
||
\f$ \gamma_r \f$, have the same dependence on latitude. The equatorial
|
||
and polar gravities are
|
||
\f[
|
||
\begin{align}
|
||
\gamma_a &= \gamma_{ma} + \gamma_{qa} + \gamma_{ra},\\
|
||
\gamma_b &= \gamma_{mb} + \gamma_{qb} + \gamma_{rb},
|
||
\end{align}
|
||
\f]
|
||
where
|
||
\f[
|
||
\begin{align}
|
||
\gamma_{ma} &= \frac{GM}{ab},\qquad \gamma_{mb} = \frac{GM}{a^2},\\
|
||
\gamma_{qa} &= -\frac{\omega^2 a}6 \frac{H(E/b)}{Q(E/b)}
|
||
= -\frac{\omega^2 a}6 \frac{H'(E'/a)}{Q'(E'/a)},\\
|
||
\gamma_{qb} &= \frac{\omega^2 b}3 \frac{H(E/b)}{Q(E/b)}
|
||
= \frac{\omega^2 b}3 \frac{H'(E'/a)}{Q'(E'/a)},\\
|
||
\gamma_{ra} &= -\omega^2 a,\qquad \gamma_{rb} = 0.
|
||
\end{align}
|
||
\f]
|
||
|
||
\section normalgravmean The mean gravity
|
||
|
||
Performing an average of the surface gravity over the area of the
|
||
ellipsoid gives
|
||
\f[
|
||
\langle \gamma \rangle = \frac {4\pi a^2 b}A
|
||
\biggl(\frac{2\gamma_a}{3a} + \frac{\gamma_b}{3b}\biggr),
|
||
\f]
|
||
where \f$ A \f$ is the area of the ellipsoid
|
||
\f[
|
||
\begin{align}
|
||
A &= 2\pi\biggl( a^2 + ab\frac{\sinh^{-1}(E/b)}{E/b} \biggr)\\
|
||
&= 2\pi\biggl( a^2 + b^2\frac{\tan^{-1}(E'/a)}{E'/a} \biggr).
|
||
\end{align}
|
||
\f]
|
||
|
||
The contributions to the mean gravity are
|
||
\f[
|
||
\begin{align}
|
||
\langle \gamma_m \rangle &= \frac{4\pi}A GM, \\
|
||
\langle \gamma_q \rangle &= 0 \quad \text{(as expected)}, \\
|
||
\langle \gamma_r \rangle &= -\frac{4\pi}A \frac{2\omega^2 a^2b}3,\\
|
||
\end{align}
|
||
\f]
|
||
resulting in
|
||
\f[
|
||
\langle \gamma \rangle = \frac{4\pi}A
|
||
\biggl(GM - \frac{2\omega^2 a^2b}3\biggr).
|
||
\f]
|
||
|
||
\section normalgravj2 Possible values of the dynamical form factor
|
||
|
||
The solution for the normal gravity is well defined for arbitrary
|
||
\f$ M \f$, \f$ \omega \f$, \f$ a > 0\f$, and \f$ f < 1 \f$. (Note that
|
||
arbitrary oblate and prolate ellipsoids are possible, although
|
||
hydrostatic equilibrium would not result in a prolate ellipsoid.)
|
||
However, it is much easier to measure the dynamical form factor
|
||
\f$ J_2 \f$ (from the motion of artificial satellites) than the
|
||
flattening \f$ f \f$. (Note too that \f$ GM \f$ is typically
|
||
measured from satellite or astronomical observations and so it
|
||
includes the mass of the atmosphere.)
|
||
|
||
So a question for the software developer is: given values of \f$ M > 0\f$,
|
||
\f$ \omega \f$, and \f$ a > 0 \f$, what are the allowed values of
|
||
\f$ J_2 \f$? We restrict the question to \f$ M > 0 \f$. The
|
||
(unphysical) case \f$ M = 0 \f$ is problematic because \f$ M \f$ appears
|
||
in the denominator in the definition of \f$ J_2 \f$. In the (also
|
||
unphysical) case \f$ M < 0 \f$, a given \f$ J_2 \f$ can result from two
|
||
distinct values of \f$ f \f$.
|
||
|
||
Holding \f$ M > 0\f$, \f$ \omega \f$, and \f$ a > 0 \f$ fixed and
|
||
varying \f$ f \f$ from \f$ -\infty \f$ to \f$ 1 \f$, we find that
|
||
\f$ J_2 \f$ monotonically increases from \f$ -\infty \f$ to
|
||
\f[
|
||
\frac13 - \frac8{45\pi} \frac{\omega^2 a^3}{GM}.
|
||
\f]
|
||
Thus any value of \f$ J_2 \f$ less that this value is permissible (but
|
||
some of these values may be unphysical). In obtaining this limiting
|
||
value, we used the result
|
||
\f$ Q(z \rightarrow \infty) \rightarrow \pi/(4 z^3) \f$. The value
|
||
\f[
|
||
J_2 = -\frac13 \frac{\omega^2 a^3}{GM}
|
||
\f]
|
||
results in a sphere (\f$ f = 0 \f$).
|
||
|
||
<center>
|
||
Back to \ref gravity. Forward to \ref magnetic. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page magnetic Magnetic models
|
||
|
||
<center>
|
||
Back to \ref normalgravity. Forward to \ref geodesic. Up to \ref contents.
|
||
</center>
|
||
|
||
GeographicLib can compute the earth's magnetic field by a magnetic
|
||
model using the MagneticModel and
|
||
MagneticCircle classes and with the
|
||
<a href="MagneticField.1.html">MagneticField</a> utility. These models
|
||
expand the internal magnetic potential of the earth as sum of spherical
|
||
harmonics. They neglect magnetic fields due to the ionosphere, the
|
||
magnetosphere, nearby magnetized materials, electric machinery, etc.
|
||
Users of MagneticModel are advised to read the
|
||
<a href="https://www.ngdc.noaa.gov/IAGA/vmod/igrfhw.html">"Health
|
||
Warning"</a> this is provided with igrf11. Although the advice is
|
||
specific to igrf11, many of the comments apply to all magnetic field
|
||
models.
|
||
|
||
The supported models are
|
||
- <b>wmm2010</b>, the
|
||
<a href="https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml"> World
|
||
Magnetic Model 2010</a>, which approximates the main magnetic field
|
||
for the period 2010--2015.
|
||
- <b>wmm2015v2</b>, the
|
||
<a href="https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml"> World
|
||
Magnetic Model 2015</a>, which approximates the main magnetic field
|
||
for the period 2015--2020.
|
||
- <b>wmm2015</b>, a deprecated version of wmm2015v2.
|
||
- <b>wmm2020</b>, the
|
||
<a href="https://ngdc.noaa.gov/geomag/WMM/DoDWMM.shtml"> World
|
||
Magnetic Model 2020</a>, which approximates the main magnetic field
|
||
for the period 2020--2025.
|
||
- <b>igrf11</b>, the
|
||
<a href="https://ngdc.noaa.gov/IAGA/vmod/igrf.html">International
|
||
Geomagnetic Reference Field (11th generation)</a>, which approximates
|
||
the main magnetic field for the period 1900--2015.
|
||
- <b>igrf12</b>, the
|
||
<a href="https://ngdc.noaa.gov/IAGA/vmod/igrf.html">International
|
||
Geomagnetic Reference Field (12th generation)</a>, which approximates
|
||
the main magnetic field for the period 1900--2020.
|
||
- <b>igrf13</b>, the
|
||
<a href="https://ngdc.noaa.gov/IAGA/vmod/igrf.html">International
|
||
Geomagnetic Reference Field (13th generation)</a>, which approximates
|
||
the main magnetic field for the period 1900--2025.
|
||
- <b>emm2010</b>, the
|
||
<a href="https://ngdc.noaa.gov/geomag/EMM/index.html"> Enhanced
|
||
Magnetic Model 2010</a>, which approximates the main and crustal
|
||
magnetic fields for the period 2010--2015.
|
||
- <b>emm2015</b>, the
|
||
<a href="https://ngdc.noaa.gov/geomag/EMM/index.html"> Enhanced
|
||
Magnetic Model 2015</a>, which approximates the main and crustal
|
||
magnetic fields for the period 2000--2020.
|
||
- <b>emm2017</b>, the
|
||
<a href="https://ngdc.noaa.gov/geomag/EMM/index.html"> Enhanced
|
||
Magnetic Model 2017</a>, which approximates the main and crustal
|
||
magnetic fields for the period 2000--2022.
|
||
|
||
Go to
|
||
- \ref magneticinst
|
||
- \ref magneticformat
|
||
|
||
\section magneticinst Installing the magnetic field models
|
||
|
||
These magnetic models are available for download:
|
||
<center>
|
||
<table>
|
||
<caption>Available magnetic models</caption>
|
||
<tr>
|
||
<th rowspan="2">name <th rowspan="2">max\n degree
|
||
<th rowspan="2">time\n interval
|
||
<th rowspan="2">size\n(kB)
|
||
<th colspan="3"><center>Download Links (size, kB)</center></th>
|
||
<tr>
|
||
<th>tar file</th>
|
||
<th>Windows\n installer</th>
|
||
<th>zip file</th>
|
||
<tr>
|
||
<td>wmm2010
|
||
<td><center>12</center>
|
||
<td><center>2010--2015</center>
|
||
<td><center>3</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2010.tar.bz2">
|
||
link</a> (2)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2010.exe">
|
||
link</a> (300)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2010.zip">
|
||
link</a> (2)</center>
|
||
<tr>
|
||
<td>wmm2015
|
||
<td><center>12</center>
|
||
<td><center>2015--2020</center>
|
||
<td><center>3</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2015.tar.bz2">
|
||
link</a> (2)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2015.exe">
|
||
link</a> (300)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2015.zip">
|
||
link</a> (2)</center>
|
||
<tr>
|
||
<td>wmm2015v2
|
||
<td><center>12</center>
|
||
<td><center>2015--2020</center>
|
||
<td><center>3</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2015v2.tar.bz2">
|
||
link</a> (2)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2015v2.exe">
|
||
link</a> (300)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2015v2.zip">
|
||
link</a> (2)</center>
|
||
<tr>
|
||
<td>wmm2020
|
||
<td><center>12</center>
|
||
<td><center>2020--2025</center>
|
||
<td><center>3</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2020.tar.bz2">
|
||
link</a> (2)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2020.exe">
|
||
link</a> (1390)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/wmm2020.zip">
|
||
link</a> (2)</center>
|
||
<tr>
|
||
<td>igrf11
|
||
<td><center>13</center>
|
||
<td><center>1900--2015</center>
|
||
<td><center>25</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/igrf11.tar.bz2">
|
||
link</a> (7)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/igrf11.exe">
|
||
link</a> (310)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/igrf11.zip">
|
||
link</a> (8)</center>
|
||
<tr>
|
||
<td>igrf12
|
||
<td><center>13</center>
|
||
<td><center>1900--2020</center>
|
||
<td><center>26</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/igrf12.tar.bz2">
|
||
link</a> (7)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/igrf12.exe">
|
||
link</a> (310)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/igrf12.zip">
|
||
link</a> (8)</center>
|
||
<tr>
|
||
<td>igrf13
|
||
<td><center>13</center>
|
||
<td><center>1900--2025</center>
|
||
<td><center>28</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/igrf13.tar.bz2">
|
||
link</a> (7)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/igrf13.exe">
|
||
link</a> (1420)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/igrf13.zip">
|
||
link</a> (8)</center>
|
||
<tr>
|
||
<td>emm2010
|
||
<td><center>739</center>
|
||
<td><center>2010--2015</center>
|
||
<td><center>4400</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/emm2010.tar.bz2">
|
||
link</a> (3700)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/emm2010.exe">
|
||
link</a> (3000)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/emm2010.zip">
|
||
link</a> (4100)</center>
|
||
<tr>
|
||
<td>emm2015
|
||
<td><center>729</center>
|
||
<td><center>2000--2020</center>
|
||
<td><center>4300</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/emm2015.tar.bz2">
|
||
link</a> (660)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/emm2015.exe">
|
||
link</a> (990)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/emm2015.zip">
|
||
link</a> (1030)</center>
|
||
<tr>
|
||
<td>emm2017
|
||
<td><center>790</center>
|
||
<td><center>2000--2022</center>
|
||
<td><center>5050</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/emm2017.tar.bz2">
|
||
link</a> (1740)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/emm2017.exe">
|
||
link</a> (1700)</center>
|
||
<td><center>
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/magnetic-distrib/emm2017.zip">
|
||
link</a> (2750)</center>
|
||
</table>
|
||
</center>
|
||
The "size" column is the size of the uncompressed data. <b>N.B.</b>, the
|
||
wmm2015 model is <b>deprecated</b>; use wmm2015v2 instead.
|
||
|
||
For Linux and Unix systems, GeographicLib provides a shell script
|
||
geographiclib-get-magnetic (typically installed in /usr/local/sbin)
|
||
which automates the process of downloading and installing the magnetic
|
||
models. For example
|
||
\verbatim
|
||
geographiclib-get-magnetic all # install all available models
|
||
geographiclib-get-magnetic -h # for help
|
||
\endverbatim
|
||
This script should be run as a user with write access to the
|
||
installation directory, which is typically
|
||
/usr/local/share/GeographicLib (this can be overridden with the -p
|
||
flag), and the data will then be placed in the "magnetic" subdirectory.
|
||
|
||
Windows users should download and run the Windows installers. These
|
||
will prompt for an installation directory with the default being
|
||
\verbatim
|
||
C:/ProgramData/GeographicLib
|
||
\endverbatim
|
||
(which you probably should not change) and the data is installed in the
|
||
"magnetic" sub-directory. (The second directory name is an alternate name
|
||
that Windows 7 uses for the "Application Data" directory.)
|
||
|
||
Otherwise download \e either the tar.bz2 file \e or the zip file (they
|
||
have the same contents). To unpack these, run, for example
|
||
\verbatim
|
||
mkdir -p /usr/local/share/GeographicLib
|
||
tar xofjC wmm2020.tar.bz2 /usr/local/share/GeographicLib
|
||
tar xofjC emm2010.tar.bz2 /usr/local/share/GeographicLib
|
||
etc.
|
||
\endverbatim
|
||
and, again, the data will be placed in the "magnetic" subdirectory.
|
||
|
||
However you install the magnetic models, all the datasets should be
|
||
installed in the same directory. MagneticModel and
|
||
<a href="MagneticField.1.html">MagneticField</a> uses a compile time
|
||
default to locate the datasets. This is
|
||
- /usr/local/share/GeographicLib/magnetic, for non-Windows systems
|
||
- C:/ProgramData/GeographicLib/magnetic, for Windows systems
|
||
.
|
||
consistent with the examples above. This may be overridden at run-time
|
||
by defining the GEOGRAPHICLIB_MAGNETIC_PATH or the GEOGRAPHIC_DATA
|
||
environment variables; see
|
||
MagneticModel::DefaultMagneticPath() for details.
|
||
Finally, the path may be set using the optional second argument to the
|
||
MagneticModel constructor or with the "-d" flag to
|
||
<a href="MagneticField.1.html">MagneticField</a>. Supplying the "-h"
|
||
flag to
|
||
<a href="MagneticField.1.html">MagneticField</a> reports the default
|
||
path for magnetic models for that utility. The "-v" flag causes
|
||
MagneticField to report the full path name of the data file it uses.
|
||
|
||
\section magneticformat The format of the magnetic model files
|
||
|
||
The constructor for MagneticModel reads a file called
|
||
NAME.wmm which specifies various properties for the magnetic model. It
|
||
then opens a binary file NAME.wmm.cof to obtain the coefficients of the
|
||
spherical harmonic sum.
|
||
|
||
The first line of the .wmm file must consist of "WMMF-v" where WMMF
|
||
stands for "World Magnetic Model Format" and v is the version number of
|
||
the format (currently "2").
|
||
|
||
The rest of the File is read a line at a time. A # character and
|
||
everything after it are discarded. If the result is just white space it
|
||
is discarded. The remaining lines are of the form "KEY WHITESPACE
|
||
VALUE". In general, the KEY and the VALUE are case-sensitive.
|
||
|
||
MagneticModel only pays attention to the following
|
||
keywords
|
||
- keywords that affect the field calculation, namely:
|
||
- <b>Radius</b> (required), the normalizing radius of the model in
|
||
meters.
|
||
- <b>NumModels</b> (default 1), the number of models. WMM2020
|
||
consists of a single model giving the magnetic field and its time
|
||
variation at 2020. IGRF12 consists of 24 models for 1900 thru 2015
|
||
at 5 year intervals. The time variation is given only for the last
|
||
model to allow extrapolation beyond 2015. For dates prior to 2015,
|
||
linear interpolation is used.
|
||
- <b>NumConstants</b> (default 0), the number of time-independent
|
||
terms; this can be 0 or 1. This keyword was introduced in format
|
||
version 2 (GeographicLib version 1.43) to support the EMM2015 and
|
||
later models. This model includes long wavelength time-varying
|
||
components of degree 15. This is supplemented by a short
|
||
wavelength time-independent component with much higher degree.
|
||
- <b>Epoch</b> (required), the time origin (in fractional years) for
|
||
the first model.
|
||
- <b>DeltaEpoch</b> (default 1), the interval between models in years
|
||
(only relevant for NumModels > 1).
|
||
- <b>Normalization</b> (default schmidt), the normalization used for
|
||
the associated Legendre functions (schmidt or full).
|
||
- <b>ID</b> (required), 8 printable characters which serve as a
|
||
signature for the .wmm.cof file (they must appear as the first 8
|
||
bytes of this file).
|
||
- keywords that store data that the user can query:
|
||
- <b>Name</b>, the name of the model.
|
||
- <b>Description</b>, a more descriptive name of the model.
|
||
- <b>ReleaseDate</b>, when the model was created.
|
||
- <b>MinTime</b>, the minimum date at which the model should be used.
|
||
- <b>MaxTime</b>, the maximum date at which the model should be used.
|
||
- <b>MinHeight</b>, the minimum height above the ellipsoid for which
|
||
the model should be used.
|
||
- <b>MaxHeight</b>, the maximum height above the ellipsoid for which
|
||
the model should be used.
|
||
.
|
||
MagneticModel does not enforce the restrictions
|
||
implied by last four quantities. However,
|
||
<a href="MagneticField.1.html">MagneticField</a> issues a warning if
|
||
these limits are exceeded.
|
||
- keywords that are examined to verify that their values are valid:
|
||
- <b>Type</b> (default linear), the type of the model. "linear"
|
||
means that the time variation is piece-wise linear (either using
|
||
interpolation between the field at two dates or using the field and
|
||
its first derivative with respect to time). This is the only type
|
||
of model supported at present.
|
||
- <b>ByteOrder</b> (default little), the order of bytes in the
|
||
.wmm.cof file. Only little endian is supported at present.
|
||
.
|
||
Other keywords are ignored.
|
||
|
||
The coefficient file NAME.wmm.cof is a binary file in little endian
|
||
order. The first 8 bytes of this file must match the ID given in
|
||
NAME.wmm. This is followed by NumModels + 1 sets of spherical harmonic
|
||
coefficients. The first NumModels of these model the magnetic field at
|
||
Epoch + \e i * DeltaEpoch for 0 ≤ \e i < NumModels. The last set of
|
||
coefficients model the rate of change of the magnetic field at Epoch +
|
||
(NumModels − 1) * DeltaEpoch. The format for each set of coefficients
|
||
is:
|
||
- \e N, the maximum degree of the sum stored as a 4-byte signed integer.
|
||
This must satisfy \e N ≥ −1.
|
||
- \e M, the maximum order of the sum stored as a 4-byte signed integer.
|
||
This must satisfy \e N ≥ \e M ≥ −1.
|
||
- <i>C</i><sub><i>nm</i></sub>, the coefficients of the cosine
|
||
coefficients of the sum in column (i.e., \e m) major order. There
|
||
are (\e M + 1) (2\e N − \e M + 2) / 2 elements which are stored
|
||
as IEEE doubles (8 bytes). For example for \e N = \e M = 3, there
|
||
are 10 coefficients arranged as
|
||
<i>C</i><sub>00</sub>,
|
||
<i>C</i><sub>10</sub>,
|
||
<i>C</i><sub>20</sub>,
|
||
<i>C</i><sub>30</sub>,
|
||
<i>C</i><sub>11</sub>,
|
||
<i>C</i><sub>21</sub>,
|
||
<i>C</i><sub>31</sub>,
|
||
<i>C</i><sub>22</sub>,
|
||
<i>C</i><sub>32</sub>,
|
||
<i>C</i><sub>33</sub>.
|
||
- <i>S</i><sub><i>nm</i></sub>, the coefficients of the sine
|
||
coefficients of the sum in column (i.e., \e m) major order starting
|
||
at \e m = 1. There are \e M (2\e N − \e M + 1) / 2 elements
|
||
which are stored as IEEE doubles (8 bytes). For example for \e N =
|
||
\e M = 3, there are 6 coefficients arranged as
|
||
<i>S</i><sub>11</sub>,
|
||
<i>S</i><sub>21</sub>,
|
||
<i>S</i><sub>31</sub>,
|
||
<i>S</i><sub>22</sub>,
|
||
<i>S</i><sub>32</sub>,
|
||
<i>S</i><sub>33</sub>.
|
||
.
|
||
Although the coefficient file is in little endian order, GeographicLib
|
||
can read it on big endian machines. It can only be read on machines
|
||
which store doubles in IEEE format.
|
||
|
||
As an illustration, here is igrf11.wmm:
|
||
\verbatim
|
||
WMMF-1
|
||
# A World Magnetic Model (Format 1) file. For documentation on the
|
||
# format of this file see
|
||
# https://geographiclib.sourceforge.io/C++/doc/magnetic.html#magneticformat
|
||
Name igrf11
|
||
Description International Geomagnetic Reference Field 11th Generation
|
||
URL https://ngdc.noaa.gov/IAGA/vmod/igrf.html
|
||
Publisher National Oceanic and Atmospheric Administration
|
||
ReleaseDate 2009-12-15
|
||
DataCutOff 2009-10-01
|
||
ConversionDate 2011-11-04
|
||
DataVersion 1
|
||
Radius 6371200
|
||
NumModels 23
|
||
Epoch 1900
|
||
DeltaEpoch 5
|
||
MinTime 1900
|
||
MaxTime 2015
|
||
MinHeight -1000
|
||
MaxHeight 600000
|
||
|
||
# The coefficients are stored in a file obtained by appending ".cof" to
|
||
# the name of this file. The coefficients were obtained from IGRF11.COF
|
||
# in the geomag70 distribution.
|
||
ID IGRF11-A
|
||
\endverbatim
|
||
|
||
<center>
|
||
Back to \ref normalgravity. Forward to \ref geodesic. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page geodesic Geodesics on an ellipsoid of revolution
|
||
|
||
<center>
|
||
Back to \ref magnetic. Forward to \ref nearest. Up to \ref contents.
|
||
</center>
|
||
|
||
Geodesic and GeodesicLine provide accurate
|
||
solutions to the direct and inverse geodesic problems. The
|
||
<a href="GeodSolve.1.html">GeodSolve</a> utility provides an interface
|
||
to these classes. AzimuthalEquidistant implements the
|
||
azimuthal equidistant projection in terms of geodesics.
|
||
CassiniSoldner implements a transverse cylindrical
|
||
equidistant projection in terms of geodesics. The
|
||
<a href="GeodesicProj.1.html">GeodesicProj</a> utility provides an
|
||
interface to these projections.
|
||
|
||
The algorithms used by Geodesic and GeodesicLine are based on a Taylor
|
||
expansion of the geodesic integrals valid when the flattening \e f is
|
||
small. GeodesicExact and GeodesicLineExact evaluate the integrals
|
||
exactly (in terms of incomplete elliptic integrals). For the WGS84
|
||
ellipsoid, the series solutions are about 2--3 times faster and 2--3
|
||
times more accurate (because it's easier to control round-off errors
|
||
with series solutions); thus Geodesic and GeodesicLine are recommended
|
||
for most geodetic applications. However, in applications where the
|
||
absolute value of \e f is greater than about 0.02, the exact classes
|
||
should be used.
|
||
|
||
Go to
|
||
- \ref testgeod
|
||
- \ref geodseries
|
||
- \ref geodellip
|
||
- \ref meridian
|
||
- \ref geodshort
|
||
.
|
||
For some background information on geodesics on triaxial ellipsoids, see
|
||
\ref triaxial.
|
||
|
||
References:
|
||
- F. W. Bessel,
|
||
<a href="https://doi.org/10.1002/asna.201011352">The calculation
|
||
of longitude and latitude from geodesic measurements (1825)</a>,
|
||
Astron. Nachr. 331(8), 852--861 (2010);
|
||
translated by C. F. F. Karney and R. E. Deakin; preprint:
|
||
<a href="https://arxiv.org/abs/0908.1824">arXiv:0908.1824</a>.
|
||
- F. R. Helmert,
|
||
<a href="https://doi.org/10.5281/zenodo.32050">
|
||
Mathematical and Physical Theories of Higher Geodesy, Part 1 (1880)</a>,
|
||
Aeronautical Chart and Information Center (St. Louis, 1964),
|
||
Chaps. 5--7.
|
||
- J. Danielsen,
|
||
The area under the geodesic,
|
||
Survey Review 30(232), 61--66 (1989).
|
||
DOI: <a href="https://doi.org/10.1179/003962689791474267">
|
||
10.1179/003962689791474267</a>
|
||
- C. F. F. Karney,
|
||
<a href="https://doi.org/10.1007/s00190-012-0578-z">
|
||
Algorithms for geodesics</a>,
|
||
J. Geodesy 87(1), 43--55 (2013);
|
||
DOI: <a href="https://doi.org/10.1007/s00190-012-0578-z">
|
||
10.1007/s00190-012-0578-z</a>;
|
||
addenda: <a href="https://geographiclib.sourceforge.io/geod-addenda.html">
|
||
geod-addenda.html</a>;
|
||
resource page:
|
||
<a href="https://geographiclib.sourceforge.io/geod.html"> geod.html</a>.
|
||
- A collection of some papers on geodesics is available at
|
||
https://geographiclib.sourceforge.io/geodesic-papers/biblio.html
|
||
- The wikipedia page,
|
||
<a href="https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid">
|
||
Geodesics on an ellipsoid</a>.
|
||
|
||
\section testgeod Test data for geodesics
|
||
|
||
A test set a geodesics is available at
|
||
- <a href="https://sourceforge.net/projects/geographiclib/files/testdata/GeodTest.dat.gz">
|
||
GeodTest.dat.gz</a>
|
||
- C. F. F. Karney, <i>Test set for geodesics</i> (2010), <br>
|
||
DOI: <a href="https://doi.org/10.5281/zenodo.32156">
|
||
10.5281/zenodo.32156</a>.
|
||
.
|
||
This is about 39 MB (compressed). This consists of a set of geodesics
|
||
for the WGS84 ellipsoid. A subset of this (consisting of 1/50 of the
|
||
members — about 690 kB, compressed) is available at
|
||
- <a href="https://sourceforge.net/projects/geographiclib/files/testdata/GeodTest-short.dat.gz">
|
||
GeodTest-short.dat.gz</a>
|
||
|
||
Each line of the test set gives 10 space delimited numbers
|
||
- latitude at point 1, \e lat1 (degrees, exact)
|
||
- longitude at point 1, \e lon1 (degrees, always 0)
|
||
- azimuth at point 1, \e azi1 (clockwise from north in degrees, exact)
|
||
- latitude at point 2, \e lat2 (degrees, accurate to
|
||
10<sup>−18</sup> deg)
|
||
- longitude at point 2, \e lon2 (degrees, accurate to
|
||
10<sup>−18</sup> deg)
|
||
- azimuth at point 2, \e azi2 (degrees, accurate to
|
||
10<sup>−18</sup> deg)
|
||
- geodesic distance from point 1 to point 2, \e s12 (meters, exact)
|
||
- arc distance on the auxiliary sphere, \e a12 (degrees, accurate to
|
||
10<sup>−18</sup> deg)
|
||
- reduced length of the geodesic, \e m12 (meters, accurate to 0.1 pm)
|
||
- the area under the geodesic, \e S12 (m<sup>2</sup>, accurate to
|
||
1 mm<sup>2</sup>)
|
||
.
|
||
These are computed using as direct geodesic calculations with the given
|
||
\e lat1, \e lon1, \e azi1, and \e s12. The distance \e s12 always
|
||
corresponds to an arc length \e a12 ≤ 180°, so the given
|
||
geodesics give the shortest paths from point 1 to point 2. For
|
||
simplicity and without loss of generality, \e lat1 is chosen in
|
||
[0°, 90°], \e lon1 is taken to be zero, \e azi1 is
|
||
chosen in [0°, 180°]. Furthermore, \e lat1 and \e
|
||
azi1 are taken to be multiples of 10<sup>−12</sup> deg and \e s12
|
||
is a multiple of 0.1 μm in [0 m, 20003931.4586254 m].
|
||
This results in \e lon2 in [0°, 180°] and \e azi2 in [0°,
|
||
180°].
|
||
|
||
The direct calculation uses an expansion of the geodesic equations
|
||
accurate to <i>f</i><sup>30</sup> (approximately 1 part in 10<sup>50</sup>)
|
||
and is computed with with
|
||
<a href="https://en.wikipedia.org/wiki/Maxima_(software)">Maxima</a>'s
|
||
bfloats and fpprec set to 100 (so the errors in the data are probably
|
||
1/2 of the values quoted above).
|
||
|
||
The contents of the file are as follows:
|
||
- 100000 entries randomly distributed
|
||
- 50000 entries which are nearly antipodal
|
||
- 50000 entries with short distances
|
||
- 50000 entries with one end near a pole
|
||
- 50000 entries with both ends near opposite poles
|
||
- 50000 entries which are nearly meridional
|
||
- 50000 entries which are nearly equatorial
|
||
- 50000 entries running between vertices (\e azi1 = \e azi2 = 90°)
|
||
- 50000 entries ending close to vertices
|
||
.
|
||
(a total of 500000 entries). The values for \e s12 for the geodesics
|
||
running between vertices are truncated to a multiple of 0.1 pm and this
|
||
is used to determine point 2.
|
||
|
||
This data can be fed to the <a href="GeodSolve.1.html">GeodSolve</a>
|
||
utility as follows
|
||
- Direct from point 1:
|
||
\verbatim
|
||
gunzip -c GeodTest.dat.gz | cut -d' ' -f1,2,3,7 | ./GeodSolve
|
||
\endverbatim
|
||
This should yield columns 4, 5, 6, and 9 of the test set.
|
||
- Direct from point 2:
|
||
\verbatim
|
||
gunzip -c GeodTest.dat.gz | cut -d' ' -f4,5,6,7 |
|
||
sed "s/ \([^ ]*$\)/ -\1/" | ./GeodSolve
|
||
\endverbatim
|
||
(The sed command negates the distance.) This should yield columns 1,
|
||
2, and 3, and the negative of column 9 of the test set.
|
||
- Inverse between points 1 and 2:
|
||
\verbatim
|
||
gunzip -c GeodTest.dat.gz | cut -d' ' -f1,2,4,5 | ./GeodSolve -i
|
||
\endverbatim
|
||
This should yield columns 3, 6, 7, and 9 of the test set.
|
||
.
|
||
Add, e.g., "-p 6", to the call to GeodSolve to change the precision of
|
||
the output. Adding "-f" causes GeodSolve to print 12 fields specifying
|
||
the geodesic; these include the 10 fields in the test set plus the
|
||
geodesic scales \e M12 and \e M21 which are inserted between \e m12 and
|
||
\e S12.
|
||
|
||
Code for computing arbitrarily accurate geodesics in maxima is available
|
||
in <a href="geodesic.mac"> geodesic.mac</a> (this depends on
|
||
<a href="ellint.mac"> ellint.mac</a> and uses the series computed by
|
||
<a href="geod.mac"> geod.mac</a>). This solve both the direct and
|
||
inverse geodesic problems and offers the ability to solve the problems
|
||
either using series expansions (similar to Geodesic) or in terms of
|
||
elliptic integrals (similar to GeodesicExact).
|
||
|
||
\section geodseries Expansions for geodesics
|
||
|
||
We give here the series expansions for the various geodesic integrals
|
||
valid to order <i>f</i><sup>10</sup>. In this release of the code, we
|
||
use a 6th-order expansions. This is sufficient to maintain accuracy for
|
||
doubles for the SRMmax ellipsoid (\e a = 6400 km, \e f = 1/150).
|
||
However, the preprocessor macro GEOGRAPHICLIB_GEODESIC_ORDER can be used
|
||
to select an order from 3 thru 8. (If using long doubles, with a 64-bit
|
||
fraction, the default order is 7.) The series expanded to order
|
||
<i>f</i><sup>30</sup> are given in <a href="geodseries30.html">
|
||
geodseries30.html</a>.
|
||
|
||
In the formulas below ^ indicates exponentiation (<i>f</i>^3 =
|
||
<i>f</i><sup>3</sup>) and / indicates real division (3/5 = 0.6). The
|
||
equations need to be converted to Horner form, but are here left in
|
||
expanded form so that they can be easily truncated to lower order.
|
||
These expansions were obtained using the Maxima code,
|
||
<a href="geod.mac">geod.mac</a>.
|
||
|
||
In the expansions below, we have
|
||
- \f$ \alpha \f$ is the azimuth
|
||
- \f$ \alpha_0 \f$ is the azimuth at the equator crossing
|
||
- \f$ \lambda \f$ is the longitude measured from the equator crossing
|
||
- \f$ \sigma \f$ is the spherical arc length
|
||
- \f$ \omega = \tan^{-1}(\sin\alpha_0\tan\sigma) \f$ is the spherical longitude
|
||
- \f$ a \f$ is the equatorial radius
|
||
- \f$ b \f$ is the polar semi-axis
|
||
- \f$ f \f$ is the flattening
|
||
- \f$ e^2 = f(2 - f) \f$
|
||
- \f$ e'^2 = e^2/(1-e^2) \f$
|
||
- \f$ k^2 = e'^2 \cos^2\alpha_0 = 4 \epsilon / (1 - \epsilon)^2 \f$
|
||
- \f$ n = f / (2 - f) \f$
|
||
- \f$ c^2 = a^2/2 + b^2/2 (\tanh^{-1}e)/e \f$
|
||
- \e ep2 = \f$ e'^2 \f$
|
||
- \e k2 = \f$ k^2 \f$
|
||
- \e eps = \f$ \epsilon = k^2 / (\sqrt{1 + k^2} + 1)^2\f$
|
||
|
||
The formula for distance is
|
||
\f[
|
||
\frac sb = I_1(\sigma)
|
||
\f]
|
||
where
|
||
\f[
|
||
\begin{align}
|
||
I_1(\sigma) &= A_1\bigl(\sigma + B_1(\sigma)\bigr) \\
|
||
B_1(\sigma) &= \sum_{j=1} C_{1j} \sin 2j\sigma
|
||
\end{align}
|
||
\f]
|
||
and
|
||
\verbatim
|
||
A1 = (1 + 1/4 * eps^2
|
||
+ 1/64 * eps^4
|
||
+ 1/256 * eps^6
|
||
+ 25/16384 * eps^8
|
||
+ 49/65536 * eps^10) / (1 - eps);
|
||
\endverbatim
|
||
\verbatim
|
||
C1[1] = - 1/2 * eps
|
||
+ 3/16 * eps^3
|
||
- 1/32 * eps^5
|
||
+ 19/2048 * eps^7
|
||
- 3/4096 * eps^9;
|
||
C1[2] = - 1/16 * eps^2
|
||
+ 1/32 * eps^4
|
||
- 9/2048 * eps^6
|
||
+ 7/4096 * eps^8
|
||
+ 1/65536 * eps^10;
|
||
C1[3] = - 1/48 * eps^3
|
||
+ 3/256 * eps^5
|
||
- 3/2048 * eps^7
|
||
+ 17/24576 * eps^9;
|
||
C1[4] = - 5/512 * eps^4
|
||
+ 3/512 * eps^6
|
||
- 11/16384 * eps^8
|
||
+ 3/8192 * eps^10;
|
||
C1[5] = - 7/1280 * eps^5
|
||
+ 7/2048 * eps^7
|
||
- 3/8192 * eps^9;
|
||
C1[6] = - 7/2048 * eps^6
|
||
+ 9/4096 * eps^8
|
||
- 117/524288 * eps^10;
|
||
C1[7] = - 33/14336 * eps^7
|
||
+ 99/65536 * eps^9;
|
||
C1[8] = - 429/262144 * eps^8
|
||
+ 143/131072 * eps^10;
|
||
C1[9] = - 715/589824 * eps^9;
|
||
C1[10] = - 2431/2621440 * eps^10;
|
||
\endverbatim
|
||
|
||
The function \f$ \tau(\sigma) = s/(b A_1) = \sigma + B_1(\sigma) \f$
|
||
may be inverted by series reversion giving
|
||
\f[
|
||
\sigma(\tau) = \tau + \sum_{j=1} C'_{1j} \sin 2j\sigma
|
||
\f]
|
||
where
|
||
\verbatim
|
||
C1'[1] = + 1/2 * eps
|
||
- 9/32 * eps^3
|
||
+ 205/1536 * eps^5
|
||
- 4879/73728 * eps^7
|
||
+ 9039/327680 * eps^9;
|
||
C1'[2] = + 5/16 * eps^2
|
||
- 37/96 * eps^4
|
||
+ 1335/4096 * eps^6
|
||
- 86171/368640 * eps^8
|
||
+ 4119073/28311552 * eps^10;
|
||
C1'[3] = + 29/96 * eps^3
|
||
- 75/128 * eps^5
|
||
+ 2901/4096 * eps^7
|
||
- 443327/655360 * eps^9;
|
||
C1'[4] = + 539/1536 * eps^4
|
||
- 2391/2560 * eps^6
|
||
+ 1082857/737280 * eps^8
|
||
- 2722891/1548288 * eps^10;
|
||
C1'[5] = + 3467/7680 * eps^5
|
||
- 28223/18432 * eps^7
|
||
+ 1361343/458752 * eps^9;
|
||
C1'[6] = + 38081/61440 * eps^6
|
||
- 733437/286720 * eps^8
|
||
+ 10820079/1835008 * eps^10;
|
||
C1'[7] = + 459485/516096 * eps^7
|
||
- 709743/163840 * eps^9;
|
||
C1'[8] = + 109167851/82575360 * eps^8
|
||
- 550835669/74317824 * eps^10;
|
||
C1'[9] = + 83141299/41287680 * eps^9;
|
||
C1'[10] = + 9303339907/2972712960 * eps^10;
|
||
\endverbatim
|
||
|
||
The reduced length is given by
|
||
\f[
|
||
\begin{align}
|
||
\frac mb &= \sqrt{1 + k^2 \sin^2\sigma_2} \cos\sigma_1 \sin\sigma_2 \\
|
||
&\quad {}-\sqrt{1 + k^2 \sin^2\sigma_1} \sin\sigma_1 \cos\sigma_2 \\
|
||
&\quad {}-\cos\sigma_1 \cos\sigma_2 \bigl(J(\sigma_2) - J(\sigma_1)\bigr)
|
||
\end{align}
|
||
\f]
|
||
where
|
||
\f[
|
||
\begin{align}
|
||
J(\sigma) &= I_1(\sigma) - I_2(\sigma) \\
|
||
I_2(\sigma) &= A_2\bigl(\sigma + B_2(\sigma)\bigr) \\
|
||
B_2(\sigma) &= \sum_{j=1} C_{2j} \sin 2j\sigma
|
||
\end{align}
|
||
\f]
|
||
\verbatim
|
||
A2 = (1 - 3/4 * eps^2
|
||
- 7/64 * eps^4
|
||
- 11/256 * eps^6
|
||
- 375/16384 * eps^8
|
||
- 931/65536 * eps^10) / (1 + eps);
|
||
\endverbatim
|
||
\verbatim
|
||
C2[1] = + 1/2 * eps
|
||
+ 1/16 * eps^3
|
||
+ 1/32 * eps^5
|
||
+ 41/2048 * eps^7
|
||
+ 59/4096 * eps^9;
|
||
C2[2] = + 3/16 * eps^2
|
||
+ 1/32 * eps^4
|
||
+ 35/2048 * eps^6
|
||
+ 47/4096 * eps^8
|
||
+ 557/65536 * eps^10;
|
||
C2[3] = + 5/48 * eps^3
|
||
+ 5/256 * eps^5
|
||
+ 23/2048 * eps^7
|
||
+ 191/24576 * eps^9;
|
||
C2[4] = + 35/512 * eps^4
|
||
+ 7/512 * eps^6
|
||
+ 133/16384 * eps^8
|
||
+ 47/8192 * eps^10;
|
||
C2[5] = + 63/1280 * eps^5
|
||
+ 21/2048 * eps^7
|
||
+ 51/8192 * eps^9;
|
||
C2[6] = + 77/2048 * eps^6
|
||
+ 33/4096 * eps^8
|
||
+ 2607/524288 * eps^10;
|
||
C2[7] = + 429/14336 * eps^7
|
||
+ 429/65536 * eps^9;
|
||
C2[8] = + 6435/262144 * eps^8
|
||
+ 715/131072 * eps^10;
|
||
C2[9] = + 12155/589824 * eps^9;
|
||
C2[10] = + 46189/2621440 * eps^10;
|
||
\endverbatim
|
||
|
||
The longitude is given in terms of the spherical longitude by
|
||
\f[
|
||
\lambda = \omega - f \sin\alpha_0 I_3(\sigma)
|
||
\f]
|
||
where
|
||
\f[
|
||
\begin{align}
|
||
I_3(\sigma) &= A_3\bigl(\sigma + B_3(\sigma)\bigr) \\
|
||
B_3(\sigma) &= \sum_{j=1} C_{3j} \sin 2j\sigma
|
||
\end{align}
|
||
\f]
|
||
and
|
||
\verbatim
|
||
A3 = 1 - (1/2 - 1/2*n) * eps
|
||
- (1/4 + 1/8*n - 3/8*n^2) * eps^2
|
||
- (1/16 + 3/16*n + 1/16*n^2 - 5/16*n^3) * eps^3
|
||
- (3/64 + 1/32*n + 5/32*n^2 + 5/128*n^3 - 35/128*n^4) * eps^4
|
||
- (3/128 + 5/128*n + 5/256*n^2 + 35/256*n^3 + 7/256*n^4) * eps^5
|
||
- (5/256 + 15/1024*n + 35/1024*n^2 + 7/512*n^3) * eps^6
|
||
- (25/2048 + 35/2048*n + 21/2048*n^2) * eps^7
|
||
- (175/16384 + 35/4096*n) * eps^8
|
||
- 245/32768 * eps^9;
|
||
\endverbatim
|
||
\verbatim
|
||
C3[1] = + (1/4 - 1/4*n) * eps
|
||
+ (1/8 - 1/8*n^2) * eps^2
|
||
+ (3/64 + 3/64*n - 1/64*n^2 - 5/64*n^3) * eps^3
|
||
+ (5/128 + 1/64*n + 1/64*n^2 - 1/64*n^3 - 7/128*n^4) * eps^4
|
||
+ (3/128 + 11/512*n + 3/512*n^2 + 1/256*n^3 - 7/512*n^4) * eps^5
|
||
+ (21/1024 + 5/512*n + 13/1024*n^2 + 1/512*n^3) * eps^6
|
||
+ (243/16384 + 189/16384*n + 83/16384*n^2) * eps^7
|
||
+ (435/32768 + 109/16384*n) * eps^8
|
||
+ 345/32768 * eps^9;
|
||
C3[2] = + (1/16 - 3/32*n + 1/32*n^2) * eps^2
|
||
+ (3/64 - 1/32*n - 3/64*n^2 + 1/32*n^3) * eps^3
|
||
+ (3/128 + 1/128*n - 9/256*n^2 - 3/128*n^3 + 7/256*n^4) * eps^4
|
||
+ (5/256 + 1/256*n - 1/128*n^2 - 7/256*n^3 - 3/256*n^4) * eps^5
|
||
+ (27/2048 + 69/8192*n - 39/8192*n^2 - 47/4096*n^3) * eps^6
|
||
+ (187/16384 + 39/8192*n + 31/16384*n^2) * eps^7
|
||
+ (287/32768 + 47/8192*n) * eps^8
|
||
+ 255/32768 * eps^9;
|
||
C3[3] = + (5/192 - 3/64*n + 5/192*n^2 - 1/192*n^3) * eps^3
|
||
+ (3/128 - 5/192*n - 1/64*n^2 + 5/192*n^3 - 1/128*n^4) * eps^4
|
||
+ (7/512 - 1/384*n - 77/3072*n^2 + 5/3072*n^3 + 65/3072*n^4) * eps^5
|
||
+ (3/256 - 1/1024*n - 71/6144*n^2 - 47/3072*n^3) * eps^6
|
||
+ (139/16384 + 143/49152*n - 383/49152*n^2) * eps^7
|
||
+ (243/32768 + 95/49152*n) * eps^8
|
||
+ 581/98304 * eps^9;
|
||
C3[4] = + (7/512 - 7/256*n + 5/256*n^2 - 7/1024*n^3 + 1/1024*n^4) * eps^4
|
||
+ (7/512 - 5/256*n - 7/2048*n^2 + 9/512*n^3 - 21/2048*n^4) * eps^5
|
||
+ (9/1024 - 43/8192*n - 129/8192*n^2 + 39/4096*n^3) * eps^6
|
||
+ (127/16384 - 23/8192*n - 165/16384*n^2) * eps^7
|
||
+ (193/32768 + 3/8192*n) * eps^8
|
||
+ 171/32768 * eps^9;
|
||
C3[5] = + (21/2560 - 9/512*n + 15/1024*n^2 - 7/1024*n^3 + 9/5120*n^4) * eps^5
|
||
+ (9/1024 - 15/1024*n + 3/2048*n^2 + 57/5120*n^3) * eps^6
|
||
+ (99/16384 - 91/16384*n - 781/81920*n^2) * eps^7
|
||
+ (179/32768 - 55/16384*n) * eps^8
|
||
+ 141/32768 * eps^9;
|
||
C3[6] = + (11/2048 - 99/8192*n + 275/24576*n^2 - 77/12288*n^3) * eps^6
|
||
+ (99/16384 - 275/24576*n + 55/16384*n^2) * eps^7
|
||
+ (143/32768 - 253/49152*n) * eps^8
|
||
+ 33/8192 * eps^9;
|
||
C3[7] = + (429/114688 - 143/16384*n + 143/16384*n^2) * eps^7
|
||
+ (143/32768 - 143/16384*n) * eps^8
|
||
+ 429/131072 * eps^9;
|
||
C3[8] = + (715/262144 - 429/65536*n) * eps^8
|
||
+ 429/131072 * eps^9;
|
||
C3[9] = + 2431/1179648 * eps^9;
|
||
\endverbatim
|
||
|
||
The formula for area between the geodesic and the equator is given in
|
||
Sec. 6 of <a href="https://doi.org/10.1007/s00190-012-0578-z">
|
||
Algorithms for geodesics</a> in terms of \e S,
|
||
\f[
|
||
S = c^2 \alpha + e^2 a^2 \cos\alpha_0 \sin\alpha_0 I_4(\sigma)
|
||
\f]
|
||
where
|
||
\f[
|
||
I_4(\sigma) = \sum_{j=0} C_{4j} \cos(2j+1)\sigma
|
||
\f]
|
||
In the paper, this was expanded in \f$ e'^2 \f$ and \f$ k^2 \f$.
|
||
However, the series converges faster for eccentric ellipsoids if the
|
||
expansion is in \f$ n \f$ and \f$ \epsilon \f$. The series to order
|
||
\f$ f^{10} \f$ becomes
|
||
\verbatim
|
||
C4[0] = + (2/3 - 4/15*n + 8/105*n^2 + 4/315*n^3 + 16/3465*n^4 + 20/9009*n^5 + 8/6435*n^6 + 28/36465*n^7 + 32/62985*n^8 + 4/11305*n^9)
|
||
- (1/5 - 16/35*n + 32/105*n^2 - 16/385*n^3 - 64/15015*n^4 - 16/15015*n^5 - 32/85085*n^6 - 112/692835*n^7 - 128/1616615*n^8) * eps
|
||
- (2/105 + 32/315*n - 1088/3465*n^2 + 1184/5005*n^3 - 128/3465*n^4 - 3232/765765*n^5 - 1856/1616615*n^6 - 6304/14549535*n^7) * eps^2
|
||
+ (11/315 - 368/3465*n - 32/6435*n^2 + 976/4095*n^3 - 154048/765765*n^4 + 368/11115*n^5 + 5216/1322685*n^6) * eps^3
|
||
+ (4/1155 + 1088/45045*n - 128/1287*n^2 + 64/3927*n^3 + 2877184/14549535*n^4 - 370112/2078505*n^5) * eps^4
|
||
+ (97/15015 - 464/45045*n + 4192/153153*n^2 - 88240/969969*n^3 + 31168/1322685*n^4) * eps^5
|
||
+ (10/9009 + 4192/765765*n - 188096/14549535*n^2 + 23392/855855*n^3) * eps^6
|
||
+ (193/85085 - 6832/2078505*n + 106976/14549535*n^2) * eps^7
|
||
+ (632/1322685 + 3456/1616615*n) * eps^8
|
||
+ 107/101745 * eps^9;
|
||
C4[1] = + (1/45 - 16/315*n + 32/945*n^2 - 16/3465*n^3 - 64/135135*n^4 - 16/135135*n^5 - 32/765765*n^6 - 112/6235515*n^7 - 128/14549535*n^8) * eps
|
||
- (2/105 - 64/945*n + 128/1485*n^2 - 1984/45045*n^3 + 256/45045*n^4 + 64/109395*n^5 + 128/855855*n^6 + 2368/43648605*n^7) * eps^2
|
||
- (1/105 - 16/2079*n - 5792/135135*n^2 + 3568/45045*n^3 - 103744/2297295*n^4 + 264464/43648605*n^5 + 544/855855*n^6) * eps^3
|
||
+ (4/1155 - 2944/135135*n + 256/9009*n^2 + 17536/765765*n^3 - 3053056/43648605*n^4 + 1923968/43648605*n^5) * eps^4
|
||
+ (1/9009 + 16/19305*n - 2656/153153*n^2 + 65072/2078505*n^3 + 526912/43648605*n^4) * eps^5
|
||
+ (10/9009 - 1472/459459*n + 106112/43648605*n^2 - 204352/14549535*n^3) * eps^6
|
||
+ (349/2297295 + 28144/43648605*n - 32288/8729721*n^2) * eps^7
|
||
+ (632/1322685 - 44288/43648605*n) * eps^8
|
||
+ 43/479655 * eps^9;
|
||
C4[2] = + (4/525 - 32/1575*n + 64/3465*n^2 - 32/5005*n^3 + 128/225225*n^4 + 32/765765*n^5 + 64/8083075*n^6 + 32/14549535*n^7) * eps^2
|
||
- (8/1575 - 128/5775*n + 256/6825*n^2 - 6784/225225*n^3 + 4608/425425*n^4 - 128/124355*n^5 - 5888/72747675*n^6) * eps^3
|
||
- (8/1925 - 1856/225225*n - 128/17325*n^2 + 42176/1276275*n^3 - 2434816/72747675*n^4 + 195136/14549535*n^5) * eps^4
|
||
+ (8/10725 - 128/17325*n + 64256/3828825*n^2 - 128/25935*n^3 - 266752/10392525*n^4) * eps^5
|
||
- (4/25025 + 928/3828825*n + 292288/72747675*n^2 - 106528/6613425*n^3) * eps^6
|
||
+ (464/1276275 - 17152/10392525*n + 83456/72747675*n^2) * eps^7
|
||
+ (1168/72747675 + 128/1865325*n) * eps^8
|
||
+ 208/1119195 * eps^9;
|
||
C4[3] = + (8/2205 - 256/24255*n + 512/45045*n^2 - 256/45045*n^3 + 1024/765765*n^4 - 256/2909907*n^5 - 512/101846745*n^6) * eps^3
|
||
- (16/8085 - 1024/105105*n + 2048/105105*n^2 - 1024/51051*n^3 + 4096/373065*n^4 - 1024/357357*n^5) * eps^4
|
||
- (136/63063 - 256/45045*n + 512/1072071*n^2 + 494336/33948915*n^3 - 44032/1996995*n^4) * eps^5
|
||
+ (64/315315 - 16384/5360355*n + 966656/101846745*n^2 - 868352/101846745*n^3) * eps^6
|
||
- (16/97461 + 14848/101846745*n + 74752/101846745*n^2) * eps^7
|
||
+ (5024/33948915 - 96256/101846745*n) * eps^8
|
||
- 1744/101846745 * eps^9;
|
||
C4[4] = + (64/31185 - 512/81081*n + 1024/135135*n^2 - 512/109395*n^3 + 2048/1247103*n^4 - 2560/8729721*n^5) * eps^4
|
||
- (128/135135 - 2048/405405*n + 77824/6891885*n^2 - 198656/14549535*n^3 + 8192/855855*n^4) * eps^5
|
||
- (512/405405 - 2048/530145*n + 299008/130945815*n^2 + 280576/43648605*n^3) * eps^6
|
||
+ (128/2297295 - 2048/1438965*n + 241664/43648605*n^2) * eps^7
|
||
- (17536/130945815 + 1024/43648605*n) * eps^8
|
||
+ 2944/43648605 * eps^9;
|
||
C4[5] = + (128/99099 - 2048/495495*n + 4096/765765*n^2 - 6144/1616615*n^3 + 8192/4849845*n^4) * eps^5
|
||
- (256/495495 - 8192/2807805*n + 376832/53348295*n^2 - 8192/855855*n^3) * eps^6
|
||
- (6784/8423415 - 432128/160044885*n + 397312/160044885*n^2) * eps^7
|
||
+ (512/53348295 - 16384/22863555*n) * eps^8
|
||
- 16768/160044885 * eps^9;
|
||
C4[6] = + (512/585585 - 4096/1422135*n + 8192/2078505*n^2 - 4096/1322685*n^3) * eps^6
|
||
- (1024/3318315 - 16384/9006855*n + 98304/21015995*n^2) * eps^7
|
||
- (103424/189143955 - 8192/4203199*n) * eps^8
|
||
- 1024/189143955 * eps^9;
|
||
C4[7] = + (1024/1640925 - 65536/31177575*n + 131072/43648605*n^2) * eps^7
|
||
- (2048/10392525 - 262144/218243025*n) * eps^8
|
||
- 84992/218243025 * eps^9;
|
||
C4[8] = + (16384/35334585 - 131072/82447365*n) * eps^8
|
||
- 32768/247342095 * eps^9;
|
||
C4[9] = + 32768/92147055 * eps^9;
|
||
\endverbatim
|
||
|
||
\section geodellip Geodesics in terms of elliptic integrals
|
||
|
||
GeodesicExact and GeodesicLineExact solve the geodesic problem using
|
||
elliptic integrals. The formulation of geodesic in terms of incomplete
|
||
elliptic integrals is given in
|
||
- C. F. F. Karney,
|
||
<a href="https://arxiv.org/abs/2208.00492">
|
||
Geodesics on an arbitrary ellipsoid of revolution</a>, Aug. 2022;
|
||
preprint <a href="https://arxiv.org/abs/2208.00492">
|
||
arxiv:2208.00492</a>.
|
||
.
|
||
|
||
The key relations used by GeographicLib are
|
||
\f[
|
||
\begin{align}
|
||
\frac sb &= E(\sigma, ik), \\
|
||
\lambda &= (1 - f) \sin\alpha_0 G(\sigma, \cos^2\alpha_0, ik) \\
|
||
&= \chi
|
||
- \frac{e'^2}{\sqrt{1+e'^2}}\sin\alpha_0 H(\sigma, -e'^2, ik), \\
|
||
J(\sigma) &= k^2 D(\sigma, ik),
|
||
\end{align}
|
||
\f]
|
||
where \f$ \chi \f$ is a modified spherical longitude given by
|
||
\f[
|
||
\tan\chi = \sqrt{\frac{1+e'^2}{1+k^2\sin^2\sigma}}\tan\omega,
|
||
\f]
|
||
and
|
||
\f[
|
||
\begin{align}
|
||
D(\phi,k) &= \int_0^\phi
|
||
\frac{\sin^2\theta}{\sqrt{1 - k^2\sin^2\theta}}\,d\theta\\
|
||
&=\frac{F(\phi, k) - E(\phi, k)}{k^2},\\
|
||
G(\phi,\alpha^2,k) &= \int_0^\phi
|
||
\frac{\sqrt{1 - k^2\sin^2\theta}}{1 - \alpha^2\sin^2\theta}\,d\theta\\
|
||
&=\frac{k^2}{\alpha^2}F(\phi, k)
|
||
+\biggl(1-\frac{k^2}{\alpha^2}\biggr)\Pi(\phi, \alpha^2, k),\\
|
||
H(\phi, \alpha^2, k)
|
||
&= \int_0^\phi
|
||
\frac{\cos^2\theta}{(1-\alpha^2\sin^2\theta)\sqrt{1-k^2\sin^2\theta}}
|
||
\,d\theta \\
|
||
&=
|
||
\frac1{\alpha^2} F(\phi, k) +
|
||
\biggl(1 - \frac1{\alpha^2}\biggr) \Pi(\phi, \alpha^2, k),
|
||
\end{align}
|
||
\f]
|
||
and \f$F(\phi, k)\f$, \f$E(\phi, k)\f$, \f$D(\phi, k)\f$, and
|
||
\f$\Pi(\phi, \alpha^2, k)\f$, are incomplete elliptic integrals (see
|
||
https://dlmf.nist.gov/19.2.ii). The formula for \f$ s \f$ and the
|
||
first expression for \f$ \lambda \f$ are given by Legendre (1811) and
|
||
are the most common representation of geodesics in terms of elliptic
|
||
integrals. The second (equivalent) expression for \f$ \lambda \f$,
|
||
which was given by Cayley (1870), is useful in that the elliptic
|
||
integral is relegated to a small correction term. This form allows
|
||
the longitude to be computed more accurately and is used in
|
||
GeographicLib. (The equivalence of the two expressions for \f$
|
||
\lambda \f$ follows from https://dlmf.nist.gov/19.7.E8.)
|
||
|
||
Nominally, GeodesicExact and GeodesicLineExact will give "exact" results
|
||
for any value of the flattening. However, the geographic latitude is a
|
||
distorted measure of distance from the equator with very eccentric
|
||
ellipsoids and this introducing an irreducible representational error in
|
||
the algorithms in this case. It is therefore recommended to restrict
|
||
the use of these classes to <i>b</i>/\e a ∈ [0.01, 100] or \e f
|
||
∈ [−99, 0.99]. GeodesicExact uses an discrete sine transform
|
||
fit for the area \e S12. The number of terms used is adjusted to give
|
||
accurate results for this same range of flattenings, \e f ∈
|
||
[−99, 0.99].
|
||
|
||
Thomas (1952) and Rollins (2010) use a different independent variable
|
||
for geodesics, \f$\theta\f$ instead of \f$\sigma\f$, where \f$
|
||
\tan\theta = \sqrt{1 + k^2} \tan\sigma \f$. The corresponding
|
||
expressions for \f$ s \f$ and \f$ \lambda \f$ are given here for
|
||
completeness:
|
||
\f[
|
||
\begin{align}
|
||
\frac sb &= \sqrt{1-k'^2} \Pi(\theta, k'^2, k'), \\
|
||
\lambda &= (1-f) \sqrt{1-k'^2} \sin\alpha_0 \Pi(\theta, k'^2/e^2, k'),
|
||
\end{align}
|
||
\f]
|
||
where \f$ k' = k/\sqrt{1 + k^2} \f$. The expression for \f$ s \f$
|
||
can be written in terms of elliptic integrals of the second kind and
|
||
Cayley's technique can be used to subtract out the leading order
|
||
behavior of \f$ \lambda \f$ to give
|
||
\f[
|
||
\begin{align}
|
||
\frac sb &=\frac1{\sqrt{1-k'^2}}
|
||
\biggl( E(\theta, k') -
|
||
\frac{k'^2 \sin\theta \cos\theta}{\sqrt{1-k'^2\sin^2\theta}} \biggr), \\
|
||
\lambda &= \psi + (1-f) \sqrt{1-k'^2} \sin\alpha_0
|
||
\bigl( F(\theta, k') - \Pi(\theta, e^2, k') \bigr),
|
||
\end{align}
|
||
\f]
|
||
where
|
||
\f[
|
||
\begin{align}
|
||
\tan\psi &= \sqrt{\frac{1+k^2\sin^2\sigma}{1+e'^2}}\tan\omega \\
|
||
&= \sqrt{\frac{1-e^2}{1+k^2\cos^2\theta}}\sin\alpha_0\tan\theta.
|
||
\end{align}
|
||
\f]
|
||
The tangents of the three "longitude-like" angles are in geometric
|
||
progression, \f$ \tan\chi/\tan\omega = \tan\omega/\tan\psi \f$.
|
||
|
||
\section meridian Parameters for the meridian
|
||
|
||
The formulas for \f$ s \f$ given in the previous section are the same as
|
||
those for the distance along a meridian for an ellipsoid with equatorial
|
||
radius \f$ a \sqrt{1 - e^2 \sin^2\alpha_0} \f$ and polar semi-axis \f$ b
|
||
\f$. Here is a list of possible ways of expressing the meridian
|
||
distance in terms of elliptic integrals using the notation:
|
||
- \f$ a \f$, equatorial axis,
|
||
- \f$ b \f$, polar axis,
|
||
- \f$ e = \sqrt{(a^2 - b^2)/a^2} \f$, eccentricity,
|
||
- \f$ e' = \sqrt{(a^2 - b^2)/b^2} \f$, second eccentricity,
|
||
- \f$ \phi = \mathrm{am}(u, e) \f$, the geographic latitude,
|
||
- \f$ \phi' = \mathrm{am}(v', ie') = \pi/2 - \phi \f$,
|
||
the geographic colatitude,
|
||
- \f$ \beta = \mathrm{am}(v, ie') \f$, the parametric latitude
|
||
(\f$ \tan^2\beta = (1 - e^2) \tan^2\phi \f$),
|
||
- \f$ \beta' = \mathrm{am}(u', e) = \pi/2 - \beta \f$,
|
||
the parametric colatitude,
|
||
- \f$ M \f$, the length of a quarter meridian (equator to pole),
|
||
- \f$ y \f$, the distance along the meridian (measured from the equator).
|
||
- \f$ y' = M -y \f$, the distance along the meridian (measured from the pole).
|
||
.
|
||
The eccentricities \f$ (e, e') \f$ are real (resp. imaginary) for
|
||
oblate (resp. prolate) ellipsoids. The elliptic variables \f$(u,
|
||
u')\f$ and \f$(v, v')\f$ are defined by
|
||
- \f$ u = F(\phi, e) ,\quad u' = F(\beta', e) \f$
|
||
- \f$ v = F(\beta, ie') ,\quad v' = F(\phi', ie') \f$,
|
||
.
|
||
and are linearly related by
|
||
- \f$ u + u' = K(e) ,\quad v + v' = K(ie') \f$
|
||
- \f$ v = \sqrt{1-e^2} u ,\quad u = \sqrt{1+e'^2} v \f$.
|
||
.
|
||
The cartesian coordinates for the meridian \f$ (x, z) \f$ are given by
|
||
\f[
|
||
\begin{align}
|
||
x &= a \cos\beta = a \cos\phi / \sqrt{1 - e^2 \sin^2\phi} \\
|
||
&= a \sin\beta' = (a^2/b) \sin\phi' / \sqrt{1 + e'^2 \sin^2\phi'} \\
|
||
&= a \,\mathrm{cn}(v, ie) = a \,\mathrm{cd}(u, e) \\
|
||
&= a \,\mathrm{sn}(u', e) = (a^2/b) \,\mathrm{sd}(v', ie'),
|
||
\end{align}
|
||
\f]
|
||
\f[
|
||
\begin{align}
|
||
z &= b \sin\beta = (b^2/a) \sin\phi / \sqrt{1 - e^2 \sin^2\phi} \\
|
||
&= b \cos\beta' = b \cos\phi' / \sqrt{1 + e'^2 \sin^2\phi'} \\
|
||
&= b \,\mathrm{sn}(v, ie) = (b^2/a) \,\mathrm{sd}(u, e) \\
|
||
&= b \,\mathrm{cn}(u', e) = b \,\mathrm{cd}(v', ie').
|
||
\end{align}
|
||
\f]
|
||
The distance along the meridian can be expressed variously as
|
||
\f[
|
||
\begin{align}
|
||
y &= b \int \sqrt{1 + e'^2 \sin^2\beta}\, d\beta
|
||
= b E(\beta, ie') \\
|
||
&= \frac{b^2}a \int \frac1{(1 - e^2 \sin^2\phi)^{3/2}}\, d\phi
|
||
= \frac{b^2}a \Pi(\phi, e^2, e) \\
|
||
&= a \biggl(E(\phi, e) -
|
||
\frac{e^2\sin\phi \cos\phi}{\sqrt{1 - e^2\sin^2\phi}}\biggr) \\
|
||
&= b \int \mathrm{dn}^2(v, ie')\, dv
|
||
= \frac{b^2}a \int \mathrm{nd}^2(u, e)\, du
|
||
= \cal E(v, ie'),
|
||
\end{align}
|
||
\f]
|
||
\f[
|
||
\begin{align}
|
||
y' &= a \int \sqrt{1 - e^2 \sin^2\beta'}\, d\beta'
|
||
= a E(\beta', e) \\
|
||
&= \frac{a^2}b \int \frac1{(1 + e'^2 \sin^2\phi')^{3/2}}\, d\phi'
|
||
= \frac{a^2}b \Pi(\phi', -e'^2, ie') \\
|
||
&= b \biggl(E(\phi', ie') +
|
||
\frac{e'^2\sin\phi' \cos\phi'}{\sqrt{1 + e'^2\sin^2\phi'}}\biggr) \\
|
||
&= a \int \mathrm{dn}^2(u', e)\, du'
|
||
= \frac{a^2}b \int \mathrm{nd}^2(v', ie')\, dv'
|
||
= \cal E(u', e),
|
||
\end{align}
|
||
\f]
|
||
with the quarter meridian distance given by
|
||
\f[
|
||
M = aE(e) = bE(ie') = (b^2/a)\Pi(e^2,e) = (a^2/b)\Pi(-e'^2,ie').
|
||
\f]
|
||
(Here \f$ E, F, \Pi \f$ are elliptic integrals defined in
|
||
https://dlmf.nist.gov/19.2.ii. \f$ \cal E, \mathrm{am}, \mathrm{sn},
|
||
\mathrm{cn}, \mathrm{sd}, \mathrm{cd}, \mathrm{dn}, \mathrm{nd} \f$ are
|
||
Jacobi elliptic functions defined in https://dlmf.nist.gov/22.2 and
|
||
https://dlmf.nist.gov/22.16.)
|
||
|
||
There are several considerations in the choice of independent variable
|
||
for evaluate the meridian distance
|
||
- The use of an imaginary modulus (namely, \f$ ie' \f$, above) is of no
|
||
practical concern. The integrals are real in this case and modern
|
||
methods (GeographicLib uses the method given in
|
||
https://dlmf.nist.gov/19.36.i) for computing integrals handles this
|
||
case using just real arithmetic.
|
||
- If the "natural" origin is the equator, choose one of \f$ \phi, \beta,
|
||
u, v \f$ (this might be preferred in geodesy). If it's the pole,
|
||
choose one of the complementary quantities \f$ \phi', \beta', u', v'
|
||
\f$ (this might be preferred by mathematicians).
|
||
- Applying these formulas to the geodesic problems, \f$ \beta \f$
|
||
becomes the arc length, \f$ \sigma \f$, on the auxiliary sphere. This
|
||
is the traditional method of solution used by Legendre (1806), Oriani
|
||
(1806), Bessel (1825), Helmert (1880), Rainsford (1955), Thomas
|
||
(1970), Vincenty (1975), Rapp (1993), and so on. Many of the
|
||
solutions in terms of elliptic functions use one of the elliptic
|
||
variables (\f$ u \f$ or \f$ v \f$), see, for example, Jacobi (1855),
|
||
Halphen (1888), Forsyth (1896). In the context of geodesics \f$
|
||
\phi \f$ becomes Thomas' variable \f$ \theta \f$; this is used by
|
||
Thomas (1952) and Rollins (2010) in their formulation of the
|
||
geodesic problem (see the previous section).
|
||
- For highly eccentric ellipsoids the variation of the meridian with
|
||
respect to \f$ \beta \f$ is considerably "better behaved" than other
|
||
choices (see the figure below). The choice of \f$ \phi \f$ is
|
||
probably a poor one in this case.
|
||
.
|
||
GeographicLib uses the geodesic generalization of
|
||
\f$ y = b E(\beta, ie') \f$, namely \f$ s = b E(\sigma, ik) \f$. See
|
||
\ref geodellip.
|
||
|
||
\image html meridian-measures.png "Comparison of meridian measures"
|
||
|
||
\section geodshort Short geodesics
|
||
|
||
Here we describe Bowring's method for solving the inverse geodesic
|
||
problem in the limit of short geodesics and contrast it with the great
|
||
circle solution using Bessel's auxiliary sphere. References:
|
||
- B. R. Bowring, The Direct and Inverse Problems for Short Geodesic
|
||
Lines on the Ellipsoid, Surveying and Mapping 41(2), 135--141 (1981).
|
||
- R. H. Rapp,
|
||
<a href="https://hdl.handle.net/1811/24333">
|
||
Geometric Geodesy, Part I</a>, Ohio State Univ. (1991), Sec. 6.5.
|
||
|
||
Bowring considers the conformal mapping of the ellipsoid to a sphere of
|
||
radius \f$ R \f$ such that circles of latitude and meridians are
|
||
preserved (and hence the azimuth of a line is preserved). Let \f$
|
||
(\phi, \lambda) \f$ and \f$ (\phi', \lambda') \f$ be the latitude and
|
||
longitude on the ellipsoid and sphere respectively. Define isometric
|
||
latitudes for the sphere and the ellipsoid as
|
||
\f[
|
||
\begin{align}
|
||
\psi' &= \sinh^{-1} \tan \phi', \\
|
||
\psi &= \sinh^{-1} \tan \phi - e \tanh^{-1}(e \sin\phi).
|
||
\end{align}
|
||
\f]
|
||
The most general conformal mapping satisfying Bowring's conditions is
|
||
\f[
|
||
\psi' = A \psi + K, \quad \lambda' = A \lambda,
|
||
\f]
|
||
where \f$ A \f$ and \f$ K \f$ are constants. (In fact a constant can be
|
||
added to the equation for \f$ \lambda' \f$, but this does affect the
|
||
analysis.) The scale of this mapping is
|
||
\f[
|
||
m(\phi) = \frac{AR}{\nu}\frac{\cos\phi'}{\cos\phi},
|
||
\f]
|
||
where \f$ \nu = a/\sqrt{1 - e^2\sin^2\phi} \f$ is the transverse radius
|
||
of curvature. (Note that in Bowring's Eq. (10), \f$ \phi \f$ should be
|
||
replaced by \f$ \phi' \f$.) The mapping from the ellipsoid to the sphere
|
||
depends on three parameters \f$ R, A, K \f$. These will be selected to
|
||
satisfy certain conditions at some representative latitude \f$ \phi_0
|
||
\f$. Two possible choices are given below.
|
||
|
||
\subsection bowring Bowring's method
|
||
|
||
Bowring (1981) requires that
|
||
\f[
|
||
m(\phi_0) = 1,\quad
|
||
\left.\frac{dm(\phi)}{d\phi}\right|_{\phi=\phi_0} = 0,\quad
|
||
\left.\frac{d^2m(\phi)}{d\phi^2}\right|_{\phi=\phi_0} = 0,
|
||
\f]
|
||
i.e, \f$m\approx 1\f$ in the vicinity of \f$\phi = \phi_0\f$.
|
||
This gives
|
||
\f[
|
||
\begin{align}
|
||
R &= \frac{\sqrt{1 + e'^2}}{B^2} a, \\
|
||
A &= \sqrt{1 + e'^2 \cos^4\phi_0}, \\
|
||
\tan\phi'_0 &= \frac1B \tan\phi_0,
|
||
\end{align}
|
||
\f]
|
||
where \f$ e' = e/\sqrt{1-e^2} \f$ is the second eccentricity, \f$ B =
|
||
\sqrt{1+e'^2\cos^2\phi_0} \f$, and \f$ K \f$ is defined implicitly by
|
||
the equation for \f$\phi'_0\f$. The radius \f$ R \f$ is the (Gaussian)
|
||
mean radius of curvature of the ellipsoid at \f$\phi_0\f$ (so near
|
||
\f$\phi_0\f$ the ellipsoid can be deformed to fit the sphere snugly).
|
||
The third derivative of \f$ m \f$ is given by
|
||
\f[
|
||
\left.\frac{d^3m(\phi)}{d\phi^3}\right|_{\phi=\phi_0} =
|
||
\frac{-2e'^2\sin2\phi_0}{B^4}.
|
||
\f]
|
||
|
||
The method for solving the inverse problem between two nearby points \f$
|
||
(\phi_1, \lambda_1) \f$ and \f$ (\phi_2, \lambda_2) \f$ is as follows:
|
||
Set \f$\phi_0 = (\phi_1 + \phi_2)/2\f$. Compute \f$ R, A, \phi'_0 \f$,
|
||
and hence find \f$ (\phi'_1, \lambda'_1) \f$ and \f$ (\phi'_2,
|
||
\lambda'_2) \f$. Finally, solve for the great circle on a sphere of
|
||
radius \f$ R \f$; the resulting distance and azimuths are good
|
||
approximations for the corresponding quantities for the ellipsoidal
|
||
geodesic.
|
||
|
||
Consistent with the accuracy of this method, we can compute
|
||
\f$\phi'_1\f$ and \f$\phi'_2\f$ using a Taylor expansion about
|
||
\f$\phi_0\f$. This also avoids numerical errors that arise from
|
||
subtracting nearly equal quantities when using the equation for
|
||
\f$\phi'\f$ directly. Write \f$\Delta \phi = \phi - \phi_0\f$ and
|
||
\f$\Delta \phi' = \phi' - \phi'_0\f$; then we have
|
||
\f[
|
||
\Delta\phi' \approx
|
||
\frac{\Delta\phi}B \biggl[1 +
|
||
\frac{\Delta\phi}{B^2}\frac{e'^2}2
|
||
\biggl(3\sin\phi_0\cos\phi_0 +
|
||
\frac{\Delta\phi}{B^2}
|
||
\bigl(B^2 - \sin^2\phi_0(2 - 3 e'^2 \cos^2\phi_0)\bigr)\biggr)\biggr],
|
||
\f]
|
||
where the error is \f$O(f\Delta\phi^4)\f$.
|
||
This is essentially Bowring's method. Significant differences between
|
||
this result, "Bowring (improved)", compared to Bowring's paper, "Bowring
|
||
(original)", are:
|
||
- Bowring elects to use \f$\phi_0 = \phi_1\f$. This simplifies the
|
||
calculations somewhat but increases the error by about a factor of
|
||
4.
|
||
- Bowring's expression for \f$ \Delta\phi' \f$ is only accurate in the
|
||
limit \f$ e' \rightarrow 0 \f$.
|
||
.
|
||
In fact, arguably, the highest order \f$O(f\Delta\phi^3)\f$ terms should
|
||
be dropped altogether. Their inclusion does result in a better estimate
|
||
for the distance. However, if your goal is to generate both accurate
|
||
distances \e and accurate azimuths, then \f$\Delta\phi\f$ needs to be
|
||
restricted sufficiently to allow these terms to be dropped to give the
|
||
"Bowring (truncated)" method.
|
||
|
||
With highly eccentric ellipsoids, the parametric latitude \f$ \beta \f$
|
||
is a better behaved independent variable to use. In this case, \f$
|
||
\phi_0 \f$ is naturally defined using \f$\beta_0 = (\beta_1 +
|
||
\beta_2)/2\f$ and in terms of \f$\Delta\beta = \beta - \beta_0\f$, we
|
||
have
|
||
\f[
|
||
\Delta\phi' \approx
|
||
\frac{\Delta\beta}{B'} \biggl[1 +
|
||
\frac{\Delta\beta}{B'^2}\frac{e'^2}2
|
||
\biggl(\sin\beta_0\cos\beta_0 +
|
||
\frac{\Delta\beta}{3B'^2}
|
||
\bigl( \cos^2\beta_0 - \sin^2\beta_0 B'^2\bigr)
|
||
\biggr)\biggr],
|
||
\f]
|
||
where \f$B' = \sqrt{1+e'^2\sin^2\beta_0} = \sqrt{1+e'^2}/B\f$, and the
|
||
error once again is \f$O(f\Delta\phi^4)\f$. This is the "Bowring
|
||
(using \f$\beta\f$)" method.
|
||
|
||
\subsection auxsphere Bessel's auxiliary sphere
|
||
|
||
GeographicLib's uses the auxiliary sphere method of Legendre, Bessel,
|
||
and Helmert. For short geodesics, this is equivalent to picking
|
||
\f$ R, A, K \f$ so that
|
||
\f[
|
||
m(\phi_0) = 1,\quad
|
||
\left.\frac{dm(\phi)}{d\phi}\right|_{\phi=\phi_0} = 0,\quad
|
||
\tan\phi'_0 = (1 - f) \tan\phi_0.
|
||
\f]
|
||
Bowring's requirement that the second derivative of \f$m\f$ vanish has
|
||
been replaced by the last relation which states that \f$\phi'_0 =
|
||
\beta_0\f$, the parametric latitude corresponding to \f$\phi_0\f$. This
|
||
gives
|
||
\f[
|
||
\begin{align}
|
||
R &= B'(1-f)a, \\
|
||
A &= \frac1{B'(1-f)}, \\
|
||
\left.\frac{d^2m(\phi)}{d\phi^2}\right|_{\phi=\phi_0} &=
|
||
-e^2B'^2\sin^2\phi_0.
|
||
\end{align}
|
||
\f]
|
||
|
||
Similar to Bowring's method, we can compute \f$\phi'_1\f$ and
|
||
\f$\phi'_2\f$ using a Taylor expansion about \f$\beta_0\f$. This results
|
||
in the simple expression
|
||
\f[
|
||
\Delta\phi' \approx \Delta\beta,
|
||
\f]
|
||
where the error is \f$O(f\Delta\beta^2)\f$.
|
||
|
||
\subsection shorterr Estimating the accuracy
|
||
|
||
In assessing the accuracy of these methods we use two metrics:
|
||
- The absolute error in the distance.
|
||
- The consistency of the predicted azimuths. Imagine starting
|
||
ellipsoidal geodesics at \f$ (\phi_1, \lambda_1) \f$ and \f$ (\phi_2,
|
||
\lambda_2) \f$ with the predicted azimuths. What is the distance
|
||
between them when they are extended a distance \f$ a \f$ beyond the
|
||
second point?
|
||
.
|
||
(The second metric is much more stringent.) We may now compare the
|
||
methods by asking for a bound to the length of a geodesic which ensures
|
||
that the one or other of the errors fall below 1 mm (an "engineering"
|
||
definition of accurate) or 1 nm (1 nanometer, about the round-off
|
||
limit).
|
||
|
||
<center>
|
||
<table>
|
||
<caption>Maximum distance that can be used in various methods for
|
||
computing short geodesics while keeping the errors within prescribed
|
||
bounds</caption>
|
||
<tr>
|
||
<th rowspan="2">method
|
||
<th colspan="2"><center>distance metric</center></th>
|
||
<th colspan="2"><center>azimuth metric</center></th>
|
||
<tr>
|
||
<th>1 mm error</th>
|
||
<th>1 nm error</th>
|
||
<th>1 mm error</th>
|
||
<th>1 nm error</th>
|
||
<tr>
|
||
<td>Bowring (original)
|
||
<td><center>87 km</center>
|
||
<td><center>870 m</center>
|
||
<td><center>35 km</center>
|
||
<td><center>350 m</center>
|
||
<tr>
|
||
<td>Bowring (improved)
|
||
<td><center>180 km</center>
|
||
<td><center>1.8 km</center>
|
||
<td><center>58 km</center>
|
||
<td><center>580 m</center>
|
||
<tr>
|
||
<td>Bowring (truncated)
|
||
<td><center>52 km</center>
|
||
<td><center>520 m</center>
|
||
<td><center>52 km</center>
|
||
<td><center>520 m</center>
|
||
<tr>
|
||
<td>Bowring (using \f$\beta\f$)
|
||
<td><center>380 km</center>
|
||
<td><center>24 km</center>
|
||
<td><center>60 km</center>
|
||
<td><center>600 m</center>
|
||
<tr>
|
||
<td>Bessel's aux. sphere
|
||
<td><center>42 km</center>
|
||
<td><center>420 m</center>
|
||
<td><center>1.7 km</center>
|
||
<td><center>1.7 m</center>
|
||
</table>
|
||
</center>
|
||
|
||
For example, if you're only interested in measuring distances and an
|
||
accuracy of 1 mm is sufficient, then Bowring's improved method can
|
||
be used for distances up to 180 km. On the other hand,
|
||
GeographicLib uses Bessel's auxiliary sphere and we require both the
|
||
distance and the azimuth to be accurate, so the great circle
|
||
approximation can only be used for distances less than 1.7 m. The
|
||
reason that GeographicLib does not use Bowring's method is that the
|
||
information necessary for auxiliary sphere method is already available
|
||
as part of the general solution and, as much as possible, we allow all
|
||
geodesics to be computed by the general method.
|
||
|
||
<center>
|
||
Back to \ref magnetic. Forward to \ref nearest. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page nearest Finding nearest neighbors
|
||
|
||
<center>
|
||
Back to \ref geodesic. Forward to \ref triaxial. Up to \ref contents.
|
||
</center>
|
||
|
||
The problem of finding the maritime boundary defined by the "median
|
||
line" is discussed in Section 14 of
|
||
- C. F. F. Karney,
|
||
<a href="https://arxiv.org/abs/1102.1215v1">Geodesics
|
||
on an ellipsoid of revolution</a>,
|
||
Feb. 2011; preprint
|
||
<a href="https://arxiv.org/abs/1102.1215v1">arxiv:1102.1215v1</a>.
|
||
.
|
||
Figure 14 shows the median line which is equidistant from Britain and
|
||
mainland Europe. Determining the median line involves finding, for any
|
||
given \e P, the closest points on the coast of Britain and on the coast
|
||
of mainland Europe. The operation of finding the closest in a set of
|
||
points is usually referred to as the <i>nearest neighbor</i> problem and
|
||
the NearestNeighbor class implements an efficient algorithm for solving
|
||
it.
|
||
|
||
The NearestNeighbor class implements nearest-neighbor calculations using
|
||
the vantage-point tree described by
|
||
- J. K. Uhlmann,
|
||
<a href="https://doi.org/10.1016/0020-0190(91)90074-r">
|
||
Satisfying general proximity/similarity queries with metric trees</a>,
|
||
Information Processing Letters 40 175--179 (1991).
|
||
- P. N. Yianilos,
|
||
<a href="https://dl.acm.org/doi/10.5555/313559.313789">
|
||
Data structures and algorithms for nearest neighbor search in general
|
||
metric spaces</a>, Proc. 4th ACM-SIAM Symposium on Discrete Algorithms,
|
||
(SIAM, 1993). pp. 311--321.
|
||
|
||
Given a set of points \e x, \e y, \e z, …, in some space and a
|
||
distance function \e d satisfying the metric conditions,
|
||
\f[
|
||
\begin{align}
|
||
d(x,y) &\ge 0,\\
|
||
d(x,y) &= 0, \ \text{iff $x = y$},\\
|
||
d(x,y) &= d(y,x),\\
|
||
d(x,z) &\le d(x,y) + d(y,z),
|
||
\end{align}
|
||
\f]
|
||
the vantage-point (VP) tree provides an efficient way of determining
|
||
nearest neighbors. The geodesic distance (implemented by the Geodesic
|
||
class) satisfies these metric conditions, while the great ellipse
|
||
distance and the rhumb line distance <i>do not</i> (they do not satisfy
|
||
the last condition, the triangle inequality). Typically the cost of
|
||
constructing a VP tree of \e N points is \e N log \e N, while the cost
|
||
of a query is log \e N. Thus a VP tree should be used in situations
|
||
where \e N is large and at least log \e N queries are to be made. The
|
||
condition, \e N is large, should be taken to mean that \f$ N \gg 2^D
|
||
\f$, where \e D is the dimensionality of the space.
|
||
|
||
- This implementation includes Yianilos' upper and lower bounds for the
|
||
inside and outside sets. This helps limit the number of searches
|
||
(compared to just using the median distance).
|
||
- Rather than do a depth-first or breath-first search on the tree, the
|
||
nodes to be processed are put on a priority queue with the nodes most
|
||
likely to contain close points processed first. Frequently, this allows
|
||
nodes lower down on the priority queue to be skipped.
|
||
- This technique also allows non-exhaustive searchs to be performed (to
|
||
answer questions such as "are there any points within 1km of the query
|
||
point?).
|
||
- When building the tree, the first vantage point is (arbitrarily)
|
||
chosen as the middle element of the set. Thereafter, the points
|
||
furthest from the parent vantage point in both the inside and outside
|
||
sets are selected as the children's vantage points. This information
|
||
is already available from the computation of the upper and lower
|
||
bounds of the children. This choice seems to lead to a reasonably
|
||
optimized tree.
|
||
- The leaf nodes can contain a bucket of points (instead of just a vantage
|
||
point).
|
||
- Coincident points are allowed in the set; these are treated as distinct
|
||
points.
|
||
|
||
The figure below shows the construction of the VP tree for the points
|
||
making up the coastlines of Britain and Ireland (about 5000 points shown
|
||
in blue). The set of points is recursively split into 2 equal "inside"
|
||
and "outside" subsets based on the distance from a "vantage point". The
|
||
boundaries between the inside and outside sets are shown as green
|
||
circular arcs (arcs of geodesic circles). At each stage, the newly
|
||
added vantage points are shown as red dots and the vantage points for
|
||
the next stage are shown as red plus signs. The data is shown in the
|
||
Cassini-Soldner projection with a central meridian of 5°W.
|
||
|
||
\image html vptree.gif "Vantage-point tree"
|
||
|
||
<center>
|
||
Back to \ref geodesic. Forward to \ref triaxial. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page triaxial Geodesics on a triaxial ellipsoid
|
||
|
||
<center>
|
||
Back to \ref nearest. Forward to \ref jacobi. Up to \ref contents.
|
||
</center>
|
||
|
||
Jacobi (1839) showed that the problem of geodesics on a triaxial
|
||
ellipsoid (with 3 unequal axes) can be reduced to quadrature. Despite
|
||
this, the detailed behavior of the geodesics is not very well known. In
|
||
this section, I briefly give Jacobi's solution and illustrate the
|
||
behavior of the geodesics and outline an algorithm for the solution of
|
||
the inverse problem.
|
||
|
||
See also
|
||
- The wikipedia page,
|
||
<a href="https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid#Geodesics_on_a_triaxial_ellipsoid">
|
||
Geodesics on a triaxial ellipsoid</a>.
|
||
|
||
Go to
|
||
- \ref triaxial-coords
|
||
- \ref triaxial-jacobi
|
||
- \ref triaxial-survey
|
||
- \ref triaxial-stab
|
||
- \ref triaxial-inverse
|
||
|
||
<b>NOTES</b>
|
||
-# A triaxial ellipsoid approximates the earth only slightly better
|
||
than an ellipsoid of revolution. If you are really considering
|
||
measuring distances on the earth using a triaxial ellipsoid, you
|
||
should also be worrying about the shape of the geoid, which
|
||
essentially makes the geodesic problem a hopeless mess; see, for
|
||
example, <a href="https://arxiv.org/abs/1112.3231"> Waters
|
||
(2011)</a>.
|
||
-# There is nothing new in this section. It is just an exercise in
|
||
exploring Jacobi's solution. My interest here is in generating long
|
||
geodesics with the correct long-time behavior. Arnold gives a
|
||
nice qualitative description of the solution in <i>Mathematical
|
||
Methods of Classical Mechanics</i> (2nd edition, Springer, 1989),
|
||
pp. 264--266.
|
||
-# Possible reasons this problem might, nevertheless, be of interest
|
||
are:
|
||
- It is the first example of a dynamical system which has a
|
||
non-trivial constant of motion. As such, Jacobi's paper generated
|
||
a lot of excitement and was followed by many papers elaborating
|
||
his solution. In particular, the unstable behavior of one of the
|
||
closed geodesics of the ellipsoid, is an early example of a system
|
||
with a positive Lyapunov exponent (one of the essential
|
||
ingredients for chaotic behavior in dynamical systems).
|
||
- Knowledge of ellipsoidal coordinates (used by Jacobi) might be
|
||
useful in other areas of geodesy.
|
||
- Geodesics which pass through the pole on an ellipsoid of revolution
|
||
represent a degenerate class (they are all closed and all pass
|
||
through the opposite pole). It is of interest to see how this
|
||
degeneracy is broken with a surface with a more general shape.
|
||
- Similarly, it is of interest to see how the Mercator projection of
|
||
the ellipsoid generalizes; this is another problem addressed by
|
||
Jacobi.
|
||
-# My interest in this problem was piqued by Jean-Marc Baillard. I put
|
||
him onto Jacobi's solution without having looked at it in detail
|
||
myself; and he quickly implemented the solution for an HP-41
|
||
calculator(!) which is posted
|
||
<a href="http://hp41programs.yolasite.com/geod3axial.php"> here</a>.
|
||
-# I do not give full citations of the papers here. You can find these
|
||
in the
|
||
<a href="https://geographiclib.sourceforge.io/geodesic-papers/biblio.html">
|
||
Geodesic Bibliography</a>; this includes links to online
|
||
versions of the papers.
|
||
-# An alternative to exploring geodesics using Jacobi's solution is to
|
||
integrate the equations for the geodesics directly. This is the
|
||
approach taken by
|
||
<a href="http://www.math.harvard.edu/~knill/caustic/">
|
||
Oliver Knill and Michael Teodorescu</a>. However it is difficult to
|
||
ensure that the long time behavior is correctly modeled with such an
|
||
approach.
|
||
-# At this point, I have no plans to add the solution of triaxial
|
||
geodesic problem to GeographicLib.
|
||
-# If you only want to learn about geodesics on a biaxial ellipsoid (an
|
||
ellipsoid of revolution), then see \ref geodesic or the paper
|
||
- C. F. F. Karney,
|
||
<a href="https://doi.org/10.1007/s00190-012-0578-z">
|
||
Algorithms for geodesics</a>,
|
||
J. Geodesy 87(1), 43--55 (2013);
|
||
DOI: <a href="https://doi.org/10.1007/s00190-012-0578-z">
|
||
10.1007/s00190-012-0578-z</a>;
|
||
addenda: <a href="https://geographiclib.sourceforge.io/geod-addenda.html">
|
||
geod-addenda.html</a>.
|
||
|
||
\section triaxial-coords Triaxial coordinate systems
|
||
|
||
Consider the ellipsoid defined by
|
||
\f[
|
||
f = \frac{X^2}{a^2} + \frac{Y^2}{b^2} + \frac{Z^2}{c^2} = 1,
|
||
\f]
|
||
where, without loss of generality, \f$ a \ge b \ge c \gt 0\f$. A
|
||
point on the surface is specified by a latitude and longitude. The \e
|
||
geographical latitude and longitude \f$(\phi, \lambda)\f$ are defined by
|
||
\f[
|
||
\frac{\nabla f}{\left| \nabla f\right|} = \left(
|
||
\begin{array}{c} \cos\phi \cos\lambda \\ \cos\phi \sin\lambda \\ \sin\phi
|
||
\end{array}\right).
|
||
\f]
|
||
The \e parametric latitude and longitude \f$(\phi', \lambda')\f$ are
|
||
defined by
|
||
\f[
|
||
\begin{align}
|
||
X &= a \cos\phi' \cos\lambda', \\
|
||
Y &= b \cos\phi' \sin\lambda', \\
|
||
Z &= c \sin\phi'.
|
||
\end{align}
|
||
\f]
|
||
Jacobi employed the \e ellipsoidal latitude and longitude \f$(\beta,
|
||
\omega)\f$ defined by
|
||
\f[
|
||
\begin{align}
|
||
X &= a \cos\omega
|
||
\frac{\sqrt{a^2 - b^2\sin^2\beta - c^2\cos^2\beta}}
|
||
{\sqrt{a^2 - c^2}}, \\
|
||
Y &= b \cos\beta \sin\omega, \\
|
||
Z &= c \sin\beta
|
||
\frac{\sqrt{a^2\sin^2\omega + b^2\cos^2\omega - c^2}}
|
||
{\sqrt{a^2 - c^2}}.
|
||
\end{align}
|
||
\f]
|
||
Grid lines of constant \f$\beta\f$ and \f$\omega\f$ are given in Fig. 1.
|
||
|
||
<center>
|
||
<img src="https://upload.wikimedia.org/wikipedia/commons/b/bd/Triaxial_ellipsoid_coordinate_system.svg"
|
||
width=419 height=397 alt="Geodesic grid on a triaxial ellipsoid">
|
||
Fig. 1
|
||
</center>\n
|
||
Fig. 1:
|
||
The ellipsoidal grid. The blue (resp. green) lines are lines of constant
|
||
\f$\beta\f$ (resp. \f$\omega\f$); the grid spacing is 10°. Also
|
||
shown in red are two of the principal sections of the ellipsoid, defined
|
||
by \f$x = 0\f$ and \f$z = 0\f$. The third principal section, \f$y =
|
||
0\f$, is covered by the lines \f$\beta = \pm 90^\circ\f$ and \f$\omega =
|
||
90^\circ \pm 90^\circ\f$. These lines meet at four umbilical points (two
|
||
of which are visible in this figure) where the principal radii of
|
||
curvature are equal. The parameters of the ellipsoid are \f$a =
|
||
1.01\f$, \f$b = 1\f$, \f$c = 0.8\f$, and it is viewed in an orthographic
|
||
projection from a point above \f$\phi = 40^\circ\f$, \f$\lambda =
|
||
30^\circ\f$. These parameters were chosen to accentuate the ellipsoidal
|
||
effects on geodesics (relative to those on the earth) while still
|
||
allowing the connection to an ellipsoid of revolution to be made.
|
||
|
||
The grid lines of the ellipsoid coordinates are "lines of curvature" on
|
||
the ellipsoid, i.e., they are parallel to the direction of principal
|
||
curvature (Monge, 1796). They are also intersections of the ellipsoid
|
||
with confocal systems of hyperboloids of one and two sheets (Dupin,
|
||
1813). Finally they are geodesic ellipses and hyperbolas defined using
|
||
two adjacent umbilical points. For example, the lines of constant
|
||
\f$\beta\f$ in Fig. 1 can be generated with the familiar string
|
||
construction for ellipses with the ends of the string pinned to the two
|
||
umbilical points.
|
||
|
||
The element of length on the ellipsoid in ellipsoidal coordinates is
|
||
given by
|
||
\f[
|
||
\begin{align}
|
||
\frac{ds^2}{(a^2-b^2)\sin^2\omega+(b^2-c^2)\cos^2\beta} &=
|
||
\frac{b^2\sin^2\beta+c^2\cos^2\beta}
|
||
{a^2-b^2\sin^2\beta-c^2\cos^2\beta}
|
||
d\beta^2 \\
|
||
&\qquad+
|
||
\frac{a^2\sin^2\omega+b^2\cos^2\omega}
|
||
{a^2\sin^2\omega+b^2\cos^2\omega-c^2}
|
||
d\omega^2.
|
||
\end{align}
|
||
\f]
|
||
|
||
The torus \f$(\omega, \beta) \in [-\pi,\pi] \times [-\pi,\pi]\f$ covers
|
||
the ellipsoid twice. In order to facilitate passing to the limit of an
|
||
oblate ellipsoid, we may regard as the principal sheet \f$[-\pi,\pi]
|
||
\times [-\frac12\pi,\frac12\pi]\f$ and insert branch cuts at
|
||
\f$\beta=\pm\frac12\pi\f$. The rule for switching sheets is
|
||
\f[
|
||
\begin{align}
|
||
\omega & \rightarrow -\omega,\\
|
||
\beta & \rightarrow \pi-\beta,\\
|
||
\alpha & \rightarrow \pi+\alpha,
|
||
\end{align}
|
||
\f]
|
||
where \f$\alpha\f$ is the heading of a path, relative to a line of
|
||
constant \f$\omega\f$.
|
||
|
||
In the limit \f$b\rightarrow a\f$ (resp. \f$b\rightarrow c\f$), the
|
||
umbilic points converge on the \f$z\f$ (resp. \f$x\f$) axis and an
|
||
oblate (resp. prolate) ellipsoid is obtained with \f$\beta\f$
|
||
(resp. \f$\omega\f$) becoming the standard parametric latitude and
|
||
\f$\omega\f$ (resp. \f$\beta\f$) becoming the standard longitude. The
|
||
sphere is a non-uniform limit, with the position of the umbilic points
|
||
depending on the ratio \f$(a-b)/(b-c)\f$.
|
||
|
||
Inter-conversions between the three different latitudes and longitudes
|
||
and the cartesian coordinates are simple algebraic exercises.
|
||
|
||
\section triaxial-jacobi Jacobi's solution
|
||
|
||
Solving the geodesic problem for an ellipsoid of revolution is, from the
|
||
mathematical point of view, trivial; because of symmetry, geodesics have
|
||
a constant of the motion (analogous to the angular momentum) which was
|
||
found by Clairaut (1733). By 1806 (with the work of Legendre, Oriani,
|
||
et al.), there was a complete understanding of the qualitative behavior
|
||
of geodesics on an ellipsoid of revolution.
|
||
|
||
On the other hand, geodesics on a triaxial ellipsoid have no obvious
|
||
constant of the motion and thus represented a challenging "unsolved"
|
||
problem in the first half of the nineteenth century. Jacobi discovered
|
||
that the geodesic equations are separable if they are expressed in
|
||
ellipsoidal coordinates. You can get an idea of the importance Jacobi
|
||
attached to his discovery from the
|
||
<a href="https://books.google.com/books?id=_09tAAAAMAAJ&pg=PA385">
|
||
letter</a> he wrote to his friend and neighbor Bessel:
|
||
<blockquote> The day before yesterday, I reduced to quadrature the
|
||
problem of geodesic lines on an <i>ellipsoid with three unequal
|
||
axes</i>. They are the simplest formulas in the world, Abelian
|
||
integrals, which become the well known elliptic integrals if 2 axes are
|
||
set equal.\n
|
||
Königsberg, 28th Dec. '38.
|
||
</blockquote>
|
||
|
||
On the same day he wrote a similar letter to the editor of Compte Rendus
|
||
and his result was published in J. Crelle in (1839) with a French
|
||
translation (from German) appearing in J. Liouville in (1841).
|
||
|
||
Here is the solution, exactly as given by Jacobi
|
||
<a href="https://books.google.com/books?id=Rh8GAAAAYAAJ&pg=PA268"> here</a>
|
||
(with minor changes in notation):
|
||
\f[
|
||
\begin{align}
|
||
\delta &= \int \frac
|
||
{\sqrt{b^2\sin^2\beta + c^2\cos^2\beta}\,d\beta}
|
||
{\sqrt{a^2 - b^2\sin^2\beta - c^2\cos^2\beta}
|
||
\sqrt{(b^2-c^2)\cos^2\beta - \gamma}}\\
|
||
&\quad -
|
||
\int \frac
|
||
{\sqrt{a^2\sin^2\omega + b^2\cos^2\omega}\,d\omega}
|
||
{\sqrt{a^2\sin^2\omega + b^2\cos^2\omega - c^2}
|
||
\sqrt{(a^2-b^2)\sin^2\omega + \gamma}}
|
||
\end{align}
|
||
\f]
|
||
As Jacobi notes "a function of the angle \f$\beta\f$ equals a
|
||
function of the angle \f$\omega\f$. These two functions are just
|
||
Abelian integrals…" Two constants \f$\delta\f$ and \f$\gamma\f$
|
||
appear in the solution. Typically \f$\delta\f$ is zero if the lower
|
||
limits of the integrals are taken to be the starting point of the geodesic
|
||
and the direction of the geodesics is determined by \f$\gamma\f$.
|
||
However for geodesics that start at an umbilical points, we have \f$\gamma
|
||
= 0\f$ and \f$\delta\f$ determines the direction at the umbilical point.
|
||
Incidentally the constant \f$\gamma\f$ may be expressed as
|
||
\f[
|
||
\gamma = (b^2-c^2)\cos^2\beta\sin^2\alpha-(a^2-b^2)\sin^2\omega\cos^2\alpha
|
||
\f]
|
||
where \f$\alpha\f$ is the angle the geodesic makes with lines of
|
||
constant \f$\omega\f$. In the limit \f$b\rightarrow a\f$, this reduces
|
||
to \f$\cos\beta\sin\alpha = \text{const.}\f$, the familiar Clairaut
|
||
relation. A nice derivation of Jacobi's result is given by Darboux
|
||
(1894) <a href="https://books.google.com/books?id=hGMSAAAAIAAJ&pg=PA9">
|
||
§§583--584</a> where he gives the solution found by Liouville
|
||
(1846) for general quadratic surfaces. In this formulation, the
|
||
distance along the geodesic, \f$s\f$, is also found using
|
||
\f[
|
||
\begin{align}
|
||
\frac{ds}{(b^2-c^2)\cos^2\beta + (a^2-b^2)\sin^2\omega}
|
||
&= \frac
|
||
{\sqrt{b^2\sin^2\beta + c^2\cos^2\beta}\,d\beta}
|
||
{\sqrt{a^2 - b^2\sin^2\beta - c^2\cos^2\beta}
|
||
\sqrt{(b^2-c^2)\cos^2\beta - \gamma}}\\
|
||
&= \frac
|
||
{\sqrt{a^2\sin^2\omega + b^2\cos^2\omega}\,d\omega}
|
||
{\sqrt{a^2\sin^2\omega + b^2\cos^2\omega - c^2}
|
||
\sqrt{(a^2-b^2)\sin^2\omega + \gamma}}
|
||
\end{align}
|
||
\f]
|
||
An alternative expression for the distance is
|
||
\f[
|
||
\begin{align}
|
||
ds
|
||
&= \frac
|
||
{\sqrt{b^2\sin^2\beta + c^2\cos^2\beta}
|
||
\sqrt{(b^2-c^2)\cos^2\beta - \gamma}\,d\beta}
|
||
{\sqrt{a^2 - b^2\sin^2\beta - c^2\cos^2\beta}}\\
|
||
&\quad {}+ \frac
|
||
{\sqrt{a^2\sin^2\omega + b^2\cos^2\omega}
|
||
\sqrt{(a^2-b^2)\sin^2\omega + \gamma}\,d\omega}
|
||
{\sqrt{a^2\sin^2\omega + b^2\cos^2\omega - c^2}}
|
||
\end{align}
|
||
\f]
|
||
|
||
Jacobi's solution is a convenient way to compute geodesics on an
|
||
ellipsoid. Care must be taken with the signs of the square roots (which
|
||
are determined by the initial azimuth of the geodesic). Also if
|
||
\f$\gamma \gt 0\f$ (resp. \f$\gamma \lt 0\f$), then the \f$\beta\f$
|
||
(resp. \f$\omega\f$) integrand diverges. The integrand can be
|
||
transformed into a finite one by a change of variable, e.g.,
|
||
\f$\sin\beta = \sin\sigma \sqrt{1 - \gamma/(b^2-c^2)}\f$. The resulting
|
||
integrals are periodic, so the behavior of an arbitrarily long geodesic
|
||
is entirely captured by tabulating the integrals over a single period.
|
||
|
||
The situation is more complicated if \f$\gamma = 0\f$ (corresponding to
|
||
umbilical geodesics). Both integrands have simple poles at the umbilical
|
||
points. However, this behavior may be subtracted from the integrands to
|
||
yield (for example) the sum of a term involving
|
||
\f$\tanh^{-1}\sin\beta\f$ and a finite integral. Since both integrals
|
||
contain similar logarithmic singularities they can be equated (thus
|
||
fixing the ratio \f$\cos\beta/\sin\omega\f$ at the umbilical point) and
|
||
connection formulas can be found which allow the geodesic to be followed
|
||
through the umbilical point. The study of umbilical geodesics was of
|
||
special interest to a group of Irish mathematicians in the 1840's and
|
||
1850's, including Michael and William Roberts (twins!), Hart, Graves,
|
||
and Salmon.
|
||
|
||
\section triaxial-survey Survey of triaxial geodesics
|
||
|
||
Before delving into the nature of geodesics on a triaxial geodesic, it
|
||
is worth reviewing geodesics on an ellipsoid of revolution. There are
|
||
two classes of simple closed geodesics (i.e., geodesics which close on
|
||
themselves without intersection): the equator and all the meridians.
|
||
All other geodesics oscillate between two equal and opposite circles of
|
||
latitude; but after completing a full oscillation in latitude these fall
|
||
slightly short (for an oblate ellipsoid) of completing a full circuit in
|
||
longitude.
|
||
|
||
Turning to the triaxial case, we find that there are only 3 simple
|
||
closed geodesics, the three principal sections of the ellipsoid given by
|
||
\f$x = 0\f$, \f$y = 0\f$, and \f$z = 0\f$. To survey the other
|
||
geodesics, it is convenient to consider geodesics which intersect the
|
||
middle principal section, \f$y = 0\f$, at right angles. Such geodesics
|
||
are shown in Figs. 2--6, where I use the same ellipsoid parameters as in
|
||
Fig. 1 and the same viewing direction. In addition, the three principal
|
||
ellipses are shown in red in each of these figures.
|
||
|
||
If the starting point is \f$\beta_1 \in (-90^\circ, 90^\circ)\f$,
|
||
\f$\omega_1 = 0\f$, and \f$\alpha_1 = 90^\circ\f$, then the geodesic
|
||
encircles the ellipsoid in a "circumpolar" sense. The geodesic
|
||
oscillates north and south of the equator; on each oscillation it
|
||
completes slightly less that a full circuit around the ellipsoid
|
||
resulting in the geodesic filling the area bounded by the two latitude
|
||
lines \f$\beta = \pm \beta_1\f$. Two examples are given in
|
||
Figs. 2 and 3. Figure 2 shows practically the same behavior as for an
|
||
oblate ellipsoid of revolution (because \f$a \approx b\f$). However, if
|
||
the starting point is at a higher latitude (Fig. 3) the distortions
|
||
resulting from \f$a \ne b\f$ are evident.
|
||
|
||
<center>
|
||
<img src="https://upload.wikimedia.org/wikipedia/commons/a/a9/Circumpolar_geodesic_on_a_triaxial_ellipsoid_case_A.svg"
|
||
width=419 height=397 alt="Example of a circumpolar geodesic on a
|
||
triaxial ellipsoid">
|
||
Fig. 2
|
||
</center>\n
|
||
Fig. 2:
|
||
Example of a circumpolar geodesic on a triaxial ellipsoid. The starting
|
||
point of this geodesic is \f$\beta_1 = 45.1^\circ\f$, \f$\omega_1 =
|
||
0^\circ\f$, and \f$\alpha_1 = 90^\circ\f$.
|
||
|
||
<center>
|
||
<img src="https://upload.wikimedia.org/wikipedia/commons/f/f3/Circumpolar_geodesic_on_a_triaxial_ellipsoid_case_B.svg"
|
||
width=419 height=397 alt="Another example of a circumpolar geodesic on a
|
||
triaxial ellipsoid">
|
||
Fig. 3
|
||
</center>\n
|
||
Fig. 3:
|
||
Another example of a circumpolar geodesic on a triaxial ellipsoid. The
|
||
starting point of this geodesic is \f$\beta_1 = 87.48^\circ\f$, \f$\omega_1 =
|
||
0^\circ\f$, and \f$\alpha_1 = 90^\circ\f$.
|
||
|
||
If the starting point is \f$\beta_1 = 90^\circ\f$, \f$\omega_1 \in
|
||
(0^\circ, 180^\circ)\f$, and \f$\alpha_1 = 180^\circ\f$, then the geodesic
|
||
encircles the ellipsoid in a "transpolar" sense. The geodesic
|
||
oscillates east and west of the ellipse \f$x = 0\f$; on each oscillation
|
||
it completes slightly more that a full circuit around the ellipsoid
|
||
resulting in the geodesic filling the area bounded by the two longitude
|
||
lines \f$\omega = \omega_1\f$ and \f$\omega = 180^\circ - \omega_1\f$.
|
||
If \f$a = b\f$, all meridians are geodesics; the effect of \f$a \ne b\f$
|
||
causes such geodesics to oscillate east and west. Two examples are
|
||
given in Figs. 4 and 5.
|
||
|
||
<center>
|
||
<img src="https://upload.wikimedia.org/wikipedia/commons/8/83/Transpolar_geodesic_on_a_triaxial_ellipsoid_case_A.svg"
|
||
width=419 height=397 alt="Example of a transpolar geodesic on a
|
||
triaxial ellipsoid">
|
||
Fig. 4
|
||
</center>\n
|
||
Fig. 4:
|
||
Example of a transpolar geodesic on a triaxial ellipsoid. The
|
||
starting point of this geodesic is \f$\beta_1 = 90^\circ\f$, \f$\omega_1 =
|
||
39.9^\circ\f$, and \f$\alpha_1 = 180^\circ\f$.
|
||
|
||
<center>
|
||
<img src="https://upload.wikimedia.org/wikipedia/commons/9/9c/Transpolar_geodesic_on_a_triaxial_ellipsoid_case_B.svg"
|
||
width=419 height=397 alt="Another example of a transpolar geodesic on a
|
||
triaxial ellipsoid">
|
||
Fig. 5
|
||
</center>\n
|
||
Fig. 5:
|
||
Another example of a transpolar geodesic on a triaxial ellipsoid. The
|
||
starting point of this geodesic is \f$\beta_1 = 90^\circ\f$, \f$\omega_1 =
|
||
9.966^\circ\f$, and \f$\alpha_1 = 180^\circ\f$.
|
||
|
||
If the starting point is \f$\beta_1 = 90^\circ\f$, \f$\omega_1 =
|
||
0^\circ\f$ (an umbilical point), and \f$\alpha_1 = 135^\circ\f$ (the
|
||
geodesic leaves the ellipse \f$y = 0\f$ at right angles), then the
|
||
geodesic repeatedly intersects the opposite umbilical point and returns to
|
||
its starting point. However on each circuit the angle at which it
|
||
intersects \f$y = 0\f$ becomes closer to \f$0^\circ\f$ or
|
||
\f$180^\circ\f$ so that asymptotically the geodesic lies on the ellipse
|
||
\f$y = 0\f$. This is shown in Fig. 6. Note that a single geodesic does
|
||
not fill an area on the ellipsoid.
|
||
|
||
<center>
|
||
<img src="https://upload.wikimedia.org/wikipedia/commons/e/e5/Unstable_umbilical_geodesic_on_a_triaxial_ellipsoid.svg"
|
||
width=419 height=397 alt="Example of an umbilical geodesic on a
|
||
triaxial ellipsoid">
|
||
Fig. 6
|
||
</center>\n
|
||
Fig. 6:
|
||
Example of an umbilical geodesic on a triaxial ellipsoid. The
|
||
starting point of this geodesic is \f$\beta_1 = 90^\circ\f$, \f$\omega_1 =
|
||
0^\circ\f$, and \f$\alpha_1 = 135^\circ\f$ and the geodesics is followed
|
||
forwards and backwards until it lies close to the plane \f$y = 0\f$ in
|
||
both directions.
|
||
|
||
Umbilical geodesics enjoy several interesting properties.
|
||
- Through any point on the ellipsoid, there are two umbilical geodesics.
|
||
- The geodesic distance between opposite umbilical points is the same
|
||
regardless of the initial direction of the geodesic.
|
||
- Whereas the closed geodesics on the ellipses \f$x = 0\f$ and \f$z =
|
||
0\f$ are stable (an geodesic initially close to and nearly parallel to
|
||
the ellipse remains close to the ellipse), the closed geodesic on the
|
||
ellipse \f$y = 0\f$, which goes through all 4 umbilical points, is \e
|
||
unstable. If it is perturbed, it will swing out of the plane \f$y =
|
||
0\f$ and flip around before returning to close to the plane. (This
|
||
behavior may repeat depending on the nature of the initial
|
||
perturbation.).
|
||
|
||
\section triaxial-stab The stability of closed geodesics
|
||
|
||
The stability of the three simple closed geodesics can be determined by
|
||
examining the properties of Jacobi's solution. In particular the
|
||
unstable behavior of umbilical geodesics was shown by Hart (1849).
|
||
However an alternative approach is to use the equations that Gauss
|
||
(1828) gives for a perturbed geodesic
|
||
\f[
|
||
\frac {d^2m}{ds^2} + Km = 0
|
||
\f]
|
||
where \f$m\f$ is the distance of perturbed geodesic from a reference
|
||
geodesic and \f$K\f$ is the Gaussian curvature of the surface. If the
|
||
reference geodesic is closed, then this is a linear homogeneous
|
||
differential equation with periodic coefficients. In fact it's a
|
||
special case of Hill's equation which can be treated using Floquet
|
||
theory, see <a href="https://dlmf.nist.gov/28.29">DLMF, §28.29</a>.
|
||
Using the notation of §3 of
|
||
<a href="https://doi.org/10.1007/s00190-012-0578-z"> Algorithms for
|
||
geodesics</a>, the stability is determined by computing the reduced
|
||
length \f$m_{12}\f$ and the geodesic scales \f$M_{12}, M_{21}\f$ over
|
||
half the perimeter of the ellipse and determining the eigenvalues
|
||
\f$\lambda_{1,2}\f$ of
|
||
\f[
|
||
{\cal M} = \left(\begin{array}{cc}
|
||
M_{12} & m_{12}\\
|
||
-\frac{1 - M_{12}M_{21}}{m_{12}} & M_{21}
|
||
\end{array}\right).
|
||
\f]
|
||
Because \f$\mathrm{det}\,{\cal M} = 1\f$, the eigenvalues are determined
|
||
by \f$\mathrm{tr}\,{\cal M}\f$. In particular if
|
||
\f$\left|\mathrm{tr}\,{\cal M}\right| < 2\f$, we have
|
||
\f$\left|\lambda_{1,2}\right| = 1\f$ and the solution is stable; if
|
||
\f$\left|\mathrm{tr}\,{\cal M}\right| > 2\f$, one of
|
||
\f$\left|\lambda_{1,2}\right|\f$ is larger than unity and the solution
|
||
is (exponentially) unstable. In the transition case,
|
||
\f$\left|\mathrm{tr}\,{\cal M}\right| = 2\f$, the solution is stable
|
||
provided that the off-diagonal elements of \f${\cal M}\f$ are zero;
|
||
otherwise the solution is linearly unstable.
|
||
|
||
The exponential instability of the geodesic on the ellipse \f$y = 0\f$
|
||
is confirmed by this analysis and results from the resonance between the
|
||
natural frequency of the equation for \f$m\f$ and the driving frequency
|
||
when \f$b\f$ lies in \f$(c, a)\f$. If \f$b\f$ is equal to either of the
|
||
other axes (and the triaxial ellipsoid degenerates to an ellipsoid of
|
||
revolution), then the solution is linearly unstable. (For example, a
|
||
geodesic is which is close to a meridian on an oblate ellipsoid, slowly
|
||
moves away from that meridian.)
|
||
|
||
\section triaxial-inverse The inverse problem
|
||
|
||
In order to solve the inverse geodesic problem, it helps to have an
|
||
understanding of the properties of all the geodesics emanating from a
|
||
single point \f$(\beta_1, \omega_1)\f$.
|
||
- If the point is an umbilical point, all the lines meet at the
|
||
opposite umbilical point.
|
||
- Otherwise, the first envelope of the geodesics is a 4-pointed
|
||
astroid. The cusps of the astroid lie on either \f$\beta = -
|
||
\beta_1\f$ or \f$\omega = \omega_1 + \pi\f$; see
|
||
<a href="https://doi.org/10.1080/10586458.2003.10504515"> Sinclair
|
||
(2003)</a>.
|
||
- All geodesics intersect (or, in the case of \f$\alpha_1 = 0\f$ or
|
||
\f$\pi\f$, touch) the line \f$\omega = \omega_1 + \pi\f$.
|
||
- All geodesics intersect (or, in the case of \f$\alpha_1 =
|
||
\pm\pi/2\f$, touch) the line \f$\beta = -\beta_1\f$.
|
||
- Two geodesics with azimuths \f$\pm\alpha_1\f$ first intersect on
|
||
\f$\omega = \omega_1 + \pi\f$ and their lengths to the point of
|
||
intersection are equal.
|
||
- Two geodesics with azimuths \f$\alpha_1\f$ and \f$\pi-\alpha_1\f$
|
||
first intersect on \f$\beta = -\beta_1\f$ and their lengths to the
|
||
point of intersection are equal.
|
||
.
|
||
(These assertions follow directly from the equations for the geodesics;
|
||
some of them are somewhat surprising given the asymmetries of the
|
||
ellipsoid.) Consider now terminating the geodesics from \f$(\beta_1,
|
||
\omega_1)\f$ at the point where they first intersect (or touch) the line
|
||
\f$\beta = -\beta_1\f$. To focus the discussion, take \f$\beta_1 \le
|
||
0\f$.
|
||
- The geodesics completely fill the portion of the ellipsoid satisfying
|
||
\f$\beta \le -\beta_1\f$.
|
||
- None of geodesics intersect any other geodesics.
|
||
- Any initial portion of these geodesics is a shortest path.
|
||
- Each geodesic intersects the line \f$\beta = \beta_2\f$, where
|
||
\f$\beta_1 < \beta_2 < -\beta_1\f$, exactly once.
|
||
- For a given \f$\beta_2\f$, this defines a continuous monotonic
|
||
mapping of the circle of azimuths \f$\alpha_1\f$ to the circle of
|
||
longitudes \f$\omega_2\f$.
|
||
- If \f$\beta_2 = \pm \beta_1\f$, then the previous two assertions need
|
||
to be modified similarly to the case for an ellipsoid of revolution.
|
||
|
||
These properties show that the inverse problem can be solved using
|
||
techniques similar to those employed for an ellipsoid of revolution (see
|
||
§4 of
|
||
<a href="https://doi.org/10.1007/s00190-012-0578-z"> Algorithms for
|
||
geodesics</a>).
|
||
- If the points are opposite umbilical points, an arbitrary
|
||
\f$\alpha_1\f$ may be chosen.
|
||
- If the points are neighboring umbilical points, the shortest path
|
||
lies on the ellipse \f$y = 0\f$.
|
||
- If only one point is an umbilicial point, the azimuth at the
|
||
non-umbilical point is found using the generalization of Clairaut's
|
||
equation (given above) with \f$\gamma = 0\f$.
|
||
- Treat the cases where the geodesic might follow a line of constant
|
||
\f$\beta\f$. There are two such cases: (a) the points lie on
|
||
the ellipse \f$z = 0\f$ on a general ellipsoid and (b) the
|
||
points lie on an ellipse whose major axis is the \f$x\f$ axis on a
|
||
prolate ellipsoid (\f$a = b > c\f$). Determine the reduced length
|
||
\f$m_{12}\f$ for the geodesic which is the shorter path along the
|
||
ellipse. If \f$m_{12} \ge 0\f$, then this is the shortest path on
|
||
the ellipsoid; otherwise proceed to the general case (next).
|
||
- Swap the points, if necessary, so that the first point is the one
|
||
closest to a pole. Estimate \f$\alpha_1\f$ (by some means) and solve
|
||
the \e hybrid problem, i.e., determine the longitude \f$\omega_2\f$
|
||
corresponding to the first intersection of the geodesic with \f$\beta
|
||
= \beta_2\f$. Adjust \f$\alpha_1\f$ so that the value of
|
||
\f$\omega_2\f$ matches the given \f$\omega_2\f$ (there is a single
|
||
root). If a sufficiently close solution can be found, Newton's
|
||
method can be employed since the necessary derivative can be
|
||
expressed in terms of the reduced length \f$m_{12}\f$.
|
||
|
||
The shortest path found by this method is unique unless:
|
||
- The length of the geodesic vanishes \f$s_{12}=0\f$, in which case any
|
||
constant can be added to the azimuths.
|
||
- The points are opposite umbilical points. In this case,
|
||
\f$\alpha_1\f$ can take on any value and \f$\alpha_2\f$ needs to be
|
||
adjusted to maintain the value of \f$\tan\alpha_1 / \tan\alpha_2\f$.
|
||
Note that \f$\alpha\f$ increases by \f$\pm 90^\circ\f$ as the
|
||
geodesic passes through an umbilical point, depending on whether the
|
||
geodesic is considered as passing to the right or left of the point.
|
||
Here \f$\alpha_2\f$ is the \e forward azimuth at the second umbilical
|
||
point, i.e., its azimuth immediately \e after passage through the
|
||
umbilical point.
|
||
- \f$\beta_1 + \beta_2 = 0\f$ and \f$\cos\alpha_1\f$ and
|
||
\f$\cos\alpha_2\f$ have opposite signs. In this case, there another
|
||
shortest geodesic with azimuths \f$\pi - \alpha_1\f$ and
|
||
\f$\pi - \alpha_2\f$.
|
||
|
||
\section triaxial-conformal Jacobi's conformal projection
|
||
|
||
This material is now on its own page; see \ref jacobi.
|
||
|
||
<center>
|
||
Back to \ref nearest. Forward to \ref jacobi. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page jacobi Jacobi's conformal projection
|
||
|
||
<center>
|
||
Back to \ref triaxial. Forward to \ref rhumb. Up to \ref contents.
|
||
</center>
|
||
|
||
In addition to solving the geodesic problem for the triaxial ellipsoid,
|
||
Jacobi (1839) briefly mentions the problem of the conformal projection
|
||
of ellipsoid. He covers this in greater detail in
|
||
<a href="https://books.google.com/books?id=ryEOAAAAQAAJ&pg=PA212">
|
||
<i>Vorlesungen über Dynamik</i>, §28</a>, which is now
|
||
available in an <a href="https://www.worldcat.org/oclc/440645889">
|
||
English translation: Lectures on Dynamics</a>
|
||
(<a href="https://geographiclib.sourceforge.io/jacobi-errata.html">
|
||
errata</a>).
|
||
|
||
\section jacobi-conformal Conformal projection
|
||
|
||
It is convenient to rotate Jacobi's ellipsoidal coordinate system so
|
||
that \f$(X,Y,Z)\f$ are respectively the middle, large, and small axes of
|
||
the ellipsoid. The longitude \f$\omega\f$ is shifted so that
|
||
\f$(\beta=0,\omega=0)\f$ is the point \f$(b,0,0)\f$. The coordinates
|
||
are thus defined by
|
||
\f[
|
||
\begin{align}
|
||
X &= b \cos\beta \cos\omega, \\
|
||
Y &= a \sin\omega
|
||
\frac{\sqrt{a^2 - b^2\sin^2\beta - c^2\cos^2\beta}}
|
||
{\sqrt{a^2 - c^2}}, \\
|
||
Z &= c \sin\beta
|
||
\frac{\sqrt{a^2\cos^2\omega + b^2\sin^2\omega - c^2}}
|
||
{\sqrt{a^2 - c^2}}.
|
||
\end{align}
|
||
\f]
|
||
After this change, the large principal ellipse is the equator,
|
||
\f$\beta=0\f$, while the small principal ellipse 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$.
|
||
|
||
Jacobi gives the following conformal mapping of the triaxial ellipsoid
|
||
onto a plane
|
||
\f[
|
||
\begin{align}
|
||
x &= \frac{\sqrt{a^2-c^2}}b \int \frac
|
||
{\sqrt{a^2 \cos^2\omega + b^2 \sin^2\omega}}
|
||
{\sqrt{a^2 \cos^2\omega + b^2 \sin^2\omega - c^2}}\, d\omega, \\
|
||
y &= \frac{\sqrt{a^2-c^2}}b \int \frac
|
||
{\sqrt{b^2 \sin^2\beta + c^2 \cos^2\beta}}
|
||
{\sqrt{a^2 - b^2 \sin^2\beta - c^2 \cos^2\beta}}\, d\beta.
|
||
\end{align}
|
||
\f]
|
||
The scale of the projection is
|
||
\f[
|
||
k = \frac{\sqrt{a^2-c^2}}
|
||
{b\sqrt{a^2 \cos^2\omega + b^2 (\sin^2\omega-\sin^2\beta) - c^2 \cos^2\beta}}.
|
||
\f]
|
||
I have scaled the Jacobi's projection by a constant factor,
|
||
\f[
|
||
\frac{\sqrt{a^2-c^2}}{2b},
|
||
\f]
|
||
so that it reduces to the familiar formulas in the case of an oblate ellipsoid.
|
||
|
||
\section jacobi-elliptic The projection in terms of elliptic integrals
|
||
|
||
The projection may be expressed in terms of elliptic integrals,
|
||
\f[
|
||
\begin{align}
|
||
x&=(1+e_a^2)\,\Pi(\omega',-e_a^2, \cos\nu),\\
|
||
y&=(1-e_c^2)\,\Pi(\beta' , e_c^2, \sin\nu),\\
|
||
k&=\frac{\sqrt{e_a^2+e_c^2}}{b\sqrt{e_a^2\cos^2\omega+e_c^2\cos^2\beta}},
|
||
\end{align}
|
||
\f]
|
||
where
|
||
\f[
|
||
\begin{align}
|
||
e_a &= \frac{\sqrt{a^2-b^2}}b, \qquad
|
||
e_c = \frac{\sqrt{b^2-c^2}}b, \\
|
||
\tan\omega' &= \frac ba \tan\omega = \frac 1{\sqrt{1+e_a^2}} \tan\omega, \\
|
||
\tan\beta' &= \frac bc \tan\beta = \frac 1{\sqrt{1-e_c^2}} \tan\beta, \\
|
||
\tan\nu &= \frac ac \frac{\sqrt{b^2-c^2}}{\sqrt{a^2-b^2}}
|
||
=\frac{e_c}{e_a}\frac{\sqrt{1+e_a^2}}{\sqrt{1-e_c^2}},
|
||
\end{align}
|
||
\f]
|
||
\f$\nu\f$ is the geographic latitude of the umbilic point at \f$\beta =
|
||
\omega = \frac12\pi\f$ (the angle a normal at the umbilic point makes
|
||
with the equatorial plane), and \f$\Pi(\phi,\alpha^2,k)\f$ is the
|
||
elliptic integral of the third kind, https://dlmf.nist.gov/19.2.E7. This
|
||
allows the projection to be numerically computed using
|
||
EllipticFunction::Pi(real phi) const.
|
||
|
||
Nyrtsov, et al.,
|
||
- M. V. Nyrtsov, M. E. Flies, M. M. Borisov, P. J. Stooke,
|
||
<a href="https://doi.org/10.1007/978-3-642-32618-9_17">
|
||
Jacobi conformal projection of the triaxial ellipsoid: new projection
|
||
for mapping of small celestial bodies,</a> in
|
||
<i>Cartography from Pole to Pole</i>
|
||
(Springer, 2014), pp. 235--246.
|
||
.
|
||
also expressed the projection in terms of elliptic integrals.
|
||
However, their expressions don't allow the limits of ellipsoids of
|
||
revolution to be readily recovered. The relations
|
||
https://dlmf.nist.gov/19.7.E5 can be used to put their results in the
|
||
form given here.
|
||
|
||
\section jacobi-properties Properties of the projection
|
||
|
||
\f$x\f$ (resp. \f$y\f$) depends on \f$\omega\f$ (resp. \f$\beta\f$)
|
||
alone, so that latitude-longitude grid maps to straight lines in the
|
||
projection. In this sense, the Jacobi projection is the natural
|
||
generalization of the Mercator projection for the triaxial ellipsoid.
|
||
(See below for the limit \f$a\rightarrow b\f$, which makes this
|
||
connection explicit.)
|
||
|
||
In the general case (all the axes are different), the scale diverges
|
||
only at the umbilic points. The behavior of these singularities is
|
||
illustrated by the complex function
|
||
\f[
|
||
f(z;e) = \cosh^{-1}(z/e) - \log(2/e).
|
||
\f]
|
||
For \f$e > 0\f$, this function has two square root singularities at
|
||
\f$\pm e\f$, corresponding to the two northern umbilic points.
|
||
Plotting contours of its real (resp. imaginary) part gives the
|
||
behavior of the lines of constant latitude (resp. longitude) near the
|
||
north pole in Fig. 1. If we pass to the limit \f$e\rightarrow 0\f$,
|
||
then \f$ f(z;e)\rightarrow\log z\f$, and the two branch points merge
|
||
yielding a stronger (logarithmic) singularity at \f$z = 0\f$,
|
||
concentric circles of latitude, and radial lines of longitude.
|
||
|
||
Again in the general case, the extents of \f$x\f$ and \f$y\f$ are
|
||
finite,
|
||
\f[
|
||
\begin{align}
|
||
x\bigl(\tfrac12\pi\bigr) &=(1+e_a^2)\,\Pi(-e_a^2, \cos\nu),\\
|
||
y\bigl(\tfrac12\pi\bigr) &=(1-e_c^2)\,\Pi(e_c^2, \sin\nu),
|
||
\end{align}
|
||
\f]
|
||
where \f$\Pi(\alpha^2,k)\f$ is the complete elliptic integral of the
|
||
third kind, https://dlmf.nist.gov/19.2.E8.
|
||
|
||
In particular, if we substitute values appropriate for the earth,
|
||
\f[
|
||
\begin{align}
|
||
a&=(6378137+35)\,\mathrm m,\\
|
||
b&=(6378137-35)\,\mathrm m,\\
|
||
c&=6356752\,\mathrm m,\\
|
||
\end{align}
|
||
\f]
|
||
we have
|
||
\f[
|
||
\begin{align}
|
||
x\bigl({\textstyle\frac12}\pi\bigr) &= 1.5720928 = \hphantom{0}90.07428^\circ,\\
|
||
y\bigl({\textstyle\frac12}\pi\bigr) &= 4.2465810 = 243.31117^\circ.\\
|
||
\end{align}
|
||
\f]
|
||
|
||
The projection may be inverted (to give \f$\omega\f$ in terms of \f$x\f$
|
||
and \f$\beta\f$ in terms of \f$y\f$) by using Newton's method to find
|
||
the root of, for example, \f$x(\omega) - x_0 = 0\f$. The derivative of
|
||
the elliptic integral is, of course, just given by its defining
|
||
relation.
|
||
|
||
If rhumb lines are defined as curves with a constant bearing relative
|
||
to the ellipsoid coordinates, then these are straight lines in the
|
||
Jacobi projection. A rhumb line which passes over an umbilic point
|
||
immediately retraces its path. A rhumb line which crosses the line
|
||
joining the two northerly umbilic points starts traveling south with
|
||
a reversed heading (e.g., a NE heading becomes a SW heading). This
|
||
behavior is preserved in the limit \f$a\rightarrow b\f$ (although the
|
||
longitude becomes indeterminate in this limit).
|
||
|
||
\section jacobi-limiting Limiting cases
|
||
|
||
<b>Oblate ellipsoid</b>, \f$a\rightarrow b\f$. The coordinate system
|
||
is
|
||
\f[
|
||
\begin{align}
|
||
X &= b \cos\beta \cos\omega, \\
|
||
Y &= b \cos\beta \sin\omega, \\
|
||
Z &= c \sin\beta.
|
||
\end{align}
|
||
\f]
|
||
Thus \f$\beta\f$ (resp. \f$\beta'\f$) is the parametric
|
||
(resp. geographic) latitude and \f$\omega=\omega'\f$ is the longitude;
|
||
the quantity \f$e_c\f$ is the eccentricity of the ellipsoid.
|
||
Using https://dlmf.nist.gov/19.6.E12 and https://dlmf.nist.gov/19.2.E19
|
||
the projection reduces to the normal Mercator projection for an oblate
|
||
ellipsoid,
|
||
\f[
|
||
\begin{align}
|
||
x &= \omega,\\
|
||
y &= \sinh^{-1}\tan\beta'
|
||
- e_c \tanh^{-1}(e_c\sin\beta'),\\
|
||
k &= \frac1{b\cos\beta}.
|
||
\end{align}
|
||
\f]
|
||
|
||
<b>Prolate ellipsoid</b>, \f$c\rightarrow b\f$. The coordinate system
|
||
is
|
||
\f[
|
||
\begin{align}
|
||
X &= b \cos\omega \cos\beta, \\
|
||
Y &= a \sin\omega, \\
|
||
Z &= b \cos\omega \sin\beta.
|
||
\end{align}
|
||
\f]
|
||
Thus \f$\omega\f$ (resp. \f$\omega'\f$) now plays the role of the
|
||
parametric (resp. geographic) latitude and while \f$\beta=\beta'\f$ is
|
||
the longitude. Using https://dlmf.nist.gov/19.6.E12
|
||
https://dlmf.nist.gov/19.2.E19 and https://dlmf.nist.gov/19.2.E18 the
|
||
projection reduces to similar expressions with the roles of \f$\beta\f$
|
||
and \f$\omega\f$ switched,
|
||
\f[
|
||
\begin{align}
|
||
x &= \sinh^{-1}\tan\omega'
|
||
+ e_a
|
||
\tan^{-1}(e_a\sin\omega'),\\
|
||
y &= \beta,\\
|
||
k &= \frac1{b\cos\omega}.
|
||
\end{align}
|
||
\f]
|
||
|
||
<b>Sphere</b>, \f$a\rightarrow b\f$ and \f$c\rightarrow b\f$. This is a
|
||
non-uniform limit depending on the parameter \f$\nu\f$,
|
||
\f[
|
||
\begin{align}
|
||
X &= b \cos\omega \cos\beta, \\
|
||
Y &= b \sin\omega \sqrt{1 - \sin^2\nu\sin^2\beta}, \\
|
||
Z &= b \sin\beta \sqrt{1 - \cos^2\nu\sin^2\omega}.
|
||
\end{align}
|
||
\f]
|
||
Using https://dlmf.nist.gov/19.6.E13 the projection can be put in terms
|
||
of the elliptic integral of the first kind, https://dlmf.nist.gov/19.2.E4
|
||
\f[
|
||
\begin{align}
|
||
x &= F(\omega, \cos\nu), \\
|
||
y &= F(\beta, \sin\nu), \\
|
||
k &= \frac1{b \sqrt{\cos^2\nu\cos^2\omega + \sin^2\nu\cos^2\beta}}.
|
||
\end{align}
|
||
\f]
|
||
Obtaining the limit of a sphere via an oblate (resp. prolate) ellipsoid
|
||
corresponds to setting \f$\nu = \frac12\pi\f$ (resp. \f$\nu
|
||
=0\f$). In these limits, the elliptic integral reduces to elementary
|
||
functions https://dlmf.nist.gov/19.6.E7 and https://dlmf.nist.gov/19.6.E8
|
||
\f[
|
||
\begin{align}
|
||
F(\phi, 0) &= \phi, \\
|
||
F(\phi, 1) &= \mathop{\mathrm{gd}}\nolimits^{-1}\phi = \sinh^{-1}\tan\phi.
|
||
\end{align}
|
||
\f]
|
||
The spherical limit gives the projection found by É. Guyou in
|
||
- <a href="https://books.google.com/books?id=saBDAQAAIAAJ&pg=PA308">
|
||
Sur un nouveau système de projection de la sphère</a>,
|
||
Comptes Rendus 102(6), 308--310 (1886).
|
||
- <a href="https://books.google.com/books?id=VjU8AQAAMAAJ&pg=PA16">
|
||
Nouveau système de projection de la sphère:
|
||
généralisation de la projection de Mercator</a>,
|
||
Annales Hydrographiques (2nd series) 9, 16--35 (1887).
|
||
.
|
||
who apparently derived it without realizing that it is just a special
|
||
case of the projection Jacobi had given some 40 years earlier. Guyou's
|
||
name is usually associated with the particular choice,
|
||
\f$\nu=\frac14\pi\f$, in which case the hemisphere
|
||
\f$\left|\omega\right|\le\frac12\pi\f$ is mapped into a square.
|
||
However, by varying \f$\nu\in[0,\frac12\pi]\f$ the hemisphere can be
|
||
mapped into a rectangle with any aspect ratio, \f$K(\cos\nu) :
|
||
K(\sin\nu)\f$, where \f$K(k)\f$ is the complete elliptic integral of
|
||
the first find, https://dlmf.nist.gov/19.2.E8.
|
||
|
||
\section jacobi-sphere Conformal mapping of an ellipsoid to a sphere
|
||
|
||
An essential tool in deriving conformal projections of an ellipsoid of
|
||
revolution is the conformal mapping of the ellipsoid onto a sphere.
|
||
This allows conformal projections of the sphere to be generalized to the
|
||
case of an ellipsoid of revolution. This conformal mapping is obtained
|
||
by using the ellipsoidal Mercator projection to map the ellipsoid to
|
||
the plane and then using the spherical Mercator projection to map the
|
||
plane onto the sphere.
|
||
|
||
A similar construction is possible for a triaxial ellipsoid. Map each
|
||
octant of the ellipsoid onto a rectangle using the Jacobi projection.
|
||
The aspect ratio of this rectangle is
|
||
\f[
|
||
(1+e_a^2)\,\Pi(-e_a^2, \cos\nu) :
|
||
(1-e_c^2)\,\Pi( e_c^2, \sin\nu).
|
||
\f]
|
||
Find the value of \f$\nu'\f$ such that this ratio equals
|
||
\f[
|
||
K(\cos\nu') : K(\sin\nu').
|
||
\f]
|
||
Map the rectangle onto the equivalent octant of the sphere using Guyou's
|
||
projection with parameter \f$\nu = \nu'\f$. This reduces to the
|
||
standard construction in the limit of an ellipsoid of revolution.
|
||
|
||
\section jacobi-implementation An implementation of the projection
|
||
|
||
The JacobiConformal class provides an implementation of the Jacobi
|
||
conformal projection is given here. <b>NOTE:</b> This is just sample
|
||
code. It is not part of GeographicLib itself.
|
||
|
||
<center>
|
||
Back to \ref triaxial. Forward to \ref rhumb. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page rhumb Rhumb lines
|
||
|
||
<center>
|
||
Back to \ref jacobi. Forward to \ref greatellipse. Up to \ref contents.
|
||
</center>
|
||
|
||
The Rhumb and RhumbLine classes together with the
|
||
<a href="RhumbSolve.1.html">RhumbSolve</a> utility perform rhumb line
|
||
calculations. A rhumb line (also called a loxodrome) is a line of
|
||
constant azimuth on the surface of the ellipsoid. It is important for
|
||
historical reasons because sailing with a constant compass heading is
|
||
simpler than sailing the shorter geodesic course; see Osborne (2013).
|
||
The formulation of the problem on an ellipsoid is covered by Smart
|
||
(1946) and Carlton-Wippern (1992). Computational approaches are given
|
||
by Williams (1950) and Bennett (1996). My interest in this problem was
|
||
piqued by Botnev and Ustinov (2014) who discuss various techniques to
|
||
improve the accuracy of rhumb line calculations. The items of interest
|
||
here are:
|
||
- Review of accurate formulas for the auxiliary latitudes.
|
||
- The calculation of the area under a rhumb line.
|
||
- Using divided differences to compute \f$\mu_{12}/\psi_{12}\f$
|
||
maintaining full accuracy. Two cases are treated:
|
||
- If \f$f\f$ is small, Krüger's series for the transverse
|
||
Mercator projection relate \f$\chi\f$ and \f$\mu\f$.
|
||
- For arbitrary \f$f\f$, the divided difference formula for
|
||
incomplete elliptic integrals of the second relates \f$\beta\f$ and
|
||
\f$\mu\f$.
|
||
.
|
||
- Extending Clenshaw summation to compute the divided difference of a
|
||
trigonometric sum.
|
||
|
||
Go to
|
||
- \ref rhumbform
|
||
- \ref rhumblat
|
||
- \ref rhumbarea
|
||
- \ref divideddiffs
|
||
- \ref dividedclenshaw
|
||
|
||
References:
|
||
- G. G. Bennett,
|
||
<a href="https://doi.org/10.1017/S0373463300013151">
|
||
Practical Rhumb Line Calculations on the Spheroid</a>
|
||
J. Navigation 49(1), 112--119 (1996).
|
||
- F. W. Bessel,
|
||
<a href="https://doi.org/10.1002/asna.201011352">The calculation
|
||
of longitude and latitude from geodesic measurements (1825)</a>,
|
||
Astron. Nachr. 331(8), 852--861 (2010);
|
||
translated by C. F. F. Karney and R. E. Deakin; preprint:
|
||
<a href="https://arxiv.org/abs/0908.1824">arXiv:0908.1824</a>.
|
||
- V.A. Botnev, S.M. Ustinov,
|
||
<a href="http://ntv.spbstu.ru/fulltext/T3.198.2014_05.PDF">
|
||
Metody resheniya pryamoy i obratnoy geodezicheskikh zadach s vysokoy
|
||
tochnost'yu
|
||
</a> (Methods for direct and inverse geodesic problems
|
||
solving with high precision), St. Petersburg State Polytechnical
|
||
University Journal 3(198), 49--58 (2014).
|
||
- K. C. Carlton-Wippern
|
||
<a href="https://doi.org/10.1017/S0373463300010791">
|
||
On Loxodromic Navigation</a>,
|
||
J. Navigation 45(2), 292--297 (1992).
|
||
- K. E. Engsager and K. Poder,
|
||
<a href="http://icaci.org/files/documents/ICC_proceedings/ICC2007/documents/doc/THEME 2/oral 1/2.1.2 A HIGHLY ACCURATE WORLD WIDE ALGORITHM FOR THE TRANSVE.doc">
|
||
A highly accurate world wide algorithm for the
|
||
transverse Mercator mapping (almost)</a>,
|
||
Proc. XXIII Intl. Cartographic Conf. (ICC2007), Moscow (2007).
|
||
- F. R. Helmert,
|
||
<a href="https://doi.org/10.5281/zenodo.32050">
|
||
Mathematical and Physical Theories of Higher Geodesy, Part 1 (1880)</a>,
|
||
Aeronautical Chart and Information Center (St. Louis, 1964),
|
||
Chaps. 5--7.
|
||
- W. M. Kahan and R. J. Fateman,
|
||
<a href="https://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf">
|
||
Symbolic computation of divided differences</a>,
|
||
SIGSAM Bull. 33(2), 7--28 (1999)
|
||
DOI: <a href="https://doi.org/10.1145/334714.334716">
|
||
10.1145/334714.334716</a>.
|
||
- C. F. F. Karney,
|
||
<a href="https://doi.org/10.1007/s00190-011-0445-3">
|
||
Transverse Mercator with an accuracy of a few nanometers</a>,
|
||
J. Geodesy 85(8), 475--485 (Aug. 2011);
|
||
addenda: <a href="https://geographiclib.sourceforge.io/tm-addenda.html">
|
||
tm-addenda.html</a>;
|
||
preprint:
|
||
<a href="https://arxiv.org/abs/1002.1417"> arXiv:1002.1417</a>;
|
||
resource page:
|
||
<a href="https://geographiclib.sourceforge.io/tm.html"> tm.html</a>.
|
||
- C. F. F. Karney,
|
||
<a href="https://doi.org/10.1007/s00190-012-0578-z">
|
||
Algorithms for geodesics</a>,
|
||
J. Geodesy 87(1), 43--55 (2013);
|
||
DOI: <a href="https://doi.org/10.1007/s00190-012-0578-z">
|
||
10.1007/s00190-012-0578-z</a>;
|
||
addenda: <a href="https://geographiclib.sourceforge.io/geod-addenda.html">
|
||
geod-addenda.html</a>;
|
||
resource page:
|
||
<a href="https://geographiclib.sourceforge.io/geod.html"> geod.html</a>.
|
||
- L. Krüger,
|
||
<a href="https://doi.org/10.2312/GFZ.b103-krueger28"> Konforme
|
||
Abbildung des Erdellipsoids in der Ebene</a> (Conformal mapping of
|
||
the ellipsoidal earth to the plane), Royal Prussian Geodetic Institute,
|
||
New Series 52, 172 pp. (1912).
|
||
- P. Osborne,
|
||
<a href="https://doi.org/10.5281/zenodo.35392">
|
||
The Mercator Projections</a> (2013), §2.5 and §6.5;
|
||
DOI: <a href="https://doi.org/10.5281/zenodo.35392">
|
||
10.5281/zenodo.35392</a>.
|
||
- W. M. Smart
|
||
<a href="https://doi.org/10.1093/mnras/106.2.124">
|
||
On a Problem in Navigation</a>
|
||
MNRAS 106(2), 124--127 (1946).
|
||
- J. E. D. Williams
|
||
<a href="https://doi.org/10.1017/S0373463300045549">
|
||
Loxodromic Distances on the Terrestrial Spheroid Journal</a>,
|
||
J. Navigation 3(2), 133--140 (1950)
|
||
|
||
\section rhumbform Formulation of the rhumb line problem
|
||
|
||
The rhumb line can formulated in terms of three types of latitude, the
|
||
isometric latitude \f$\psi\f$ (this serves to define the course of rhumb
|
||
lines), the rectifying latitude \f$\mu\f$ (needed for computing
|
||
distances along rhumb lines), and the parametric latitude \f$\beta\f$
|
||
(needed for dealing with rhumb lines that run along a parallel). These
|
||
are defined in terms of the geographical latitude \f$\phi\f$ by
|
||
\f[
|
||
\begin{align}
|
||
\frac{d\psi}{d\phi} &= \frac{\rho}R, \\
|
||
\frac{d\mu}{d\phi} &= \frac{\pi}{2M}\rho, \\
|
||
\end{align}
|
||
\f]
|
||
where \f$\rho\f$ is the meridional radius of curvature, \f$R =
|
||
a\cos\beta\f$ is the radius of a circle of latitude, and \f$M\f$ is the
|
||
length of a quarter meridian (from the equator to the pole).
|
||
|
||
Rhumb lines are straight in the Mercator projection, which maps a point
|
||
with geographical coordinates \f$ (\phi,\lambda) \f$ on the ellipsoid to
|
||
a point \f$ (\psi,\lambda) \f$. The azimuth \f$\alpha_{12}\f$ of a
|
||
rhumb line from \f$ (\phi_1,\lambda_1) \f$ to \f$ (\phi_2,\lambda_2) \f$
|
||
is thus given by
|
||
\f[
|
||
\tan\alpha_{12} = \frac{\lambda_{12}}{\psi_{12}},
|
||
\f]
|
||
where the quadrant of \f$\alpha_{12}\f$ is determined by the signs of
|
||
the numerator and denominator of the right-hand side, \f$\lambda_{12} =
|
||
\lambda_2 - \lambda_1\f$, \f$\psi_{12} = \psi_2 - \psi_1\f$, and,
|
||
typically, \f$\lambda_{12}\f$ is reduced to the range \f$[-\pi,\pi]\f$
|
||
(thus giving the course of the <i>shortest</i> rhumb line).
|
||
|
||
The distance is given by
|
||
\f[
|
||
\begin{align}
|
||
s_{12} &= \frac {2M}{\pi} \mu_{12} \sec\alpha_{12} \\
|
||
&= \frac {2M}{\pi}
|
||
\frac{\mu_{12}}{\psi_{12}} \sqrt{\lambda_{12}^2 + \psi_{12}^2},
|
||
\end{align}
|
||
\f]
|
||
where \f$\mu_{12} = \mu_2 - \mu_1\f$. This relation is indeterminate if
|
||
\f$\phi_1 = \phi_2\f$, so we take the limits
|
||
\f$\psi_{12}\rightarrow0\f$ and \f$\mu_{12}\rightarrow0\f$ and apply
|
||
L'Hôpital's rule to yield
|
||
\f[
|
||
\begin{align}
|
||
s_{12} &= \frac {2M}{\pi} \frac{d\mu}{d\psi} \left|\lambda_{12}\right|\\
|
||
&=a \cos\beta \left|\lambda_{12}\right|,
|
||
\end{align}
|
||
\f]
|
||
where the last relation is given by the defining equations for
|
||
\f$\psi\f$ and \f$\mu\f$.
|
||
|
||
This provides a complete solution for rhumb lines. This formulation
|
||
entirely encapsulates the ellipsoidal shape of the earth via the
|
||
\ref auxlat; thus in the Rhumb class, the ellipsoidal
|
||
generalization is handled by the Ellipsoid class where the auxiliary
|
||
latitudes are defined.
|
||
|
||
\section rhumblat Determining the auxiliary latitudes
|
||
|
||
Here we brief develop the necessary formulas for the \ref auxlat.
|
||
|
||
<b>Isometric latitude:</b> The equation for \f$\psi\f$ can be integrated
|
||
to give
|
||
\f[
|
||
\psi = \sinh^{-1}\tan\phi - e\tanh^{-1}(e \sin\phi),
|
||
\f]
|
||
where \f$e = \sqrt{f(2-f)}\f$ is the eccentricity of the ellipsoid. To
|
||
invert this equation (to give \f$\phi\f$ in terms of \f$\psi\f$), it is
|
||
convenient to introduce the variables \f$\tau=\tan\phi\f$ and \f$\tau' =
|
||
\tan\chi = \sinh\psi\f$ (\f$\chi\f$ is the conformal latitude) which are
|
||
related by (Karney, 2011)
|
||
\f[
|
||
\begin{align}
|
||
\tau' &= \tau \sqrt{1 + \sigma^2} - \sigma \sqrt{1 + \tau^2}, \\
|
||
\sigma &= \sinh\bigl(e \tanh^{-1}(e \tau/\sqrt{1 + \tau^2}) \bigr).
|
||
\end{align}
|
||
\f]
|
||
The equation for \f$\tau'\f$ can be inverted to give \f$\tau\f$ in terms
|
||
of \f$\tau'\f$ using Newton's method with \f$\tau_0 = \tau'/(1-e^2)\f$
|
||
as a starting guess; and, of course, \f$\phi\f$ and \f$\psi\f$ are then
|
||
given by
|
||
\f[
|
||
\begin{align}
|
||
\phi &= \tan^{-1}\tau,\\
|
||
\psi &= \sinh^{-1}\tau'.
|
||
\end{align}
|
||
\f]
|
||
This allows conversions to and from \f$\psi\f$ to be carried out for any
|
||
value of the flattening \f$f\f$; these conversions are implemented by
|
||
Ellipsoid::IsometricLatitude and Ellipsoid::InverseIsometricLatitude.
|
||
(For prolate ellipsoids, \f$f\f$ is negative and \f$e\f$ is imaginary,
|
||
and the equation for \f$\sigma\f$ needs to be recast in terms of the
|
||
tangent function.)
|
||
|
||
For small values of \f$f\f$, Engsager and Poder (2007) express
|
||
\f$\chi\f$ as a trigonometric series in \f$\phi\f$. This series can be
|
||
reverted to give a series for \f$\phi\f$ in terms of \f$\chi\f$. Both
|
||
series can be efficiently evaluated using Clenshaw summation and this
|
||
provides a fast non-iterative way of making the conversions.
|
||
|
||
<b>Parametric latitude:</b> This is given by
|
||
\f[
|
||
\tan\beta = (1-f)\tan\phi,
|
||
\f]
|
||
which allows rapid and accurate conversions; these conversions are
|
||
implemented by Ellipsoid::ParametricLatitude and
|
||
Ellipsoid::InverseParametricLatitude.
|
||
|
||
<b>Rectifying latitude:</b> Solving for distances on the meridian is
|
||
naturally carried out in terms of the parametric latitude instead of the
|
||
geographical latitude. This leads to a simpler elliptic integral which
|
||
is easier to evaluate and to invert. Helmert (1880, §5.11) notes
|
||
that the series for meridian distance in terms of \f$\beta\f$ converge
|
||
faster than the corresponding ones in terms of \f$\phi\f$.
|
||
|
||
In terms of \f$\beta\f$, the rectifying latitude is given by
|
||
\f[
|
||
\mu = \frac{\pi}{2E(ie')} E(\beta,ie'),
|
||
\f]
|
||
where \f$e'=e/\sqrt{1-e^2}\f$ is the second eccentricity and \f$E(k)\f$
|
||
and \f$E(\phi,k)\f$ are the complete and incomplete elliptic integrals
|
||
of the second kind; see https://dlmf.nist.gov/19.2.ii. These can be
|
||
evaluated accurately for arbitrary flattening using the method given in
|
||
https://dlmf.nist.gov/19.36.i. To find \f$\beta\f$ in terms of
|
||
\f$\mu\f$, Newton's method can be used (noting that \f$dE(\phi,k)/d\phi
|
||
= \sqrt{1 - k^2\sin^2\phi}\f$); for a starting guess use \f$\beta_0 =
|
||
\mu\f$ (or use the first terms in the reverted series; see below).
|
||
These conversions are implemented by Ellipsoid::RectifyingLatitude and
|
||
Ellipsoid::InverseRectifyingLatitude.
|
||
|
||
If the flattening is small, \f$\mu\f$ can be expressed as a series in
|
||
various ways. The most economical series is in terms of the third
|
||
flattening \f$ n = f/(2-f)\f$ and was found by Bessel (1825); see
|
||
Eq. 5.5.7 of Helmert (1880). Helmert (1880, Eq. 5.6.8) also gives the
|
||
reverted series (finding \f$\beta\f$ given \f$\mu\f$). These series are
|
||
used by the Geodesic class where the coefficients are \f$C_{1j}\f$ and
|
||
\f$C_{1j}'\f$; see Eqs. (18) and (21) of Karney (2013) and \ref
|
||
geodseries. (Make the replacements, \f$\sigma\rightarrow\beta\f$,
|
||
\f$\tau\rightarrow\mu\f$, \f$\epsilon\rightarrow n\f$, to convert the
|
||
notation of the geodesic problem to the problem at hand.) The series
|
||
are evaluated by Clenshaw summation.
|
||
|
||
These relations allow inter-conversions between the various latitudes
|
||
\f$\phi\f$, \f$\psi\f$, \f$\chi\f$, \f$\beta\f$, \f$\mu\f$ to be carried
|
||
out simply and accurately. The approaches using series apply only if
|
||
\f$f\f$ is small. The others apply for arbitrary values of \f$f\f$.
|
||
|
||
\section rhumbarea The area under a rhumb line
|
||
|
||
The area between a rhumb line and the equator is given by
|
||
\f[
|
||
S_{12} = \int_{\lambda_1}^{\lambda_2} c^2 \sin\xi \,d\lambda,
|
||
\f]
|
||
where \f$c\f$ is the authalic radius and \f$\xi\f$ is the authalic
|
||
latitude. Express \f$\sin\xi\f$ in terms of the conformal latitude
|
||
\f$\chi\f$ and expand as a series in the third flattening \f$n\f$. This
|
||
can be expressed in terms of powers of \f$\sin\chi\f$. Substitute
|
||
\f$\sin\chi=\tanh\psi\f$, where \f$\psi\f$ is the isometric latitude.
|
||
For a rhumb line we have
|
||
\f[
|
||
\begin{align}
|
||
\psi &= m(\lambda-\lambda_0),\\
|
||
m &= \frac{\psi_2 - \psi_1}{\lambda_2 - \lambda_1}.
|
||
\end{align}
|
||
\f]
|
||
Performing the integral over \f$\lambda\f$ gives
|
||
\f[
|
||
S_{12} = c^2 \lambda_{12} \left<\sin\xi\right>_{12},
|
||
\f]
|
||
where \f$\left<\sin\xi\right>_{12}\f$ is the mean value of \f$\sin\xi\f$
|
||
given by
|
||
\f[
|
||
\begin{align}
|
||
\left<\sin\xi\right>_{12} &= \frac{S(\chi_2) - S(\chi_1)}{\psi_2 - \psi_1},\\
|
||
S(\chi) &= \log\sec\chi + \sum_{l=1} R_l\cos(2l\chi),
|
||
\end{align}
|
||
\f]
|
||
\f$\log\f$ is the natural logarithm, and \f$R_l = O(n^l)\f$ is given as
|
||
a series in \f$n\f$ below. In the spherical limit, the sum vanishes.
|
||
|
||
Note the simple way that longitude enters into the expression for the
|
||
area. In the limit \f$\chi_2 \rightarrow \chi_1\f$, we can apply
|
||
l'Hôpital's rule
|
||
\f[
|
||
\left<\sin\xi\right>_{12}
|
||
\rightarrow \frac{dS(\chi_1)/d\chi_1}{\sec\chi_1}
|
||
=\sin\xi_1,
|
||
\f]
|
||
as expected.
|
||
|
||
In order to maintain accuracy, particularly for rhumb lines which nearly
|
||
follow a parallel, evaluate \f$\left<\sin\xi\right>_{12}\f$ using
|
||
divided differences (see the \ref divideddiffs "next section") and use
|
||
Clenshaw summation to evaluate the sum (see the \ref dividedclenshaw
|
||
"last section").
|
||
|
||
Here is the series expansion accurate to 10th order, found by the Maxima
|
||
script <a href="rhumbarea.mac">rhumbarea.mac</a>:
|
||
|
||
\verbatim
|
||
R[1] = - 1/3 * n
|
||
+ 22/45 * n^2
|
||
- 356/945 * n^3
|
||
+ 1772/14175 * n^4
|
||
+ 41662/467775 * n^5
|
||
- 114456994/638512875 * n^6
|
||
+ 258618446/1915538625 * n^7
|
||
- 1053168268/37574026875 * n^8
|
||
- 9127715873002/194896477400625 * n^9
|
||
+ 33380126058386/656284056553125 * n^10;
|
||
R[2] = - 2/15 * n^2
|
||
+ 106/315 * n^3
|
||
- 1747/4725 * n^4
|
||
+ 18118/155925 * n^5
|
||
+ 51304574/212837625 * n^6
|
||
- 248174686/638512875 * n^7
|
||
+ 2800191349/14801889375 * n^8
|
||
+ 10890707749202/64965492466875 * n^9
|
||
- 3594078400868794/10719306257034375 * n^10;
|
||
R[3] = - 31/315 * n^3
|
||
+ 104/315 * n^4
|
||
- 23011/51975 * n^5
|
||
+ 1554472/14189175 * n^6
|
||
+ 114450437/212837625 * n^7
|
||
- 8934064508/10854718875 * n^8
|
||
+ 4913033737121/21655164155625 * n^9
|
||
+ 591251098891888/714620417135625 * n^10;
|
||
R[4] = - 41/420 * n^4
|
||
+ 274/693 * n^5
|
||
- 1228489/2027025 * n^6
|
||
+ 3861434/42567525 * n^7
|
||
+ 1788295991/1550674125 * n^8
|
||
- 215233237178/123743795175 * n^9
|
||
+ 95577582133463/714620417135625 * n^10;
|
||
R[5] = - 668/5775 * n^5
|
||
+ 1092376/2027025 * n^6
|
||
- 3966679/4343625 * n^7
|
||
+ 359094172/10854718875 * n^8
|
||
+ 7597613999411/3093594879375 * n^9
|
||
- 378396252233936/102088631019375 * n^10;
|
||
R[6] = - 313076/2027025 * n^6
|
||
+ 4892722/6081075 * n^7
|
||
- 1234918799/834978375 * n^8
|
||
- 74958999806/618718975875 * n^9
|
||
+ 48696857431916/9280784638125 * n^10;
|
||
R[7] = - 3189007/14189175 * n^7
|
||
+ 930092876/723647925 * n^8
|
||
- 522477774212/206239658625 * n^9
|
||
- 2163049830386/4331032831125 * n^10;
|
||
R[8] = - 673429061/1929727800 * n^8
|
||
+ 16523158892/7638505875 * n^9
|
||
- 85076917909/18749059875 * n^10;
|
||
R[9] = - 39191022457/68746552875 * n^9
|
||
+ 260863656866/68746552875 * n^10;
|
||
R[10] = - 22228737368/22915517625 * n^10;
|
||
\endverbatim
|
||
|
||
\section divideddiffs Use of divided differences
|
||
|
||
Despite our ability to compute latitudes accurately, the way that
|
||
distances enter into the solution involves the ratio
|
||
\f$\mu_{12}/\psi_{12}\f$; the numerical calculation of this term is
|
||
subject to catastrophic round-off errors when \f$\phi_1\f$ and
|
||
\f$\phi_2\f$ are close. A simple solution, suggested by Bennett (1996),
|
||
is to extend the treatment of rhumb lines along parallels to this case,
|
||
i.e., to replace the ratio by the derivative evaluated at the midpoint.
|
||
However this is not entirely satisfactory: you have to pick the
|
||
transition point where the derivative takes over from the ratio of
|
||
differences; and, near this transition point, many bits of accuracy will
|
||
be lost (I estimate that about 1/3 of bits are lost, leading to errors
|
||
on the order of 0.1 mm for double precision). Note too that this
|
||
problem crops up even in the spherical limit.
|
||
|
||
It turns out that we can do substantially better than this and maintain
|
||
full double precision accuracy. Indeed Botnev and Ustinov provide
|
||
formulas which allow \f$\mu_{12}/\psi_{12}\f$ to be computed accurately
|
||
(but the formula for \f$\mu_{12}\f$ applies only for small flattening).
|
||
|
||
Here I give a more systematic treatment using the algebra of <i>divided
|
||
differences</i>. Many readers will be already using this technique,
|
||
e.g., when writing, for example,
|
||
\f[
|
||
\frac{\sin(2x) - \sin(2y)}{x-y} = 2\frac{\sin(x-y)}{x-y}\cos(x+y).
|
||
\f]
|
||
However, Kahan and Fateman (1999) provide an extensive set of rules
|
||
which allow the technique to be applied to a wide range of problems.
|
||
(The classes LambertConformalConic and AlbersEqualArea use this
|
||
technique to improve the accuracy.)
|
||
|
||
To illustrate the technique, consider the relation between \f$\psi\f$
|
||
and \f$\chi\f$,
|
||
\f[
|
||
\psi = \sinh^{-1}\tan\chi.
|
||
\f]
|
||
The divided difference operator is defined by
|
||
\f[
|
||
\Delta[f](x,y) =
|
||
\begin{cases}
|
||
df(x)/dx, & \text{if $x=y$,} \\
|
||
\displaystyle\frac{f(x)-f(y)}{x-y}, & \text{otherwise.}
|
||
\end{cases}
|
||
\f]
|
||
Many of the rules for differentiation apply to divided differences; in
|
||
particular, we can use the chain rule to write
|
||
\f[
|
||
\frac{\psi_1 - \psi_2}{\chi_1 - \chi_2}
|
||
= \Delta[\sinh^{-1}](\tan\chi_1,\tan\chi_2) \times
|
||
\Delta[\tan](\chi_1,\chi_2).
|
||
\f]
|
||
|
||
Kahan and Fateman catalog the divided difference formulas for all the
|
||
elementary functions. In this case, we need
|
||
\f[
|
||
\begin{align}
|
||
\Delta[\tan](x,y) &= \frac{\tan(x-y)}{x-y} (1 + \tan x\tan y),\\
|
||
\Delta[\sinh^{-1}](x,y) &= \frac1{x-y}
|
||
\sinh^{-1}\biggl(\frac{(x-y)(x+y)}{x\sqrt{1+y^2}+y\sqrt{1+x^2}}\biggr).
|
||
\end{align}
|
||
\f]
|
||
The crucial point in these formulas is that the right hand sides can be
|
||
evaluated accurately even if \f$x-y\f$ is small. (I've only included
|
||
the basic results here; Kahan and Fateman supplement these with the
|
||
derivatives if \f$x-y\f$ vanishes or the direct ratios if \f$x-y\f$ is
|
||
not small.)
|
||
|
||
To complete the computation of \f$\mu_{12}/\psi_{12}\f$, we now need
|
||
\f$(\mu_1 - \mu_2)/(\chi_1 - \chi_2)\f$, i.e., we need the divided
|
||
difference of the function that converts the conformal latitude to
|
||
rectifying latitude. We could go through the chain of relations between
|
||
these quantities. However, we can take a short cut and recognize that
|
||
this function was given as a trigonometric series by Krüger (1912)
|
||
in his development of the transverse Mercator projection. This is also
|
||
given by Eqs. (5) and (35) of Karney (2011) with the replacements
|
||
\f$\zeta \rightarrow \mu\f$ and \f$\zeta' \rightarrow \chi\f$. The
|
||
coefficients appearing in this series and the reverted series Eqs. (6)
|
||
and (36) are already computed by the TransverseMercator class. The
|
||
series can be readily converted to divided difference form (see the
|
||
example at the beginning of this section) and Clenshaw summation can be
|
||
used to evaluate it (see below).
|
||
|
||
The approach of using the series for the transverse Mercator projection
|
||
limits the applicability of the method to \f$\left|f\right|\lt 0.01\f$.
|
||
If we want to extend the method to arbitrary flattening we need to
|
||
compute \f$\Delta[E](x,y;k)\f$. The necessary relation is the "addition
|
||
theorem" for the incomplete elliptic integral of the second kind given
|
||
in https://dlmf.nist.gov/19.11.E2. This can be converted in the
|
||
following divided difference formula
|
||
\f[
|
||
\Delta[E](x,y;k)
|
||
=\begin{cases}
|
||
\sqrt{1 - k^2\sin^2x}, & \text{if $x=y$,} \\
|
||
\displaystyle \frac{E(x,k)-E(y,k)}{x-y}, & \text{if $xy \le0$,}\\
|
||
\displaystyle
|
||
\biggl(\frac{E(z,k)}{\sin z} - k^2 \sin x \sin y\biggr)\frac{\sin z}{x-y},
|
||
&\text{otherwise,}
|
||
\end{cases}
|
||
\f]
|
||
where the angle \f$z\f$ is given by
|
||
\f[
|
||
\begin{align}
|
||
\sin z &= \frac{2t}{1 + t^2},\quad\cos z = \frac{(1-t)(1+t)}{1 + t^2},\\
|
||
t &=
|
||
\frac{(x-y)\Delta[\sin](x,y)}
|
||
{\sin x\sqrt{1 - k^2\sin^2y} + \sin y\sqrt{1 - k^2\sin^2x}}
|
||
\frac{\sin x + \sin y}{\cos x + \cos y}.
|
||
\end{align}
|
||
\f]
|
||
We also need to apply the divided difference formulas to the conversions
|
||
from \f$\phi\f$ to \f$\beta\f$ and \f$\phi\f$ to \f$\psi\f$; but these
|
||
all involve elementary functions and the techniques given in Kahan and
|
||
Fateman can be used.
|
||
|
||
The end result is that the Rhumb class allows the computation of all
|
||
rhumb lines for any flattening with full double precision accuracy (the
|
||
maximum error is about 10 nanometers). I've kept the implementation
|
||
simple, which results in rather a lot of repeated evaluations of
|
||
quantities. However, in this case, the need for clarity trumps the
|
||
desire for speed.
|
||
|
||
\section dividedclenshaw Clenshaw evaluation of differenced sums
|
||
|
||
The use of
|
||
<a href="https://en.wikipedia.org/wiki/Clenshaw_algorithm#Meridian_arc_length_on_the_ellipsoid">
|
||
Clenshaw summation</a> for summing series of the form,
|
||
\f[
|
||
g(x) = \sum_{k=1}^N c_k \sin kx,
|
||
\f]
|
||
is well established. However when computing divided differences, we are
|
||
interested in evaluating
|
||
\f[
|
||
g(x)-g(y) = \sum_{k=1}^N 2 c_k
|
||
\sin\bigl({\textstyle\frac12}k(x-y)\bigr)
|
||
\cos\bigl({\textstyle\frac12}k(x+y)\bigr).
|
||
\f]
|
||
Clenshaw summation can be used in this case if we simultaneously compute
|
||
\f$g(x)+g(y)\f$ and perform a matrix summation,
|
||
\f[
|
||
\mathsf G(x,y) = \begin{bmatrix}
|
||
(g(x) + g(y)) / 2\\
|
||
(g(x) - g(y)) / (x - y)
|
||
\end{bmatrix} = \sum_{k=1}^N c_k \mathsf F_k(x,y),
|
||
\f]
|
||
where
|
||
\f[
|
||
\mathsf F_k(x,y)=
|
||
\begin{bmatrix}
|
||
\cos kd \sin kp\\
|
||
{\displaystyle\frac{\sin kd}d} \cos kp
|
||
\end{bmatrix},
|
||
\f]
|
||
\f$d=\frac12(x-y)\f$, \f$p=\frac12(x+y)\f$, and, in the limit
|
||
\f$d\rightarrow0\f$, \f$(\sin kd)/d \rightarrow k\f$. The first element
|
||
of \f$\mathsf G(x,y)\f$ is the average value of \f$g\f$ and the second
|
||
element, the divided difference, is the average slope. \f$\mathsf
|
||
F_k(x,y)\f$ satisfies the recurrence relation
|
||
\f[
|
||
\mathsf F_{k+1}(x,y) =
|
||
\mathsf A(x,y) \mathsf F_k(x,y) - \mathsf F_{k-1}(x,y),
|
||
\f]
|
||
where
|
||
\f[
|
||
\mathsf A(x,y) = 2\begin{bmatrix}
|
||
\cos d \cos p & -d\sin d \sin p \\
|
||
- {\displaystyle\frac{\sin d}d} \sin p & \cos d \cos p
|
||
\end{bmatrix},
|
||
\f]
|
||
and \f$\lim_{d\rightarrow0}(\sin d)/d = 1\f$. The standard Clenshaw
|
||
algorithm can now be applied to yield
|
||
\f[
|
||
\begin{align}
|
||
\mathsf B_{N+1} &= \mathsf B_{N+2} = \mathsf 0, \\
|
||
\mathsf B_k &= \mathsf A \mathsf B_{k+1} - \mathsf B_{k+2} +
|
||
c_k \mathsf I, \qquad\text{for $N\ge k \ge 1$},\\
|
||
\mathsf G(x,y) &= \mathsf B_1 \mathsf F_1(x,y),
|
||
\end{align}
|
||
\f]
|
||
where \f$\mathsf B_k\f$ are \f$2\times2\f$ matrices. The divided
|
||
difference \f$\Delta[g](x,y)\f$ is given by the second element of
|
||
\f$\mathsf G(x,y)\f$.
|
||
|
||
The same basic recursion applies to the more general case,
|
||
\f[
|
||
g(x) = \sum_{k=0}^N c_k \sin\bigl( (k+k_0)x + x_0\bigr).
|
||
\f]
|
||
For example, the sum area arising in the computation of geodesic areas,
|
||
\f[
|
||
\sum_{k=0}^N c_k\cos\bigl((2k+1)\sigma)
|
||
\f]
|
||
is given by \f$x=2\sigma\f$, \f$x_0=\frac12\pi\f$, \f$k_0=\frac12\f$.
|
||
Again we consider the matrix sum,
|
||
\f[
|
||
\mathsf G(x,y) = \begin{bmatrix}
|
||
(g(x) + g(y)) / 2\\
|
||
(g(x) - g(y)) / (x - y)
|
||
\end{bmatrix} = \sum_{k=0}^N c_k \mathsf F_k(x,y),
|
||
\f]
|
||
where
|
||
\f[
|
||
\mathsf F_k(x,y)=
|
||
\begin{bmatrix}
|
||
\cos\bigl( (k+k_0)d \bigr) \sin \bigl( (k+k_0)p + x_0 \bigr)\\
|
||
{\displaystyle\frac{\sin\bigl( (k+k_0)d \bigr)}d}
|
||
\cos \bigl( (k+k_0)p + x_0 \bigr)
|
||
\end{bmatrix}.
|
||
\f]
|
||
The recursion for \f$\mathsf B_k\f$ is identical to the previous case;
|
||
in particular, the expression for \f$\mathsf A(x,y)\f$ remains
|
||
unchanged. The result for the sum is
|
||
\f[
|
||
\mathsf G(x,y) =
|
||
(c_0\mathsf I - \mathsf B_2) \mathsf F_0(x,y)
|
||
+ \mathsf B_1 \mathsf F_1(x,y).
|
||
\f]
|
||
|
||
<center>
|
||
Back to \ref jacobi. Forward to \ref greatellipse. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page greatellipse Great Ellipses
|
||
|
||
<center>
|
||
Back to \ref rhumb. Forward to \ref transversemercator. Up to \ref contents.
|
||
</center>
|
||
|
||
Great ellipses are sometimes proposed (Williams, 1996; Pallikaris &
|
||
Latsas, 2009) as alternatives to geodesics for the purposes of
|
||
navigation. This is predicated on the assumption that solving the
|
||
geodesic problems is complex and costly. These assumptions are no
|
||
longer true, and geodesics should normally be used in place of great
|
||
ellipses. This is discussed in more detail in \ref gevsgeodesic.
|
||
|
||
Solutions of the great ellipse problems implemented for MATLAB and
|
||
Octave are provided by
|
||
- gedoc: briefly describe the routines
|
||
- gereckon: solve the direct great ellipse problem
|
||
- gedistance: solve the inverse great ellipse problem
|
||
.
|
||
At this time, there is no C++ support in GeographicLib for great
|
||
ellipses.
|
||
|
||
References:
|
||
- P. D. Thomas,
|
||
<a href="https://apps.dtic.mil/sti/citations/AD0627893">
|
||
Mathematical Models for Navigation Systems</a>,
|
||
TR-182 (U.S. Naval Oceanographic Office, 1965).
|
||
- B. R. Bowring,
|
||
<a href="https://doi.org/10.1007/BF02521760">
|
||
The direct and inverse solutions for the great elliptic line on the
|
||
reference ellipsoid</a>, Bull. Geod. 58, 101--108 (1984).
|
||
- M. A. Earle,
|
||
A vector solution for navigation on a great ellipse,
|
||
J. Navigation 53(3), 473--481 (2000).
|
||
- M. A. Earle,
|
||
<a href="https://doi.org/10.1017/S037346330800475X">
|
||
Vector solutions for azimuth</a>,
|
||
J. Navigation 61(3), 537--545 (2008).
|
||
- C. F. F. Karney,
|
||
<a href="https://doi.org/10.1007/s00190-012-0578-z">
|
||
Algorithms for geodesics</a>, J. Geodesy 87(1), 43--55 (2013);
|
||
addenda: <a href="https://geographiclib.sourceforge.io/geod-addenda.html">
|
||
geod-addenda.html</a>.
|
||
- A. Pallikaris & G. Latsas,
|
||
<a href="https://doi.org/10.1017/S0373463309005323">
|
||
New algorithm for great elliptic sailing (GES)</a>,
|
||
J. Navigation 62(3), 493--507 (2009).
|
||
- A. Pallikaris, L. Tsoulos, & D. Paradissis,
|
||
New meridian arc formulas for sailing calculations in navigational
|
||
GIS, International Hydrographic Review, 24--34 (May 2009).
|
||
- L. E. Sjöberg,
|
||
<a href="https://doi.org/10.2478/v10156-011-0040-9">
|
||
Solutions to the direct and inverse navigation problems on the great
|
||
ellipse</a>, J. Geodetic Science 2(3), 200--205 (2012).
|
||
- R. Williams,
|
||
<a href="https://doi.org/10.1017/S0373463300013333">
|
||
The Great Ellipse on the Surface of the Spheroid</a>,
|
||
J. Navigation 49(2), 229--234 (1996).
|
||
- T. Vincenty,
|
||
<a href="https://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf">
|
||
Direct and Inverse Solutions of Geodesics on the Ellipsoid with
|
||
Application of Nested Equations</a>,
|
||
Survey Review 23(176), 88--93 (1975).
|
||
- Wikipedia page, <a href="https://en.wikipedia.org/wiki/Great_ellipse">
|
||
Great ellipse</a>.
|
||
|
||
Go to
|
||
- \ref geformulation
|
||
- \ref gearea
|
||
- \ref gevsgeodesic
|
||
|
||
\section geformulation Solution of great ellipse problems
|
||
|
||
Adopt the usual notation for the ellipsoid: equatorial semi-axis
|
||
\f$a\f$, polar semi-axis \f$b\f$, flattening \f$f = (a-b)/a\f$,
|
||
eccentricity \f$e = \sqrt{f(2-f)}\f$, second eccentricity \f$e' =
|
||
e/(1-f)\f$, and third flattening \f$n=(a-b)/(a+b)=f/(2-f)\f$.
|
||
|
||
There are several ways in which an ellipsoid can be mapped into a sphere
|
||
converting the great ellipse into a great circle. The simplest ones
|
||
entail scaling the ellipsoid in the \f$\hat z\f$ direction, the
|
||
direction of the axis of rotation, scaling the ellipsoid radially, or a
|
||
combination of the two.
|
||
|
||
One such combination (scaling by \f$a^2/b^2\f$ in the \f$\hat z\f$
|
||
direction, following by a radial scaling to the sphere) preserves the
|
||
geographical latitude \f$\phi\f$. This enables a great ellipse to be
|
||
plotted on a chart merely by determining way points on the corresponding
|
||
great circle and transferring them directly on the chart. In this
|
||
exercise the flattening of the ellipsoid can be <i>ignored</i>!
|
||
|
||
Bowring (1984), Williams (1996), Earle (2000, 2008) and Pallikaris &
|
||
Latsas (2009), scale the ellipsoid radially onto a sphere preserving the
|
||
geocentric latitude \f$\theta\f$. More convenient than this is to scale
|
||
the ellipsoid along \f$\hat z\f$ onto the sphere, as is done by
|
||
Thomas (1965) and Sjöberg (2012), thus preserving the parametric
|
||
latitude \f$\beta\f$. The advantage of this "parametric" mapping is
|
||
that Bessel's rapidly converging series for meridian arc in terms of
|
||
parametric latitude can be used (a possibility that is overlooked by
|
||
Sjöberg).
|
||
|
||
The full parametric mapping is:
|
||
- The geographic latitude \f$\phi\f$ on the ellipsoid maps to the
|
||
parametric latitude \f$\beta\f$ on the sphere,
|
||
where
|
||
\f[a\tan\beta = b\tan\phi.\f]
|
||
- The longitude \f$\lambda\f$ is unchanged.
|
||
- The azimuth \f$\alpha\f$ on the ellipsoid maps to an azimuth
|
||
\f$\gamma\f$ on the sphere where
|
||
\f[
|
||
\begin{align}
|
||
\tan\alpha &= \frac{\tan\gamma}{\sqrt{1-e^2\cos^2\beta}}, \\
|
||
\tan\gamma &= \frac{\tan\alpha}{\sqrt{1+e'^2\cos^2\phi}},
|
||
\end{align}
|
||
\f]
|
||
and the quadrants of \f$\alpha\f$ and \f$\gamma\f$ are the same.
|
||
- Positions on the great circle of radius \f$a\f$ are parametrized by
|
||
arc length \f$\sigma\f$ measured from the northward crossing of the
|
||
equator. The great ellipse has semi-axes \f$a\f$ and
|
||
\f$b'=a\sqrt{1-e^2\cos^2\gamma_0}\f$, where \f$\gamma_0\f$ is the
|
||
great-circle azimuth at the northward equator crossing, and
|
||
\f$\sigma\f$ is the parametric angle on the ellipse. [In contrast,
|
||
the ellipse giving distances on a geodesic has semi-axes
|
||
\f$b\sqrt{1+e'^2\cos^2\alpha_0}\f$ and \f$b\f$.]
|
||
.
|
||
To determine the distance along the ellipse in terms of \f$\sigma\f$ and
|
||
vice versa, the series for distance \f$s\f$ and for \f$\tau\f$ given in
|
||
\ref geodseries can be used. The direct and inverse great ellipse
|
||
problems are now simply solved by mapping the problem to the sphere,
|
||
solving the resulting great circle problem, and mapping this back onto
|
||
the ellipsoid.
|
||
|
||
\section gearea The area under a great ellipse
|
||
|
||
The area between the segment of a great ellipse and the equator can be
|
||
found by very similar methods to those used for geodesic areas; see
|
||
<a href="https://doi.org/10.1179/003962689791474267"> Danielsen
|
||
(1989)</a>. The notation here is similar to that employed by
|
||
<a href="https://doi.org/10.1007/s00190-012-0578-z"> Karney
|
||
(2013)</a>.
|
||
\f[
|
||
\begin{align}
|
||
S_{12} &= S(\sigma_2) - S(\sigma_1) \\
|
||
S(\sigma) &= c^2\gamma + e^2 a^2 \cos\gamma_0 \sin\gamma_0 I_4(\sigma)\\
|
||
c^2 &= {\textstyle\frac12}\bigl(a^2 + b^2 (\tanh^{-1}e)/e\bigr)
|
||
\end{align}
|
||
\f]
|
||
\f[
|
||
I_4(\sigma) = - \sqrt{1+e'^2}\int
|
||
\frac{r(e'^2) - r(k^2\sin^2\sigma)}{e'^2 - k^2\sin^2\sigma}
|
||
\frac{\sin\sigma}2 \,d\sigma
|
||
\f]
|
||
\f[
|
||
\begin{align}
|
||
k &= e' \cos\gamma_0,\\
|
||
r(x) &= \sqrt{1+x} + (\sinh^{-1}\sqrt x)/\sqrt x.
|
||
\end{align}
|
||
\f]
|
||
Expand in terms of the third flattening of the ellipsoid, \f$n\f$, and the
|
||
third flattening of the great ellipse, \f$\epsilon=(a-b')/(a+b')\f$, by
|
||
substituting
|
||
\f[
|
||
\begin{align}
|
||
e'&=\frac{2\sqrt n}{1-n},\\
|
||
k&=\frac{1+n}{1-n} \frac{2\sqrt{\epsilon}}{1+\epsilon},
|
||
\end{align}
|
||
\f]
|
||
to give
|
||
\f[
|
||
I_4(\sigma) = \sum_{l = 0}^\infty G_{4l}\cos \bigl((2l+1)\sigma\bigr).
|
||
\f]
|
||
Compared to the area under a geodesic, we have
|
||
- \f$\gamma\f$ and \f$\gamma_0\f$ instead of \f$\alpha\f$ and
|
||
\f$\alpha_0\f$. In both cases, these are azimuths on the auxiliary
|
||
sphere; however, for the geodesic, they are also the azimuths on the
|
||
ellipsoid.
|
||
- \f$r(x) = \bigl(1+t(x)\bigr)/\sqrt{1+x}\f$ instead of \f$t(x)\f$ with
|
||
a balancing factor of \f$\sqrt{1+e'^2}\f$ appearing in front of the
|
||
integral. These changes are because expressing
|
||
\f$\sin\phi\,d\lambda\f$ in terms of \f$\sigma\f$ is a little more
|
||
complicated with great ellipses. (Don't worry about the addition of
|
||
\f$1\f$ to \f$t(x)\f$; that's immaterial.)
|
||
- the factors involving \f$n\f$ in the expression for \f$k\f$ in terms
|
||
of \f$\epsilon\f$. This is because \f$k\f$ is defined in terms of
|
||
\f$e'\f$, whereas it is \f$e\cos\gamma_0\f$ that plays the role of the
|
||
eccentricity for the great ellipse.
|
||
|
||
Here is the series expansion accurate to 10th order, found by
|
||
<a href="gearea.mac">gearea.mac</a>:
|
||
|
||
\verbatim
|
||
G4[0] = + (1/6 + 7/30 * n + 8/105 * n^2 + 4/315 * n^3 + 16/3465 * n^4 + 20/9009 * n^5 + 8/6435 * n^6 + 28/36465 * n^7 + 32/62985 * n^8 + 4/11305 * n^9)
|
||
- (3/40 + 12/35 * n + 589/840 * n^2 + 1063/1155 * n^3 + 14743/15015 * n^4 + 14899/15015 * n^5 + 254207/255255 * n^6 + 691127/692835 * n^7 + 1614023/1616615 * n^8) * eps
|
||
+ (67/280 + 7081/5040 * n + 5519/1320 * n^2 + 6417449/720720 * n^3 + 708713/45045 * n^4 + 2700154/109395 * n^5 + 519037063/14549535 * n^6 + 78681626/1616615 * n^7) * eps^2
|
||
- (29597/40320 + 30013/5280 * n + 33759497/1441440 * n^2 + 100611307/1441440 * n^3 + 16639623457/98017920 * n^4 + 3789780779/10581480 * n^5 + 1027832503/1511640 * n^6) * eps^3
|
||
+ (357407/147840 + 19833349/823680 * n + 61890679/480480 * n^2 + 97030756063/196035840 * n^3 + 2853930388817/1862340480 * n^4 + 15123282583393/3724680960 * n^5) * eps^4
|
||
- (13200233/1537536 + 306285589/2882880 * n + 26279482199/37340160 * n^2 + 3091446335399/931170240 * n^3 + 93089556575647/7449361920 * n^4) * eps^5
|
||
+ (107042267/3294720 + 253176989449/522762240 * n + 57210830762263/14898723840 * n^2 + 641067300459403/29797447680 * n^3) * eps^6
|
||
- (51544067373/398295040 + 38586720036247/17027112960 * n + 104152290127363/4966241280 * n^2) * eps^7
|
||
+ (369575321823/687964160 + 1721481081751393/158919720960 * n) * eps^8
|
||
- 10251814360817/4445306880 * eps^9;
|
||
G4[1] = + (1/120 + 4/105 * n + 589/7560 * n^2 + 1063/10395 * n^3 + 14743/135135 * n^4 + 14899/135135 * n^5 + 254207/2297295 * n^6 + 691127/6235515 * n^7 + 1614023/14549535 * n^8) * eps
|
||
- (53/1680 + 847/4320 * n + 102941/166320 * n^2 + 1991747/1441440 * n^3 + 226409/90090 * n^4 + 3065752/765765 * n^5 + 24256057/4157010 * n^6 + 349229428/43648605 * n^7) * eps^2
|
||
+ (4633/40320 + 315851/332640 * n + 5948333/1441440 * n^2 + 11046565/864864 * n^3 + 9366910279/294053760 * n^4 + 23863367599/349188840 * n^5 + 45824943037/349188840 * n^6) * eps^3
|
||
- (8021/18480 + 39452953/8648640 * n + 3433618/135135 * n^2 + 29548772933/294053760 * n^3 + 44355142973/139675536 * n^4 + 4771229132843/5587021440 * n^5) * eps^4
|
||
+ (2625577/1537536 + 5439457/247104 * n + 353552588953/2352430080 * n^2 + 405002114215/558702144 * n^3 + 61996934629789/22348085760 * n^4) * eps^5
|
||
- (91909777/13178880 + 2017395395921/18819440640 * n + 51831652526149/59594895360 * n^2 + 1773086701957889/357569372160 * n^3) * eps^6
|
||
+ (35166639971/1194885120 + 26948019211109/51081338880 * n + 7934238355871/1596291840 * n^2) * eps^7
|
||
- (131854991623/1031946240 + 312710596037369/119189790720 * n) * eps^8
|
||
+ 842282436291/1481768960 * eps^9;
|
||
G4[2] = + (1/560 + 29/2016 * n + 1027/18480 * n^2 + 203633/1441440 * n^3 + 124051/450450 * n^4 + 1738138/3828825 * n^5 + 98011493/145495350 * n^6 + 4527382/4849845 * n^7) * eps^2
|
||
- (533/40320 + 14269/110880 * n + 908669/1441440 * n^2 + 15253627/7207200 * n^3 + 910103119/163363200 * n^4 + 2403810527/193993800 * n^5 + 746888717/30630600 * n^6) * eps^3
|
||
+ (2669/36960 + 2443153/2882880 * n + 1024791/200200 * n^2 + 10517570057/490089600 * n^3 + 164668999127/2327925600 * n^4 + 1826633124599/9311702400 * n^5) * eps^4
|
||
- (5512967/15375360 + 28823749/5765760 * n + 31539382001/871270400 * n^2 + 1699098121381/9311702400 * n^3 + 287618085731/398361600 * n^4) * eps^5
|
||
+ (22684703/13178880 + 25126873327/896163840 * n + 10124249914577/42567782400 * n^2 + 836412216748957/595948953600 * n^3) * eps^6
|
||
- (3259030001/398295040 + 2610375232847/17027112960 * n + 2121882247763/1418926080 * n^2) * eps^7
|
||
+ (13387413913/343982080 + 939097138279/1135140864 * n) * eps^8
|
||
- 82722916855/444530688 * eps^9;
|
||
G4[3] = + (5/8064 + 23/3168 * n + 1715/41184 * n^2 + 76061/480480 * n^3 + 812779/1782144 * n^4 + 9661921/8953560 * n^5 + 40072069/18106088 * n^6) * eps^3
|
||
- (409/59136 + 10211/109824 * n + 46381/73920 * n^2 + 124922951/43563520 * n^3 + 12524132449/1241560320 * n^4 + 30022391821/1022461440 * n^5) * eps^4
|
||
+ (22397/439296 + 302399/384384 * n + 461624513/74680320 * n^2 + 1375058687/41385344 * n^3 + 4805085120841/34763688960 * n^4) * eps^5
|
||
- (14650421/46126080 + 17533571183/3136573440 * n + 1503945368767/29797447680 * n^2 + 43536234862451/139054755840 * n^3) * eps^6
|
||
+ (5074867067/2788065280 + 479752611137/13243310080 * n + 1228808683449/3310827520 * n^2) * eps^7
|
||
- (12004715823/1203937280 + 17671119291563/79459860480 * n) * eps^8
|
||
+ 118372499107/2222653440 * eps^9;
|
||
G4[4] = + (7/25344 + 469/109824 * n + 13439/411840 * n^2 + 9282863/56010240 * n^3 + 37558503/59121920 * n^4 + 44204289461/22348085760 * n^5) * eps^4
|
||
- (5453/1317888 + 58753/823680 * n + 138158857/224040960 * n^2 + 191056103/53209728 * n^3 + 712704605341/44696171520 * n^4) * eps^5
|
||
+ (28213/732160 + 331920271/448081920 * n + 2046013913/283785216 * n^2 + 11489035343/241274880 * n^3) * eps^6
|
||
- (346326947/1194885120 + 11716182499/1891901440 * n + 860494893431/12770334720 * n^2) * eps^7
|
||
+ (750128501/386979840 + 425425087409/9287516160 * n) * eps^8
|
||
- 80510858479/6667960320 * eps^9;
|
||
G4[5] = + (21/146432 + 23/8320 * n + 59859/2263040 * n^2 + 452691/2687360 * n^3 + 21458911/26557440 * n^4) * eps^5
|
||
- (3959/1464320 + 516077/9052160 * n + 51814927/85995520 * n^2 + 15444083489/3611811840 * n^3) * eps^6
|
||
+ (1103391/36208640 + 120920041/171991040 * n + 18522863/2263040 * n^2) * eps^7
|
||
- (92526613/343982080 + 24477436759/3611811840 * n) * eps^8
|
||
+ 1526273559/740884480 * eps^9;
|
||
G4[6] = + (11/133120 + 1331/696320 * n + 145541/6615040 * n^2 + 46863487/277831680 * n^3) * eps^6
|
||
- (68079/36208640 + 621093/13230080 * n + 399883/680960 * n^2) * eps^7
|
||
+ (658669/26460160 + 186416197/277831680 * n) * eps^8
|
||
- 748030679/2963537920 * eps^9;
|
||
G4[7] = + (143/2785280 + 11011/7938048 * n + 972829/52093440 * n^2) * eps^7
|
||
- (434863/317521920 + 263678129/6667960320 * n) * eps^8
|
||
+ 185257501/8890613760 * eps^9;
|
||
G4[8] = + (715/21168128 + 27313/26148864 * n) * eps^8
|
||
- 1838551/1778122752 * eps^9;
|
||
G4[9] = + 2431/104595456 * eps^9;
|
||
\endverbatim
|
||
|
||
\section gevsgeodesic Great ellipses vs geodesics
|
||
|
||
Some papers advocating the use of great ellipses for navigation exhibit
|
||
a prejudice against the use of geodesics. These excerpts from
|
||
Pallikaris, Tsoulos, & Paradissis (2009) give the flavor
|
||
- … it is required to adopt realistic accuracy standards in order not
|
||
only to eliminate the significant errors of the spherical model but
|
||
also to avoid the exaggerated and unrealistic requirements of sub
|
||
meter accuracy.
|
||
- Calculation of shortest sailings paths on the ellipsoid by a geodetic
|
||
inverse method involve formulas that are much too complex.
|
||
- Despite the fact that contemporary computers are fast enough to
|
||
handle more complete geodetic formulas of sub meter accuracy, a basic
|
||
principle for the design of navigational systems is the avoidance of
|
||
unnecessary consumption of computing power.
|
||
.
|
||
This prejudice was probably due to the fact that the most well-known
|
||
algorithms for geodesics, by Vincenty (1975), come with some
|
||
"asterisks":
|
||
- no derivation was given (although they follow in a straightforward
|
||
fashion from classic 19th century methods);
|
||
- the accuracy is "only" 0.5 mm or so, surely good enough for most
|
||
applications, but still a reason for a user to worry and a spur to
|
||
numerous studies "validating" the algorithms;
|
||
- no indication is given for how to extend the series to improve the
|
||
accuracy;
|
||
- there was a belief in some quarters (erroneous!) that the Vincenty
|
||
algorithms could not be used to compute waypoints;
|
||
- the algorithm for the inverse problem fails to converge for some
|
||
inputs.
|
||
.
|
||
These problems meant that users were reluctant to bundle the algorithms
|
||
into a library and treat them as a part of the software infrastructure
|
||
(much as you might regard the computation of \f$\sin x\f$ as a given).
|
||
In particular, I regard the last issue, lack of convergence of the
|
||
inverse solution, as fatal. Even though the problem only arises for
|
||
nearly antipodal points, it means all users of the library must have
|
||
some way to handle this problem.
|
||
|
||
For these reasons, substitution of a great ellipse for the geodesic
|
||
makes some sense. The solution of the great ellipse is, in principle,
|
||
no more difficult than solving for the great circle and, for paths of
|
||
less then 10000 km, the error in the distance is less than
|
||
13.5 m.
|
||
|
||
Now (2014), however, the situation has reversed. The algorithms given
|
||
by Karney (2013)—and used in GeographicLib since
|
||
2009—explicitly resolve the issues with Vincenty's algorithm. The
|
||
geodesic problem is conveniently bundled into a library. Users can call
|
||
this with an assurance of an accurate result much as they would when
|
||
evaluating \f$\sin x\f$. On the other hand, great ellipses come with
|
||
their own set of asterisks:
|
||
- To the extent that they are regarded as approximations to geodesics,
|
||
the errors need to be quantified, the limits of allowable use
|
||
documented, etc.
|
||
- The user is now left with decisions on when to trust the results and
|
||
to find alternative solutions if necessary.
|
||
- Even though the great ellipse is no more that 13.5 m longer than
|
||
a 10000 km geodesic, the path of the great ellipse can deviate
|
||
from the geodesic by as much as 8.3 km. This disqualifies great
|
||
ellipses from use in congested air corridors where the
|
||
<a href="https://en.wikipedia.org/wiki/Strategic_lateral_offset_procedure">
|
||
strategic lateral offset procedure</a> is in effect and in any
|
||
situation which demands coordination in the routes of vessels.
|
||
- Because geodesics obey the triangle inequality, while great ellipses
|
||
do not, the solutions for realistic navigational problems, e.g.,
|
||
determining the time of closest approach of two vessels, are often
|
||
simpler in terms of geodesics.
|
||
|
||
To address some other of the objections in the quotes from Pallikaris et
|
||
al. given above:
|
||
- "exaggerated and unrealistic requirements of sub meter accuracy": The
|
||
geodesic algorithms allow full double precision accuracy at
|
||
essentially no cost. This is because Clenshaw summation allows
|
||
additional terms to be added to the series without the need for
|
||
addition trigonometric evaluations. Full accuracy is important to
|
||
maintain because it allows the results to be used reliably in more
|
||
complex problems (e.g., in the determination of maritime boundaries).
|
||
- "unnecessary consumption of computing power": The solution of the
|
||
inverse geodesic problem takes 2.3 μs; multiple points on a
|
||
geodesic can be computed at a rate of one point per 0.4 μs.
|
||
The actual power consumed in these calculations is minuscule compared
|
||
to the power needed to drive the display of a navigational computer.
|
||
- "formulas that are much too complex": There's no question that the
|
||
solution of the geodesic problem is more complex than for great
|
||
ellipses. However this complexity is only an issue when
|
||
<b>implementing</b> the algorithms. For the <b>end user</b>,
|
||
navigational software employing geodesics is <b>less</b> complex
|
||
compared with that employing great ellipses. Here is what the user
|
||
needs to know about the geodesic solution:
|
||
<blockquote>"The shortest path is found."</blockquote>
|
||
And here is the corresponding documentation for great ellipses:
|
||
<blockquote>"A path which closely approximates the shortest path is
|
||
found. Provided that the distance is less than 10000 km, the
|
||
error in distance is no more than 14 m and the deviation the
|
||
route from that of the shortest path is no more than 9 km.
|
||
These bounds apply to the WGS84 ellipsoid. The deviation of the path
|
||
means that it should be used with caution when planning routes. In
|
||
addition, great ellipses do not obey the triangle inequality; this
|
||
disqualifies them from use in some applications."</blockquote>
|
||
|
||
Having all the geodesic functions bundled up into a reliable "black box"
|
||
enables users to concentrate on how to solve problems using geodesics
|
||
(instead of figuring out how to solve for the geodesics). A wide range
|
||
of problems (intersection of paths, the path for an interception, the
|
||
time of closest approach, median lines, tri-points, etc.) are all
|
||
amenable to simple and fast solutions in terms of geodesics.
|
||
|
||
<center>
|
||
Back to \ref rhumb. Forward to \ref transversemercator. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page transversemercator Transverse Mercator projection
|
||
|
||
<center>
|
||
Back to \ref greatellipse. Forward to \ref geocentric. Up to \ref contents.
|
||
</center>
|
||
|
||
TransverseMercator and TransverseMercatorExact provide accurate
|
||
implementations of the transverse Mercator projection. The
|
||
<a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a>
|
||
utility provides an interface to these classes.
|
||
|
||
Go to
|
||
- \ref testmerc
|
||
- \ref tmseries
|
||
- \ref tmfigures
|
||
|
||
References:
|
||
- L. Krüger,
|
||
<a href="https://doi.org/10.2312/GFZ.b103-krueger28"> Konforme
|
||
Abbildung des Erdellipsoids in der Ebene</a> (Conformal mapping of
|
||
the ellipsoidal earth to the plane), Royal Prussian Geodetic Institute,
|
||
New Series 52, 172 pp. (1912).
|
||
- L. P. Lee,
|
||
Conformal Projections Based on Elliptic Functions,
|
||
(B. V. Gutsell, Toronto, 1976), 128pp.,
|
||
ISBN: 0919870163
|
||
(Also appeared as:
|
||
Monograph 16, Suppl. No. 1 to Canadian Cartographer, Vol 13).
|
||
Part V, pp. 67--101,
|
||
<a href="https://doi.org/10.3138/X687-1574-4325-WM62">Conformal
|
||
Projections Based On Jacobian Elliptic Functions</a>;
|
||
<a href="https://archive.org/details/conformalproject0000leel/page/92">
|
||
borrow from archive.org</a>.
|
||
- C. F. F. Karney,
|
||
<a href="https://doi.org/10.1007/s00190-011-0445-3">
|
||
Transverse Mercator with an accuracy of a few nanometers</a>,
|
||
J. Geodesy 85(8), 475--485 (Aug. 2011);
|
||
addenda: <a href="https://geographiclib.sourceforge.io/tm-addenda.html">
|
||
tm-addenda.html</a>;
|
||
preprint:
|
||
<a href="https://arxiv.org/abs/1002.1417"> arXiv:1002.1417</a>;
|
||
resource page:
|
||
<a href="https://geographiclib.sourceforge.io/tm.html"> tm.html</a>.
|
||
.
|
||
The algorithm for TransverseMercator is based on
|
||
Krüger (1912); that for TransverseMercatorExact is
|
||
based on Lee (1976).
|
||
|
||
See <a href="https://geographiclib.sourceforge.io/tm-grid.kmz"
|
||
type="application/vnd.google-earth.kmz"> tm-grid.kmz</a>, for an
|
||
illustration of the exact transverse Mercator grid in Google Earth.
|
||
|
||
\section testmerc Test data for the transverse Mercator projection
|
||
|
||
A test set for the transverse Mercator projection is available at
|
||
- <a href="https://sourceforge.net/projects/geographiclib/files/testdata/TMcoords.dat.gz">
|
||
TMcoords.dat.gz</a>
|
||
- C. F. F. Karney, <i>Test data for the transverse Mercator projection</i>
|
||
(2009), <br>
|
||
DOI: <a href="https://doi.org/10.5281/zenodo.32470">
|
||
10.5281/zenodo.32470</a>.
|
||
.
|
||
This is about 17 MB (compressed). This test set consists of a set of
|
||
geographic coordinates together with the corresponding transverse
|
||
Mercator coordinates. The WGS84 ellipsoid is used, with central
|
||
meridian 0°, central scale factor 0.9996 (the UTM value),
|
||
false easting = false northing = 0 m.
|
||
|
||
Each line of the test set gives 6 space delimited numbers
|
||
- latitude (degrees, exact)
|
||
- longitude (degrees, exact — see below)
|
||
- easting (meters, accurate to 0.1 pm)
|
||
- northing (meters, accurate to 0.1 pm)
|
||
- meridian convergence (degrees, accurate to 10<sup>−18</sup> deg)
|
||
- scale (accurate to 10<sup>−20</sup>)
|
||
.
|
||
The latitude and longitude are all multiples of 10<sup>−12</sup>
|
||
deg and should be regarded as exact, except that longitude =
|
||
82.63627282416406551 should be interpreted as exactly (1 − \e e)
|
||
90°. These results are computed using Lee's formulas with
|
||
<a href="https://en.wikipedia.org/wiki/Maxima_(software)">Maxima</a>'s
|
||
bfloats and fpprec set to 80 (so the errors in the data are probably 1/2
|
||
of the values quoted above). The Maxima code,
|
||
<a href="tm.mac">tm.mac</a> and <a href="ellint.mac">ellint.mac</a>,
|
||
was used to prepare this data set is included in the distribution; you
|
||
will need to have Maxima installed to use this code. The comments at
|
||
the top of <a href="tm.mac">tm.mac</a> illustrate how to run it.
|
||
|
||
The contents of the file are as follows:
|
||
- 250000 entries randomly distributed in lat in [0°, 90°], lon
|
||
in [0°, 90°];
|
||
- 1000 entries randomly distributed on lat in [0°, 90°], lon =
|
||
0°;
|
||
- 1000 entries randomly distributed on lat = 0°, lon in [0°,
|
||
90°];
|
||
- 1000 entries randomly distributed on lat in [0°, 90°], lon =
|
||
90°;
|
||
- 1000 entries close to lat = 90° with lon in [0°, 90°];
|
||
- 1000 entries close to lat = 0°, lon = 0° with lat ≥
|
||
0°, lon ≥ 0°;
|
||
- 1000 entries close to lat = 0°, lon = 90° with lat ≥
|
||
0°, lon ≤ 90°;
|
||
- 2000 entries close to lat = 0°, lon = (1 − \e e) 90°
|
||
with lat ≥ 0°;
|
||
- 25000 entries randomly distributed in lat in [−89°,
|
||
0°], lon in [(1 − \e e) 90°, 90°];
|
||
- 1000 entries randomly distributed on lat in [−89°, 0°],
|
||
lon = 90°;
|
||
- 1000 entries randomly distributed on lat in [−89°, 0°],
|
||
lon = (1 − \e e) 90°;
|
||
- 1000 entries close to lat = 0°, lon = 90° (lat < 0°, lon
|
||
≤ 90°);
|
||
- 1000 entries close to lat = 0°, lon = (1 − \e e) 90°
|
||
(lat < 0°, lon ≤ (1 − \e e) 90°);
|
||
.
|
||
(a total of 287000 entries). The entries for lat < 0° and
|
||
lon in [(1 − \e e) 90°, 90°] use the "extended"
|
||
domain for the transverse Mercator projection explained in Sec. 5 of
|
||
Karney (2011). The first
|
||
258000 entries have lat ≥ 0° and are suitable for testing
|
||
implementations following the standard convention.
|
||
|
||
\section tmseries Series approximation for transverse Mercator
|
||
|
||
Krüger (1912) gives a 4th-order approximation to the transverse
|
||
Mercator projection. This is accurate to about 200 nm (200
|
||
nanometers) within the UTM domain. Here we present the series
|
||
extended to 10th order. By default, TransverseMercator
|
||
uses the 6th-order approximation. The preprocessor macro
|
||
GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER can be used to select an order
|
||
from 4 thru 8. The series expanded to order <i>n</i><sup>30</sup> are
|
||
given in <a href="tmseries30.html"> tmseries30.html</a>.
|
||
|
||
In the formulas below ^ indicates exponentiation (<i>n</i>^3 =
|
||
<i>n</i>*<i>n</i>*<i>n</i>) and / indicates real division (3/5 = 0.6).
|
||
The equations need to be converted to Horner form, but are here left in
|
||
expanded form so that they can be easily truncated to lower order in \e
|
||
n. Some of the integers here are not representable as 32-bit integers
|
||
and will need to be included as 64-bit integers.
|
||
|
||
\e A in Krüger, p. 12, eq. (5)
|
||
\verbatim
|
||
A = a/(n + 1) * (1 + 1/4 * n^2
|
||
+ 1/64 * n^4
|
||
+ 1/256 * n^6
|
||
+ 25/16384 * n^8
|
||
+ 49/65536 * n^10);
|
||
\endverbatim
|
||
|
||
γ in Krüger, p. 21, eq. (41)
|
||
\verbatim
|
||
alpha[1] = 1/2 * n
|
||
- 2/3 * n^2
|
||
+ 5/16 * n^3
|
||
+ 41/180 * n^4
|
||
- 127/288 * n^5
|
||
+ 7891/37800 * n^6
|
||
+ 72161/387072 * n^7
|
||
- 18975107/50803200 * n^8
|
||
+ 60193001/290304000 * n^9
|
||
+ 134592031/1026432000 * n^10;
|
||
alpha[2] = 13/48 * n^2
|
||
- 3/5 * n^3
|
||
+ 557/1440 * n^4
|
||
+ 281/630 * n^5
|
||
- 1983433/1935360 * n^6
|
||
+ 13769/28800 * n^7
|
||
+ 148003883/174182400 * n^8
|
||
- 705286231/465696000 * n^9
|
||
+ 1703267974087/3218890752000 * n^10;
|
||
alpha[3] = 61/240 * n^3
|
||
- 103/140 * n^4
|
||
+ 15061/26880 * n^5
|
||
+ 167603/181440 * n^6
|
||
- 67102379/29030400 * n^7
|
||
+ 79682431/79833600 * n^8
|
||
+ 6304945039/2128896000 * n^9
|
||
- 6601904925257/1307674368000 * n^10;
|
||
alpha[4] = 49561/161280 * n^4
|
||
- 179/168 * n^5
|
||
+ 6601661/7257600 * n^6
|
||
+ 97445/49896 * n^7
|
||
- 40176129013/7664025600 * n^8
|
||
+ 138471097/66528000 * n^9
|
||
+ 48087451385201/5230697472000 * n^10;
|
||
alpha[5] = 34729/80640 * n^5
|
||
- 3418889/1995840 * n^6
|
||
+ 14644087/9123840 * n^7
|
||
+ 2605413599/622702080 * n^8
|
||
- 31015475399/2583060480 * n^9
|
||
+ 5820486440369/1307674368000 * n^10;
|
||
alpha[6] = 212378941/319334400 * n^6
|
||
- 30705481/10378368 * n^7
|
||
+ 175214326799/58118860800 * n^8
|
||
+ 870492877/96096000 * n^9
|
||
- 1328004581729009/47823519744000 * n^10;
|
||
alpha[7] = 1522256789/1383782400 * n^7
|
||
- 16759934899/3113510400 * n^8
|
||
+ 1315149374443/221405184000 * n^9
|
||
+ 71809987837451/3629463552000 * n^10;
|
||
alpha[8] = 1424729850961/743921418240 * n^8
|
||
- 256783708069/25204608000 * n^9
|
||
+ 2468749292989891/203249958912000 * n^10;
|
||
alpha[9] = 21091646195357/6080126976000 * n^9
|
||
- 67196182138355857/3379030566912000 * n^10;
|
||
alpha[10]= 77911515623232821/12014330904576000 * n^10;
|
||
\endverbatim
|
||
|
||
β in Krüger, p. 18, eq. (26*)
|
||
\verbatim
|
||
beta[1] = 1/2 * n
|
||
- 2/3 * n^2
|
||
+ 37/96 * n^3
|
||
- 1/360 * n^4
|
||
- 81/512 * n^5
|
||
+ 96199/604800 * n^6
|
||
- 5406467/38707200 * n^7
|
||
+ 7944359/67737600 * n^8
|
||
- 7378753979/97542144000 * n^9
|
||
+ 25123531261/804722688000 * n^10;
|
||
beta[2] = 1/48 * n^2
|
||
+ 1/15 * n^3
|
||
- 437/1440 * n^4
|
||
+ 46/105 * n^5
|
||
- 1118711/3870720 * n^6
|
||
+ 51841/1209600 * n^7
|
||
+ 24749483/348364800 * n^8
|
||
- 115295683/1397088000 * n^9
|
||
+ 5487737251099/51502252032000 * n^10;
|
||
beta[3] = 17/480 * n^3
|
||
- 37/840 * n^4
|
||
- 209/4480 * n^5
|
||
+ 5569/90720 * n^6
|
||
+ 9261899/58060800 * n^7
|
||
- 6457463/17740800 * n^8
|
||
+ 2473691167/9289728000 * n^9
|
||
- 852549456029/20922789888000 * n^10;
|
||
beta[4] = 4397/161280 * n^4
|
||
- 11/504 * n^5
|
||
- 830251/7257600 * n^6
|
||
+ 466511/2494800 * n^7
|
||
+ 324154477/7664025600 * n^8
|
||
- 937932223/3891888000 * n^9
|
||
- 89112264211/5230697472000 * n^10;
|
||
beta[5] = 4583/161280 * n^5
|
||
- 108847/3991680 * n^6
|
||
- 8005831/63866880 * n^7
|
||
+ 22894433/124540416 * n^8
|
||
+ 112731569449/557941063680 * n^9
|
||
- 5391039814733/10461394944000 * n^10;
|
||
beta[6] = 20648693/638668800 * n^6
|
||
- 16363163/518918400 * n^7
|
||
- 2204645983/12915302400 * n^8
|
||
+ 4543317553/18162144000 * n^9
|
||
+ 54894890298749/167382319104000 * n^10;
|
||
beta[7] = 219941297/5535129600 * n^7
|
||
- 497323811/12454041600 * n^8
|
||
- 79431132943/332107776000 * n^9
|
||
+ 4346429528407/12703122432000 * n^10;
|
||
beta[8] = 191773887257/3719607091200 * n^8
|
||
- 17822319343/336825216000 * n^9
|
||
- 497155444501631/1422749712384000 * n^10;
|
||
beta[9] = 11025641854267/158083301376000 * n^9
|
||
- 492293158444691/6758061133824000 * n^10;
|
||
beta[10]= 7028504530429621/72085985427456000 * n^10;
|
||
\endverbatim
|
||
|
||
The high-order expansions for α and β were produced by the
|
||
Maxima program <a href="tmseries.mac"> tmseries.mac</a> (included in the
|
||
distribution). To run, start Maxima and enter
|
||
\verbatim
|
||
load("tmseries.mac")$
|
||
\endverbatim
|
||
Further instructions are included at the top of the file.
|
||
|
||
\section tmfigures Figures from paper on transverse Mercator projection
|
||
|
||
This section gives color versions of the figures in
|
||
- C. F. F. Karney,
|
||
<a href="https://doi.org/10.1007/s00190-011-0445-3">
|
||
Transverse Mercator with an accuracy of a few nanometers</a>,
|
||
J. Geodesy 85(8), 475--485 (Aug. 2011);
|
||
addenda: <a href="https://geographiclib.sourceforge.io/tm-addenda.html">
|
||
tm-addenda.html</a>;
|
||
preprint:
|
||
<a href="https://arxiv.org/abs/1002.1417"> arXiv:1002.1417</a>;
|
||
resource page:
|
||
<a href="https://geographiclib.sourceforge.io/tm.html"> tm.html</a>.
|
||
|
||
\b NOTE:
|
||
The numbering of the figures matches that in the paper cited above. The
|
||
figures in this section are relatively small in order to allow them to
|
||
be displayed quickly. Vector versions of these figures are available in
|
||
<a href="https://geographiclib.sourceforge.io/tm-figs.pdf"
|
||
type="application/pdf"> tm-figs.pdf</a>. This allows you to magnify the
|
||
figures to show the details more clearly.
|
||
|
||
\image html gauss-schreiber-graticule-a.png "Fig. 1(a)"
|
||
Fig. 1(a):
|
||
The graticule for the spherical transverse Mercator projection.
|
||
The equator lies on \e y = 0.
|
||
Compare this with Lee, Fig. 1 (right), which shows the graticule for
|
||
half a sphere, but note that in his notation \e x and \e y have switched
|
||
meanings. The graticule for the ellipsoid differs from that for a
|
||
sphere only in that the latitude lines have shifted slightly. (The
|
||
conformal transformation from an ellipsoid to a sphere merely relabels
|
||
the lines of latitude.) This projection places the point latitude =
|
||
0°, longitude = 90° at infinity.
|
||
|
||
\image html gauss-krueger-graticule-a.png "Fig. 1(b)"
|
||
Fig. 1(b):
|
||
The graticule for the Gauss-Krüger transverse Mercator projection.
|
||
The equator lies on \e y = 0 for longitude < 81°; beyond
|
||
this, it arcs up to meet \e y = 1. Compare this with Lee, Fig. 45
|
||
(upper), which shows the graticule for the International Ellipsoid. Lee,
|
||
Fig. 46, shows the graticule for the entire ellipsoid. This projection
|
||
(like the Thompson projection) projects the ellipsoid to a finite area.
|
||
|
||
\image html thompson-tm-graticule-a.png "Fig. 1(c)"
|
||
Fig. 1(c):
|
||
The graticule for the Thompson transverse Mercator projection. The
|
||
equator lies on \e y = 0 for longitude < 81°; at longitude =
|
||
81°, it turns by 120° and heads for \e y = 1.
|
||
Compare this with Lee, Fig. 43, which shows the graticule for the
|
||
International Ellipsoid. Lee, Fig. 44, shows the graticule for the
|
||
entire ellipsoid. This projection (like the Gauss-Krüger
|
||
projection) projects the ellipsoid to a finite area.
|
||
|
||
\image html gauss-krueger-error.png "Fig. 2"
|
||
Fig. 2:
|
||
The truncation error for the series for the Gauss-Krüger transverse
|
||
Mercator projection. The blue curves show the truncation error for the
|
||
order of the series \e J = 2 (top) thru \e J = 12 (bottom). The red
|
||
curves show the combined truncation and round-off errors for
|
||
- float and \e J = 4 (top)
|
||
- double and \e J = 6 (middle)
|
||
- long double and \e J = 8 (bottom)
|
||
|
||
\image html gauss-krueger-graticule.png "Fig. 3(a)"
|
||
Fig. 3(a):
|
||
The graticule for the extended domain. The blue lines show
|
||
latitude and longitude at multiples of 10°. The green lines
|
||
show 1° intervals for longitude in [80°, 90°] and latitude in
|
||
[−5°, 10°].
|
||
|
||
\image html gauss-krueger-convergence-scale.png "Fig. 3(b)"
|
||
Fig. 3(b):
|
||
The convergence and scale for the Gauss-Krüger
|
||
transverse Mercator projection in the extended domain. The blue lines
|
||
emanating from the top left corner (the north pole) are lines of
|
||
constant convergence. Convergence = 0° is given by the
|
||
dog-legged line joining the points (0,1), (0,0), (1.71,0),
|
||
(1.71,−∞).
|
||
Convergence = 90° is given by the line y = 1. The other
|
||
lines show multiples of 10° between 0° and
|
||
90°. The other blue, the green and the black lines show
|
||
scale = 1 thru 2 at intervals of 0.1, 2 thru 15 at intervals of 1, and
|
||
15 thru 35 at intervals of 5. Multiples of 5 are shown in black,
|
||
multiples of 1 are shown in blue, and the rest are shown in green.
|
||
Scale = 1 is given by the line segment (0,0) to (0,1). The red line
|
||
shows the equator between lon = 81° and 90°. The
|
||
scale and convergence at the branch point are 1/\e e = 10 and
|
||
0°, respectively.
|
||
|
||
\image html thompson-tm-graticule.png "Fig. 3(c)"
|
||
Fig. 3(c):
|
||
The graticule for the Thompson transverse Mercator
|
||
projection for the extended domain. The range of the projection is the
|
||
rectangular region shown
|
||
- 0 ≤ \e u ≤ K(<i>e</i><sup>2</sup>),
|
||
0 ≤ \e v ≤ K(1 − <i>e</i><sup>2</sup>)
|
||
.
|
||
The coloring of the lines is the same as Fig. 3(a), except that latitude
|
||
lines extended down to −10° and a red line has been added
|
||
showing the line \e y = 0 for \e x > 1.71 in the Gauss-Krüger
|
||
projection (Fig. 3(a)). The extended Thompson projection figure has
|
||
reflection symmetry on all the four sides of Fig. 3(c).
|
||
|
||
<center>
|
||
Back to \ref greatellipse. Forward to \ref geocentric. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page geocentric Geocentric coordinates
|
||
|
||
<center>
|
||
Back to \ref transversemercator. Forward to \ref auxlat. Up to \ref contents.
|
||
</center>
|
||
|
||
The implementation of Geocentric::Reverse is adapted from
|
||
- H. Vermeille,
|
||
<a href="https://doi.org/10.1007/s00190-002-0273-6">
|
||
Direct transformation from geocentric coordinates to geodetic
|
||
coordinates</a>, J. Geodesy 76, 451--454 (2002).
|
||
|
||
This provides a closed-form solution but can't directly be applied close to
|
||
the center of the earth. Several changes have been made to remove this
|
||
restriction and to improve the numerical accuracy. Now the method is
|
||
accurate for all inputs (even if \e h is infinite). The changes are
|
||
described in Appendix B of
|
||
- C. F. F. Karney,
|
||
<a href="https://arxiv.org/abs/1102.1215v1">Geodesics
|
||
on an ellipsoid of revolution</a>,
|
||
Feb. 2011; preprint
|
||
<a href="https://arxiv.org/abs/1102.1215v1">arxiv:1102.1215v1</a>.
|
||
.
|
||
Vermeille similarly updated his method in
|
||
- H. Vermeille,
|
||
<a href="https://doi.org/10.1007/s00190-010-0419-x">
|
||
An analytical method to transform geocentric into
|
||
geodetic coordinates</a>, J. Geodesy 85, 105--117 (2011).
|
||
|
||
The problems encountered near the center of the ellipsoid are:
|
||
- There's a potential division by zero in the definition of \e s. The
|
||
equations are easily reformulated to avoid this problem.
|
||
- <i>t</i><sup>3</sup> may be negative. This is OK; we just take the
|
||
real root.
|
||
- The solution for \e t may be complex. However this leads to 3 real roots
|
||
for <i>u</i>/\e r. It's then just a matter of picking the one that computes
|
||
the geodetic result which minimizes |<i>h</i>| and which avoids large
|
||
round-off errors.
|
||
- Some of the equations result in a large loss of accuracy due to
|
||
subtracting nearly equal quantities. E.g., \e k = sqrt(\e u + \e v +
|
||
<i>w</i><sup>2</sup>) − \e w is inaccurate if \e u + \e v is small;
|
||
we can fix this by writing \e k = (\e u + \e v)/(sqrt(\e u + \e v +
|
||
<i>w</i><sup>2</sup>) + \e w).
|
||
|
||
The error is computed as follows. Write a version of
|
||
Geocentric::WGS84.Forward which uses long doubles (including using long
|
||
doubles for the WGS84 parameters). Generate random (long double)
|
||
geodetic coordinates (\e lat0, \e lon0, \e h0) and use the "long double"
|
||
WGS84.Forward to obtain the corresponding (long double) geocentric
|
||
coordinates (\e x0, \e y0, \e z0). [We restrict \e h0 so that \e h0
|
||
≥ − \e a (1 − <i>e</i><sup>2</sup>) / sqrt(1 −
|
||
<i>e</i><sup>2</sup> sin<sup>2</sup>\e lat0), which ensures that (\e
|
||
lat0, \e lon0, \e h0) is the principal geodetic inverse of (\e x0, \e
|
||
y0, \e z0).] Because the forward calculation is numerically stable and
|
||
because long doubles (on Linux systems using g++) provide 11 bits
|
||
additional accuracy (about 3.3 decimal digits), we regard this set of
|
||
test data as exact.
|
||
|
||
Apply the double version of WGS84.Reverse to (\e x0, \e y0, \e z0) to
|
||
compute the approximate geodetic coordinates (\e lat1, \e lon1, \e h1).
|
||
Convert (\e lat1 − \e lat0, \e lon1 − \e lon0) to a
|
||
distance, \e ds, on the surface of the ellipsoid and define \e err =
|
||
hypot(\e ds, \e h1 − \e h0). For |<i>h0</i>| < 5000 km, we
|
||
have \e err < 7 nm (7 nanometers).
|
||
|
||
This methodology is not very useful very far from the globe, because the
|
||
absolute errors in the approximate geodetic height become large, or
|
||
within 50 km of the center of the earth, because of errors in
|
||
computing the approximate geodetic latitude. To illustrate the second
|
||
issue, the maximum value of \e err for \e h0 < 0 is about 80 mm.
|
||
The error is maximum close to the circle given by geocentric coordinates
|
||
satisfying hypot(\e x, \e y) = \e a <i>e</i><sup>2</sup> (=
|
||
42.7 km), \e z = 0. (This is the center of meridional curvature
|
||
for \e lat = 0.) The geodetic latitude for these points is \e lat = 0.
|
||
However, if we move 1 nm towards the center of the earth, the
|
||
geodetic latitude becomes 0.04", a distance of 1.4 m from the
|
||
equator. If, instead, we move 1 nm up, the geodetic latitude
|
||
becomes 7.45", a distance of 229 m from the equator. In light of
|
||
this, Reverse does quite well in this vicinity.
|
||
|
||
To obtain a practical measure of the error for the general case we define
|
||
- <i>err</i><sub>h</sub> = |\e h1 − <i>h0</i>| / max(1, \e h0 / \e a)
|
||
- for \e h0 > 0, <i>err</i><sub>out</sub> = \e ds
|
||
- for \e h0 < 0, apply the long double version of WGS84.Forward to (\e
|
||
lat1, \e lon1, \e h1) to give (\e x1, \e y1, \e z1) and compute
|
||
<i>err</i><sub>in</sub> = hypot(\e x1 − \e x0, \e y1 − \e
|
||
y0, \e z1 − \e z0).
|
||
.
|
||
We then find <i>err</i><sub>h</sub> < 8 nm,
|
||
<i>err</i><sub>out</sub> < 4 nm, and <i>err</i><sub>in</sub> <
|
||
7 nm (1 nm = 1 nanometer).
|
||
|
||
The testing has been confined to the WGS84 ellipsoid. The method will
|
||
work for all ellipsoids used in terrestrial geodesy. However, the
|
||
central region, which leads to multiple real roots for the cubic
|
||
equation in Reverse, pokes outside the ellipsoid (at the poles) for
|
||
ellipsoids with \e e > 1/sqrt(2); Reverse has not been analyzed for this
|
||
case. Similarly ellipsoids which are very nearly spherical may yield
|
||
inaccurate results due to underflow; in the other hand, the case of the
|
||
sphere, \e f = 0, is treated specially and gives accurate results.
|
||
|
||
Other comparable methods are K. M. Borkowski,
|
||
<a href="https://doi.org/10.1007/BF00643807"> Transformation
|
||
of geocentric to geodetic coordinates without approximations</a>,
|
||
Astrophys. Space Sci. 139, 1--4 (1987)
|
||
(<a href="https://doi.org/10.1007/BF00656995"> erratum</a>)
|
||
and T. Fukushima,
|
||
<a href="https://doi.org/10.1007/s001900050271"> Fast transform from
|
||
geocentric to geodetic coordinates</a>, J. Geodesy 73, 603--610 (1999).
|
||
However the choice of independent variables in these methods leads
|
||
to a loss of accuracy for points near the equatorial plane.
|
||
|
||
<center>
|
||
Back to \ref transversemercator. Forward to \ref auxlat. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page auxlat Auxiliary latitudes
|
||
|
||
<center>
|
||
Back to \ref geocentric. Forward to \ref highprec. Up to \ref contents.
|
||
</center>
|
||
|
||
This material is now written up as
|
||
- C. F. F. Karney,<br>
|
||
<a href="https://arxiv.org/abs/2212.05818">On auxiliary latitudes</a>,<br>
|
||
Technical Report, SRI International, December 2022.<br>
|
||
<a href="https://arxiv.org/abs/2212.05818">arxiv:2212.05818</a>
|
||
.
|
||
An implementation of the methods described in this paper is available in
|
||
the files <code>examples/AuxLatitude.[hc]pp</code> which provides the
|
||
classes AuxAngle and AuxLatitude. These classes are <b>not</b> yet part
|
||
of GeographicLib.
|
||
The series expansions described in the paper are available in
|
||
- C. F. F. Karney,<br>
|
||
<a href="https://doi.org/10.5281/zenodo.7382666">Series expansions
|
||
for converting between auxiliary latitudes</a>,<br>
|
||
December 2022.<br>
|
||
<a href="https://doi.org/10.5281/zenodo.7382666">
|
||
doi:10.5281/zenodo.7382666</a>
|
||
.
|
||
|
||
Go to
|
||
- \ref auxlatformula
|
||
- \ref auxlattable
|
||
- \ref auxlaterror
|
||
|
||
Six latitudes are used by GeographicLib:
|
||
- φ, the (geographic) latitude;
|
||
- β, the parametric latitude;
|
||
- θ, the geocentric latitude;
|
||
- μ, the rectifying latitude;
|
||
- χ, the conformal latitude;
|
||
- ξ, the authalic latitude.
|
||
.
|
||
The last five of these are called <i>auxiliary latitudes</i>. These
|
||
quantities are all defined in the
|
||
<a href="https://en.wikipedia.org/wiki/Latitude#Auxiliary_latitudes">
|
||
Wikipedia article on latitudes</a>. The Ellipsoid class contains
|
||
methods for converting all of these and the geographic latitude.
|
||
|
||
In addition there's the isometric latitude, ψ, defined by ψ =
|
||
gd<sup>−1</sup>χ = sinh<sup>−1</sup> tanχ and
|
||
χ = gdψ = tan<sup>−1</sup> sinhψ. This is not an
|
||
angle-like variable (for example, it diverges at the poles) and so we
|
||
don't treat it further here. However conversions between ψ and any
|
||
of the auxiliary latitudes is easily accomplished via an intermediate
|
||
conversion to χ.
|
||
|
||
The relations between φ, β, and θ are all simple
|
||
elementary functions. The latitudes χ and ξ can be expressed as
|
||
elementary functions of φ; however, these functions can only be
|
||
inverted iteratively. The rectifying latitude μ as a function of
|
||
φ (or β) involves the incomplete elliptic integral of the
|
||
second kind (which is not an elementary function) and this needs to be
|
||
inverted iteratively. The Ellipsoid class evaluates all the auxiliary
|
||
latitudes (and the corresponding inverse relations) in terms of their
|
||
basic definitions.
|
||
|
||
An alternative method of evaluating these auxiliary latitudes is in
|
||
terms of trigonometric series. This offers some advantages:
|
||
- these series give a uniform way of expressing any latitude in terms of
|
||
any other latitude;
|
||
- the evaluation may be faster, particularly if
|
||
<a href="https://en.wikipedia.org/wiki/Clenshaw_algorithm#Meridian_arc_length_on_the_ellipsoid">
|
||
Clenshaw summation</a> is used;
|
||
- provided that the flattening is sufficiently small, the result may be
|
||
more accurate (because the round-off errors are smaller).
|
||
|
||
Here we give the complete matrix of relations between all six latitudes;
|
||
there are 30 (= 6 × 5) such relations. These
|
||
expansions complement the work of
|
||
- O. S. Adams,
|
||
<a href="https://geodesy.noaa.gov/library/pdfs/Special_Publication_No_67.pdf">
|
||
Latitude developments connected with geodesy and cartography</a>,
|
||
Spec. Pub. 67 (US Coast and Geodetic Survey, 1921).
|
||
- P. Osborne,
|
||
<a href="https://dx.doi.org/10.5281/zenodo.35392">
|
||
The Mercator Projections</a> (2013), Chap. 5.
|
||
- S. Orihuela,
|
||
<a href="https://www.academia.edu/7580468/Funciones_de_Latitud">
|
||
Funciones de Latitud</a> (2013).
|
||
.
|
||
Here, the expansions are in terms of the third flattening <i>n</i> =
|
||
(<i>a</i> − <i>b</i>)/(<i>a</i> + <i>b</i>).
|
||
This choice of expansion parameter results in expansions in which half
|
||
the coefficients vanish for all relations between φ, β,
|
||
θ, and μ. In addition, the expansions converge for |<i>n</i>|
|
||
< 1 or <i>b</i>/<i>a</i> ∈ (0, ∞). These expansions
|
||
were obtained with the the maxima code, <a
|
||
href="auxlat.mac">auxlat.mac</a>.
|
||
|
||
Adams (1921) uses the eccentricity squared <i>e</i><sup>2</sup> as the
|
||
expansion parameter, but the resulting series only converge for
|
||
|<i>e</i><sup>2</sup>| < 1 or <i>b</i>/<i>a</i> ∈
|
||
(0, √2). In addition, it is shown in \ref auxlaterror, that
|
||
the errors when the series are truncated are much worse than for the
|
||
corresponding series in \e n.
|
||
|
||
\b NOTE: The assertions about convergence above are too optimistic.
|
||
Some of the series do indeed converge for |<i>n</i>| < 1. However
|
||
others have a smaller radius of convergence. More on this later…
|
||
|
||
\section auxlatformula Series approximations for conversions
|
||
|
||
Here are the relations between φ, β, θ, and μ carried
|
||
out to 4th order in <i>n</i>:
|
||
\f[
|
||
\begin{align}
|
||
\beta-\phi&=\textstyle{}
|
||
-n\sin 2\phi
|
||
+\frac{1}{2}n^{2}\sin 4\phi
|
||
-\frac{1}{3}n^{3}\sin 6\phi
|
||
+\frac{1}{4}n^{4}\sin 8\phi
|
||
-\ldots\\
|
||
\phi-\beta&=\textstyle{}
|
||
+n\sin 2\beta
|
||
+\frac{1}{2}n^{2}\sin 4\beta
|
||
+\frac{1}{3}n^{3}\sin 6\beta
|
||
+\frac{1}{4}n^{4}\sin 8\beta
|
||
+\ldots\\
|
||
\theta-\phi&=\textstyle{}
|
||
-\bigl(2n-2n^{3}\bigr)\sin 2\phi
|
||
+\bigl(2n^{2}-4n^{4}\bigr)\sin 4\phi
|
||
-\frac{8}{3}n^{3}\sin 6\phi
|
||
+4n^{4}\sin 8\phi
|
||
-\ldots\\
|
||
\phi-\theta&=\textstyle{}
|
||
+\bigl(2n-2n^{3}\bigr)\sin 2\theta
|
||
+\bigl(2n^{2}-4n^{4}\bigr)\sin 4\theta
|
||
+\frac{8}{3}n^{3}\sin 6\theta
|
||
+4n^{4}\sin 8\theta
|
||
+\ldots\\
|
||
\theta-\beta&=\textstyle{}
|
||
-n\sin 2\beta
|
||
+\frac{1}{2}n^{2}\sin 4\beta
|
||
-\frac{1}{3}n^{3}\sin 6\beta
|
||
+\frac{1}{4}n^{4}\sin 8\beta
|
||
-\ldots\\
|
||
\beta-\theta&=\textstyle{}
|
||
+n\sin 2\theta
|
||
+\frac{1}{2}n^{2}\sin 4\theta
|
||
+\frac{1}{3}n^{3}\sin 6\theta
|
||
+\frac{1}{4}n^{4}\sin 8\theta
|
||
+\ldots\\
|
||
\mu-\phi&=\textstyle{}
|
||
-\bigl(\frac{3}{2}n-\frac{9}{16}n^{3}\bigr)\sin 2\phi
|
||
+\bigl(\frac{15}{16}n^{2}-\frac{15}{32}n^{4}\bigr)\sin 4\phi
|
||
-\frac{35}{48}n^{3}\sin 6\phi
|
||
+\frac{315}{512}n^{4}\sin 8\phi
|
||
-\ldots\\
|
||
\phi-\mu&=\textstyle{}
|
||
+\bigl(\frac{3}{2}n-\frac{27}{32}n^{3}\bigr)\sin 2\mu
|
||
+\bigl(\frac{21}{16}n^{2}-\frac{55}{32}n^{4}\bigr)\sin 4\mu
|
||
+\frac{151}{96}n^{3}\sin 6\mu
|
||
+\frac{1097}{512}n^{4}\sin 8\mu
|
||
+\ldots\\
|
||
\mu-\beta&=\textstyle{}
|
||
-\bigl(\frac{1}{2}n-\frac{3}{16}n^{3}\bigr)\sin 2\beta
|
||
-\bigl(\frac{1}{16}n^{2}-\frac{1}{32}n^{4}\bigr)\sin 4\beta
|
||
-\frac{1}{48}n^{3}\sin 6\beta
|
||
-\frac{5}{512}n^{4}\sin 8\beta
|
||
-\ldots\\
|
||
\beta-\mu&=\textstyle{}
|
||
+\bigl(\frac{1}{2}n-\frac{9}{32}n^{3}\bigr)\sin 2\mu
|
||
+\bigl(\frac{5}{16}n^{2}-\frac{37}{96}n^{4}\bigr)\sin 4\mu
|
||
+\frac{29}{96}n^{3}\sin 6\mu
|
||
+\frac{539}{1536}n^{4}\sin 8\mu
|
||
+\ldots\\
|
||
\mu-\theta&=\textstyle{}
|
||
+\bigl(\frac{1}{2}n+\frac{13}{16}n^{3}\bigr)\sin 2\theta
|
||
-\bigl(\frac{1}{16}n^{2}-\frac{33}{32}n^{4}\bigr)\sin 4\theta
|
||
-\frac{5}{16}n^{3}\sin 6\theta
|
||
-\frac{261}{512}n^{4}\sin 8\theta
|
||
-\ldots\\
|
||
\theta-\mu&=\textstyle{}
|
||
-\bigl(\frac{1}{2}n+\frac{23}{32}n^{3}\bigr)\sin 2\mu
|
||
+\bigl(\frac{5}{16}n^{2}-\frac{5}{96}n^{4}\bigr)\sin 4\mu
|
||
+\frac{1}{32}n^{3}\sin 6\mu
|
||
+\frac{283}{1536}n^{4}\sin 8\mu
|
||
+\ldots\\
|
||
\end{align}
|
||
\f]
|
||
|
||
Here are the remaining relations (including χ and ξ) carried out
|
||
to 3rd order in <i>n</i>:
|
||
\f[
|
||
\begin{align}
|
||
\chi-\phi&=\textstyle{}
|
||
-\bigl(2n-\frac{2}{3}n^{2}-\frac{4}{3}n^{3}\bigr)\sin 2\phi
|
||
+\bigl(\frac{5}{3}n^{2}-\frac{16}{15}n^{3}\bigr)\sin 4\phi
|
||
-\frac{26}{15}n^{3}\sin 6\phi
|
||
+\ldots\\
|
||
\phi-\chi&=\textstyle{}
|
||
+\bigl(2n-\frac{2}{3}n^{2}-2n^{3}\bigr)\sin 2\chi
|
||
+\bigl(\frac{7}{3}n^{2}-\frac{8}{5}n^{3}\bigr)\sin 4\chi
|
||
+\frac{56}{15}n^{3}\sin 6\chi
|
||
+\ldots\\
|
||
\chi-\beta&=\textstyle{}
|
||
-\bigl(n-\frac{2}{3}n^{2}\bigr)\sin 2\beta
|
||
+\bigl(\frac{1}{6}n^{2}-\frac{2}{5}n^{3}\bigr)\sin 4\beta
|
||
-\frac{1}{15}n^{3}\sin 6\beta
|
||
+\ldots\\
|
||
\beta-\chi&=\textstyle{}
|
||
+\bigl(n-\frac{2}{3}n^{2}-\frac{1}{3}n^{3}\bigr)\sin 2\chi
|
||
+\bigl(\frac{5}{6}n^{2}-\frac{14}{15}n^{3}\bigr)\sin 4\chi
|
||
+\frac{16}{15}n^{3}\sin 6\chi
|
||
+\ldots\\
|
||
\chi-\theta&=\textstyle{}
|
||
+\bigl(\frac{2}{3}n^{2}+\frac{2}{3}n^{3}\bigr)\sin 2\theta
|
||
-\bigl(\frac{1}{3}n^{2}-\frac{4}{15}n^{3}\bigr)\sin 4\theta
|
||
-\frac{2}{5}n^{3}\sin 6\theta
|
||
-\ldots\\
|
||
\theta-\chi&=\textstyle{}
|
||
-\bigl(\frac{2}{3}n^{2}+\frac{2}{3}n^{3}\bigr)\sin 2\chi
|
||
+\bigl(\frac{1}{3}n^{2}-\frac{4}{15}n^{3}\bigr)\sin 4\chi
|
||
+\frac{2}{5}n^{3}\sin 6\chi
|
||
+\ldots\\
|
||
\chi-\mu&=\textstyle{}
|
||
-\bigl(\frac{1}{2}n-\frac{2}{3}n^{2}+\frac{37}{96}n^{3}\bigr)\sin 2\mu
|
||
-\bigl(\frac{1}{48}n^{2}+\frac{1}{15}n^{3}\bigr)\sin 4\mu
|
||
-\frac{17}{480}n^{3}\sin 6\mu
|
||
-\ldots\\
|
||
\mu-\chi&=\textstyle{}
|
||
+\bigl(\frac{1}{2}n-\frac{2}{3}n^{2}+\frac{5}{16}n^{3}\bigr)\sin 2\chi
|
||
+\bigl(\frac{13}{48}n^{2}-\frac{3}{5}n^{3}\bigr)\sin 4\chi
|
||
+\frac{61}{240}n^{3}\sin 6\chi
|
||
+\ldots\\
|
||
\xi-\phi&=\textstyle{}
|
||
-\bigl(\frac{4}{3}n+\frac{4}{45}n^{2}-\frac{88}{315}n^{3}\bigr)\sin 2\phi
|
||
+\bigl(\frac{34}{45}n^{2}+\frac{8}{105}n^{3}\bigr)\sin 4\phi
|
||
-\frac{1532}{2835}n^{3}\sin 6\phi
|
||
+\ldots\\
|
||
\phi-\xi&=\textstyle{}
|
||
+\bigl(\frac{4}{3}n+\frac{4}{45}n^{2}-\frac{16}{35}n^{3}\bigr)\sin 2\xi
|
||
+\bigl(\frac{46}{45}n^{2}+\frac{152}{945}n^{3}\bigr)\sin 4\xi
|
||
+\frac{3044}{2835}n^{3}\sin 6\xi
|
||
+\ldots\\
|
||
\xi-\beta&=\textstyle{}
|
||
-\bigl(\frac{1}{3}n+\frac{4}{45}n^{2}-\frac{32}{315}n^{3}\bigr)\sin 2\beta
|
||
-\bigl(\frac{7}{90}n^{2}+\frac{4}{315}n^{3}\bigr)\sin 4\beta
|
||
-\frac{83}{2835}n^{3}\sin 6\beta
|
||
-\ldots\\
|
||
\beta-\xi&=\textstyle{}
|
||
+\bigl(\frac{1}{3}n+\frac{4}{45}n^{2}-\frac{46}{315}n^{3}\bigr)\sin 2\xi
|
||
+\bigl(\frac{17}{90}n^{2}+\frac{68}{945}n^{3}\bigr)\sin 4\xi
|
||
+\frac{461}{2835}n^{3}\sin 6\xi
|
||
+\ldots\\
|
||
\xi-\theta&=\textstyle{}
|
||
+\bigl(\frac{2}{3}n-\frac{4}{45}n^{2}+\frac{62}{105}n^{3}\bigr)\sin 2\theta
|
||
+\bigl(\frac{4}{45}n^{2}-\frac{32}{315}n^{3}\bigr)\sin 4\theta
|
||
-\frac{524}{2835}n^{3}\sin 6\theta
|
||
-\ldots\\
|
||
\theta-\xi&=\textstyle{}
|
||
-\bigl(\frac{2}{3}n-\frac{4}{45}n^{2}+\frac{158}{315}n^{3}\bigr)\sin 2\xi
|
||
+\bigl(\frac{16}{45}n^{2}-\frac{16}{945}n^{3}\bigr)\sin 4\xi
|
||
-\frac{232}{2835}n^{3}\sin 6\xi
|
||
+\ldots\\
|
||
\xi-\mu&=\textstyle{}
|
||
+\bigl(\frac{1}{6}n-\frac{4}{45}n^{2}-\frac{817}{10080}n^{3}\bigr)\sin 2\mu
|
||
+\bigl(\frac{49}{720}n^{2}-\frac{2}{35}n^{3}\bigr)\sin 4\mu
|
||
+\frac{4463}{90720}n^{3}\sin 6\mu
|
||
+\ldots\\
|
||
\mu-\xi&=\textstyle{}
|
||
-\bigl(\frac{1}{6}n-\frac{4}{45}n^{2}-\frac{121}{1680}n^{3}\bigr)\sin 2\xi
|
||
-\bigl(\frac{29}{720}n^{2}-\frac{26}{945}n^{3}\bigr)\sin 4\xi
|
||
-\frac{1003}{45360}n^{3}\sin 6\xi
|
||
-\ldots\\
|
||
\xi-\chi&=\textstyle{}
|
||
+\bigl(\frac{2}{3}n-\frac{34}{45}n^{2}+\frac{46}{315}n^{3}\bigr)\sin 2\chi
|
||
+\bigl(\frac{19}{45}n^{2}-\frac{256}{315}n^{3}\bigr)\sin 4\chi
|
||
+\frac{248}{567}n^{3}\sin 6\chi
|
||
+\ldots\\
|
||
\chi-\xi&=\textstyle{}
|
||
-\bigl(\frac{2}{3}n-\frac{34}{45}n^{2}+\frac{88}{315}n^{3}\bigr)\sin 2\xi
|
||
+\bigl(\frac{1}{45}n^{2}-\frac{184}{945}n^{3}\bigr)\sin 4\xi
|
||
-\frac{106}{2835}n^{3}\sin 6\xi
|
||
-\ldots\\
|
||
\end{align}
|
||
\f]
|
||
|
||
\section auxlattable Series approximations in tabular form
|
||
|
||
Finally, this is a listing of all the coefficients for the expansions
|
||
carried out to 8th order in <i>n</i>. Here's how to interpret this
|
||
data: the 5th line for φ − θ is <tt>[32/5, 0,
|
||
-32, 0]</tt>; this means that the coefficient of sin(10θ) is
|
||
[(32/5)<i>n</i><sup>5</sup> −
|
||
32<i>n</i><sup>7</sup> + <i>O</i>(<i>n</i><sup>9</sup>)].
|
||
<p>β − φ:<br><tt><small>
|
||
[-1, 0, 0, 0, 0, 0, 0, 0]<br>
|
||
[1/2, 0, 0, 0, 0, 0, 0]<br>
|
||
[-1/3, 0, 0, 0, 0, 0]<br>
|
||
[1/4, 0, 0, 0, 0]<br>
|
||
[-1/5, 0, 0, 0]<br>
|
||
[1/6, 0, 0]<br>
|
||
[-1/7, 0]<br>
|
||
[1/8]<br>
|
||
</small></tt>
|
||
<p>φ − β:<br><tt><small>
|
||
[1, 0, 0, 0, 0, 0, 0, 0]<br>
|
||
[1/2, 0, 0, 0, 0, 0, 0]<br>
|
||
[1/3, 0, 0, 0, 0, 0]<br>
|
||
[1/4, 0, 0, 0, 0]<br>
|
||
[1/5, 0, 0, 0]<br>
|
||
[1/6, 0, 0]<br>
|
||
[1/7, 0]<br>
|
||
[1/8]<br>
|
||
</small></tt>
|
||
<p>θ − φ:<br><tt><small>
|
||
[-2, 0, 2, 0, -2, 0, 2, 0]<br>
|
||
[2, 0, -4, 0, 6, 0, -8]<br>
|
||
[-8/3, 0, 8, 0, -16, 0]<br>
|
||
[4, 0, -16, 0, 40]<br>
|
||
[-32/5, 0, 32, 0]<br>
|
||
[32/3, 0, -64]<br>
|
||
[-128/7, 0]<br>
|
||
[32]<br>
|
||
</small></tt>
|
||
<p>φ − θ:<br><tt><small>
|
||
[2, 0, -2, 0, 2, 0, -2, 0]<br>
|
||
[2, 0, -4, 0, 6, 0, -8]<br>
|
||
[8/3, 0, -8, 0, 16, 0]<br>
|
||
[4, 0, -16, 0, 40]<br>
|
||
[32/5, 0, -32, 0]<br>
|
||
[32/3, 0, -64]<br>
|
||
[128/7, 0]<br>
|
||
[32]<br>
|
||
</small></tt>
|
||
<p>θ − β:<br><tt><small>
|
||
[-1, 0, 0, 0, 0, 0, 0, 0]<br>
|
||
[1/2, 0, 0, 0, 0, 0, 0]<br>
|
||
[-1/3, 0, 0, 0, 0, 0]<br>
|
||
[1/4, 0, 0, 0, 0]<br>
|
||
[-1/5, 0, 0, 0]<br>
|
||
[1/6, 0, 0]<br>
|
||
[-1/7, 0]<br>
|
||
[1/8]<br>
|
||
</small></tt>
|
||
<p>β − θ:<br><tt><small>
|
||
[1, 0, 0, 0, 0, 0, 0, 0]<br>
|
||
[1/2, 0, 0, 0, 0, 0, 0]<br>
|
||
[1/3, 0, 0, 0, 0, 0]<br>
|
||
[1/4, 0, 0, 0, 0]<br>
|
||
[1/5, 0, 0, 0]<br>
|
||
[1/6, 0, 0]<br>
|
||
[1/7, 0]<br>
|
||
[1/8]<br>
|
||
</small></tt>
|
||
<p>μ − φ:<br><tt><small>
|
||
[-3/2, 0, 9/16, 0, -3/32, 0, 57/2048, 0]<br>
|
||
[15/16, 0, -15/32, 0, 135/2048, 0, -105/4096]<br>
|
||
[-35/48, 0, 105/256, 0, -105/2048, 0]<br>
|
||
[315/512, 0, -189/512, 0, 693/16384]<br>
|
||
[-693/1280, 0, 693/2048, 0]<br>
|
||
[1001/2048, 0, -1287/4096]<br>
|
||
[-6435/14336, 0]<br>
|
||
[109395/262144]<br>
|
||
</small></tt>
|
||
<p>φ − μ:<br><tt><small>
|
||
[3/2, 0, -27/32, 0, 269/512, 0, -6607/24576, 0]<br>
|
||
[21/16, 0, -55/32, 0, 6759/4096, 0, -155113/122880]<br>
|
||
[151/96, 0, -417/128, 0, 87963/20480, 0]<br>
|
||
[1097/512, 0, -15543/2560, 0, 2514467/245760]<br>
|
||
[8011/2560, 0, -69119/6144, 0]<br>
|
||
[293393/61440, 0, -5962461/286720]<br>
|
||
[6459601/860160, 0]<br>
|
||
[332287993/27525120]<br>
|
||
</small></tt>
|
||
<p>μ − β:<br><tt><small>
|
||
[-1/2, 0, 3/16, 0, -1/32, 0, 19/2048, 0]<br>
|
||
[-1/16, 0, 1/32, 0, -9/2048, 0, 7/4096]<br>
|
||
[-1/48, 0, 3/256, 0, -3/2048, 0]<br>
|
||
[-5/512, 0, 3/512, 0, -11/16384]<br>
|
||
[-7/1280, 0, 7/2048, 0]<br>
|
||
[-7/2048, 0, 9/4096]<br>
|
||
[-33/14336, 0]<br>
|
||
[-429/262144]<br>
|
||
</small></tt>
|
||
<p>β − μ:<br><tt><small>
|
||
[1/2, 0, -9/32, 0, 205/1536, 0, -4879/73728, 0]<br>
|
||
[5/16, 0, -37/96, 0, 1335/4096, 0, -86171/368640]<br>
|
||
[29/96, 0, -75/128, 0, 2901/4096, 0]<br>
|
||
[539/1536, 0, -2391/2560, 0, 1082857/737280]<br>
|
||
[3467/7680, 0, -28223/18432, 0]<br>
|
||
[38081/61440, 0, -733437/286720]<br>
|
||
[459485/516096, 0]<br>
|
||
[109167851/82575360]<br>
|
||
</small></tt>
|
||
<p>μ − θ:<br><tt><small>
|
||
[1/2, 0, 13/16, 0, -15/32, 0, 509/2048, 0]<br>
|
||
[-1/16, 0, 33/32, 0, -1673/2048, 0, 2599/4096]<br>
|
||
[-5/16, 0, 349/256, 0, -2989/2048, 0]<br>
|
||
[-261/512, 0, 963/512, 0, -43531/16384]<br>
|
||
[-921/1280, 0, 5545/2048, 0]<br>
|
||
[-6037/6144, 0, 16617/4096]<br>
|
||
[-19279/14336, 0]<br>
|
||
[-490925/262144]<br>
|
||
</small></tt>
|
||
<p>θ − μ:<br><tt><small>
|
||
[-1/2, 0, -23/32, 0, 499/1536, 0, -14321/73728, 0]<br>
|
||
[5/16, 0, -5/96, 0, 6565/12288, 0, -201467/368640]<br>
|
||
[1/32, 0, -77/128, 0, 2939/4096, 0]<br>
|
||
[283/1536, 0, -4037/7680, 0, 1155049/737280]<br>
|
||
[1301/7680, 0, -19465/18432, 0]<br>
|
||
[17089/61440, 0, -442269/286720]<br>
|
||
[198115/516096, 0]<br>
|
||
[48689387/82575360]<br>
|
||
</small></tt>
|
||
<p>χ − φ:<br><tt><small>
|
||
[-2, 2/3, 4/3, -82/45, 32/45, 4642/4725, -8384/4725, 1514/1323]<br>
|
||
[5/3, -16/15, -13/9, 904/315, -1522/945, -2288/1575, 142607/42525]<br>
|
||
[-26/15, 34/21, 8/5, -12686/2835, 44644/14175, 120202/51975]<br>
|
||
[1237/630, -12/5, -24832/14175, 1077964/155925, -1097407/187110]<br>
|
||
[-734/315, 109598/31185, 1040/567, -12870194/1216215]<br>
|
||
[444337/155925, -941912/184275, -126463/72765]<br>
|
||
[-2405834/675675, 3463678/467775]<br>
|
||
[256663081/56756700]<br>
|
||
</small></tt>
|
||
<p>φ − χ:<br><tt><small>
|
||
[2, -2/3, -2, 116/45, 26/45, -2854/675, 16822/4725, 189416/99225]<br>
|
||
[7/3, -8/5, -227/45, 2704/315, 2323/945, -31256/1575, 141514/8505]<br>
|
||
[56/15, -136/35, -1262/105, 73814/2835, 98738/14175, -2363828/31185]<br>
|
||
[4279/630, -332/35, -399572/14175, 11763988/155925, 14416399/935550]<br>
|
||
[4174/315, -144838/6237, -2046082/31185, 258316372/1216215]<br>
|
||
[601676/22275, -115444544/2027025, -2155215124/14189175]<br>
|
||
[38341552/675675, -170079376/1216215]<br>
|
||
[1383243703/11351340]<br>
|
||
</small></tt>
|
||
<p>χ − β:<br><tt><small>
|
||
[-1, 2/3, 0, -16/45, 2/5, -998/4725, -34/4725, 1384/11025]<br>
|
||
[1/6, -2/5, 19/45, -22/105, -2/27, 1268/4725, -12616/42525]<br>
|
||
[-1/15, 16/105, -22/105, 116/567, -1858/14175, 1724/51975]<br>
|
||
[17/1260, -8/105, 2123/14175, -26836/155925, 115249/935550]<br>
|
||
[-1/105, 128/4455, -424/6237, 140836/1216215]<br>
|
||
[149/311850, -31232/2027025, 210152/4729725]<br>
|
||
[-499/225225, 30208/6081075]<br>
|
||
[-68251/113513400]<br>
|
||
</small></tt>
|
||
<p>β − χ:<br><tt><small>
|
||
[1, -2/3, -1/3, 38/45, -1/3, -3118/4725, 4769/4725, -25666/99225]<br>
|
||
[5/6, -14/15, -7/9, 50/21, -247/270, -14404/4725, 193931/42525]<br>
|
||
[16/15, -34/21, -5/3, 17564/2835, -36521/14175, -1709614/155925]<br>
|
||
[2069/1260, -28/9, -49877/14175, 2454416/155925, -637699/85050]<br>
|
||
[883/315, -28244/4455, -20989/2835, 48124558/1216215]<br>
|
||
[797222/155925, -2471888/184275, -16969807/1091475]<br>
|
||
[2199332/225225, -1238578/42525]<br>
|
||
[87600385/4540536]<br>
|
||
</small></tt>
|
||
<p>χ − θ:<br><tt><small>
|
||
[0, 2/3, 2/3, -2/9, -14/45, 1042/4725, 18/175, -1738/11025]<br>
|
||
[-1/3, 4/15, 43/45, -4/45, -712/945, 332/945, 23159/42525]<br>
|
||
[-2/5, 2/105, 124/105, 274/2835, -1352/945, 13102/31185]<br>
|
||
[-55/126, -16/105, 21068/14175, 1528/4725, -2414843/935550]<br>
|
||
[-22/45, -9202/31185, 20704/10395, 60334/93555]<br>
|
||
[-90263/155925, -299444/675675, 40458083/14189175]<br>
|
||
[-8962/12285, -3818498/6081075]<br>
|
||
[-4259027/4365900]<br>
|
||
</small></tt>
|
||
<p>θ − χ:<br><tt><small>
|
||
[0, -2/3, -2/3, 4/9, 2/9, -3658/4725, 76/225, 64424/99225]<br>
|
||
[1/3, -4/15, -23/45, 68/45, 61/135, -2728/945, 2146/1215]<br>
|
||
[2/5, -24/35, -46/35, 9446/2835, 428/945, -95948/10395]<br>
|
||
[83/126, -80/63, -34712/14175, 4472/525, 29741/85050]<br>
|
||
[52/45, -2362/891, -17432/3465, 280108/13365]<br>
|
||
[335882/155925, -548752/96525, -48965632/4729725]<br>
|
||
[51368/12285, -197456/15795]<br>
|
||
[1461335/174636]<br>
|
||
</small></tt>
|
||
<p>χ − μ:<br><tt><small>
|
||
[-1/2, 2/3, -37/96, 1/360, 81/512, -96199/604800, 5406467/38707200, -7944359/67737600]<br>
|
||
[-1/48, -1/15, 437/1440, -46/105, 1118711/3870720, -51841/1209600, -24749483/348364800]<br>
|
||
[-17/480, 37/840, 209/4480, -5569/90720, -9261899/58060800, 6457463/17740800]<br>
|
||
[-4397/161280, 11/504, 830251/7257600, -466511/2494800, -324154477/7664025600]<br>
|
||
[-4583/161280, 108847/3991680, 8005831/63866880, -22894433/124540416]<br>
|
||
[-20648693/638668800, 16363163/518918400, 2204645983/12915302400]<br>
|
||
[-219941297/5535129600, 497323811/12454041600]<br>
|
||
[-191773887257/3719607091200]<br>
|
||
</small></tt>
|
||
<p>μ − χ:<br><tt><small>
|
||
[1/2, -2/3, 5/16, 41/180, -127/288, 7891/37800, 72161/387072, -18975107/50803200]<br>
|
||
[13/48, -3/5, 557/1440, 281/630, -1983433/1935360, 13769/28800, 148003883/174182400]<br>
|
||
[61/240, -103/140, 15061/26880, 167603/181440, -67102379/29030400, 79682431/79833600]<br>
|
||
[49561/161280, -179/168, 6601661/7257600, 97445/49896, -40176129013/7664025600]<br>
|
||
[34729/80640, -3418889/1995840, 14644087/9123840, 2605413599/622702080]<br>
|
||
[212378941/319334400, -30705481/10378368, 175214326799/58118860800]<br>
|
||
[1522256789/1383782400, -16759934899/3113510400]<br>
|
||
[1424729850961/743921418240]<br>
|
||
</small></tt>
|
||
<p>ξ − φ:<br><tt><small>
|
||
[-4/3, -4/45, 88/315, 538/4725, 20824/467775, -44732/2837835, -86728/16372125, -88002076/13956067125]<br>
|
||
[34/45, 8/105, -2482/14175, -37192/467775, -12467764/212837625, -895712/147349125, -2641983469/488462349375]<br>
|
||
[-1532/2835, -898/14175, 54968/467775, 100320856/1915538625, 240616/4209975, 8457703444/488462349375]<br>
|
||
[6007/14175, 24496/467775, -5884124/70945875, -4832848/147349125, -4910552477/97692469875]<br>
|
||
[-23356/66825, -839792/19348875, 816824/13395375, 9393713176/488462349375]<br>
|
||
[570284222/1915538625, 1980656/54729675, -4532926649/97692469875]<br>
|
||
[-496894276/1915538625, -14848113968/488462349375]<br>
|
||
[224557742191/976924698750]<br>
|
||
</small></tt>
|
||
<p>φ − ξ:<br><tt><small>
|
||
[4/3, 4/45, -16/35, -2582/14175, 60136/467775, 28112932/212837625, 22947844/1915538625, -1683291094/37574026875]<br>
|
||
[46/45, 152/945, -11966/14175, -21016/51975, 251310128/638512875, 1228352/3007125, -14351220203/488462349375]<br>
|
||
[3044/2835, 3802/14175, -94388/66825, -8797648/10945935, 138128272/147349125, 505559334506/488462349375]<br>
|
||
[6059/4725, 41072/93555, -1472637812/638512875, -45079184/29469825, 973080708361/488462349375]<br>
|
||
[768272/467775, 455935736/638512875, -550000184/147349125, -1385645336626/488462349375]<br>
|
||
[4210684958/1915538625, 443810768/383107725, -2939205114427/488462349375]<br>
|
||
[387227992/127702575, 101885255158/54273594375]<br>
|
||
[1392441148867/325641566250]<br>
|
||
</small></tt>
|
||
<p>ξ − β:<br><tt><small>
|
||
[-1/3, -4/45, 32/315, 34/675, 2476/467775, -70496/8513505, -18484/4343625, 29232878/97692469875]<br>
|
||
[-7/90, -4/315, 74/2025, 3992/467775, 53836/212837625, -4160804/1915538625, -324943819/488462349375]<br>
|
||
[-83/2835, 2/14175, 7052/467775, -661844/1915538625, 237052/383107725, -168643106/488462349375]<br>
|
||
[-797/56700, 934/467775, 1425778/212837625, -2915326/1915538625, 113042383/97692469875]<br>
|
||
[-3673/467775, 390088/212837625, 6064888/1915538625, -558526274/488462349375]<br>
|
||
[-18623681/3831077250, 41288/29469825, 155665021/97692469875]<br>
|
||
[-6205669/1915538625, 504234982/488462349375]<br>
|
||
[-8913001661/3907698795000]<br>
|
||
</small></tt>
|
||
<p>β − ξ:<br><tt><small>
|
||
[1/3, 4/45, -46/315, -1082/14175, 11824/467775, 7947332/212837625, 9708931/1915538625, -5946082372/488462349375]<br>
|
||
[17/90, 68/945, -338/2025, -16672/155925, 39946703/638512875, 164328266/1915538625, 190673521/69780335625]<br>
|
||
[461/2835, 1102/14175, -101069/467775, -255454/1563705, 236067184/1915538625, 86402898356/488462349375]<br>
|
||
[3161/18900, 1786/18711, -189032762/638512875, -98401826/383107725, 110123070361/488462349375]<br>
|
||
[88868/467775, 80274086/638512875, -802887278/1915538625, -200020620676/488462349375]<br>
|
||
[880980241/3831077250, 66263486/383107725, -296107325077/488462349375]<br>
|
||
[37151038/127702575, 4433064236/18091198125]<br>
|
||
[495248998393/1302566265000]<br>
|
||
</small></tt>
|
||
<p>ξ − θ:<br><tt><small>
|
||
[2/3, -4/45, 62/105, 778/4725, -193082/467775, -4286228/42567525, 53702182/212837625, 182466964/8881133625]<br>
|
||
[4/45, -32/315, 12338/14175, 92696/467775, -61623938/70945875, -32500616/273648375, 367082779691/488462349375]<br>
|
||
[-524/2835, -1618/14175, 612536/467775, 427003576/1915538625, -663111728/383107725, -42668482796/488462349375]<br>
|
||
[-5933/14175, -8324/66825, 427770788/212837625, 421877252/1915538625, -327791986997/97692469875]<br>
|
||
[-320044/467775, -9153184/70945875, 6024982024/1915538625, 74612072536/488462349375]<br>
|
||
[-1978771378/1915538625, -46140784/383107725, 489898512247/97692469875]<br>
|
||
[-2926201612/1915538625, -42056042768/488462349375]<br>
|
||
[-2209250801969/976924698750]<br>
|
||
</small></tt>
|
||
<p>θ − ξ:<br><tt><small>
|
||
[-2/3, 4/45, -158/315, -2102/14175, 109042/467775, 216932/2627625, -189115382/1915538625, -230886326/6343666875]<br>
|
||
[16/45, -16/945, 934/14175, -7256/155925, 117952358/638512875, 288456008/1915538625, -11696145869/69780335625]<br>
|
||
[-232/2835, 922/14175, -25286/66825, -7391576/54729675, 478700902/1915538625, 91546732346/488462349375]<br>
|
||
[719/4725, 268/18711, -67048172/638512875, -67330724/383107725, 218929662961/488462349375]<br>
|
||
[14354/467775, 46774256/638512875, -117954842/273648375, -129039188386/488462349375]<br>
|
||
[253129538/1915538625, 2114368/34827975, -178084928947/488462349375]<br>
|
||
[13805944/127702575, 6489189398/54273594375]<br>
|
||
[59983985827/325641566250]<br>
|
||
</small></tt>
|
||
<p>ξ − μ:<br><tt><small>
|
||
[1/6, -4/45, -817/10080, 1297/18900, 7764059/239500800, -9292991/302702400, -25359310709/1743565824000, 39534358147/2858202547200]<br>
|
||
[49/720, -2/35, -29609/453600, 35474/467775, 36019108271/871782912000, -14814966289/245188944000, -13216941177599/571640509440000]<br>
|
||
[4463/90720, -2917/56700, -4306823/59875200, 3026004511/30648618000, 99871724539/1569209241600, -27782109847927/250092722880000]<br>
|
||
[331799/7257600, -102293/1871100, -368661577/4036032000, 2123926699/15324309000, 168979300892599/1600593426432000]<br>
|
||
[11744233/239500800, -875457073/13621608000, -493031379277/3923023104000, 1959350112697/9618950880000]<br>
|
||
[453002260127/7846046208000, -793693009/9807557760, -145659994071373/800296713216000]<br>
|
||
[103558761539/1426553856000, -53583096419057/500185445760000]<br>
|
||
[12272105438887727/128047474114560000]<br>
|
||
</small></tt>
|
||
<p>μ − ξ:<br><tt><small>
|
||
[-1/6, 4/45, 121/1680, -1609/28350, -384229/14968800, 12674323/851350500, 7183403063/560431872000, -375027460897/125046361440000]<br>
|
||
[-29/720, 26/945, 16463/453600, -431/17325, -31621753811/1307674368000, 1117820213/122594472000, 30410873385097/2000741783040000]<br>
|
||
[-1003/45360, 449/28350, 3746047/119750400, -32844781/1751349600, -116359346641/3923023104000, 151567502183/17863765920000]<br>
|
||
[-40457/2419200, 629/53460, 10650637121/326918592000, -13060303/766215450, -317251099510901/8002967132160000]<br>
|
||
[-1800439/119750400, 205072597/20432412000, 146875240637/3923023104000, -2105440822861/125046361440000]<br>
|
||
[-59109051671/3923023104000, 228253559/24518894400, 91496147778023/2000741783040000]<br>
|
||
[-4255034947/261534873600, 126430355893/13894040160000]<br>
|
||
[-791820407649841/42682491371520000]<br>
|
||
</small></tt>
|
||
<p>ξ − χ:<br><tt><small>
|
||
[2/3, -34/45, 46/315, 2458/4725, -55222/93555, 2706758/42567525, 16676974/30405375, -64724382148/97692469875]<br>
|
||
[19/45, -256/315, 3413/14175, 516944/467775, -340492279/212837625, 158999572/1915538625, 85904355287/37574026875]<br>
|
||
[248/567, -15958/14175, 206834/467775, 4430783356/1915538625, -7597644214/1915538625, 2986003168/37574026875]<br>
|
||
[16049/28350, -832976/467775, 62016436/70945875, 851209552/174139875, -375566203/39037950]<br>
|
||
[15602/18711, -651151712/212837625, 3475643362/1915538625, 5106181018156/488462349375]<br>
|
||
[2561772812/1915538625, -10656173804/1915538625, 34581190223/8881133625]<br>
|
||
[873037408/383107725, -5150169424688/488462349375]<br>
|
||
[7939103697617/1953849397500]<br>
|
||
</small></tt>
|
||
<p>χ − ξ:<br><tt><small>
|
||
[-2/3, 34/45, -88/315, -2312/14175, 27128/93555, -55271278/212837625, 308365186/1915538625, -17451293242/488462349375]<br>
|
||
[1/45, -184/945, 6079/14175, -65864/155925, 106691108/638512875, 149984636/1915538625, -101520127208/488462349375]<br>
|
||
[-106/2835, 772/14175, -14246/467775, 5921152/54729675, -99534832/383107725, 10010741462/37574026875]<br>
|
||
[-167/9450, -5312/467775, 75594328/638512875, -35573728/273648375, 1615002539/75148053750]<br>
|
||
[-248/13365, 2837636/638512875, 130601488/1915538625, -3358119706/488462349375]<br>
|
||
[-34761247/1915538625, -3196/3553875, 46771947158/488462349375]<br>
|
||
[-2530364/127702575, -18696014/18091198125]<br>
|
||
[-14744861191/651283132500]<br>
|
||
</small></tt>
|
||
|
||
\section auxlaterror Truncation errors
|
||
|
||
There are two sources of error when using these series. The truncation
|
||
error arises from retaing terms up to a certain order in \e n; it is the
|
||
absolute difference between the value of the truncated series compared
|
||
with the exact latitude (evaluated with exact arithmetic). In addition,
|
||
using standard double-precision arithmetic entails accumulating
|
||
round-off errors so that at the end of a complex calculation a few of
|
||
the trailing bits of the result are wrong.
|
||
|
||
Here's a table of the truncation errors. The errors are given in "units
|
||
in the last place (ulp)" where 1 ulp = 2<sup>−53</sup> radian =
|
||
6.4 × 10<sup>−15</sup> degree = 2.3 ×
|
||
10<sup>−11</sup> arcsecond which is a measure of the round-off
|
||
error for double precision. Here is some rough guidance on how to
|
||
interpret these errors:
|
||
- if the truncation error is less than 1 ulp, then round-off errors
|
||
dominate;
|
||
- if the truncation error is greater than 8 ulp, then truncation errors
|
||
dominate;
|
||
- otherwise, round-off and truncation errors are comparable.
|
||
.
|
||
The truncation errors are given accurate to 2 significant figures.
|
||
|
||
<center>
|
||
<table>
|
||
<caption>Auxiliary latitude truncation errors (ulp)</caption>
|
||
<tr>
|
||
<th rowspan="2"> expression
|
||
<th colspan="2"> [<i>f</i> = 1/150, order = 6]
|
||
<th colspan="2"> [<i>f</i> = 1/297, order = 5]
|
||
<tr>
|
||
<th> <i>n</i> series <th> <i>e</i><sup>2</sup> series
|
||
<th> <i>n</i> series <th> <i>e</i><sup>2</sup> series
|
||
<tr><td> β − φ <td><tt><center> 0.0060 </center></tt><td><tt><center> 28 </center></tt><td><tt><center> 0.035 </center></tt><td><tt><center> 41 </center></tt>
|
||
<tr><td> φ − β <td><tt><center> 0.0060 </center></tt><td><tt><center> 28 </center></tt><td><tt><center> 0.035 </center></tt><td><tt><center> 41 </center></tt>
|
||
<tr><td> θ − φ <td><tt><center> 2.9 </center></tt><td><tt><center> 82 </center></tt><td><tt><center> 6.0 </center></tt><td><tt><center> 120 </center></tt>
|
||
<tr><td> φ − θ <td><tt><center> 2.9 </center></tt><td><tt><center> 82 </center></tt><td><tt><center> 6.0 </center></tt><td><tt><center> 120 </center></tt>
|
||
<tr><td> θ − β <td><tt><center> 0.0060 </center></tt><td><tt><center> 28 </center></tt><td><tt><center> 0.035 </center></tt><td><tt><center> 41 </center></tt>
|
||
<tr><td> β − θ <td><tt><center> 0.0060 </center></tt><td><tt><center> 28 </center></tt><td><tt><center> 0.035 </center></tt><td><tt><center> 41 </center></tt>
|
||
<tr><td> μ − φ <td><tt><center> 0.037 </center></tt><td><tt><center> 41 </center></tt><td><tt><center> 0.18 </center></tt><td><tt><center> 60 </center></tt>
|
||
<tr><td> φ − μ <td><tt><center> 0.98 </center></tt><td><tt><center> 59 </center></tt><td><tt><center> 2.3 </center></tt><td><tt><center> 84 </center></tt>
|
||
<tr><td> μ − β <td><tt><center> 0.00069 </center></tt><td><tt><center> 5.8 </center></tt><td><tt><center> 0.0024 </center></tt><td><tt><center> 9.6 </center></tt>
|
||
<tr><td> β − μ <td><tt><center> 0.13 </center></tt><td><tt><center> 12 </center></tt><td><tt><center> 0.35 </center></tt><td><tt><center> 19 </center></tt>
|
||
<tr><td> μ − θ <td><tt><center> 0.24 </center></tt><td><tt><center> 30 </center></tt><td><tt><center> 0.67 </center></tt><td><tt><center> 40 </center></tt>
|
||
<tr><td> θ − μ <td><tt><center> 0.099 </center></tt><td><tt><center> 23 </center></tt><td><tt><center> 0.23 </center></tt><td><tt><center> 33 </center></tt>
|
||
<tr><td> χ − φ <td><tt><center> 0.78 </center></tt><td><tt><center> 43 </center></tt><td><tt><center> 2.1 </center></tt><td><tt><center> 64 </center></tt>
|
||
<tr><td> φ − χ <td><tt><center> 9.0 </center></tt><td><tt><center> 71 </center></tt><td><tt><center> 17 </center></tt><td><tt><center> 100 </center></tt>
|
||
<tr><td> χ − β <td><tt><center> 0.018 </center></tt><td><tt><center> 3.7 </center></tt><td><tt><center> 0.11 </center></tt><td><tt><center> 6.4 </center></tt>
|
||
<tr><td> β − χ <td><tt><center> 1.7 </center></tt><td><tt><center> 16 </center></tt><td><tt><center> 3.4 </center></tt><td><tt><center> 24 </center></tt>
|
||
<tr><td> χ − θ <td><tt><center> 0.18 </center></tt><td><tt><center> 31 </center></tt><td><tt><center> 0.56 </center></tt><td><tt><center> 43 </center></tt>
|
||
<tr><td> θ − χ <td><tt><center> 0.87 </center></tt><td><tt><center> 23 </center></tt><td><tt><center> 1.9 </center></tt><td><tt><center> 32 </center></tt>
|
||
<tr><td> χ − μ <td><tt><center> 0.022 </center></tt><td><tt><center> 0.56 </center></tt><td><tt><center> 0.11 </center></tt><td><tt><center> 0.91 </center></tt>
|
||
<tr><td> μ − χ <td><tt><center> 0.31 </center></tt><td><tt><center> 1.2 </center></tt><td><tt><center> 0.86 </center></tt><td><tt><center> 2.0 </center></tt>
|
||
<tr><td> ξ − φ <td><tt><center> 0.015 </center></tt><td><tt><center> 39 </center></tt><td><tt><center> 0.086 </center></tt><td><tt><center> 57 </center></tt>
|
||
<tr><td> φ − ξ <td><tt><center> 0.34 </center></tt><td><tt><center> 53 </center></tt><td><tt><center> 1.1 </center></tt><td><tt><center> 75 </center></tt>
|
||
<tr><td> ξ − β <td><tt><center> 0.00042 </center></tt><td><tt><center> 6.3 </center></tt><td><tt><center> 0.0039 </center></tt><td><tt><center> 10 </center></tt>
|
||
<tr><td> β − ξ <td><tt><center> 0.040 </center></tt><td><tt><center> 10 </center></tt><td><tt><center> 0.15 </center></tt><td><tt><center> 15 </center></tt>
|
||
<tr><td> ξ − θ <td><tt><center> 0.28 </center></tt><td><tt><center> 28 </center></tt><td><tt><center> 0.75 </center></tt><td><tt><center> 38 </center></tt>
|
||
<tr><td> θ − ξ <td><tt><center> 0.040 </center></tt><td><tt><center> 23 </center></tt><td><tt><center> 0.11 </center></tt><td><tt><center> 33 </center></tt>
|
||
<tr><td> ξ − μ <td><tt><center> 0.015 </center></tt><td><tt><center> 0.79 </center></tt><td><tt><center> 0.058 </center></tt><td><tt><center> 1.5 </center></tt>
|
||
<tr><td> μ − ξ <td><tt><center> 0.0043 </center></tt><td><tt><center> 0.54 </center></tt><td><tt><center> 0.018 </center></tt><td><tt><center> 1.1 </center></tt>
|
||
<tr><td> ξ − χ <td><tt><center> 0.60 </center></tt><td><tt><center> 1.9 </center></tt><td><tt><center> 1.5 </center></tt><td><tt><center> 3.6 </center></tt>
|
||
<tr><td> χ − ξ <td><tt><center> 0.023 </center></tt><td><tt><center> 0.53 </center></tt><td><tt><center> 0.079 </center></tt><td><tt><center> 0.92 </center></tt>
|
||
</table>
|
||
</center>
|
||
|
||
\if SKIP
|
||
0 beta phi ,0.0060!,28!!!,!0.035!,!41!!!
|
||
1 phi beta ,0.0060!,28!!!,!0.035!,!41!!!
|
||
2 theta phi ,2.9!!!!,82!!!,!6.0!!!,120!!!
|
||
3 phi theta,2.9!!!!,82!!!,!6.0!!!,120!!!
|
||
4 theta beta ,0.0060!,28!!!,!0.035!,!41!!!
|
||
5 beta theta,0.0060!,28!!!,!0.035!,!41!!!
|
||
6 mu phi ,0.037!!,41!!!,!0.18!!,!60!!!
|
||
7 phi mu ,0.98!!!,59!!!,!2.3!!!,!84!!!
|
||
8 mu beta ,0.00069,!5.8!,!0.0024,!!9.6!
|
||
9 beta mu ,0.13!!!,12!!!,!0.35!!,!19!!!
|
||
10 mu theta,0.24!!!,30!!!,!0.67!!,!40!!!
|
||
11 theta mu ,0.099!!,23!!!,!0.23!!,!33!!!
|
||
12 chi phi ,0.78!!!,43!!!,!2.1!!!,!64!!!
|
||
13 phi chi ,9.0!!!!,71!!!,17!!!!!,100!!!
|
||
14 chi beta ,0.018!!,!3.7!,!0.11!!,!!6.4!
|
||
15 beta chi ,1.7!!!!,16!!!,!3.4!!!,!24!!!
|
||
16 chi theta,0.18!!!,31!!!,!0.56!!,!43!!!
|
||
17 theta chi ,0.87!!!,23!!!,!1.9!!!,!32!!!
|
||
18 chi mu ,0.022!!,!0.56,!0.11!!,!!0.91
|
||
19 mu chi ,0.31!!!,!1.2!,!0.86!!,!!2.0!
|
||
20 xi phi ,0.015!!,39!!!,!0.086!,!57!!!
|
||
21 phi xi ,0.34!!!,53!!!,!1.1!!!,!75!!!
|
||
22 xi beta ,0.00042,!6.3!,!0.0039,!10!!!
|
||
23 beta xi ,0.040!!,10!!!,!0.15!!,!15!!!
|
||
24 xi theta,0.28!!!,28!!!,!0.75!!,!38!!!
|
||
25 theta xi ,0.040!!,23!!!,!0.11!!,!33!!!
|
||
26 xi mu ,0.015!!,!0.79,!0.058!,!!1.5!
|
||
27 mu xi ,0.0043!,!0.54,!0.018!,!!1.1!
|
||
28 xi chi ,0.60!!!,!1.9!,!1.5!!!,!!3.6!
|
||
29 chi xi ,0.023!!,!0.53,!0.079!,!!0.92
|
||
\endif
|
||
|
||
The 2nd and 3rd columns show the results for the SRMmax ellipsoid, \e f
|
||
= 1/150, retaining 6th order terms in the series expansion. The 4th and
|
||
5th columns show the results for the International ellipsoid, \e f =
|
||
1/297, retaining 5th order terms in the series expansion. The 2nd and
|
||
4th columns give the errors for the series expansions in terms of \e n
|
||
given in this section (appropriately truncated). The 3rd and 5th
|
||
columns give the errors when the series are reexpanded in terms of
|
||
<i>e</i><sup>2</sup> = 4\e n/(1 + \e n)<sup>2</sup> and truncated
|
||
retaining the <i>e</i><sup>12</sup> and <i>e</i><sup>10</sup> terms
|
||
respectively.
|
||
|
||
Some observations:
|
||
- For production use, the 6th order series in \e n are recommended. For
|
||
\e f = 1/150, the resulting errors are close to the round-off limit.
|
||
The errors in the 6th order series scale as <i>f</i><sup>7</sup>; so
|
||
the errors with \e f = 1/297 are about 120 times smaller.
|
||
- It's inadvisable to use the 5th order series in \e n; this order is
|
||
barely acceptable for \e f = 1/297 and the errors grow as
|
||
<i>f</i><sup>6</sup> as \e f is increased.
|
||
- In all cases, the expansions in terms of <i>e</i><sup>2</sup> are
|
||
considerably less accurate than the corresponding series in \e n.
|
||
- For every series converting between φ and any of θ, μ,
|
||
χ, or ξ, the series where β is substituted for φ is
|
||
more accurate. Considering that the transformation between φ and
|
||
β is so simple, tanβ = (1 - \e f) tanφ, it sometimes
|
||
makes sense to use β internally as the basic measure of latitude.
|
||
(This is the case with geodesic calculations.)
|
||
|
||
<center>
|
||
Back to \ref geocentric. Forward to \ref highprec. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page highprec Support for high precision arithmetic
|
||
|
||
<center>
|
||
Back to \ref auxlat. Forward to \ref changes. Up to \ref contents.
|
||
</center>
|
||
|
||
One of the goals with the algorithms in GeographicLib is to deliver
|
||
accuracy close to the limits for double precision. In order to develop
|
||
such algorithms it is very useful to be have accurate test data. For
|
||
this purpose, I used Maxima's bfloat capability, which support arbitrary
|
||
precision floating point arithmetic. As of version 1.37, such
|
||
high-precision test data can be generated directly by GeographicLib by
|
||
compiling it with <code>GEOGRAPHICLIB_PRECISION</code> equal to 4 or 5.
|
||
|
||
Here's what you should know:
|
||
- This is mainly for use for algorithm developers. It's not
|
||
recommended for installation for all users on a system.
|
||
- Configuring with <code>-D GEOGRAPHICLIB_PRECISION=4</code> gives quad
|
||
precision (113-bit precision) via boost::multiprecision::float128;
|
||
this requires:
|
||
- <a href="https://www.boost.org"> Boost</a>, version 1.64 or later,
|
||
- the quadmath library (the package names are libquadmath
|
||
and libquadmath-devel),
|
||
- the use of g++.
|
||
- Configuring with <code>-D GEOGRAPHICLIB_PRECISION=5</code> gives
|
||
arbitrary precision via mpfr::mpreal; this requires:
|
||
- <a href="https://www.mpfr.org"> MPFR</a>, version 3.0 or later,
|
||
- <a href="http://www.holoborodko.com/pavel/mpfr"> MPFR C++</a>
|
||
(version 3.6.9, dated 2022-01-18, or later; version 3.6.9 also
|
||
requires the fixes given in pull requests #15),
|
||
- a compiler which supports the explicit cast operator (e.g., g++ 4.5
|
||
or later, Visual Studio 12 2013 or later).
|
||
- MPFR, MPFR C++, and Boost all come with their own licenses. Be sure
|
||
to respect these.
|
||
- The indicated precision is used for <b>all</b> floating point
|
||
arithmetic. Thus, you can't compare the results of different
|
||
precisions within a single invocation of a program. Instead, you can
|
||
create a file of accurate test data at a high precision and use this
|
||
to test the algorithms at double precision.
|
||
- With MPFR, the precision should be set (using Utility::set_digits)
|
||
just once before any other GeographicLib routines are called.
|
||
Calling this function after other GeographicLib routines will lead to
|
||
inconsistent results (because the precision of some constants like
|
||
Math::pi() is set when the functions are first called).
|
||
- All the \ref utilities call Utility::set_digits() (with no
|
||
arguments). This causes the precision (in bits) to be determined by
|
||
the <code>GEOGRAPHICLIB_DIGITS</code> environment variable. If this
|
||
is not defined the precision is set to 256 bits (about 77 decimal
|
||
digits).
|
||
- The accuracy of most calculations should increase as the precision
|
||
increases (and typically only a few bits of accuracy should be lost).
|
||
We can distinguish 4 sources of error:
|
||
- Round-off errors; these are reliably reduced when the precision is
|
||
increased. For the most part, the algorithms used by GeographicLib
|
||
are carefully tuned to minimize round-off errors, so that only a
|
||
few bits of accuracy are lost.
|
||
- Convergence errors due to not iterating certain algorithms to
|
||
convergence. However, all iterative methods used by GeographicLib
|
||
converge quadratically (the number of correct digits doubles on
|
||
each iteration) so that full convergence is obtained for
|
||
"reasonable" precisions (no more than, say, 100 decimal digits or
|
||
about 340 bits). An exception is thrown if the convergence
|
||
criterion is not met when using high precision arithmetic.
|
||
- Truncation errors. Some classes (namely, Geodesic and
|
||
TransverseMercator) use series expansion to approximate the true
|
||
solution. Additional terms in the series are used for high
|
||
precision, however there's always a finite truncation error which
|
||
varies as some power of the flattening. On the other hand,
|
||
GeodesicExact and TransverseMercatorExact are somewhat slower
|
||
classes offering the same functionality implemented with
|
||
EllipticFunction. These classes provide arbitrary accuracy.
|
||
(However, a caveat is that the evaluation of the area in
|
||
GeodesicExact still uses a series (albeit of considerably higher
|
||
order). So the area calculations are always have a finite
|
||
truncation error.)
|
||
- Quantization errors. Geoid, GravityModel, and MagneticModel all
|
||
depend on external data files. The coefficient files for
|
||
GravityModel and MagneticModel store the coefficients as IEEE
|
||
doubles (and perhaps these coefficients can be regarded as exact).
|
||
However, with Geoid, the data files for the geoid heights are
|
||
quantized at 3mm leading to an irreducible ±1.5mm
|
||
quantization error. On the other hand, all the physical constants
|
||
used by GeographicLib, e.g., the flattening of the WGS84 ellipsoid,
|
||
are evaluated as exact decimal numbers.
|
||
- Where might high accuracy be important?
|
||
- checking the truncation error of series approximations;
|
||
- checking for excessive round-off errors (typically due to subtraction);
|
||
- checking the round-off error in computing areas of many-sided polygons;
|
||
- checking the summation of high order spherical harmonic expansions
|
||
(where underflow and overflow may also be a problem).
|
||
- Because only a tiny number of people will be interested in using this
|
||
facility:
|
||
- the cmake support for the required libraries is rudimentary;
|
||
- however geographiclib-config.cmake does export
|
||
<code>GEOGRAPHICLIB_PRECISION</code> and
|
||
<code>GeographicLib_HIGHPREC_LIBRARIES</code>, the libraries
|
||
providing the support for high-precision arithmetic;
|
||
- support for the C++11 mathematical functions and the explicit cast
|
||
operator is required;
|
||
- quad precision is only available on Linux;
|
||
- mpfr has been mostly tested on Linux (but it works on Windows with
|
||
Visual Studio 12 and MacOS too).
|
||
|
||
The following steps needed to be taken
|
||
|
||
- Phase 1, make sure you can switch easily between double, float, and
|
||
long double.
|
||
- use <code>\#include <cmath></code> instead of <code>\#include
|
||
<math.h></code>;
|
||
- use, e.g., <code>std::sqrt</code> instead of <code>sqrt</code> in
|
||
header files (similarly for <code>sin</code>, <code>cos</code>,
|
||
<code>atan2</code>, etc.);
|
||
- use <code>using namespace std;</code> and plain <code>sqrt</code>,
|
||
etc., in code files;
|
||
- express all convergence criteria in terms of\code
|
||
numeric_limits<double>::epsilon() \endcode
|
||
etc., instead of using "magic constants", such as 1.0e-15;
|
||
- use <code>typedef double real;</code> and replace all occurrences of
|
||
<code>double</code> by <code>real</code>;
|
||
- write all literals by, e.g., <code>real(0.5)</code>. Some
|
||
constants might need the L suffix, e.g., <code>real f =
|
||
1/real(298.257223563L)</code> (but see below);
|
||
- Change the typedef of <code>real</code> to <code>float</code> or
|
||
<code>long double</code>, compile, and test. In this way, the
|
||
library can be run with any of the three basic floating point
|
||
types.
|
||
- If you want to run the library with multiple floating point types
|
||
within a single executable, then make all your classes take a
|
||
template parameter specifying the floating-point type and
|
||
instantiate your classes with the floating-point types that you
|
||
plan to use. I did not take this approach with GeographicLib
|
||
because double precision is suitable for the vast majority of
|
||
applications and turning all the classes into templates classes
|
||
would end up needlessly complicating (and bloating) the library.
|
||
|
||
- Phase 2, changes to support arbitrary, but fixed, precision
|
||
- Use, e.g., \code
|
||
typedef boost::multiprecision::float128 real; \endcode
|
||
- Change <code>std::sqrt(...)</code>, etc. to \code
|
||
using std::sqrt;
|
||
sqrt(...) \endcode
|
||
(but note that <code>std::max</code> can stay). It's only necessary
|
||
to do this in header files (code files already have <code>using
|
||
namespace std;</code>).
|
||
- In the case of boost's multiprecision numbers, the C++11
|
||
mathematical functions need special treatment, see Math.hpp.
|
||
- If necessary, use series with additional terms to improve the
|
||
accuracy.
|
||
- Replace slowly converging root finding methods with rapidly
|
||
converging methods. In particular, the simple iterative method to
|
||
determine the flattening from the dynamical form factor in
|
||
NormalGravity converged too slowly; this was replaced by Newton's
|
||
method.
|
||
- If necessary, increase the maximum allowed iteration count in root
|
||
finding loops. Also throw an exception of the maximum iteration
|
||
count is exceeded.
|
||
- Write literal constants in a way that works for any precision, e.g.,
|
||
\code
|
||
real f = 1/( real(298257223563LL) / 1000000000 ); \endcode
|
||
[Note that \code
|
||
real f = 1/( 298 + real(257223563) / 1000000000 ); \endcode
|
||
and <code>1/real(298.257223563L)</code> are susceptible to
|
||
double rounding errors. We normally want to avoid such errors when
|
||
real is a double.]
|
||
- For arbitrary constants, you might have to resort to macros \code
|
||
#if GEOGRAPHICLIB_PRECISION == 1
|
||
#define REAL(x) x##F
|
||
#elif GEOGRAPHICLIB_PRECISION == 2
|
||
#define REAL(x) x
|
||
#elif GEOGRAPHICLIB_PRECISION == 3
|
||
#define REAL(x) x##L
|
||
#elif GEOGRAPHICLIB_PRECISION == 4
|
||
#define REAL(x) x##Q
|
||
#else
|
||
#define REAL(x) real(#x)
|
||
#endif \endcode
|
||
and then use \code
|
||
real f = 1/REAL(298.257223563); \endcode
|
||
- Perhaps use local static declarations to avoid the overhead of
|
||
reevaluating constants, e.g., \code
|
||
static inline real pi() {
|
||
using std::atan2;
|
||
// pi is computed just once
|
||
static const real pi = atan2(real(0), real(-1));
|
||
return pi;
|
||
} \endcode
|
||
This is <b>not</b> necessary for built-in floating point types,
|
||
since the atan2 function will be evaluated at compile time.
|
||
- In Utility::readarray and Utility::writearray, arrays of reals were
|
||
treated as plain old data. This assumption now no longer holds and
|
||
these functions needed special treatment.
|
||
- volatile declarations don't apply.
|
||
|
||
- Phase 3, changes to support arbitrary precision which can be set at
|
||
runtime.
|
||
- The big change now is that the precision is not known at compile
|
||
time. All static initializations which involve floating point
|
||
numbers need to be eliminated.
|
||
- Some static variables (e.g., tolerances which are expressed in
|
||
terms of <code>numeric_limits<double>\::epsilon()</code>)
|
||
were made member variables and so initialized when the
|
||
constructor was called.
|
||
- Some simple static real arrays (e.g., the interpolating stencils
|
||
for Geoid) were changed into integer arrays.
|
||
- Some static variables where converted to static functions similar
|
||
to the definition of pi() above.
|
||
- All the static instances of classes where converted as follows
|
||
\code
|
||
// declaration
|
||
static const Geodesic WGS84;
|
||
// definition
|
||
const Geodesic Geodesic::WGS84(Constants::WGS84_a(),
|
||
Constants::WGS84_f());
|
||
// use
|
||
const Geodesic& geod = Geodesic::WGS84; \endcode
|
||
becomes \code
|
||
// declaration
|
||
static const Geodesic& WGS84();
|
||
// definition
|
||
const Geodesic& Geodesic::WGS84() {
|
||
static const Geodesic wgs84(Constants::WGS84_a(),
|
||
Constants::WGS84_f());
|
||
return wgs84;
|
||
static const Geodesic& WGS84();
|
||
}
|
||
// use
|
||
const Geodesic& geod = Geodesic::WGS84(); \endcode
|
||
This is the so-called
|
||
<a href="https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use">
|
||
"construct on first use idiom"</a>. This is the most disruptive
|
||
of the changes since it requires a different calling convention
|
||
in user code. However the old static initializations were
|
||
invoked every time a code linking to GeographicLib was started,
|
||
even if the objects were not subsequently used. The new method
|
||
only initializes the static objects if they are used.
|
||
.
|
||
- <code>numeric_limits<double>\::digits</code> is no longer a
|
||
compile-time constant. It becomes
|
||
<code>numeric_limits<double>\::digits()</code>.
|
||
- Depending on the precision cos(π/2) might be negative.
|
||
Similarly atan(tan(π/2)) may evaluate to −π/2.
|
||
GeographicLib already handled this, because this happens with long
|
||
doubles (64 bits in the fraction).
|
||
- The precision needs to be set in each thread in a multi-processing
|
||
applications (for an example, see
|
||
<code>examples/GeoidToGTX.cpp</code>).
|
||
- Passing numbers to functions by value incurs a substantially higher
|
||
overhead than with doubles. This could be avoided by passing such
|
||
arguments by reference. This was <b>not</b> done here because it
|
||
would junk up the code to benefit a narrow application.
|
||
- The constants in GeodesicExact, e.g., 831281402884796906843926125,
|
||
can't be specified as long doubles nor long longs (since they have
|
||
more than 64 significant bits):
|
||
- first tried macro which expanded to a string (see the macro REAL
|
||
above);
|
||
- now use inline function to combine two long long ints each with at
|
||
most 52 significant bits;
|
||
- also needed to simplify one routine in GeodesicExact which took
|
||
inordinately long (15 minutes) to compile using g++.
|
||
|
||
<center>
|
||
Back to \ref auxlat. Forward to \ref changes. Up to \ref contents.
|
||
</center>
|
||
|
||
**********************************************************************/
|
||
/**
|
||
\page changes Change log
|
||
|
||
<center>
|
||
Back to \ref highprec. Up to \ref contents.
|
||
</center>
|
||
|
||
List of versions in reverse chronological order together with a brief
|
||
list of changes. (Note: Old versions of the library use a year-month
|
||
style of numbering. Now, the library uses a major and minor version
|
||
number.) Recent versions of GeographicLib are available at
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/distrib-C++/">
|
||
https://sourceforge.net/projects/geographiclib/files/distrib-C++/</a>.
|
||
Older versions are in
|
||
<a href="https://sourceforge.net/projects/geographiclib/files/distrib/">
|
||
https://sourceforge.net/projects/geographiclib/files/distrib/</a>.
|
||
|
||
The corresponding documentation for these versions is obtained by
|
||
clicking on the “Version <i>m.nn</i>” links below. Some of
|
||
the links in the documentation of older versions may be out of date (in
|
||
particular the links for the source code will not work if the code has
|
||
been migrated to the archive subdirectory). All the releases are
|
||
available as tags “r<i>m.nn</i>” in the the "release" branch
|
||
of the
|
||
<a href="https://github.com/geographiclib/geographiclib/tree/release">
|
||
git repository for GeographicLib</a>.
|
||
|
||
\if SKIP
|
||
- TODO: Planned updates
|
||
- Change templating in PolygonArea so that the AddPoint and AddEdge
|
||
methods are templated instead of the class itself. This would
|
||
allow a polygon to contain a mixture of geodesic and rhumb-line
|
||
edges.
|
||
- Generalize Geoid, UTMUPS, MGRS, GeoCoords to handle non-WGS84
|
||
ellipsoids.
|
||
- Add GreatEllipse class.
|
||
- Implement Geodesic + TM + PolarStereographic on Jets.
|
||
- Template versions of Gnomonic and AzimuthalEquidistant so that they
|
||
can use either Geodesic and GeodesicExact. Use typedefs so that
|
||
Geodesic::Line points to GeodesicLine.
|
||
- Add information on radius of convergence for aux latitude series.
|
||
- Check Geocentric::Reverse for accuracy for extreme ellipsoids, \e e
|
||
> 1/sqrt(2).
|
||
- Check Visual Studo "code analysis" results (from Analize VS
|
||
menu). Probably an awful lot of false positives.
|
||
- Add Math routine for Clenshaw summation; and maybe AuxiliaryLatitude
|
||
class for conversions via the series?
|
||
- Allow addition of points to NearestNeighbor objects (maybe by
|
||
allowing larger buckets on construction or by just do additional
|
||
splits as necessary).
|
||
- Check whether boost/quadmath workarounds can be removed with boost 1.79.
|
||
\endif
|
||
|
||
- <a href="https://geographiclib.sourceforge.io/C++/2.1.2">Version 2.1.2</a>
|
||
(released 2022-12-13)
|
||
- Add MGRS::Decode to break an MGRS string into its components.
|
||
- Add definite integral overload for DST::integral. This is used in
|
||
GeodesicExact.
|
||
- Add example code <code>examples/AuxLatitude.[hc]pp</code>
|
||
implementating the AuxAngle and AuxLatitude classes. These classes
|
||
implement the methods documented in the paper
|
||
<a href="https://arxiv.org/abs/2212.05818">On auxiliary
|
||
latitudes</a>. They are <b>not</b> part of GeographicLib. See
|
||
\ref auxlat for more details.
|
||
- Minor cmake issues:
|
||
- fix cross-compile build on Windows;
|
||
- check cmake version for "cmake rm -rf";
|
||
- move cmake_minimum_required to the beginning of the cmake file
|
||
and update minimum version to 3.13.0.
|
||
|
||
- <a href="https://geographiclib.sourceforge.io/C++/2.1.1">Version 2.1.1</a>
|
||
(released 2022-07-25)
|
||
- Paper describing algorithms in GeodesicExact class is available at
|
||
<a href="https://arxiv.org/abs/2208.00492">arxiv:2208.00492</a>.
|
||
- The <a href="Planimeter.1.html">Planimeter</a> utility used to
|
||
accept polygon vertices as UTM/UPS or MGRS coordinates. However,
|
||
since these are converted to latitude and longitude using the WGS84
|
||
ellipoid, this convention is incompatible with the -e option to
|
||
specify the ellipsoid. So now, you have to provide the
|
||
\--geoconvert-input option to allow vertices to be specified in
|
||
this way.
|
||
- Fix sign error in DST::refine.
|
||
- Relax overly strict convergence test for inverse problem in
|
||
Geodesic and GeodesicExact.
|
||
- Minor:
|
||
- Use lookup table for selecting number of points for DST in
|
||
GeodesicExact.
|
||
- Relax one of the test thresholds in geodtest.cpp.
|
||
|
||
- <a href="https://geographiclib.sourceforge.io/C++/2.1">Version 2.1</a>
|
||
(released 2022-06-09)
|
||
- Improve the accuracy of the area calculations in GeodesicExact and
|
||
the <a href="Planimeter.1.html">Planimeter</a> utility with the -E
|
||
option. This now gives full double precision accuracy for
|
||
<i>b</i>/\e a ∈ [0.01, 100] or \e f ∈ [-99, 0.99].
|
||
(Previously the range for full accuracy was <i>b</i>/\e a ∈
|
||
[0.5, 2].) The method involves a direct computation of the Fourier
|
||
series for the integrand of area integral which then allows the
|
||
integral to be evaluated.
|
||
- Add a new class DST for doing discrete sine transforms. This is
|
||
mainly for "internal" use, to compute the area in GeodesicExact.
|
||
Internally, this uses the
|
||
<a href="https://github.com/mborgerding/kissfft">kissfft</a>
|
||
package by Mark Borgerding.
|
||
- Fix various warnings from Visual Studio about arithmetic involving
|
||
enums.
|
||
- Minor improvement in the logic for the geodesic inverse problem to
|
||
address a slow down that can occur with `GEOGRAPHICLIB_PRECISION =
|
||
5` due to the time it takes to calculate, for example,
|
||
`sin(10^(10^8))` accurately.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/C++/2.0">Version 2.0</a>
|
||
(released 2022-05-06)
|
||
- Remove non C++ implementations from this package. These are now
|
||
managed as separate packages. See
|
||
[https://geographiclib.sourceforge.io/doc/library.html#languages](
|
||
../../doc/library.html#languages).
|
||
- This allowed the cmake interface to be rationalized, see \ref cmake
|
||
- Replace `GEOGRAPHICLIB_LIB_TYPE` by `BUILD_SHARED_LIBS` (a
|
||
standard cmake variable) and `BUILD_BOTH_LIBS`.
|
||
- Remove `COMMON_INSTALL_PATH` and replace with variables to
|
||
specify where various components are to be installed.
|
||
- `GEOGRAPHICLIB_DOCUMENTATION` is now `BUILD_DOCUMENTATION`.
|
||
- Remove `BUILD_NETGEOGRAPHICLIB`.
|
||
- Remove legacy cmake config support (non-namespace).
|
||
- `make exampleprograms` does a separate cmake configuration to
|
||
mimic how a user's program might find GeographicLib.
|
||
- `find_package (GeographicLib)` now sets and checks the value of
|
||
`GEOGRAPHICLIB_PRECISION`.
|
||
- Improve the separation of end-user and maintain cmake code.
|
||
- More careful treatment of ±0° and ±180°.
|
||
- These behave consistently with taking the limits
|
||
- ±0 means ±ε as ε → 0+
|
||
- ±180 means ±(180 − ε) as ε
|
||
→ 0+
|
||
- As a consequence, azimuths of +0° and +180° are reckoned
|
||
to be east-going, as far as tracking the longitude with
|
||
Geodesic::LONG_UNROLL and the area goes, while azimuths
|
||
−0° and −180° are reckoned to be west-going.
|
||
- When computing longitude differences, if λ<sub>2</sub>
|
||
− λ<sub>1</sub> = ±180° (mod 360°),
|
||
then the sign is picked depending on the sign of the difference.
|
||
- The normal range for returned longitudes and azimuths is
|
||
[−180°, 180°].
|
||
- Programs in directory `tests` now allow testing to extend beyond
|
||
invocations of the utility programs.
|
||
- BUG FIXES:
|
||
- Fixed bug where in the solution of the inverse geodesic problem where
|
||
with lat1 = 0 and lat2 = nan was treated as equatorial.
|
||
- Fixed roundoff corner case in geodesic area computation (only
|
||
triggered with long double).
|
||
- Minor changes in code:
|
||
- Use fmin, fmax, fabs instead of min, max, abs, where appropriate.
|
||
- Parameterize the conversion units for degrees, minutes, seconds as
|
||
Math::qd, Math::dm, Math::ms.
|
||
- Ellipsoid::MinorRadius() has be renamed Ellipsoid::PolarRadius().
|
||
- Remove deprecated functions: XXX::MajorRadius, Utility::val, and
|
||
placeholders (Math::cbrt, etc.) for C++11 math functions.
|
||
- Can specify the comment character in Utility::ParseLine.
|
||
- Rename various internal identifiers to avoid reserved names.
|
||
- Remove unused internal variable in RhumbLine.
|
||
- The documentation for EllipticFunction specifies restrictions on
|
||
the arguments.
|
||
- Put GeodesicExactC4.cpp back into GeodesicExact.cpp.
|
||
- Library file now called `libGeographicLib.so`, etc., instead of
|
||
`libGeographic.so`.
|
||
- The .NET version of GeographicLib has been removed.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.52">Version 1.52</a>
|
||
(released 2021-06-22)
|
||
- Add MagneticModel::FieldGeocentric and
|
||
MagneticCircle::FieldGeocentric to return the field in geocentric
|
||
coordinates (thanks to Marcelo Banik de Padua).
|
||
- Document realistic errors for PolygonAreaT and
|
||
<a href="Planimeter.1.html">Planimeter</a>.
|
||
- Geodesic routines: be more aggressive in preventing negative \e s12
|
||
and \e m12 for short lines (all languages).
|
||
- Fix bug in AlbersEqualArea for extreme prolate ellipsoids (plus
|
||
general cleanup in the code).
|
||
- Thanks to Thomas Warner, a sample of wrapping the C++ library, so
|
||
it's accessible in Excel, is given in <code>wrapper/Excel</code>.
|
||
- Minor changes
|
||
- Work around inaccuracies in hypot routines in Visual Studio
|
||
(win32), Python, and JavaScript.
|
||
- Initialize reference argument to remquo (C++ and C).
|
||
- Get ready to retire unused _exact in RhumbLine.
|
||
- Declare RhumbLine copy constructor "= default".
|
||
- Use C++11 "= delete" idiom to delete copy assignment and copy
|
||
constructors in RhumbLine, Geoid, GravityModel, MagneticModel.
|
||
- Fix MGRS::Forward to work around aggressive optimization leading to
|
||
incorrect rounding.
|
||
- Fix plain makefiles, Makefile.mk, so that PREFIX is handled
|
||
properly.
|
||
- Make cmake's GeographicLib_LIBRARIES point to namespace versions.
|
||
- <b>NOTE:</b> In the next version (tentatively 2.0), I plan to split
|
||
up the git repository and the packaging of GeographicLib into
|
||
separate entities for each language. This will simplify
|
||
development and deployment of the library.
|
||
- <b>WARNING:</b> The .NET version of GeographicLib will not be
|
||
supported in the next version.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.51">Version 1.51</a>
|
||
(released 2020-11-22)
|
||
- C++11 compiler required for C++ library. As a consequence:
|
||
- The workaround implementations for C++11 routines (Math::hypot,
|
||
Math::expm1, Math::log1p, Math::asinh, Math::atanh,
|
||
Math::copysign, Math::cbrt, Math::remainder, Math::remquo,
|
||
Math::round, Math::lround, Math::fma, Math::isfinite, and
|
||
Math::isnan) are now deprecated. Just use the versions in the
|
||
std:: namespace instead.
|
||
- SphericalEngine class, fix the namespace for using streamoff.
|
||
- Some templated functions, e.g., Math::degree(), now have default
|
||
template parameters, T = Math::real.
|
||
- C99 compiler required for C library.
|
||
- Reduce memory footprint in Java implementation.
|
||
- New form of Utility::ParseLine to allow the syntax "KEY = VAL".
|
||
- Add International Geomagnetic Reference Field (13th generation),
|
||
igrf13, which approximates the main magnetic field of the earth for
|
||
the period 1900--2025.
|
||
- More symbols allowed with DMS decoding in C++, JS, and cgi-bin
|
||
packages; see DMS::Decode.
|
||
- Fix bug in cgi-bin argument processing which causes "+" to be
|
||
misinterpreted.
|
||
- Required minium version of CMake is now 3.7.0 (released
|
||
2016-11-11). This is to work around a bug in find_package for
|
||
cmake 3.4 and 3.5.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.50.1">Version 1.50.1</a>
|
||
(released 2019-12-13)
|
||
- Add the World Magnetic Model 2020, wmm2020, covering the period
|
||
2020--2025. This is now the model returned by
|
||
MagneticModel::DefaultMagneticName and is default magnetic model
|
||
for <a href="MagneticField.1.html">MagneticField</a> (replacing
|
||
wmm2015v2 which is only valid thru the end of 2019).
|
||
- Include float instantiations of those templated Math functions
|
||
which migrated to Math.cpp in version 1.50.
|
||
- <b>WARNING:</b> The <i>next</i> version of GeographicLib will
|
||
require a C++11 compliant compiler. This means that the minimum
|
||
version of Visual Studio will be Visual Studio 14 2015. (This
|
||
repeats the warning given with version 1.50. It didn't apply to
|
||
this version because this is a minor update.)
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.50">Version 1.50</a>
|
||
(released 2019-09-24)
|
||
- BUG fixes:
|
||
- Java + JavaScript implementations of PolygonArea::TestEdge counted
|
||
the pole encirclings wrong.
|
||
- Fix typo in JavaScript implementation which affected unsigned
|
||
areas.
|
||
- Adding edges to a polygon counted pole encirclings inconsistent
|
||
with the way the adding point counted them. This might have
|
||
caused an incorrect result if a polygon vertex had longitude = 0.
|
||
This affected all implementations except Fortran and MATLAB).
|
||
- GARS::Forward: fix BUG in handling of longitude = ±180°.
|
||
- Fix bug in Rhumb class and
|
||
<a href="RhumbSolve.1.html">RhumbSolve(1)</a> utiity which caused
|
||
incorrect area to be reported if an endpoint is at a pole.
|
||
Thanks to Natalia Sabourova for reporting this.
|
||
- Fix bug in MATLAB routine mgrs_inv which resulted in incorrect
|
||
results for UPS zones with prec = −1.
|
||
- In geodreckon.m geoddistance.m, suppress (innocuous) "warning:
|
||
division by zero" messages from Octave.
|
||
- In python implementation, work around problems caused by sin(inf)
|
||
and fmod(inf) raising exceptions.
|
||
- Geoid class, fix the use of streamoff.
|
||
- The PolygonArea class, the
|
||
<a href="Planimeter.1.html">Planimeter</a> utility, and their
|
||
equivalents in C, Fortran, MATLAB, Java, JavaScript, Python, and
|
||
Maxima can now handle arbitrarily complex polygons. In the case of
|
||
self-intersecting polygons the area is accumulated "algebraically",
|
||
e.g., the areas of the 2 loops in a figure-8 polygon will partially
|
||
cancel.
|
||
- Changes in gravity and magnetic model handling
|
||
- SphericalEngine::coeff::readcoeffs takes new optional argument
|
||
\e truncate.
|
||
- The constructors for GravityModel and MagneticModel allow the
|
||
maximum degree and order to be specified. The array of
|
||
coefficients will then be truncated if necessary.
|
||
- GravityModel::Degree(), GravityModel::Order(),
|
||
MagneticModel::Degree(), MagneticModel::Order() return the
|
||
maximum degree and order of all the components of a GravityModel
|
||
or MagneticModel.
|
||
- <a href="Gravity.1.html">Gravity</a> and
|
||
<a href="MagneticField.1.html">MagneticField</a> utilities
|
||
accept -N and -M options to to allow the maximum degree and order
|
||
to be specified.
|
||
- The <a href="GeodSolve.1.html">GeodSolve</a> allows fractional
|
||
distances to be entered as fractions (with the <code>-F</code>
|
||
flag).
|
||
- MajorRadius() methods are now called EquatorialRadius() for the
|
||
C++, Java, and .NET libraries. "Equatorial" is more descriptive in
|
||
the case of prolate ellipsoids. MajorRadius() is retained for
|
||
backward compatibility for C++ and Java but is deprecated.
|
||
- Minimum version updates:
|
||
- CMake = 3.1.0, released 2014-12-15.
|
||
- Minimum g++ version = 4.8.0, released 2013-03-22.
|
||
- Visual Studio 10 2010 (haven't been able to check Visual Studio
|
||
2008 for a long time).
|
||
- <b>WARNING:</b> The <i>next</i> version of GeographicLib will
|
||
require a C++11 compliant compiler. This means that the minimum
|
||
version of Visual Studio will be Visual Studio 14 2015.
|
||
- Minimum boost version = 1.64 needed for GEOGRAPHICLIB_PRECISION =
|
||
4.
|
||
- Java = 1.6; this allows the removal of epsilon, min, hypot,
|
||
log1p, copysign, cbrt from GeoMath.
|
||
- CMake updates:
|
||
- Fine tune Visual Studio compatibility check in
|
||
find_package(GeographicLib); this allows GeographicLib compiled
|
||
with Visual Studio 14 2015 to be used with a project compiled
|
||
with Visual Studio 15 2017 and 16 2019.
|
||
- Suppress warnings with dotnet build.
|
||
- Change CMake target names and add an interface library (thanks to
|
||
Matthew Woehlke).
|
||
- Remove pre-3.1.0 cruft and update the documentation to remove the
|
||
need to call include_dirctories.
|
||
- Add _d suffix to example and test programs.
|
||
- Changer installation path for binary installer to the Windows
|
||
default.
|
||
- Add support for Intel compiler (for C++, C, Fortran). This
|
||
entails supplying the <code>-fp-model precise</code> flag to
|
||
prevent the compiler from incorrectly simplying <code>(a + b) +
|
||
c</code> and <code>0.0 + x</code>.
|
||
- Add version 2 of the World Magnetic Model 2015, wmm2015v2. This
|
||
is now the default magnetic model for
|
||
<a href="MagneticField.1.html">MagneticField</a> (replacing wmm2015
|
||
which is now deprecated). Coming in 2019-12: the wmm2020 model.
|
||
- The -f flag in the scripts geographiclib-get-geoids,
|
||
geographiclib-get-gravity, and geographiclib-get-magnetic, allows
|
||
you to load new models (not yet in the set defined by "all"). This
|
||
is in addition to its original role of allowing you to overwrite
|
||
existing models.
|
||
- Changes in math function support:
|
||
- Move some of the functionality from Math.hpp to Math.cpp to make
|
||
compilation of package which depend on GeographicLib less
|
||
sensitive to the current compiler environment.
|
||
- Add Math::remainder, Math::remquo, Math::round, and Math::lround.
|
||
Also add implementations of remainder, remquo to C
|
||
implementation.
|
||
- Math::cbrt, Math::atanh, and Math::asinh now preserve the sign of
|
||
−0. (Also: C, Java, JavaScript, Python, MATLAB. Not
|
||
necessary: Fortran because sign is a built-in function.)
|
||
- JavaScript: fall back to Math.hypot, Math.cbrt, Math.log1p,
|
||
Math.atanh if they are available.
|
||
- When parsing DMS strings ignore various non-breaking spaces (C++
|
||
and JavaScript).
|
||
- Improve code coverage in the tests of geodesic algorithms (C++, C,
|
||
Java, JavaScript, Python, MATLAB, Fortran).
|
||
- Old deprecated NormalGravity::NormalGravity constructor removed.
|
||
- Additions to the documentation:
|
||
- add documentation links to ge{distance,reckon}.m;
|
||
- clarify which solution is returned for Geocentric::Reverse.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.49">Version 1.49</a>
|
||
(released 2017-10-05)
|
||
- Add the Enhanced Magnetic Model 2017, emm2017. This is valid for
|
||
2000 thru the end of 2021.
|
||
- Avoid potential problems with the order of initializations in DMS,
|
||
GARS, Geohash, Georef, MGRS, OSGB, SphericalEngine; this only would
|
||
have been an issue if GeographicLib objects were instantiated
|
||
globally. Now no GeographicLib initialization code should be run
|
||
prior to the entry of main().
|
||
- To support the previous fix, add an overload,
|
||
Utility::lookup(const char* s, char c).
|
||
- NearestNeighbor::Search throws an error if \e pts is the wrong size
|
||
(instead of merely returning no results).
|
||
- Use complex arithmetic for Clenshaw sums in TransverseMercator and
|
||
tranmerc_{fwd,inv}.m.
|
||
- Changes in cmake support:
|
||
- fix compiler flags for GEOGRAPHICLIB_PRECISION = 4;
|
||
- add CONVERT_WARNINGS_TO_ERRORS option (default OFF), if ON then
|
||
compiler warnings are treated as errors.
|
||
- Fix warnings about implicit conversions of doubles to bools in C++,
|
||
C, and JavaScript packages.
|
||
- Binary installers for Windows now use Visual Studio 14 2015.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.48">Version 1.48</a>
|
||
(released 2017-04-09)
|
||
- The "official" URL for GeographicLib is now
|
||
https://geographiclib.sourceforge.io (instead of
|
||
http://geographiclib.sourceforge.net).
|
||
- The default range for longitude and azimuth is now
|
||
(−180°, 180°], instead of [−180°,
|
||
180°). This was already the case for the C++ library; now the
|
||
change has been made to the other implementations (C, Fortran,
|
||
Java, JavaScript, Python, MATLAB, and Maxima).
|
||
- Changes to NearestNeighbor:
|
||
- fix BUG in reading a NearestNeighbor object from a stream which
|
||
sometimes incorrectly caused a "Bad index" exception to be
|
||
thrown;
|
||
- add NearestNeighbor::operator<<, NearestNeighbor::operator>>,
|
||
NearestNeighbor::swap, std::swap(GeographicLib::NearestNeighbor&,
|
||
GeographicLib::NearestNeighbor&);
|
||
- Additions to the documentation:
|
||
- add documentation on \ref nearest;
|
||
- \ref normalgravity documentation is now on its own page and now
|
||
has an illustrative figure;
|
||
- document the \ref auxlaterror in the series for auxiliary
|
||
latitudes.
|
||
- Fix BUGS in MATLAB function geodreckon with mixed scalar and array
|
||
arguments.
|
||
- Workaround bug in math.fmod for Python 2.7 on 32-bit Windows
|
||
machines.
|
||
- Changes in cmake support:
|
||
- add USE_BOOST_FOR_EXAMPLES option (default OFF), if ON search for
|
||
Boost libraries for building examples;
|
||
- add APPLE_MULTIPLE_ARCHITECTURES option (default OFF), if ON
|
||
build for both i386 and x86_64 on Mac OS X systems;
|
||
- don't add flag for C++11 for g++ 6.0 (since it's not needed).
|
||
- Fix compiler warnings with Visual Studio 2017 and for the C
|
||
library.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.47">Version 1.47</a>
|
||
(released 2017-02-15)
|
||
- Add NearestNeighbor class.
|
||
- Improve accuracy of area calculation (fixing a flaw introduced in
|
||
version 1.46); fix applied in Geodesic, GeodesicExact, and the
|
||
implementations in C, Fortran, Java, JavaScript, Python, MATLAB,
|
||
and Maxima.
|
||
- Generalize NormalGravity to allow oblate and prolate ellipsoids.
|
||
As a consequence a new form of constructor,
|
||
NormalGravity::NormalGravity, has been introduced and the old
|
||
form is now <b>deprecated</b> (and because the signatures of the two
|
||
constructors are similar, the compiler will warn about the use of
|
||
the old one).
|
||
- Changes in Math class:
|
||
- Math::sincosd, Math::sind, Math::cosd only return −0 for
|
||
the case sin(−0);
|
||
- Math::atan2d and Math::AngNormalize return results in
|
||
(−180°, 180°]; this may affect the longitudes and
|
||
azimuth returned by several other functions.
|
||
- Add Utility::trim() and Utility::val<T>(); Utility::num<T>() is now
|
||
<b>deprecated</b>.
|
||
- Changes in cmake support:
|
||
- remove support of PACKAGE_PATH and INSTALL_PATH in cmake
|
||
configuration;
|
||
- fix to FindGeographicLib.cmake to make it work on Debian systems;
|
||
- use $<TARGET_PDB_FILE:tgt> (cmake version ≥ 3.1);
|
||
- use NAMESPACE for exported targets;
|
||
- geographiclib-config.cmake exports GEOGRAPHICLIB_DATA,
|
||
GEOGRAPHICLIB_PRECISION, and GeographicLib_HIGHPREC_LIBRARIES.
|
||
- Add pkg-config support for cmake and autoconf builds.
|
||
- Minor fixes:
|
||
- fix the order of declarations in C library, incorporating the
|
||
patches in version 1.46.1;
|
||
- fix the packaging of the Python library, incorporating the
|
||
patches in version 1.46.3;
|
||
- restrict junit dependency in the Java package to testing scope
|
||
(thanks to Mick Killianey);
|
||
- various behind-the-scenes fixes to EllipticFunction;
|
||
- fix documentation and default install location for Windows binary
|
||
installers;
|
||
- fix clang compiler warnings in GeodesicExactC4 and
|
||
TransverseMercator.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.46">Version 1.46</a>
|
||
(released 2016-02-15)
|
||
- The following BUGS have been fixed:
|
||
- the -w flag to <a href="Planimeter.1.html">Planimeter(1)</a> was
|
||
being ignored;
|
||
- in the Java package, the wrong longitude was being returned with
|
||
direct geodesic calculation with a negative distance when
|
||
starting point was at a pole (this bug was introduced in version
|
||
1.44);
|
||
- in the JavaScript package, PolygonArea.TestEdge contained a
|
||
misspelling of a variable name and other typos (problem found by
|
||
threepointone).
|
||
- INCOMPATIBLE CHANGES:
|
||
- make the -w flag (to swap the default order of latitude and
|
||
longitude) a toggle for all \ref utilities;
|
||
- the -a option to <a href="GeodSolve.1.html">GeodSolve(1)</a> now
|
||
toggles (instead of sets) arc mode;
|
||
- swap order \e coslon and \e sinlon arguments in CircularEngine
|
||
class.
|
||
- Remove deprecated functionality:
|
||
- remove gradient calculation from the Geoid class and
|
||
<a href="GeoidEval.1.html">GeoidEval(1)</a> (this was inaccurate
|
||
and of dubious utility);
|
||
- remove reciprocal flattening functions, InverseFlattening in many
|
||
classes and Constants::WGS84_r(); stop treating flattening > 1
|
||
as the reciprocal flattening in constructors;
|
||
- remove DMS::Decode(string), DMS::DecodeFraction,
|
||
EllipticFunction:m, EllipticFunction:m1, Math::extradigits,
|
||
Math::AngNormalize2, PolygonArea::TestCompute;
|
||
- stop treating LONG_NOWRAP as an alias for LONG_UNROLL in
|
||
Geodesic (and related classes) and Rhumb;
|
||
- stop treating full/schmidt as aliases for FULL/SCHMIDT in
|
||
SphericalEngine (and related classes);
|
||
- remove qmake project file src/GeographicLib.pro because QtCreator
|
||
can handle cmake projects now;
|
||
- remove deprecated Visual Studio 2005 project and solution files.
|
||
- Changes to GeodesicLine and GeodesicLineExact classes; these
|
||
changes (1) simplify the process of computing waypoints on a
|
||
geodesic given two endpoints and (2) allow a GeodesicLine to be
|
||
defined which is consistent with the solution of the inverse
|
||
problem (in particular Geodesic::InverseLine the specification of
|
||
south-going lines which pass the poles in a westerly direction by
|
||
setting sin α<sub>1</sub> = −0):
|
||
- the class stores the distance \e s13 and arc length \e a13 to a
|
||
reference point 3; by default these quantities are NaNs;
|
||
- GeodesicLine::SetDistance (and GeodesicLine::SetArc) specify the
|
||
distance (and arc length) to point 3;
|
||
- GeodesicLine::Distance (and GeodesicLine::Arc) return the
|
||
distance (and arc length) to point 3;
|
||
- new methods Geodesic::InverseLine and Geodesic::DirectLine return
|
||
a GeodesicLine with the reference point 3 defined as point 2 of
|
||
the corresponding geodesic calculation;
|
||
- these changes are also included in the C, Java, JavaScript, and
|
||
Python packages.
|
||
- Other changes to the geodesic routines:
|
||
- more accurate solution of the inverse problem when longitude
|
||
difference is close to 180° (also in C, Fortran, Java,
|
||
JavaScript, Python, MATLAB, and Maxima packages);
|
||
- more accurate calculation of lon2 in the inverse calculation with
|
||
LONG_UNROLL (also in Java, JavaScript, Python packages).
|
||
- Changes to <a href="GeodSolve.1.html">GeodSolve(1)</a> utility:
|
||
- the -I and -D options now specify geodesic line calculation via
|
||
the standard inverse or direct geodesic problems;
|
||
- rename -l flag to -L to parallel the new -I and -D flags (-l is
|
||
is retained for backward compatibility but is <b>deprecated</b>),
|
||
and similarly for <a href="GeodSolve.1.html">RhumbSolve(1)</a>;
|
||
- the -F flag (in conjunction with the -I or -D flags) specifies that
|
||
distances read on standard input are fractions of \e s13 or \e
|
||
a13;
|
||
- the -a option now toggles arc mode (noted above);
|
||
- the -w option now toggles longitude first mode (noted above).
|
||
- Changes to Math class:
|
||
- Math::copysign added;
|
||
- add overloaded version of Math::AngDiff which returns the error
|
||
in the difference. This allows a more accurate treatment of
|
||
inverse geodesic problem when \e lon12 is close to 180°;
|
||
- Math::AngRound now converts tiny negative numbers to −0
|
||
(instead of +0), however −0 is still converted to +0.
|
||
- Add -S and -T options to
|
||
<a href="GeoConvert.1.html">GeoConvert(1)</a>.
|
||
- Add <a href="https://www.sphinx-doc.org/en/master/">Sphinx</a>
|
||
documentation for Python package.
|
||
- Samples of wrapping the C++ library, so it's accessible in other
|
||
languages, are given in <code>wrapper/C</code>,
|
||
<code>wrapper/python</code>, and <code>wrapper/matlab</code>.
|
||
- Binary installers for Windows now use Visual Studio 12 2013.
|
||
- Remove top-level pom.xml from release (it was specific to SRI).
|
||
- A reminder: because of the JavaScript changes introduced in version
|
||
1.45, you should remove the following installation directories from
|
||
your system:
|
||
- Windows: ${CMAKE_INSTALL_PREFIX}/doc/scripts
|
||
- Others: ${CMAKE_INSTALL_PREFIX}/share/doc/GeographicLib/scripts
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.45">Version 1.45</a>
|
||
(released 2015-09-30)
|
||
- Fix BUG in solution of inverse geodesic caused by misbehavior of
|
||
some versions of Visual Studio on Windows (fmod(−0.0, 360.0)
|
||
returns +0.0 instead of −0.0) and Octave (sind(−0.0)
|
||
returns +0.0 instead of −0.0). These bugs were exposed
|
||
because max(−0.0, +0.0) returns −0.0 for some
|
||
languages.
|
||
- Geodesic::Inverse now correctly returns NaNs if one of the
|
||
latitudes is a NaN.
|
||
- Changes to JavaScript package:
|
||
- thanks to help from Yurij Mikhalevich, it is a now a
|
||
<a href="https://nodejs.org">node</a> package that can be
|
||
installed with <a href="https://www.npmjs.com">npm</a>;
|
||
- make install now installs the node package in
|
||
<code>lib/node_modules/geographiclib</code>;
|
||
- add unit tests using mocha;
|
||
- add documentation via <a href="http://usejsdoc.org">JSDoc</a>;
|
||
- fix bug Geodesic.GenInverse (this bug, introduced in version
|
||
1.44, resulted in the wrong azimuth being reported for points at
|
||
the pole).
|
||
- Changes to Java package:
|
||
- add implementation of ellipsoidal Gnomonic projection (courtesy
|
||
of Sebastian Mattheis);
|
||
- add unit tests using JUnit;
|
||
- Math.toRadians and Math.toDegrees are used instead of
|
||
GeoMath.degree (which is now removed), as a result…
|
||
- Java version 1.2 (released 1998-12) or later is now required.
|
||
- Changes to Python package:
|
||
- add unit tests using the unittest framework;
|
||
- fixed bug in normalization of the area.
|
||
- Changes to MATLAB package:
|
||
- fix array size mismatch in geoddistance by avoiding calls to
|
||
subfunctions with zero-length arrays;
|
||
- fix tranmerc_{fwd,inv} so that they work with arrays and
|
||
mixed array/scalar arguments;
|
||
- work around Octave problem which causes mgrs_fwd to return
|
||
garbage with prec = 10 or 11;
|
||
- add geographiclib_test.m to run a test suite.
|
||
- Behavior of substituting 1/\e f for \e f if \e f > 1 is now
|
||
<b>deprecated</b>. This behavior has been removed from the
|
||
JavaScript, C, and Python implementations (it was never
|
||
documented). Maxima, MATLAB, and Fortran implementations never
|
||
included this behavior.
|
||
- Other changes:
|
||
- fix bug, introduced in version 1.42, in the C++ implementation to
|
||
the computation of area which causes NaNs to be returned in the
|
||
case of a sphere;
|
||
- fixed bug, introduced in version 1.44, in the detection of C++11
|
||
math functions in configure.ac;
|
||
- throw error on non-convergence in Gnomonic::Reverse if
|
||
GEOGRAPHICLIB_PRECISION > 3;
|
||
- add geod_polygon_clear to C library;
|
||
- turn illegal latitudes into NaNs for Fortran library;
|
||
- add test suites for the C and Fortran libraries.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.44">Version 1.44</a>
|
||
(released 2015-08-14)
|
||
- Various changes to improve accuracy, e.g., by minimizing round-off
|
||
errors:
|
||
- Add Math::sincosd, Math::sind, Math::cosd which take their
|
||
arguments in degrees. These functions do exact range reduction
|
||
and thus they obey exactly the elementary properties of the
|
||
trigonometric functions, e.g., sin 9° = cos 81° = −
|
||
sin 123456789°.
|
||
- Math::AngNormalize now works for any angles, instead of angles in
|
||
the range [−540°, 540°); the function
|
||
Math::AngNormalize2 is now <b>deprecated</b>.
|
||
- This means that there is now no restriction on longitudes and
|
||
azimuths; any values can be used.
|
||
- Improve the accuracy of Math::atan2d.
|
||
- DMS::Decode avoids unnecessary round-off errors; thus 7:33:36 and
|
||
7.56 result in identical values. DMS::Encode rounds ties to
|
||
even. These changes have also been made to DMS.js.
|
||
- More accurate rounding in MGRS::Reverse and mgrs_inv.m; this
|
||
change only makes a difference at sub-meter precisions.
|
||
- With MGRS::Forward and mgrs_fwd.m, ensure that digits in lower
|
||
precision results match those at higher precision; as a result,
|
||
strings of trailing 9s are less likely to be generated. This
|
||
change only makes a difference at sub-meter precisions.
|
||
- Replace the series for <i>A</i><sub>2</sub> in the Geodesic class
|
||
with one with smaller truncation errors.
|
||
- Geodesic::Inverse sets \e s12 to zero for coincident points at
|
||
pole (instead of returning a tiny quantity).
|
||
- Math::LatFix returns its argument if it is in [−90°,
|
||
90°]; if not, it returns NaN.
|
||
- Using Math::LatFix, routines which don't check their arguments
|
||
now interpret a latitude outside the legal range of
|
||
[−90°, 90°] as a NaN; such routines will return
|
||
NaNs instead of finite but incorrect results; <b>caution</b>:
|
||
code that (dangerously) relied on the "reasonable" results being
|
||
returned for values of the latitude outside the allowed range
|
||
will now malfunction.
|
||
- All the \ref utilities accept the -w option to swap the
|
||
latitude-longitude order on input and output (and where appropriate
|
||
on the command-line arguments). CartConvert now accepts the -p
|
||
option to set the precision; now all of the utilities except
|
||
GeoidEval accept -p.
|
||
- Add classes for GARS, the Global Area Reference System, and for
|
||
Georef, the World Geographic Reference System.
|
||
- Changes to DMS::Decode and DMS.js:
|
||
- tighten up the rules:
|
||
- 30:70.0 and 30:60 are illegal (minutes and second must be
|
||
strictly less than 60), however
|
||
- 30:60.0 and 30:60. are legal (floating point 60 is OK, since it
|
||
might have been generated by rounding 59.99…);
|
||
- generalize a+b concept, introduced in version 1.42, to any number
|
||
of pieces; thus 8+0:40-0:0:10 is interpreted as 8:39:50.
|
||
- Documentation fixes:
|
||
- update man pages to refer to
|
||
<a href="GeoConvert.1.html">GeoConvert(1)</a> on handling of
|
||
geographic coordinates;
|
||
- document limitations of the series used for TransverseMercator;
|
||
- hide the documentation of the computation of the gradient of the
|
||
geoid height (now <b>deprecated</b>) in the Geoid class;
|
||
- warn about the possible misinterpretation of 7.0E+1 by
|
||
DMS::Decode;
|
||
- \e swaplatlong optional argument of DMS::DecodeLatLon and
|
||
various functions in the GeoCoords class is now called \e
|
||
longfirst;
|
||
- require Doxygen 1.8.7 or later.
|
||
- More systematic treatment of version numbers:
|
||
- Python: \__init\__.py defines \__version\__ and \__version_info\__;
|
||
- JavaScript:
|
||
- Math.js defines Constants.version and Constants.version_string;
|
||
- version number included as comment in packed script
|
||
geographiclib.js;
|
||
- <a href="../scripts/geod-calc.html">geod-calc.html</a> and
|
||
<a href="../scripts/geod-google.html">geod-google.html</a>
|
||
report the version number;
|
||
- https://geographiclib.sourceforge.io/scripts/ gives access to
|
||
earlier versions of geographiclib.js as
|
||
geographiclib-<i>m.nn</i>.js;
|
||
- Fortran: add geover subroutine to return version numbers;
|
||
- Maxima: geodesic.mac defines geod_version;
|
||
- CGI scripts: these report the version numbers of the utilities.
|
||
- BUG FIXES:
|
||
- NormalGravity now works properly for a sphere (\e omega = \e f =
|
||
\e J2 = 0), instead of returning NaNs (problem found by htallon);
|
||
- CassiniSoldner::Forward and cassini_fwd.m now returns the correct
|
||
azimuth for points at the pole.
|
||
- MATLAB-specific fixes:
|
||
- mgrs_fwd now treats treats prec > 11 as prec = 11;
|
||
- illegal letter combinations are now correctly detected by
|
||
mgrs_inv;
|
||
- fixed bug where mgrs_inv returned the wrong results for prec = 0
|
||
strings and center = 0;
|
||
- mgrs_inv now decodes prec = 11 strings properly;
|
||
- routines now return array results with the right shape;
|
||
- routines now properly handle mixed scalar and array arguments.
|
||
- Add Accumulator<T>::operator*=(T y).
|
||
- Geohash uses "invalid" instead of "nan" when the latitude or
|
||
longitude is a nan.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.43">Version 1.43</a>
|
||
(released 2015-05-23)
|
||
- Add the Enhanced Magnetic Model 2015, emm2015. This is valid for
|
||
2000 thru the end of 2019. This required some changes in the
|
||
MagneticModel and MagneticCircle classes; so this model cannot be
|
||
used with versions of GeographicLib prior to 1.43.
|
||
- Fix BLUNDER in PolarStereographic constructor introduced in version
|
||
1.42. This affected UTMUPS conversions for UPS which could be
|
||
incorrect by up to 0.5 km.
|
||
- Changes in the LONG_NOWRAP option (added in version 1.39) in the
|
||
Geodesic and GeodesicLine classes:
|
||
- The option is now called LONG_UNROLL (a less negative sounding
|
||
term); the original name, LONG_NOWRAP, is retained for backwards
|
||
compatibility.
|
||
- There were two bad BUGS in the implementation of this capability:
|
||
(a) it gave <i>incorrect</i> results for west-going
|
||
geodesics; (b) the option was <i>ignored</i> if used
|
||
directly via the GeodesicLine class. The first bug affected the
|
||
implementations in all languages. The second affected the
|
||
implementation in C++ (GeodesicLine and GeodesicLineExact),
|
||
JavaScript, Java, C, Python. These bugs have now been FIXED.
|
||
- The <a href="GeodSolve.1.html">GeodSolve</a> utility now accepts
|
||
a -u option, which turns on the LONG_UNROLL treatment. With this
|
||
option <code>lon1</code> is reported as entered and
|
||
<code>lon2</code> is given such that <code>lon2</code> −
|
||
<code>lon1</code> indicates how often and in what sense the
|
||
geodesic has encircled the earth. (This option also affects the
|
||
value of longitude reported when an inverse calculation is run
|
||
with the -f option.)
|
||
- The inverse calculation with the JavaScript and Python libraries
|
||
similarly sets <code>lon1</code> and <code>lon2</code> in output
|
||
dictionary respecting the LONG_UNROLL flag.
|
||
- The online version of
|
||
<a href="https://geographiclib.sourceforge.io/cgi-bin/GeodSolve">
|
||
GeodSolve</a> now offers an option to unroll the longitude.
|
||
- To support these changes DMS::DecodeLatLon no longer reduces the
|
||
longitude to the range [−180°, 180°) and
|
||
Math::AngRound now coverts −0 to +0.
|
||
- Add Math::polyval (also to C, Java, JavaScript, Fortran, Python
|
||
versions of the library; this is a built-in function for
|
||
MATLAB/Octave). This evaluates a polynomial using Horner's method.
|
||
The Maxima-generated code fragments for the evaluation of series in
|
||
the Geodesic, TransverseMercator, and Rhumb classes and MATLAB
|
||
routines for great ellipses have been replaced by Maxima-generated
|
||
arrays of polynomial coefficients which are used as input to
|
||
Math::polyval.
|
||
- Add MGRS::Check() to verify that \e a, \e f,
|
||
<i>k</i><sub>UTM</sub>, and <i>k</i><sub>UPS</sub> are consistent
|
||
with the assumptions in the UTMUPS and MGRS classes. This is
|
||
invoked with <code>GeoConvert \--version</code>. (This function
|
||
was added to document and check the assumptions used in the UTMUPS
|
||
and MGRS classes in case they are extended to deal with ellipsoids
|
||
other than WS84.)
|
||
- MATLAB function mgrs_inv now takes an optional \e center argument
|
||
and strips white space from both beginning and end of the string.
|
||
- Minor internal changes:
|
||
- GeodSolve sets the geodesic mask so that unnecessary calculations
|
||
are avoided;
|
||
- some routines have migrated into a math class for the Python,
|
||
Java, and JavaScript libraries.
|
||
- A reminder: because of changes in the installation directories for
|
||
non-Windows systems introduced in version 1.42, you should remove
|
||
the following directories from your system:
|
||
- ${CMAKE_INSTALL_PREFIX}/share/cmake/GeographicLib*
|
||
- ${CMAKE_INSTALL_PREFIX}/libexec/GeographicLib/matlab
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.42">Version 1.42</a>
|
||
(released 2015-04-28)
|
||
- DMS::Decode allows a single addition or subtraction operation,
|
||
e.g., 70W+0:0:15. This affects the GeoCoords class and the
|
||
utilities (which use the DMS class for reading coordinates).
|
||
- Add Math::norm, Math::AngRound, Math::tand, Math::atan2d,
|
||
Math::eatanhe, Math::taupf, Math::tauf, Math::fma and remove
|
||
duplicated (but private) functionality from other classes.
|
||
- On non-Windows systems, the cmake config-style find_package files
|
||
are now installed under ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}
|
||
instead of ${CMAKE_INSTALL_PREFIX}/share, because the files are
|
||
architecture-specific. This change will let 32-bit and 64-bit
|
||
versions coexist on the same machine (in lib and lib64). You
|
||
should remove the versions in the old "share" location.
|
||
- MATLAB changes:
|
||
- provide native MATLAB implementations for compiled interface
|
||
functions, see `wrapper/octave`;
|
||
- the compiled MATLAB interface is now <b>deprecated</b> and so the
|
||
MATLAB_COMPILER option in the cmake build has been removed;
|
||
- reorganize directories, so that
|
||
- matlab/geographiclib contains the native matlab code;
|
||
- matlab/geographiclib-legacy contains wrapper functions to mimic
|
||
the previous compiled functionality;
|
||
- the installed MATLAB code mirrors this layout, but the parent
|
||
installation directory on non-Windows systems is
|
||
${CMAKE_INSTALL_PREFIX}/share (instead of
|
||
${CMAKE_INSTALL_PREFIX}/libexec), because the files are now
|
||
architecture independent;
|
||
- matlab/geographiclib is now packaged and distributed as
|
||
MATLAB File Exchange package
|
||
<a href="https://www.mathworks.com/matlabcentral/fileexchange/50605">
|
||
50605</a> (this supersedes three earlier MATLAB packages);
|
||
- point fix for geodarea.m to correct bug in area of polygons which
|
||
encircle a pole multiple times (released as version 1.41.1 of
|
||
MATLAB File Exchange package 39108, 2014-04-22).
|
||
- artifactId for Java package changed from GeographicLib to
|
||
GeographicLib-Java and the package is now deployed to
|
||
Maven Central (thanks to Chris Bennight for help on this).
|
||
- Fix autoconf mismatch of version numbers (which were inconsistent
|
||
in versions 1.40 and 1.41).
|
||
- Mark the computation of the gradient of the geoid height in the
|
||
Geoid class and the <a href="GeoidEval.1.html">GeoidEval</a>
|
||
utility as <b>deprecated</b>.
|
||
- Work around the boost-quadmath bug with setprecision(0).
|
||
- Deprecate use of Visual Studio 2005 "-vc8" project files in the
|
||
windows directory.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.41">Version 1.41</a>
|
||
(released 2015-03-09)
|
||
- Fix bug in Rhumb::Inverse (with \e exact = true) and related
|
||
functions which causes the wrong distance to be reported if one of
|
||
the end points is at a pole. Thanks to Thomas Murray for reporting
|
||
this.
|
||
- Add International Geomagnetic Reference Field (12th generation),
|
||
igrf12, which approximates the main magnetic field of the earth for
|
||
the period 1900--2020.
|
||
- Split information about \ref jacobi to a separate section and
|
||
include more material.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.40">Version 1.40</a>
|
||
(released 2014-12-18)
|
||
- Add the World Magnetic Model 2015, wmm2015. This is now the
|
||
default magnetic model for
|
||
<a href="MagneticField.1.html">MagneticField</a> (replacing wmm2010
|
||
which is valid thru the end of 2014).
|
||
- Geodesic::Inverse didn't return NaN if one of the longitudes was a
|
||
NaN (bug introduced in version 1.25). Fixed in the C++, Java,
|
||
JavaScript, C, Fortran, and Python implementations of the geodesic
|
||
routines. This bug was not present in the MATLAB version.
|
||
- Fix bug in Utility::readarray and Utility::writearray which caused
|
||
an exception in debug mode with zero-sized arrays.
|
||
- Fix BLUNDER in OSGB::GridReference (found by kalderami) where the
|
||
wrong result was returned if the easting or northing was negative.
|
||
- OSGB::GridReference now returns "INVALID" if either coordinate is
|
||
NaN. Similarly a grid reference starting with "IN" results in NaNs
|
||
for the coordinates.
|
||
- Default constructor for GeoCoords corresponds to an undefined
|
||
position (latitude and longitude = NaN), instead of the north pole.
|
||
- Add an online version of <a href="RhumbSolve.1.html">RhumbSolve</a>
|
||
at https://geographiclib.sourceforge.io/cgi-bin/RhumbSolve.
|
||
- Additions to the documentation:
|
||
- documentation on \ref triaxial-conformal;
|
||
- a page on \ref auxlat (actually, this was added in version 1.39);
|
||
- document the use of two single quotes to stand for a double quote
|
||
in DMS (this feature was introduced in version 1.13).
|
||
- The MATLAB function, geographiclibinterface, which compiles the
|
||
wrapper routines for MATLAB now works with MATLAB on a Mac.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.39">Version 1.39</a>
|
||
(released 2014-11-11)
|
||
- GeographicLib usually normalizes longitudes to the range
|
||
[−180°, 180°). However, when solving the direct
|
||
geodesic and rhumb line problems, it is sometimes necessary to know
|
||
how many lines the line encircled the earth by returning the
|
||
longitude "unwrapped". So the following changes have been made:
|
||
- add a LONG_NOWRAP flag to \e mask enums for the \e outmask
|
||
arguments for Geodesic, GeodesicLine, Rhumb, and RhumbLine;
|
||
- similar changes have been made to the Python, JavaScript, and
|
||
Java implementations of the geodesic routines;
|
||
- for the C, Fortran, and MATLAB implementations the \e arcmode
|
||
argument to the routines was generalized to allow a combination
|
||
of ARCMODE and LONG_NOWRAP bits;
|
||
- the Maxima version now returns the longitude unwrapped.
|
||
.
|
||
These changes were necessary to fix the PolygonAreaT::AddEdge (see
|
||
the next item).
|
||
- Changes in area calculations:
|
||
- fix BUG in PolygonAreaT::AddEdge (also in C, Java, JavaScript,
|
||
and Python implementations) which sometimes causes the wrong area
|
||
to be returned if the edge spanned more than 180°;
|
||
- add area calculation to the Rhumb and RhumbLine classes and the
|
||
<a href="RhumbSolve.1.html">RhumbSolve</a> utility (see \ref
|
||
rhumbarea);
|
||
- add PolygonAreaRhumb typedef for PolygonAreaT<Rhumb>;
|
||
- add -R option to <a href="Planimeter.1.html">Planimeter</a> to use
|
||
PolygonAreaRhumb (and -G option for the default geodesic polygon);
|
||
- fix BLUNDER in area calculation in MATLAB routine geodreckon;
|
||
- add area calculation to MATLAB/Octave routines for great ellipses
|
||
(see \ref gearea).
|
||
- Fix bad BUG in Geohash::Reverse; this was introduced in version
|
||
1.37 and affected all platforms where unsigned longs are 32-bits.
|
||
Thanks to Christian Csar for reporting and diagnosing this.
|
||
- Binary installers for Windows are now built with Visual Studio 11
|
||
2012 (instead of Visual Studio 10 2010). Compiled MATLAB support
|
||
still with version 2013a (64-bit).
|
||
- Update GeographicLib.pro for builds with qmake to include all the
|
||
source files.
|
||
- Cmake updates:
|
||
- include cross-compiling checks in cmake config file;
|
||
- improve the way unsuitable versions are reported;
|
||
- include_directories (${GeographicLib_INCLUDE_DIRS}) is no longer
|
||
necessary with cmake 2.8.11 or later.
|
||
- legacy/Fortran now includes drop-in replacements for the geodesic
|
||
utilities from the NGS.
|
||
- geographiclib-get-{geoids,gravity,magnetic} with no arguments now
|
||
print the usage instead of loading the minimal sets.
|
||
- Utility::date(const std::string&, int&, int&, int&) and hence the
|
||
<a href="MagneticField.1.html">MagneticField</a> utility accepts
|
||
the string "now" as a legal time (meaning today).
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.38">Version 1.38</a>
|
||
(released 2014-10-02)
|
||
- On MacOSX, the installed package is relocatable (for cmake version
|
||
2.8.12 and later).
|
||
- On Mac OSX, GeographicLib can be installed using homebrew.
|
||
- In cmake builds under Windows, set the output directories so that
|
||
binaries and shared libraries are together.
|
||
- Accept the minus sign as a synonym for - in DMS.{cpp,js}.
|
||
- The cmake configuration file geographiclib-depends.cmake has been
|
||
renamed to geographiclib-targets.cmake.
|
||
- MATLAB/Octave routines for great ellipses added; see \ref
|
||
greatellipse.
|
||
- Provide man pages for geographiclib-get-{geoids,gravity,magnetic}.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.37">Version 1.37</a>
|
||
(released 2014-08-08)
|
||
- Add \ref highprec.
|
||
- <b>INCOMPATIBLE CHANGE</b>: the static instantiations of various
|
||
classes for the WGS84 ellipsoid have been changed to a
|
||
<a href="https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use">
|
||
"construct on first use idiom"</a>. This avoids a lot of wasteful
|
||
initialization before the user's code starts. Unfortunately it
|
||
means that existing source code that relies on any of the following
|
||
static variables will need to be changed to a function call:
|
||
- AlbersEqualArea::AzimuthalEqualAreaNorth
|
||
- AlbersEqualArea::AzimuthalEqualAreaSouth
|
||
- AlbersEqualArea::CylindricalEqualArea
|
||
- Ellipsoid::WGS84
|
||
- Geocentric::WGS84
|
||
- Geodesic::WGS84
|
||
- GeodesicExact::WGS84
|
||
- LambertConformalConic::Mercator
|
||
- NormalGravity::GRS80
|
||
- NormalGravity::WGS84
|
||
- PolarStereographic::UPS
|
||
- TransverseMercator::UTM
|
||
- TransverseMercatorExact::UTM
|
||
.
|
||
Thus, occurrences of, for example, \code
|
||
const Geodesic& geod = Geodesic::WGS84; // version 1.36 and earlier
|
||
\endcode
|
||
need to be changed to \code
|
||
const Geodesic& geod = Geodesic::WGS84(); // version 1.37 and later
|
||
\endcode
|
||
(note the parentheses!); alternatively use \code
|
||
// works with all versions
|
||
const Geodesic geod(Constants::WGS84_a(), Constants::WGS84_a()); \endcode
|
||
- Incompatible change: the environment variables
|
||
<code>{GEOID,GRAVITY,MAGNETIC}_{NAME,PATH}</code> are now prefixed
|
||
with <code>GEOGRAPHICLIB_</code>.
|
||
- Incompatible change for Windows XP: retire the Windows XP common
|
||
data path. If you're still using Windows XP, then you might have
|
||
to move the folder <code>C:\\Documents and Settings\\All
|
||
Users\\Application Data\\GeographicLib</code> to
|
||
<code>C:\\ProgramData\\GeographicLib</code>.
|
||
- All macro names affecting the compilation now start with
|
||
<code>GEOGRAPHICLIB_</code>; this applies to
|
||
<code>GEOID_DEFAULT_NAME</code>, <code>GRAVITY_DEFAULT_NAME</code>,
|
||
<code>MAGNETIC_DEFAULT_NAME</code>, <code>PGM_PIXEL_WIDTH</code>,
|
||
<code>HAVE_LONG_DOUBLE</code>, <code>STATIC_ASSERT</code>,
|
||
<code>WORDS_BIGENDIAN</code>.
|
||
- Changes to PolygonArea:
|
||
- introduce PolygonAreaT which takes a geodesic class as a parameter;
|
||
- PolygonArea and PolygonAreaExact are typedef'ed to
|
||
PolygonAreaT<Geodesic> and PolygonAreaT<GeodesicExact>;
|
||
- add -E option to <a href="Planimeter.1.html">Planimeter</a> to use
|
||
PolygonAreaExact;
|
||
- add -Q option to <a href="Planimeter.1.html">Planimeter</a> to
|
||
calculate the area on the authalic sphere.
|
||
- Add -p option to <a href="Planimeter.1.html">Planimeter</a>,
|
||
<a href="ConicProj.1.html">ConicProj</a>,
|
||
<a href="GeodesicProj.1.html">GeodesicProj</a>,
|
||
<a href="TransverseMercatorProj.1.html">TransverseMercatorProj</a>.
|
||
- Add Rhumb and RhumbLine classes and the
|
||
<a href="RhumbSolve.1.html">RhumbSolve</a> utility; see \ref rhumb
|
||
for more information.
|
||
- Minor changes to NormalGravity:
|
||
- add NormalGravity::J2ToFlattening and NormalGravity::FlatteningToJ2;
|
||
- use Newton's method to determine \e f from \e J2;
|
||
- in constructor, allow \e omega = 0 (i.e., treat the spherical case).
|
||
- Add grs80 GravityModel, see \ref gravity.
|
||
- Make geographiclib-get-{geoids,gravity,magnetic} scripts work on MacOS.
|
||
- Minor changes:
|
||
- simplify cross-platform support for C++11 mathematical functions;
|
||
- change way area coefficients are given in GeodesicExact to improve
|
||
compile times;
|
||
- enable searching the online documentation;
|
||
- add macros <code>GEOGRAPHICLIB_VERSION</code> and
|
||
<code>GEOGRAPHICLIB_VERSION_NUM</code>;
|
||
- add solution and project files for Visual Studio Express 2010.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.36">Version 1.36</a>
|
||
(released 2014-05-13)
|
||
- Changes to comply with NGA's prohibition of the use of the
|
||
upper-case letters N/S to designate the hemisphere when displaying
|
||
UTM/UPS coordinates:
|
||
- UTMUPS::DecodeZone allows north/south as hemisphere
|
||
designators (in addition to n/s);
|
||
- UTMUPS::EncodeZone now encodes the hemisphere in
|
||
<i>lower case</i> (to distinguish this use from a grid zone
|
||
designator);
|
||
- UTMUPS::EncodeZone takes an optional parameter \e
|
||
abbrev to indicate whether to use n/s or north/south as the
|
||
hemisphere designator;
|
||
- GeoCoords::UTMUPSRepresentation and
|
||
GeoCoords::AltUTMUPSRepresentation similarly accept
|
||
the \e abbrev parameter;
|
||
- <a href="GeoConvert.1.html">GeoConvert</a> uses the
|
||
flags -a and -l to govern whether UTM/UPS output uses n/s
|
||
(the -a flag) or north/south (the -l flag) to denote the
|
||
hemisphere;
|
||
- Fixed a bug what allowed +3N to be accepted as an alternative UTM
|
||
zone designation (instead of 3N).
|
||
.
|
||
<b>WARNING:</b> The use of lower case n/s for the hemisphere might
|
||
cause compatibility problems. However DecodeZone has always
|
||
accepted either case; so the issue will only arise with other
|
||
software reading the zone information. To avoid possible
|
||
misinterpretation of the zone designator, consider calling
|
||
EncodeZone with \e abbrev = false and GeoConvert with -l, so that
|
||
north/south are used to denote the hemisphere.
|
||
- MGRS::Forward with \e prec = −1 will produce a grid
|
||
zone designation. Similarly MGRS::Reverse will
|
||
decode a grid zone designation (and return \e prec = −1).
|
||
- Stop using the throw() declaration specification which is
|
||
deprecated in C++11.
|
||
- Add missing std:: qualifications to copy in LocalCartesion and
|
||
Geocentric headers (bug found by Clemens).
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.35">Version 1.35</a>
|
||
(released 2014-03-13)
|
||
- Fix blunder in UTMUPS::EncodeEPSG (found by Ben
|
||
Adler).
|
||
- MATLAB wrapper routines geodesic{direct,inverse,line} switch to
|
||
"exact" routes if |<i>f</i>| > 0.02.
|
||
- GeodSolve.cgi allows ellipsoid to be set (and uses the -E option
|
||
for <a href="GeodSolve.1.html">GeodSolve</a>).
|
||
- Set title in HTML versions of man pages for the \ref utilities.
|
||
- Changes in cmake support:
|
||
- add _d to names of executables in debug mode of Visual Studio;
|
||
- add support for Android (cmake-only), thanks to Pullan Yu;
|
||
- check CPACK version numbers supplied on command line;
|
||
- configured version of project-config.cmake.in is
|
||
project-config.cmake (instead of geographiclib-config.cmake), to
|
||
prevent find_package incorrectly using this file;
|
||
- fix tests with multi-line output;
|
||
- this release includes a file, pom.xml, which is used by an
|
||
experimental build system (based on maven) at SRI.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.34">Version 1.34</a>
|
||
(released 2013-12-11)
|
||
- Many changes in cmake support:
|
||
- minimum version of cmake needed increased to 2.8.4 (which was
|
||
released in 2011-02);
|
||
- allow building both shared and static libraries with <code>-D
|
||
GEOGRAPHICLIB_LIB_TYPE=BOTH</code>;
|
||
- both shared and static libraries (Release plus Debug) included in
|
||
binary installer;
|
||
- find_package uses COMPONENTS and GeographicLib_USE_STATIC_LIBS to
|
||
select the library to use;
|
||
- find_package version checking allows nmake and Visual Studio
|
||
generators to interoperate on Windows;
|
||
- find_package (GeographicLib …) requires that GeographicLib be
|
||
capitalized correctly;
|
||
- on Unix/Linux, don't include the version number in directory for
|
||
the cmake configuration files;
|
||
- defaults for GEOGRAPHICLIB_DOCUMENTATION and
|
||
BUILD_NETGEOGRAPHICLIB are now OFF;
|
||
- the GEOGRAPHICLIB_EXAMPLES configuration parameter is no longer
|
||
used; cmake always configures to build the examples, but they are
|
||
not built by default (instead build targets: exampleprograms and
|
||
netexamples);
|
||
- matlab-all target renamed to matlabinterface;
|
||
- the configuration parameters PACKAGE_PATH and INSTALL_PATH are
|
||
now deprecated (use CMAKE_INSTALL_PREFIX instead);
|
||
- on Linux, the installed package is relocatable;
|
||
- on MacOSX, the installed utilities can find the shared library.
|
||
- Use a more precise value for OSGB::CentralScale().
|
||
- Add Arc routines to Python interface.
|
||
- The Geod utility has been removed; the same functionality lives on
|
||
with <a href="GeodSolve.1.html">GeodSolve</a> (introduced in
|
||
version 1.30).
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.33">Version 1.33</a>
|
||
(released 2013-10-08)
|
||
- Add <a href="NET/index.html">NETGeographic .NET wrapper library</a>
|
||
(courtesy of Scott Heiman).
|
||
- Make inspector functions in Ellipsoid const.
|
||
- Add Accumulator.cpp to instantiate Accumulator.
|
||
- Defer some of the initialization of OSGB to when it
|
||
is first called.
|
||
- Fix bug in autoconf builds under MacOS.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.32">Version 1.32</a>
|
||
(released 2013-07-12)
|
||
- Generalize C interface for polygon areas to allow vertices to be
|
||
specified incrementally.
|
||
- Fix way flags for C++11 support are determined.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.31">Version 1.31</a>
|
||
(released 2013-07-01)
|
||
- Changes breaking binary compatibility (source compatibility is
|
||
maintained):
|
||
- overloaded versions of DMS::Encode,
|
||
EllipticFunction::EllipticFunction, and
|
||
GeoCoords::DMSRepresentation, have been eliminated
|
||
by the use of optional arguments;
|
||
- correct the declaration of first arg to
|
||
UTMUPS::DecodeEPSG.
|
||
- FIX BUG in GravityCircle constructor (found by
|
||
Mathieu Peyréga) which caused bogus results for the gravity
|
||
disturbance and gravity anomaly vectors. (This only affected
|
||
calculations using GravityCircle. GravityModel calculations did
|
||
not suffer from this bug.)
|
||
- Improvements to the build:
|
||
- add macros GEOGRAPHICLIB_VERSION_{MAJOR,MINOR,PATCH} to Config.h;
|
||
- fix documentation for new version of perlpod;
|
||
- improving setting of runtime path for Unix-like systems with cmake;
|
||
- install PDB files when compiling with Visual Studio to aid
|
||
debugging;
|
||
- Windows binary release now uses MATLAB R2013a (64-bit) and
|
||
uses the -largeArrayDims option.
|
||
- fixes to the way the MATLAB interface routines are built (thanks
|
||
to Phil Miller and Chris F.).
|
||
- Changes to the geodesic routines:
|
||
- add Java implementation of the geodesic routines (thanks to Skip
|
||
Breidbach for the maven support);
|
||
- FIX BUG: avoid altering input args in Fortran implementation;
|
||
- more systematic treatment of very short geodesic;
|
||
- fixes to Python port so that they work with version 3.x, in
|
||
addition to 2.x (courtesy of Amato);
|
||
- accumulate the perimeter and area of polygons via a double-wide
|
||
accumulator in Fortran, C, and MATLAB implementations (this is
|
||
already included in the other implementations);
|
||
- port PolygonArea::AddEdge and
|
||
PolygonArea::TestEdge to JavaScript and Python
|
||
interfaces;
|
||
- include documentation on \ref geodshort.
|
||
- Unix scripts for downloading datasets,
|
||
geographiclib-get-{geoids,gravity,magnetic}, skip already download
|
||
models by default, unless the -f flag is given.
|
||
- FIX BUGS: meridian convergence and scale returned by
|
||
TransverseMercatorExact was wrong at a pole.
|
||
- Improve efficiency of MGRS::Forward by avoiding the
|
||
calculation of the latitude if possible (adapting an idea of Craig
|
||
Rollins).
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.30">Version 1.30</a>
|
||
(released 2013-02-27)
|
||
- Changes to geodesic routines:
|
||
- FIX BUG in fail-safe mechanisms in Geodesic::Inverse;
|
||
- the command line utility Geod is now called
|
||
<a href="GeodSolve.1.html">GeodSolve</a>;
|
||
- allow addition of polygon edges in PolygonArea;
|
||
- add full Maxima implementation of geodesic algorithms.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.29">Version 1.29</a>
|
||
(released 2013-01-16)
|
||
- Changes to allow compilation with libc++ (courtesy of Kal Conley).
|
||
- Add description of \ref triaxial to documentation.
|
||
- Update journal reference for "Algorithms for geodesics".
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.28">Version 1.28</a>
|
||
(released 2012-12-11)
|
||
- Changes to geodesic routines:
|
||
- compute longitude difference exactly;
|
||
- hence FIX BUG in area calculations for polygons with vertices very
|
||
close to the prime meridian;
|
||
- FIX BUG is geoddistance.m where the value of m12 was wrong for
|
||
meridional geodesics;
|
||
- add MATLAB implementations of the geodesic projections;
|
||
- remove unneeded special code for geodesics which start at a pole;
|
||
- include polygon area routine in C and Fortran implementations;
|
||
- add doxygen documentation for C and Fortran libraries.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.27">Version 1.27</a>
|
||
(released 2012-11-29)
|
||
- Changes to geodesic routines:
|
||
- add native MATLAB implementations: geoddistance.m, geodreckon.m,
|
||
geodarea.m;
|
||
- add C and Fortran implementations;
|
||
- improve the solution of the direct problem so that the series
|
||
solution is accurate to round off for |<i>f</i>| < 1/50;
|
||
- tighten up the convergence criteria for solution of the inverse
|
||
problem;
|
||
- no longer signal failures of convergence with NaNs (a slightly
|
||
less accurate answer is returned instead).
|
||
- Fix DMS::Decode double rounding BUG.
|
||
- On MacOSX platforms with the cmake configuration, universal
|
||
binaries are built.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.26">Version 1.26</a>
|
||
(released 2012-10-22)
|
||
- Replace the series used for geodesic areas by one with better
|
||
convergence (this only makes an appreciable difference if
|
||
|<i>f</i>| > 1/150).
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.25">Version 1.25</a>
|
||
(released 2012-10-16)
|
||
- Changes to geodesic calculations:
|
||
- restart Newton's method in Geodesic::Inverse when it goes awry;
|
||
- back up Newton's method with the bisection method;
|
||
- Geodesic::Inverse now converges for any value of \e f;
|
||
- add GeodesicExact and GeodesicLineExact which are formulated in
|
||
terms of elliptic integrals and thus yield accurate results even
|
||
for very eccentric ellipsoids;
|
||
- the -E option to <a href="GeodSolve.1.html">Geod</a> invokes these
|
||
exact classes.
|
||
- Add functionality to EllipticFunction:
|
||
- add all the traditional elliptic integrals;
|
||
- remove restrictions on argument range for incomplete elliptic integrals;
|
||
- allow imaginary modulus for elliptic integrals and elliptic functions;
|
||
- make interface to the symmetric elliptic integrals public.
|
||
- Allow Ellipsoid to be copied.
|
||
- Changes to the build tools:
|
||
- cmake uses folders in Visual Studio to reduce clutter;
|
||
- allow precision of reals to be set in cmake;
|
||
- fail gracefully in the absence of pod documentation tools;
|
||
- remove support for maintainer tasks in Makefile.mk;
|
||
- upgrade to automake 1.11.6 to fix the "make distcheck" security
|
||
vulnerability; see
|
||
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-3386
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.24">Version 1.24</a>
|
||
(released 2012-09-22)
|
||
- Allow the specification of the hemisphere in UTM coordinates in
|
||
order to provide continuity across the equator:
|
||
- add UTMUPS::Transfer;
|
||
- add GeoCoords::UTMUPSRepresentation(bool, int) and
|
||
GeoCoords::AltUTMUPSRepresentation(bool, int);
|
||
- use the hemisphere letter in, e.g.,
|
||
<a href="GeoConvert.1.html">GeoConvert</a> -u -z 31n.
|
||
- Add UTMUPS::DecodeEPSG and
|
||
UTMUPS::EncodeEPSG.
|
||
- cmake changes:
|
||
- restore support for cmake 2.4.x;
|
||
- explicitly check version of doxygen.
|
||
- Fix building under cygwin.
|
||
- Document restrictions on \e f in \ref intro.
|
||
- Fix Python interface to work with version 2.6.x.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.23">Version 1.23</a>
|
||
(released 2012-07-17)
|
||
- Documentation changes:
|
||
- remove html documentation from distribution and use web links if
|
||
doxygen is not available;
|
||
- use doxygen tags to document exceptions;
|
||
- begin migrating the documentation to using Greek letters where
|
||
appropriate (requires doxygen 1.8.1.2 or later).
|
||
- Add Math::AngNormalize and
|
||
Math::AngNormalize2; the allowed range for longitudes
|
||
and azimuths widened to [−540°, 540°).
|
||
- DMS::Decode understands more unicode symbols.
|
||
- Geohash uses geohash code "nan" to stand for not a
|
||
number.
|
||
- Add Ellipsoid::NormalCurvatureRadius.
|
||
- Various fixes in LambertConformalConic,
|
||
TransverseMercator,
|
||
PolarStereographic, and Ellipsoid to
|
||
handle reverse projections of points near infinity.
|
||
- Fix programming blunder in LambertConformalConic::Forward
|
||
(incorrect results were returned if the tangent latitude was
|
||
negative).
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.22">Version 1.22</a>
|
||
(released 2012-05-27)
|
||
- Add Geohash and Ellipsoid classes.
|
||
- FIX BUG in AlbersEqualArea for very prolate
|
||
ellipsoids (<i>b</i><sup>2</sup> > 2 <i>a</i><sup>2</sup>).
|
||
- cmake changes:
|
||
- optionally use PACKAGE_PATH and INSTALL_PATH to determine
|
||
CMAKE_INSTALL_PREFIX;
|
||
- use COMMON_INSTALL_PATH to determine layout of installation
|
||
directories;
|
||
- as a consequence, the installation paths for the documentation,
|
||
and Python and MATLAB interfaces are shortened for Windows;
|
||
- zip source distribution now uses DOS line endings;
|
||
- the tests work in debug mode for Windows;
|
||
- default setting of GEOGRAPHICLIB_DATA does not depend on
|
||
CMAKE_INSTALL_PREFIX;
|
||
- add a cmake configuration for build tree.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.21">Version 1.21</a>
|
||
(released 2012-04-25)
|
||
- Support colon-separated DMS output:
|
||
- DMS::Encode and
|
||
GeoCoords::DMSRepresentation generalized;
|
||
- <a href="GeoConvert.1.html">GeoConvert</a> and
|
||
<a href="GeodSolve.1.html">Geod</a> now accept a -: option.
|
||
- <a href="GeoidEval.1.html">GeoidEval</a> does not print the gradient
|
||
of the geoid height by default (because it's subject to large
|
||
errors); give the -g option to get the gradient printed.
|
||
- Work around optimization BUG in Geodesic::Inverse
|
||
with tdm mingw g++ version 4.6.1.
|
||
- autoconf fixed to ensure that that out-of-sources builds work;
|
||
document this as the preferred method of using autoconf.
|
||
- cmake tweaks:
|
||
- simplify the configuration of doxygen;
|
||
- allow the MATLAB compiler to be specified with the
|
||
MATLAB_COMPILER option.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.20">Version 1.20</a>
|
||
(released 2012-03-23)
|
||
- cmake tweaks:
|
||
- improve find_package's matching of compiler versions;
|
||
- CMAKE_INSTALL_PREFIX set from CMAKE_PREFIX_PATH if available;
|
||
- add "x64" to the package name for the 64-bit binary installer;
|
||
- fix cmake warning with Visual Studio Express.
|
||
- Fix SphericalEngine to deal with aggressive iterator
|
||
checking by Visual Studio.
|
||
- Fix transcription BUG is Geodesic.js.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.19">Version 1.19</a>
|
||
(released 2012-03-13)
|
||
- Slight improvement in Geodesic::Inverse for very
|
||
short lines.
|
||
- Fix argument checking tests in MGRS::Forward.
|
||
- Add \--comment-delimiter and \--line-separator options to the \ref
|
||
utilities.
|
||
- Add installer for 64-bit Windows; the compiled MATLAB interface is
|
||
supplied with the Windows 64-bit installer only.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.18">Version 1.18</a>
|
||
(released 2012-02-18)
|
||
- Improve documentation on configuration with cmake.
|
||
- cmake's find_package ensures that the compiler versions match on Windows.
|
||
- Improve documentation on compiling MATLAB interface.
|
||
- Binary installer for Windows installs under C:/pkg-vc10 by default.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.17">Version 1.17</a>
|
||
(released 2012-01-21)
|
||
- Work around optimization BUG in Geodesic::Inverse
|
||
with g++ version 4.4.0 (mingw).
|
||
- Fix BUG in argument checking with OSGB::GridReference.
|
||
- Fix missing include file in SphericalHarmonic2.
|
||
- Add simple examples of usage for each class.
|
||
- Add internal documentation to the cmake configuration files.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.16">Version 1.16</a>
|
||
(released 2011-12-07)
|
||
- Add calculation of the earth's gravitational field:
|
||
- add NormalGravity GravityModel and
|
||
GravityCircle classes;
|
||
- add command line utility
|
||
<a href="Gravity.1.html">Gravity</a>;
|
||
- add \ref gravity;
|
||
- add Constants::WGS84_GM(), Constants::WGS84_omega(), and
|
||
similarly for GRS80.
|
||
- Build uses GEOGRAPHICLIB_DATA to specify a common parent directory
|
||
for geoid, gravity, and magnetic data (instead of
|
||
GEOGRAPHICLIB_GEOID_PATH, etc.); similarly,
|
||
<a href="GeoidEval.1.html">GeoidEval</a>,
|
||
<a href="Gravity.1.html">Gravity</a>, and
|
||
<a href="MagneticField.1.html">MagneticField</a>, look at the
|
||
environment variable GEOGRAPHICLIB_DATA to locate the data.
|
||
- Spherical harmonic software changes:
|
||
- capitalize enums SphericalHarmonic::FULL and
|
||
SphericalHarmonic::SCHMIDT (the lower case names
|
||
are retained but deprecated);
|
||
- optimize the sum by using a static table of square roots which is
|
||
updated by SphericalEngine::RootTable;
|
||
- avoid overflow for high degree models.
|
||
- Magnetic software fixes:
|
||
- fix documentation BUG in MagneticModel::Circle;
|
||
- make MagneticModel constructor explicit;
|
||
- provide default MagneticCircle constructor;
|
||
- add additional inspector functions to
|
||
MagneticCircle;
|
||
- add -c option to <a href="MagneticField.1.html">MagneticField</a>;
|
||
- default height to zero in
|
||
<a href="MagneticField.1.html">MagneticField</a>.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.15">Version 1.15</a>
|
||
(released 2011-11-08)
|
||
- Add calculation of the earth's magnetic field:
|
||
- add MagneticModel and MagneticCircle
|
||
classes;
|
||
- add command line utility
|
||
<a href="MagneticField.1.html">MagneticField</a>;
|
||
- add \ref magnetic;
|
||
- add \ref magneticinst;
|
||
- add \ref magneticformat;
|
||
- add classes SphericalEngine,
|
||
CircularEngine, SphericalHarmonic,
|
||
SphericalHarmonic1, and
|
||
SphericalHarmonic2. which sum spherical harmonic
|
||
series.
|
||
- Add Utility class to support I/O and date
|
||
manipulation.
|
||
- Cmake configuration includes a _d suffix on the library built in
|
||
debug mode.
|
||
- For the Python package, include manifest and readme files; don't
|
||
install setup.py for non-Windows systems.
|
||
- Include Doxygen tag file in distribution as doc/html/Geographic.tag.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.14">Version 1.14</a>
|
||
(released 2011-09-30)
|
||
- Ensure that geographiclib-config.cmake is relocatable.
|
||
- Allow more unicode symbols to be used in DMS::Decode.
|
||
- Modify <a href="GeoidEval.1.html">GeoidEval</a> so that it can be
|
||
used to convert the height datum for LIDAR data.
|
||
- Modest speed-up of Geodesic::Inverse.
|
||
- Changes in Python interface:
|
||
- FIX BUG in transcription of Geodesic::Inverse;
|
||
- include setup.py for easy installation;
|
||
- Python only distribution is available at
|
||
https://pypi.python.org/pypi/geographiclib
|
||
- Supply a minimal Qt qmake project file for library
|
||
src/Geographic.pro.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.13">Version 1.13</a>
|
||
(released 2011-08-13)
|
||
- Changes to I/O:
|
||
- allow : (colon) to be used as a DMS separator in
|
||
DMS::Decode(const std::string&, flag&);
|
||
- also accept Unicode symbols for degrees, minutes, and seconds
|
||
(coded as UTF-8);
|
||
- provide optional \e swaplatlong argument to various
|
||
DMS and GeoCoords functions to make
|
||
longitude precede latitude;
|
||
- <a href="GeoConvert.1.html">GeoConvert</a> now has a -w option to
|
||
make longitude precede latitude on input and output;
|
||
- include a JavaScript version of DMS.
|
||
- Slight improvement in starting guess for solution of geographic
|
||
latitude in terms of conformal latitude in TransverseMercator,
|
||
TransverseMercatorExact, and LambertConformalConic.
|
||
- For most classes, get rid of const member variables so that the
|
||
default copy assignment works.
|
||
- Put Math and Accumulator in their own
|
||
header files.
|
||
- Remove unused "fast" Accumulator method.
|
||
- Reorganize `wrapper/python`.
|
||
- Withdraw some deprecated routines.
|
||
- cmake changes:
|
||
- include FindGeographic.cmake in distribution;
|
||
- building with cmake creates and installs
|
||
geographiclib-config.cmake;
|
||
- better support for building a shared library under Windows.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.12">Version 1.12</a>
|
||
(released 2011-07-21)
|
||
- Change license to MIT/X11.
|
||
- Add PolygonArea class and equivalent MATLAB function.
|
||
- Provide JavaScript and Python implementations of geodesic routines.
|
||
- Fix Windows installer to include runtime dlls for MATLAB.
|
||
- Fix (innocuous) unassigned variable in Geodesic::GenInverse.
|
||
- Geodesic routines in MATLAB return a12 as first column of aux return
|
||
value (incompatible change).
|
||
- A couple of code changes to enable compilation with Visual
|
||
Studio 2003.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.11">Version 1.11</a>
|
||
(released 2011-06-27)
|
||
- Changes to <a href="Planimeter.1.html">Planimeter</a>:
|
||
- add -l flag to <a href="Planimeter.1.html">Planimeter</a> for polyline
|
||
calculations;
|
||
- trim precision of area to 3 decimal places;
|
||
- FIX BUG with pole crossing edges (due to compiler optimization).
|
||
- <a href="GeodSolve.1.html">Geod</a> no longer reports the reduced
|
||
length by default; however the -f flag still reports this and in
|
||
addition gives the geodesic scales and the geodesic area.
|
||
- FIX BUGS (compiler-specific) in inverse geodesic calculations.
|
||
- FIX BUG: accommodate tellg() returning −1 at end of string.
|
||
- Change way flattening of the ellipsoid is specified:
|
||
- constructors take \e f argument which is taken to be the
|
||
flattening if \e f < 1 and the inverse flattening otherwise
|
||
(this is a compatible change for spheres and oblate ellipsoids, but it
|
||
is an INCOMPATIBLE change for prolate ellipsoids);
|
||
- the -e arguments to the \ref utilities are handled similarly; in
|
||
addition, simple fractions, e.g., 1/297, can be used for the
|
||
flattening;
|
||
- introduce Constants::WGS84_f() for the WGS84
|
||
flattening (and deprecate Constants::WGS84_r() for the inverse
|
||
flattening);
|
||
- most classes have a Flattening() member function;
|
||
- InverseFlattening() has been deprecated (and now returns inf for a
|
||
sphere, instead of 0).
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.10">Version 1.10</a>
|
||
(released 2011-06-11)
|
||
- Improvements to MATLAB/Octave interface:
|
||
- add {geocentric,localcartesian}{forward,reverse};
|
||
- make geographiclibinterface more general;
|
||
- install the source for the interface;
|
||
- cmake compiles the interface if ENABLE_MATLAB=ON;
|
||
- include compiled interface with Windows binary installer.
|
||
- Fix various configuration issues
|
||
- autoconf did not install Config.h;
|
||
- cmake installed in man/man1 instead of share/man/man1;
|
||
- cmake did not set the rpath on the tools.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.9">Version 1.9</a>
|
||
(released 2011-05-28)
|
||
- FIX BUG in area returned by
|
||
<a href="Planimeter.1.html">Planimeter</a> for pole encircling polygons.
|
||
- FIX BUG in error message reported when DMS::Decode reads the string
|
||
"5d.".
|
||
- FIX BUG in AlbersEqualArea::Reverse (lon0 not being used).
|
||
- Ensure that all exceptions thrown in the \ref utilities are caught.
|
||
- Avoid using catch within DMS.
|
||
- Move Accumulator class from Planimeter.cpp to
|
||
Constants.hpp.
|
||
- Add Math::sq<T>.
|
||
- Simplify \ref geoidinst
|
||
- add geographiclib-get-geoids for Unix-like systems;
|
||
- add installers for Windows.
|
||
- Provide cmake support:
|
||
- build binary installer for Windows;
|
||
- include regression tests;
|
||
- add \--input-string, \--input-file, \--output-file options to the
|
||
\ref utilities to support tests.
|
||
- Rename utility EquidistantTest as <a href="GeodesicProj.1.html">
|
||
GeodesicProj</a> and TransverseMercatorTest as
|
||
<a href="TransverseMercatorProj.1.html"> TransverseMercatorProj</a>.
|
||
- Add <a href="ConicProj.1.html"> ConicProj</a>.
|
||
- Reverse the initial sense of the -s option for
|
||
<a href="Planimeter.1.html"> Planimeter</a>.
|
||
- Migrate source from subversion to git.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.8">Version 1.8</a>
|
||
(released 2011-02-22)
|
||
- Optionally return rotation matrix from Geocentric and
|
||
LocalCartesian.
|
||
- For the \ref utilities, supply man pages, -h prints the synopsis,
|
||
\--help prints the man page, \--version prints the version.
|
||
- Use accurate summation in <a href="Planimeter.1.html">Planimeter</a>.
|
||
- Add 64-bit targets for Visual Studio 2010.
|
||
- Use templates for defining math functions and some constants.
|
||
- Geoid updates
|
||
- Add Geoid::DefaultGeoidPath and
|
||
Geoid::DefaultGeoidName;
|
||
- <a href="GeoidEval.1.html">GeoidEval</a> uses environment variable
|
||
GEOGRAPHICLIB_GEOID_NAME as the default geoid;
|
||
- Add \--msltohae and \--haetomsl as
|
||
<a href="GeoidEval.1.html">GeoidEval</a> options (and don't
|
||
document the single hyphen versions).
|
||
- Remove documentation that duplicates papers on transverse Mercator
|
||
and geodesics.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.7">Version 1.7</a>
|
||
(released 2010-12-21)
|
||
- FIX BUG in scale returned by LambertConformalConic::Reverse.
|
||
- Add AlbersEqualArea projection.
|
||
- Library created by Visual Studio is Geographic.lib instead of
|
||
GeographicLib.lib (compatible with makefiles).
|
||
- Make classes NaN aware.
|
||
- Use cell arrays for MGRS strings in MATLAB.
|
||
- Add solution/project files for Visual Studio 2010 (32-bit only).
|
||
- Use C++11 static_assert and math functions, if available.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.6">Version 1.6</a>
|
||
(released 2010-11-23)
|
||
- FIX BUG introduced in Geoid in version 1.5 (found by
|
||
Dave Edwards).
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.5">Version 1.5</a>
|
||
(released 2010-11-19)
|
||
- Improve area calculations for small polygons.
|
||
- Add -s and -r flags to <a href="Planimeter.1.html">Planimeter</a>.
|
||
- Improve the accuracy of LambertConformalConic using
|
||
divided differences.
|
||
- FIX BUG in meridian convergence returned by
|
||
LambertConformalConic::Forward.
|
||
- Add optional threadsafe parameter to Geoid
|
||
constructor. WARNING: This changes may break binary compatibility
|
||
with previous versions of GeographicLib. However, the library is
|
||
source compatible.
|
||
- Add OSGB.
|
||
- MATLAB and Octave interfaces to UTMUPS,
|
||
MGRS, Geoid, Geodesic
|
||
provided.
|
||
- Minor changes
|
||
- explicitly turn on optimization in Visual Studio 2008 projects;
|
||
- add missing dependencies in some Makefiles;
|
||
- move pi() and degree() from Constants to
|
||
Math;
|
||
- introduce Math::extended type to aid testing;
|
||
- add Math::epi() and Math::edegree().
|
||
- fixes to compile under cygwin;
|
||
- tweak expression used to find latitude from conformal latitude.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.4">Version 1.4</a>
|
||
(released 2010-09-12)
|
||
- Changes to Geodesic and GeodesicLine:
|
||
- FIX BUG in Geodesic::Inverse with prolate ellipsoids;
|
||
- add area computations to Geodesic::Direct and Geodesic::Inverse;
|
||
- add geodesic areas to geodesic test set;
|
||
- make GeodesicLine constructor public;
|
||
- change longitude series in Geodesic into Helmert-like form;
|
||
- ensure that equatorial geodesics have cos(alpha0) = 0 identically;
|
||
- generalize interface for Geodesic and GeodesicLine;
|
||
- split GeodesicLine and Geodesic into different files;
|
||
- signal convergence failure in Geodesic::Inverse with NaNs;
|
||
- deprecate one function in Geodesic and two functions in
|
||
GeodesicLine;
|
||
- deprecate -n option for <a href="GeodSolve.1.html">Geod</a>.
|
||
.
|
||
<b>WARNING</b>: These changes may break binary compatibility with
|
||
previous versions of GeographicLib. However, the library is
|
||
source compatible (with the proviso that
|
||
GeographicLib/GeodesicLine.hpp may now need to be included).
|
||
- Add the <a href="Planimeter.1.html">Planimeter</a> utility for
|
||
computing the areas of geodesic polygons.
|
||
- Improve iterative solution of Gnomonic::Reverse.
|
||
- Add Geoid::ConvertHeight.
|
||
- Add -msltohae, -haetomsl, and -z options to
|
||
<a href="GeoidEval.1.html">GeoidEval</a>.
|
||
- Constructors check that minor radius is positive.
|
||
- Add overloaded Forward and Reverse functions to the projection
|
||
classes which don't return the convergence (or azimuth) and scale.
|
||
- Document function parameters and return values consistently.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.3">Version 1.3</a>
|
||
(released 2010-07-21)
|
||
- Add Gnomonic, the ellipsoid generalization of the
|
||
gnomonic projection.
|
||
- Add -g and -e options to
|
||
<a href="GeodesicProj.1.html">EquidistantTest</a>.
|
||
- Use fixed-point notation for output from
|
||
<a href="CartConvert.1.html">CartConvert</a>,
|
||
<a href="GeodesicProj.1.html">EquidistantTest</a>,
|
||
<a href="TransverseMercatorProj.1.html">TransverseMercatorTest</a>.
|
||
- PolarStereographic:
|
||
- Improved conversion to conformal coordinates;
|
||
- Fix bug with scale at opposite pole;
|
||
- Complain if latitude out of range in SetScale.
|
||
- Add Math::NaN().
|
||
- Add long double version of hypot for Windows.
|
||
- Add EllipticFunction::E(real).
|
||
- Update references to Geotrans in MGRS documentation.
|
||
- Speed up tmseries.mac.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.2">Version 1.2</a>
|
||
(released 2010-05-21)
|
||
- FIX BUGS in Geodesic,
|
||
- wrong azimuth returned by Direct if point 2 is on a pole;
|
||
- Inverse sometimes fails with very close points.
|
||
- Improve calculation of scale in CassiniSoldner,
|
||
- add GeodesicLine::Scale,
|
||
GeodesicLine::EquatorialAzimuth, and
|
||
GeodesicLine::EquatorialArc;
|
||
- break friend connection between CassiniSoldner and Geodesic.
|
||
- Add DMS::DecodeAngle and
|
||
DMS::DecodeAzimuth. Extend
|
||
DMS::Decode and DMS::Encode to deal
|
||
with distances.
|
||
- Code and documentation changes in Geodesic and
|
||
Geocentric for consistency with
|
||
the forthcoming paper on geodesics.
|
||
- Increase order of series using in Geodesic to 6 (full
|
||
accuracy maintained for ellipsoid flattening < 0.01).
|
||
- Macro __NO_LONG_DOUBLE_MATH to disable use of long double.
|
||
- Correct declaration of Math::isfinite to return a bool.
|
||
- Changes in the \ref utilities,
|
||
- improve error reporting when parsing command line arguments;
|
||
- accept latitudes and longitudes in decimal degrees or degrees,
|
||
minutes, and seconds, with optional hemisphere designators;
|
||
- <a href="GeoConvert.1.html">GeoConvert</a> -z accepts zone or
|
||
zone+hemisphere;
|
||
- <a href="GeoidEval.1.html">GeoidEval</a> accepts any of the input
|
||
formats used by <a href="GeoConvert.1.html">GeoConvert</a>;
|
||
- <a href="CartConvert.1.html">CartConvert</a> allows the ellipsoid
|
||
to be specified with -e.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.1">Version 1.1</a>
|
||
(released 2010-02-09)
|
||
- FIX BUG (introduced in 2009-03) in EllipticFunction::E(sn,cn,dn).
|
||
- Increase accuracy of scale calculation in TransverseMercator and
|
||
TransverseMercatorExact.
|
||
- Code and documentation changes for consistency with
|
||
<a href="https://arxiv.org/abs/1002.1417">arXiv:1002.1417</a>
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/1.0">Version 1.0</a>
|
||
(released 2010-01-07)
|
||
- Add autoconf configuration files.
|
||
- BUG FIX: Improve initial guess for Newton's method in
|
||
PolarStereographic::Reverse. (Previously this failed to converge
|
||
when the co-latitude exceeded about 130 deg.)
|
||
- Constructors for TransverseMercator, TransverseMercatorExact,
|
||
PolarStereographic, Geocentric, and Geodesic now check for obvious
|
||
problems with their arguments and throw an exception if necessary.
|
||
- Most classes now include inspector functions such as MajorRadius()
|
||
so that you can determine how instances were constructed.
|
||
- Add LambertConformalConic class.
|
||
- Add PolarStereographic::SetScale to allow the
|
||
latitude of true scale to be specified.
|
||
- Add solution and project files for Visual Studio 2008.
|
||
- Add GeographicErr for exceptions.
|
||
- Geoid changes:
|
||
- BUG FIX: fix typo in Geoid::Cache which could cause
|
||
a segmentation fault in some cases when the cached area spanned
|
||
the prime meridian.
|
||
- Include sufficient edge data to allow heights to be returned for
|
||
cached area without disk reads;
|
||
- Add inspector functions to query the extent of the cache.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-11">Version 2009-11</a>
|
||
(released 2009-11-03)
|
||
- Allow specification of "closest UTM zone" in UTMUPS
|
||
and <a href="GeoConvert.1.html">GeoConvert</a> (via -t option).
|
||
- Utilities now complain is there are too many tokens on input lines.
|
||
- Include real-to-real versions of DMS::Decode and
|
||
DMS::Encode.
|
||
- More house-cleaning changes:
|
||
- Ensure that functions which return results through reference
|
||
arguments do not alter the arguments when an exception is thrown.
|
||
- Improve accuracy of MGRS::Forward.
|
||
- Include more information in some error messages.
|
||
- Improve accuracy of inverse hyperbolic functions.
|
||
- Fix the way Math functions handle different precisions.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-10">Version 2009-10</a>
|
||
(released 2009-10-18)
|
||
- Change web site to https://geographiclib.sourceforge.io
|
||
- Several house-cleaning changes:
|
||
- Change from the a flat directory structure to a more easily
|
||
maintained one.
|
||
- Introduce Math class for common mathematical functions (in
|
||
Constants.hpp).
|
||
- Use Math::real as the type for all real quantities. By default this
|
||
is typedef'ed to double; and the library should be installed this
|
||
way.
|
||
- Eliminate const reference members of AzimuthalEquidistant,
|
||
CassiniSoldner and LocalCartesian so that they may be copied.
|
||
- Make several constructors explicit. Disallow some constructors.
|
||
Disallow copy constructor/assignment for Geoid.
|
||
- Document least squares formulas in Geoid.cpp.
|
||
- Use unsigned long long for files positions of geoid files in Geoid.
|
||
- Introduce optional mgrslimits argument in UTMUPS::Forward and
|
||
UTMUPS::Reverse to enforce stricter MGRS limits on eastings and
|
||
northings.
|
||
- Add 64-bit targets in Visual Studio project files.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-09">Version 2009-09</a>
|
||
(released 2009-09-01)
|
||
- Add Geoid and
|
||
<a href="GeoidEval.1.html">GeoidEval</a> utility.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-08">Version 2009-08</a>
|
||
(released 2009-08-14)
|
||
- Add CassiniSoldner class and
|
||
<a href="GeodesicProj.1.html">EquidistantTest</a> utility.
|
||
- Fix bug in Geodesic::Inverse where NaNs were
|
||
sometimes returned.
|
||
- INCOMPATIBLE CHANGE: AzimuthalEquidistant now returns the reciprocal
|
||
of the azimuthal scale instead of the reduced length.
|
||
- Add -n option to <a href="GeoConvert.1.html">GeoConvert</a>.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-07">Version 2009-07</a>
|
||
(released 2009-07-16)
|
||
- Speed up the series inversion code in tmseries.mac and geod.mac.
|
||
- Reference Borkowski in section on \ref geocentric.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-06">Version 2009-06</a>
|
||
(released 2009-06-01)
|
||
- Add routines to decode and encode zone+hemisphere to UTMUPS.
|
||
- Clean up code in Geodesic.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-05">Version 2009-05</a>
|
||
(released 2009-05-01)
|
||
- Improvements to Geodesic:
|
||
- more economical series expansions,
|
||
- return reduced length (as does the
|
||
<a href="GeodSolve.1.html">Geod</a> utility),
|
||
- improved calculation of starting point for inverse method,
|
||
- use reduced length to give derivative for Newton's method.
|
||
- Add AzimuthalEquidistant class.
|
||
- Make Geocentric, TransverseMercator,
|
||
and PolarStereographic classes work with prolate
|
||
ellipsoids.
|
||
- <a href="CartConvert.1.html">CartConvert</a> checks its inputs more
|
||
carefully.
|
||
- Remove reference to defunct Constants.cpp from GeographicLib.vcproj.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-04">Version 2009-04</a>
|
||
(released 2009-04-01)
|
||
- Use compile-time constants to select the order of series in
|
||
TransverseMercator.
|
||
- 2x unroll of Clenshaw summation to avoid data shuffling.
|
||
- Simplification of EllipticFunction::E.
|
||
- Use STATIC_ASSERT for compile-time checking of constants.
|
||
- Improvements to Geodesic:
|
||
- compile-time option to change order of series used,
|
||
- post Maxima code for generating the series,
|
||
- tune the order of series for double,
|
||
- improvements in the selection of starting points for Newton's
|
||
method,
|
||
- accept and return spherical arc lengths,
|
||
- works with both oblate and prolate ellipsoids,
|
||
- add -a, -e, -b options to the <a href="GeodSolve.1.html">Geod</a>
|
||
utility.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-03">Version 2009-03</a>
|
||
(released 2009-03-01)
|
||
- Add Geodesic and the
|
||
<a href="GeodSolve.1.html">Geod</a> utility.
|
||
- Declare when no exceptions are thrown by functions.
|
||
- Minor changes to DMS class.
|
||
- Use invf = 0 to mean a sphere in constructors to some classes.
|
||
- The makefile creates a library and includes an install target.
|
||
- Rename ECEF to Geocentric, ECEFConvert
|
||
to <a href="CartConvert.1.html">CartConvert</a>.
|
||
- Use inline functions to define constant doubles in Constants.hpp.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-02">Version 2009-02</a>
|
||
(released 2009-01-30)
|
||
- Fix documentation of constructors (flattening → inverse
|
||
flattening).
|
||
- Use std versions of math functions.
|
||
- Add ECEF and LocalCartesian classes
|
||
and the ECEFConvert utility.
|
||
- Gather the documentation on the \ref utilities onto one page.
|
||
.
|
||
- <a href="https://geographiclib.sourceforge.io/2009-01">Version 2009-01</a>
|
||
(released 2009-01-12)
|
||
- First proper release of library.
|
||
- More robust TransverseMercatorExact:
|
||
- Introduce \e extendp version of constructor,
|
||
- Test against extended test data,
|
||
- Optimize starting positions for Newton's method,
|
||
- Fix behavior near all singularities,
|
||
- Fix order dependence in C++ start-up code,
|
||
- Improved method of computing scale and convergence.
|
||
- Documentation on transverse Mercator projection.
|
||
- Add MGRS, UTMUPS, etc.
|
||
.
|
||
- Version 2008-09
|
||
- Ad hoc posting of information on the transverse Mercator projection.
|
||
|
||
<center>
|
||
Back to \ref highprec. Up to \ref contents.
|
||
</center>
|
||
**********************************************************************/
|
||
}
|