+
+%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,
+ GeographicLib::Geodesic::Inverse works for anti-podal points.
+ Similarly, GeographicLib::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 GeographicLib::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 g++ 4.4 under Linux, with g++
+4.2 under Mac OS X, and with MS Visual Studio 9 (2008), 10 (2010), 11
+(2012), and 12 (2013) compiled for 32 bit and 64 bit.
+
+Matlab, JavaScript, and Python interfaces are provided to portions of
+%GeographicLib; see \ref other.
+
+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 GeographicLib::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 \e f:
+ - Some classes, specifically GeographicLib::Geodesic,
+ GeographicLib::GeodesicLine, and GeographicLib::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.
+
+
+Back to \ref intro. Forward to \ref start. Up to \ref contents.
+
+
+%GeographicLib has been developed under Linux with the g++ compiler
+(versions 4.0 and later) and under Windows with Visual Studio 2005, 2008,
+and 2010. Earlier versions were tested also under Darwin and Solaris. It
+should compile on a wide range of other systems. First download either
+
+GeographicLib-1.34.tar.gz or
+
+GeographicLib-1.34.zip (or
+
+GeographicLib-1.34-win32.exe or
+
+GeographicLib-1.34-win64.exe for binary installation under 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
+ cmake installed.
+- \ref autoconf. This method works for most Unix-like systems,
+ including Linux and Mac OS X.
+- \ref gnu. This is a simple installation method that works with g++
+ and GNU make on Linux and many Unix platforms.
+- \ref windows. This is a simple installation method that works with
+ Visual Studio 2005, 2008, and 2010 under Windows.
+- \ref windowsbin. Use this installation method if you only need to use
+ the \ref utilities supplied with %GeographicLib. (This method also
+ installs the header files and the library for use by Visual Studio 10.)
+- \ref qt. How to compile %GeographicLib so that it can be used by Qt
+ programs.
+- \ref maintainer. This describes addition tasks of interest only to
+ the maintainers of this code.
+.
+This section documents only how to install the software. 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 maintanence simpler
+- Out-of-source builds: 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-vc9 for Visual Studio 9, 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.
+- The library is installed: After compilation, there is a
+ separate install 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
+cmake 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 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 2.8.4 (which was released on 2011-02-16). (Actually,
+a few earlier versions will also work for non-Windows platforms.)
+
+On other systems, download a binary installer from http://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.
+
+Here are the steps to compile and install %GeographicLib:
+- Unpack the source, running one of \verbatim
+ tar xfpz GeographicLib-1.34.tar.gz
+ unzip -q GeographicLib-1.34.zip \endverbatim
+ then enter the directory created with one of \verbatim
+ cd GeographicLib-1.34 \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 one of \verbatim
+ cmake -G "Visual Studio 10" -D CMAKE_INSTALL_PREFIX=C:/pkg-vc10/GeographicLib-1.34 ..
+ cmake -G "Visual Studio 9 2008" -D CMAKE_INSTALL_PREFIX=C:/pkg-vc9/GeographicLib-1.34 ..
+\endverbatim
+ The definitions of CMAKE_INSTALL_PREFIX are optional (see below). 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 -D (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
+ - COMMON_INSTALL_PATH governs the installation
+ convention. If it is on ON (the Linux default), the installation
+ is to a common directory, e.g., /usr/local. If it is OFF (the
+ Windows default), the installation directory contains the package
+ name, e.g., C:/pkg/GeographicLib-1.34. The installation
+ directories for the documentation, cmake configuration, python and
+ matlab interfaces all depend on the variable with deeper paths
+ relative to CMAKE_INSTALL_PREFIX being used when it's ON:
+ - documentation: OFF: doc/html; ON: share/doc/GeographicLib/html;
+ - cmake configuration: OFF cmake; ON: share/cmake/GeographicLib;
+ - python interface: OFF: python; ON: lib/python/site-packages;
+ - matlab interface: OFF: matlab; ON: libexec/GeographicLib/matlab;
+ .
+ - CMAKE_INSTALL_PREFIX (default: /usr/local
+ on non-Windows systems, C:/Program Files/GeographicLib
+ on Windows systems) specifies where the library will be installed.
+ For windows systems, it is recommended to use a prefix which
+ includes the compiler version, as shown above (and also, possibly,
+ whether this is a 64-bit build, e.g., cmake -G "Visual Studio
+ 10 Win64" -D CMAKE_INSTALL_PREFIX=C:/pkg-vc10-x64/GeographicLib-1.34
+ ..). If you just want to try the library to see if it suits
+ your needs, pick, for example,
+ CMAKE_INSTALL_PREFIX=/tmp/geographic.
+ - GEOGRAPHICLIB_DATA (default:
+ /usr/local/share/GeographicLib for non-Windows systems,
+ C:/Documents and Settings/All Users/Application
+ Data/GeographicLib for Windows systems) specifies the default
+ location for the various datasets for use by GeographicLib::Geoid,
+ GeographicLib::GravityModel, and GeographicLib::MagneticModel.
+ See \ref geoidinst, \ref gravityinst, and \ref magneticinst for more
+ information.
+ - GEOGRAPHICLIB_LIB_TYPE (allowed values: SHARED, STATIC, or
+ BOTH), specifies the types of libraries build. The default is
+ STATIC for Windows and SHARED otherwise. If building %GeographicLib
+ for sytem-wide use, BOTH is recommended, because this provides users
+ with the choice of which library to use.
+ - CMAKE_BUILD_TYPE (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.)
+ - MATLAB_COMPILER (default: OFF). Set this to either
+ "mex" (for Matlab) or "mkoctfile" (for Octave) to specify the
+ compiler to use for the Matlab/Octave interface. See \ref matlab
+ for more information.
+ - GEOGRAPHICLIB_DOCUMENTATION (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.
+ - BUILD_NETGEOGRAPHICLIB (default: OFF). If set to ON,
+ build the managed C++ wrapper library
+ NETGeographicLib. This only makes
+ sense for Windows systems.
+ - GEOGRAPHICLIB_PRECISION specifies the precision to be
+ used for "real" (i.e., floating point) numbers. 1 means float
+ (single precision); 2 (the default) means double; 3 means long
+ double; 4 is reserved for quadruple 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.
+- Build and install the software. In non-IDE environments, run
+ \verbatim
+ make # compile the library and the examples
+ make test # run some tests
+ make install # as root, if CMAKE_INSTALL_PREFIX is a system directory
+\endverbatim
+ Possible additional targets are \verbatim
+ make matlabinterface (only for the Release configuration on Windows)
+ make dist
+ make exampleprograms
+ make netexamples (supported only for Release configuration) \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, 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 both 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
+ CMAKE_INSTALL_PREFIX. (dll dynamic libraries are
+ installed in bin.) For documentation, open in a web browser
+
+ PREFIX/share/doc/GeographicLib/html/index.html, if
+ COMMON_INSTALL_PATH is ON, or
+ PREFIX/doc/index.html, otherwise.
+
+\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-1.34.tar.gz \endverbatim
+ then enter the directory created \verbatim
+ cd GeographicLib-1.34 \endverbatim
+- Create a separate build directory and enter it, for example, \verbatim
+ mkdir BUILD
+ cd BUILD \endverbatim
+- Configure the software, specifing 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
+ prefix. This installation method does not compile
+ the Matlab/Octave interface; however the source for the interface is
+ installed in libexec/GeographicLib/matlab, see \ref matlab of
+ instructions on compiling the interface. For documentation, open
+
+ share/doc/GeographicLib/html/index.html in a web browser.
+
+\section gnu Installation with GNU compiler and Make
+
+This method requires the standard GNU suite of tools, in particular make
+and g++. This builds a static library and the examples.
+
+Here are the steps to compile and install %GeographicLib:
+- Unpack the source, running \verbatim
+ tar xfpz GeographicLib-1.34.tar.gz \endverbatim
+ then enter the directory created \verbatim
+ cd GeographicLib-1.34 \endverbatim
+- Edit \verbatim
+ include/GeographicLib/Config.h \endverbatim
+ If your C++ compiler does not recognize the long double type
+ (unlikely), insert \code
+ #undef HAVE_LONG_DOUBLE \endcode
+ If your machine using big endian ordering, then insert \code
+ #define WORDS_BIGENDIAN 1 \endcode
+- Build and install the software: \verbatim
+ make # compile the library and the examples
+ make install # as root \endverbatim
+ The installation is in directories under /usr/local. You
+ can specify a different installation directory with, for example,
+ \verbatim
+ make PREFIX=/tmp/geographic install \endverbatim
+- The headers, library, and utilities are installed in the
+ include/GeographicLib, lib, and bin directories under
+ PREFIX. This installation method does not compile
+ the Matlab/Octave interface; however the source for the interface is
+ installed in libexec/GeographicLib/matlab, see \ref matlab of
+ instructions on compiling the interface. For documentation, open
+
+ share/doc/GeographicLib/html/index.html in a web browser.
+
+\section windows Installation on Windows
+
+This method requires Visual Studio 2005, 2008, or 2010. This builds a
+static library and the utilities. If you only have Visual Studio 2003,
+use cmake to create the necessary solution file, see \ref cmake. (cmake
+is needed to build the Matlab interface and to run the tests.)
+- Unpack the source, running \verbatim
+ unzip -q GeographicLib-1.34.zip \endverbatim
+- Open GeographicLib-1.34/windows/GeographicLib-vc10.sln in Visual Studio
+ 2010 (for Visual Studio 2005 and 2008, replace -vc10 by -vc8 or -vc9).
+- Pick the build type (e.g., Release), and select "Build Solution".
+- The library and the compiled examples are in the windows/Release.
+- Copy the library windows/Release/GeographicLib.lib and the
+ headers in include/GeographicLib somewhere convenient. The
+ headers should remain in a directory named %GeographicLib. If you
+ expect to use the Matlab/Octave interface, copy matlab/*.m and
+ matlab/*.cpp to a directory in your matlab/octave path, see \ref
+ matlab for instructions on compiling the interface. For documentation,
+ open
+ doc/html/index.html in a web
+ browser.
+
+The Visual Studio 10 solution also contains projects to build
+NETGeographicLib and the C# example project.
+
+\section windowsbin Using a binary installer for 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 2010 (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 either \ref cmake or \ref windows.
+
+Download and run
+
+GeographicLib-1.34-win32.exe or
+
+GeographicLib-1.34-win64.exe:
+ - read the MIT/X11 License agreement,
+ - select whether you want your PATH modified,
+ - select the installation folder, by default
+ C:\\pkg-vc10\\GeographicLib-1.34 or C:\\pkg-vc10-x64\\GeographicLib-1.34,
+ - 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 C:/pkg-vc10/GeographicLib-1.34/bin where the utilities are
+installed. The headers and library are installed in the
+include/GeographicLib and lib folders. With the 64-bit installer, the
+Matlab interface is installed in the matlab folder. Add this to your
+path in Matlab to access this interface. The libraries were built using
+using Visual Studio 10 in release and debug modes. The utilities were
+linked against the release-mode shared library. The Matlab interface
+was compiled with Matlab R2013a 64-bit, however it may work with some
+other 64-bit versions of Matlab.
+NETGeographicLib library dlls (release and
+debug) are included with the binary installers; these are linked against
+the shared library for %GeographicLib.
+
+\section qt Building the library for use with Qt
+
+If Qt is using a standard compiler, then build %GeographicLib with that
+same compiler (and optimization flags) as Qt.
+
+If you are using the mingw compiler on Windows for Qt, then you need to
+build %GeographicLib with mingw. You can accomplish this with cmake
+under cygwin with, for example, \verbatim
+ export PATH="`cygpath -m c:/QtSDK/mingw/bin`:$PATH"
+ mkdir BUILD
+ cd BUILD
+ cmake -G "MinGW Makefiles" -D CMAKE_INSTALL_PREFIX=C:/pkg-mingw/GeographicLib ..
+ mingw32-make
+ mingw32-make install \endverbatim
+If cmake complains that sh mustn't be in your path, invoke cmake with
+\verbatim
+ env PATH="$( echo $PATH | tr : '\n' |
+ while read d; do test -f "$d/sh.exe" || echo -n "$d:"; done |
+ sed 's/:$//' )" \
+ cmake -G "MinGW Makefiles" -D CMAKE_INSTALL_PREFIX=C:/pkg-mingw/GeographicLib ..
+\endverbatim
+If cmake is not available, there is a simple project file that compiles
+the %GeographicLib library only with the Qt compiler: \verbatim
+ cd src
+ qmake GeographicLib.pro # configure the project
+ make # build the library \endverbatim
+The library will be in the src directory (or the src/release or
+src/debug directory under Windows). The headers are in
+include/GeographicLib.
+
+\section maintainer Maintainer tasks
+
+Check the code out of git with \verbatim
+ git clone -b master git://git.code.sf.net/p/geographiclib/code geographiclib
+\endverbatim
+Here the "master" branch is checked out. There are three branches in
+the git repository:
+- master: the main branch for code maintainence. Releases are
+ tagged on this branch as, e.g., v1.34.
+- devel: the development branch; changes made here are merged
+ into master.
+- release: 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 is the \e default branch of the
+ repository (the branch you get if cloning the repository without
+ specifying a branch). This differs from the master 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., r1.34.
+.
+The autoconf configuration script and the formatted man pages are not
+checked into master branch of the repository. In order to create the
+autoconf configuration script, run \verbatim
+ sh autogen.sh \endverbatim
+in the top level directory. Provided you are running on a system with
+doxygen, pod2man, and pod2html installed, then you can create the
+documentation and the man pages by building the system using cmake or
+configure.
+
+In the case of cmake, you then 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-1.34.tar.gz
+ GeographicLib-1.34.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
+NSIS. On Windows, you should
+configure %GeographicLib with PACKAGE_DEBUG_LIBS=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 10 Win64" \
+ -D GEOGRAPHICLIB_LIB_TYPE=BOTH \
+ -D PACKAGE_DEBUG_LIBS=ON \
+ -D MATLAB_COMPILER=mex \
+ -D BUILD_NETGEOGRAPHICLIB=ON \
+ ..
+ cmake --build . --config Debug --target ALL_BUILD
+ cmake --build . --config Release --target ALL_BUILD
+ cmake --build . --config Release --target matlabinterface
+ cmake --build . --config Release --target PACKAGE \endverbatim
+
+With configure, run \verbatim
+ make dist-gzip \endverbatim
+which will create the additional files and packages the results ready
+for distribution as \verbatim
+ geographiclib-1.34.tar.gz \endverbatim
+
+
+Back to \ref intro. Forward to \ref start. Up to \ref contents.
+
+**********************************************************************/
+/**
+\page start Getting started
+
+
+Back to \ref install. Forward to \ref utilities. Up to \ref contents.
+
+
+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 \endcode
+- Include the GeographicLib:: namespace prefix to the %GeographicLib classes,
+ or include \code
+ using namespace GeographicLib; \endcode
+ in your code.
+- Finally compile and link your code. You have two options here.
+ - Use cmake to build your package. If you are familiar with cmake
+ this typically will be far the simplest option.
+ - Set the include paths and linking options "manually".
+- Building your code with cmake. In brief, the necessary steps are:
+ - include in your CMakeLists.txt files \verbatim
+ find_package (GeographicLib 1.34 REQUIRED)
+ include_directories (${GeographicLib_INCLUDE_DIRS})
+ add_definitions (${GeographicLib_DEFINITIONS})
+ add_executable (program source1.cpp source2.cpp)
+ target_link_libraries (program ${GeographicLib_LIBRARIES}) \endverbatim
+ (The add_definitions line is only needed for Windows
+ and can be omitted if you're using cmake version 2.8.11 or later.)
+ - configure your package, e.g., with \verbatim
+ mkdir BUILD
+ cd BUILD
+ cmake -G "Visual Studio 10" \
+ -D CMAKE_PREFIX_PATH=C:/pkg-vc10 \
+ -D CMAKE_PREFIX_PATH=C:/pkg-vc10/testgeographic \
+ .. \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).
+ - 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).
+ .
+ The most import step 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 reverse order) are
+ - under the system paths, i.e., locations such as C:/Program
+ Files and /usr/local);
+ - 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 CMAKE_PREFIX_PATH (illustrated above);
+ - the package directory for %GeographicLib can be overridden with the
+ environment variableGeographicLib_DIR (which is the
+ directory under which %GeographicLib is installed);
+ - finally, if you need to point to a particular build of %GeographicLib,
+ define the cmake variableGeographicLib_DIR, which
+ specifies the directory containing the configuration file
+ geographiclib-config.cmake (for debugging this be the
+ top-level build directory, as opposed to installation
+ directory, for %GeographicLib).
+ .
+ Typically, specifying nothing or CMAKE_PREFIX_PATH
+ suffices. However the two GeographicLib_DIR 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 CMAKE_MODULE_PATH in order for
+ find_package to work. However, this method has not been thoroughly
+ tested.)
+
+ If %GeographicLib is found, then the following cmake variables are set:
+ - GeographicLib_FOUND = 1
+ - GeographicLib_VERSION = 1.34
+ - GeographicLib_INCLUDE_DIRS
+ - GeographicLib_LIBRARIES = one of the following two:
+ - GeographicLib_SHARED_LIBRARIES = %GeographicLib
+ - GeographicLib_STATIC_LIBRARIES = GeographicLib_STATIC
+ - GeographicLib_DEFINITIONS = one of the following two:
+ - GeographicLib_SHARED_DEFINITIONS = -DGEOGRAPHICLIB_SHARED_LIB=1
+ - GeographicLib_STATIC_DEFINITIONS = -DGEOGRAPHICLIB_SHARED_LIB=0
+ - GeographicLib_LIBRARY_DIRS
+ - GeographicLib_BINARY_DIRS
+ .
+ Either of GeographicLib_SHARED_LIBRARIES or
+ GeographicLib_STATIC_LIBRARIES 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 COMPONENTS clause
+ to find_package, e.g.,
+ \verbatim
+ find_package (GeographicLib 1.34 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
+ GeographicLib_LIBRARIES and
+ GeographicLib_DEFINITIONS are set to the shared versions,
+ unless you include \verbatim
+ set (GeographicLib_USE_STATIC_LIBS ON) \endverbatim
+ before the find_package command. You can check whether
+ GeographicLib_LIBRARIES refers to the shared or static
+ library with \verbatim
+ get_target_property(_LIBTYPE ${GeographicLib_LIBRARIES} TYPE) \endverbatim
+ which results in _LIBTYPE being set to
+ SHARED_LIBRARY or STATIC_LIBRARY.
+ 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.)
+- Here are the steps to compile and link your code using %GeographicLib
+ "manually".
+ - Tell the compiler where to find the header files. With g++ and with
+ /usr/local specified as the installation directory,
+ this is accomplished with \verbatim
+ g++ -c -g -O3 -funroll-loops -I/usr/local/include testprogram.cpp
+ \endverbatim
+ With Visual Studio, specify the include directory in the IDE via,
+ e.g.,
+ \verbatim
+ C/C++ -> General -> Additional Include Directories = C:\pkg-vc10\GeographicLib\include
+ \endverbatim
+ - If using the shared (or static) library with Visual Studio, define
+ the macro GEOGRAPHICLIB_SHARED_LIB=1 (or
+ 0), e.g.,
+ \verbatim
+ C/C++ -> Preprocessor -> Preprocessor Definitions = GEOGRAPHICLIB_SHARED_LIB=1
+ \endverbatim
+ This is only needed for Windows systems when both shared and static
+ libraries have been installed. (If you configure your package with
+ cmake, this definition is added automatically.)
+ - Tell the linker the name, Geographic, and location of the
+ library. Using g++ as the linker, you would use \verbatim
+ g++ -g -o testprogram testprogram.o -L/usr/local/lib -lGeographic
+ \endverbatim
+ With Visual Studio, you supply this information in the IDE via,
+ e.g., \verbatim
+ Linker -> Input -> Additional Dependencies = Geographic-i.lib (for shared library)
+ Linker -> Input -> Additional Dependencies = Geographic.lib (for static library)
+ Linker -> General -> Additional Library Directories = C:\pkg-vc10\Geographic\lib
+ \endverbatim
+ Note that the library name is Geographic and not
+ %GeographicLib. For the Debug version of your program on Windows
+ add "_d" to the library, e.g., Geographic_d-i.lib or
+ Geographic_d.lib.
+ - Tell the runtime environment where to find the shared library
+ (assuming you compiled %Geographic as a shared library). With g++,
+ this is accomplished by modifying the link line above to read \verbatim
+ g++ -g -o testprogram testprogram.o -Wl,-rpath=/usr/local/lib \
+ -L/usr/local/lib -lGeographic
+ \endverbatim
+ (There are two other ways to specify the location of shared libraries
+ at runtime: (1) define the environment variable
+ LD_LIBRARY_PATH to be a colon-separated list of
+ directories to search; (2) as root, specify /usr/local/lib as a
+ directory searched by ldconfig(8).) On Windows, you need to ensure
+ that Geographic.dll or Geographic_d.dll is in the same directory as
+ your executable or else include the directory containing the dll in
+ your PATH.
+
+Here is a very simple test code, which uses the GeographicLib::Geodesic
+class:
+\include example-Geodesic-small.cpp
+This example is examples/example-Geodesic-small.cpp. 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 2.8.4)
+
+find_package (GeographicLib 1.34 REQUIRED)
+
+if (NOT MSVC)
+ set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+endif ()
+
+include_directories (${GeographicLib_INCLUDE_DIRS})
+add_definitions (${GeographicLib_DEFINITIONS})
+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 $ ${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 Class List 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:
+ -
+ WGS84, World Geodetic System 1984.
+ -
+ UTM, Universal Transverse Mercator coordinate system.
+ -
+ UPS, Universal Polar Stereographic coordinate system.
+ -
+ MGRS, Military Grid Reference System.
+ -
+ EGM, Earth Gravity Model.
+ -
+ WMM, World Magnetic Model.
+ -
+ IGRF, International Geomagnetic Reference Field.
+
+
+Back to \ref install. Forward to \ref utilities. Up to \ref contents.
+
+Back to \ref start. Forward to \ref organization. Up to \ref contents.
+
+
+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
+ -
+ GeoConvert: convert geographic coordinates using
+ GeographicLib::GeoCoords.
+ -
+ GeodSolve: perform geodesic calculations using
+ GeographicLib::Geodesic and GeographicLib::GeodesicLine.
+ -
+ Planimeter: compute the area of geodesic polygons using
+ GeographicLib::PolygonArea.
+ -
+ TransverseMercatorProj: convert between geographic
+ and transverse Mercator. This is for testing
+ GeographicLib::TransverseMercatorExact and
+ GeographicLib::TransverseMercator.
+ -
+ CartConvert: convert geodetic coordinates to geocentric or
+ local cartesian using GeographicLib::Geocentric and
+ GeographicLib::LocalCartesian.
+ -
+ GeodesicProj: perform projections based on geodesics
+ using GeographicLib::AzimuthalEquidistant, GeographicLib::Gnomonic,
+ and GeographicLib::CassiniSoldner.
+ -
+ ConicProj: perform conic projections using
+ GeographicLib::LambertConformalConic and
+ GeographicLib::AlbersEqualArea.
+ -
+ GeoidEval: look up geoid heights using
+ GeographicLib::Geoid.
+ -
+ Gravity: compute the earth's gravitational field using
+ GeographicLib::GravityModel and GeographicLib::GravityCircle.
+ -
+ MagneticField: compute the earth's magnetic field using
+ GeographicLib::MagneticModel and GeographicLib::MagneticCircle.
+ .
+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 --help option. A brief summary of usage is given
+by invoking the utility with the -h option. The version of the utility
+is given by the --version 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:
+ - GeoConvert
+ - GeodSolve
+ - Planimeter
+ - GeoidEval
+
+
+Back to \ref start. Forward to \ref organization. Up to \ref contents.
+
+Back to \ref utilities. Forward to \ref other. Up to \ref contents.
+
+
+Here is a brief description of the relationship between the various
+components of %GeographicLib. All of these are defined in the
+GeographicLib namespace.
+
+GeographicLib::TransverseMercator, GeographicLib::PolarStereographic,
+GeographicLib::LambertConformalConic, and GeographicLib::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).
+
+GeographicLib::TransverseMercator::UTM and
+GeographicLib::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 GeographicLib::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).
+GeographicLib::AlbersEqualArea::CylindricalEqualArea,
+AzimuthalEqualAreaNorth, and AzimuthalEqualAreaSouth, likewise provide
+special cases of the equal area projection.
+
+GeographicLib::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.
+
+GeographicLib::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.
+
+GeographicLib::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.
+GeoConvert is a simple command line
+utility to provide access to the GeoCoords class.
+
+GeographicLib::TransverseMercatorExact is a drop in replacement for
+TransverseMercator which uses the exact formulas, based on elliptic
+functions, for the projection as given by Lee.
+TransverseMercatorProj is a
+simple command line utility to test to the TransverseMercator and
+TransverseMercatorExact.
+
+GeographicLib::Geodesic and GeographicLib::GeodesicLine perform geodesic
+calculations. The constructor for GeographicLib::Geodesic specifies the
+ellipsoid and the direct and inverse calculations are implemented as
+const member functions. GeographicLib::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 GeographicLib::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. GeodSolve is a simple command
+line utility to perform geodesic calculations.
+GeographicLib::PolygonArea is a class which compute the area of geodesic
+polygons using the Geodesic class and Planimeter is a command line utility for
+the same purpose. GeographicLib::AzimuthalEquidistant,
+GeographicLib::CassiniSoldner, and GeographicLib::Gnomonic are
+projections based on the Geodesic class. GeodesicProj is a command line utility to
+exercise these projections.
+
+GeographicLib::GeodesicExact and GeographicLib::GeodesicLineExact are
+drop in replacements for GeographicLib::Geodesic and
+GeographicLib::GeodesicLine in which the solution is given in terms of
+elliptic integrals (computed by GeographicLib::EllipticFunction).
+These classes should be used if the absolute value of the flattening
+exceeds 0.02. The -E option to GeodSolve
+uses these classes.
+
+GeographicLib::Geocentric and GeographicLib::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. GeographicLib::Geocentric::WGS84 is a
+const static instantiation of Geocentric specific for the WGS84 ellipsoid.
+CartConvert is a simple command line
+utility to provide access to these classes.
+
+GeographicLib::Geoid evaluates geoid heights by interpolation. This is
+provided by the operator() member function.
+GeoidEval 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.
+
+GeographicLib::Ellipsoid is a class which performs latitude
+conversions and returns various properties of the ellipsoid.
+
+GeographicLib::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 Gravity 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
+GeographicLib::GravityModel::Circle to return a
+GeographicLib::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.
+
+GeographicLib::MagneticModel evaluates the earth's magnetic field using
+a particular magnetic model. The field is provided by the operator()
+member function. MagneticField 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
+GeographicLib::MagneticModel::Circle to return a
+GeographicLib::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.
+
+GeographicLib::Constants, GeographicLib::Math, GeographicLib::Utility,
+GeographicLib::DMS, are general utility class which are used
+internally by the library; in addition GeographicLib::EllipticFunction
+is used by GeographicLib::TransverseMercatorExact,
+GeographicLib::Ellipsoid, and GeographicLib::GeodesicExact, and
+GeographicLib::GeodesicLineExact; GeographicLib::Accumulator is used
+by GeographicLib::PolygonArea, and GeographicLib::SphericalEngine,
+GeographicLib::CircularEngine, GeographicLib::SphericalHarmonic,
+GeographicLib::SphericalHarmonic1, and
+GeographicLib::SphericalHarmonic2 facilitate the summation of
+spherical harmonic series which is needed by and
+GeographicLib::MagneticModel and GeographicLib::MagneticCircle. One
+important definition is GeographicLib::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.
+
+In general, the constructors for the classes in %GeographicLib check
+their arguments and throw GeographicLib::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 not 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 GeographicLib::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. (Similary "nan" is the equivalent invalid Geohash.) 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
+ - GeographicLib::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.
+ - GeographicLib::Geoid, GeographicLib::GravityModel, and
+ GeographicLib::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.
+ - GeographicLib::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 WORDS_BIGENDIAN macro (which sets the compile-time constant
+ GeographicLib::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.34. There's
+also a macro GEOGRAPHICLIB_VERSION_STRING which expands to, e.g.,
+"1.34"; this macro has been defined since version 1.9.
+
+
+Back to \ref utilities. Forward to \ref other. Up to \ref contents.
+
+**********************************************************************/
+/**
+\page other Implementations in other languages
+
+
+Back to \ref organization. Forward to \ref geoid. Up to \ref contents.
+
+
+Implementations of subsets of %GeographicLib are available in other languages
+- \ref c-fortran
+- \ref java.
+- \ref javascript.
+- \ref python.
+- \ref matlab.
+- \ref maxima.
+- \ref dotnet.
+
+\section c-fortran C and Fortran implementation
+
+The directories legacy/C and legacy/Fortran
+contain implementations of GeographicLib::Geodesic,
+GeographicLib::GeodesicLine, and GeographicLib::PolygonArea in C and
+Fortran respectively. These are intended for use in old codes written
+in these languages and should work any reasonably modern compiler.
+These implementations are entirely self-contained and do not depend on
+the rest of %GeographicLib. Sample main programs to solve the direct
+and inverse geodesic problems and to compute polygonal areas are
+provided.
+
+For documentation, see
+ - C library for geodesics,
+ - Fortran library for geodesics.
+
+\section java Java implementation
+
+The directory java contains implementations of
+GeographicLib::Geodesic, GeographicLib::GeodesicLine, and
+GeographicLib::PolygonArea in Java. This implementation is entirely
+self-contained and does not depend on the rest of %GeographicLib.
+Sample main programs to solve the direct and inverse geodesic problems
+and to compute polygonal areas are provided.
+
+For documentation, see
+ - Java library for geodesics.
+
+\section javascript JavaScript implementation
+
+The directory doc/scripts/GeographicLib contains the classes
+- GeographicLib::Math
+- GeographicLib::Accumulator
+- GeographicLib::Geodesic
+- GeographicLib::GeodesicLine
+- GeographicLib::PolygonArea
+- GeographicLib::DMS
+.
+translated into JavaScript. See Interface.js for a simple JavaScript
+interface to these routines (documented near the top of the file).
+Examples of using this interface are
+- a geodesic calculator showing
+ the solution of direct and inverse geodesic problem, finding
+ intermediate points on a geodesic line, and computing the area of a
+ geodesic polygon.
+- displaying geodesics in Google
+ Maps which shows the geodesic, the geodesic circle, and various
+ geodesic envelopes.
+.
+These examples include a "stripped" version of the JavaScript code, \code
+ \endcode
+which loads faster.
+
+\section python Python implementation
+
+A python implementation of the geodesic routines from GeographicLib
+are provided in the python/geographiclib directory (which is installed
+as PREFIX/lib/python/site-packages/geographiclib, if
+COMMON_INSTALL_PATH is ON, and as PREFIX/python/geographiclib,
+otherwise). This contains implementations of the classes
+- GeographicLib::Math
+- GeographicLib::Accumulator
+- GeographicLib::Geodesic
+- GeographicLib::GeodesicLine
+- GeographicLib::PolygonArea
+.
+You can also download the python interface independent of the rest of
+%GeographicLib from
+-
+ http://pypi.python.org/pypi/geographiclib
+.
+and then unpack the .tar.gz or .zip file.
+
+You can "install" these routines, so that they are in python's default
+path with, for example \verbatim
+ cd geographiclib-1.16
+ python setup.py install
+\endverbatim
+(this will require root privileges). Or else you can set the path
+within python using \code
+>>> import sys
+>>> sys.path.append("/usr/local/lib/python/site-packages")
+\endcode
+
+An example of using this interface is \code
+>>> from geographiclib.geodesic import Geodesic
+>>> # The geodesic inverse problem
+... Geodesic.WGS84.Inverse(-41.32, 174.81, 40.96, -5.50)
+>>> # The geodesic direct problem
+... Geodesic.WGS84.Direct(40.6, -73.8, 45, 10000e3)
+>>> # How to obtain several points along a geodesic
+... line = Geodesic.WGS84.Line(40.6, -73.8, 45)
+>>> line.Position( 5000e3)
+>>> line.Position(10000e3)
+>>> # Computing the area of a geodesic polygon
+... def p(lat,lon): return {'lat': lat, 'lon': lon}
+...
+>>> Geodesic.WGS84.Area([p(0, 0), p(0, 90), p(90, 0)])
+>>> # Introductory help
+... help(Geodesic)
+\endcode
+
+Another illustrative exercise is finding the point midway between JFK
+Airport to Singapore Changi Airport
+\code
+from geographiclib.geodesic import Geodesic
+
+# Coordinates of airports
+lat1, lon1 = 40.640, -73.779 # JFK
+lat2, lon2 = 1.359, 103.989 # SIN
+
+# Compute path from 1 to 2
+g = Geodesic.WGS84.Inverse(lat1, lon1, lat2, lon2)
+
+# Compute midpoint starting at 1
+h = Geodesic.WGS84.Direct(lat1, lon1, g['azi1'], g['s12']/2)
+print(h['lat2'], h['lon2']);
+\endcode
+
+(Note: The initial version of setup.py was provided by Andrew MacIntyre
+of the Australian Communications and Media Authority.)
+
+\section matlab Matlab and Octave implementations
+
+The matlab directory contains
+ - Native Matlab implementations of the geodesic routines. To use
+ these, start Matlab or Octave and run one of (for example) \verbatim
+ addpath /usr/local/libexec/GeographicLib/matlab
+ addpath 'C:/pkg-vc10-x64/GeographicLib-1.34/libexec/GeographicLib/matlab'
+ \endverbatim
+ The available functions are:
+ - geoddoc: briefly descibe the routines
+ - geodreckon: solve the direct geodesic problem
+ - geoddistance: solve the inverse geodesic problem
+ - geodarea: compute the area of ellipsoidal polygons
+ .
+ Use the help function to get documentation, e.g., \code
+ help geoddistance \endcode
+ to obtain documentation. These functions are also available as a
+ standalone package from
+
+ Matlab File Exchange using the link
+ -
+ http://www.mathworks.com/matlabcentral/fileexchange/39108
+ - Native Matlab implementations of projections which are related to
+ geodesics. These are
+ - geodproj: briefly descibe the routines
+ - eqdazim_fwd, eqdazim_inv: azimuthal equidistant
+ - cassini_fwd, cassini_inv: Cassini-Soldner
+ - tranmerc_fwd, tranmerc_inv: transverse Mercator
+ - gnomonic_fwd, gnomonic_inv: ellipsoidal gnomonic
+ - utm_fwd, utm_inv: universal transverse Mercator
+ .
+ These functions are also available as a package from
+
+ Matlab File Exchange using the link
+ -
+ http://www.mathworks.com/matlabcentral/fileexchange/39366
+ .
+ (This requires that the previous package also be installed.)
+ - Interface code so that some %GeographicLib classes can be accessed
+ from Matlab or Octave. The rest of this section describes how to
+ compile and use these interfaces.
+
+There are two ways of compiling the interface code: (1) using cmake and
+(2) invoking the compiler from Matlab.
+ - Using cmake: Before running cmake, configure MATLAB on
+ Windows to use the same compiler that you're going to use for compiling
+ %GeographicLib. For example \verbatim
+ mex.bat -setup
+
+ Please choose your compiler for building MEX-files:
+ Would you like mex to locate installed compilers [y]/n? y
+ Select a compiler:
+ [1] Microsoft Visual C++ 2012 in C:\Program Files (x86)\Microsoft Visual Studio 11.0
+ [2] Microsoft Visual C++ 2010 in C:\Program Files (x86)\Microsoft Visual Studio 10.0
+
+ [0] None
+
+ Compiler: 2
+ etc. \endverbatim
+ (This will require that mex.bat is in your PATH. With Linux, use
+ mex -setup.) Then configure cmake with, for example
+ \verbatim
+ cmake -G "Visual Studio 10" -D MATLAB_COMPILER=mex ..
+ cmake --build . --config Release --target matlabinterface \endverbatim
+ (Note that only the Release configuration is supported for Matlab.)
+ If you are running a 64-bit version of Matlab, be sure to select a
+ 64-bit generator with cmake, e.g., "Visual Studio 10 Win64". Finally
+ compile %GeographicLib with Visual Studio. (The binary installer for
+ 64-bit Windows includes the compiled interface built with Visual
+ Studio 10 and Matlab R2013a 64-bit).
+ On Linux systems, you can compile the interface for use with octave
+ instead by using \verbatim
+ cmake -D MATLAB_COMPILER=mkoctfile ..
+ make matlabinterface \endverbatim
+ - Invoking the compiler from Matlab or Octave: Start Matlab or
+ Octave and run, e.g., \code
+ mex -setup
+ cd 'C:/pkg-vc10-x64/GeographicLib-1.34/matlab'
+ help geographiclibinterface
+ geographiclibinterface('C:/pkg-vc10/GeographicLib-1.34');
+ addpath(pwd);
+ \endcode
+ The first command allows you to select the compiler to use (which
+ should be the same as that used to compile %GeographicLib).
+
+To use the interface routines for %GeographicLib, run one of (for
+example) \verbatim
+ addpath /usr/local/libexec/GeographicLib/matlab
+ addpath 'C:/pkg-vc10-x64/GeographicLib-1.34/libexec/GeographicLib/matlab'
+\endverbatim
+in Octave or Matlab. The available functions are:
+ - geodesicdirect: solve direct geodesic problem
+ (see GeographicLib::Geodesic::Direct)
+ - geodesicinverse: solve inverse geodesic problem
+ (see GeographicLib::Geodesic::Inverse)
+ - geodesicline: compute points along a geodesic
+ (see GeographicLib::GeodesicLine::Position)
+ - polygonarea: compute area of a geodesic polygon
+ (see GeographicLib::PolygonArea)
+ - utmupsforward: convert geographic coordinates to UTM/UPS
+ (see GeographicLib::UTMUPS::Forward)
+ - utmupsreverse: convert UTM/UPS coordinates to geographic
+ (see GeographicLib::UTMUPS::Reverse)
+ - mgrsforward: convert UTM/UPS coordinates to MGRS
+ (see GeographicLib::MGRS::Forward)
+ - mgrsreverse: convert MGRS coordinates to UTM/UPS
+ (see GeographicLib::MGRS::Reverse)
+ - geoidheight: compute geoid height
+ (see GeographicLib::Geoid::operator()())
+ - geocentricforward: convert geographic coordinates to geocentric
+ (see GeographicLib::Geocentric::Forward)
+ - geocentricreverse: convert geocentric coordinates to geographic
+ (see GeographicLib::Geocentric::Reverse)
+ - localcartesianforward: convert geographic coordinates to local cartesian
+ (see GeographicLib::LocalCartesian::Forward)
+ - localcartesianreverse: convert local cartesian coordinates to geographic
+ (see GeographicLib::LocalCartesian::Reverse)
+ .
+These routines just offer a simple interface to the corresponding C++
+class. Use the help function to get documentation, e.g., \code
+ help geodesicdirect \endcode
+Unfortunately, the help function does not work for compiled functions in
+Octave; in this case, just list the .m file, e.g., \code
+ type geodesicdirect \endcode
+Other useful functions, e.g., to convert from geographic
+coordinates to MGRS can easily be written with Matlab code.
+
+Note that geoidheight, when compiled with Visual Studio 2008 causes
+Matlab to crash. (The problem does not occur with Visual Studio 2005 or
+Visual Studio 2010.)
+
+\section maxima Maxima routines
+
+Maxima is a free computer algebra system which can be downloaded from
+http://maxima.sf.net. Maxima was used to generate the series used by
+GeographicLib::TransverseMercator (
+tmseries.mac) and GeographicLib::Geodesic (
+geod.mac) and to generate accurate data for testing
+( tm.mac and
+geodesic.mac). The latter uses Maxima's bigfloat arithmetic
+together with series extended to high order or solutions in terms of
+elliptic integrals ( ellint.mac). These files
+contain brief instructions on how to use them.
+
+\section dotnet .NET wrapper
+
+This is a comprehensive wrapper library, written and maintained by Scott
+Heiman, which exposes all of the functionality of %GeographicLib to the
+.NET family of languages. For documentation, see
+ - NETGeographicLib .NET wrapper library.
+
+
+Back to \ref organization. Forward to \ref geoid. Up to \ref contents.
+
+Back to \ref other. Forward to \ref gravity. Up to \ref contents.
+
+
+The gravitational equipotential surface approximately coinciding with
+mean sea level is called the geoid. The GeographicLib::Geoid class and
+the GeoidEval 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:
+- EGM84:
+ http://earth-info.nga.mil/GandG/wgs84/gravitymod/wgs84_180/wgs84_180.html
+- EGM96:
+ http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/egm96.html
+- EGM2008:
+ http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008
+.
+GeographicLib::Geoid offers a uniform way to handle all 3 geoids at a
+variety of grid resolutions. (In contrast, the software tools that NGA
+offers are different for each geoid, 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.)
+
+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 GeographicLib::GravityModel class calculates geoid heights using the
+underlying gravity model. This is slower then GeographicLib::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:
+
+The "size" column is the size of the uncompressed data and it also
+gives the memory requirements for caching the entire dataset using the
+GeographicLib::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 one of
+\verbatim
+ C:/Documents and Settings/All Users/Application Data/GeographicLib
+ 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. GeographicLib::Geoid and
+GeoidEval uses a compile time default to
+locate the datasets. This is
+- /usr/local/share/GeographicLib/geoids, for non-Windows systems
+- C:/Documents and Settings/All Users/Application Data/GeographicLib/geoids,
+ for Windows systems
+.
+consistent with the examples above. This may be overridden at run-time
+by defining the GEOID_PATH or the GEOGRAPHICLIB_DATA environment variables;
+see GeographicLib::Geoid::DefaultGeoidPath() for details. Finally, the
+path may be set using the optional second argument to the
+GeographicLib::Geoid constructor or with the "-d" flag to
+GeoidEval. Supplying the "-h" flag to
+GeoidEval 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 GeographicLib::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
+ here;
+- 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
+ libnetpbm
+ 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 http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/egm96.html
+ # 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
+GeographicLib::Geoid::Description, GeographicLib::Geoid::DateTime,
+GeographicLib::Geoid::MaxError, and GeographicLib::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
+GDAL. Neither of these files is read
+by GeographicLib::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 GeoidEval 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 -co BLOCKXSIZE=256 -co BLOCKYSIZE=256 \
+ egmyy-g.pgm egmyy-g.tif
+\endverbatim
+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.
+
+\section geoidinterp Interpolating the geoid data
+
+GeographicLib::Geoid evaluates the geoid height using bilinear or cubic
+interpolation. The gradient of the geoid height is obtained by
+differentiating the interpolated height and referencing the result to
+distance on the WGS84 ellipsoid.
+
+WARNING: Although GeographicLib::Geoid computes the gradient of
+the geoid height, this is subject to large quantization errors as a
+result of the way that the geoid data is stored. This is particularly
+acute for fine grids, at high latitudes, and for the easterly gradient.
+If you need to compute the direction of the acceleration due to gravity
+accurately, you should use GeographicLib::GravityModel::Gravity.
+
+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,
+Multi-dimensional least-squares polynomial curve fitting, CACM 2, 29-30
+(1959). This algorithm is not part of GeographicLib::Geoid; instead it is
+implemented as
+Maxima
+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.
+
+
Interpolation and quantization errors for geoid heights
+
+
name
+
geoid
+
grid
+
bilinear error
+
cubic error
+
+
max
rms
+
max
rms
+
+
egm84-30
EGM84
30'
+
1.546 m
70 mm
+
0.274 m
14 mm
+
+
egm84-15
EGM84
15'
+
0.413 m
18 mm
+
0.021 m
1.2 mm
+
+
egm96-15
EGM96
15'
+
1.152 m
40 mm
+
0.169 m
7.0 mm
+
+
egm96-5
EGM96
5'
+
0.140 m
4.6 mm
+
0.0032 m
0.7 mm
+
+
egm2008-5
EGM2008
5'
+
0.478 m
12 mm
+
0.294 m
4.5 mm
+
+
egm2008-2_5
EGM2008
2.5'
+
0.135 m
3.2 mm
+
0.031 m
0.8 mm
+
+
egm2008-1
EGM2008
1'
+
0.025 m
0.8 mm
+
0.0022 m
0.7 mm
+
+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 GeographicLib::Geoid uses are quantized to
+3 mm. If, instead, GeographicLib::Geoid were to use data files without
+such quantization artifacts, the overall error would be reduced but
+only modestly as shown in the following table, where only the
+changed rows are included and where the changed entries are given in
+bold:
+
+
Interpolation (only!) errors for geoid heights
+
+
name
+
geoid
+
grid
+
bilinear error
+
cubic error
+
+
max
rms
+
max
rms
+
+
egm96-5
EGM96
5'
+
0.140 m
4.6 mm
+
0.0026 m
0.1 mm
+
+
egm2008-2_5
EGM2008
2.5'
+
0.135 m
3.2 mm
+
0.031 m
0.4 mm
+
+
egm2008-1
EGM2008
1'
+
0.025 m
0.6 mm
+
0.0010 m
0.011 mm
+
+
+\section geoidcache Caching the geoid data
+
+A simple way of calling Geoid is as follows
+\code
+ #include
+ #include
+ ...
+ 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
+GeographicLib::Geoid::CacheArea or the entire dataset with
+GeographicLib::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.
+ - GeographicLib::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
+ -
+ GeoidHeights.dat.gz
+ .
+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 6 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−6
+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 SAVE statement needed to be added to
+subroutine latf, in order for the program to compile
+correctly with a stack-based compiler. Similarly the EGM96 code
+requires a SAVE statement in subroutine
+legfdn.
+
+
+Back to \ref other. Forward to \ref gravity. Up to \ref contents.
+
+Back to \ref geoid. Forward to \ref magnetic. Up to \ref contents.
+
+
+%GeographicLib can compute the earth's gravitational field with an
+earth gravity model using the GeographicLib::GravityModel and
+GeographicLib::GravityCircle classes and with the
+Gravity 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.
+
+The supported models are
+ - egm84, the
+
+ Earth Gravity Model 1984, which includes terms up to degree 180.
+ - egm96, the
+
+ Earth Gravity Model 1996, which includes terms up to degree 360.
+ - egm2008, the
+
+ Earth Gravity Model 2008, which includes terms up to degree 2190.
+ - wgs84, the
+
+ WGS84 Reference Ellipsoid. This is just reproduces the normal
+ gravitational field for the reference ellipsoid. Usually
+ GeographicLib::NormalGravity::WGS84 should be used instead.
+
+See
+ - W. A. Heiskanen and H. Moritz, Physical Geodesy (Freeman, San
+ Francisco, 1967).
+ .
+for more information.
+
+Acknowledgment: 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.
+
+Go to
+ - \ref gravityinst
+ - \ref gravityformat
+ - \ref gravitynga
+ - \ref gravitygeoid
+ - \ref gravityatmos
+ - \ref gravityparallel
+
+\section gravityinst Installing the gravity models
+
+These gravity models are available for download:
+
+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 one of
+\verbatim
+ C:/Documents and Settings/All Users/Application Data/GeographicLib
+ 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. GeographicLib::GravityModel and
+Gravity uses a compile time default to
+locate the datasets. This is
+- /usr/local/share/GeographicLib/gravity, for non-Windows systems
+- C:/Documents and Settings/All Users/Application Data/GeographicLib/gravity,
+ for Windows systems
+.
+consistent with the examples above. This may be overridden at run-time
+by defining the GRAVITY_PATH or the GEOGRAPHICLIB_DATA environment
+variables; see GeographicLib::GravityModel::DefaultGravityPath() for
+details. Finally, the path may be set using the optional second
+argument to the GeographicLib::GravityModel constructor or with the "-d"
+flag to
+Gravity. Supplying the "-h" flag to
+Gravity 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 GeographicLib::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.
+
+GeographicLib::GravityModel only pays attention to the following
+keywords
+ - keywords that affect the field calculation, namely:
+ - ModelRadius (required), the normalizing radius for the model
+ in meters.
+ - ReferenceRadius (required), the major radius \e a for the
+ reference ellipsoid meters.
+ - ModelMass (required), the mass constant \e GM for the model
+ in meters3/seconds2.
+ - ReferenceMass (required), the mass constant \e GM for the
+ reference ellipsoid in meters3/seconds2.
+ - AngularVelocity (required), the angular velocity ω for
+ the model \e and the reference ellipsoid in rad
+ seconds−1.
+ - Flattening, the flattening of the reference ellipsoid; this
+ can be given a fraction, e.g., 1/298.257223563. One of
+ Flattening and DynamicalFormFactor is required.
+ - DynamicalFormFactor, the dynamical form factor
+ J2 for the reference ellipsoid. One of
+ Flattening and DynamicalFormFactor is required.
+ - HeightOffset (default 0), the constant height offset
+ (meters) added to obtain the geoid height.
+ - CorrectionMultiplier (default 1), the multiplier for the
+ "zeta-to-N" correction terms for the geoid height to convert them
+ to meters.
+ - Normalization (default full), the normalization used for the
+ associated Legendre functions (full or schmidt).
+ - ID (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 ModelRadius, ModelMass, and
+ AngularVelocity apply to the gravity model, while
+ ReferenceRadius, ReferenceMass, AngularVelocity,
+ and either Flattening or DynamicalFormFactor
+ characterize the reference ellipsoid. AngularVelocity
+ (because it can be measured precisely) is the same for the gravity
+ model and the reference ellipsoid. ModelRadius is merely a
+ scaling parameter for the gravity model and there's no requirement
+ that it be close to the major radius of the earth (although that's
+ typically how it is chosen). ModelMass and
+ ReferenceMass 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:
+ - Name, the name of the model.
+ - Description, a more descriptive name of the model.
+ - ReleaseDate, when the model was created.
+ - keywords that are examined to verify that their values are valid:
+ - ByteOrder (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.
+ - \e C\e nm, 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
+ C00,
+ C10,
+ C20,
+ C30,
+ C11,
+ C21,
+ C31,
+ C22,
+ C32,
+ C33.
+ - \e S\e nm, 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
+ S11,
+ S21,
+ S31,
+ S22,
+ S32,
+ S33.
+ .
+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
+# http://geographiclib.sf.net/html/gravity.html#gravityformat
+Name egm2008
+Publisher National Geospatial Intelligence Agency
+Description Earth Gravity Model 2008
+URL http://earth-info.nga.mil/GandG/wgs84/gravitymod/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
+
+\section gravitynga Comments on the NGA harmonic synthesis code
+
+GeographicLib::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
+ SAVE statement in subroutine latf.
+ -# Because the model and references masses for egm2008 differ (by about
+ 1 part in 109), 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 = U0 outward by about 5 mm.
+ Note too that the reference ellipsoid is no longer a level surface of
+ the effective normal potential.
+ -# Subroutine radgrav 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−7 arcsec at
+ \e h = 400 km).
+ -# There are several expressions which will return inaccurate results
+ due to cancellation. For example, subroutine grs
+ computes the flattening using \e f = 1 - sqrt(1 -
+ e2). Much better is to use \e f =
+ e2/(1 + sqrt(1 - e2)). The
+ expressions for \e q and \e q' in grs and
+ radgrav 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
+GeographicLib::GravityModel corrects issues 3--5. On issue 2,
+GeographicLib::GravityModel neglects the 1/\e r term in \e T in
+GeographicLib::GravityModel::GeoidHeight and
+GeographicLib::GravityModel::SphericalAnomaly in order to produce
+results which match NGA's for these quantities. On the other hand,
+GeographicLib::GravityModel::Disturbance and
+GeographicLib::GravityModel::T do 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 GeographicLib::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., GeographicLib::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 = U0 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
+
+There is no such thing as "The" EGM96 geoid: Subtle points on the use of
+a global geopotential model, IGeS Bulletin No. 8, International
+Geoid Service, Milan, Italy, pp. 17--28 (1998).
+
+GeographicLib::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 ab initio). 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 GeographicLib::GravityModel::SphericalAnomaly uses the
+same approximation for compatibility. In this approximation, the
+gravity disturbance delta = grad \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 delta 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. delta is expressed in \e
+spherical coordinates as \e deltax, \e deltay, \e deltaz where, for
+example, \e deltaz is the \e radial component of delta (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 - 2T/\e R, where \e R
+ distance to the center of the earth;
+ - northerly component of the deflection of the vertical, \e xi = -
+ deltay/\e gamma, where \e gamma is the magnitude of the normal
+ gravity;
+ - easterly component of the deflection of the vertical, \e eta = -
+ deltax/\e gamma.
+ .
+GeographicLib::NormalGravity computes the normal gravity accurately and
+avoids issue 3 of \ref gravitynga. Thus while
+GeographicLib::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
+
+TR8350.2, table 3.1)
+ - \e a = 6378137 m
+ - \e f = 1/298.257223563
+ - ω = 7292115 × 10−11 rad
+ s−1
+ - \e GM = 3986004.418 × 108 m3
+ s−2.
+ .
+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πG/\e
+g) \e A = 8.552 × 10−11 \e A m2/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−6 m
+s−2, 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 GeographicLib::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
+ OpenMP; 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
+.gtx
+file. On an 8-processor Intel 2.66 GHz machine using OpenMP
+(-DHAVE_OPENMP=1), it takes about 40 minutes of elapsed time to compute
+the geoid height for EGM2008 on a 1' gride. (Without these
+optimizations, the computation would have taken about 200 days!)
+\include GeoidToGTX.cpp
+
+This example, examples/GeoidToGTX.cpp, is built if cmake
+is configured with -D GEOGRAPHICLIB_EXAMPLES=ON. cmake
+will add in support for OpenMP, if it is available.
+
+
+Back to \ref geoid. Forward to \ref magnetic. Up to \ref contents.
+
+**********************************************************************/
+/**
+\page magnetic Magnetic models
+
+
+Back to \ref gravity. Forward to \ref geodesic. Up to \ref contents.
+
+
+%GeographicLib can compute the earth's magnetic field by a magnetic
+model using the GeographicLib::MagneticModel and
+GeographicLib::MagneticCircle classes and with the
+MagneticField 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 GeographicLib::MagneticModel are advised to read the
+"Health
+Warning" 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
+ - wmm2010, the
+ World
+ Magnetic Model 2010, which approximates the main magnetic field
+ for the period 2010--2015.
+ - igrf11, the
+ International
+ Geomagnetic Reference Field (11th generation), which approximates
+ the main magnetic field for the period 1900--2015.
+ - emm2010, the
+ Enhanced
+ Magnetic Model 2010, which approximates the main and crustal
+ magnetic fields for the period 2010--2015.
+
+Go to
+ - \ref magneticinst
+ - \ref magneticformat
+
+\section magneticinst Installing the magnetic field models
+
+These magnetic models are available for download:
+
+The "size" column is the size of the uncompressed data.
+
+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 # to install wmm2010, igrf11, emm2010
+ 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 one of
+\verbatim
+ C:/Documents and Settings/All Users/Application Data/GeographicLib
+ 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 wmm2010.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. GeographicLib::MagneticModel and
+MagneticField uses a compile time
+default to locate the datasets. This is
+- /usr/local/share/GeographicLib/magnetic, for non-Windows systems
+- C:/Documents and Settings/All Users/Application Data/GeographicLib/magnetic,
+ for Windows systems
+.
+consistent with the examples above. This may be overridden at run-time
+by defining the MAGNETIC_PATH or the GEOGRAPHIC_DATA environment
+variables; see GeographicLib::MagneticModel::DefaultMagneticPath() for
+details. Finally, the path may be set using the optional second
+argument to the GeographicLib::MagneticModel constructor or with the
+"-d" flag to MagneticField.
+Supplying the "-h" flag to
+MagneticField 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 GeographicLib::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 "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.
+
+GeographicLib::MagneticModel only pays attention to the following
+keywords
+ - keywords that affect the field calculation, namely:
+ - Radius (required), the normalizing radius of the model in
+ meters.
+ - NumModels (default 1), the number of models. WMM2010
+ consists of a single model giving the magnetic field and its time
+ variation at 2010. IGRF11 consists of 23 models for 1900 thru 2010
+ at 5 year intervals. The time variation is given only for the last
+ model to allow extrapolation beyond 2010. For dates prior to 2010,
+ linear interpolation is used.
+ - Epoch (required), the time origin (in fractional years) for
+ the first model.
+ - DeltaEpoch (default 1), the interval between models in years
+ (only relevant for NumModels > 1).
+ - Normalization (default schmidt), the normalization used for
+ the associated Legendre functions (schmidt or full).
+ - ID (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:
+ - Name, the name of the model.
+ - Description, a more descriptive name of the model.
+ - ReleaseDate, when the model was created.
+ - MinTime, the minimum date at which the model should be used.
+ - MaxTime, the maximum date at which the model should be used.
+ - MinHeight, the minimum height above the ellipsoid for which
+ the model should be used.
+ - MaxHeight, the maximum height above the ellipsoid for which
+ the model should be used.
+ .
+ GeographicLib::MagneticModel does not enforce the restrictions
+ implied by last four quantities. However,
+ MagneticField issues a warning if
+ these limits are exceeded.
+ - keywords that are examined to verify that their values are valid:
+ - Type (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.
+ - ByteOrder (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.
+ - \e C\e nm, 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
+ C00,
+ C10,
+ C20,
+ C30,
+ C11,
+ C21,
+ C31,
+ C22,
+ C32,
+ C33.
+ - \e S\e nm, 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
+ S11,
+ S21,
+ S31,
+ S22,
+ S32,
+ S33.
+ .
+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
+# http://geographiclib.sf.net/html/magnetic.html#magneticformat
+Name igrf11
+Description International Geomagnetic Reference Field 11th Generation
+URL http://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
+
+
+Back to \ref gravity. Forward to \ref geodesic. Up to \ref contents.
+
+**********************************************************************/
+/**
+\page geodesic Geodesics on an ellipsoid of revolution
+
+
+Back to \ref magnetic. Forward to \ref triaxial. Up to \ref contents.
+
+
+GeographicLib::Geodesic and GeographicLib::GeodesicLine provide accurate
+solutions to the direct and inverse geodesic problems. The
+GeodSolve utility provides an interface
+to these classes. GeographicLib::AzimuthalEquidistant implements the
+azimuthal equidistant projection in terms of geodesics.
+GeographicLib::CassiniSoldner implements a transverse cylindrical
+equidistant projection in terms of geodesics. The GeodesicProj utility provides an
+interface to these projections.
+
+The algorithms used by GeographicLib::Geodesic and
+GeographicLib::GeodesicLine are based on a Taylor expansion of the
+geodesic integrals valid when the flattening \e f is small.
+GeographicLib::GeodesicExact and GeographicLib::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
+GeographicLib::Geodesic and GeographicLib::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,
+ The calculation
+ of longitude and latitude from geodesic measurements (1825),
+ Astron. Nachr. 331(8), 852-861 (2010);
+ translated by C. F. F. Karney and R. E. Deakin. Preprint:
+ arXiv:0908.1824.
+ - F. R. Helmert,
+
+ Mathematical and Physical Theories of Higher Geodesy, Part 1 (1880),
+ 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).
+ - C. F. F. Karney,
+
+ Algorithms for geodesics,
+ J. Geodesy 87(1), 43--55 (Jan. 2013);
+ DOI:
+ 10.1007/s00190-012-0578-z;
+ addenda:
+ geod-addenda.html;
+ resource page:
+ geod.html.
+ - A collection of some papers on geodesics is available at
+ http://geographiclib.sourceforge.net/geodesic-papers/biblio.html
+ - The wikipedia page,
+
+ Geodesics on an ellipsoid.
+
+\section testgeod Test data for geodesics
+
+A test set a geodesics is available at
+ -
+ GeodTest.dat.gz
+ .
+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
+ -
+ GeodTest-short.dat.gz
+
+Each line of the test set gives 10 space delimited numbers
+ - latitude for point 1, \e lat1 (degrees, exact)
+ - longitude for point 1, \e lon1 (degrees, always 0)
+ - azimuth for point 1, \e azi1 (clockwise from north in degrees, exact)
+ - latitude for point 2, \e lat2 (degrees, accurate to
+ 10−18 deg)
+ - longitude for point 2, \e lon2 (degrees, accurate to
+ 10−18 deg)
+ - azimuth for point 2, \e azi2 (degrees, accurate to
+ 10−18 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−18 deg)
+ - reduced length of the geodesic, \e m12 (meters, accurate to 0.1 pm)
+ - the area under the geodesic, \e S12 (m2, accurate to
+ 1 mm2)
+ .
+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−12 deg and \e s12
+is a multiple of 0.1 μm in [0 m, 20003931.4586254 m]. This results \e
+lon2 in [0°, 180°] and \e azi2 in [0°, 180°].
+
+The direct calculation uses an expansion of the geodesic equations
+accurate to f30 (approximately 1 part in 1050)
+and is computed with with
+Maxima'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 GeodSolve
+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 geodesic.mac (this depends on
+ ellint.mac and uses the series computed by
+ geod.mac). This solve both the direct and
+inverse geodesic problems and offers the ability to solve the problems
+either using series expansions (similar to GeographicLib::Geodesic) or
+in terms of elliptic integrals (similar to
+GeographicLib::GeodesicExact).
+
+\section geodseries Expansions for geodesics
+
+We give here the series expansions for the various geodesic integrals
+valid to order f10. 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 any order up to 8. (If using long doubles, with a
+64-bit fraction, the default order is 7.) The series expanded to
+order f30 are given in
+geodseries30.html.
+
+In the formulas below ^ indicates exponentiation (\e f^3 =
+f3) 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,
+geod.mac.
+
+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 \f$
+
+The formula for distance is
+\f[
+ \frac sb = I_1(\sigma)
+\f]
+where
+\f[
+\begin{aligned}
+ I_1(\sigma) &= A_1\bigl(\sigma + B_1(\sigma)\bigr) \\
+ B_1(\sigma) &= \sum_{j=1} C_{1j} \sin 2j\sigma
+\end{aligned}
+\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{aligned}
+ \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{aligned}
+\f]
+where
+\f[
+\begin{aligned}
+ 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{aligned}
+\f]
+\verbatim
+A2 = (1 + 1/4 * eps^2
+ + 9/64 * eps^4
+ + 25/256 * eps^6
+ + 1225/16384 * eps^8
+ + 3969/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{aligned}
+ I_3(\sigma) &= A_3\bigl(\sigma + B_3(\sigma)\bigr) \\
+ B_3(\sigma) &= \sum_{j=1} C_{3j} \sin 2j\sigma
+\end{aligned}
+\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
+Algorithms for geodesics 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
+
+GeographicLib::GeodesicExact and GeographicLib::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,
+ Geodesics
+ on an ellipsoid of revolution,
+ Feb. 2011; preprint
+ arxiv:1102.1215v1.
+ .
+It is most convenient to use the form derived for a prolate ellipsoid in
+Appendix D. For an oblate ellipsoid this results in elliptic integrals
+with an imaginary modulus. However, the integrals themselves are real
+and the algorithms used to compute the elliptic integrals handles the
+case of an imaginary modulus using real arithmetic.
+
+The key relations used by %GeographicLib are
+\f[
+ \begin{aligned}
+ \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{aligned}
+\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{aligned}
+ 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{aligned}
+\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
+http://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 http://dlmf.nist.gov/19.7.E8.)
+
+Nominally, GeographicLib::GeodesicExact and
+GeographicLib::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 \e b/\e a ∈ [0.01, 100] or \e f ∈ [-99, 0.99].
+Note that GeographicLib::GeodesicExact still uses a series expansion for
+the area \e S12. However the series is taken out to 30th order and
+gives accurate results for \e b/\e a ∈ [1/2, 2]; the accuracy is
+about 8 decimal digits for \e b/\e a ∈ [1/4, 4]. Additional work
+planned for this aspect of the geodesic problem:
+- formulate the area integral \e S12 in terms of elliptic integrals;
+- generate accurate test geodesics for highly eccentric ellipsoids so
+ that the roundoff errors can be quantified.
+
+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{aligned}
+\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{aligned}
+\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{aligned}
+\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{aligned}
+\f]
+where
+\f[
+\begin{aligned}
+\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{aligned}
+\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, y) \f$ are given by
+\f[
+\begin{aligned}
+ 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{aligned}
+\f]
+\f[
+\begin{aligned}
+ 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{aligned}
+\f]
+The distance along the meridian can be expressed variously as
+\f[
+\begin{aligned}
+ 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{aligned}
+\f]
+\f[
+\begin{aligned}
+ 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{aligned}
+\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
+http://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 http://dlmf.nist.gov/22.2 and
+http://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
+ http://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,
+
+ Geometric Geodesy, Part I, 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{aligned}
+ \psi' &= \sinh^{-1} \tan \phi', \\
+ \psi &= \sinh^{-1} \tan \phi - e \tanh^{-1}(e \sin\phi).
+\end{aligned}
+\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{aligned}
+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{aligned}
+\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{aligned}
+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{aligned}
+\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).
+
+
+
+
Maximum distance that can be used in various methods for
+computing short geodesics while keeping the errors within prescribed
+bounds
+
+
method
+
distance metric
+
azimuth metric
+
+
1 mm error
+
1 nm error
+
1 mm error
+
1 nm error
+
+
Bowring (original)
+
87 km
+
870 m
+
35 km
+
350 m
+
+
Bowring (improved)
+
180 km
+
1.8 km
+
58 km
+
580 m
+
+
Bowring (truncated)
+
52 km
+
520 m
+
52 km
+
520 m
+
+
Bowring (using \f$\beta\f$)
+
380 km
+
24 km
+
60 km
+
600 m
+
+
Bessel's aux. sphere
+
42 km
+
420 m
+
1.7 km
+
1.7 m
+
+
+
+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.
+
+
+Back to \ref magnetic. Forward to \ref triaxial. Up to \ref contents.
+
+**********************************************************************/
+/**
+\page triaxial Geodesics on a triaxial ellipsoid
+
+
+Back to \ref geodesic. Forward to \ref transversemercator. Up to
+\ref contents.
+
+
+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,
+
+ Geodesics on a triaxial ellipsoid.
+
+Go to
+ - \ref triaxial-coords
+ - \ref triaxial-jacobi
+ - \ref triaxial-survey
+ - \ref triaxial-stab
+ - \ref triaxial-inverse
+
+NOTES
+ -# 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, Waters
+ (2011).
+ -# 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 Mathematical
+ Methods of Classical Mechanics (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.
+ -# 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
+ here.
+ -# I do not give full citations of the papers here. You can find these
+ in the
+
+ Online Geodesic Bibliography; 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
+
+ Oliver Knill and Michael Teodorescu. 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,
+
+ Algorithms for geodesics,
+ J. Geodesy 87(1), 43--55 (Jan. 2013);
+ DOI:
+ 10.1007/s00190-012-0578-z;
+ addenda:
+ geod-addenda.html.
+
+\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{aligned}
+ x &= a \cos\phi' \cos\lambda', \\
+ y &= b \cos\phi' \sin\lambda', \\
+ z &= c \sin\phi'.
+\end{aligned}
+\f]
+Jacobi employed the \e ellipsoidal latitude and longitude \f$(\beta,
+\omega)\f$ defined by
+\f[
+\begin{aligned}
+ 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{aligned}
+\f]
+Grid lines of constant \f$\beta\f$ and \f$\omega\f$ are given in Fig. 1.
+
+
+
+Fig. 1
+
\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.
+
+Inter-conversions between these three 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
+
+letter he wrote to his friend and neighbor Bessel:
+
The day before yesterday, I reduced to quadrature the
+problem of geodesic lines on an ellipsoid with three unequal
+axes. 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.
+
+
+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
+ here
+(with minor changes in notation):
+\f[
+\begin{aligned}
+\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{aligned}
+\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$a\rightarrow b\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)
+§§583--584 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{aligned}
+\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{aligned}
+\f]
+An alternative expression for the distance is
+\f[
+\begin{aligned}
+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{aligned}
+\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.
+
+
+
+Fig. 2
+
\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$.
+
+
+
+Fig. 3
+
\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 = 0^\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.
+
+
+
+Fig. 4
+
\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 = 0^\circ\f$.
+
+
+
+Fig. 5
+
\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 = 0^\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 = 45^\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.
+
+
+
+Fig. 6
+
\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 = 45^\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 geodesic 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 DLMF, §28.29.
+Using the notation of §3 of
+ Algorithms for
+geodesics, 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
+ Sinclair
+ (2003).
+ - 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
+ Algorithms for
+geodesics).
+ - 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$.
+ - If both points lie on the equator \f$\beta = 0\f$, then determine the
+ reduced length \f$m_{12}\f$ for the geodesic which is the shorter
+ path along the ellipse \f$z = 0\f$. 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$.
+ - \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$.
+
+
+Back to \ref geodesic. Forward to \ref transversemercator. Up to
+\ref contents.
+
+Back to \ref triaxial. Forward to \ref geocentric. Up to \ref contents.
+
+
+GeographicLib::TransverseMercator and
+GeographicLib::TransverseMercatorExact provide accurate implementations
+of the transverse Mercator projection. The
+ TransverseMercatorProj
+utility provides an interface to these classes.
+
+Go to
+ - \ref testmerc
+ - \ref tmseries
+ - \ref tmfigures
+
+References
+ - L. Krüger,
+ Konforme
+ Abbildung des Erdellipsoids in der Ebene (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,
+ Conformal
+ Projections Based On Jacobian Elliptic Functions.
+ - C. F. F. Karney,
+
+ Transverse Mercator with an accuracy of a few nanometers,
+ J. Geodesy 85(8), 475--485 (Aug. 2011);
+ preprint:
+ arXiv:1002.1417;
+ resource page:
+ tm.html.
+ .
+The algorithm for GeographicLib::TransverseMercator is based on
+Krüger (1912); that for GeographicLib::TransverseMercatorExact is
+based on Lee (1976).
+
+See tm-grid.kmz, 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
+ -
+ TMcoords.dat.gz
+ .
+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−18 deg)
+ - scale (accurate to 10−20)
+ .
+The latitude and longitude are all multiples of 10−12
+deg and should be regarded as exact, except that longitude =
+82.63627282416406551 should be interpreted as exactly 90 (1 - \e e)
+degrees. These results are computed using Lee's formulas with
+Maxima'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,
+tm.mac and ellint.mac,
+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 tm.mac 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 = 90° (1 − \e e)
+ with lat ≥ 0°;
+ - 25000 entries randomly distributed in lat in [−89°,
+ 0°], lon in [90° (1 − \e e), 90°];
+ - 1000 entries randomly distributed on lat in [−89°, 0°],
+ lon = 90°;
+ - 1000 entries randomly distributed on lat in [−89°, 0°],
+ lon = 90° (1 − \e e);
+ - 1000 entries close to lat = 0°, lon = 90° (lat < 0°, lon
+ ≤ 90°);
+ - 1000 entries close to lat = 0°, lon = 90° (1 − \e e)
+ (lat < 0°, lon ≤ 90° (1 − \e e));
+ .
+(a total of 287000 entries). The entries for lat < 0° and
+lon in [90° (1 − \e e), 90°] use the "extended"
+domain for the transverse Mercator projection explained in Sec. 5 of
+arXiv:1002.1417. 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, GeographicLib::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 n30 are
+given in tmseries30.html.
+
+In the formulas below ^ indicates exponentiation (\e n^3 = \e n*\e n*\e
+n) 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 double literals.
+
+\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 tmseries.mac (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,
+
+ Transverse Mercator with an accuracy of a few nanometers,
+ J. Geodesy 85(8), 475--485 (Aug. 2011);
+ preprint:
+ arXiv:1002.1417;
+ resource page:
+ tm.html.
+
+\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
+ tm-figs.pdf. 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(e2),
+ 0 ≤ \e v ≤ K(1 − e2)
+ .
+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).
+
+
+Back to \ref triaxial. Forward to \ref geocentric. Up to \ref contents.
+
+Back to \ref transversemercator. Forward to \ref old. Up to \ref contents.
+
+
+The implementation of GeographicLib::Geocentric::Reverse is adapted from
+ - H. Vermeille,
+
+ Direct transformation from geocentric coordinates to geodetic
+ coordinates, 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,
+ Geodesics
+ on an ellipsoid of revolution,
+ Feb. 2011; preprint
+ arxiv:1102.1215v1.
+
+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.
+ - t3 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 u/\e r. It's then just a matter of picking the one that computes
+ the geodetic result which minimizes |\e h| 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 +
+ w2) − \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 +
+ w2) + \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 − e2) / sqrt(1 −
+e2 sin2\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 |\e h0| < 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 e2 (= 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
+- errh = |\e h1 − \e h0| / max(1, \e h0 / \e a)
+- for \e h0 > 0, errout = \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
+ errin = hypot(\e x1 − \e x0, \e y1 − \e
+ y0, \e z1 − \e z0).
+.
+We then find errh < 8 nm, errout < 4 nm,
+and errin < 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 near 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,
+ Transformation
+of geocentric to geodetic coordinates without approximations,
+Astrophys. Space Sci. 139, 1--4 (1987)
+( erratum)
+and T. Fukushima,
+ Fast transform from
+geocentric to geodetic coordinates, 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.
+
+
+Back to \ref transversemercator. Forward to \ref old. Up to \ref contents.
+
+
+**********************************************************************/
+/**
+\page old Old versions
+
+
+Back to \ref geocentric. Up to \ref contents.
+
+
+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
+
+http://sourceforge.net/projects/geographiclib/files/distrib/.
+Older versions are in
+
+http://sourceforge.net/projects/geographiclib/files/distrib/archive/.
+
+The corresponding documentation for these versions is obtained by
+clicking on the “Version m.nn” links below. Some of
+the links in the documentaion 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 “rm.nn” in the the "release" branch
+of the git repository for %GeographicLib.
+
+ - Version 1.34
+ (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 librarys with -D
+ GEOGRAPHICLIB_LIB_TYPE=BOTH;
+ - 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 GeographicLib::OSGB::CentralScale().
+ - Add Arc routines to python interface.
+ - The Geod utility has been removed; the same functionality lives on
+ with GeodSolve (introduced in
+ version 1.30).
+
+ - Version 1.33
+ (released 2013-10-08)
+ - Add NETGeographic .NET wrapper library
+ (courtesy of Scott Heiman).
+ - Make inspector functions in GeographicLib::Ellipsoid const.
+ - Add Accumulator.cpp to instantiate GeographicLib::Accumulator.
+ - Defer some of the initialization of GeographicLib::OSGB to when it
+ is first called.
+ - Fix bug in autoconf builds under MacOS.
+
+ - Version 1.32
+ (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.
+
+ - Version 1.31
+ (released 2013-07-01)
+ - Changes breaking binary compatibility (source compatibility is
+ maintained):
+ - overloaded versions of GeographicLib::DMS::Encode,
+ GeographicLib::EllipticFunction::EllipticFunction, and
+ GeographicLib::GeoCoords::DMSRepresentation, have been eliminated
+ by the use of optional arguments;
+ - correct the declaration of first arg to
+ GeographicLib::UTMUPS::DecodeEPSG.
+ - FIX BUG in GeographicLib::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 \ref java 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 GeographicLib::PolygonArea::AddEdge and
+ GeographicLib::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
+ GeographicLib::TransverseMercatorExact was wrong at a pole.
+ - Improve efficiency of GeographicLib::MGRS::Forward by avoiding the
+ calculation of the latitude if possible (adapting an idea of Craig
+ Rollins).
+ - Fixes to the way the Matlab interface routines are built (thanks to
+ Phil Miller and Chris F.).
+
+ - Version 1.30
+ (released 2013-02-27)
+ - Changes to geodesic routines:
+ - FIX BUG in fail-safe mechanisms in GeographicLib::Geodesic::Inverse;
+ - the command line utility Geod is now called
+ GeodSolve;
+ - allow addition of polygon edges in GeographicLib::PolygonArea;
+ - add full Maxima implementation of geodesic algorithms.
+
+ - Version 1.29
+ (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".
+
+ - Version 1.28
+ (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.
+
+ - Version 1.27
+ (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 |f| < 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 GeographicLib::DMS::Decode double rounding BUG.
+ - On MacOSX platforms with the cmake configuration, universal
+ binaries are built.
+
+ - Version 1.26
+ (released 2012-10-22)
+ - Replace the series used for geodesic areas by one with better
+ convergence (this only makes an appreciable difference if
+ |f| > 1/150).
+
+ - Version 1.25
+ (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;
+ - GeographicLib::Geodesic::Inverse now converges for any value of \e f;
+ - add GeographicLib::GeodesicExact and
+ GeographicLib::GeodesicLineExact which are formulated in terms
+ of elliptic integrals and thus yield accurate results even for
+ very eccentric ellipsoids.
+ - the -E option to Geod invokes these
+ exact classes.
+ - Add functionality to GeographicLib::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 GeographicLib::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.
+
+ - Version 1.24
+ (released 2012-09-22)
+ - Allow the specification of the hemisphere in UTM coordinates in
+ order to provide continuity across the equator:
+ - add GeographicLib::UTMUPS::Transfer;
+ - add GeographicLib::GeoCoords::UTMUPSRepresentation(bool, int) and
+ GeographicLib::GeoCoords::AltUTMUPSRepresentation(bool, int);
+ - use the hemisphere letter in, e.g.,
+ GeoConvert -u -z 31N.
+ - Add GeographicLib::UTMUPS::DecodeEPSG and
+ GeographicLib::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.
+
+ - Version 1.23
+ (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 GeographicLib::Math::AngNormalize and
+ GeographicLib::Math::AngNormalize2; the allowed range for longitudes
+ and azimuths widened to [−540°, 540°).
+ - GeographicLib::DMS::Decode understands more unicode symbols.
+ - GeographicLib::Geohash uses geohash code "nan" to stand for not a
+ number.
+ - Add GeographicLib::Ellipsoid::NormalCurvatureRadius.
+ - Various fixes in GeographicLib::LambertConformalConic,
+ GeographicLib::TransverseMercator,
+ GeographicLib::PolarStereographic, and GeographicLib::Ellipsoid to
+ handle reverse projections of points near infinity.
+ - Fix programming blunder in GeographicLib::LambertConformalConic::Forward
+ (incorrect results were returned if the tangent latitude was
+ negative).
+
+ - Version 1.22
+ (released 2012-05-27)
+ - Add GeographicLib::Geohash and GeographicLib::Ellipsoid classes.
+ - FIX BUG in GeographicLib::AlbersEqualArea for very prolate
+ ellipsoids (b2 > 2 a2).
+ - 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.
+
+ - Version 1.21
+ (released 2012-04-25)
+ - Support colon-separated DMS output:
+ - GeographicLib::DMS::Encode and
+ GeographicLib::GeoCoords::DMSRepresentation generalized;
+ - GeoConvert and
+ Geod now accept a -: option.
+ - GeoidEval 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 GeographicLib::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.
+
+ - Version 1.20
+ (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 GeographicLib::SphericalEngine to deal with aggessive iterator
+ checking by Visual Studio.
+ - Fix transcription BUG is Geodesic.js.
+
+ - Version 1.19
+ (released 2012-03-13)
+ - Slight improvement in GeographicLib::Geodesic::Inverse for very
+ short lines.
+ - Fix argument checking tests in GeographicLib::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.
+
+ - Version 1.18
+ (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.
+
+ - Version 1.17
+ (released 2012-01-21)
+ - Work around optimization BUG in GeographicLib::Geodesic::Inverse
+ with g++ version 4.4.0 (mingw).
+ - Fix BUG in argument checking with GeographicLib::OSGB::GridReference.
+ - Fix missing include file in GeographicLib::SphericalHarmonic2.
+ - Add simple examples of usage for each class.
+ - Add internal documentation to the cmake configuration files.
+
+ - Version 1.16
+ (released 2011-12-07)
+ - Add calculation of the earth's gravitational field:
+ - add GeographicLib::NormalGravity GeographicLib::GravityModel and
+ GeographicLib::GravityCircle classes;
+ - add command line utility
+ Gravity;
+ - add \ref gravity;
+ - add GeographicLib::Constants::WGS84_GM(),
+ GeographicLib::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,
+ GeoidEval,
+ Gravity, and
+ MagneticField, look at the
+ environment variable GEOGRAPHICLIB_DATA to locate the data.
+ - Spherical harmonic software changes:
+ - capitalize enums GeographicLib::SphericalHarmonic::FULL and
+ GeographicLib::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 GeographicLib::SphericalEngine::RootTable;
+ - avoid overflow for high degree models.
+ - Magnetic software fixes:
+ - fix documentation BUG in GeographicLib::MagneticModel::Circle;
+ - make GeographicLib::MagneticModel constructor explicit;
+ - provide default GeographicLib::MagneticCircle constructor;
+ - add additional inspector functions to
+ GeographicLib::MagneticCircle;
+ - add -c option to MagneticField;
+ - default height to zero in
+ MagneticField.
+
+ - Version 1.15
+ (released 2011-11-08)
+ - Add calculation of the earth's magnetic field:
+ - add GeographicLib::MagneticModel and GeographicLib::MagneticCircle
+ classes;
+ - add command line utility
+ MagneticField;
+ - add \ref magnetic;
+ - add \ref magneticinst;
+ - add \ref magneticformat;
+ - add classes GeographicLib::SphericalEngine,
+ GeographicLib::CircularEngine, GeographicLib::SphericalHarmonic,
+ GeographicLib::SphericalHarmonic1, and
+ GeographicLib::SphericalHarmonic2. which sum spherical harmonic
+ series.
+ - Add GeographicLib::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.
+
+ - Version 1.14
+ (released 2011-09-30)
+ - Ensure that geographiclib-config.cmake is relocatable.
+ - Allow more unicode symbols to be used in GeographicLib::DMS::Decode.
+ - Modify GeoidEval 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
+ http://pypi.python.org/pypi/geographiclib
+ - Supply a minimal Qt qmake project file for library
+ src/Geographic.pro.
+
+ - Version 1.13
+ (released 2011-08-13)
+ - Changes to I/O:
+ - allow : (colon) to be used as a DMS separator in
+ GeographicLib::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
+ GeographicLib::DMS and GeographicLib::GeoCoords functions to make
+ longitude precede latitude;
+ - GeoConvert now has a -w option to
+ make longitude precede latitude on input and output;
+ - include a JavaScript version of GeographicLib::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 GeographicLib::Math and GeographicLib::Accumulator in their own
+ header files.
+ - Remove unused "fast" GeographicLib::Accumulator method.
+ - Reorganize the \ref 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.
+
+ - Version 1.12
+ (released 2011-07-21)
+ - Change license to MIT/X11.
+ - Add GeographicLib::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.
+
+ - Version 1.11
+ (released 2011-06-27)
+ - Changes to Planimeter:
+ - add -l flag to Planimeter for polyline
+ calculations;
+ - trim precision of area to 3 decimal places;
+ - FIX BUG with pole crossing edges (due to compiler optimization).
+ - Geod 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 GeographicLib::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).
+
+ - Version 1.10
+ (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.
+
+ - Version 1.9
+ (released 2011-05-28)
+ - FIX BUG in area returned by
+ Planimeter 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 GeographicLib::DMS.
+ - Move GeographicLib::Accumulator class from Planimeter.cpp to
+ Constants.hpp.
+ - Add GeographicLib::Math::sq.
+ - 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
+ GeodesicProj and TransverseMercatorTest as
+ TransverseMercatorProj.
+ - Add ConicProj.
+ - Reverse the initial sense of the -s option for
+ Planimeter.
+ - Migrate source from subversion to
+
+ git.
+
+ - Version 1.8
+ (released 2011-02-22)
+ - Optionally return rotation matrix from GeographicLib::Geocentric and
+ GeographicLib::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 Planimeter.
+ - Add 64-bit targets for Visual Studio 2010.
+ - Use templates for defining math functions and some constants.
+ - GeographicLib::Geoid updates
+ - Add GeographicLib::Geoid::DefaultGeoidPath and
+ GeographicLib::Geoid::DefaultGeoidName;
+ - GeoidEval uses environment variable
+ GEOID_NAME as the default geoid;
+ - Add --msltohae and --haetomsl as
+ GeoidEval options (and don't
+ document the single hyphen versions).
+ - Remove documentation that duplicates papers on transverse Mercator
+ and geodesics.
+
+ - Version 1.7
+ (released 2010-12-21)
+ - FIX BUG in scale returned by GeographicLib::LambertConformalConic::Reverse.
+ - Add GeographicLib::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.
+
+ - Version 1.6
+ (released 2010-11-23)
+ - FIX BUG introduced in GeographicLib::Geoid in version 1.5 (found by
+ Dave Edwards).
+
+ - Version 1.5
+ (released 2010-11-19)
+ - Improve area calculations for small polygons.
+ - Add -s and -r flags to Planimeter.
+ - Improve the accuracy of GeographicLib::LambertConformalConic using
+ divided differences.
+ - FIX BUG in meridian convergence returned by
+ LambertConformalConic::Forward.
+ - Add optional threadsafe parameter to GeographicLib::Geoid
+ constructor. WARNING: This changes may break binary compatibility
+ with previous versions of %GeographicLib. However, the library is
+ source compatible.
+ - Add GeographicLib::OSGB.
+ - Matlab and Octave interfaces to GeographicLib::UTMUPS,
+ GeographicLib::MGRS, GeographicLib::Geoid, GeographicLib::Geodesic
+ provided.
+ - Minor changes
+ - explicitly turn on optimization in Visual Studio 2008 projects;
+ - add missing dependencies in some Makefiles;
+ - move pi() and degree() from GeographicLib::Constants to
+ GeographicLib::Math;
+ - introduce GeographicLib::Math::extended type to aid testing;
+ - add GeographicLib::Math::epi() and GeographicLib::Math::edegree().
+ - fixes to compile under cygwin;
+ - tweak expression used to find latitude from conformal latitude.
+
+ - Version 1.4
+ (released 2010-09-12)
+ - Changes to GeographicLib::Geodesic and GeographicLib::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 Geod.
+ .
+ WARNING: 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 Planimeter utility for
+ computing the areas of geodesic polygons.
+ - Improve iterative solution of GeographicLib::Gnomonic::Reverse.
+ - Add GeographicLib::Geoid::ConvertHeight.
+ - Add -msltohae, -haetomsl, and -z options to
+ GeoidEval.
+ - 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.
+
+ - Version 1.3
+ (released 2010-07-21)
+ - Add GeographicLib::Gnomonic, the ellipsoid generalization of the
+ gnomonic projection.
+ - Add -g and -e options to
+ EquidistantTest.
+ - Use fixed-point notation for output from
+ CartConvert,
+ EquidistantTest,
+ TransverseMercatorTest.
+ - PolarStereographic:
+ - Improved conversion to conformal coordinates;
+ - Fix bug with scale at opposite pole;
+ - Complain if latitude out of range in SetScale.
+ - Add GeographicLib::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.
+
+ - Version 1.2
+ (released 2010-05-21)
+ - FIX BUGS in GeographicLib::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 GeographicLib::CassiniSoldner,
+ - add GeographicLib::GeodesicLine::Scale,
+ GeographicLib::GeodesicLine::EquatorialAzimuth, and
+ GeographicLib::GeodesicLine::EquatorialArc;
+ - break friend connection between CassiniSoldner and Geodesic.
+ - Add GeographicLib::DMS::DecodeAngle and
+ GeographicLib::DMS::DecodeAzimuth. Extend
+ GeographicLib::DMS::Decode and GeographicLib::DMS::Encode to deal
+ with distances.
+ - Code and documentation changes in GeographicLib::Geodesic and
+ GeographicLib::Geocentric for consistency with
+ the forthcoming paper on geodesics.
+ - Increase order of series using in GeographicLib::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 GeographicLib::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;
+ - GeoConvert -z accepts zone or
+ zone+hemisphere;
+ - GeoidEval accepts any of the input
+ formats used by GeoConvert;
+ - CartConvert allows the ellipsoid
+ to be specified with -e.
+
+ - Version 1.1
+ (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
+ arXiv:1002.1417
+
+ - Version 1.0
+ (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 GeographicLib::LambertConformalConic class.
+ - Add GeographicLib::PolarStereographic::SetScale to allow the
+ latitude of true scale to be specified.
+ - Add solution and project files for Visual Studio 2008.
+ - Add GeographicLib::GeographicErr for exceptions.
+ - GeographicLib::Geoid changes:
+ - BUG FIX: fix typo in GeographicLib::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.
+
+ - Version 2009-11
+ (released 2009-11-03)
+ - Allow specification of "closest UTM zone" in GeographicLib::UTMUPS
+ and GeoConvert (via -t option).
+ - Utilities now complain is there are too many tokens on input lines.
+ - Include real-to-real versions of GeographicLib::DMS::Decode and
+ GeographicLib::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 GeographicLib::MGRS::Forward.
+ - Include more information in some error messages.
+ - Improve accuracy of inverse hyperbolic functions.
+ - Fix the way GeographicLib::Math functions handle different precisions.
+
+ - Version 2009-10
+ (released 2009-10-18)
+ - Change web site to http://geographiclib.sourceforge.net
+ - 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.
+
+ - Version 2009-09
+ (released 2009-09-01)
+ - Add GeographicLib::Geoid and
+ GeoidEval utility.
+
+ - Version 2009-08
+ (released 2009-08-14)
+ - Add GeographicLib::CassiniSoldner class and
+ EquidistantTest utility.
+ - Fix bug in GeographicLib::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 GeoConvert.
+
+ - Version 2009-07
+ (released 2009-07-16)
+ - Speed up the series inversion code in tmseries.mac and geod.mac.
+ - Reference Borkowski in section on \ref geocentric.
+
+ - Version 2009-06
+ (released 2009-06-01)
+ - Add routines to decode and encode zone+hemisphere to GeographicLib::UTMUPS.
+ - Clean up code in GeographicLib::Geodesic.
+
+ - Version 2009-05
+ (released 2009-05-01)
+ - Improvements to GeographicLib::Geodesic:
+ - more economical series expansions,
+ - return reduced length (as does the
+ Geod utility),
+ - improved calculation of starting point for inverse method,
+ - use reduced length to give derivative for Newton's method.
+ - Add GeographicLib::AzimuthalEquidistant class.
+ - Make GeographicLib::Geocentric, GeographicLib::TransverseMercator,
+ and GeographicLib::PolarStereographic classes work with prolate
+ ellipsoids.
+ - CartConvert checks its inputs more
+ carefully.
+ - Remove reference to defunct Constants.cpp from GeographicLib.vcproj.
+
+ - Version 2009-04
+ (released 2009-04-01)
+ - Use compile-time constants to select the order of series in
+ GeographicLib::TransverseMercator.
+ - 2x unroll of Clenshaw summation to avoid data shuffling.
+ - Simplification of GeographicLib::EllipticFunction::E.
+ - Use STATIC_ASSERT for compile-time checking of constants.
+ - Improvements to GeographicLib::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 Geod
+ utility.
+
+ - Version 2009-03
+ (released 2009-03-01)
+ - Add GeographicLib::Geodesic and the
+ Geod utility.
+ - Declare when no exceptions are thrown by functions.
+ - Minor changes to GeographicLib::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 GeographicLib::ECEF to GeographicLib::Geocentric, ECEFConvert
+ to CartConvert.
+ - Use inline functions to define constant doubles in Constants.hpp.
+
+ - Version 2009-02
+ (released 2009-01-30)
+ - Fix documentation of constructors (flattening -> inverse
+ flattening).
+ - Use std versions of math functions.
+ - Add GeographicLib::ECEF and GeographicLib::LocalCartesian classes
+ and the ECEFConvert utility.
+ - Gather the documentation on the \ref utilities onto one page.
+
+ - Version 2009-01
+ (released 2009-01-12)
+ - First proper release of library.
+ - More robust GeographicLib::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 GeographicLib::MGRS, GeographicLib::UTMUPS, etc.
+
+ - Version 2008-09
+ - Ad hoc posting of information on the transverse Mercator projection.
+
+
+Back to \ref geocentric. Up to \ref contents.
+
+**********************************************************************/
diff --git a/gtsam/3rdparty/GeographicLib/doc/Makefile.am b/gtsam/3rdparty/GeographicLib/doc/Makefile.am
new file mode 100644
index 000000000..84c8ccc87
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/Makefile.am
@@ -0,0 +1,160 @@
+EXTRAFILES = $(srcdir)/tmseries30.html $(srcdir)/geodseries30.html
+
+FIGURES = $(srcdir)/gauss-krueger-graticule.png \
+ $(srcdir)/thompson-tm-graticule.png \
+ $(srcdir)/gauss-krueger-convergence-scale.png \
+ $(srcdir)/gauss-schreiber-graticule-a.png \
+ $(srcdir)/gauss-krueger-graticule-a.png \
+ $(srcdir)/thompson-tm-graticule-a.png \
+ $(srcdir)/gauss-krueger-error.png \
+ $(srcdir)/meridian-measures.png
+
+SCRIPTDRIVERS = \
+ $(srcdir)/scripts/geod-calc.html \
+ $(srcdir)/scripts/geod-google.html \
+ $(srcdir)/scripts/geod-google-instructions.html
+
+JSSCRIPTS = \
+ $(srcdir)/scripts/GeographicLib/Math.js \
+ $(srcdir)/scripts/GeographicLib/Geodesic.js \
+ $(srcdir)/scripts/GeographicLib/GeodesicLine.js \
+ $(srcdir)/scripts/GeographicLib/PolygonArea.js \
+ $(srcdir)/scripts/GeographicLib/DMS.js \
+ $(srcdir)/scripts/GeographicLib/Interface.js
+
+HPPFILES = \
+ $(top_srcdir)/include/GeographicLib/Accumulator.hpp \
+ $(top_srcdir)/include/GeographicLib/AlbersEqualArea.hpp \
+ $(top_srcdir)/include/GeographicLib/AzimuthalEquidistant.hpp \
+ $(top_srcdir)/include/GeographicLib/CassiniSoldner.hpp \
+ $(top_srcdir)/include/GeographicLib/Constants.hpp \
+ $(top_srcdir)/include/GeographicLib/DMS.hpp \
+ $(top_srcdir)/include/GeographicLib/Ellipsoid.hpp \
+ $(top_srcdir)/include/GeographicLib/EllipticFunction.hpp \
+ $(top_srcdir)/include/GeographicLib/Geocentric.hpp \
+ $(top_srcdir)/include/GeographicLib/GeoCoords.hpp \
+ $(top_srcdir)/include/GeographicLib/Geodesic.hpp \
+ $(top_srcdir)/include/GeographicLib/GeodesicExact.hpp \
+ $(top_srcdir)/include/GeographicLib/GeodesicLine.hpp \
+ $(top_srcdir)/include/GeographicLib/GeodesicLineExact.hpp \
+ $(top_srcdir)/include/GeographicLib/Geohash.hpp \
+ $(top_srcdir)/include/GeographicLib/Geoid.hpp \
+ $(top_srcdir)/include/GeographicLib/Gnomonic.hpp \
+ $(top_srcdir)/include/GeographicLib/LambertConformalConic.hpp \
+ $(top_srcdir)/include/GeographicLib/LocalCartesian.hpp \
+ $(top_srcdir)/include/GeographicLib/Math.hpp \
+ $(top_srcdir)/include/GeographicLib/MGRS.hpp \
+ $(top_srcdir)/include/GeographicLib/OSGB.hpp \
+ $(top_srcdir)/include/GeographicLib/PolarStereographic.hpp \
+ $(top_srcdir)/include/GeographicLib/PolygonArea.hpp \
+ $(top_srcdir)/include/GeographicLib/TransverseMercatorExact.hpp \
+ $(top_srcdir)/include/GeographicLib/TransverseMercator.hpp \
+ $(top_srcdir)/include/GeographicLib/UTMUPS.hpp
+
+ALLSOURCES = \
+ $(top_srcdir)/src/AlbersEqualArea.cpp \
+ $(top_srcdir)/src/AzimuthalEquidistant.cpp \
+ $(top_srcdir)/src/CassiniSoldner.cpp \
+ $(top_srcdir)/src/DMS.cpp \
+ $(top_srcdir)/src/Ellipsoid.cpp \
+ $(top_srcdir)/src/EllipticFunction.cpp \
+ $(top_srcdir)/src/Geocentric.cpp \
+ $(top_srcdir)/src/GeoCoords.cpp \
+ $(top_srcdir)/src/Geodesic.cpp \
+ $(top_srcdir)/src/GeodesicLine.cpp \
+ $(top_srcdir)/src/Geohash.cpp \
+ $(top_srcdir)/src/Geoid.cpp \
+ $(top_srcdir)/src/Gnomonic.cpp \
+ $(top_srcdir)/src/LambertConformalConic.cpp \
+ $(top_srcdir)/src/LocalCartesian.cpp \
+ $(top_srcdir)/src/MGRS.cpp \
+ $(top_srcdir)/src/OSGB.cpp \
+ $(top_srcdir)/src/PolarStereographic.cpp \
+ $(top_srcdir)/src/PolygonArea.cpp \
+ $(top_srcdir)/src/TransverseMercator.cpp \
+ $(top_srcdir)/src/TransverseMercatorExact.cpp \
+ $(top_srcdir)/src/UTMUPS.cpp \
+ $(top_srcdir)/tools/CartConvert.cpp \
+ $(top_srcdir)/tools/ConicProj.cpp \
+ $(top_srcdir)/tools/GeodesicProj.cpp \
+ $(top_srcdir)/tools/GeoConvert.cpp \
+ $(top_srcdir)/tools/GeodSolve.cpp \
+ $(top_srcdir)/tools/GeoidEval.cpp \
+ $(top_srcdir)/tools/Gravity.cpp \
+ $(top_srcdir)/tools/Planimeter.cpp \
+ $(top_srcdir)/tools/TransverseMercatorProj.cpp
+
+MANPAGES = \
+ ../man/CartConvert.1.html \
+ ../man/ConicProj.1.html \
+ ../man/GeodesicProj.1.html \
+ ../man/GeoConvert.1.html \
+ ../man/GeodSolve.1.html \
+ ../man/GeoidEval.1.html \
+ ../man/Gravity.1.html \
+ ../man/MagneticField.1.html \
+ ../man/Planimeter.1.html \
+ ../man/TransverseMercatorProj.1.html
+
+LEGACYFILES = \
+ $(top_srcdir)/legacy/C/geodesic.c \
+ $(top_srcdir)/legacy/C/geodesic.h \
+ $(top_srcdir)/legacy/C/direct.c \
+ $(top_srcdir)/legacy/C/inverse.c \
+ $(top_srcdir)/legacy/C/planimeter.c \
+ $(top_srcdir)/legacy/Fortran/geodesic.for \
+ $(top_srcdir)/legacy/Fortran/geodesic.inc \
+ $(top_srcdir)/legacy/Fortran/geoddirect.for \
+ $(top_srcdir)/legacy/Fortran/geodinverse.for \
+ $(top_srcdir)/legacy/Fortran/planimeter.for
+
+doc: html/index.html
+
+if HAVE_DOXYGEN
+manpages: $(MANPAGES)
+ if test -d html; then rm -rf html/*; else mkdir html; fi
+ cp $^ html/
+ touch $@
+
+html/index.html: manpages doxyfile.in GeographicLib.dox \
+ $(HPPFILES) $(ALLSOURCES) $(EXTRAFILES) $(FIGURES) \
+ doxyfile-c.in geodesic-c.dox doxyfile-for.in geodesic-for.dox \
+ $(LEGACYFILES)
+ cp -p $(EXTRAFILES) $(top_srcdir)/maxima/*.mac \
+ $(top_srcdir)/LICENSE.txt html/
+ sed -e "s%@PROJECT_SOURCE_DIR@%$(top_srcdir)%g" \
+ -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+ $(srcdir)/doxyfile.in | $(DOXYGEN) -
+ sed -e "s%@PROJECT_SOURCE_DIR@%$(top_srcdir)%g" \
+ -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+ $(srcdir)/doxyfile-c.in | $(DOXYGEN) -
+ sed -e "s%@PROJECT_SOURCE_DIR@%$(top_srcdir)%g" \
+ -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+ $(srcdir)/doxyfile-for.in | $(DOXYGEN) -
+else
+html/index.html: index.html.in utilities.html.in
+ if test -d html; then rm -rf html/*; else mkdir html; fi
+ cp $(top_srcdir)/LICENSE.txt html/
+ sed -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+ $(srcdir)/utilities.html.in > html/utilities.html
+ sed -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+ $(srcdir)/index.html.in > html/index.html
+endif
+
+maintainer-clean-local:
+ rm -rf html manpages
+
+install-doc: html/index.html
+ $(INSTALL) -d $(DESTDIR)$(docdir)/html
+ $(INSTALL) -m 644 `dirname $<`/*.* $(DESTDIR)$(docdir)/html
+ -test -f `dirname $<`/C/index.html && \
+ $(INSTALL) -d $(DESTDIR)$(docdir)/html/C && \
+ $(INSTALL) -m 644 `dirname $<`/C/*.* $(DESTDIR)$(docdir)/html/C
+ -test -f `dirname $<`/Fortran/index.html && \
+ $(INSTALL) -d $(DESTDIR)$(docdir)/html/Fortran && \
+ $(INSTALL) -m 644 `dirname $<`/Fortran/*.* \
+ $(DESTDIR)$(docdir)/html/Fortran
+ $(INSTALL) -d $(DESTDIR)$(docdir)/scripts
+ $(INSTALL) -m 644 $(SCRIPTDRIVERS) $(DESTDIR)$(docdir)/scripts
+ $(INSTALL) -d $(DESTDIR)$(docdir)/scripts/GeographicLib
+ $(INSTALL) -m 644 $(JSSCRIPTS) $(DESTDIR)$(docdir)/scripts/GeographicLib
diff --git a/gtsam/3rdparty/GeographicLib/doc/Makefile.in b/gtsam/3rdparty/GeographicLib/doc/Makefile.in
new file mode 100644
index 000000000..859662692
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/Makefile.in
@@ -0,0 +1,561 @@
+# Makefile.in generated by automake 1.12.2 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2012 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = doc
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/GeographicLib/Config-ac.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COL = @COL@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEOGRAPHICLIB_VERSION_MAJOR = @GEOGRAPHICLIB_VERSION_MAJOR@
+GEOGRAPHICLIB_VERSION_MINOR = @GEOGRAPHICLIB_VERSION_MINOR@
+GEOGRAPHICLIB_VERSION_PATCH = @GEOGRAPHICLIB_VERSION_PATCH@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_AGE = @LT_AGE@
+LT_CURRENT = @LT_CURRENT@
+LT_REVISION = @LT_REVISION@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POD2HTML = @POD2HTML@
+POD2MAN = @POD2MAN@
+POW_LIB = @POW_LIB@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRAFILES = $(srcdir)/tmseries30.html $(srcdir)/geodseries30.html
+FIGURES = $(srcdir)/gauss-krueger-graticule.png \
+ $(srcdir)/thompson-tm-graticule.png \
+ $(srcdir)/gauss-krueger-convergence-scale.png \
+ $(srcdir)/gauss-schreiber-graticule-a.png \
+ $(srcdir)/gauss-krueger-graticule-a.png \
+ $(srcdir)/thompson-tm-graticule-a.png \
+ $(srcdir)/gauss-krueger-error.png \
+ $(srcdir)/meridian-measures.png
+
+SCRIPTDRIVERS = \
+ $(srcdir)/scripts/geod-calc.html \
+ $(srcdir)/scripts/geod-google.html \
+ $(srcdir)/scripts/geod-google-instructions.html
+
+JSSCRIPTS = \
+ $(srcdir)/scripts/GeographicLib/Math.js \
+ $(srcdir)/scripts/GeographicLib/Geodesic.js \
+ $(srcdir)/scripts/GeographicLib/GeodesicLine.js \
+ $(srcdir)/scripts/GeographicLib/PolygonArea.js \
+ $(srcdir)/scripts/GeographicLib/DMS.js \
+ $(srcdir)/scripts/GeographicLib/Interface.js
+
+HPPFILES = \
+ $(top_srcdir)/include/GeographicLib/Accumulator.hpp \
+ $(top_srcdir)/include/GeographicLib/AlbersEqualArea.hpp \
+ $(top_srcdir)/include/GeographicLib/AzimuthalEquidistant.hpp \
+ $(top_srcdir)/include/GeographicLib/CassiniSoldner.hpp \
+ $(top_srcdir)/include/GeographicLib/Constants.hpp \
+ $(top_srcdir)/include/GeographicLib/DMS.hpp \
+ $(top_srcdir)/include/GeographicLib/Ellipsoid.hpp \
+ $(top_srcdir)/include/GeographicLib/EllipticFunction.hpp \
+ $(top_srcdir)/include/GeographicLib/Geocentric.hpp \
+ $(top_srcdir)/include/GeographicLib/GeoCoords.hpp \
+ $(top_srcdir)/include/GeographicLib/Geodesic.hpp \
+ $(top_srcdir)/include/GeographicLib/GeodesicExact.hpp \
+ $(top_srcdir)/include/GeographicLib/GeodesicLine.hpp \
+ $(top_srcdir)/include/GeographicLib/GeodesicLineExact.hpp \
+ $(top_srcdir)/include/GeographicLib/Geohash.hpp \
+ $(top_srcdir)/include/GeographicLib/Geoid.hpp \
+ $(top_srcdir)/include/GeographicLib/Gnomonic.hpp \
+ $(top_srcdir)/include/GeographicLib/LambertConformalConic.hpp \
+ $(top_srcdir)/include/GeographicLib/LocalCartesian.hpp \
+ $(top_srcdir)/include/GeographicLib/Math.hpp \
+ $(top_srcdir)/include/GeographicLib/MGRS.hpp \
+ $(top_srcdir)/include/GeographicLib/OSGB.hpp \
+ $(top_srcdir)/include/GeographicLib/PolarStereographic.hpp \
+ $(top_srcdir)/include/GeographicLib/PolygonArea.hpp \
+ $(top_srcdir)/include/GeographicLib/TransverseMercatorExact.hpp \
+ $(top_srcdir)/include/GeographicLib/TransverseMercator.hpp \
+ $(top_srcdir)/include/GeographicLib/UTMUPS.hpp
+
+ALLSOURCES = \
+ $(top_srcdir)/src/AlbersEqualArea.cpp \
+ $(top_srcdir)/src/AzimuthalEquidistant.cpp \
+ $(top_srcdir)/src/CassiniSoldner.cpp \
+ $(top_srcdir)/src/DMS.cpp \
+ $(top_srcdir)/src/Ellipsoid.cpp \
+ $(top_srcdir)/src/EllipticFunction.cpp \
+ $(top_srcdir)/src/Geocentric.cpp \
+ $(top_srcdir)/src/GeoCoords.cpp \
+ $(top_srcdir)/src/Geodesic.cpp \
+ $(top_srcdir)/src/GeodesicLine.cpp \
+ $(top_srcdir)/src/Geohash.cpp \
+ $(top_srcdir)/src/Geoid.cpp \
+ $(top_srcdir)/src/Gnomonic.cpp \
+ $(top_srcdir)/src/LambertConformalConic.cpp \
+ $(top_srcdir)/src/LocalCartesian.cpp \
+ $(top_srcdir)/src/MGRS.cpp \
+ $(top_srcdir)/src/OSGB.cpp \
+ $(top_srcdir)/src/PolarStereographic.cpp \
+ $(top_srcdir)/src/PolygonArea.cpp \
+ $(top_srcdir)/src/TransverseMercator.cpp \
+ $(top_srcdir)/src/TransverseMercatorExact.cpp \
+ $(top_srcdir)/src/UTMUPS.cpp \
+ $(top_srcdir)/tools/CartConvert.cpp \
+ $(top_srcdir)/tools/ConicProj.cpp \
+ $(top_srcdir)/tools/GeodesicProj.cpp \
+ $(top_srcdir)/tools/GeoConvert.cpp \
+ $(top_srcdir)/tools/GeodSolve.cpp \
+ $(top_srcdir)/tools/GeoidEval.cpp \
+ $(top_srcdir)/tools/Gravity.cpp \
+ $(top_srcdir)/tools/Planimeter.cpp \
+ $(top_srcdir)/tools/TransverseMercatorProj.cpp
+
+MANPAGES = \
+ ../man/CartConvert.1.html \
+ ../man/ConicProj.1.html \
+ ../man/GeodesicProj.1.html \
+ ../man/GeoConvert.1.html \
+ ../man/GeodSolve.1.html \
+ ../man/GeoidEval.1.html \
+ ../man/Gravity.1.html \
+ ../man/MagneticField.1.html \
+ ../man/Planimeter.1.html \
+ ../man/TransverseMercatorProj.1.html
+
+LEGACYFILES = \
+ $(top_srcdir)/legacy/C/geodesic.c \
+ $(top_srcdir)/legacy/C/geodesic.h \
+ $(top_srcdir)/legacy/C/direct.c \
+ $(top_srcdir)/legacy/C/inverse.c \
+ $(top_srcdir)/legacy/C/planimeter.c \
+ $(top_srcdir)/legacy/Fortran/geodesic.for \
+ $(top_srcdir)/legacy/Fortran/geodesic.inc \
+ $(top_srcdir)/legacy/Fortran/geoddirect.for \
+ $(top_srcdir)/legacy/Fortran/geodinverse.for \
+ $(top_srcdir)/legacy/Fortran/planimeter.for
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu doc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic \
+ maintainer-clean-local
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic maintainer-clean-local mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ uninstall uninstall-am
+
+
+doc: html/index.html
+
+@HAVE_DOXYGEN_TRUE@manpages: $(MANPAGES)
+@HAVE_DOXYGEN_TRUE@ if test -d html; then rm -rf html/*; else mkdir html; fi
+@HAVE_DOXYGEN_TRUE@ cp $^ html/
+@HAVE_DOXYGEN_TRUE@ touch $@
+
+@HAVE_DOXYGEN_TRUE@html/index.html: manpages doxyfile.in GeographicLib.dox \
+@HAVE_DOXYGEN_TRUE@ $(HPPFILES) $(ALLSOURCES) $(EXTRAFILES) $(FIGURES) \
+@HAVE_DOXYGEN_TRUE@ doxyfile-c.in geodesic-c.dox doxyfile-for.in geodesic-for.dox \
+@HAVE_DOXYGEN_TRUE@ $(LEGACYFILES)
+@HAVE_DOXYGEN_TRUE@ cp -p $(EXTRAFILES) $(top_srcdir)/maxima/*.mac \
+@HAVE_DOXYGEN_TRUE@ $(top_srcdir)/LICENSE.txt html/
+@HAVE_DOXYGEN_TRUE@ sed -e "s%@PROJECT_SOURCE_DIR@%$(top_srcdir)%g" \
+@HAVE_DOXYGEN_TRUE@ -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+@HAVE_DOXYGEN_TRUE@ $(srcdir)/doxyfile.in | $(DOXYGEN) -
+@HAVE_DOXYGEN_TRUE@ sed -e "s%@PROJECT_SOURCE_DIR@%$(top_srcdir)%g" \
+@HAVE_DOXYGEN_TRUE@ -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+@HAVE_DOXYGEN_TRUE@ $(srcdir)/doxyfile-c.in | $(DOXYGEN) -
+@HAVE_DOXYGEN_TRUE@ sed -e "s%@PROJECT_SOURCE_DIR@%$(top_srcdir)%g" \
+@HAVE_DOXYGEN_TRUE@ -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+@HAVE_DOXYGEN_TRUE@ $(srcdir)/doxyfile-for.in | $(DOXYGEN) -
+@HAVE_DOXYGEN_FALSE@html/index.html: index.html.in utilities.html.in
+@HAVE_DOXYGEN_FALSE@ if test -d html; then rm -rf html/*; else mkdir html; fi
+@HAVE_DOXYGEN_FALSE@ cp $(top_srcdir)/LICENSE.txt html/
+@HAVE_DOXYGEN_FALSE@ sed -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+@HAVE_DOXYGEN_FALSE@ $(srcdir)/utilities.html.in > html/utilities.html
+@HAVE_DOXYGEN_FALSE@ sed -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+@HAVE_DOXYGEN_FALSE@ $(srcdir)/index.html.in > html/index.html
+
+maintainer-clean-local:
+ rm -rf html manpages
+
+install-doc: html/index.html
+ $(INSTALL) -d $(DESTDIR)$(docdir)/html
+ $(INSTALL) -m 644 `dirname $<`/*.* $(DESTDIR)$(docdir)/html
+ -test -f `dirname $<`/C/index.html && \
+ $(INSTALL) -d $(DESTDIR)$(docdir)/html/C && \
+ $(INSTALL) -m 644 `dirname $<`/C/*.* $(DESTDIR)$(docdir)/html/C
+ -test -f `dirname $<`/Fortran/index.html && \
+ $(INSTALL) -d $(DESTDIR)$(docdir)/html/Fortran && \
+ $(INSTALL) -m 644 `dirname $<`/Fortran/*.* \
+ $(DESTDIR)$(docdir)/html/Fortran
+ $(INSTALL) -d $(DESTDIR)$(docdir)/scripts
+ $(INSTALL) -m 644 $(SCRIPTDRIVERS) $(DESTDIR)$(docdir)/scripts
+ $(INSTALL) -d $(DESTDIR)$(docdir)/scripts/GeographicLib
+ $(INSTALL) -m 644 $(JSSCRIPTS) $(DESTDIR)$(docdir)/scripts/GeographicLib
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/gtsam/3rdparty/GeographicLib/doc/Makefile.mk b/gtsam/3rdparty/GeographicLib/doc/Makefile.mk
new file mode 100644
index 000000000..ca852d9d0
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/Makefile.mk
@@ -0,0 +1,30 @@
+SCRIPTDRIVERS = $(wildcard scripts/[A-Za-z]*.html)
+JSSCRIPTS = $(wildcard scripts/GeographicLib/[A-Za-z]*.js)
+
+VERSION:=$(shell grep '\bVERSION=' ../configure | cut -f2 -d\' | head -1)
+
+doc: html/index.html
+
+html/index.html: index.html.in utilities.html.in
+ if test -d html; then rm -rf html/*; else mkdir html; fi
+ cp ../LICENSE.txt html/
+ sed -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+ utilities.html.in > html/utilities.html
+ sed -e "s%@PROJECT_VERSION@%$(VERSION)%g" \
+ index.html.in > html/index.html
+
+PREFIX = /usr/local
+DEST = $(PREFIX)/share/doc/GeographicLib
+DOCDEST = $(DEST)/html
+SCRIPTDEST = $(DEST)/scripts
+INSTALL = install -b
+
+install: html/index.html
+ test -d $(DOCDEST) || mkdir -p $(DOCDEST)
+ $(INSTALL) -m 644 html/* $(DOCDEST)/
+ test -d $(SCRIPTDEST)/GeographicLib || \
+ mkdir -p $(SCRIPTDEST)/GeographicLib
+ $(INSTALL) -m 644 $(SCRIPTDRIVERS) $(SCRIPTDEST)/
+ $(INSTALL) -m 644 $(JSSCRIPTS) $(SCRIPTDEST)/GeographicLib/
+
+.PHONY: doc install clean
diff --git a/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib.dox b/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib.dox
new file mode 100644
index 000000000..89b934a7d
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib.dox
@@ -0,0 +1,241 @@
+// -*- text -*-
+/**
+ * \file NETGeographicLib.dox
+ * \brief Documentation for NETGeographicLib
+ *
+ * Written by Scott Heiman and licensed under the
+ * MIT/X11 License. For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+/**
+\mainpage NETGeographicLib library
+\author Scott Heiman (mrmtdew2@outlook.com)
+\version 1.34
+\date 2013-12-11
+
+\section abstract Abstract
+
+%NETGeographicLib is a .NET wrapper for GeographicLib. It allows
+.NET developers to access GeographicLib classes within C#, Visual
+Basic, Managed C++, and other Microsoft .NET languages.
+
+NETGeographicLib is written in Managed C++. It IS NOT a reimplementation
+of the GeographicLib software. It is a container that provides interfaces
+to the GeographicLib classes. GeographicLib and NETGeographicLib is an
+integrated product.
+
+The NETGeographic project in the GeographicLib-vc10.sln file located in
+\/GeographicLib-1.34/windows will create the NETGeographicLib
+DLL. The source code for NETGeographicLib is located in
+\/GeographicLib-1.34/dotnet/NETGeographicLib. NETGeographicLib
+is not available for older versions of Microsoft Visual Studio.
+
+NETGeographicLib has been tested with C#, Managed C++, and Visual Basic.
+Sample code snippets can be found in
+\/GeographicLib-1.34/dotnet/examples.
+
+\section differences Differences between NETGeographicLib and GeographicLib
+
+The NETGeographicLib class names are identical to the GeographicLib class names.
+All NETGeographicLib classes are in the NETGeographicLib namespace.
+
+NETGeographicLib exposes most of the GeographicLib classes. The exceptions
+are SphericalEngine, GeographicLib::Math, and GeographicLib::Utility. The
+SphericalEngine class is a template class which (according to the comments in
+the SphericalEngine.h file) is not usually accessible to developers. The
+GeographicLib::Math class contains several specialized functions required by
+GeographicLib classes. They have limited use outside GeographicLib. This class
+may be exposed in a future release if there is demand for it. The functions
+provided by GeographicLib::Utility duplicate functions provided by existing .NET
+controls (DateTime).
+
+The SphericalCoefficients class replaces the SphericalEngine::coeff class.
+
+The NETGeographicLib class function interfaces are similar, and in many cases,
+identical to the GeographicLib interfaces. There are differences because of
+limitations in .NET and other differences that are discretionary. The comments
+in the header files contain a section labeled "INTERFACE DIFFERENCES" that detail
+the differences between the NETGeographicLib interfaces and the GeographicLib
+interfaces. The differences are summarized in the text that follows.
+
+Default values for function parameters are not supported in .NET.
+
+Several GeographicLib class functions accept or return a "capabilities mask" as
+an unsigned integer. The NETGeographicLib classes accept and return the capabilities
+mask as an enumeration.
+
+The Geocentric and LocalCartesian classes have functions that return a rotation matrix.
+The NETGeographicLib versions return a two-dimensional, 3 × 3 array rather than a vector.
+
+A lot of GeographicLib classes have inspector functions (MajorRadius,
+Flattening, etc.). These inspector functions are implemented as
+properties in NETGeographicLib.
+
+NETGeographicLib classes do not implement constructors that create "uninitialized" objects.
+
+Many NETGeographicLib classes implement a default constructor that assumes WGS84 parameters.
+
+Several GeographicLib classes implement the () operator. NETGeographicLib classes
+replace the () operator with a specific function. Managed C++ allows developers to
+overload the () operator; however, the () operator is not 'elegantly' supported in
+other .NET languages. For example, if the () operator was implemented in the
+NETGeographicLib::Geoid class, then C# code would look like
+\code
+Geoid geoid = new Geoid();
+double h = geoid.op_FuncCall(latitude,longitude); // if () operator was implemented.
+h = geoid.Height(latitude,longitude); // with () operator replaced with Height
+\endcode
+The author felt that the op_FuncCall syntax did not appropriately define the purpose
+of the function call.
+
+.NET does not allow developers to overload the assignment operators (=,+=,-=,*=).
+These operators have been replaced with functions in the NETGeographicLib::Accumulator class.
+
+\section library Using NETGeographicLib in a .NET Application
+
+If you have access to the NETGeographicLib and GeographicLib projects then
+-# Create a new solution.
+-# Create a new project using any .NET language. For this example, call it MyApp.
+-# Add the NETGeographic and Geographic projects to the solution. Verify that NETGeographicLib depends upon GeographicLib.
+-# Right-Click MyApp in the Solution View and select "Add Reference..." (C#/VB) or "References..." (Managed C++) in the pop-up menu.
+-# (Managed C++) Click the "Add New Reference..." button in the Properties dialog.
+\image html NETGeographicLib3.png
+-# Click the Projects Tab and select NETGeographic.
+ \image html NETGeographicLib1.png
+-# Click OK.
+
+If you only have access to the NETGeographic.dll then
+-# Create a new solution.
+-# Create a new project using any .NET language. For this example, call it MyApp.
+-# Right-Click MyApp in the Solution View and select "Add Reference..." in the popup menu.
+-# Right-Click MyApp in the Solution View and select "Add Reference..." (C#/VB) or "References..." (Managed C++) in the pop-up menu.
+-# (Managed C++) Click the "Add New Reference..." button in the Properties dialog.
+\image html NETGeographicLib3.png
+-# Click the Browse Tab and navigate to the folder containing NETGeographic.dll.
+\image html NETGeographicLib2.png
+-# Select NETGeographic.dll and click OK.
+
+The MyApp project will have access to all public NETGeographicLib classes after the
+NETGeographic reference is added to MyApp.
+
+C# developers should add
+\code using NETGeographicLib; \endcode
+to any C# source file that uses NETGeographicLib.
+
+Managed C++ developers should add
+\code using namespace NETGeographicLib; \endcode
+to any C++ source that uses NETGeographicLib classes.
+
+Visual Basic developers should add
+\code Imports NETGeographicLib \endcode
+to any Visual Basic source that uses NETGeographicLib classes.
+
+\section sample C# Sample Application
+
+A C# sample application is provided that demonstrates NETGeographicLib classes.
+The source code for the sample application is located in
+\/GeographicLib-1.34/dotnet/Projections. The sample
+application creates a tabbed dialog. Each tab provides data entry fields that
+allow the user to exercise one or more NETGeographicLib classes.
+
+The following table lists the source code that demonstrates specific classes.
+
+
+\section netcmake Using cmake to build a Managed C++ Application
+
+The following assumes that you have installed %GeographicLib in one of
+two ways:
+- you have built and installed %GeographicLib using cmake with
+ -D BUILD_NETGEOGRAPHICLIB=ON (see
+ \ref cmake "Installation with cmake" in the %GeographicLib
+ documentation). You can use any version of Visual Studio to build
+ %GeographicLib and should use the same version to build your
+ application. You can build %GeographicLib as a shared library using
+ -D GEOGRAPHICLIB_LIB_TYPE=SHARED or BOTH.
+- you have installed %GeographicLib using one of the binary installers (see
+ \ref windowsbin "Using a binary installer for Windows" in the
+ %GeographicLib documentation). In this case, you are restricted to using
+ Visual Studio 10.
+
+The minimum recommended version of cmake for use with NETGeographicLib
+is 2.8.7. In order to build an application that uses NETGeographicLib
+with cmake, ask for the NETGeographicLib "component" of %GeographicLib
+using \verbatim
+find_package(GeographicLib COMPONENTS NETGeographicLib) \endverbatim
+If NETGeographicLib is found, then
+GeographicLib_NETGeographicLib_FOUND will be set to true and
+GeographicLib_NETGeographicLib_LIBRARIES will be set to the
+NETGeographic shared library. This is the name of the cmake target from
+which the pathname of the dll can be obtained.
+
+Here is a very simple test code, which uses the
+NETGeographicLib::Geodesic class:
+\include example-Geodesic-small.cpp
+This example is
+dotnet/examples/ManagedCPP/example-Geodesic-small.cpp.
+
+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 2.8.7) # required for VS_DOTNET_REFERENCES
+
+find_package (GeographicLib 1.34 REQUIRED COMPONENTS NETGeographicLib)
+
+add_executable (${PROJECT_NAME} example-Geodesic-small.cpp)
+set_target_properties (${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/clr")
+string (REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+string (REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+# This is set up for Release builds only. Change RELEASE to DEBUG for
+# Debug builds.
+get_target_property (_LOC "${GeographicLib_NETGeographicLib_LIBRARIES}"
+ IMPORTED_LOCATION_RELEASE)
+set_target_properties (${PROJECT_NAME} PROPERTIES VS_DOTNET_REFERENCES ${_LOC})
+
+get_target_property (_LIB "${GeographicLib_NETGeographicLib_LIBRARIES}"
+ IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE)
+get_target_property (_LIBTYPE ${_LIB} 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 $ ${CMAKE_CFG_INTDIR}
+ COMMENT "Copying shared library for GeographicLib")
+endif () \endverbatim
+The typical invocation of cmake is \verbatim
+mkdir BUILD
+cd BUILD
+cmake -G "Visual Studio 10" -D CMAKE_PREFIX_PATH=C:/pkg-vc10 ..
+cmake --build . --config Release \endverbatim
+The version of Visual Studio should match that used to build
+NETGeographicLib. NOTE: With Visual Studio 10, this results in
+warnings such as \verbatim
+warning C4945: 'ExtensionAttribute' : cannot import symbol from ... \endverbatim
+which can be safely(?) ignored.
+
+Running the example with \verbatim
+Release\geodesictest.exe \endverbatim
+should give \verbatim
+ 5551.75940031868 km \endverbatim
+**********************************************************************/
diff --git a/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib1.png b/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib1.png
new file mode 100644
index 000000000..22049cdbf
Binary files /dev/null and b/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib1.png differ
diff --git a/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib2.png b/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib2.png
new file mode 100644
index 000000000..57e34a69c
Binary files /dev/null and b/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib2.png differ
diff --git a/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib3.png b/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib3.png
new file mode 100644
index 000000000..6d4870b80
Binary files /dev/null and b/gtsam/3rdparty/GeographicLib/doc/NETGeographicLib3.png differ
diff --git a/gtsam/3rdparty/GeographicLib/doc/doxyfile-c.in b/gtsam/3rdparty/GeographicLib/doc/doxyfile-c.in
new file mode 100644
index 000000000..f77a0b334
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/doxyfile-c.in
@@ -0,0 +1,1810 @@
+# Doxyfile 1.8.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = "C library for Geodesics"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PROJECT_VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
+
+STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@/legacy/C/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH = @PROJECT_SOURCE_DIR@/legacy/C/
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes,
+# or namespaces to their corresponding documentation. Such a link can be
+# prevented in individual cases by by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter and setter methods for a property. Setting this option to YES (the default) will make doxygen replace the get and set methods by a property in the documentation. This will only work if the methods are indeed getting or setting a simple type. If this is not the case, or you want to show the methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 0
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command , where is the value of
+# the FILE_VERSION_FILTER tag, and is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @PROJECT_SOURCE_DIR@/legacy/C \
+ @PROJECT_SOURCE_DIR@/doc/geodesic-c.dox
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS = *.c \
+ *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = @PROJECT_SOURCE_DIR@/legacy/C
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command , where
+# is the value of the INPUT_FILTER tag, and is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html/C
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+#
+# Qt Help Project / Custom Filters.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+#
+# Qt Help Project / Filter Attributes.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = DOXYGEN
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES = html/GeographicLib.tag=..
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = html/C/GeographicLib-C.tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/gtsam/3rdparty/GeographicLib/doc/doxyfile-for.in b/gtsam/3rdparty/GeographicLib/doc/doxyfile-for.in
new file mode 100644
index 000000000..47ef530d7
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/doxyfile-for.in
@@ -0,0 +1,1810 @@
+# Doxyfile 1.8.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = "Fortran library for Geodesics"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PROJECT_VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
+
+STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@/legacy/Fortran/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH = @PROJECT_SOURCE_DIR@/legacy/Fortran/
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = YES
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
+
+EXTENSION_MAPPING = inc=Fortran
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes,
+# or namespaces to their corresponding documentation. Such a link can be
+# prevented in individual cases by by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter and setter methods for a property. Setting this option to YES (the default) will make doxygen replace the get and set methods by a property in the documentation. This will only work if the methods are indeed getting or setting a simple type. If this is not the case, or you want to show the methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command , where is the value of
+# the FILE_VERSION_FILTER tag, and is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @PROJECT_SOURCE_DIR@/legacy/Fortran \
+ @PROJECT_SOURCE_DIR@/doc/geodesic-for.dox
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS = *.for \
+ *.inc
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = @PROJECT_SOURCE_DIR@/legacy/Fortran
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command , where
+# is the value of the INPUT_FILTER tag, and is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER = "sed -e /@cond/,/@endcond/g"
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html/Fortran
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+#
+# Qt Help Project / Custom Filters.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+#
+# Qt Help Project / Filter Attributes.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = DOXYGEN
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES = html/GeographicLib.tag=..
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = html/Fortran/GeographicLib-for.tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/gtsam/3rdparty/GeographicLib/doc/doxyfile-net.in b/gtsam/3rdparty/GeographicLib/doc/doxyfile-net.in
new file mode 100644
index 000000000..b9fedb587
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/doxyfile-net.in
@@ -0,0 +1,1811 @@
+# Doxyfile 1.8.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = NETGeographicLib
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PROJECT_VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
+
+STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@/dotnet/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH = @PROJECT_SOURCE_DIR@/dotnet/
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes,
+# or namespaces to their corresponding documentation. Such a link can be
+# prevented in individual cases by by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = YES
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter and setter methods for a property. Setting this option to YES (the default) will make doxygen replace the get and set methods by a property in the documentation. This will only work if the methods are indeed getting or setting a simple type. If this is not the case, or you want to show the methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command , where is the value of
+# the FILE_VERSION_FILTER tag, and is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @PROJECT_SOURCE_DIR@/dotnet/NETGeographicLib \
+ @PROJECT_SOURCE_DIR@/doc/NETGeographicLib.dox
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS = [A-Za-z]*.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = @PROJECT_SOURCE_DIR@/dotnet/examples/CS \
+ @PROJECT_SOURCE_DIR@/dotnet/examples/ManagedCPP \
+ @PROJECT_SOURCE_DIR@/dotnet/examples/VB
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = @PROJECT_SOURCE_DIR@/doc
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command , where
+# is the value of the INPUT_FILTER tag, and is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html/NET
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+#
+# Qt Help Project / Custom Filters.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+#
+# Qt Help Project / Filter Attributes.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = YES
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = DOXYGEN
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES = html/GeographicLib.tag=..
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = html/NET/NETGeographicLib.tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/gtsam/3rdparty/GeographicLib/doc/doxyfile.in b/gtsam/3rdparty/GeographicLib/doc/doxyfile.in
new file mode 100644
index 000000000..448affa1a
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/doxyfile.in
@@ -0,0 +1,1812 @@
+# Doxyfile 1.8.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = GeographicLib
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PROJECT_VERSION@
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
+
+STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@/
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH = @PROJECT_SOURCE_DIR@/include/
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented classes,
+# or namespaces to their corresponding documentation. Such a link can be
+# prevented in individual cases by by putting a % sign in front of the word or
+# globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter and setter methods for a property. Setting this option to YES (the default) will make doxygen replace the get and set methods by a property in the documentation. This will only work if the methods are indeed getting or setting a simple type. If this is not the case, or you want to show the methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = NO
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command , where is the value of
+# the FILE_VERSION_FILTER tag, and is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = @PROJECT_SOURCE_DIR@/src \
+ @PROJECT_SOURCE_DIR@/include/GeographicLib \
+ @PROJECT_SOURCE_DIR@/tools \
+ @PROJECT_SOURCE_DIR@/doc/GeographicLib.dox
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS = [A-Za-z]*.cpp \
+ [A-Za-z]*.hpp
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = @PROJECT_SOURCE_DIR@/examples
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH = @PROJECT_SOURCE_DIR@/doc
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command , where
+# is the value of the INPUT_FILTER tag, and is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+#
+# Qt Help Project / Custom Filters.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+#
+# Qt Help Project / Filter Attributes.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = YES
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = NO
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED = DOXYGEN
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = html/GeographicLib.tag
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# managable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-convergence-scale.png b/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-convergence-scale.png
new file mode 100644
index 000000000..1a3172b85
Binary files /dev/null and b/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-convergence-scale.png differ
diff --git a/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-error.png b/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-error.png
new file mode 100644
index 000000000..cd397e669
Binary files /dev/null and b/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-error.png differ
diff --git a/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-graticule-a.png b/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-graticule-a.png
new file mode 100644
index 000000000..bffd83207
Binary files /dev/null and b/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-graticule-a.png differ
diff --git a/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-graticule.png b/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-graticule.png
new file mode 100644
index 000000000..af793eab6
Binary files /dev/null and b/gtsam/3rdparty/GeographicLib/doc/gauss-krueger-graticule.png differ
diff --git a/gtsam/3rdparty/GeographicLib/doc/gauss-schreiber-graticule-a.png b/gtsam/3rdparty/GeographicLib/doc/gauss-schreiber-graticule-a.png
new file mode 100644
index 000000000..51a5e9db2
Binary files /dev/null and b/gtsam/3rdparty/GeographicLib/doc/gauss-schreiber-graticule-a.png differ
diff --git a/gtsam/3rdparty/GeographicLib/doc/geodesic-c.dox b/gtsam/3rdparty/GeographicLib/doc/geodesic-c.dox
new file mode 100644
index 000000000..d07fb61ba
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/geodesic-c.dox
@@ -0,0 +1,118 @@
+// -*- text -*-
+/**
+ * \file geodesic-c.dox
+ * \brief Documentation for geodesic routines implemented in C
+ *
+ * Written by Charles Karney and licensed under the
+ * MIT/X11 License. For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+/**
+\mainpage Geodesic routines implemented in C
+\author Charles F. F. Karney (charles@karney.com)
+\version 1.32
+
+\section abstract Abstract
+
+This is a C implementation of the geodesic algorithms from GeographicLib. This is a
+self-contained library (requiring only the standard C math library)
+which makes it easy to do geodesic computations for an ellipsoid of
+revolution in a C program. It uses ANSI C as described in
+B. W. Kernigan and D. M. Ritchie, The C Programming Language, 2nd
+Ed. (Prentice Hall, 1988), and so should compile correctly with just
+about any C compiler.
+
+\section download Downloading the source
+
+The C library is part of %GeographicLib which available for download at
+-
+ GeographicLib-1.32.tar.gz
+-
+ GeographicLib-1.32.zip
+.
+as either a compressed tar file (tar.gz) or a zip file. After unpacking
+the source, the C library can be found in GeographicLib-1.32/legacy/C.
+The library consists of two files geodesic.c and geodesic.h.
+
+The library is also included as part of
+proj.4 starting with version
+4.9.0, where is used as the computational backend for
+geod(1).
+Instructions for how to use the library via proj.4 are given below.
+
+\section doc Library documentation
+
+The interface to the library is documented via doxygen in the header
+file. To access this, see geodesic.h.
+
+\section samples Sample programs
+
+Also included are 3 small test programs:
+ - direct.c is a simple command line utility for solving the
+ direct geodesic problem;
+ - inverse.c is a simple command line utility for solving the
+ inverse geodesic problem;
+ - planimeter.c is a simple command line utility for computing the
+ area of a geodesic polygon given its vertices.
+ .
+Here, for example, is inverse.c
+\include inverse.c
+To compile, link, and run this, you would typically use \verbatim
+cc -o inverse inverse.c geodesic.c -lm
+echo 30 0 29.5 179.5 | ./inverse \endverbatim
+These sample programs can also be built with the supplied cmake file,
+CMakeLists.txt, as follows \verbatim
+mkdir BUILD
+cd BUILD
+cmake ..
+make
+echo 30 0 29.5 179.5 | ./inverse \endverbatim
+
+Alternatively, if you have proj.4 installed, you can compile and link
+with \verbatim
+cc -c inverse.c
+cc -o inverse inverse.o -lproj
+echo 30 0 29.5 179.5 | ./inverse \endverbatim
+If proj.4 is installed, e.g., in /usr/local, you might have to use
+\verbatim
+cc -c -I/usr/local/include inverse.c
+cc -o inverse inverse.o -lproj -L/usr/local/lib -Wl,-rpath=/usr/local/lib
+echo 30 0 29.5 179.5 | ./inverse \endverbatim
+
+\section library Using the library
+
+- Put @verbatim
+ #include "geodesic.h" @endverbatim
+ in your source code. If you are using the library via proj.4, change
+ this to @verbatim
+ #include @endverbatim
+- make calls to the geodesic routines from your code. The interface to
+ the library is documented in geodesic.h.
+- Compile and link as described above.
+
+\section external External links
+
+- These algorithms are derived in C. F. F. Karney,
+
+ Algorithms for geodesics,
+ J. Geodesy 87, 43--55 (2013)
+ ( addenda).
+- A longer paper on geodesics: C. F. F. Karney,
+ Geodesics
+ on an ellipsoid of revolution,
+ Feb. 2011
+ (
+ errata).
+- The GeographicLib web site.
+- The C++ library.
+- The Java library.
+- The Fortran library.
+- Documentation on the C++ classes: GeographicLib::Geodesic,
+ GeographicLib::GeodesicLine, GeographicLib::PolygonArea.
+- The section in the %GeographicLib documentation on geodesics: \ref
+ geodesic.
+-
+ An online geodesic bibliography.
+**********************************************************************/
diff --git a/gtsam/3rdparty/GeographicLib/doc/geodesic-for.dox b/gtsam/3rdparty/GeographicLib/doc/geodesic-for.dox
new file mode 100644
index 000000000..1ebc59860
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/geodesic-for.dox
@@ -0,0 +1,100 @@
+// -*- text -*-
+/**
+ * \file geodesic-for.dox
+ * \brief Documentation for geodesic routines implemented in Fortran
+ *
+ * Written by Charles Karney and licensed under the
+ * MIT/X11 License. For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+/**
+\mainpage Geodesic routines implemented in Fortran
+\author Charles F. F. Karney (charles@karney.com)
+\version 1.31
+
+\section abstract Abstract
+
+This is a Fortran implementation of the geodesic algorithms from GeographicLib. This is a
+self-contained library which makes it easy to do geodesic computations
+for an ellipsoid of revolution in a Fortran program. It is written in
+Fortran 77 (avoiding features which are now deprecated) and should
+compile correctly with just about any Fortran compiler.
+
+\section download Downloading the source
+
+The Fortran library is part of %GeographicLib which available for download at
+-
+ GeographicLib-1.31.tar.gz
+-
+ GeographicLib-1.31.zip
+.
+as either a compressed tar file (tar.gz) or a zip file. After unpacking
+the source, the Fortran library can be found in
+GeographicLib-1.31/legacy/Fortran. The library consists of the file
+geodesic.for.
+
+\section doc Library documentation
+
+The interface to the library is documented via doxygen in the source
+file. To access this, see geodesic.for.
+
+\section samples Sample programs
+
+Also included are 3 small test programs:
+ - geoddirect.for is a simple command line utility for solving the
+ direct geodesic problem;
+ - geodinverse.for is a simple command line utility for solving the
+ inverse geodesic problem;
+ - planimeter.for is a simple command line utility for computing the
+ area of a geodesic polygon given its vertices.
+ .
+Here, for example, is geodinverse.for
+\include geodinverse.for
+To compile, link, and run this, you would typically use \verbatim
+f95 -o geodinverse geodinverse.for geodesic.for
+echo 30 0 29.5 179.5 | ./geodinverse \endverbatim
+These sample programs can also be built with the supplied cmake file,
+CMakeLists.txt, as follows \verbatim
+mkdir BUILD
+cd BUILD
+cmake ..
+make
+echo 30 0 29.5 179.5 | ./geodinverse \endverbatim
+
+\section library Using the library
+
+- Optionall put @verbatim
+ include "geodesic.inc" @endverbatim
+ in declaration section of your subroutines.
+- make calls to the geodesic routines from your code. The interface to
+ the library is documented in geodesic.for.
+- Compile and link as described above.
+
+\section external External links
+
+- These algorithms are derived in C. F. F. Karney,
+
+ Algorithms for geodesics,
+ J. Geodesy 87, 43--55 (2013)
+ ( addenda).
+- A longer paper on geodesics: C. F. F. Karney,
+ Geodesics
+ on an ellipsoid of revolution,
+ Feb. 2011
+ (
+ errata).
+- The GeographicLib web site.
+- The C++ library.
+- The C library.
+- The Java library.
+- Documentation on the C++ classes: GeographicLib::Geodesic,
+ GeographicLib::GeodesicLine, GeographicLib::PolygonArea.
+- The section in the %GeographicLib documentation on geodesics: \ref
+ geodesic.
+-
+ An online geodesic bibliography.
+**********************************************************************/
+
+**********************************************************************/
diff --git a/gtsam/3rdparty/GeographicLib/doc/geodseries30.html b/gtsam/3rdparty/GeographicLib/doc/geodseries30.html
new file mode 100644
index 000000000..9305117b3
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/geodseries30.html
@@ -0,0 +1,1717 @@
+
+
+
+ Series for geodesic calculations
+
+
+
+ Series for geodesic calculations
+
+This extends the series given
+here to 30th order in the
+flattening. See
+
+
+ You will be redirected there. Click on the link to go there
+ directly.
+
+
+
+
+
diff --git a/gtsam/3rdparty/GeographicLib/doc/meridian-measures.png b/gtsam/3rdparty/GeographicLib/doc/meridian-measures.png
new file mode 100644
index 000000000..f18deae35
Binary files /dev/null and b/gtsam/3rdparty/GeographicLib/doc/meridian-measures.png differ
diff --git a/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/DMS.js b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/DMS.js
new file mode 100644
index 000000000..e2f339f01
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/DMS.js
@@ -0,0 +1,364 @@
+/**
+ * DMS.js
+ * Transcription of DMS.[ch]pp into JavaScript.
+ *
+ * See the documentation for the C++ class. The conversion is a literal
+ * conversion from C++.
+ *
+ * Copyright (c) Charles Karney (2011) and licensed
+ * under the MIT/X11 License. For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+GeographicLib.DMS = {};
+
+(function() {
+ var d = GeographicLib.DMS;
+ var m = GeographicLib.Math;
+ d.lookup = function(s, c) {
+ return s.indexOf(c.toUpperCase());
+ }
+ d.zerofill = function(s, n) {
+ return String("0000").substr(0, Math.max(0, Math.min(4, n-s.length))) +
+ s;
+ }
+ d.hemispheres_ = "SNWE";
+ d.signs_ = "-+";
+ d.digits_ = "0123456789";
+ d.dmsindicators_ = "D'\":";
+ // d.dmsindicatorsu_ = "\u00b0\u2032\u2033"; // Unicode variants
+ d.dmsindicatorsu_ = "\u00b0'\""; // Use degree symbol
+ d.components_ = ["degrees", "minutes", "seconds"];
+ d.NONE = 0;
+ d.LATITUDE = 1;
+ d.LONGITUDE = 2;
+ d.AZIMUTH = 3;
+ d.NUMBER = 4;
+ d.DEGREE = 0;
+ d.MINUTE = 1;
+ d.SECOND = 2;
+
+ // return val, ind
+ d.Decode = function(dms) {
+ var vals = {};
+ var errormsg = new String("");
+ var dmsa = dms;
+ dmsa = dmsa.replace(/\u00b0/g, 'd');
+ dmsa = dmsa.replace(/\u00ba/g, 'd');
+ dmsa = dmsa.replace(/\u2070/g, 'd');
+ dmsa = dmsa.replace(/\u02da/g, 'd');
+ dmsa = dmsa.replace(/\u2032/g, '\'');
+ dmsa = dmsa.replace(/\u00b4/g, '\'');
+ dmsa = dmsa.replace(/\u2019/g, '\'');
+ dmsa = dmsa.replace(/\u2033/g, '"');
+ dmsa = dmsa.replace(/\u201d/g, '"');
+ dmsa = dmsa.replace(/''/g, '"');
+ dmsa = dmsa.replace(/^\s+/, "");
+ dmsa = dmsa.replace(/\s+$/, "");
+ do { // Executed once (provides the ability to break)
+ var sign = 1;
+ var beg = 0, end = dmsa.length;
+ var ind1 = d.NONE;
+ var k = -1;
+ if (end > beg && (k = d.lookup(d.hemispheres_, dmsa.charAt(beg))) >= 0) {
+ ind1 = (k & 2) ? d.LONGITUDE : d.LATITUDE;
+ sign = (k & 1) ? 1 : -1;
+ ++beg;
+ }
+ if (end > beg &&
+ (k = d.lookup(d.hemispheres_, dmsa.charAt(end-1))) >= 0) {
+ if (k >= 0) {
+ if (ind1 != d.NONE) {
+ if (dmsa.charAt(beg - 1).toUpperCase() ==
+ dmsa.charAt(end - 1).toUpperCase())
+ errormsg = "Repeated hemisphere indicators " +
+ dmsa.charAt(beg - 1) + " in " +
+ dmsa.substr(beg - 1, end - beg + 1);
+ else
+ errormsg = "Contradictory hemisphere indicators " +
+ dmsa.charAt(beg - 1) + " and " + dmsa.charAt(end - 1) + " in " +
+ dmsa.substr(beg - 1, end - beg + 1);
+ break;
+ }
+ ind1 = (k & 2) ? d.LONGITUDE : d.LATITUDE;
+ sign = (k & 1) ? 1 : -1;
+ --end;
+ }
+ }
+ if (end > beg && (k = d.lookup(d.signs_, dmsa.charAt(beg))) >= 0) {
+ if (k >= 0) {
+ sign *= k ? 1 : -1;
+ ++beg;
+ }
+ }
+ if (end == beg) {
+ errormsg = "Empty or incomplete DMS string " + dmsa;
+ break;
+ }
+ var ipieces = [0, 0, 0];
+ var fpieces = [0, 0, 0];
+ var npiece = 0;
+ var icurrent = 0;
+ var fcurrent = 0;
+ var ncurrent = 0, p = beg;
+ var pointseen = false;
+ var digcount = 0;
+ var intcount = 0;
+ while (p < end) {
+ var x = dmsa.charAt(p++);
+ if ((k = d.lookup(d.digits_, x)) >= 0) {
+ ++ncurrent;
+ if (digcount > 0)
+ ++digcount; // Count of decimal digits
+ else {
+ icurrent = 10 * icurrent + k;
+ ++intcount;
+ }
+ } else if (x == '.') {
+ if (pointseen) {
+ errormsg = "Multiple decimal points in "
+ + dmsa.substr(beg, end - beg);
+ break;
+ }
+ pointseen = true;
+ digcount = 1;
+ } else if ((k = d.lookup(d.dmsindicators_, x)) >= 0) {
+ if (k >= 3) {
+ if (p == end) {
+ errormsg = "Illegal for : to appear at the end of " +
+ dmsa.substr(beg, end - beg);
+ break;
+ }
+ k = npiece;
+ }
+ if (k == npiece - 1) {
+ errormsg = "Repeated " + d.components_[k] +
+ " component in " + dmsa.substr(beg, end - beg);
+ break;
+ } else if (k < npiece) {
+ errormsg = d.components_[k] + " component follows "
+ + d.components_[npiece - 1] + " component in "
+ + dmsa.substr(beg, end - beg);
+ break;
+ }
+ if (ncurrent == 0) {
+ errormsg = "Missing numbers in " + d.components_[k] +
+ " component of " + dmsa.substr(beg, end - beg);
+ break;
+ }
+ if (digcount > 1) {
+ fcurrent = parseFloat(dmsa.substr(p - intcount - digcount - 1,
+ intcount + digcount));
+ icurrent = 0;
+ }
+ ipieces[k] = icurrent;
+ fpieces[k] = icurrent + fcurrent;
+ if (p < end) {
+ npiece = k + 1;
+ icurrent = fcurrent = 0;
+ ncurrent = digcount = intcount = 0;
+ }
+ } else if (d.lookup(d.signs_, x) >= 0) {
+ errormsg = "Internal sign in DMS string "
+ + dmsa.substr(beg, end - beg);
+ break;
+ } else {
+ errormsg = "Illegal character " + x + " in DMS string "
+ + dmsa.substr(beg, end - beg);
+ break;
+ }
+ }
+ if (errormsg.length)
+ break;
+ if (d.lookup(d.dmsindicators_, dmsa.charAt(p - 1)) < 0) {
+ if (npiece >= 3) {
+ errormsg = "Extra text following seconds in DMS string "
+ + dmsa.substr(beg, end - beg);
+ break;
+ }
+ if (ncurrent == 0) {
+ errormsg = "Missing numbers in trailing component of "
+ + dmsa.substr(beg, end - beg);
+ break;
+ }
+ if (digcount > 1) {
+ fcurrent = parseFloat(dmsa.substr(p - intcount - digcount,
+ intcount + digcount));
+ icurrent = 0;
+ }
+ ipieces[npiece] = icurrent;
+ fpieces[npiece] = icurrent + fcurrent;
+ }
+ if (pointseen && digcount == 0) {
+ errormsg = "Decimal point in non-terminal component of "
+ + dmsa.substr(beg, end - beg);
+ break;
+ }
+ // Note that we accept 59.999999... even though it rounds to 60.
+ if (ipieces[1] >= 60) {
+ errormsg = "Minutes " + fpieces[1] + " not in range [0, 60)";
+ break;
+ }
+ if (ipieces[2] >= 60) {
+ errormsg = "Seconds " + fpieces[2] + " not in range [0, 60)";
+ break;
+ }
+ vals.ind = ind1;
+ // Assume check on range of result is made by calling routine (which
+ // might be able to offer a better diagnostic).
+ vals.val = sign * (fpieces[0] + (fpieces[1] + fpieces[2] / 60) / 60);
+ return vals;
+ } while (false);
+ vals.val = d.NumMatch(dmsa);
+ if (vals.val == 0)
+ throw new Error(errormsg);
+ else
+ vals.ind = d.NONE;
+ return vals;
+ }
+
+ d.NumMatch = function(s) {
+ if (s.length < 3)
+ return 0;
+ var t = s.toUpperCase().replace(/0+$/,"");
+ var sign = t.charAt(0) == '-' ? -1 : 1;
+ var p0 = t.charAt(0) == '-' || t.charAt(0) == '+' ? 1 : 0;
+ var p1 = t.length - 1;
+ if (p1 + 1 < p0 + 3)
+ return 0;
+ // Strip off sign and trailing 0s
+ t = t.substr(p0, p1 + 1 - p0); // Length at least 3
+ if (t == "NAN" || t == "1.#QNAN" || t == "1.#SNAN" || t == "1.#IND" ||
+ t == "1.#R")
+ return sign * Number.NaN;
+ else if (t == "INF" || t == "1.#INF")
+ return sign * Number.POSITIVE_INFINITY;
+ return 0;
+ }
+
+ // return lat, lon
+ d.DecodeLatLon = function(stra, strb, swaplatlong) {
+ var vals = {};
+ if (!swaplatlong) swaplatlong = false;
+ var valsa = d.Decode(stra);
+ var valsb = d.Decode(strb);
+ var a = valsa.val, ia = valsa.ind;
+ var b = valsb.val, ib = valsb.ind;
+ if (ia == d.NONE && ib == d.NONE) {
+ // Default to lat, long unless swaplatlong
+ ia = swaplatlong ? d.LONGITUDE : d.LATITUDE;
+ ib = swaplatlong ? d.LATITUDE : d.LONGITUDE;
+ } else if (ia == d.NONE)
+ ia = d.LATITUDE + d.LONGITUDE - ib;
+ else if (ib == d.NONE)
+ ib = d.LATITUDE + d.LONGITUDE - ia;
+ if (ia == ib)
+ throw new Error("Both " + stra + " and "
+ + strb + " interpreted as "
+ + (ia == d.LATITUDE ? "latitudes" : "longitudes"));
+ var lat = ia == d.LATITUDE ? a : b, lon = ia == d.LATITUDE ? b : a;
+ if (Math.abs(lat) > 90)
+ throw new Error("Latitude " + lat + "d not in [-90d, 90d]");
+ if (lon < -540 || lon >= 540)
+ throw new Error("Latitude " + lon + "d not in [-540d, 540d)");
+ lon = m.AngNormalize(lon);
+ vals.lat = lat;
+ vals.lon = lon;
+ return vals;
+ }
+
+ d.DecodeAngle = function(angstr) {
+ var vals = d.Decode(angstr);
+ var ang = vals.val, ind = vals.ind;
+ if (ind != d.NONE)
+ throw new Error("Arc angle " + angstr
+ + " includes a hemisphere, N/E/W/S");
+ return ang;
+ }
+
+ d.DecodeAzimuth = function(azistr) {
+ var vals = d.Decode(azistr);
+ var azi = vals.val, ind = vals.ind;
+ if (ind == d.LATITUDE)
+ throw new Error("Azimuth " + azistr
+ + " has a latitude hemisphere, N/S");
+ if (azi < -540 || azi >= 540)
+ throw new Error("Azimuth " + azistr + " not in range [-540d, 540d)");
+ azi = m.AngNormalize(azi);
+ return azi;
+ }
+
+ d.Encode = function(angle, trailing, prec, ind) {
+ // Assume check on range of input angle has been made by calling
+ // routine (which might be able to offer a better diagnostic).
+ if (!ind) ind = d.NONE;
+ if (!isFinite(angle))
+ return angle < 0 ? String("-inf") :
+ (angle > 0 ? String("inf") : String("nan"));
+
+ // 15 - 2 * trailing = ceiling(log10(2^53/90/60^trailing)).
+ // This suffices to give full real precision for numbers in [-90,90]
+ prec = Math.min(15 - 2 * trailing, prec);
+ var scale = 1, i;
+ for (i = 0; i < trailing; ++i)
+ scale *= 60;
+ for (i = 0; i < prec; ++i)
+ scale *= 10;
+ if (ind == d.AZIMUTH)
+ angle -= Math.floor(angle/360) * 360;
+ var sign = angle < 0 ? -1 : 1;
+ angle *= sign;
+
+ // Break off integer part to preserve precision in manipulation of
+ // fractional part.
+ var
+ idegree = Math.floor(angle),
+ fdegree = Math.floor((angle - idegree) * scale + 0.5) / scale;
+ if (fdegree >= 1) {
+ idegree += 1;
+ fdegree -= 1;
+ }
+ var pieces = [fdegree, 0, 0];
+ for (i = 1; i <= trailing; ++i) {
+ var
+ ip = Math.floor(pieces[i - 1]),
+ fp = pieces[i - 1] - ip;
+ pieces[i] = fp * 60;
+ pieces[i - 1] = ip;
+ }
+ pieces[0] += idegree;
+ var s = new String("");
+ if (ind == d.NONE && sign < 0)
+ s += '-';
+ switch (trailing) {
+ case d.DEGREE:
+ s += d.zerofill(pieces[0].toFixed(prec),
+ ind == d.NONE ? 0 :
+ 1 + Math.min(ind, 2) + prec + (prec ? 1 : 0)) +
+ d.dmsindicatorsu_.charAt(0);
+ break;
+ default:
+ s += d.zerofill(pieces[0].toFixed(0),
+ ind == d.NONE ? 0 : 1 + Math.min(ind, 2)) +
+ d.dmsindicatorsu_.charAt(0);
+ switch (trailing) {
+ case d.MINUTE:
+ s += d.zerofill(pieces[1].toFixed(prec), 2 + prec + (prec ? 1 : 0)) +
+ d.dmsindicatorsu_.charAt(1);
+ break;
+ case d.SECOND:
+ s += d.zerofill(pieces[1].toFixed(0), 2) + d.dmsindicatorsu_.charAt(1);
+ s += d.zerofill(pieces[2].toFixed(prec), 2 + prec + (prec ? 1 : 0)) +
+ d.dmsindicatorsu_.charAt(2);
+ break;
+ default:
+ break;
+ }
+ }
+ if (ind != d.NONE && ind != d.AZIMUTH)
+ s += d.hemispheres_.charAt((ind == d.LATITUDE ? 0 : 2) +
+ (sign < 0 ? 0 : 1));
+ return s;
+ }
+
+})();
diff --git a/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/Geodesic.js b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/Geodesic.js
new file mode 100644
index 000000000..09d22593a
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/Geodesic.js
@@ -0,0 +1,1019 @@
+/**
+ * Geodesic.js
+ * Transcription of Geodesic.[ch]pp into JavaScript.
+ *
+ * See the documentation for the C++ class. The conversion is a literal
+ * conversion from C++.
+ *
+ * The algorithms are derived in
+ *
+ * Charles F. F. Karney,
+ * Algorithms for geodesics, J. Geodesy 87, 43-55 (2013);
+ * http://dx.doi.org/10.1007/s00190-012-0578-z
+ * Addenda: http://geographiclib.sf.net/geod-addenda.html
+ *
+ * Copyright (c) Charles Karney (2011-2013) and licensed
+ * under the MIT/X11 License. For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+// Load AFTER Math.js
+
+GeographicLib.Geodesic = {};
+GeographicLib.GeodesicLine = {};
+
+(function() {
+ var m = GeographicLib.Math;
+ var g = GeographicLib.Geodesic;
+ var l = GeographicLib.GeodesicLine;
+ g.GEOGRAPHICLIB_GEODESIC_ORDER = 6;
+ g.nA1_ = g.GEOGRAPHICLIB_GEODESIC_ORDER;
+ g.nC1_ = g.GEOGRAPHICLIB_GEODESIC_ORDER;
+ g.nC1p_ = g.GEOGRAPHICLIB_GEODESIC_ORDER;
+ g.nA2_ = g.GEOGRAPHICLIB_GEODESIC_ORDER;
+ g.nC2_ = g.GEOGRAPHICLIB_GEODESIC_ORDER;
+ g.nA3_ = g.GEOGRAPHICLIB_GEODESIC_ORDER;
+ g.nA3x_ = g.nA3_;
+ g.nC3_ = g.GEOGRAPHICLIB_GEODESIC_ORDER;
+ g.nC3x_ = (g.nC3_ * (g.nC3_ - 1)) / 2;
+ g.nC4_ = g.GEOGRAPHICLIB_GEODESIC_ORDER;
+ g.nC4x_ = (g.nC4_ * (g.nC4_ + 1)) / 2;
+ g.maxit1_ = 20;
+ g.maxit2_ = g.maxit1_ + m.digits + 10;
+ g.tiny_ = Math.sqrt(Number.MIN_VALUE);
+ g.tol0_ = m.epsilon;
+ g.tol1_ = 200 * g.tol0_;
+ g.tol2_ = Math.sqrt(g.tol0_);
+ g.tolb_ = g.tol0_ * g.tol1_;
+ g.xthresh_ = 1000 * g.tol2_;
+
+ g.CAP_NONE = 0;
+ g.CAP_C1 = 1<<0;
+ g.CAP_C1p = 1<<1;
+ g.CAP_C2 = 1<<2;
+ g.CAP_C3 = 1<<3;
+ g.CAP_C4 = 1<<4;
+ g.CAP_ALL = 0x1F;
+ g.OUT_ALL = 0x7F80;
+ g.NONE = 0;
+ g.LATITUDE = 1<<7 | g.CAP_NONE;
+ g.LONGITUDE = 1<<8 | g.CAP_C3;
+ g.AZIMUTH = 1<<9 | g.CAP_NONE;
+ g.DISTANCE = 1<<10 | g.CAP_C1;
+ g.DISTANCE_IN = 1<<11 | g.CAP_C1 | g.CAP_C1p;
+ g.REDUCEDLENGTH = 1<<12 | g.CAP_C1 | g.CAP_C2;
+ g.GEODESICSCALE = 1<<13 | g.CAP_C1 | g.CAP_C2;
+ g.AREA = 1<<14 | g.CAP_C4;
+ g.ALL = g.OUT_ALL| g.CAP_ALL;
+
+ g.SinCosSeries = function(sinp, sinx, cosx, c, n) {
+ // Evaluate
+ // y = sinp ? sum(c[i] * sin( 2*i * x), i, 1, n) :
+ // sum(c[i] * cos((2*i+1) * x), i, 0, n-1)
+ // using Clenshaw summation. N.B. c[0] is unused for sin series
+ // Approx operation count = (n + 5) mult and (2 * n + 2) add
+ var k = n + (sinp ? 1 : 0); // Point to one beyond last element
+ var
+ ar = 2 * (cosx - sinx) * (cosx + sinx), // 2 * cos(2 * x)
+ y0 = n & 1 ? c[--k] : 0, y1 = 0; // accumulators for sum
+ // Now n is even
+ n = Math.floor(n/2);
+ while (n--) {
+ // Unroll loop x 2, so accumulators return to their original role
+ y1 = ar * y0 - y1 + c[--k];
+ y0 = ar * y1 - y0 + c[--k];
+ }
+ return (sinp
+ ? 2 * sinx * cosx * y0 // sin(2 * x) * y0
+ : cosx * (y0 - y1)); // cos(x) * (y0 - y1)
+ }
+
+ g.AngRound = function(x) {
+ // The makes the smallest gap in x = 1/16 - nextafter(1/16, 0) = 1/2^57
+ // for reals = 0.7 pm on the earth if x is an angle in degrees. (This
+ // is about 1000 times more resolution than we get with angles around 90
+ // degrees.) We use this to avoid having to deal with near singular
+ // cases when x is non-zero but tiny (e.g., 1.0e-200).
+ var z = 1/16;
+ var y = Math.abs(x);
+ // The compiler mustn't "simplify" z - (z - y) to y
+ y = y < z ? z - (z - y) : y;
+ return x < 0 ? -y : y;
+ }
+ g.Astroid = function(x, y) {
+ // Solve k^4+2*k^3-(x^2+y^2-1)*k^2-2*y^2*k-y^2 = 0 for positive
+ // root k. This solution is adapted from Geocentric::Reverse.
+ var k;
+ var
+ p = m.sq(x),
+ q = m.sq(y),
+ r = (p + q - 1) / 6;
+ if ( !(q == 0 && r <= 0) ) {
+ var
+ // Avoid possible division by zero when r = 0 by multiplying
+ // equations for s and t by r^3 and r, resp.
+ S = p * q / 4, // S = r^3 * s
+ r2 = m.sq(r),
+ r3 = r * r2,
+ // The discrimant of the quadratic equation for T3. This is
+ // zero on the evolute curve p^(1/3)+q^(1/3) = 1
+ disc = S * (S + 2 * r3);
+ var u = r;
+ if (disc >= 0) {
+ var T3 = S + r3;
+ // Pick the sign on the sqrt to maximize abs(T3). This
+ // minimizes loss of precision due to cancellation. The
+ // result is unchanged because of the way the T is used
+ // in definition of u.
+ T3 += T3 < 0 ? -Math.sqrt(disc)
+ : Math.sqrt(disc); // T3 = (r * t)^3
+ // N.B. cbrt always returns the real root. cbrt(-8) = -2.
+ var T = m.cbrt(T3); // T = r * t
+ // T can be zero; but then r2 / T -> 0.
+ u += T + (T != 0 ? r2 / T : 0);
+ } else {
+ // T is complex, but the way u is defined the result is real.
+ var ang = Math.atan2(Math.sqrt(-disc), -(S + r3));
+ // There are three possible cube roots. We choose the
+ // root which avoids cancellation. Note that disc < 0
+ // implies that r < 0.
+ u += 2 * r * Math.cos(ang / 3);
+ }
+ var
+ v = Math.sqrt(m.sq(u) + q), // guaranteed positive
+ // Avoid loss of accuracy when u < 0.
+ uv = u < 0 ? q / (v - u) : u + v, // u+v, guaranteed positive
+ w = (uv - q) / (2 * v); // positive?
+ // Rearrange expression for k to avoid loss of accuracy due to
+ // subtraction. Division by 0 not possible because uv > 0, w >= 0.
+ k = uv / (Math.sqrt(uv + m.sq(w)) + w); // guaranteed positive
+ } else { // q == 0 && r <= 0
+ // y = 0 with |x| <= 1. Handle this case directly.
+ // for y small, positive root is k = abs(y)/sqrt(1-x^2)
+ k = 0;
+ }
+ return k;
+ }
+
+ g.A1m1f = function(eps) {
+ var
+ eps2 = m.sq(eps),
+ t = eps2*(eps2*(eps2+4)+64)/256;
+ return (t + eps) / (1 - eps);
+ }
+
+ g.C1f = function(eps, c) {
+ var
+ eps2 = m.sq(eps),
+ d = eps;
+ c[1] = d*((6-eps2)*eps2-16)/32;
+ d *= eps;
+ c[2] = d*((64-9*eps2)*eps2-128)/2048;
+ d *= eps;
+ c[3] = d*(9*eps2-16)/768;
+ d *= eps;
+ c[4] = d*(3*eps2-5)/512;
+ d *= eps;
+ c[5] = -7*d/1280;
+ d *= eps;
+ c[6] = -7*d/2048;
+ }
+
+ g.C1pf = function(eps, c) {
+ var
+ eps2 = m.sq(eps),
+ d = eps;
+ c[1] = d*(eps2*(205*eps2-432)+768)/1536;
+ d *= eps;
+ c[2] = d*(eps2*(4005*eps2-4736)+3840)/12288;
+ d *= eps;
+ c[3] = d*(116-225*eps2)/384;
+ d *= eps;
+ c[4] = d*(2695-7173*eps2)/7680;
+ d *= eps;
+ c[5] = 3467*d/7680;
+ d *= eps;
+ c[6] = 38081*d/61440;
+ }
+
+ g.A2m1f = function(eps) {
+ var
+ eps2 = m.sq(eps),
+ t = eps2*(eps2*(25*eps2+36)+64)/256;
+ return t * (1 - eps) - eps;
+ }
+
+ g.C2f = function(eps, c) {
+ var
+ eps2 = m.sq(eps),
+ d = eps;
+ c[1] = d*(eps2*(eps2+2)+16)/32;
+ d *= eps;
+ c[2] = d*(eps2*(35*eps2+64)+384)/2048;
+ d *= eps;
+ c[3] = d*(15*eps2+80)/768;
+ d *= eps;
+ c[4] = d*(7*eps2+35)/512;
+ d *= eps;
+ c[5] = 63*d/1280;
+ d *= eps;
+ c[6] = 77*d/2048;
+ }
+
+ g.Geodesic = function(a, f) {
+ this._a = a;
+ this._f = f <= 1 ? f : 1/f;
+ this._f1 = 1 - this._f;
+ this._e2 = this._f * (2 - this._f);
+ this._ep2 = this._e2 / m.sq(this._f1); // e2 / (1 - e2)
+ this._n = this._f / ( 2 - this._f);
+ this._b = this._a * this._f1;
+ // authalic radius squared
+ this._c2 = (m.sq(this._a) + m.sq(this._b) *
+ (this._e2 == 0 ? 1 :
+ (this._e2 > 0 ? m.atanh(Math.sqrt(this._e2)) :
+ Math.atan(Math.sqrt(-this._e2))) /
+ Math.sqrt(Math.abs(this._e2))))/2;
+ // The sig12 threshold for "really short". Using the auxiliary sphere
+ // solution with dnm computed at (bet1 + bet2) / 2, the relative error in
+ // the azimuth consistency check is sig12^2 * abs(f) * min(1, 1-f/2) / 2.
+ // (Error measured for 1/100 < b/a < 100 and abs(f) >= 1/1000. For a given
+ // f and sig12, the max error occurs for lines near the pole. If the old
+ // rule for computing dnm = (dn1 + dn2)/2 is used, then the error increases
+ // by a factor of 2.) Setting this equal to epsilon gives sig12 = etol2.
+ // Here 0.1 is a safety factor (error decreased by 100) and max(0.001,
+ // abs(f)) stops etol2 getting too large in the nearly spherical case.
+ this._etol2 = 0.1 * g.tol2_ /
+ Math.sqrt( Math.max(0.001, Math.abs(this._f)) *
+ Math.min(1.0, 1 - this._f/2) / 2 );
+ if (!(isFinite(this._a) && this._a > 0))
+ throw new Error("Major radius is not positive");
+ if (!(isFinite(this._b) && this._b > 0))
+ throw new Error("Minor radius is not positive");
+ this._A3x = new Array(g.nA3x_);
+ this._C3x = new Array(g.nC3x_);
+ this._C4x = new Array(g.nC4x_);
+ this.A3coeff();
+ this.C3coeff();
+ this.C4coeff();
+ }
+
+ g.Geodesic.prototype.A3coeff = function() {
+ var _n = this._n;
+ this._A3x[0] = 1;
+ this._A3x[1] = (_n-1)/2;
+ this._A3x[2] = (_n*(3*_n-1)-2)/8;
+ this._A3x[3] = ((-_n-3)*_n-1)/16;
+ this._A3x[4] = (-2*_n-3)/64;
+ this._A3x[5] = -3/128;
+ }
+
+ g.Geodesic.prototype.C3coeff = function() {
+ var _n = this._n;
+ this._C3x[0] = (1-_n)/4;
+ this._C3x[1] = (1-_n*_n)/8;
+ this._C3x[2] = ((3-_n)*_n+3)/64;
+ this._C3x[3] = (2*_n+5)/128;
+ this._C3x[4] = 3/128;
+ this._C3x[5] = ((_n-3)*_n+2)/32;
+ this._C3x[6] = ((-3*_n-2)*_n+3)/64;
+ this._C3x[7] = (_n+3)/128;
+ this._C3x[8] = 5/256;
+ this._C3x[9] = (_n*(5*_n-9)+5)/192;
+ this._C3x[10] = (9-10*_n)/384;
+ this._C3x[11] = 7/512;
+ this._C3x[12] = (7-14*_n)/512;
+ this._C3x[13] = 7/512;
+ this._C3x[14] = 21/2560;
+ }
+
+ g.Geodesic.prototype.C4coeff = function() {
+ var _n = this._n;
+ this._C4x[0] = (_n*(_n*(_n*(_n*(100*_n+208)+572)+3432)-12012)+30030)/45045;
+ this._C4x[1] = (_n*(_n*(_n*(64*_n+624)-4576)+6864)-3003)/15015;
+ this._C4x[2] = (_n*((14144-10656*_n)*_n-4576)-858)/45045;
+ this._C4x[3] = ((-224*_n-4784)*_n+1573)/45045;
+ this._C4x[4] = (1088*_n+156)/45045;
+ this._C4x[5] = 97/15015.0;
+ this._C4x[6] = (_n*(_n*((-64*_n-624)*_n+4576)-6864)+3003)/135135;
+ this._C4x[7] = (_n*(_n*(5952*_n-11648)+9152)-2574)/135135;
+ this._C4x[8] = (_n*(5792*_n+1040)-1287)/135135;
+ this._C4x[9] = (468-2944*_n)/135135;
+ this._C4x[10] = 1/9009.0;
+ this._C4x[11] = (_n*((4160-1440*_n)*_n-4576)+1716)/225225;
+ this._C4x[12] = ((4992-8448*_n)*_n-1144)/225225;
+ this._C4x[13] = (1856*_n-936)/225225;
+ this._C4x[14] = 8/10725.0;
+ this._C4x[15] = (_n*(3584*_n-3328)+1144)/315315;
+ this._C4x[16] = (1024*_n-208)/105105;
+ this._C4x[17] = -136/63063.0;
+ this._C4x[18] = (832-2560*_n)/405405;
+ this._C4x[19] = -128/135135.0;
+ this._C4x[20] = 128/99099.0;
+ }
+
+ g.Geodesic.prototype.A3f = function(eps) {
+ // Evaluate sum(_A3x[k] * eps^k, k, 0, nA3x_-1) by Horner's method
+ var v = 0;
+ for (var i = g.nA3x_; i; )
+ v = eps * v + this._A3x[--i];
+ return v;
+ }
+
+ g.Geodesic.prototype.C3f = function(eps, c) {
+ // Evaluate C3 coeffs by Horner's method
+ // Elements c[1] thru c[nC3_ - 1] are set
+ for (var j = g.nC3x_, k = g.nC3_ - 1; k; ) {
+ var t = 0;
+ for (var i = g.nC3_ - k; i; --i)
+ t = eps * t + this._C3x[--j];
+ c[k--] = t;
+ }
+
+ var mult = 1;
+ for (var k = 1; k < g.nC3_; ) {
+ mult *= eps;
+ c[k++] *= mult;
+ }
+ }
+
+ g.Geodesic.prototype.C4f = function(eps, c) {
+ // Evaluate C4 coeffs by Horner's method
+ // Elements c[0] thru c[nC4_ - 1] are set
+ for (var j = g.nC4x_, k = g.nC4_; k; ) {
+ var t = 0;
+ for (var i = g.nC4_ - k + 1; i; --i)
+ t = eps * t + this._C4x[--j];
+ c[--k] = t;
+ }
+
+ var mult = 1;
+ for (var k = 1; k < g.nC4_; ) {
+ mult *= eps;
+ c[k++] *= mult;
+ }
+ }
+
+ // return s12b, m12b, m0, M12, M21
+ g.Geodesic.prototype.Lengths = function(eps, sig12,
+ ssig1, csig1, dn1, ssig2, csig2, dn2,
+ cbet1, cbet2, scalep,
+ C1a, C2a) {
+ var vals = {};
+ // Return m12b = (reduced length)/_b; also calculate s12b =
+ // distance/_b, and m0 = coefficient of secular term in
+ // expression for reduced length.
+ g.C1f(eps, C1a);
+ g.C2f(eps, C2a);
+ var
+ A1m1 = g.A1m1f(eps),
+ AB1 = (1 + A1m1) * (g.SinCosSeries(true, ssig2, csig2, C1a, g.nC1_) -
+ g.SinCosSeries(true, ssig1, csig1, C1a, g.nC1_)),
+ A2m1 = g.A2m1f(eps),
+ AB2 = (1 + A2m1) * (g.SinCosSeries(true, ssig2, csig2, C2a, g.nC2_) -
+ g.SinCosSeries(true, ssig1, csig1, C2a, g.nC2_));
+ vals.m0 = A1m1 - A2m1;
+ var J12 = vals.m0 * sig12 + (AB1 - AB2);
+ // Missing a factor of _b.
+ // Add parens around (csig1 * ssig2) and (ssig1 * csig2) to
+ // ensure accurate cancellation in the case of coincident
+ // points.
+ vals.m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2)
+ - csig1 * csig2 * J12;
+ // Missing a factor of _b
+ vals.s12b = (1 + A1m1) * sig12 + AB1;
+ if (scalep) {
+ var csig12 = csig1 * csig2 + ssig1 * ssig2;
+ var t = this._ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
+ vals.M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
+ vals.M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
+ }
+ return vals;
+ }
+
+ // return sig12, salp1, calp1, salp2, calp2, dnm
+ g.Geodesic.prototype.InverseStart = function(sbet1, cbet1, dn1,
+ sbet2, cbet2, dn2, lam12,
+ C1a, C2a) {
+ // Return a starting point for Newton's method in salp1 and calp1
+ // (function value is -1). If Newton's method doesn't need to be
+ // used, return also salp2 and calp2 and function value is sig12.
+ // salp2, calp2 only updated if return val >= 0.
+ var
+ vals = {},
+ // bet12 = bet2 - bet1 in [0, pi); bet12a = bet2 + bet1 in (-pi, 0]
+ sbet12 = sbet2 * cbet1 - cbet2 * sbet1,
+ cbet12 = cbet2 * cbet1 + sbet2 * sbet1;
+ vals.sig12 = -1; // Return value
+ // Volatile declaration needed to fix inverse cases
+ // 88.202499451857 0 -88.202499451857 179.981022032992859592
+ // 89.262080389218 0 -89.262080389218 179.992207982775375662
+ // 89.333123580033 0 -89.333123580032997687 179.99295812360148422
+ // which otherwise fail with g++ 4.4.4 x86 -O3
+ var sbet12a = sbet2 * cbet1;
+ sbet12a += cbet2 * sbet1;
+
+ var shortline = cbet12 >= 0 && sbet12 < 0.5 && cbet2 * lam12 < 0.5;
+ var omg12 = lam12;
+ if (shortline) {
+ var sbetm2 = m.sq(sbet1 + sbet2);
+ // sin((bet1+bet2)/2)^2
+ // = (sbet1 + sbet2)^2 / ((sbet1 + sbet2)^2 + (cbet1 + cbet2)^2)
+ sbetm2 /= sbetm2 + m.sq(cbet1 + cbet2);
+ vals.dnm = Math.sqrt(1 + this._ep2 * sbetm2);
+ omg12 /= this._f1 * vals.dnm;
+ }
+ var somg12 = Math.sin(omg12), comg12 = Math.cos(omg12);
+
+ vals.salp1 = cbet2 * somg12;
+ vals.calp1 = comg12 >= 0 ?
+ sbet12 + cbet2 * sbet1 * m.sq(somg12) / (1 + comg12) :
+ sbet12a - cbet2 * sbet1 * m.sq(somg12) / (1 - comg12);
+
+ var
+ ssig12 = m.hypot(vals.salp1, vals.calp1),
+ csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12;
+
+ if (shortline && ssig12 < this._etol2) {
+ // really short lines
+ vals.salp2 = cbet1 * somg12;
+ vals.calp2 = sbet12 - cbet1 * sbet2 *
+ (comg12 >= 0 ? m.sq(somg12) / (1 + comg12) : 1 - comg12);
+ // SinCosNorm(vals.salp2, vals.calp2);
+ var t = m.hypot(vals.salp2, vals.calp2); vals.salp2 /= t; vals.calp2 /= t;
+ // Set return value
+ vals.sig12 = Math.atan2(ssig12, csig12);
+ } else if (Math.abs(this._n) > 0.1 || // Skip astroid calc if too eccentric
+ csig12 >= 0 ||
+ ssig12 >= 6 * Math.abs(this._n) * Math.PI * m.sq(cbet1)) {
+ // Nothing to do, zeroth order spherical approximation is OK
+ } else {
+ // Scale lam12 and bet2 to x, y coordinate system where antipodal
+ // point is at origin and singular point is at y = 0, x = -1.
+ var y, lamscale, betscale;
+ // Volatile declaration needed to fix inverse case
+ // 56.320923501171 0 -56.320923501171 179.664747671772880215
+ // which otherwise fails with g++ 4.4.4 x86 -O3
+ var x;
+ if (this._f >= 0) { // In fact f == 0 does not get here
+ // x = dlong, y = dlat
+ {
+ var
+ k2 = m.sq(sbet1) * this._ep2,
+ eps = k2 / (2 * (1 + Math.sqrt(1 + k2)) + k2);
+ lamscale = this._f * cbet1 * this.A3f(eps) * Math.PI;
+ }
+ betscale = lamscale * cbet1;
+
+ x = (lam12 - Math.PI) / lamscale;
+ y = sbet12a / betscale;
+ } else { // _f < 0
+ // x = dlat, y = dlong
+ var
+ cbet12a = cbet2 * cbet1 - sbet2 * sbet1,
+ bet12a = Math.atan2(sbet12a, cbet12a);
+ var m12b, m0;
+ // In the case of lon12 = 180, this repeats a calculation made
+ // in Inverse.
+ var nvals = this.Lengths(this._n, Math.PI + bet12a,
+ sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
+ cbet1, cbet2, false, C1a, C2a);
+ m12b = nvals.m12b; m0 = nvals.m0;
+ x = -1 + m12b / (cbet1 * cbet2 * m0 * Math.PI);
+ betscale = x < -0.01 ? sbet12a / x :
+ -this._f * m.sq(cbet1) * Math.PI;
+ lamscale = betscale / cbet1;
+ y = (lam12 - Math.PI) / lamscale;
+ }
+
+ if (y > -g.tol1_ && x > -1 - g.xthresh_) {
+ // strip near cut
+ if (this._f >= 0) {
+ vals.salp1 = Math.min(1, -x);
+ vals.calp1 = - Math.sqrt(1 - m.sq(vals.salp1));
+ } else {
+ vals.calp1 = Math.max(x > -g.tol1_ ? 0 : -1, x);
+ vals.salp1 = Math.sqrt(1 - m.sq(vals.calp1));
+ }
+ } else {
+ // Estimate alp1, by solving the astroid problem.
+ //
+ // Could estimate alpha1 = theta + pi/2, directly, i.e.,
+ // calp1 = y/k; salp1 = -x/(1+k); for _f >= 0
+ // calp1 = x/(1+k); salp1 = -y/k; for _f < 0 (need to check)
+ //
+ // However, it's better to estimate omg12 from astroid and use
+ // spherical formula to compute alp1. This reduces the mean number of
+ // Newton iterations for astroid cases from 2.24 (min 0, max 6) to 2.12
+ // (min 0 max 5). The changes in the number of iterations are as
+ // follows:
+ //
+ // change percent
+ // 1 5
+ // 0 78
+ // -1 16
+ // -2 0.6
+ // -3 0.04
+ // -4 0.002
+ //
+ // The histogram of iterations is (m = number of iterations estimating
+ // alp1 directly, n = number of iterations estimating via omg12, total
+ // number of trials = 148605):
+ //
+ // iter m n
+ // 0 148 186
+ // 1 13046 13845
+ // 2 93315 102225
+ // 3 36189 32341
+ // 4 5396 7
+ // 5 455 1
+ // 6 56 0
+ //
+ // Because omg12 is near pi, estimate work with omg12a = pi - omg12
+ var k = g.Astroid(x, y);
+ var
+ omg12a = lamscale * ( this._f >= 0 ? -x * k/(1 + k) : -y * (1 + k)/k );
+ somg12 = Math.sin(omg12a); comg12 = -Math.cos(omg12a);
+ // Update spherical estimate of alp1 using omg12 instead of
+ // lam12
+ vals.salp1 = cbet2 * somg12;
+ vals.calp1 = sbet12a -
+ cbet2 * sbet1 * m.sq(somg12) / (1 - comg12);
+ }
+ }
+ if (vals.salp1 > 0) { // Sanity check on starting guess
+ // SinCosNorm(vals.salp1, vals.calp1);
+ var t = m.hypot(vals.salp1, vals.calp1); vals.salp1 /= t; vals.calp1 /= t;
+ } else {
+ vals.salp1 = 1; vals.calp1 = 0;
+ }
+ return vals;
+ }
+
+ // return lam12, salp2, calp2, sig12, ssig1, csig1, ssig2, csig2, eps,
+ // domg12, dlam12,
+ g.Geodesic.prototype.Lambda12 = function(sbet1, cbet1, dn1, sbet2, cbet2, dn2,
+ salp1, calp1, diffp,
+ C1a, C2a, C3a) {
+ var vals = {};
+ if (sbet1 == 0 && calp1 == 0)
+ // Break degeneracy of equatorial line. This case has already been
+ // handled.
+ calp1 = -g.tiny_;
+
+ var
+ // sin(alp1) * cos(bet1) = sin(alp0)
+ salp0 = salp1 * cbet1,
+ calp0 = m.hypot(calp1, salp1 * sbet1); // calp0 > 0
+
+ var somg1, comg1, somg2, comg2, omg12;
+ // tan(bet1) = tan(sig1) * cos(alp1)
+ // tan(omg1) = sin(alp0) * tan(sig1) = tan(omg1)=tan(alp1)*sin(bet1)
+ vals.ssig1 = sbet1; somg1 = salp0 * sbet1;
+ vals.csig1 = comg1 = calp1 * cbet1;
+ // SinCosNorm(vals.ssig1, vals.csig1);
+ var t = m.hypot(vals.ssig1, vals.csig1); vals.ssig1 /= t; vals.csig1 /= t;
+ // SinCosNorm(somg1, comg1); -- don't need to normalize!
+
+ // Enforce symmetries in the case abs(bet2) = -bet1. Need to be careful
+ // about this case, since this can yield singularities in the Newton
+ // iteration.
+ // sin(alp2) * cos(bet2) = sin(alp0)
+ vals.salp2 = cbet2 != cbet1 ? salp0 / cbet2 : salp1;
+ // calp2 = sqrt(1 - sq(salp2))
+ // = sqrt(sq(calp0) - sq(sbet2)) / cbet2
+ // and subst for calp0 and rearrange to give (choose positive sqrt
+ // to give alp2 in [0, pi/2]).
+ vals.calp2 = cbet2 != cbet1 || Math.abs(sbet2) != -sbet1 ?
+ Math.sqrt(m.sq(calp1 * cbet1) + (cbet1 < -sbet1 ?
+ (cbet2 - cbet1) * (cbet1 + cbet2) :
+ (sbet1 - sbet2) * (sbet1 + sbet2)))
+ / cbet2 : Math.abs(calp1);
+ // tan(bet2) = tan(sig2) * cos(alp2)
+ // tan(omg2) = sin(alp0) * tan(sig2).
+ vals.ssig2 = sbet2; somg2 = salp0 * sbet2;
+ vals.csig2 = comg2 = vals.calp2 * cbet2;
+ // SinCosNorm(vals.ssig2, vals.csig2);
+ var t = m.hypot(vals.ssig2, vals.csig2); vals.ssig2 /= t; vals.csig2 /= t;
+ // SinCosNorm(somg2, comg2); -- don't need to normalize!
+
+ // sig12 = sig2 - sig1, limit to [0, pi]
+ vals.sig12 = Math.atan2(Math.max(vals.csig1 * vals.ssig2 -
+ vals.ssig1 * vals.csig2, 0),
+ vals.csig1 * vals.csig2 + vals.ssig1 * vals.ssig2);
+
+ // omg12 = omg2 - omg1, limit to [0, pi]
+ omg12 = Math.atan2(Math.max(comg1 * somg2 - somg1 * comg2, 0),
+ comg1 * comg2 + somg1 * somg2);
+ var B312, h0;
+ var k2 = m.sq(calp0) * this._ep2;
+ vals.eps = k2 / (2 * (1 + Math.sqrt(1 + k2)) + k2);
+ this.C3f(vals.eps, C3a);
+ B312 = (g.SinCosSeries(true, vals.ssig2, vals.csig2, C3a, g.nC3_-1) -
+ g.SinCosSeries(true, vals.ssig1, vals.csig1, C3a, g.nC3_-1));
+ h0 = -this._f * this.A3f(vals.eps);
+ vals.domg12 = salp0 * h0 * (vals.sig12 + B312);
+ vals.lam12 = omg12 + vals.domg12;
+
+ if (diffp) {
+ if (vals.calp2 == 0)
+ vals.dlam12 = - 2 * this._f1 * dn1 / sbet1;
+ else {
+ var nvals = this.Lengths(vals.eps, vals.sig12,
+ vals.ssig1, vals.csig1, dn1,
+ vals.ssig2, vals.csig2, dn2,
+ cbet1, cbet2, false, C1a, C2a);
+ vals.dlam12 = nvals.m12b;
+ vals.dlam12 *= this._f1 / (vals.calp2 * cbet2);
+ }
+ }
+ return vals;
+ }
+
+ // return a12, s12, azi1, azi2, m12, M12, M21, S12
+ g.Geodesic.prototype.GenInverse = function(lat1, lon1, lat2, lon2, outmask) {
+ var vals = {};
+ outmask &= g.OUT_ALL;
+ // Compute longitude difference (AngDiff does this carefully). Result is
+ // in [-180, 180] but -180 is only for west-going geodesics. 180 is for
+ // east-going and meridional geodesics.
+ var lon12 = m.AngDiff(m.AngNormalize(lon1), m.AngNormalize(lon2));
+ // If very close to being on the same half-meridian, then make it so.
+ lon12 = g.AngRound(lon12);
+ // Make longitude difference positive.
+ var lonsign = lon12 >= 0 ? 1 : -1;
+ lon12 *= lonsign;
+ // If really close to the equator, treat as on equator.
+ lat1 = g.AngRound(lat1);
+ lat2 = g.AngRound(lat2);
+ // Swap points so that point with higher (abs) latitude is point 1
+ var swapp = Math.abs(lat1) >= Math.abs(lat2) ? 1 : -1;
+ if (swapp < 0) {
+ lonsign *= -1;
+ var t = lat1;
+ lat1 = lat2;
+ lat2 = t;
+ // swap(lat1, lat2);
+ }
+ // Make lat1 <= 0
+ var latsign = lat1 < 0 ? 1 : -1;
+ lat1 *= latsign;
+ lat2 *= latsign;
+ // Now we have
+ //
+ // 0 <= lon12 <= 180
+ // -90 <= lat1 <= 0
+ // lat1 <= lat2 <= -lat1
+ //
+ // longsign, swapp, latsign register the transformation to bring the
+ // coordinates to this canonical form. In all cases, 1 means no change was
+ // made. We make these transformations so that there are few cases to
+ // check, e.g., on verifying quadrants in atan2. In addition, this
+ // enforces some symmetries in the results returned.
+
+ var phi, sbet1, cbet1, sbet2, cbet2, s12x, m12x;
+
+ phi = lat1 * m.degree;
+ // Ensure cbet1 = +epsilon at poles
+ sbet1 = this._f1 * Math.sin(phi);
+ cbet1 = lat1 == -90 ? g.tiny_ : Math.cos(phi);
+ // SinCosNorm(sbet1, cbet1);
+ var t = m.hypot(sbet1, cbet1); sbet1 /= t; cbet1 /= t;
+
+ phi = lat2 * m.degree;
+ // Ensure cbet2 = +epsilon at poles
+ sbet2 = this._f1 * Math.sin(phi);
+ cbet2 = Math.abs(lat2) == 90 ? g.tiny_ : Math.cos(phi);
+ // SinCosNorm(sbet2, cbet2);
+ var t = m.hypot(sbet2, cbet2); sbet2 /= t; cbet2 /= t;
+
+ // If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
+ // |bet1| - |bet2|. Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
+ // a better measure. This logic is used in assigning calp2 in Lambda12.
+ // Sometimes these quantities vanish and in that case we force bet2 = +/-
+ // bet1 exactly. An example where is is necessary is the inverse problem
+ // 48.522876735459 0 -48.52287673545898293 179.599720456223079643
+ // which failed with Visual Studio 10 (Release and Debug)
+
+ if (cbet1 < -sbet1) {
+ if (cbet2 == cbet1)
+ sbet2 = sbet2 < 0 ? sbet1 : -sbet1;
+ } else {
+ if (Math.abs(sbet2) == -sbet1)
+ cbet2 = cbet1;
+ }
+
+ var
+ dn1 = Math.sqrt(1 + this._ep2 * m.sq(sbet1)),
+ dn2 = Math.sqrt(1 + this._ep2 * m.sq(sbet2));
+
+ var
+ lam12 = lon12 * m.degree,
+ slam12 = lon12 == 180 ? 0 : Math.sin(lam12),
+ clam12 = Math.cos(lam12); // lon12 == 90 isn't interesting
+
+ var sig12, calp1, salp1, calp2, salp2;
+ // index zero elements of these arrays are unused
+ var
+ C1a = new Array(g.nC1_ + 1),
+ C2a = new Array(g.nC2_ + 1),
+ C3a = new Array(g.nC3_);
+
+ var meridian = lat1 == -90 || slam12 == 0;
+
+ if (meridian) {
+
+ // Endpoints are on a single full meridian, so the geodesic might
+ // lie on a meridian.
+
+ calp1 = clam12; salp1 = slam12; // Head to the target longitude
+ calp2 = 1; salp2 = 0; // At the target we're heading north
+
+ var
+ // tan(bet) = tan(sig) * cos(alp)
+ ssig1 = sbet1, csig1 = calp1 * cbet1,
+ ssig2 = sbet2, csig2 = calp2 * cbet2;
+
+ // sig12 = sig2 - sig1
+ sig12 = Math.atan2(Math.max(csig1 * ssig2 - ssig1 * csig2, 0),
+ csig1 * csig2 + ssig1 * ssig2);
+ {
+ var nvals = this.Lengths(this._n, sig12,
+ ssig1, csig1, dn1, ssig2, csig2, dn2,
+ cbet1, cbet2, (outmask & g.GEODESICSCALE) != 0,
+ C1a, C2a);
+ s12x = nvals.s12b;
+ m12x = nvals.m12b;
+ // Ignore m0
+ if ((outmask & g.GEODESICSCALE) != 0) {
+ vals.M12 = nvals.M12;
+ vals.M21 = nvals.M21;
+ }
+ }
+ // Add the check for sig12 since zero length geodesics might yield
+ // m12 < 0. Test case was
+ //
+ // echo 20.001 0 20.001 0 | Geod -i
+ //
+ // In fact, we will have sig12 > pi/2 for meridional geodesic
+ // which is not a shortest path.
+ if (sig12 < 1 || m12x >= 0) {
+ m12x *= this._b;
+ s12x *= this._b;
+ vals.a12 = sig12 / m.degree;
+ } else
+ // m12 < 0, i.e., prolate and too close to anti-podal
+ meridian = false;
+ }
+
+ var omg12;
+ if (!meridian &&
+ sbet1 == 0 && // and sbet2 == 0
+ // Mimic the way Lambda12 works with calp1 = 0
+ (this._f <= 0 || lam12 <= Math.PI - this._f * Math.PI)) {
+
+ // Geodesic runs along equator
+ calp1 = calp2 = 0; salp1 = salp2 = 1;
+ s12x = this._a * lam12;
+ sig12 = omg12 = lam12 / this._f1;
+ m12x = this._b * Math.sin(sig12);
+ if (outmask & g.GEODESICSCALE)
+ vals.M12 = vals.M21 = Math.cos(sig12);
+ vals.a12 = lon12 / this._f1;
+
+ } else if (!meridian) {
+
+ // Now point1 and point2 belong within a hemisphere bounded by a
+ // meridian and geodesic is neither meridional or equatorial.
+
+ // Figure a starting point for Newton's method
+ var nvals = this.InverseStart(sbet1, cbet1, dn1, sbet2, cbet2, dn2, lam12,
+ C1a, C2a);
+ sig12 = nvals.sig12;
+ salp1 = nvals.salp1;
+ calp1 = nvals.calp1;
+
+ if (sig12 >= 0) {
+ salp2 = nvals.salp2;
+ calp2 = nvals.calp2;
+ // Short lines (InverseStart sets salp2, calp2, dnm)
+
+ var dnm = nvals.dnm;
+ s12x = sig12 * this._b * dnm;
+ m12x = m.sq(dnm) * this._b * Math.sin(sig12 / dnm);
+ if (outmask & g.GEODESICSCALE)
+ vals.M12 = vals.M21 = Math.cos(sig12 / dnm);
+ vals.a12 = sig12 / m.degree;
+ omg12 = lam12 / (this._f1 * dnm);
+ } else {
+
+ // Newton's method. This is a straightforward solution of f(alp1) =
+ // lambda12(alp1) - lam12 = 0 with one wrinkle. f(alp) has exactly one
+ // root in the interval (0, pi) and its derivative is positive at the
+ // root. Thus f(alp) is positive for alp > alp1 and negative for alp <
+ // alp1. During the course of the iteration, a range (alp1a, alp1b) is
+ // maintained which brackets the root and with each evaluation of
+ // f(alp) the range is shrunk if possible. Newton's method is
+ // restarted whenever the derivative of f is negative (because the new
+ // value of alp1 is then further from the solution) or if the new
+ // estimate of alp1 lies outside (0,pi); in this case, the new starting
+ // guess is taken to be (alp1a + alp1b) / 2.
+ var ssig1, csig1, ssig2, csig2, eps;
+ var numit = 0;
+ // Bracketing range
+ var salp1a = g.tiny_, calp1a = 1, salp1b = g.tiny_, calp1b = -1;
+ for (var tripn = false, tripb = false; numit < g.maxit2_; ++numit) {
+ // the WGS84 test set: mean = 1.47, sd = 1.25, max = 16
+ // WGS84 and random input: mean = 2.85, sd = 0.60
+ var dv;
+ var nvals = this.Lambda12(sbet1, cbet1, dn1, sbet2, cbet2, dn2,
+ salp1, calp1, numit < g.maxit1_,
+ C1a, C2a, C3a);
+ var v = nvals.lam12 - lam12;
+ salp2 = nvals.salp2;
+ calp2 = nvals.calp2;
+ sig12 = nvals.sig12;
+ ssig1 = nvals.ssig1;
+ csig1 = nvals.csig1;
+ ssig2 = nvals.ssig2;
+ csig2 = nvals.csig2;
+ eps = nvals.eps;
+ omg12 = nvals.domg12;
+ dv = nvals.dlam12;
+
+ // 2 * tol0 is approximately 1 ulp for a number in [0, pi].
+ // Reversed test to allow escape with NaNs
+ if (tripb || !(Math.abs(v) >= (tripn ? 8 : 2) * g.tol0_))
+ break;
+ // Update bracketing values
+ if (v > 0 && (numit < g.maxit1_ || calp1/salp1 > calp1b/salp1b)) {
+ salp1b = salp1; calp1b = calp1;
+ } else if (v < 0 &&
+ (numit < g.maxit1_ || calp1/salp1 < calp1a/salp1a)) {
+ salp1a = salp1; calp1a = calp1;
+ }
+ if (numit < g.maxit1_ && dv > 0) {
+ var
+ dalp1 = -v/dv;
+ var
+ sdalp1 = Math.sin(dalp1), cdalp1 = Math.cos(dalp1),
+ nsalp1 = salp1 * cdalp1 + calp1 * sdalp1;
+ if (nsalp1 > 0 && Math.abs(dalp1) < Math.PI) {
+ calp1 = calp1 * cdalp1 - salp1 * sdalp1;
+ salp1 = Math.max(0, nsalp1);
+ // SinCosNorm(salp1, calp1);
+ var t = m.hypot(salp1, calp1); salp1 /= t; calp1 /= t;
+ // In some regimes we don't get quadratic convergence because
+ // slope -> 0. So use convergence conditions based on epsilon
+ // instead of sqrt(epsilon).
+ tripn = Math.abs(v) <= 16 * g.tol0_;
+ continue;
+ }
+ }
+ // Either dv was not postive or updated value was outside legal
+ // range. Use the midpoint of the bracket as the next estimate.
+ // This mechanism is not needed for the WGS84 ellipsoid, but it does
+ // catch problems with more eccentric ellipsoids. Its efficacy is
+ // such for the WGS84 test set with the starting guess set to alp1 =
+ // 90deg:
+ // the WGS84 test set: mean = 5.21, sd = 3.93, max = 24
+ // WGS84 and random input: mean = 4.74, sd = 0.99
+ salp1 = (salp1a + salp1b)/2;
+ calp1 = (calp1a + calp1b)/2;
+ // SinCosNorm(salp1, calp1);
+ var t = m.hypot(salp1, calp1); salp1 /= t; calp1 /= t;
+ tripn = false;
+ tripb = (Math.abs(salp1a - salp1) + (calp1a - calp1) < g.tolb_ ||
+ Math.abs(salp1 - salp1b) + (calp1 - calp1b) < g.tolb_);
+ }
+ {
+ var nvals = this.Lengths(eps, sig12,
+ ssig1, csig1, dn1, ssig2, csig2, dn2,
+ cbet1, cbet2,
+ (outmask & g.GEODESICSCALE) != 0,
+ C1a, C2a);
+ s12x = nvals.s12b;
+ m12x = nvals.m12b;
+ // Ignore m0
+ if ((outmask & g.GEODESICSCALE) != 0) {
+ vals.M12 = nvals.M12;
+ vals.M21 = nvals.M21;
+ }
+ }
+ m12x *= this._b;
+ s12x *= this._b;
+ vals.a12 = sig12 / m.degree;
+ omg12 = lam12 - omg12;
+ }
+ }
+
+ if (outmask & g.DISTANCE)
+ vals.s12 = 0 + s12x; // Convert -0 to 0
+
+ if (outmask & g.REDUCEDLENGTH)
+ vals.m12 = 0 + m12x; // Convert -0 to 0
+
+ if (outmask & g.AREA) {
+ var
+ // From Lambda12: sin(alp1) * cos(bet1) = sin(alp0)
+ salp0 = salp1 * cbet1,
+ calp0 = m.hypot(calp1, salp1 * sbet1); // calp0 > 0
+ var alp12;
+ if (calp0 != 0 && salp0 != 0) {
+ var
+ // From Lambda12: tan(bet) = tan(sig) * cos(alp)
+ ssig1 = sbet1, csig1 = calp1 * cbet1,
+ ssig2 = sbet2, csig2 = calp2 * cbet2,
+ k2 = m.sq(calp0) * this._ep2,
+ eps = k2 / (2 * (1 + Math.sqrt(1 + k2)) + k2);
+ // Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0).
+ A4 = m.sq(this._a) * calp0 * salp0 * this._e2;
+ // SinCosNorm(ssig1, csig1);
+ var t = m.hypot(ssig1, csig1); ssig1 /= t; csig1 /= t;
+ // SinCosNorm(ssig2, csig2);
+ var t = m.hypot(ssig2, csig2); ssig2 /= t; csig2 /= t;
+ var C4a = new Array(g.nC4_);
+ this.C4f(eps, C4a);
+ var
+ B41 = g.SinCosSeries(false, ssig1, csig1, C4a, g.nC4_),
+ B42 = g.SinCosSeries(false, ssig2, csig2, C4a, g.nC4_);
+ vals.S12 = A4 * (B42 - B41);
+ } else
+ // Avoid problems with indeterminate sig1, sig2 on equator
+ vals.S12 = 0;
+ if (!meridian &&
+ omg12 < 0.75 * Math.PI && // Long difference too big
+ sbet2 - sbet1 < 1.75) { // Lat difference too big
+ // Use tan(Gamma/2) = tan(omg12/2)
+ // * (tan(bet1/2)+tan(bet2/2))/(1+tan(bet1/2)*tan(bet2/2))
+ // with tan(x/2) = sin(x)/(1+cos(x))
+ var
+ somg12 = Math.sin(omg12), domg12 = 1 + Math.cos(omg12),
+ dbet1 = 1 + cbet1, dbet2 = 1 + cbet2;
+ alp12 = 2 * Math.atan2( somg12 * (sbet1*dbet2 + sbet2*dbet1),
+ domg12 * (sbet1*sbet2 + dbet1*dbet2) );
+ } else {
+ // alp12 = alp2 - alp1, used in atan2 so no need to normalize
+ var
+ salp12 = salp2 * calp1 - calp2 * salp1,
+ calp12 = calp2 * calp1 + salp2 * salp1;
+ // The right thing appears to happen if alp1 = +/-180 and alp2 = 0, viz
+ // salp12 = -0 and alp12 = -180. However this depends on the sign
+ // being attached to 0 correctly. The following ensures the correct
+ // behavior.
+ if (salp12 == 0 && calp12 < 0) {
+ salp12 = g.tiny_ * calp1;
+ calp12 = -1;
+ }
+ alp12 = Math.atan2(salp12, calp12);
+ }
+ vals.S12 += this._c2 * alp12;
+ vals.S12 *= swapp * lonsign * latsign;
+ // Convert -0 to 0
+ vals.S12 += 0;
+ }
+
+ // Convert calp, salp to azimuth accounting for lonsign, swapp, latsign.
+ if (swapp < 0) {
+ var t = salp1;
+ salp1 = salp2;
+ salp2 = t;
+ // swap(salp1, salp2);
+ var t = calp1;
+ calp1 = calp2;
+ calp2 = t;
+ // swap(calp1, calp2);
+ if (outmask & g.GEODESICSCALE) {
+ var t = vals.M12;
+ vals.M12 = vals.M21;
+ vals.M21 = t;
+ // swap(vals.M12, vals.M21);
+ }
+ }
+
+ salp1 *= swapp * lonsign; calp1 *= swapp * latsign;
+ salp2 *= swapp * lonsign; calp2 *= swapp * latsign;
+
+ if (outmask & g.AZIMUTH) {
+ // minus signs give range [-180, 180). 0- converts -0 to +0.
+ vals.azi1 = 0 - Math.atan2(-salp1, calp1) / m.degree;
+ vals.azi2 = 0 - Math.atan2(-salp2, calp2) / m.degree;
+ }
+
+ // Returned value in [0, 180]
+ return vals;
+ }
+
+ // return a12, lat2, lon2, azi2, s12, m12, M12, M21, S12
+ g.Geodesic.prototype.GenDirect = function (lat1, lon1, azi1,
+ arcmode, s12_a12, outmask) {
+ var line = new l.GeodesicLine
+ (this, lat1, lon1, azi1,
+ // Automatically supply DISTANCE_IN if necessary
+ outmask | (arcmode ? g.NONE : g.DISTANCE_IN));
+ return line.GenPosition(arcmode, s12_a12, outmask);
+ }
+
+ g.WGS84 = new g.Geodesic(GeographicLib.Constants.WGS84.a,
+ GeographicLib.Constants.WGS84.f);
+})();
diff --git a/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/GeodesicLine.js b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/GeodesicLine.js
new file mode 100644
index 000000000..b2df9c1f6
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/GeodesicLine.js
@@ -0,0 +1,294 @@
+/**
+ * GeodesicLine.js
+ * Transcription of GeodesicLine.[ch]pp into JavaScript.
+ *
+ * See the documentation for the C++ class. The conversion is a literal
+ * conversion from C++.
+ *
+ * The algorithms are derived in
+ *
+ * Charles F. F. Karney,
+ * Algorithms for geodesics, J. Geodesy 87, 43-55 (2013);
+ * http://dx.doi.org/10.1007/s00190-012-0578-z
+ * Addenda: http://geographiclib.sf.net/geod-addenda.html
+ *
+ * Copyright (c) Charles Karney (2011-2012) and licensed
+ * under the MIT/X11 License. For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+// Load AFTER GeographicLib/Math.js and GeographicLib/Geodesic.js
+
+(function() {
+ var g = GeographicLib.Geodesic;
+ var l = GeographicLib.GeodesicLine;
+ var m = GeographicLib.Math;
+
+ l.GeodesicLine = function(geod, lat1, lon1, azi1, caps) {
+ this._a = geod._a;
+ this._f = geod._f;
+ this._b = geod._b;
+ this._c2 = geod._c2;
+ this._f1 = geod._f1;
+ this._caps = !caps ? g.ALL : (caps | g.LATITUDE | g.AZIMUTH);
+
+ azi1 = g.AngRound(m.AngNormalize(azi1));
+ lon1 = m.AngNormalize(lon1);
+ this._lat1 = lat1;
+ this._lon1 = lon1;
+ this._azi1 = azi1;
+ // alp1 is in [0, pi]
+ var alp1 = azi1 * m.degree;
+ // Enforce sin(pi) == 0 and cos(pi/2) == 0. Better to face the ensuing
+ // problems directly than to skirt them.
+ this._salp1 = azi1 == -180 ? 0 : Math.sin(alp1);
+ this._calp1 = Math.abs(azi1) == 90 ? 0 : Math.cos(alp1);
+ var cbet1, sbet1, phi;
+ phi = lat1 * m.degree;
+ // Ensure cbet1 = +epsilon at poles
+ sbet1 = this._f1 * Math.sin(phi);
+ cbet1 = Math.abs(lat1) == 90 ? g.tiny_ : Math.cos(phi);
+ // SinCosNorm(sbet1, cbet1);
+ var t = m.hypot(sbet1, cbet1); sbet1 /= t; cbet1 /= t;
+ this._dn1 = Math.sqrt(1 + geod._ep2 * m.sq(sbet1));
+
+ // Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0),
+ this._salp0 = this._salp1 * cbet1; // alp0 in [0, pi/2 - |bet1|]
+ // Alt: calp0 = hypot(sbet1, calp1 * cbet1). The following
+ // is slightly better (consider the case salp1 = 0).
+ this._calp0 = m.hypot(this._calp1, this._salp1 * sbet1);
+ // Evaluate sig with tan(bet1) = tan(sig1) * cos(alp1).
+ // sig = 0 is nearest northward crossing of equator.
+ // With bet1 = 0, alp1 = pi/2, we have sig1 = 0 (equatorial line).
+ // With bet1 = pi/2, alp1 = -pi, sig1 = pi/2
+ // With bet1 = -pi/2, alp1 = 0 , sig1 = -pi/2
+ // Evaluate omg1 with tan(omg1) = sin(alp0) * tan(sig1).
+ // With alp0 in (0, pi/2], quadrants for sig and omg coincide.
+ // No atan2(0,0) ambiguity at poles since cbet1 = +epsilon.
+ // With alp0 = 0, omg1 = 0 for alp1 = 0, omg1 = pi for alp1 = pi.
+ this._ssig1 = sbet1; this._somg1 = this._salp0 * sbet1;
+ this._csig1 = this._comg1 =
+ sbet1 != 0 || this._calp1 != 0 ? cbet1 * this._calp1 : 1;
+ // SinCosNorm(this._ssig1, this._csig1); // sig1 in (-pi, pi]
+ var t = m.hypot(this._ssig1, this._csig1);
+ this._ssig1 /= t; this._csig1 /= t;
+ // SinCosNorm(this._somg1, this._comg1); -- don't need to normalize!
+
+ this._k2 = m.sq(this._calp0) * geod._ep2;
+ var eps = this._k2 / (2 * (1 + Math.sqrt(1 + this._k2)) + this._k2);
+
+ if (this._caps & g.CAP_C1) {
+ this._A1m1 = g.A1m1f(eps);
+ this._C1a = new Array(g.nC1_ + 1);
+ g.C1f(eps, this._C1a);
+ this._B11 = g.SinCosSeries(true, this._ssig1, this._csig1,
+ this._C1a, g.nC1_);
+ var s = Math.sin(this._B11), c = Math.cos(this._B11);
+ // tau1 = sig1 + B11
+ this._stau1 = this._ssig1 * c + this._csig1 * s;
+ this._ctau1 = this._csig1 * c - this._ssig1 * s;
+ // Not necessary because C1pa reverts C1a
+ // _B11 = -SinCosSeries(true, _stau1, _ctau1, _C1pa, nC1p_);
+ }
+
+ if (this._caps & g.CAP_C1p) {
+ this._C1pa = new Array(g.nC1p_ + 1),
+ g.C1pf(eps, this._C1pa);
+ }
+
+ if (this._caps & g.CAP_C2) {
+ this._A2m1 = g.A2m1f(eps);
+ this._C2a = new Array(g.nC2_ + 1);
+ g.C2f(eps, this._C2a);
+ this._B21 = g.SinCosSeries(true, this._ssig1, this._csig1,
+ this._C2a, g.nC2_);
+ }
+
+ if (this._caps & g.CAP_C3) {
+ this._C3a = new Array(g.nC3_);
+ geod.C3f(eps, this._C3a);
+ this._A3c = -this._f * this._salp0 * geod.A3f(eps);
+ this._B31 = g.SinCosSeries(true, this._ssig1, this._csig1,
+ this._C3a, g.nC3_-1);
+ }
+
+ if (this._caps & g.CAP_C4) {
+ this._C4a = new Array(g.nC4_); // all the elements of _C4a are used
+ geod.C4f(eps, this._C4a);
+ // Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0)
+ this._A4 = m.sq(this._a) * this._calp0 * this._salp0 * geod._e2;
+ this._B41 = g.SinCosSeries(false, this._ssig1, this._csig1,
+ this._C4a, g.nC4_);
+ }
+ }
+
+ // return a12, lat2, lon2, azi2, s12, m12, M12, M21, S12
+ l.GeodesicLine.prototype.GenPosition = function(arcmode, s12_a12,
+ outmask) {
+ var vals = {};
+ outmask &= this._caps & g.OUT_ALL;
+ if (!( arcmode || (this._caps & g.DISTANCE_IN & g.OUT_ALL) )) {
+ // Uninitialized or impossible distance calculation requested
+ vals.a12 = Number.NaN;
+ return vals;
+ }
+
+ // Avoid warning about uninitialized B12.
+ var sig12, ssig12, csig12, B12 = 0, AB1 = 0;
+ if (arcmode) {
+ // Interpret s12_a12 as spherical arc length
+ sig12 = s12_a12 * m.degree;
+ var s12a = Math.abs(s12_a12);
+ s12a -= 180 * Math.floor(s12a / 180);
+ ssig12 = s12a == 0 ? 0 : Math.sin(sig12);
+ csig12 = s12a == 90 ? 0 : Math.cos(sig12);
+ } else {
+ // Interpret s12_a12 as distance
+ var
+ tau12 = s12_a12 / (this._b * (1 + this._A1m1)),
+ s = Math.sin(tau12),
+ c = Math.cos(tau12);
+ // tau2 = tau1 + tau12
+ B12 = - g.SinCosSeries(true,
+ this._stau1 * c + this._ctau1 * s,
+ this._ctau1 * c - this._stau1 * s,
+ this._C1pa, g.nC1p_);
+ sig12 = tau12 - (B12 - this._B11);
+ ssig12 = Math.sin(sig12); csig12 = Math.cos(sig12);
+ if (Math.abs(this._f) > 0.01) {
+ // Reverted distance series is inaccurate for |f| > 1/100, so correct
+ // sig12 with 1 Newton iteration. The following table shows the
+ // approximate maximum error for a = WGS_a() and various f relative to
+ // GeodesicExact.
+ // erri = the error in the inverse solution (nm)
+ // errd = the error in the direct solution (series only) (nm)
+ // errda = the error in the direct solution (series + 1 Newton) (nm)
+ //
+ // f erri errd errda
+ // -1/5 12e6 1.2e9 69e6
+ // -1/10 123e3 12e6 765e3
+ // -1/20 1110 108e3 7155
+ // -1/50 18.63 200.9 27.12
+ // -1/100 18.63 23.78 23.37
+ // -1/150 18.63 21.05 20.26
+ // 1/150 22.35 24.73 25.83
+ // 1/100 22.35 25.03 25.31
+ // 1/50 29.80 231.9 30.44
+ // 1/20 5376 146e3 10e3
+ // 1/10 829e3 22e6 1.5e6
+ // 1/5 157e6 3.8e9 280e6
+ var
+ ssig2 = this._ssig1 * csig12 + this._csig1 * ssig12,
+ csig2 = this._csig1 * csig12 - this._ssig1 * ssig12;
+ B12 = g.SinCosSeries(true, ssig2, csig2, this._C1a, g.nC1_);
+ var serr = (1 + this._A1m1) * (sig12 + (B12 - this._B11)) -
+ s12_a12 / this._b;
+ sig12 = sig12 - serr / Math.sqrt(1 + this._k2 * m.sq(ssig2));
+ ssig12 = Math.sin(sig12); csig12 = Math.cos(sig12);
+ // Update B12 below
+ }
+ }
+
+ var omg12, lam12, lon12;
+ var ssig2, csig2, sbet2, cbet2, somg2, comg2, salp2, calp2;
+ // sig2 = sig1 + sig12
+ ssig2 = this._ssig1 * csig12 + this._csig1 * ssig12;
+ csig2 = this._csig1 * csig12 - this._ssig1 * ssig12;
+ var dn2 = Math.sqrt(1 + this._k2 * m.sq(ssig2));
+ if (outmask & (g.DISTANCE | g.REDUCEDLENGTH | g.GEODESICSCALE)) {
+ if (arcmode || Math.abs(this._f) > 0.01)
+ B12 = g.SinCosSeries(true, ssig2, csig2, this._C1a, g.nC1_);
+ AB1 = (1 + this._A1m1) * (B12 - this._B11);
+ }
+ // sin(bet2) = cos(alp0) * sin(sig2)
+ sbet2 = this._calp0 * ssig2;
+ // Alt: cbet2 = hypot(csig2, salp0 * ssig2);
+ cbet2 = m.hypot(this._salp0, this._calp0 * csig2);
+ if (cbet2 == 0)
+ // I.e., salp0 = 0, csig2 = 0. Break the degeneracy in this case
+ cbet2 = csig2 = g.tiny_;
+ // tan(omg2) = sin(alp0) * tan(sig2)
+ somg2 = this._salp0 * ssig2; comg2 = csig2; // No need to normalize
+ // tan(alp0) = cos(sig2)*tan(alp2)
+ salp2 = this._salp0; calp2 = this._calp0 * csig2; // No need to normalize
+ // omg12 = omg2 - omg1
+ omg12 = Math.atan2(somg2 * this._comg1 - comg2 * this._somg1,
+ comg2 * this._comg1 + somg2 * this._somg1);
+
+ if (outmask & g.DISTANCE)
+ vals.s12 = arcmode ? this._b * ((1 + this._A1m1) * sig12 + AB1) : s12_a12;
+
+ if (outmask & g.LONGITUDE) {
+ lam12 = omg12 + this._A3c *
+ ( sig12 + (g.SinCosSeries(true, ssig2, csig2, this._C3a, g.nC3_-1)
+ - this._B31));
+ lon12 = lam12 / m.degree;
+ // Use AngNormalize2 because longitude might have wrapped multiple times.
+ lon12 = m.AngNormalize2(lon12);
+ vals.lon2 = m.AngNormalize(this._lon1 + lon12);
+ }
+
+ if (outmask & g.LATITUDE)
+ vals.lat2 = Math.atan2(sbet2, this._f1 * cbet2) / m.degree;
+
+ if (outmask & g.AZIMUTH)
+ // minus signs give range [-180, 180). 0- converts -0 to +0.
+ vals.azi2 = 0 - Math.atan2(-salp2, calp2) / m.degree;
+
+ if (outmask & (g.REDUCEDLENGTH | g.GEODESICSCALE)) {
+ var
+ B22 = g.SinCosSeries(true, ssig2, csig2, this._C2a, g.nC2_),
+ AB2 = (1 + this._A2m1) * (B22 - this._B21),
+ J12 = (this._A1m1 - this._A2m1) * sig12 + (AB1 - AB2);
+ if (outmask & g.REDUCEDLENGTH)
+ // Add parens around (_csig1 * ssig2) and (_ssig1 * csig2) to ensure
+ // accurate cancellation in the case of coincident points.
+ vals.m12 = this._b * (( dn2 * (this._csig1 * ssig2) -
+ this._dn1 * (this._ssig1 * csig2))
+ - this._csig1 * csig2 * J12);
+ if (outmask & g.GEODESICSCALE) {
+ var t = this._k2 * (ssig2 - this._ssig1) * (ssig2 + this._ssig1) /
+ (this._dn1 + dn2);
+ vals.M12 = csig12 + (t * ssig2 - csig2 * J12) * this._ssig1 / this._dn1;
+ vals.M21 = csig12 - (t * this._ssig1 - this._csig1 * J12) * ssig2 / dn2;
+ }
+ }
+
+ if (outmask & g.AREA) {
+ var
+ B42 = g.SinCosSeries(false, ssig2, csig2, this._C4a, g.nC4_);
+ var salp12, calp12;
+ if (this._calp0 == 0 || this._salp0 == 0) {
+ // alp12 = alp2 - alp1, used in atan2 so no need to normalized
+ salp12 = salp2 * this._calp1 - calp2 * this._salp1;
+ calp12 = calp2 * this._calp1 + salp2 * this._salp1;
+ // The right thing appears to happen if alp1 = +/-180 and alp2 = 0, viz
+ // salp12 = -0 and alp12 = -180. However this depends on the sign being
+ // attached to 0 correctly. The following ensures the correct behavior.
+ if (salp12 == 0 && calp12 < 0) {
+ salp12 = g.tiny_ * this._calp1;
+ calp12 = -1;
+ }
+ } else {
+ // tan(alp) = tan(alp0) * sec(sig)
+ // tan(alp2-alp1) = (tan(alp2) -tan(alp1)) / (tan(alp2)*tan(alp1)+1)
+ // = calp0 * salp0 * (csig1-csig2) / (salp0^2 + calp0^2 * csig1*csig2)
+ // If csig12 > 0, write
+ // csig1 - csig2 = ssig12 * (csig1 * ssig12 / (1 + csig12) + ssig1)
+ // else
+ // csig1 - csig2 = csig1 * (1 - csig12) + ssig12 * ssig1
+ // No need to normalize
+ salp12 = this._calp0 * this._salp0 *
+ (csig12 <= 0 ? this._csig1 * (1 - csig12) + ssig12 * this._ssig1 :
+ ssig12 * (this._csig1 * ssig12 / (1 + csig12) + this._ssig1));
+ calp12 = m.sq(this._salp0) + m.sq(this._calp0) * this._csig1 * csig2;
+ }
+ vals.S12 = this._c2 * Math.atan2(salp12, calp12) +
+ this._A4 * (B42 - this._B41);
+ }
+
+ vals.a12 = arcmode ? s12_a12 : sig12 / m.degree;
+ return vals;
+ }
+
+})();
diff --git a/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/Interface.js b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/Interface.js
new file mode 100644
index 000000000..55a230888
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/Interface.js
@@ -0,0 +1,257 @@
+/**
+ * Interface.js
+ * JavaScript interface routines for the geodesic routines GeographicLib.
+ *
+ * This provides JavaScript-style interfaces to Math.js, Geodesic.js,
+ * GeodesicLine.js, and PolygonArea.js which, in turn, are rather
+ * literal translations of the following classes from GeographicLib:
+ * Math, Accumulator, Geodesic, GeodesicLine, PolygonArea. See the
+ * documentation for the C++ class for more information at
+ *
+ * http://geographiclib.sourceforge.net/html/annotated.html
+ *
+ * The algorithms are derived in
+ *
+ * Charles F. F. Karney,
+ * Algorithms for geodesics, J. Geodesy 87, 43-55 (2013);
+ * http://dx.doi.org/10.1007/s00190-012-0578-z
+ * Addenda: http://geographiclib.sf.net/geod-addenda.html
+ *
+ * Copyright (c) Charles Karney (2011) and licensed
+ * under the MIT/X11 License. For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************
+ * GeographicLib.Geodesic.WGS84.Inverse(lat1, lon1, lat2, lon2, outmask);
+ * GeographicLib.Geodesic.WGS84.Direct(lat1, lon1, azi1, s12, outmask);
+ *
+ * perform the basic geodesic calculations. These return an object with
+ * (some) of the following fields:
+ *
+ * lat1 latitude of point 1
+ * lon1 longitude of point 1
+ * azi1 azimuth of line at point 1
+ * lat2 latitude of point 2
+ * lon2 longitude of point 2
+ * azi2 azimuth of line at point 2
+ * s12 distance from 1 to 2
+ * a12 arc length on auxiliary sphere from 1 to 2
+ * m12 reduced length of geodesic
+ * M12 geodesic scale 2 relative to 1
+ * M21 geodesic scale 1 relative to 2
+ * S12 area between geodesic and equator
+ *
+ * outmask determines which fields get included and if outmask is
+ * omitted, then only the basic geodesic fields are computed. The mask
+ * is an or'ed combination of the following values
+ *
+ * GeographicLib.Geodesic.LATITUDE
+ * GeographicLib.Geodesic.LONGITUDE
+ * GeographicLib.Geodesic.AZIMUTH
+ * GeographicLib.Geodesic.DISTANCE
+ * GeographicLib.Geodesic.REDUCEDLENGTH
+ * GeographicLib.Geodesic.GEODESICSCALE
+ * GeographicLib.Geodesic.AREA
+ * GeographicLib.Geodesic.ALL
+ *
+ **********************************************************************
+ * GeographicLib.Geodesic.WGS84.InversePath(lat1, lon1, lat2, lon2, ds12, maxk);
+ * GeographicLib.Geodesic.WGS84.DirectPath(lat1, lon1, azi1, s12, ds12, maxk);
+ *
+ * splits a geodesic line into k equal pieces which are no longer than
+ * about ds12 (but k cannot exceed maxk, default 20), and returns an
+ * array of length k + 1 of objects with fields
+ *
+ * lat, lon, azi
+ *
+ **********************************************************************
+ * GeographicLib.Geodesic.Envelope(lat1, lon1, azi1, s12, k)
+ *
+ * return the geodesic circle of radius s12 centered on the point lat1,
+ * lon1. k equally spaced azimuths starting at azi1 are computed. This
+ * returns an array of k + 1 points with fields lat and lon (with the
+ * first and last points matching).
+ *
+ **********************************************************************
+ * GeographicLib.Geodesic.Envelope(lat1, lon1, k, ord);
+ *
+ * returns the ord'th order envelope for geodesics emanating from lat1,
+ * lon1. This is located approximately circumference * ord/2 from the
+ * point. Thus odd numbered envelopes are centered at the antipodal
+ * point and even number envelopes are centered on the point itself.
+ * This returns an array of k + 1 points with fields lat and lon (with
+ * the first and last points matching).
+ *
+ **********************************************************************
+ * GeographicLib.Geodesic.WGS84.Area(points, polyline);
+ *
+ * computes the area of a polygon with vertices given by an array
+ * points, each of whose elements contains lat and lon fields. The
+ * function returns an object with fields.
+ *
+ * number, perimeter, area
+ *
+ * There is no need to "close" the polygon. If polyline (default =
+ * false) is true, then the points denote a polyline and its length is
+ * returned as the perimeter (and the area is not calculated).
+ **********************************************************************/
+
+(function() {
+ var m = GeographicLib.Math;
+ var g = GeographicLib.Geodesic;
+ var l = GeographicLib.GeodesicLine;
+
+ g.Geodesic.CheckPosition = function(lat, lon) {
+ if (!(Math.abs(lat) <= 90))
+ throw new Error("latitude " + lat + " not in [-90, 90]");
+ if (!(lon >= -540 && lon < 540))
+ throw new Error("longitude " + lon + " not in [-540, 540)");
+ return m.AngNormalize(lon);
+ }
+
+ g.Geodesic.CheckAzimuth = function(azi) {
+ if (!(azi >= -540 && azi < 540))
+ throw new Error("longitude " + azi + " not in [-540, 540)");
+ return m.AngNormalize(azi);
+ }
+
+ g.Geodesic.CheckDistance = function(s) {
+ if (!(isFinite(s)))
+ throw new Error("distance " + s + " not a finite number");
+ }
+
+ g.Geodesic.prototype.Inverse = function(lat1, lon1, lat2, lon2, outmask) {
+ if (!outmask) outmask = g.DISTANCE | g.AZIMUTH;
+ lon1 = g.Geodesic.CheckPosition(lat1, lon1);
+ lon2 = g.Geodesic.CheckPosition(lat2, lon2);
+
+ var result = this.GenInverse(lat1, lon1, lat2, lon2, outmask);
+ result.lat1 = lat1; result.lon1 = lon1;
+ result.lat2 = lat2; result.lon2 = lon2;
+
+ return result;
+ }
+
+ g.Geodesic.prototype.Direct = function(lat1, lon1, azi1, s12, outmask) {
+ if (!outmask) outmask = g.LATITUDE | g.LONGITUDE | g.AZIMUTH;
+ lon1 = g.Geodesic.CheckPosition(lat1, lon1);
+ azi1 = g.Geodesic.CheckAzimuth(azi1);
+ g.Geodesic.CheckDistance(s12);
+
+ var result = this.GenDirect(lat1, lon1, azi1, false, s12, outmask);
+ result.lat1 = lat1; result.lon1 = lon1;
+ result.azi1 = azi1; result.s12 = s12;
+
+ return result;
+ }
+
+ g.Geodesic.prototype.InversePath =
+ function(lat1, lon1, lat2, lon2, ds12, maxk) {
+ var t = this.Inverse(lat1, lon1, lat2, lon2);
+ if (!maxk) maxk = 20;
+ if (!(ds12 > 0))
+ throw new Error("ds12 must be a positive number")
+ var
+ k = Math.max(1, Math.min(maxk, Math.ceil(t.s12/ds12))),
+ points = new Array(k + 1);
+ points[0] = {lat: t.lat1, lon: t.lon1, azi: t.azi1};
+ points[k] = {lat: t.lat2, lon: t.lon2, azi: t.azi2};
+ if (k > 1) {
+ var line = new l.GeodesicLine(this, t.lat1, t.lon1, t.azi1,
+ g.LATITUDE | g.LONGITUDE | g.AZIMUTH),
+ da12 = t.a12/k;
+ var vals;
+ for (var i = 1; i < k; ++i) {
+ vals =
+ line.GenPosition(true, i * da12, g.LATITUDE | g.LONGITUDE | g.AZIMUTH);
+ points[i] = {lat: vals.lat2, lon: vals.lon2, azi: vals.azi2};
+ }
+ }
+ return points;
+ }
+
+ g.Geodesic.prototype.DirectPath =
+ function(lat1, lon1, azi1, s12, ds12, maxk) {
+ var t = this.Direct(lat1, lon1, azi1, s12);
+ if (!maxk) maxk = 20;
+ if (!(ds12 > 0))
+ throw new Error("ds12 must be a positive number")
+ var
+ k = Math.max(1, Math.min(maxk, Math.ceil(Math.abs(t.s12)/ds12))),
+ points = new Array(k + 1);
+ points[0] = {lat: t.lat1, lon: t.lon1, azi: t.azi1};
+ points[k] = {lat: t.lat2, lon: t.lon2, azi: t.azi2};
+ if (k > 1) {
+ var line = new l.GeodesicLine(this, t.lat1, t.lon1, t.azi1,
+ g.LATITUDE | g.LONGITUDE | g.AZIMUTH),
+ da12 = t.a12/k;
+ var vals;
+ for (var i = 1; i < k; ++i) {
+ vals =
+ line.GenPosition(true, i * da12, g.LATITUDE | g.LONGITUDE | g.AZIMUTH);
+ points[i] = {lat: vals.lat2, lon: vals.lon2, azi: vals.azi2};
+ }
+ }
+ return points;
+ }
+
+ g.Geodesic.prototype.Circle = function(lat1, lon1, azi1, s12, k) {
+ if (!(Math.abs(lat1) <= 90))
+ throw new Error("lat1 must be in [-90, 90]");
+ if (!(lon1 >= -540 && lon1 < 540))
+ throw new Error("lon1 must be in [-540, 540)");
+ if (!(azi1 >= -540 && azi1 < 540))
+ throw new Error("azi1 must be in [-540, 540)");
+ if (!(isFinite(s12)))
+ throw new Error("s12 must be a finite number");
+ lon1 = m.AngNormalize(lon1);
+ azi1 = m.AngNormalize(azi1);
+ if (!k || k < 4) k = 24;
+ var points = new Array(k + 1);
+ var vals;
+ for (var i = 0; i <= k; ++i) {
+ var azi1a = azi1 + (k - i) * 360 / k; // Traverse circle counter-clocwise
+ if (azi1a >= 180) azi1a -= 360;
+ vals =
+ this.GenDirect(lat1, lon1, azi1a, false, s12, g.LATITUDE | g.LONGITUDE);
+ points[i] = {lat: vals.lat2, lon: vals.lon2};
+ }
+ return points;
+ }
+
+ g.Geodesic.prototype.Envelope = function(lat1, lon1, k, ord) {
+ if (!(Math.abs(lat1) <= 90))
+ throw new Error("lat1 must be in [-90, 90]");
+ if (!(lon1 >= -540 && lon1 < 540))
+ throw new Error("lon1 must be in [-540, 540)");
+ lon1 = m.AngNormalize(lon1);
+ if (!k || k < 4) k = 24;
+ if (!ord) ord = 1;
+ var points = new Array(k + 1);
+ var vals, line, s12, j;
+ for (var i = 0; i <= k; ++i) {
+ var azi1 = -180 + i * 360 / k;
+ line = new l.GeodesicLine(this, lat1, lon1, azi1,
+ g.LATITUDE | g.LONGITUDE | g.DISTANCE_IN |
+ g.DISTANCE | g.REDUCEDLENGTH | g.GEODESICSCALE);
+ vals = line.GenPosition(true, 180 * ord,
+ g.DISTANCE | g.REDUCEDLENGTH | g.GEODESICSCALE);
+ j = 0;
+ while (true) {
+ // Solve m12(s12) = 0 by Newton's method using dm12/ds12 = M21
+ s12 = vals.s12 - vals.m12/vals.M21;
+ if (Math.abs(vals.m12) < line._a * g.tol2_ * 0.1 || ++j > 10)
+ break;
+ vals = line.GenPosition(false, s12,
+ g.DISTANCE | g.REDUCEDLENGTH | g.GEODESICSCALE);
+ }
+ vals = line.GenPosition(false, s12, g.LATITUDE | g.LONGITUDE);
+ points[i] = {lat: vals.lat2, lon: vals.lon2};
+ }
+ return points;
+ }
+
+ g.Geodesic.prototype.Area = function(points, polyline) {
+ return GeographicLib.PolygonArea.Area(this, points, polyline);
+ }
+
+})();
diff --git a/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/Math.js b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/Math.js
new file mode 100644
index 000000000..c13dd2c93
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/Math.js
@@ -0,0 +1,172 @@
+/**
+ * Math.js
+ * Transcription of Math.hpp, Constants.hpp, and Accumulator.hpp into
+ * JavaScript.
+ *
+ * Copyright (c) Charles Karney (2011) and licensed
+ * under the MIT/X11 License. For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+var GeographicLib; if (!GeographicLib) GeographicLib = {};
+
+GeographicLib.Math = {};
+
+GeographicLib.Math.sq = function(x) { return x * x; }
+
+GeographicLib.Math.hypot = function(x, y) {
+ x = Math.abs(x);
+ y = Math.abs(y);
+ var a = Math.max(x, y), b = Math.min(x, y) / (a ? a : 1);
+ return a * Math.sqrt(1 + b * b);
+}
+
+GeographicLib.Math.cbrt = function(x) {
+ var y = Math.pow(Math.abs(x), 1/3);
+ return x < 0 ? -y : y;
+}
+
+GeographicLib.Math.log1p = function(x) {
+ var
+ y = 1 + x,
+ z = y - 1;
+ // Here's the explanation for this magic: y = 1 + z, exactly, and z
+ // approx x, thus log(y)/z (which is nearly constant near z = 0) returns
+ // a good approximation to the true log(1 + x)/x. The multiplication x *
+ // (log(y)/z) introduces little additional error.
+ return z == 0 ? x : x * Math.log(y) / z;
+}
+
+GeographicLib.Math.atanh = function(x) {
+ var y = Math.abs(x); // Enforce odd parity
+ y = GeographicLib.Math.log1p(2 * y/(1 - y))/2;
+ return x < 0 ? -y : y;
+}
+
+GeographicLib.Math.sum = function(u, v) {
+ var
+ s = u + v,
+ up = s - v,
+ vpp = s - up;
+ up -= u;
+ vpp -= v;
+ t = -(up + vpp);
+ // u + v = s + t
+ // = round(u + v) + t
+ return {s: s, t: t};
+}
+
+GeographicLib.Math.AngNormalize = function(x) {
+ // Place angle in [-180, 180). Assumes x is in [-540, 540).
+ return x >= 180 ? x - 360 : (x < -180 ? x + 360 : x);
+}
+
+GeographicLib.Math.AngNormalize2 = function(x) {
+ // Place arbitrary angle in [-180, 180).
+ return GeographicLib.Math.AngNormalize(x % 360);
+}
+
+GeographicLib.Math.AngDiff = function(x, y) {
+ // Compute y - x and reduce to [-180,180] accurately.
+ // This is the same logic as the Accumulator class uses.
+ var
+ d = y - x,
+ yp = d + x,
+ xpp = yp - d;
+ yp -= y;
+ xpp -= x;
+ var t = xpp - yp;
+ // y - x = d + t
+ // = round(y - x) + t
+ if ((d - 180) + t > 0) // y - x > 180
+ d -= 360; // exact
+ else if ((d + 180) + t <= 0) // y - x <= -180
+ d += 360; // exact
+ return d + t;
+}
+
+GeographicLib.Math.epsilon = Math.pow(0.5, 52);
+GeographicLib.Math.degree = Math.PI/180;
+GeographicLib.Math.digits = 53;
+
+GeographicLib.Constants = {};
+GeographicLib.Constants.WGS84 = { a: 6378137, f: 1/298.257223563 };
+
+GeographicLib.Accumulator = {};
+(function() {
+ a = GeographicLib.Accumulator;
+ var m = GeographicLib.Math;
+
+ a.Accumulator = function(y) {
+ this.Set(y);
+ }
+
+ a.Accumulator.prototype.Set = function(y) {
+ if (!y) y = 0;
+ if (y.constructor == a.Accumulator) {
+ this._s = y._s;
+ this._t = y._t;
+ } else {
+ this._s = y;
+ this._t = 0;
+ }
+ }
+
+ a.Accumulator.prototype.Add = function(y) {
+ // Here's Shewchuk's solution...
+ // Accumulate starting at least significant end
+ var u = m.sum(y, this._t);
+ var v = m.sum(u.s, this._s);
+ u = u.t;
+ this._s = v.s;
+ this._t = v.t;
+ // Start is _s, _t decreasing and non-adjacent. Sum is now (s + t + u)
+ // exactly with s, t, u non-adjacent and in decreasing order (except
+ // for possible zeros). The following code tries to normalize the
+ // result. Ideally, we want _s = round(s+t+u) and _u = round(s+t+u -
+ // _s). The follow does an approximate job (and maintains the
+ // decreasing non-adjacent property). Here are two "failures" using
+ // 3-bit floats:
+ //
+ // Case 1: _s is not equal to round(s+t+u) -- off by 1 ulp
+ // [12, -1] - 8 -> [4, 0, -1] -> [4, -1] = 3 should be [3, 0] = 3
+ //
+ // Case 2: _s+_t is not as close to s+t+u as it shold be
+ // [64, 5] + 4 -> [64, 8, 1] -> [64, 8] = 72 (off by 1)
+ // should be [80, -7] = 73 (exact)
+ //
+ // "Fixing" these problems is probably not worth the expense. The
+ // representation inevitably leads to small errors in the accumulated
+ // values. The additional errors illustrated here amount to 1 ulp of
+ // the less significant word during each addition to the Accumulator
+ // and an additional possible error of 1 ulp in the reported sum.
+ //
+ // Incidentally, the "ideal" representation described above is not
+ // canonical, because _s = round(_s + _t) may not be true. For
+ // example, with 3-bit floats:
+ //
+ // [128, 16] + 1 -> [160, -16] -- 160 = round(145).
+ // But [160, 0] - 16 -> [128, 16] -- 128 = round(144).
+ //
+ if (this._s == 0) // This implies t == 0,
+ this._s = u; // so result is u
+ else
+ this._t += u; // otherwise just accumulate u to t.
+ }
+
+ a.Accumulator.prototype.Sum = function(y) {
+ if (!y)
+ return this._s;
+ else {
+ var b = new a.Accumulator(this);
+ b.Add(y);
+ return b._s;
+ }
+ }
+
+ a.Accumulator.prototype.Negate = function() {
+ this._s *= -1;
+ this._t *= -1;
+ }
+
+})();
diff --git a/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/PolygonArea.js b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/PolygonArea.js
new file mode 100644
index 000000000..e1e07f608
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/scripts/GeographicLib/PolygonArea.js
@@ -0,0 +1,241 @@
+/**
+ * PolygonArea.js
+ * Transcription of PolygonArea.[ch]pp into JavaScript.
+ *
+ * See the documentation for the C++ class. The conversion is a literal
+ * conversion from C++.
+ *
+ * The algorithms are derived in
+ *
+ * Charles F. F. Karney,
+ * Algorithms for geodesics, J. Geodesy 87, 43-55 (2013);
+ * http://dx.doi.org/10.1007/s00190-012-0578-z
+ * Addenda: http://geographiclib.sf.net/geod-addenda.html
+ *
+ * Copyright (c) Charles Karney (2011-2013) and licensed
+ * under the MIT/X11 License. For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+// Load AFTER GeographicLib/Math.js and GeographicLib/Geodesic.js
+
+GeographicLib.PolygonArea = {};
+
+(function() {
+ var m = GeographicLib.Math;
+ var a = GeographicLib.Accumulator;
+ var g = GeographicLib.Geodesic;
+ var p = GeographicLib.PolygonArea;
+
+ p.transit = function(lon1, lon2) {
+ // Return 1 or -1 if crossing prime meridian in east or west direction.
+ // Otherwise return zero.
+ // Compute lon12 the same way as Geodesic::Inverse.
+ lon1 = m.AngNormalize(lon1);
+ lon2 = m.AngNormalize(lon2);
+ var lon12 = m.AngDiff(lon1, lon2);
+ var cross =
+ lon1 < 0 && lon2 >= 0 && lon12 > 0 ? 1 :
+ (lon2 < 0 && lon1 >= 0 && lon12 < 0 ? -1 : 0);
+ return cross;
+ }
+
+ p.PolygonArea = function(earth, polyline) {
+ this._earth = earth;
+ this._area0 = 4 * Math.PI * earth._c2;
+ this._polyline = !polyline ? false : polyline;
+ this._mask = g.LATITUDE | g.LONGITUDE | g.DISTANCE |
+ (this._polyline ? g.NONE : g.AREA);
+ if (!this._polyline)
+ this._areasum = new a.Accumulator(0);
+ this._perimetersum = new a.Accumulator(0);
+ this.Clear();
+ }
+
+ p.PolygonArea.prototype.Clear = function() {
+ this._num = 0;
+ this._crossings = 0;
+ if (!this._polyline)
+ this._areasum.Set(0);
+ this._perimetersum.Set(0);
+ this._lat0 = this._lon0 = this._lat1 = this._lon1 = Number.NaN;
+ }
+
+ p.PolygonArea.prototype.AddPoint = function(lat, lon) {
+ if (this._num == 0) {
+ this._lat0 = this._lat1 = lat;
+ this._lon0 = this._lon1 = lon;
+ } else {
+ var t = this._earth.Inverse(this._lat1, this._lon1, lat, lon, this._mask);
+ this._perimetersum.Add(t.s12);
+ if (!this._polyline) {
+ this._areasum.Add(t.S12);
+ this._crossings += p.transit(this._lon1, lon);
+ }
+ this._lat1 = lat;
+ this._lon1 = lon;
+ }
+ ++this._num;
+ }
+
+ p.PolygonArea.prototype.AddEdge = function(azi, s) {
+ if (this._num) {
+ var t = this._earth.Direct(this._lat1, this._lon1, azi, s, this._mask);
+ this._perimetersum.Add(s);
+ if (!this._polyline) {
+ this._areasum.Add(t.S12);
+ this._crossings += p.transit(this._lon1, t.lon2);
+ }
+ this._lat1 = t.lat2;
+ this._lon1 = t.lon2;
+ }
+ ++this._num;
+ }
+
+ // return number, perimeter, area
+ p.PolygonArea.prototype.Compute = function(reverse, sign) {
+ var vals = {number: this._num};
+ if (this._num < 2) {
+ vals.perimeter = 0;
+ if (!this._polyline)
+ vals.area = 0;
+ return vals;
+ }
+ if (this._polyline) {
+ vals.perimeter = this._perimetersum.Sum();
+ return vals;
+ }
+ var t = this._earth.Inverse(this._lat1, this._lon1, this._lat0, this._lon0,
+ this._mask);
+ vals.perimeter = this._perimetersum.Sum(t.s12);
+ var tempsum = new a.Accumulator(this._areasum);
+ tempsum.Add(t.S12);
+ var crossings = this._crossings + p.transit(this._lon1, this._lon0);
+ if (crossings & 1)
+ tempsum.Add( (tempsum.Sum() < 0 ? 1 : -1) * this._area0/2 );
+ // area is with the clockwise sense. If !reverse convert to
+ // counter-clockwise convention.
+ if (!reverse)
+ tempsum.Negate();
+ // If sign put area in (-area0/2, area0/2], else put area in [0, area0)
+ if (sign) {
+ if (tempsum.Sum() > this._area0/2)
+ tempsum.Add( -this._area0 );
+ else if (tempsum.Sum() <= -this._area0/2)
+ tempsum.Add( +this._area0 );
+ } else {
+ if (tempsum.Sum() >= this._area0)
+ tempsum.Add( -this._area0 );
+ else if (tempsum < 0)
+ tempsum.Add( -this._area0 );
+ }
+ vals.area = tempsum.Sum();
+ return vals;
+ }
+
+ // return number, perimeter, area
+ p.PolygonArea.prototype.TestPoint = function(lat, lon, reverse, sign) {
+ var vals = {number: this._num + 1};
+ if (this._num == 0) {
+ vals.perimeter = 0;
+ if (!this._polyline)
+ vals.area = 0;
+ return vals;
+ }
+ vals.perimeter = this._perimetersum.Sum();
+ var tempsum = this._polyline ? 0 : this._areasum.Sum();
+ var crossings = this._crossings;
+ var t;
+ for (var i = 0; i < (this._polyline ? 1 : 2); ++i) {
+ t = this._earth.Inverse
+ (i == 0 ? this._lat1 : lat, i == 0 ? this._lon1 : lon,
+ i != 0 ? this._lat0 : lat, i != 0 ? this._lon0 : lon,
+ this._mask);
+ vals.perimeter += t.s12;
+ if (!this._polyline) {
+ tempsum += t.S12;
+ crossings += p.transit(i == 0 ? this._lon1 : lon,
+ i != 0 ? this._lon0 : lon);
+ }
+ }
+
+ if (this._polyline)
+ return vals;
+
+ if (crossings & 1)
+ tempsum += (tempsum < 0 ? 1 : -1) * this._area0/2;
+ // area is with the clockwise sense. If !reverse convert to
+ // counter-clockwise convention.
+ if (!reverse)
+ tempsum *= -1;
+ // If sign put area in (-area0/2, area0/2], else put area in [0, area0)
+ if (sign) {
+ if (tempsum > this._area0/2)
+ tempsum -= this._area0;
+ else if (tempsum <= -this._area0/2)
+ tempsum += this._area0;
+ } else {
+ if (tempsum >= this._area0)
+ tempsum -= this._area0;
+ else if (tempsum < 0)
+ tempsum += this._area0;
+ }
+ vals.area = tempsum;
+ return vals;
+ }
+
+ // return number, perimeter, area
+ p.PolygonArea.prototype.TestEdge = function(azi, s, reverse, sign) {
+ var vals = {number: this._num ? this._num + 1 : 0};
+ if (this._num == 0)
+ return vals;
+ vals.perimeter = this._perimetersum.Sum() + s;
+ if (this._polyline)
+ return vals;
+
+ var tempsum = this._areasum.Sum();
+ var crossings = this._crossings;
+ var t;
+ t = this._earth.Direct(this._lat1, this._lon1, azi, s, this._mask);
+ tempsum += t.S12;
+ crossings += p.transit(this._lon1, t.lon2);
+ t = this._earth(t.lat2, t.lon2, this._lat0, this._lon0, this._mask);
+ perimeter += t.s12;
+ tempsum += t.S12;
+ crossings += p.transit(t.lon2, this._lon0);
+
+ if (crossings & 1)
+ tempsum += (tempsum < 0 ? 1 : -1) * this._area0/2;
+ // area is with the clockwise sense. If !reverse convert to
+ // counter-clockwise convention.
+ if (!reverse)
+ tempsum *= -1;
+ // If sign put area in (-area0/2, area0/2], else put area in [0, area0)
+ if (sign) {
+ if (tempsum > this._area0/2)
+ tempsum -= this._area0;
+ else if (tempsum <= -this._area0/2)
+ tempsum += this._area0;
+ } else {
+ if (tempsum >= this._area0)
+ tempsum -= this._area0;
+ else if (tempsum < 0)
+ tempsum += this._area0;
+ }
+ vals.area = tempsum;
+ return vals;
+ }
+
+ p.PolygonArea.prototype.CurrentPoint = function() {
+ var vals = {lat: this._lat1, lon: this._lon1};
+ return vals;
+ }
+
+ p.Area = function(earth, points, polyline) {
+ var poly = new p.PolygonArea(earth, polyline);
+ for (var i = 0; i < points.length; ++i)
+ poly.AddPoint(points[i].lat, points[i].lon);
+ return poly.Compute(false, true);
+ }
+
+})();
diff --git a/gtsam/3rdparty/GeographicLib/doc/scripts/geod-calc.html b/gtsam/3rdparty/GeographicLib/doc/scripts/geod-calc.html
new file mode 100644
index 000000000..a6e0b094b
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/doc/scripts/geod-calc.html
@@ -0,0 +1,471 @@
+
+
+
+ Geodesic calculations for an ellipsoid done right
+
+
+
+
+
+
+
+
+
Geodesic calculations for an ellipsoid done right
+
+
+ This page illustrates the geodesic routines available in
+ GeographicLib.
+ The C++ code has been converted to JavaScript so the calculations
+ are carried out on the client. The algorithms are considerably
+ more accurate than Vincenty's method, and offer more functionality
+ (an inverse method which never fails to converge, differential
+ properties of the geodesic, and the area under a geodesic). The
+ algorithms are derived in
+
+ This page just provides a basic interface. Enter latitudes,
+ longitudes, and azimuths as degrees and distances as meters using
+ spaces or commas as separators. (Angles may be entered as decimal
+ degrees or as degrees, minutes, and seconds, e.g. -20.51125,
+ 20°30′40.5″S, S20d30'40.5", or
+ -20:30:40.5.) The results are accurate to about
+ 15 nanometers (or 0.1 m2 per vertex for
+ areas). A slicker page where the geodesics are incorporated into
+ Google Maps is given here.
+
+ Geodesic lines, circles, envelopes in Google Maps (instructions)
+
+
+ The page allows you to draw
+ accurate ellipsoidal geodesics on Google Maps. You can specify the
+ geodesic in one of two forms:
+
+
+ The direct problem: specify a starting point, an
+ azimuth and a distance as lat1 lon1 azi1 s12 as degrees
+ and meters.
+
+ The inverse problem: specify the two end points
+ as lat1 lon1 lat2 lon2 as degrees; this finds the
+ shortest path between the two points.
+
+ (Angles may be entered as decimal degrees or as degrees, minutes,
+ and seconds, e.g. -20.51125, 20°30′40.5″S,
+ S20d30'40.5", or -20:30:40.5.) Click on the
+ corresponding "compute" button. The display then shows
+
+
The requested geodesic as a blue
+ line; the WGS84 ellipsoid model is used.
+
The geodesic circle as a green
+ curve; this shows the locus of points a
+ distance s12 from lat1, lon1.
+
The geodesic envelopes as red
+ curves; all the geodesics emanating from lat1,
+ lon1 are tangent to the envelopes (providing they are
+ extended far enough). The number of solutions to the inverse
+ problem changes depending on whether lat2, lon2 lies
+ inside the envelopes. For example, there are four (resp. two)
+ approximately hemispheroidal geodesics if this point lies
+ inside (resp. outside) the inner envelope (only one of which
+ is a shortest path).
+
+
+
+ The sample data has lat1, lon1 in Wellington, New
+ Zealand, lat2, lon2 in Salamanca, Spain, and s12
+ about 1.5 times the earth's circumference. Try clicking on the
+ "compute" button next to the "Direct:" input box when the page
+ first loads. You can navigate around the map using the normal
+ Google Map controls.
+
+
+ The precision of output for the geodesic is 0.1" or 1 m.
+ A text-only geodesic calculator based
+ on the same JavaScript library is also available; this calculator
+ solves the inverse and direct geodesic problems, computes
+ intermediate points on a geodesic, and finds the area of a
+ geodesic polygon; it allows you to specify the precision of the
+ output and choose between decimal degrees and degress, minutes,
+ and seconds.
+
+ The Javascipt code for computing the geodesic lines, circles, and
+ envelopes is part of
+ GeographicLib.
+ The algorithms are derived in
+
+
+ You will be redirected there. Click on the link to go there
+ directly.
+
+
+
+
+
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Accumulator.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Accumulator.cpp
new file mode 100644
index 000000000..fda88f606
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Accumulator.cpp
@@ -0,0 +1,99 @@
+/**
+ * \file NETGeographicLib/Accumulator.cpp
+ * \brief Implementation for NETGeographicLib::Accumulator class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/Accumulator.hpp"
+#include "Accumulator.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+//*****************************************************************************
+Accumulator::!Accumulator(void)
+{
+ if ( m_pAccumulator != NULL )
+ {
+ delete m_pAccumulator;
+ m_pAccumulator = NULL;
+ }
+}
+
+//*****************************************************************************
+Accumulator::Accumulator(void)
+{
+ try
+ {
+ m_pAccumulator = new GeographicLib::Accumulator();
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr("Failed to allocate memory for a GeogrpicLib::Accumulator");
+ }
+}
+
+//*****************************************************************************
+void Accumulator::Assign( double a )
+{
+ m_pAccumulator->operator=( a);
+}
+
+//*****************************************************************************
+double Accumulator::Result()
+{
+ return m_pAccumulator->operator()();
+}
+
+//*****************************************************************************
+void Accumulator::Sum( double a )
+{
+ m_pAccumulator->operator+=( a );
+}
+
+//*****************************************************************************
+void Accumulator::Multiply( int i )
+{
+ m_pAccumulator->operator*=( i );
+}
+
+//*****************************************************************************
+bool Accumulator::operator == ( Accumulator^ lhs, double a )
+{
+ return lhs->m_pAccumulator->operator==( a );
+}
+
+//*****************************************************************************
+bool Accumulator::operator != ( Accumulator^ lhs, double a )
+{
+ return lhs->m_pAccumulator->operator!=( a );
+}
+
+//*****************************************************************************
+bool Accumulator::operator < ( Accumulator^ lhs, double a )
+{
+ return lhs->m_pAccumulator->operator<( a );
+}
+
+//*****************************************************************************
+bool Accumulator::operator <= ( Accumulator^ lhs, double a )
+{
+ return lhs->m_pAccumulator->operator<=( a );
+}
+
+//*****************************************************************************
+bool Accumulator::operator > ( Accumulator^ lhs, double a )
+{
+ return lhs->m_pAccumulator->operator>( a );
+}
+
+//*****************************************************************************
+bool Accumulator::operator >= ( Accumulator^ lhs, double a )
+{
+ return lhs->m_pAccumulator->operator>=( a );
+}
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Accumulator.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Accumulator.h
new file mode 100644
index 000000000..825306f32
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Accumulator.h
@@ -0,0 +1,116 @@
+#pragma once
+/**
+ * \file NETGeographicLib/Accumulator.h
+ * \brief Header for NETGeographicLib::Accumulator class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+namespace NETGeographicLib
+{
+ /*!
+ \brief .NET wrapper for GeographicLib::Accumulator.
+
+ This class allows .NET applications to access GeographicLib::Accumulator.
+
+ This allow many numbers of floating point type \e double to be added together
+ with twice the normal precision. The effective
+ precision of the sum is 106 bits or about 32 decimal places.
+
+ The implementation follows J. R. Shewchuk,
+ Adaptive Precision
+ Floating-Point Arithmetic and Fast Robust Geometric Predicates,
+ Discrete & Computational Geometry 18(3) 305--363 (1997).
+
+ C# Example:
+ \include example-Accumulator.cs
+ Managed C++ Example:
+ \include example-Accumulator.cpp
+ Visual Basic Example:
+ \include example-Accumulator.vb
+
+ INTERFACE DIFFERENCES:
+ Since assignment operators (=,+=,-=,*=) are not supported in managed classes;
+ - the Assign() method replaces the = operator,
+ - the Sum() method replaces the += and -= operators, and
+ - the Multiply() method replaces the *= operator,
+
+ Use Result() instead of the () operator to obtain the summed value from the accumulator.
+ */
+ public ref class Accumulator
+ {
+ private:
+ // Pointer to the unmanaged GeographicLib::Accumulator.
+ GeographicLib::Accumulator* m_pAccumulator;
+ // The finalizer releases the unmanaged object when this class is destroyrd.
+ !Accumulator(void);
+ public:
+ //! \brief Constructor.
+ Accumulator(void);
+ //! \brief Destructor calls the finalizer.
+ ~Accumulator() { this->!Accumulator(); }
+ /*!
+ \brief Assigns a value to an accumulator.
+ \param[in] a The value to be assigned.
+ */
+ void Assign( double a );
+ //! \brief Returns the accumulated value.
+ double Result();
+ /*!
+ \brief Adds a value to the accumulator.
+ \param[in] a The value to be added.
+ */
+ void Sum( double a );
+ /*!
+ \brief Multiplication by an integer
+ \param[in] i The multiplier.
+ */
+ void Multiply( int i );
+ /*!
+ \brief Equality operator.
+ \param[in] lhs The accumulator.
+ \param[in] a The value to be compared to.
+ \return true if the accumulated value is equal to a.
+ */
+ static bool operator == ( Accumulator^ lhs, double a );
+ /*!
+ \brief Inequality operator.
+ \param[in] lhs The accumulator.
+ \param[in] a The value to be compared to.
+ \return true if the accumulated value is not equal to a.
+ */
+ static bool operator != ( Accumulator^ lhs, double a );
+ /*!
+ \brief Less than operator.
+ \param[in] lhs The accumulator.
+ \param[in] a The value to be compared to.
+ \return true if the accumulated value is less than a.
+ */
+ static bool operator < ( Accumulator^ lhs, double a );
+ /*!
+ \brief Less than or equal to operator.
+ \param[in] lhs The accumulator.
+ \param[in] a The value to be compared to.
+ \return true if the accumulated value is less than or equal to a.
+ */
+ static bool operator <= ( Accumulator^ lhs, double a );
+ /*!
+ \brief Greater than operator.
+ \param[in] lhs The accumulator.
+ \param[in] a The value to be compared to.
+ \return true if the accumulated value is greater than a.
+ */
+ static bool operator > ( Accumulator^ lhs, double a );
+ /*!
+ \brief Greater than or equal to operator.
+ \param[in] lhs The accumulator.
+ \param[in] a The value to be compared to.
+ \return true if the accumulated value is greater than or equal to a.
+ */
+ static bool operator >= ( Accumulator^ lhs, double a );
+ };
+} //namespace NETGeographicLib
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AlbersEqualArea.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AlbersEqualArea.cpp
new file mode 100644
index 000000000..87a3160e8
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AlbersEqualArea.cpp
@@ -0,0 +1,186 @@
+/**
+ * \file NETGeographicLib/AlbersEqualArea.cpp
+ * \brief Implementation for NETGeographicLib::AlbersEqualArea class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/AlbersEqualArea.hpp"
+#include "AlbersEqualArea.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+//*****************************************************************************
+AlbersEqualArea::!AlbersEqualArea()
+{
+ if ( m_pAlbersEqualArea != NULL )
+ {
+ delete m_pAlbersEqualArea;
+ m_pAlbersEqualArea = NULL;
+ }
+}
+
+//*****************************************************************************
+AlbersEqualArea::AlbersEqualArea( StandardTypes type )
+{
+ try
+ {
+ switch ( type )
+ {
+ case StandardTypes::CylindricalEqualArea:
+ m_pAlbersEqualArea = new GeographicLib::AlbersEqualArea( GeographicLib::AlbersEqualArea::CylindricalEqualArea );
+ break;
+ case StandardTypes::AzimuthalEqualAreaNorth:
+ m_pAlbersEqualArea = new GeographicLib::AlbersEqualArea( GeographicLib::AlbersEqualArea::AzimuthalEqualAreaNorth );
+ break;
+ case StandardTypes::AzimuthalEqualAreaSouth:
+ m_pAlbersEqualArea = new GeographicLib::AlbersEqualArea( GeographicLib::AlbersEqualArea::AzimuthalEqualAreaSouth );
+ break;
+ }
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( "Failed to allocate memory for a GeographicLib::AlbersEqualArea" );
+ }
+}
+
+//*****************************************************************************
+AlbersEqualArea::AlbersEqualArea(double a, double f, double stdlat1, double stdlat2, double k1)
+{
+ try
+ {
+ m_pAlbersEqualArea = new GeographicLib::AlbersEqualArea( a, f, stdlat1, stdlat2, k1 );
+ }
+ catch ( GeographicLib::GeographicErr err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( "Failed to allocate memory for a GeographicLib::AlbersEqualArea" );
+ }
+}
+
+//*****************************************************************************
+AlbersEqualArea::AlbersEqualArea(double a, double f, double stdlat, double k0)
+{
+ try
+ {
+ m_pAlbersEqualArea = new GeographicLib::AlbersEqualArea( a, f, stdlat, k0 );
+ }
+ catch ( GeographicLib::GeographicErr err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( "Failed to allocate memory for a GeographicLib::AlbersEqualArea" );
+ }
+}
+
+//*****************************************************************************
+AlbersEqualArea::AlbersEqualArea(double a, double f,
+ double sinlat1, double coslat1,
+ double sinlat2, double coslat2,
+ double k1)
+{
+ try
+ {
+ m_pAlbersEqualArea = new GeographicLib::AlbersEqualArea(
+ a, f, sinlat1, coslat1, sinlat2, coslat2, k1 );
+ }
+ catch ( GeographicLib::GeographicErr err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( "Failed to allocate memory for a GeographicLib::AlbersEqualArea" );
+ }
+}
+
+//*****************************************************************************
+void AlbersEqualArea::SetScale(double lat, double k)
+{
+ try
+ {
+ m_pAlbersEqualArea->SetScale( lat, k );
+ }
+ catch ( const std::exception& xcpt )
+ {
+ throw gcnew GeographicErr( xcpt.what() );
+ }
+}
+
+//*****************************************************************************
+void AlbersEqualArea::Forward(double lon0, double lat, double lon,
+ [System::Runtime::InteropServices::Out] double% x,
+ [System::Runtime::InteropServices::Out] double% y,
+ [System::Runtime::InteropServices::Out] double% gamma,
+ [System::Runtime::InteropServices::Out] double% k)
+{
+ double lx, ly, lgamma, lk;
+ m_pAlbersEqualArea->Forward( lon0, lat, lon, lx, ly, lgamma, lk );
+ x = lx;
+ y = ly;
+ gamma = lgamma;
+ k = lk;
+}
+
+//*****************************************************************************
+void AlbersEqualArea::Reverse(double lon0, double x, double y,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ [System::Runtime::InteropServices::Out] double% gamma,
+ [System::Runtime::InteropServices::Out] double% k)
+{
+ double llat, llon, lgamma, lk;
+ m_pAlbersEqualArea->Reverse( lon0, x, y, llat, llon, lgamma, lk );
+ lat = llat;
+ lon = llon;
+ gamma = lgamma;
+ k = lk;
+}
+
+//*****************************************************************************
+void AlbersEqualArea::Forward(double lon0, double lat, double lon,
+ [System::Runtime::InteropServices::Out] double% x,
+ [System::Runtime::InteropServices::Out] double% y)
+{
+ double lx, ly, lgamma, lk;
+ m_pAlbersEqualArea->Forward( lon0, lat, lon, lx, ly, lgamma, lk );
+ x = lx;
+ y = ly;
+}
+
+//*****************************************************************************
+void AlbersEqualArea::Reverse(double lon0, double x, double y,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon)
+{
+ double llat, llon, lgamma, lk;
+ m_pAlbersEqualArea->Reverse( lon0, x, y, llat, llon, lgamma, lk );
+ lat = llat;
+ lon = llon;
+}
+
+//*****************************************************************************
+double AlbersEqualArea::MajorRadius::get()
+{ return m_pAlbersEqualArea->MajorRadius(); }
+
+//*****************************************************************************
+double AlbersEqualArea::Flattening::get()
+{ return m_pAlbersEqualArea->Flattening(); }
+
+//*****************************************************************************
+double AlbersEqualArea::OriginLatitude::get()
+{ return m_pAlbersEqualArea->OriginLatitude(); }
+
+//*****************************************************************************
+double AlbersEqualArea::CentralScale::get()
+{ return m_pAlbersEqualArea->CentralScale(); }
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AlbersEqualArea.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AlbersEqualArea.h
new file mode 100644
index 000000000..c1105173a
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AlbersEqualArea.h
@@ -0,0 +1,269 @@
+#pragma once
+/**
+ * \file NETGeographicLib/AlbersEqualArea.h
+ * \brief Header for NETGeographicLib::AlbersEqualArea class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+
+namespace NETGeographicLib
+{
+ /**
+ * \brief .NET Wrapper for GeographicLib::AlbersEqualArea.
+ *
+ * This class allows .NET applications to access
+ * GeographicLib::AlbersEqualArea
+ *
+ * Implementation taken from the report,
+ * - J. P. Snyder,
+ * Map Projections: A
+ * Working Manual, USGS Professional Paper 1395 (1987),
+ * pp. 101--102.
+ *
+ * This is a implementation of the equations in Snyder except that divided
+ * differences will be [have been] used to transform the expressions into
+ * ones which may be evaluated accurately. [In this implementation, the
+ * projection correctly becomes the cylindrical equal area or the azimuthal
+ * equal area projection when the standard latitude is the equator or a
+ * pole.]
+ *
+ * The ellipsoid parameters, the standard parallels, and the scale on the
+ * standard parallels are set in the constructor. Internally, the case with
+ * two standard parallels is converted into a single standard parallel, the
+ * latitude of minimum azimuthal scale, with an azimuthal scale specified on
+ * this parallel. This latitude is also used as the latitude of origin which
+ * is returned by AlbersEqualArea::OriginLatitude. The azimuthal scale on
+ * the latitude of origin is given by AlbersEqualArea::CentralScale. The
+ * case with two standard parallels at opposite poles is singular and is
+ * disallowed. The central meridian (which is a trivial shift of the
+ * longitude) is specified as the \e lon0 argument of the
+ * AlbersEqualArea::Forward and AlbersEqualArea::Reverse functions.
+ * AlbersEqualArea::Forward and AlbersEqualArea::Reverse also return the
+ * meridian convergence, γ, and azimuthal scale, \e k. A small square
+ * aligned with the cardinal directions is projected to a rectangle with
+ * dimensions \e k (in the E-W direction) and 1/\e k (in the N-S direction).
+ * The E-W sides of the rectangle are oriented γ degrees
+ * counter-clockwise from the \e x axis. There is no provision in this class
+ * for specifying a false easting or false northing or a different latitude
+ * of origin.
+ *
+ * C# Example:
+ * \include example-AlbersEqualArea.cs
+ * Managed C++ Example:
+ * \include example-AlbersEqualArea.cpp
+ * Visual Basic Example:
+ * \include example-AlbersEqualArea.vb
+ *
+ * INTERFACE DIFFERENCES:
+ * A constructor has been provided that creates the standard projections.
+ *
+ * The MajorRadius, Flattening, OriginLatitude, and CentralScale functions
+ * are implemented as properties.
+ **********************************************************************/
+ public ref class AlbersEqualArea
+ {
+ private:
+ // pointer to the unmanaged GeographicLib::AlbersEqualArea
+ GeographicLib::AlbersEqualArea* m_pAlbersEqualArea;
+
+ // Frees the unmanaged m_pAlbersEqualArea when object is destroyed.
+ !AlbersEqualArea();
+ public:
+ /**
+ Standard AlbersEqualAreaProjections that assume the WGS84 ellipsoid.
+ *********************************************************************/
+ enum class StandardTypes
+ {
+ CylindricalEqualArea, //!< cylindrical equal area projection (stdlat = 0, and \e k0 = 1)
+ AzimuthalEqualAreaNorth, //!< Lambert azimuthal equal area projection (stdlat = 90°, and \e k0 = 1)
+ AzimuthalEqualAreaSouth //!< Lambert azimuthal equal area projection (stdlat = −90°, and \e k0 = 1)
+ };
+
+ //! \brief Destructor
+ ~AlbersEqualArea() { this->!AlbersEqualArea(); }
+
+ /**!
+ * Constructor for one of the standard types.
+ * @param[in] type The desired standard type.
+ **********************************************************************/
+ AlbersEqualArea( StandardTypes type );
+
+ /**
+ * Constructor with a single standard parallel.
+ *
+ * @param[in] a equatorial radius of ellipsoid (meters).
+ * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
+ * Negative \e f gives a prolate ellipsoid. If \e f > 1, set flattening
+ * to 1/\e f.
+ * @param[in] stdlat standard parallel (degrees), the circle of tangency.
+ * @param[in] k0 azimuthal scale on the standard parallel.
+ * @exception GeographicErr if \e a, (1 − \e f ) \e a, or \e k0 is
+ * not positive.
+ * @exception GeographicErr if \e stdlat is not in [−90°,
+ * 90°].
+ **********************************************************************/
+ AlbersEqualArea(double a, double f, double stdlat, double k0);
+
+ /**
+ * Constructor with two standard parallels.
+ *
+ * @param[in] a equatorial radius of ellipsoid (meters).
+ * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
+ * Negative \e f gives a prolate ellipsoid. If \e f > 1, set flattening
+ * to 1/\e f.
+ * @param[in] stdlat1 first standard parallel (degrees).
+ * @param[in] stdlat2 second standard parallel (degrees).
+ * @param[in] k1 azimuthal scale on the standard parallels.
+ * @exception GeographicErr if \e a, (1 − \e f ) \e a, or \e k1 is
+ * not positive.
+ * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
+ * [−90°, 90°], or if \e stdlat1 and \e stdlat2 are
+ * opposite poles.
+ **********************************************************************/
+ AlbersEqualArea(double a, double f, double stdlat1, double stdlat2, double k1);
+
+ /**
+ * Constructor with two standard parallels specified by sines and cosines.
+ *
+ * @param[in] a equatorial radius of ellipsoid (meters).
+ * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
+ * Negative \e f gives a prolate ellipsoid. If \e f > 1, set flattening
+ * to 1/\e f.
+ * @param[in] sinlat1 sine of first standard parallel.
+ * @param[in] coslat1 cosine of first standard parallel.
+ * @param[in] sinlat2 sine of second standard parallel.
+ * @param[in] coslat2 cosine of second standard parallel.
+ * @param[in] k1 azimuthal scale on the standard parallels.
+ * @exception GeographicErr if \e a, (1 − \e f ) \e a, or \e k1 is
+ * not positive.
+ * @exception GeographicErr if \e stdlat1 or \e stdlat2 is not in
+ * [−90°, 90°], or if \e stdlat1 and \e stdlat2 are
+ * opposite poles.
+ *
+ * This allows parallels close to the poles to be specified accurately.
+ * This routine computes the latitude of origin and the azimuthal scale at
+ * this latitude. If \e dlat = abs(\e lat2 − \e lat1) ≤ 160°,
+ * then the error in the latitude of origin is less than 4.5 ×
+ * 10−14d;.
+ **********************************************************************/
+ AlbersEqualArea(double a, double f,
+ double sinlat1, double coslat1,
+ double sinlat2, double coslat2,
+ double k1);
+
+ /**
+ * Set the azimuthal scale for the projection.
+ *
+ * @param[in] lat (degrees).
+ * @param[in] k azimuthal scale at latitude \e lat (default 1).
+ * @exception GeographicErr \e k is not positive.
+ * @exception GeographicErr if \e lat is not in (−90°,
+ * 90°).
+ *
+ * This allows a "latitude of conformality" to be specified.
+ **********************************************************************/
+ void SetScale(double lat, double k);
+
+ /**
+ * Forward projection, from geographic to Lambert conformal conic.
+ *
+ * @param[in] lon0 central meridian longitude (degrees).
+ * @param[in] lat latitude of point (degrees).
+ * @param[in] lon longitude of point (degrees).
+ * @param[out] x easting of point (meters).
+ * @param[out] y northing of point (meters).
+ * @param[out] gamma meridian convergence at point (degrees).
+ * @param[out] k azimuthal scale of projection at point; the radial
+ * scale is the 1/\e k.
+ *
+ * The latitude origin is given by AlbersEqualArea::LatitudeOrigin(). No
+ * false easting or northing is added and \e lat should be in the range
+ * [−90°, 90°]; \e lon and \e lon0 should be in the
+ * range [−540°, 540°). The values of \e x and \e y
+ * returned for points which project to infinity (i.e., one or both of the
+ * poles) will be large but finite.
+ **********************************************************************/
+ void Forward(double lon0, double lat, double lon,
+ [System::Runtime::InteropServices::Out] double% x,
+ [System::Runtime::InteropServices::Out] double% y,
+ [System::Runtime::InteropServices::Out] double% gamma,
+ [System::Runtime::InteropServices::Out] double% k);
+
+ /**
+ * Reverse projection, from Lambert conformal conic to geographic.
+ *
+ * @param[in] lon0 central meridian longitude (degrees).
+ * @param[in] x easting of point (meters).
+ * @param[in] y northing of point (meters).
+ * @param[out] lat latitude of point (degrees).
+ * @param[out] lon longitude of point (degrees).
+ * @param[out] gamma meridian convergence at point (degrees).
+ * @param[out] k azimuthal scale of projection at point; the radial
+ * scale is the 1/\e k.
+ *
+ * The latitude origin is given by AlbersEqualArea::LatitudeOrigin(). No
+ * false easting or northing is added. \e lon0 should be in the range
+ * [−540°, 540°). The value of \e lon returned is in
+ * the range [−180°, 180°). The value of \e lat
+ * returned is in the range [−90°, 90°]. If the
+ * input point is outside the legal projected space the nearest pole is
+ * returned.
+ **********************************************************************/
+ void Reverse(double lon0, double x, double y,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ [System::Runtime::InteropServices::Out] double% gamma,
+ [System::Runtime::InteropServices::Out] double% k);
+
+ /**
+ * AlbersEqualArea::Forward without returning the convergence and
+ * scale.
+ **********************************************************************/
+ void Forward(double lon0, double lat, double lon,
+ [System::Runtime::InteropServices::Out] double% x,
+ [System::Runtime::InteropServices::Out] double% y);
+
+ /**
+ * AlbersEqualArea::Reverse without returning the convergence and
+ * scale.
+ **********************************************************************/
+ void Reverse(double lon0, double x, double y,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon);
+
+ /** \name Inspector functions
+ **********************************************************************/
+ ///@{
+ /**
+ * @return \e a the equatorial radius of the ellipsoid (meters). This is
+ * the value used in the constructor.
+ **********************************************************************/
+ property double MajorRadius { double get(); }
+
+ /**
+ * @return \e f the flattening of the ellipsoid. This is the value used in
+ * the constructor.
+ **********************************************************************/
+ property double Flattening { double get(); }
+
+ /**
+ * @return latitude of the origin for the projection (degrees).
+ *
+ * This is the latitude of minimum azimuthal scale and equals the \e stdlat
+ * in the 1-parallel constructor and lies between \e stdlat1 and \e stdlat2
+ * in the 2-parallel constructors.
+ **********************************************************************/
+ property double OriginLatitude { double get(); }
+
+ /**
+ * @return central scale for the projection. This is the azimuthal scale
+ * on the latitude of origin.
+ **********************************************************************/
+ property double CentralScale { double get(); }
+ ///@}
+ };
+} // namespace NETGeographic
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AssemblyInfo.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AssemblyInfo.cpp
new file mode 100644
index 000000000..579e0f9d9
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AssemblyInfo.cpp
@@ -0,0 +1,43 @@
+#include "stdafx.h"
+
+using namespace System;
+using namespace System::Reflection;
+using namespace System::Runtime::CompilerServices;
+using namespace System::Runtime::InteropServices;
+using namespace System::Security::Permissions;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly:AssemblyTitleAttribute("NETGeographic")];
+[assembly:AssemblyDescriptionAttribute(".NET Interface for GeographicLib")];
+[assembly:AssemblyConfigurationAttribute("1.33")];
+[assembly:AssemblyCompanyAttribute("Open Source")];
+[assembly:AssemblyProductAttribute("NETGeographic")];
+[assembly:AssemblyCopyrightAttribute("GeographicLib copyright (c) Charles Karney 2013\nNETGeographicLib copyright (c) Scott Heiman 2013")];
+[assembly:AssemblyTrademarkAttribute("")];
+[assembly:AssemblyCultureAttribute("")];
+
+//
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the value or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly:AssemblyVersionAttribute("1.33.*")];
+
+[assembly:ComVisible(false)];
+
+[assembly:CLSCompliantAttribute(true)];
+
+#if _MSC_VER < 1800
+// RequestMinium marked as obsolete in Visual Studio 12 (2013)
+[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
+#endif
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AzimuthalEquidistant.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AzimuthalEquidistant.cpp
new file mode 100644
index 000000000..5279ee938
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AzimuthalEquidistant.cpp
@@ -0,0 +1,110 @@
+/**
+ * \file NETGeographicLib/AzimuthalEquidistant.cpp
+ * \brief Implementation for NETGeographicLib::AzimuthalEquidistant class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/AzimuthalEquidistant.hpp"
+#include "AzimuthalEquidistant.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+const char BADALLOC[] = "Failed to allocate memory for a GeographicLib::AzimuthalEquidistant";
+
+//*****************************************************************************
+AzimuthalEquidistant::!AzimuthalEquidistant()
+{
+ if ( m_pAzimuthalEquidistant != NULL )
+ {
+ delete m_pAzimuthalEquidistant;
+ m_pAzimuthalEquidistant = NULL;
+ }
+}
+
+//*****************************************************************************
+AzimuthalEquidistant::AzimuthalEquidistant(void)
+{
+ try
+ {
+ m_pAzimuthalEquidistant = new GeographicLib::AzimuthalEquidistant( GeographicLib::Geodesic::WGS84 );
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+AzimuthalEquidistant::AzimuthalEquidistant( Geodesic^ g )
+{
+ try
+ {
+ const GeographicLib::Geodesic* pGeodesic =
+ reinterpret_cast(
+ g->GetUnmanaged()->ToPointer() );
+ m_pAzimuthalEquidistant = new GeographicLib::AzimuthalEquidistant( *pGeodesic );
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+void AzimuthalEquidistant::Forward(double lat0, double lon0, double lat, double lon,
+ double% x, double% y, double% azi, double% rk)
+{
+ double lx, ly, lazi, lrk;
+ m_pAzimuthalEquidistant->Forward( lat0, lon0, lat, lon,
+ lx, ly, lazi, lrk );
+ x = lx;
+ y = ly;
+ azi = lazi;
+ rk = lrk;
+}
+
+//*****************************************************************************
+void AzimuthalEquidistant::Reverse(double lat0, double lon0, double x, double y,
+ double% lat, double% lon, double% azi, double% rk)
+{
+ double llat, llon, lazi, lrk;
+ m_pAzimuthalEquidistant->Reverse(lat0, lon0, x, y,
+ llat, llon, lazi, lrk);
+ lat = llat;
+ lon = llon;
+ azi = lazi;
+ rk = lrk;
+}
+//*****************************************************************************
+void AzimuthalEquidistant::Forward(double lat0, double lon0, double lat, double lon,
+ double% x, double% y)
+{
+ double azi, rk, lx, ly;
+ m_pAzimuthalEquidistant->Forward(lat0, lon0, lat, lon, lx, ly, azi, rk);
+ x = lx;
+ y = ly;
+}
+
+//*****************************************************************************
+void AzimuthalEquidistant::Reverse(double lat0, double lon0, double x, double y,
+ double% lat, double% lon)
+{
+ double azi, rk, llat, llon;
+ m_pAzimuthalEquidistant->Reverse(lat0, lon0, x, y, llat, llon, azi, rk);
+ lat = llat;
+ lon = llon;
+}
+
+//*****************************************************************************
+double AzimuthalEquidistant::MajorRadius::get()
+{ return m_pAzimuthalEquidistant->MajorRadius(); }
+
+//*****************************************************************************
+double AzimuthalEquidistant::Flattening::get()
+{ return m_pAzimuthalEquidistant->Flattening(); }
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AzimuthalEquidistant.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AzimuthalEquidistant.h
new file mode 100644
index 000000000..ab0643fc4
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/AzimuthalEquidistant.h
@@ -0,0 +1,161 @@
+/**
+ * \file NETGeographicLib/AzimuthalEquidistant.h
+ * \brief Header for NETGeographicLib::AzimuthalEquidistant class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+#include "Geodesic.h"
+
+namespace NETGeographicLib
+{
+ /**
+ * \brief .NET wrapper for GeographicLib::AzimuthalEquidistant.
+ *
+ * This class allows .NET applications to access GeographicLib::AzimuthalEquidistant.
+ *
+ * Azimuthal equidistant projection centered at an arbitrary position on the
+ * ellipsoid. For a point in projected space (\e x, \e y), the geodesic
+ * distance from the center position is hypot(\e x, \e y) and the azimuth of
+ * the geodesic from the center point is atan2(\e x, \e y). The Forward and
+ * Reverse methods also return the azimuth \e azi of the geodesic at (\e x,
+ * \e y) and reciprocal scale \e rk in the azimuthal direction which,
+ * together with the basic properties of the projection, serve to specify
+ * completely the local affine transformation between geographic and
+ * projected coordinates.
+ *
+ * The conversions all take place using a Geodesic object (by default
+ * Geodesic::WGS84). For more information on geodesics see \ref geodesic.
+ *
+ * C# Example:
+ * \include example-AzimuthalEquidistant.cs
+ * Managed C++ Example:
+ * \include example-AzimuthalEquidistant.cpp
+ * Visual Basic Example:
+ * \include example-AzimuthalEquidistant.vb
+ *
+ * INTERFACE DIFFERENCES:
+ * A default constructor is provided that assumes a WGS84 ellipsoid.
+ *
+ * The MajorRadius and Flattening functions are implemented as
+ * properties.
+ **********************************************************************/
+ public ref class AzimuthalEquidistant
+ {
+ private:
+ // Pointer to the unmanaged GeographicLib::AzimuthalEquidistant
+ const GeographicLib::AzimuthalEquidistant* m_pAzimuthalEquidistant;
+
+ // Frees the unmanaged memory when the object is destroyed.
+ !AzimuthalEquidistant();
+ public:
+ /**
+ * Default Constructor for AzimuthalEquidistant.
+ * Assumes WGS84 Geodesic
+ **********************************************************************/
+ AzimuthalEquidistant(void);
+
+ /**
+ * Constructor for AzimuthalEquidistant.
+ *
+ * @param[in] earth the Geodesic object to use for geodesic calculations.
+ **********************************************************************/
+ AzimuthalEquidistant( Geodesic^ earth );
+
+ /**
+ * Destructor
+ *
+ * frees unmanaged memory.
+ **********************************************************************/
+ ~AzimuthalEquidistant()
+ { this->!AzimuthalEquidistant(); }
+
+ /**
+ * Forward projection, from geographic to azimuthal equidistant.
+ *
+ * @param[in] lat0 latitude of center point of projection (degrees).
+ * @param[in] lon0 longitude of center point of projection (degrees).
+ * @param[in] lat latitude of point (degrees).
+ * @param[in] lon longitude of point (degrees).
+ * @param[out] x easting of point (meters).
+ * @param[out] y northing of point (meters).
+ * @param[out] azi azimuth of geodesic at point (degrees).
+ * @param[out] rk reciprocal of azimuthal scale at point.
+ *
+ * \e lat0 and \e lat should be in the range [−90°,
+ * 90°] and \e lon0 and \e lon should be in the range
+ * [−540°, 540°). The scale of the projection is 1
+ * in the "radial" direction, \e azi clockwise from true north, and is 1/\e
+ * rk in the direction perpendicular to this. A call to Forward followed
+ * by a call to Reverse will return the original (\e lat, \e lon) (to
+ * within roundoff).
+ **********************************************************************/
+ void Forward(double lat0, double lon0, double lat, double lon,
+ [System::Runtime::InteropServices::Out] double% x,
+ [System::Runtime::InteropServices::Out] double% y,
+ [System::Runtime::InteropServices::Out] double% azi,
+ [System::Runtime::InteropServices::Out] double% rk);
+
+ /**
+ * Reverse projection, from azimuthal equidistant to geographic.
+ *
+ * @param[in] lat0 latitude of center point of projection (degrees).
+ * @param[in] lon0 longitude of center point of projection (degrees).
+ * @param[in] x easting of point (meters).
+ * @param[in] y northing of point (meters).
+ * @param[out] lat latitude of point (degrees).
+ * @param[out] lon longitude of point (degrees).
+ * @param[out] azi azimuth of geodesic at point (degrees).
+ * @param[out] rk reciprocal of azimuthal scale at point.
+ *
+ * \e lat0 should be in the range [−90°, 90°] and \e
+ * lon0 should be in the range [−540°, 540°). \e lat
+ * will be in the range [−90°, 90°] and \e lon will
+ * be in the range [−180°, 180°). The scale of the
+ * projection is 1 in the "radial" direction, \e azi clockwise from true
+ * north, and is 1/\e rk in the direction perpendicular to this. A call to
+ * Reverse followed by a call to Forward will return the original (\e x, \e
+ * y) (to roundoff) only if the geodesic to (\e x, \e y) is a shortest
+ * path.
+ **********************************************************************/
+ void Reverse(double lat0, double lon0, double x, double y,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ [System::Runtime::InteropServices::Out] double% azi,
+ [System::Runtime::InteropServices::Out] double% rk);
+
+ /**
+ * AzimuthalEquidistant::Forward without returning the azimuth and scale.
+ **********************************************************************/
+ void Forward(double lat0, double lon0, double lat, double lon,
+ [System::Runtime::InteropServices::Out] double% x,
+ [System::Runtime::InteropServices::Out] double% y);
+
+ /**
+ * AzimuthalEquidistant::Reverse without returning the azimuth and scale.
+ **********************************************************************/
+ void Reverse(double lat0, double lon0, double x, double y,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon);
+
+ /** \name Inspector functions
+ **********************************************************************/
+ ///@{
+ /**
+ * @return \e a the equatorial radius of the ellipsoid (meters). This is
+ * the value inherited from the Geodesic object used in the constructor.
+ **********************************************************************/
+ property double MajorRadius { double get(); }
+
+ /**
+ * @return \e f the flattening of the ellipsoid. This is the value
+ * inherited from the Geodesic object used in the constructor.
+ **********************************************************************/
+ property double Flattening { double get(); }
+ ///@}
+ };
+} // namespace NETGeographicLib
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CMakeLists.txt b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CMakeLists.txt
new file mode 100644
index 000000000..664b1bc07
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CMakeLists.txt
@@ -0,0 +1,42 @@
+# Build the .NET library...
+
+# Include all the .cpp files in the library.
+file (GLOB SOURCES [A-Za-z]*.cpp)
+file (GLOB HEADERS [A-Za-z]*.h)
+
+add_library (${NETGEOGRAPHICLIB_LIBRARIES} SHARED ${SOURCES} ${HEADERS})
+set_target_properties (${NETGEOGRAPHICLIB_LIBRARIES}
+ PROPERTIES COMPILE_FLAGS "/clr")
+
+string (REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
+string (REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+add_definitions (${PROJECT_DEFINITIONS})
+target_link_libraries (${NETGEOGRAPHICLIB_LIBRARIES} ${PROJECT_LIBRARIES})
+
+# Set the version number on the library
+set_target_properties (${NETGEOGRAPHICLIB_LIBRARIES} PROPERTIES
+ VERSION "${LIBVERSIONFULL}" OUTPUT_NAME ${NETLIBNAME}
+ PDB_NAME ${NETLIBNAME}${CMAKE_DEBUG_POSTFIX})
+
+# Specify where the library is installed, adding it to the export depends
+install (TARGETS ${NETGEOGRAPHICLIB_LIBRARIES}
+ EXPORT depends
+ RUNTIME DESTINATION bin)
+
+if (PACKAGE_DEBUG_LIBS)
+ install (PROGRAMS
+ "${CMAKE_CURRENT_BINARY_DIR}/Debug/${NETLIBNAME}${CMAKE_DEBUG_POSTFIX}.dll"
+ DESTINATION bin CONFIGURATIONS Release)
+endif ()
+
+# Install pdb file in debug mode.
+get_target_property (_P ${NETGEOGRAPHICLIB_LIBRARIES} LOCATION_DEBUG)
+get_filename_component (_P ${_P} PATH)
+get_target_property (_N ${NETGEOGRAPHICLIB_LIBRARIES} PDB_NAME)
+set (_PDB ${_P}/${_N}.pdb)
+install (FILES ${_PDB} DESTINATION bin
+ RENAME ${NETLIBNAME}${CMAKE_DEBUG_POSTFIX}.pdb CONFIGURATIONS Debug)
+
+# Put all the library into a folder in the IDE
+set_property (TARGET ${NETGEOGRAPHICLIB_LIBRARIES} PROPERTY FOLDER library)
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CassiniSoldner.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CassiniSoldner.cpp
new file mode 100644
index 000000000..cfaa96aea
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CassiniSoldner.cpp
@@ -0,0 +1,134 @@
+/**
+ * \file NETGeographicLib/CassiniSoldner.cpp
+ * \brief Implementation for NETGeographicLib::CassiniSoldner class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/CassiniSoldner.hpp"
+#include "Geodesic.h"
+#include "CassiniSoldner.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+const char BADALLOC[] = "Failed to allocate memory for a GeographicLib::CassiniSoldner";
+
+//*****************************************************************************
+CassiniSoldner::!CassiniSoldner()
+{
+ if ( m_pCassiniSoldner != NULL )
+ {
+ delete m_pCassiniSoldner;
+ m_pCassiniSoldner = NULL;
+ }
+}
+
+//*****************************************************************************
+CassiniSoldner::CassiniSoldner(double lat0, double lon0)
+{
+ try
+ {
+ m_pCassiniSoldner = new GeographicLib::CassiniSoldner( GeographicLib::Geodesic::WGS84 );
+ m_pCassiniSoldner->Reset(lat0, lon0);
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+CassiniSoldner::CassiniSoldner(double lat0, double lon0,
+ Geodesic^ earth )
+{
+ try
+ {
+ const GeographicLib::Geodesic* pGeodesic =
+ reinterpret_cast(
+ earth->GetUnmanaged()->ToPointer() );
+ m_pCassiniSoldner = new GeographicLib::CassiniSoldner( *pGeodesic );
+ m_pCassiniSoldner->Reset(lat0, lon0);
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+void CassiniSoldner::Reset(double lat0, double lon0)
+{
+ m_pCassiniSoldner->Reset(lat0, lon0);
+}
+
+//*****************************************************************************
+void CassiniSoldner::Forward(double lat, double lon,
+ [System::Runtime::InteropServices::Out] double% x,
+ [System::Runtime::InteropServices::Out] double% y,
+ [System::Runtime::InteropServices::Out] double% azi,
+ [System::Runtime::InteropServices::Out] double% rk)
+{
+ double lx, ly, lazi, lrk;
+ m_pCassiniSoldner->Forward(lat, lon, lx, ly, lazi, lrk);
+ x = lx;
+ y = ly;
+ azi = lazi;
+ rk = lrk;
+}
+
+//*****************************************************************************
+void CassiniSoldner::Reverse(double x, double y,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ [System::Runtime::InteropServices::Out] double% azi,
+ [System::Runtime::InteropServices::Out] double% rk)
+{
+ double llat, llon, lazi, lrk;
+ m_pCassiniSoldner->Reverse( x, y, llat, llon, lazi, lrk );
+ lat = llat;
+ lon = llon;
+ azi = lazi;
+ rk = lrk;
+}
+//*****************************************************************************
+void CassiniSoldner::Forward(double lat, double lon,
+ [System::Runtime::InteropServices::Out] double% x,
+ [System::Runtime::InteropServices::Out] double% y)
+{
+ double lx, ly, azi, rk;
+ m_pCassiniSoldner->Forward(lat, lon, lx, ly, azi, rk);
+ x = lx;
+ y = ly;
+}
+
+//*****************************************************************************
+void CassiniSoldner::Reverse(double x, double y,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon)
+{
+ double llat, llon, lazi, lrk;
+ m_pCassiniSoldner->Reverse( x, y, llat, llon, lazi, lrk );
+ lat = llat;
+ lon = llon;
+}
+
+//*****************************************************************************
+double CassiniSoldner::LatitudeOrigin::get()
+{ return m_pCassiniSoldner->LatitudeOrigin(); }
+
+//*****************************************************************************
+double CassiniSoldner::LongitudeOrigin::get()
+{ return m_pCassiniSoldner->LongitudeOrigin(); }
+
+//*****************************************************************************
+double CassiniSoldner::MajorRadius::get()
+{ return m_pCassiniSoldner->MajorRadius(); }
+
+//*****************************************************************************
+double CassiniSoldner::Flattening::get()
+{ return m_pCassiniSoldner->Flattening(); }
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CassiniSoldner.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CassiniSoldner.h
new file mode 100644
index 000000000..7150da02d
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CassiniSoldner.h
@@ -0,0 +1,201 @@
+/**
+ * \file NETGeographicLib/CassiniSoldner.h
+ * \brief Header for NETGeographicLib::CassiniSoldner class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+
+namespace NETGeographicLib
+{
+ /**
+ * \brief .NET wrapper for GeographicLib::CassiniSoldner.
+ *
+ * This class allows .NET applications to access GeographicLib::CassiniSoldner.
+ *
+ * Cassini-Soldner projection centered at an arbitrary position, \e lat0, \e
+ * lon0, on the ellipsoid. This projection is a transverse cylindrical
+ * equidistant projection. The projection from (\e lat, \e lon) to easting
+ * and northing (\e x, \e y) is defined by geodesics as follows. Go north
+ * along a geodesic a distance \e y from the central point; then turn
+ * clockwise 90° and go a distance \e x along a geodesic.
+ * (Although the initial heading is north, this changes to south if the pole
+ * is crossed.) This procedure uniquely defines the reverse projection. The
+ * forward projection is constructed as follows. Find the point (\e lat1, \e
+ * lon1) on the meridian closest to (\e lat, \e lon). Here we consider the
+ * full meridian so that \e lon1 may be either \e lon0 or \e lon0 +
+ * 180°. \e x is the geodesic distance from (\e lat1, \e lon1) to
+ * (\e lat, \e lon), appropriately signed according to which side of the
+ * central meridian (\e lat, \e lon) lies. \e y is the shortest distance
+ * along the meridian from (\e lat0, \e lon0) to (\e lat1, \e lon1), again,
+ * appropriately signed according to the initial heading. [Note that, in the
+ * case of prolate ellipsoids, the shortest meridional path from (\e lat0, \e
+ * lon0) to (\e lat1, \e lon1) may not be the shortest path.] This procedure
+ * uniquely defines the forward projection except for a small class of points
+ * for which there may be two equally short routes for either leg of the
+ * path.
+ *
+ * Because of the properties of geodesics, the (\e x, \e y) grid is
+ * orthogonal. The scale in the easting direction is unity. The scale, \e
+ * k, in the northing direction is unity on the central meridian and
+ * increases away from the central meridian. The projection routines return
+ * \e azi, the true bearing of the easting direction, and \e rk = 1/\e k, the
+ * reciprocal of the scale in the northing direction.
+ *
+ * The conversions all take place using a Geodesic object (by default
+ * Geodesic::WGS84). For more information on geodesics see \ref geodesic.
+ * The determination of (\e lat1, \e lon1) in the forward projection is by
+ * solving the inverse geodesic problem for (\e lat, \e lon) and its twin
+ * obtained by reflection in the meridional plane. The scale is found by
+ * determining where two neighboring geodesics intersecting the central
+ * meridian at \e lat1 and \e lat1 + \e dlat1 intersect and taking the ratio
+ * of the reduced lengths for the two geodesics between that point and,
+ * respectively, (\e lat1, \e lon1) and (\e lat, \e lon).
+ *
+ * C# Example:
+ * \include example-CassiniSoldner.cs
+ * Managed C++ Example:
+ * \include example-CassiniSoldner.cpp
+ * Visual Basic Example:
+ * \include example-CassiniSoldner.vb
+ *
+ * INTERFACE DIFFERENCES:
+ * The LatitudeOrigin, LongitudeOrigin, MajorRadius and Flattening
+ * functions are implimented as properties.
+ **********************************************************************/
+ public ref class CassiniSoldner
+ {
+ private:
+ // A pointer to the unmanaged GeographicLib::CassiniSoldner
+ GeographicLib::CassiniSoldner* m_pCassiniSoldner;
+
+ // The finalizer frees the unmanaged memory when the object is destroyed.
+ !CassiniSoldner();
+ public:
+ /**
+ * Constructor for CassiniSoldner specifying a center point and
+ * assuming the WGS84 ellipsoid.
+ *
+ * @param[in] lat0 latitude of center point of projection (degrees).
+ * @param[in] lon0 longitude of center point of projection (degrees).
+ **********************************************************************/
+ CassiniSoldner(double lat0, double lon0);
+
+ /**
+ * Constructor for CassiniSoldner specifying a center point.
+ *
+ * @param[in] lat0 latitude of center point of projection (degrees).
+ * @param[in] lon0 longitude of center point of projection (degrees).
+ * @param[in] earth the Geodesic object to use for geodesic calculations.
+ * By default this uses the WGS84 ellipsoid.
+ *
+ * \e lat0 should be in the range [−90°, 90°] and \e
+ * lon0 should be in the range [−540°, 540°).
+ **********************************************************************/
+ CassiniSoldner(double lat0, double lon0, Geodesic^ earth );
+
+ /**
+ * The destructor calls the finalizer.
+ **********************************************************************/
+ ~CassiniSoldner()
+ { this->!CassiniSoldner(); }
+
+ /**
+ * Set the central point of the projection
+ *
+ * @param[in] lat0 latitude of center point of projection (degrees).
+ * @param[in] lon0 longitude of center point of projection (degrees).
+ *
+ * \e lat0 should be in the range [−90°, 90°] and \e
+ * lon0 should be in the range [−540°, 540°).
+ **********************************************************************/
+ void Reset(double lat0, double lon0);
+
+ /**
+ * Forward projection, from geographic to Cassini-Soldner.
+ *
+ * @param[in] lat latitude of point (degrees).
+ * @param[in] lon longitude of point (degrees).
+ * @param[out] x easting of point (meters).
+ * @param[out] y northing of point (meters).
+ * @param[out] azi azimuth of easting direction at point (degrees).
+ * @param[out] rk reciprocal of azimuthal northing scale at point.
+ *
+ * \e lat should be in the range [−90°, 90°] and \e
+ * lon should be in the range [−540°, 540°). A call
+ * to Forward followed by a call to Reverse will return the original (\e
+ * lat, \e lon) (to within roundoff). The routine does nothing if the
+ * origin has not been set.
+ **********************************************************************/
+ void Forward(double lat, double lon,
+ [System::Runtime::InteropServices::Out] double% x,
+ [System::Runtime::InteropServices::Out] double% y,
+ [System::Runtime::InteropServices::Out] double% azi,
+ [System::Runtime::InteropServices::Out] double% rk);
+
+ /**
+ * Reverse projection, from Cassini-Soldner to geographic.
+ *
+ * @param[in] x easting of point (meters).
+ * @param[in] y northing of point (meters).
+ * @param[out] lat latitude of point (degrees).
+ * @param[out] lon longitude of point (degrees).
+ * @param[out] azi azimuth of easting direction at point (degrees).
+ * @param[out] rk reciprocal of azimuthal northing scale at point.
+ *
+ * A call to Reverse followed by a call to Forward will return the original
+ * (\e x, \e y) (to within roundoff), provided that \e x and \e y are
+ * sufficiently small not to "wrap around" the earth. The routine does
+ * nothing if the origin has not been set.
+ **********************************************************************/
+ void Reverse(double x, double y,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ [System::Runtime::InteropServices::Out] double% azi,
+ [System::Runtime::InteropServices::Out] double% rk);
+
+ /**
+ * CassiniSoldner::Forward without returning the azimuth and scale.
+ **********************************************************************/
+ void Forward(double lat, double lon,
+ [System::Runtime::InteropServices::Out] double% x,
+ [System::Runtime::InteropServices::Out] double% y);
+
+ /**
+ * CassiniSoldner::Reverse without returning the azimuth and scale.
+ **********************************************************************/
+ void Reverse(double x, double y,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon);
+
+ /** \name Inspector functions
+ **********************************************************************/
+ ///@{
+ /**
+ * @return \e lat0 the latitude of origin (degrees).
+ **********************************************************************/
+ property double LatitudeOrigin { double get(); }
+
+ /**
+ * @return \e lon0 the longitude of origin (degrees).
+ **********************************************************************/
+ property double LongitudeOrigin { double get(); }
+
+ /**
+ * @return \e a the equatorial radius of the ellipsoid (meters). This is
+ * the value inherited from the Geodesic object used in the constructor.
+ **********************************************************************/
+ property double MajorRadius { double get(); }
+
+ /**
+ * @return \e f the flattening of the ellipsoid. This is the value
+ * inherited from the Geodesic object used in the constructor.
+ **********************************************************************/
+ property double Flattening { double get(); }
+ ///@}
+ };
+} // namespace NETGeographicLib
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CircularEngine.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CircularEngine.cpp
new file mode 100644
index 000000000..37aae2150
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CircularEngine.cpp
@@ -0,0 +1,83 @@
+/**
+ * \file NETGeographicLib/CircularEngine.cpp
+ * \brief Implementation for NETGeographicLib::CircularEngine class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/CircularEngine.hpp"
+#include "CircularEngine.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+//*****************************************************************************
+CircularEngine::CircularEngine(const GeographicLib::CircularEngine& c)
+{
+ try
+ {
+ m_pCircularEngine = new GeographicLib::CircularEngine( c );
+ }
+ catch ( GeographicLib::GeographicErr err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( "Failed to allocate memory for a GeographicLib::CircularEngine" );
+ }
+}
+
+//*****************************************************************************
+CircularEngine::!CircularEngine()
+{
+ if ( m_pCircularEngine != NULL )
+ {
+ delete m_pCircularEngine;
+ m_pCircularEngine = NULL;
+ }
+}
+
+//*****************************************************************************
+double CircularEngine::LongitudeSum(double coslon, double sinlon)
+{
+ return m_pCircularEngine->operator()( coslon, sinlon );
+}
+
+//*****************************************************************************
+double CircularEngine::LongitudeSum(double lon)
+{
+ return m_pCircularEngine->operator()( lon );
+}
+
+//*****************************************************************************
+double CircularEngine::LongitudeSum(double coslon, double sinlon,
+ [System::Runtime::InteropServices::Out] double% gradx,
+ [System::Runtime::InteropServices::Out] double% grady,
+ [System::Runtime::InteropServices::Out] double% gradz)
+{
+ double lgradx, lgrady, lgradz;
+ double output = m_pCircularEngine->operator()( coslon, sinlon, lgradx, lgrady, lgradz );
+ gradx = lgradx;
+ grady = lgrady;
+ gradz = lgradz;
+ return output;
+}
+
+//*****************************************************************************
+double CircularEngine::LongitudeSum(double lon,
+ [System::Runtime::InteropServices::Out] double% gradx,
+ [System::Runtime::InteropServices::Out] double% grady,
+ [System::Runtime::InteropServices::Out] double% gradz)
+{
+ double lgradx, lgrady, lgradz;
+ double output = m_pCircularEngine->operator()( lon, lgradx, lgrady, lgradz );
+ gradx = lgradx;
+ grady = lgrady;
+ gradz = lgradz;
+ return output;
+}
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CircularEngine.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CircularEngine.h
new file mode 100644
index 000000000..febed2bf9
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/CircularEngine.h
@@ -0,0 +1,142 @@
+/**
+ * \file NETGeographicLib/CircularEngine.h
+ * \brief Header for NETGeographicLib::CircularEngine class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+
+namespace NETGeographicLib
+{
+ /**
+ * \brief .NET wrapper for GeographicLib::CircularEngine.
+ *
+ * This class allows .NET applications to access GeographicLib::CircularEngine.
+ *
+ * The class is a companion to SphericalEngine. If the results of a
+ * spherical harmonic sum are needed for several points on a circle of
+ * constant latitude \e lat and height \e h, then SphericalEngine::Circle can
+ * compute the inner sum, which is independent of longitude \e lon, and
+ * produce a CircularEngine object. CircularEngine::LongitudeSum() can
+ * then be used to perform the outer sum for particular values of \e lon.
+ * This can lead to substantial improvements in computational speed for high
+ * degree sum (approximately by a factor of \e N / 2 where \e N is the
+ * maximum degree).
+ *
+ * CircularEngine is tightly linked to the internals of SphericalEngine. For
+ * that reason, the constructor for this class is for internal use only. Use
+ * SphericalHarmonic::Circle, SphericalHarmonic1::Circle, and
+ * SphericalHarmonic2::Circle to create instances of this class.
+ *
+ * CircularEngine stores the coefficients needed to allow the summation over
+ * order to be performed in 2 or 6 vectors of length \e M + 1 (depending on
+ * whether gradients are to be calculated). For this reason the constructor
+ * may throw a GeographicErr exception.
+ *
+ * C# Example:
+ * \include example-CircularEngine.cs
+ * Managed C++ Example:
+ * \include example-CircularEngine.cpp
+ * Visual Basic Example:
+ * \include example-CircularEngine.vb
+ *
+ * INTERFACE DIFFERENCES:
+ * The () operator has been replaced with with LongitudeSum.
+ *
+ * This class does not have a constructor that can be used in a .NET
+ * application. Use SphericalHarmonic::Circle, SphericalHarmonic1::Circle or
+ * SphericalHarmonic2::Circle to create instances of this class.
+ **********************************************************************/
+ public ref class CircularEngine
+ {
+ private:
+ // pointer to the unmanaged GeographicLib::CircularEngine
+ const GeographicLib::CircularEngine* m_pCircularEngine;
+
+ // The finalizer frees the unmanaged memory when the object is destroyed.
+ !CircularEngine();
+ public:
+ /**
+ * The constructor.
+ *
+ * This constructor should not be used in .NET applications.
+ * Use SphericalHarmonic::Circle, SphericalHarmonic1::Circle or
+ * SphericalHarmonic2::Circle to create instances of this class.
+ *
+ * @param[in] c The unmanaged CircularEngine to be copied.
+ **********************************************************************/
+ CircularEngine( const GeographicLib::CircularEngine& c );
+
+ /**
+ * The destructor calls the finalizer
+ **********************************************************************/
+ ~CircularEngine()
+ { this->!CircularEngine(); }
+
+ /**
+ * Evaluate the sum for a particular longitude given in terms of its
+ * cosine and sine.
+ *
+ * @param[in] coslon the cosine of the longitude.
+ * @param[in] sinlon the sine of the longitude.
+ * @return \e V the value of the sum.
+ *
+ * The arguments must satisfy coslon2 +
+ * sinlon2 = 1.
+ **********************************************************************/
+ double LongitudeSum(double coslon, double sinlon);
+
+ /**
+ * Evaluate the sum for a particular longitude.
+ *
+ * @param[in] lon the longitude (degrees).
+ * @return \e V the value of the sum.
+ **********************************************************************/
+ double LongitudeSum(double lon);
+
+ /**
+ * Evaluate the sum and its gradient for a particular longitude given in
+ * terms of its cosine and sine.
+ *
+ * @param[in] coslon the cosine of the longitude.
+ * @param[in] sinlon the sine of the longitude.
+ * @param[out] gradx \e x component of the gradient.
+ * @param[out] grady \e y component of the gradient.
+ * @param[out] gradz \e z component of the gradient.
+ * @return \e V the value of the sum.
+ *
+ * The gradients will only be computed if the CircularEngine object was
+ * created with this capability (e.g., via \e gradp = true in
+ * SphericalHarmonic::Circle). If not, \e gradx, etc., will not be
+ * touched. The arguments must satisfy coslon2 +
+ * sinlon2 = 1.
+ **********************************************************************/
+ double LongitudeSum(double coslon, double sinlon,
+ [System::Runtime::InteropServices::Out] double% gradx,
+ [System::Runtime::InteropServices::Out] double% grady,
+ [System::Runtime::InteropServices::Out] double% gradz);
+
+ /**
+ * Evaluate the sum and its gradient for a particular longitude.
+ *
+ * @param[in] lon the longitude (degrees).
+ * @param[out] gradx \e x component of the gradient.
+ * @param[out] grady \e y component of the gradient.
+ * @param[out] gradz \e z component of the gradient.
+ * @return \e V the value of the sum.
+ *
+ * The gradients will only be computed if the CircularEngine object was
+ * created with this capability (e.g., via \e gradp = true in
+ * SphericalHarmonic::Circle). If not, \e gradx, etc., will not be
+ * touched.
+ **********************************************************************/
+ double LongitudeSum(double lon,
+ [System::Runtime::InteropServices::Out] double% gradx,
+ [System::Runtime::InteropServices::Out] double% grady,
+ [System::Runtime::InteropServices::Out] double% gradz);
+ };
+} //namespace NETGeographicLib
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/DMS.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/DMS.cpp
new file mode 100644
index 000000000..8271b7fd2
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/DMS.cpp
@@ -0,0 +1,130 @@
+/**
+ * \file NETGeographicLib/DMS.cpp
+ * \brief Implementation for NETGeographicLib::DMS class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/DMS.hpp"
+#include "DMS.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+//*****************************************************************************
+double DMS::Decode( System::String^ dms,
+ [System::Runtime::InteropServices::Out] Flag% ind)
+{
+ try
+ {
+ GeographicLib::DMS::flag lind;
+ double out = GeographicLib::DMS::Decode( StringConvert::ManagedToUnmanaged(dms), lind );
+ ind = static_cast(lind);
+ return out;
+ }
+ catch ( const std::exception& xcpt )
+ {
+ throw gcnew GeographicErr( xcpt.what() );
+ }
+}
+
+//*****************************************************************************
+double DMS::Decode(System::String^ str)
+{
+ try
+ {
+ return GeographicLib::DMS::Decode(StringConvert::ManagedToUnmanaged(str));
+ }
+ catch ( const std::exception& xcpt )
+ {
+ throw gcnew GeographicErr( xcpt.what() );
+ }
+}
+
+//*****************************************************************************
+void DMS::DecodeLatLon(System::String^ dmsa, System::String^ dmsb,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ bool swaplatlong )
+{
+ try
+ {
+ double llat, llon;
+ GeographicLib::DMS::DecodeLatLon( StringConvert::ManagedToUnmanaged( dmsa ),
+ StringConvert::ManagedToUnmanaged( dmsb ), llat, llon, swaplatlong );
+ lat = llat;
+ lon = llon;
+ }
+ catch ( const std::exception& xcpt )
+ {
+ throw gcnew GeographicErr( xcpt.what() );
+ }
+}
+
+//*****************************************************************************
+double DMS::DecodeAngle(System::String^ angstr)
+{
+ try
+ {
+ return GeographicLib::DMS::DecodeAngle(StringConvert::ManagedToUnmanaged( angstr ));
+ }
+ catch ( const std::exception& xcpt )
+ {
+ throw gcnew GeographicErr( xcpt.what() );
+ }
+}
+
+//*****************************************************************************
+double DMS::DecodeAzimuth(System::String^ azistr)
+{
+ try
+ {
+ return GeographicLib::DMS::DecodeAzimuth(StringConvert::ManagedToUnmanaged( azistr ));
+ }
+ catch ( const std::exception& xcpt )
+ {
+ throw gcnew GeographicErr( xcpt.what() );
+ }
+}
+
+//*****************************************************************************
+System::String^ DMS::Encode(double angle, Component trailing, unsigned prec,
+ Flag ind, char dmssep)
+{
+ try
+ {
+ return StringConvert::UnmanagedToManaged(
+ GeographicLib::DMS::Encode( angle,
+ static_cast(trailing),
+ prec,
+ static_cast(ind),
+ dmssep )
+ );
+ }
+ catch ( const std::exception& xcpt )
+ {
+ throw gcnew GeographicErr( xcpt.what() );
+ }
+}
+//*****************************************************************************
+System::String^ DMS::Encode(double angle, unsigned prec, Flag ind,
+ char dmssep )
+{
+ try
+ {
+ return StringConvert::UnmanagedToManaged(
+ GeographicLib::DMS::Encode( angle,
+ prec,
+ static_cast(ind),
+ dmssep )
+ );
+ }
+ catch ( const std::exception& xcpt )
+ {
+ throw gcnew GeographicErr( xcpt.what() );
+ }
+}
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/DMS.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/DMS.h
new file mode 100644
index 000000000..a0c37fe4e
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/DMS.h
@@ -0,0 +1,326 @@
+/**
+ * \file NETGeographicLib/DMS.h
+ * \brief Header for NETGeographicLib::DMS class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+
+namespace NETGeographicLib
+{
+ /**
+ * \brief .NET wrapper for GeographicLib::DMS.
+ *
+ * Parse a string representing degree, minutes, and seconds and return the
+ * angle in degrees and format an angle in degrees as degree, minutes, and
+ * seconds. In addition, handle NANs and infinities on input and output.
+ *
+ * C# Example:
+ * \include example-DMS.cs
+ * Managed C++ Example:
+ * \include example-DMS.cpp
+ * Visual Basic Example:
+ * \include example-DMS.vb
+ **********************************************************************/
+public ref class DMS
+{
+public:
+ /**
+ * Indicator for presence of hemisphere indicator (N/S/E/W) on latitudes
+ * and longitudes.
+ **********************************************************************/
+ enum class Flag {
+ /**
+ * No indicator present.
+ * @hideinitializer
+ **********************************************************************/
+ NONE = 0,
+ /**
+ * Latitude indicator (N/S) present.
+ * @hideinitializer
+ **********************************************************************/
+ LATITUDE = 1,
+ /**
+ * Longitude indicator (E/W) present.
+ * @hideinitializer
+ **********************************************************************/
+ LONGITUDE = 2,
+ /**
+ * Used in Encode to indicate output of an azimuth in [000, 360) with no
+ * letter indicator.
+ * @hideinitializer
+ **********************************************************************/
+ AZIMUTH = 3,
+ /**
+ * Used in Encode to indicate output of a plain number.
+ * @hideinitializer
+ **********************************************************************/
+ NUMBER = 4,
+ };
+
+ /**
+ * Indicator for trailing units on an angle.
+ **********************************************************************/
+ enum class Component {
+ /**
+ * Trailing unit is degrees.
+ * @hideinitializer
+ **********************************************************************/
+ DEGREE = 0,
+ /**
+ * Trailing unit is arc minutes.
+ * @hideinitializer
+ **********************************************************************/
+ MINUTE = 1,
+ /**
+ * Trailing unit is arc seconds.
+ * @hideinitializer
+ **********************************************************************/
+ SECOND = 2,
+ };
+
+ /**
+ * Convert a string in DMS to an angle.
+ *
+ * @param[in] dms string input.
+ * @param[out] ind a DMS::flag value signaling the presence of a
+ * hemisphere indicator.
+ * @exception GeographicErr if \e dms is malformed (see below).
+ * @return angle (degrees).
+ *
+ * Degrees, minutes, and seconds are indicated by the characters d, '
+ * (single quote), " (double quote), and these components may only be
+ * given in this order. Any (but not all) components may be omitted and
+ * other symbols (e.g., the ° symbol for degrees and the unicode
+ * prime and double prime symbols for minutes and seconds) may be
+ * substituted. The last component indicator may be omitted and is assumed
+ * to be the next smallest unit (thus 33d10 is interpreted as 33d10'). The
+ * final component may be a decimal fraction but the non-final components
+ * must be integers. Instead of using d, ', and " to indicate
+ * degrees, minutes, and seconds, : (colon) may be used to separate
+ * these components (numbers must appear before and after each colon); thus
+ * 50d30'10.3" may be written as 50:30:10.3, 5.5' may be written
+ * 0:5.5, and so on. The integer parts of the minutes and seconds
+ * components must be less than 60. A single leading sign is permitted. A
+ * hemisphere designator (N, E, W, S) may be added to the beginning or end
+ * of the string. The result is multiplied by the implied sign of the
+ * hemisphere designator (negative for S and W). In addition \e ind is set
+ * to DMS::LATITUDE if N or S is present, to DMS::LONGITUDE if E or W is
+ * present, and to DMS::NONE otherwise. Throws an error on a malformed
+ * string. No check is performed on the range of the result. Examples of
+ * legal and illegal strings are
+ * - LEGAL (all the entries on each line are equivalent)
+ * - -20.51125, 20d30'40.5"S, -20°30'40.5, -20d30.675,
+ * N-20d30'40.5", -20:30:40.5
+ * - 4d0'9, 4d9", 4d9'', 4:0:9, 004:00:09, 4.0025, 4.0025d, 4d0.15,
+ * 04:.15
+ * - ILLEGAL (the exception thrown explains the problem)
+ * - 4d5"4', 4::5, 4:5:, :4:5, 4d4.5'4", -N20.5, 1.8e2d, 4:60,
+ * 4d-5'
+ *
+ * NOTE: At present, all the string handling in the C++
+ * implementation %GeographicLib is with 8-bit characters. The support for
+ * unicode symbols for degrees, minutes, and seconds is therefore via the
+ * UTF-8 encoding. (The
+ * JavaScript implementation of this class uses unicode natively, of
+ * course.)
+ *
+ * Here is the list of Unicode symbols supported for degrees, minutes,
+ * seconds:
+ * - degrees:
+ * - d, D lower and upper case letters
+ * - U+00b0 degree symbol (°)
+ * - U+00ba masculine ordinal indicator
+ * - U+2070 superscript zero
+ * - U+02da ring above
+ * - minutes:
+ * - ' apostrophe
+ * - U+2032 prime (′)
+ * - U+00b4 acute accent
+ * - U+2019 right single quote (’)
+ * - seconds:
+ * - " quotation mark
+ * - U+2033 double prime (″)
+ * - U+201d right double quote (”)
+ * - ' ' any two consecutive symbols for minutes
+ * .
+ * The codes with a leading zero byte, e.g., U+00b0, are accepted in their
+ * UTF-8 coded form 0xc2 0xb0 and as a single byte 0xb0.
+ **********************************************************************/
+ static double Decode(System::String^ dms,
+ [System::Runtime::InteropServices::Out] Flag% ind);
+
+ /**
+ * Convert DMS to an angle.
+ *
+ * @param[in] d degrees.
+ * @param[in] m arc minutes.
+ * @param[in] s arc seconds.
+ * @return angle (degrees)
+ *
+ * This does not propagate the sign on \e d to the other components, so
+ * -3d20' would need to be represented as - DMS::Decode(3.0, 20.0) or
+ * DMS::Decode(-3.0, -20.0).
+ **********************************************************************/
+ static double Decode(double d, double m, double s )
+ { return d + (m + s/double(60))/double(60); }
+
+ /// \cond SKIP
+ /**
+ * DEPRECATED (use Utility::num, instead).
+ * Convert a string to a double number.
+ *
+ * @param[in] str string input.
+ * @exception GeographicErr if \e str is malformed.
+ * @return decoded number.
+ **********************************************************************/
+ static double Decode(System::String^ str);
+ /// \endcond
+
+ /**
+ * Convert a pair of strings to latitude and longitude.
+ *
+ * @param[in] dmsa first string.
+ * @param[in] dmsb second string.
+ * @param[out] lat latitude.
+ * @param[out] lon longitude reduced to the range [−180°,
+ * 180°).
+ * @param[in] swaplatlong if true assume longitude is given before latitude
+ * in the absence of hemisphere designators (default false).
+ * @exception GeographicErr if \e dmsa or \e dmsb is malformed.
+ * @exception GeographicErr if \e dmsa and \e dmsb are both interpreted as
+ * latitudes.
+ * @exception GeographicErr if \e dmsa and \e dmsb are both interpreted as
+ * longitudes.
+ * @exception GeographicErr if decoded latitude is not in [−90°,
+ * 90°].
+ * @exception GeographicErr if decoded longitude is not in
+ * [−540°, 540°).
+ *
+ * By default, the \e lat (resp., \e lon) is assigned to the results of
+ * decoding \e dmsa (resp., \e dmsb). However this is overridden if either
+ * \e dmsa or \e dmsb contain a latitude or longitude hemisphere designator
+ * (N, S, E, W). If an exception is thrown, \e lat and \e lon are
+ * unchanged.
+ **********************************************************************/
+ static void DecodeLatLon(System::String^ dmsa, System::String^ dmsb,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ bool swaplatlong );
+
+ /**
+ * Convert a string to an angle in degrees.
+ *
+ * @param[in] angstr input string.
+ * @exception GeographicErr if \e angstr is malformed.
+ * @exception GeographicErr if \e angstr includes a hemisphere designator.
+ * @return angle (degrees)
+ *
+ * No hemisphere designator is allowed and no check is done on the range of
+ * the result.
+ **********************************************************************/
+ static double DecodeAngle(System::String^ angstr);
+
+ /**
+ * Convert a string to an azimuth in degrees.
+ *
+ * @param[in] azistr input string.
+ * @exception GeographicErr if \e azistr is malformed.
+ * @exception GeographicErr if \e azistr includes a N/S designator.
+ * @exception GeographicErr if decoded azimuth is not in
+ * [−540°, 540°).
+ * @return azimuth (degrees) reduced to the range [−180°,
+ * 180°).
+ *
+ * A hemisphere designator E/W can be used; the result is multiplied by
+ * −1 if W is present.
+ **********************************************************************/
+ static double DecodeAzimuth(System::String^ azistr);
+
+ /**
+ * Convert angle (in degrees) into a DMS string (using d, ', and ").
+ *
+ * @param[in] angle input angle (degrees)
+ * @param[in] trailing DMS::component value indicating the trailing units
+ * on the string and this is given as a decimal number if necessary.
+ * @param[in] prec the number of digits after the decimal point for the
+ * trailing component.
+ * @param[in] ind DMS::flag value indicated additional formatting.
+ * @param[in] dmssep if non-null, use as the DMS separator character
+ * (instead of d, ', " delimiters).
+ * @exception GeographicErr if memory for the string can't be allocated.
+ * @return formatted string
+ *
+ * The interpretation of \e ind is as follows:
+ * - ind == DMS::NONE, signed result no leading zeros on degrees except in
+ * the units place, e.g., -8d03'.
+ * - ind == DMS::LATITUDE, trailing N or S hemisphere designator, no sign,
+ * pad degrees to 2 digits, e.g., 08d03'S.
+ * - ind == DMS::LONGITUDE, trailing E or W hemisphere designator, no
+ * sign, pad degrees to 3 digits, e.g., 008d03'W.
+ * - ind == DMS::AZIMUTH, convert to the range [0, 360°), no
+ * sign, pad degrees to 3 digits, , e.g., 351d57'.
+ * .
+ * The integer parts of the minutes and seconds components are always given
+ * with 2 digits.
+ **********************************************************************/
+ static System::String^ Encode(double angle, Component trailing, unsigned prec,
+ Flag ind, char dmssep );
+
+ /**
+ * Convert angle into a DMS string (using d, ', and ") selecting the
+ * trailing component based on the precision.
+ *
+ * @param[in] angle input angle (degrees)
+ * @param[in] prec the precision relative to 1 degree.
+ * @param[in] ind DMS::flag value indicated additional formatting.
+ * @param[in] dmssep if non-null, use as the DMS separator character
+ * (instead of d, ', " delimiters).
+ * @exception std::bad_alloc if memory for the string can't be allocated.
+ * @return formatted string
+ *
+ * \e prec indicates the precision relative to 1 degree, e.g., \e prec = 3
+ * gives a result accurate to 0.1' and \e prec = 4 gives a result accurate
+ * to 1". \e ind is interpreted as in DMS::Encode with the additional
+ * facility that DMS::NUMBER represents \e angle as a number in fixed
+ * format with precision \e prec.
+ **********************************************************************/
+ static System::String^ Encode(double angle, unsigned prec, Flag ind,
+ char dmssep );
+
+ /**
+ * Split angle into degrees and minutes
+ *
+ * @param[in] ang angle (degrees)
+ * @param[out] d degrees (an integer returned as a double)
+ * @param[out] m arc minutes.
+ **********************************************************************/
+ static void Encode(double ang,
+ [System::Runtime::InteropServices::Out] double% d,
+ [System::Runtime::InteropServices::Out] double% m)
+ {
+ d = int(ang); m = 60 * (ang - d);
+ }
+
+ /**
+ * Split angle into degrees and minutes and seconds.
+ *
+ * @param[in] ang angle (degrees)
+ * @param[out] d degrees (an integer returned as a double)
+ * @param[out] m arc minutes (an integer returned as a double)
+ * @param[out] s arc seconds.
+ **********************************************************************/
+ static void Encode(double ang,
+ [System::Runtime::InteropServices::Out] double% d,
+ [System::Runtime::InteropServices::Out] double% m,
+ [System::Runtime::InteropServices::Out] double% s)
+ {
+ d = int(ang); ang = 60 * (ang - d);
+ m = int(ang); s = 60 * (ang - m);
+ }
+};
+} // namespace NETGeographicLib
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Ellipsoid.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Ellipsoid.cpp
new file mode 100644
index 000000000..8f5acd6e0
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Ellipsoid.cpp
@@ -0,0 +1,270 @@
+/**
+ * \file NETGeographicLib/Ellipsoid.cpp
+ * \brief Implementation for NETGeographicLib::Ellipsoid class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/Ellipsoid.hpp"
+#include "Ellipsoid.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+const char BADALLOC[] = "Failed to allocate memory for a GeographicLib::Ellipsoid";
+
+//*****************************************************************************
+Ellipsoid::!Ellipsoid(void)
+{
+ if ( m_pEllipsoid != NULL )
+ {
+ delete m_pEllipsoid;
+ m_pEllipsoid = NULL;
+ }
+}
+
+//*****************************************************************************
+Ellipsoid::Ellipsoid()
+{
+ try
+ {
+ m_pEllipsoid = new GeographicLib::Ellipsoid( GeographicLib::Ellipsoid::WGS84 );
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+Ellipsoid::Ellipsoid(double a, double f)
+{
+ try
+ {
+ m_pEllipsoid = new GeographicLib::Ellipsoid( a, f );
+ }
+ catch ( std::bad_alloc err )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+ catch ( const std::exception& err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+}
+
+//*****************************************************************************
+double Ellipsoid::ParametricLatitude(double phi)
+{
+ return m_pEllipsoid->ParametricLatitude( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::InverseParametricLatitude(double beta)
+{
+ return m_pEllipsoid->InverseParametricLatitude( beta );
+}
+
+//*****************************************************************************
+double Ellipsoid::GeocentricLatitude(double phi)
+{
+ return m_pEllipsoid->GeocentricLatitude( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::InverseGeocentricLatitude(double theta)
+{
+ return m_pEllipsoid->InverseGeocentricLatitude( theta );
+}
+
+//*****************************************************************************
+double Ellipsoid::RectifyingLatitude(double phi)
+{
+ return m_pEllipsoid->RectifyingLatitude( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::InverseRectifyingLatitude(double mu)
+{
+ return m_pEllipsoid->InverseRectifyingLatitude( mu );
+}
+
+//*****************************************************************************
+double Ellipsoid::AuthalicLatitude(double phi)
+{
+ return m_pEllipsoid->AuthalicLatitude( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::InverseAuthalicLatitude(double xi)
+{
+ return m_pEllipsoid->InverseAuthalicLatitude( xi );
+}
+
+//*****************************************************************************
+double Ellipsoid::ConformalLatitude(double phi)
+{
+ return m_pEllipsoid->ConformalLatitude( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::InverseConformalLatitude(double chi)
+{
+ return m_pEllipsoid->InverseConformalLatitude( chi );
+}
+
+//*****************************************************************************
+double Ellipsoid::IsometricLatitude(double phi)
+{
+ return m_pEllipsoid->IsometricLatitude( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::InverseIsometricLatitude(double psi)
+{
+ return m_pEllipsoid->InverseIsometricLatitude( psi );
+}
+
+//*****************************************************************************
+double Ellipsoid::CircleRadius(double phi)
+{
+ return m_pEllipsoid->CircleRadius( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::CircleHeight(double phi)
+{
+ return m_pEllipsoid->CircleHeight( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::MeridianDistance(double phi)
+{
+ return m_pEllipsoid->MeridianDistance( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::MeridionalCurvatureRadius(double phi)
+{
+ return m_pEllipsoid->MeridionalCurvatureRadius( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::TransverseCurvatureRadius(double phi)
+{
+ return m_pEllipsoid->TransverseCurvatureRadius( phi );
+}
+
+//*****************************************************************************
+double Ellipsoid::NormalCurvatureRadius(double phi, double azi)
+{
+ return m_pEllipsoid->NormalCurvatureRadius( phi, azi );
+}
+
+//*****************************************************************************
+double Ellipsoid::SecondFlatteningToFlattening(double fp)
+{
+ return GeographicLib::Ellipsoid::SecondFlatteningToFlattening( fp );
+}
+
+//*****************************************************************************
+double Ellipsoid::FlatteningToSecondFlattening(double f)
+{
+ return GeographicLib::Ellipsoid::FlatteningToSecondFlattening( f );
+}
+
+//*****************************************************************************
+double Ellipsoid::ThirdFlatteningToFlattening(double n)
+{
+ return GeographicLib::Ellipsoid::ThirdFlatteningToFlattening( n );
+}
+
+//*****************************************************************************
+double Ellipsoid::FlatteningToThirdFlattening(double f)
+{
+ return GeographicLib::Ellipsoid::FlatteningToThirdFlattening( f );
+}
+
+//*****************************************************************************
+double Ellipsoid::EccentricitySqToFlattening(double e2)
+{
+ return GeographicLib::Ellipsoid::EccentricitySqToFlattening( e2 );
+}
+
+//*****************************************************************************
+double Ellipsoid::FlatteningToEccentricitySq(double f)
+{
+ return GeographicLib::Ellipsoid::FlatteningToEccentricitySq( f );
+}
+
+//*****************************************************************************
+double Ellipsoid::SecondEccentricitySqToFlattening(double ep2)
+{
+ return GeographicLib::Ellipsoid::SecondEccentricitySqToFlattening( ep2 );
+}
+
+//*****************************************************************************
+double Ellipsoid::FlatteningToSecondEccentricitySq(double f)
+{
+ return GeographicLib::Ellipsoid::FlatteningToSecondEccentricitySq( f );
+}
+
+//*****************************************************************************
+double Ellipsoid::ThirdEccentricitySqToFlattening(double epp2)
+{
+ return GeographicLib::Ellipsoid::ThirdEccentricitySqToFlattening( epp2 );
+}
+
+//*****************************************************************************
+double Ellipsoid::FlatteningToThirdEccentricitySq(double f)
+{
+ return GeographicLib::Ellipsoid::FlatteningToThirdEccentricitySq( f );
+}
+
+//*****************************************************************************
+double Ellipsoid::MajorRadius::get()
+{ return m_pEllipsoid->MajorRadius(); }
+
+//*****************************************************************************
+double Ellipsoid::MinorRadius::get()
+{ return m_pEllipsoid->MinorRadius(); }
+
+//*****************************************************************************
+double Ellipsoid::QuarterMeridian::get()
+{ return m_pEllipsoid->QuarterMeridian(); }
+
+//*****************************************************************************
+double Ellipsoid::Area::get()
+{ return m_pEllipsoid->Area(); }
+
+//*****************************************************************************
+double Ellipsoid::Volume::get()
+{ return m_pEllipsoid->Volume(); }
+
+//*****************************************************************************
+double Ellipsoid::Flattening::get()
+{ return m_pEllipsoid->Flattening(); }
+
+//*****************************************************************************
+double Ellipsoid::SecondFlattening::get()
+{ return m_pEllipsoid->SecondFlattening(); }
+
+//*****************************************************************************
+double Ellipsoid::ThirdFlattening::get()
+{ return m_pEllipsoid->ThirdFlattening(); }
+
+//*****************************************************************************
+double Ellipsoid::EccentricitySq::get()
+{ return m_pEllipsoid->EccentricitySq(); }
+
+//*****************************************************************************
+double Ellipsoid::SecondEccentricitySq::get()
+{ return m_pEllipsoid->SecondEccentricitySq(); }
+
+//*****************************************************************************
+double Ellipsoid::ThirdEccentricitySq::get()
+{ return m_pEllipsoid->ThirdEccentricitySq(); }
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Ellipsoid.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Ellipsoid.h
new file mode 100644
index 000000000..751bf6c5a
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Ellipsoid.h
@@ -0,0 +1,521 @@
+/**
+ * \file NETGeographicLib/Ellipsoid.h
+ * \brief Header for NETGeographicLib::Ellipsoid class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+
+namespace NETGeographicLib
+{
+ /**
+ * \brief .NET wrapper for GeographicLib::Ellipsoid.
+ *
+ * This class allows .NET applications to access GeographicLib::Ellipsoid.
+ *
+ * This class returns various properties of the ellipsoid and converts
+ * between various types of latitudes. The latitude conversions are also
+ * possible using the various projections supported by %GeographicLib; but
+ * Ellipsoid provides more direct access (sometimes using private functions
+ * of the projection classes). Ellipsoid::RectifyingLatitude,
+ * Ellipsoid::InverseRectifyingLatitude, and Ellipsoid::MeridianDistance
+ * provide functionality which can be provided by the Geodesic class.
+ * However Geodesic uses a series approximation (valid for abs \e f < 1/150),
+ * whereas Ellipsoid computes these quantities using EllipticFunction which
+ * provides accurate results even when \e f is large. Use of this class
+ * should be limited to −3 < \e f < 3/4 (i.e., 1/4 < b/a < 4).
+ *
+ * C# Example:
+ * \include example-Ellipsoid.cs
+ * Managed C++ Example:
+ * \include example-Ellipsoid.cpp
+ * Visual Basic Example:
+ * \include example-Ellipsoid.vb
+ *
+ * INTERFACE DIFFERENCES:
+ * A default constructor has been provided that assumes a WGS84 ellipsoid.
+ *
+ * The following functions are implemented as properties:
+ * MajorRadius, MinorRadius, QuarterMeridian, Area, Volume, Flattening,
+ * SecondFlattening, ThirdFlattening, EccentricitySq, SecondEccentricitySq,
+ * and ThirdEccentricitySq.
+ **********************************************************************/
+ public ref class Ellipsoid
+ {
+ private:
+ // A pointer to the unmanaged GeographicLib::Ellipsoid
+ GeographicLib::Ellipsoid* m_pEllipsoid;
+
+ // Th efinalizer frees the unmanaged memory when the object is destroyed.
+ !Ellipsoid();
+ public:
+ /** \name Constructor
+ **********************************************************************/
+ ///@{
+
+ /**
+ * Constructor for a WGS84 ellipsoid
+ **********************************************************************/
+ Ellipsoid();
+
+ /**
+ * Constructor for a ellipsoid with
+ *
+ * @param[in] a equatorial radius (meters).
+ * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
+ * Negative \e f gives a prolate ellipsoid. If \e f > 1, set flattening
+ * to 1/\e f.
+ * @exception GeographicErr if \e a or (1 − \e f ) \e a is not
+ * positive.
+ **********************************************************************/
+ Ellipsoid(double a, double f);
+ ///@}
+
+ /** The destructor calls the finalizer.
+ **********************************************************************/
+ ~Ellipsoid()
+ { this->!Ellipsoid(); }
+
+ /** \name %Ellipsoid dimensions.
+ **********************************************************************/
+ ///@{
+
+ /**
+ * @return \e a the equatorial radius of the ellipsoid (meters). This is
+ * the value used in the constructor.
+ **********************************************************************/
+ property double MajorRadius { double get(); }
+
+ /**
+ * @return \e b the polar semi-axis (meters).
+ **********************************************************************/
+ property double MinorRadius { double get(); }
+
+ /**
+ * @return \e L the distance between the equator and a pole along a
+ * meridian (meters). For a sphere \e L = (π/2) \e a. The radius
+ * of a sphere with the same meridian length is \e L / (π/2).
+ **********************************************************************/
+ property double QuarterMeridian { double get(); }
+
+ /**
+ * @return \e A the total area of the ellipsoid (meters2). For
+ * a sphere \e A = 4π a2. The radius of a sphere
+ * with the same area is sqrt(\e A / (4π)).
+ **********************************************************************/
+ property double Area { double get(); }
+
+ /**
+ * @return \e V the total volume of the ellipsoid (meters3).
+ * For a sphere \e V = (4π / 3) a3. The radius of
+ * a sphere with the same volume is cbrt(\e V / (4π/3)).
+ **********************************************************************/
+ property double Volume { double get(); }
+ ///@}
+
+ /** \name %Ellipsoid shape
+ **********************************************************************/
+ ///@{
+
+ /**
+ * @return \e f = (\e a − \e b) / \e a, the flattening of the
+ * ellipsoid. This is the value used in the constructor. This is zero,
+ * positive, or negative for a sphere, oblate ellipsoid, or prolate
+ * ellipsoid.
+ **********************************************************************/
+ property double Flattening { double get(); }
+
+ /**
+ * @return \e f ' = (\e a − \e b) / \e b, the second flattening of
+ * the ellipsoid. This is zero, positive, or negative for a sphere,
+ * oblate ellipsoid, or prolate ellipsoid.
+ **********************************************************************/
+ property double SecondFlattening { double get(); }
+
+ /**
+ * @return \e n = (\e a − \e b) / (\e a + \e b), the third flattening
+ * of the ellipsoid. This is zero, positive, or negative for a sphere,
+ * oblate ellipsoid, or prolate ellipsoid.
+ **********************************************************************/
+ property double ThirdFlattening { double get(); }
+
+ /**
+ * @return e2 = (a2 −
+ * b2) / a2, the eccentricity squared
+ * of the ellipsoid. This is zero, positive, or negative for a sphere,
+ * oblate ellipsoid, or prolate ellipsoid.
+ **********************************************************************/
+ property double EccentricitySq { double get(); }
+
+ /**
+ * @return e'2 = (a2 −
+ * b2) / b2, the second eccentricity
+ * squared of the ellipsoid. This is zero, positive, or negative for a
+ * sphere, oblate ellipsoid, or prolate ellipsoid.
+ **********************************************************************/
+ property double SecondEccentricitySq { double get(); }
+
+ /**
+ * @return e''2 = (a2 −
+ * b2) / (a2 + b2),
+ * the third eccentricity squared of the ellipsoid. This is zero,
+ * positive, or negative for a sphere, oblate ellipsoid, or prolate
+ * ellipsoid.
+ **********************************************************************/
+ property double ThirdEccentricitySq { double get(); }
+ ///@}
+
+ /** \name Latitude conversion.
+ **********************************************************************/
+ ///@{
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return β the parametric latitude (degrees).
+ *
+ * The geographic latitude, φ, is the angle beween the equatorial
+ * plane and a vector normal to the surface of the ellipsoid.
+ *
+ * The parametric latitude (also called the reduced latitude), β,
+ * allows the cartesian coordinated of a meridian to be expressed
+ * conveniently in parametric form as
+ * - \e R = \e a cos β
+ * - \e Z = \e b sin β
+ * .
+ * where \e a and \e b are the equatorial radius and the polar semi-axis.
+ * For a sphere β = φ.
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold. The returned value
+ * β lies in [−90°, 90°].
+ **********************************************************************/
+ double ParametricLatitude(double phi);
+
+ /**
+ * @param[in] beta the parametric latitude (degrees).
+ * @return φ the geographic latitude (degrees).
+ *
+ * β must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold. The returned value
+ * φ lies in [−90°, 90°].
+ **********************************************************************/
+ double InverseParametricLatitude(double beta);
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return θ the geocentric latitude (degrees).
+ *
+ * The geocentric latitude, θ, is the angle beween the equatorial
+ * plane and a line between the center of the ellipsoid and a point on the
+ * ellipsoid. For a sphere θ = φ.
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold. The returned value
+ * θ lies in [−90°, 90°].
+ **********************************************************************/
+ double GeocentricLatitude(double phi);
+
+ /**
+ * @param[in] theta the geocentric latitude (degrees).
+ * @return φ the geographic latitude (degrees).
+ *
+ * θ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold. The returned value
+ * φ lies in [−90°, 90°].
+ **********************************************************************/
+ double InverseGeocentricLatitude(double theta);
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return μ the rectifying latitude (degrees).
+ *
+ * The rectifying latitude, μ, has the property that the distance along
+ * a meridian of the ellipsoid between two points with rectifying latitudes
+ * μ1 and μ2 is equal to
+ * (μ2 - μ1) \e L / 90°,
+ * where \e L = QuarterMeridian(). For a sphere μ = φ.
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold. The returned value
+ * μ lies in [−90°, 90°].
+ **********************************************************************/
+ double RectifyingLatitude(double phi);
+
+ /**
+ * @param[in] mu the rectifying latitude (degrees).
+ * @return φ the geographic latitude (degrees).
+ *
+ * μ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold. The returned value
+ * φ lies in [−90°, 90°].
+ **********************************************************************/
+ double InverseRectifyingLatitude(double mu);
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return ξ the authalic latitude (degrees).
+ *
+ * The authalic latitude, ξ, has the property that the area of the
+ * ellipsoid between two circles with authalic latitudes
+ * ξ1 and ξ2 is equal to (sin
+ * ξ2 - sin ξ1) \e A / 2, where \e A
+ * = Area(). For a sphere ξ = φ.
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold. The returned value
+ * ξ lies in [−90°, 90°].
+ **********************************************************************/
+ double AuthalicLatitude(double phi);
+
+ /**
+ * @param[in] xi the authalic latitude (degrees).
+ * @return φ the geographic latitude (degrees).
+ *
+ * ξ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold. The returned value
+ * φ lies in [−90°, 90°].
+ **********************************************************************/
+ double InverseAuthalicLatitude(double xi);
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return χ the conformal latitude (degrees).
+ *
+ * The conformal latitude, χ, gives the mapping of the ellipsoid to a
+ * sphere which which is conformal (angles are preserved) and in which the
+ * equator of the ellipsoid maps to the equator of the sphere. For a
+ * sphere χ = φ.
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold. The returned value
+ * χ lies in [−90°, 90°].
+ **********************************************************************/
+ double ConformalLatitude(double phi);
+
+ /**
+ * @param[in] chi the conformal latitude (degrees).
+ * @return φ the geographic latitude (degrees).
+ *
+ * χ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold. The returned value
+ * φ lies in [−90°, 90°].
+ **********************************************************************/
+ double InverseConformalLatitude(double chi);
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return ψ the isometric latitude (degrees).
+ *
+ * The isometric latitude gives the mapping of the ellipsoid to a plane
+ * which which is conformal (angles are preserved) and in which the equator
+ * of the ellipsoid maps to a straight line of constant scale; this mapping
+ * defines the Mercator projection. For a sphere ψ =
+ * sinh−1 tan φ.
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold.
+ **********************************************************************/
+ double IsometricLatitude(double phi);
+
+ /**
+ * @param[in] psi the isometric latitude (degrees).
+ * @return φ the geographic latitude (degrees).
+ *
+ * The returned value φ lies in [−90°, 90°].
+ **********************************************************************/
+ double InverseIsometricLatitude(double psi);
+ ///@}
+
+ /** \name Other quantities.
+ **********************************************************************/
+ ///@{
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return \e R = \e a cos β the radius of a circle of latitude
+ * φ (meters). \e R (π/180°) gives meters per degree
+ * longitude measured along a circle of latitude.
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold.
+ **********************************************************************/
+ double CircleRadius(double phi);
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return \e Z = \e b sin β the distance of a circle of latitude
+ * φ from the equator measured parallel to the ellipsoid axis
+ * (meters).
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold.
+ **********************************************************************/
+ double CircleHeight(double phi);
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return \e s the distance along a meridian
+ * between the equator and a point of latitude φ (meters). \e s is
+ * given by \e s = μ \e L / 90°, where \e L =
+ * QuarterMeridian()).
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold.
+ **********************************************************************/
+ double MeridianDistance(double phi);
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return ρ the meridional radius of curvature of the ellipsoid at
+ * latitude φ (meters); this is the curvature of the meridian. \e
+ * rho is given by ρ = (180°/π) d\e s / dφ,
+ * where \e s = MeridianDistance(); thus ρ (π/180°)
+ * gives meters per degree latitude measured along a meridian.
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold.
+ **********************************************************************/
+ double MeridionalCurvatureRadius(double phi);
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @return ν the transverse radius of curvature of the ellipsoid at
+ * latitude φ (meters); this is the curvature of a curve on the
+ * ellipsoid which also lies in a plane perpendicular to the ellipsoid
+ * and to the meridian. ν is related to \e R = CircleRadius() by \e
+ * R = ν cos φ.
+ *
+ * φ must lie in the range [−90°, 90°]; the
+ * result is undefined if this condition does not hold.
+ **********************************************************************/
+ double TransverseCurvatureRadius(double phi);
+
+ /**
+ * @param[in] phi the geographic latitude (degrees).
+ * @param[in] azi the angle between the meridian and the normal section
+ * (degrees).
+ * @return the radius of curvature of the ellipsoid in the normal
+ * section at latitude φ inclined at an angle \e azi to the
+ * meridian (meters).
+ *
+ * φ must lie in the range [−90°, 90°] and \e
+ * azi must lie in the range [−540°, 540°); the
+ * result is undefined if either of conditions does not hold.
+ **********************************************************************/
+ double NormalCurvatureRadius(double phi, double azi);
+ ///@}
+
+ /** \name Eccentricity conversions.
+ **********************************************************************/
+ ///@{
+
+ /**
+ * @param[in] fp = \e f ' = (\e a − \e b) / \e b, the second
+ * flattening.
+ * @return \e f = (\e a − \e b) / \e a, the flattening.
+ *
+ * \e f ' should lie in (−1, ∞).
+ * The returned value \e f lies in (−∞, 1).
+ **********************************************************************/
+ static double SecondFlatteningToFlattening(double fp);
+
+ /**
+ * @param[in] f = (\e a − \e b) / \e a, the flattening.
+ * @return \e f ' = (\e a − \e b) / \e b, the second flattening.
+ *
+ * \e f should lie in (−∞, 1).
+ * The returned value \e f ' lies in (−1, ∞).
+ **********************************************************************/
+ static double FlatteningToSecondFlattening(double f);
+
+ /**
+ * @param[in] n = (\e a − \e b) / (\e a + \e b), the third
+ * flattening.
+ * @return \e f = (\e a − \e b) / \e a, the flattening.
+ *
+ * \e n should lie in (−1, 1).
+ * The returned value \e f lies in (−∞, 1).
+ **********************************************************************/
+ static double ThirdFlatteningToFlattening(double n);
+
+ /**
+ * @param[in] f = (\e a − \e b) / \e a, the flattening.
+ * @return \e n = (\e a − \e b) / (\e a + \e b), the third
+ * flattening.
+ *
+ * \e f should lie in (−∞, 1).
+ * The returned value \e n lies in (−1, 1).
+ **********************************************************************/
+ static double FlatteningToThirdFlattening(double f);
+
+ /**
+ * @param[in] e2 = e2 = (a2 −
+ * b2) / a2, the eccentricity
+ * squared.
+ * @return \e f = (\e a − \e b) / \e a, the flattening.
+ *
+ * e2 should lie in (−∞, 1).
+ * The returned value \e f lies in (−∞, 1).
+ **********************************************************************/
+ static double EccentricitySqToFlattening(double e2);
+
+ /**
+ * @param[in] f = (\e a − \e b) / \e a, the flattening.
+ * @return e2 = (a2 −
+ * b2) / a2, the eccentricity
+ * squared.
+ *
+ * \e f should lie in (−∞, 1).
+ * The returned value e2 lies in (−∞, 1).
+ **********************************************************************/
+ static double FlatteningToEccentricitySq(double f);
+
+ /**
+ * @param[in] ep2 = e'2 = (a2 −
+ * b2) / b2, the second eccentricity
+ * squared.
+ * @return \e f = (\e a − \e b) / \e a, the flattening.
+ *
+ * e'2 should lie in (−1, ∞).
+ * The returned value \e f lies in (−∞, 1).
+ **********************************************************************/
+ static double SecondEccentricitySqToFlattening(double ep2);
+
+ /**
+ * @param[in] f = (\e a − \e b) / \e a, the flattening.
+ * @return e'2 = (a2 −
+ * b2) / b2, the second eccentricity
+ * squared.
+ *
+ * \e f should lie in (−∞, 1).
+ * The returned value e'2 lies in (−1, ∞).
+ **********************************************************************/
+ static double FlatteningToSecondEccentricitySq(double f);
+
+ /**
+ * @param[in] epp2 = e''2 = (a2
+ * − b2) / (a2 +
+ * b2), the third eccentricity squared.
+ * @return \e f = (\e a − \e b) / \e a, the flattening.
+ *
+ * e''2 should lie in (−1, 1).
+ * The returned value \e f lies in (−∞, 1).
+ **********************************************************************/
+ static double ThirdEccentricitySqToFlattening(double epp2);
+
+ /**
+ * @param[in] f = (\e a − \e b) / \e a, the flattening.
+ * @return e''2 = (a2 −
+ * b2) / (a2 + b2),
+ * the third eccentricity squared.
+ *
+ * \e f should lie in (−∞, 1).
+ * The returned value e''2 lies in (−1, 1).
+ **********************************************************************/
+ static double FlatteningToThirdEccentricitySq(double f);
+ };
+} // namespace NETGeographicLib
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/EllipticFunction.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/EllipticFunction.cpp
new file mode 100644
index 000000000..1a05b8a56
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/EllipticFunction.cpp
@@ -0,0 +1,311 @@
+/**
+ * \file NETGeographicLib/EllipticFunction.cpp
+ * \brief Implementation for NETGeographicLib::EllipticFunction class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/EllipticFunction.hpp"
+#include "EllipticFunction.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+const char BADALLOC[] = "Failed to allocate memory for the GeographicLib::EllipticFunction.";
+
+//*****************************************************************************
+EllipticFunction::EllipticFunction(double k2, double alpha2)
+{
+ try
+ {
+ m_pEllipticFunction = new GeographicLib::EllipticFunction( k2, alpha2 );
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+EllipticFunction::EllipticFunction(double k2, double alpha2, double kp2, double alphap2)
+{
+ try
+ {
+ m_pEllipticFunction = new GeographicLib::EllipticFunction( k2, alpha2, kp2, alphap2 );
+ }
+ catch ( std::bad_alloc err )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+EllipticFunction::!EllipticFunction()
+{
+ if ( m_pEllipticFunction != NULL )
+ {
+ delete m_pEllipticFunction;
+ m_pEllipticFunction = NULL;
+ }
+}
+
+//*****************************************************************************
+void EllipticFunction::Reset(double k2, double alpha2 )
+{
+ m_pEllipticFunction->Reset( k2, alpha2 );
+}
+
+//*****************************************************************************
+void EllipticFunction::Reset(double k2, double alpha2, double kp2, double alphap2)
+{
+ m_pEllipticFunction->Reset( k2, alpha2, kp2, alphap2 );
+}
+
+//*****************************************************************************
+double EllipticFunction::K()
+{
+ return m_pEllipticFunction->K();
+}
+
+//*****************************************************************************
+double EllipticFunction::E()
+{
+ return m_pEllipticFunction->E();
+}
+
+//*****************************************************************************
+double EllipticFunction::D()
+{
+ return m_pEllipticFunction->D();
+}
+
+//*****************************************************************************
+double EllipticFunction::KE()
+{
+ return m_pEllipticFunction->KE();
+}
+
+//*****************************************************************************
+double EllipticFunction::Pi()
+{
+ return m_pEllipticFunction->Pi();
+}
+
+//*****************************************************************************
+double EllipticFunction::G()
+{
+ return m_pEllipticFunction->G();
+}
+
+//*****************************************************************************
+double EllipticFunction::H()
+{
+ return m_pEllipticFunction->H();
+}
+
+//*****************************************************************************
+double EllipticFunction::F(double phi)
+{
+ return m_pEllipticFunction->F( phi );
+}
+
+//*****************************************************************************
+double EllipticFunction::E(double phi)
+{
+ return m_pEllipticFunction->E( phi );
+}
+
+//*****************************************************************************
+double EllipticFunction::Ed(double ang)
+{
+ return m_pEllipticFunction->Ed(ang);
+}
+
+//*****************************************************************************
+double EllipticFunction::Einv(double x)
+{
+ return m_pEllipticFunction->Einv(x);
+}
+
+//*****************************************************************************
+double EllipticFunction::Pi(double phi)
+{
+ return m_pEllipticFunction->Pi(phi);
+}
+
+//*****************************************************************************
+double EllipticFunction::D(double phi)
+{
+ return m_pEllipticFunction->D(phi);
+}
+
+//*****************************************************************************
+double EllipticFunction::G(double phi)
+{
+ return m_pEllipticFunction->G(phi);
+}
+
+//*****************************************************************************
+double EllipticFunction::H(double phi)
+{
+ return m_pEllipticFunction->H(phi);
+}
+
+//*****************************************************************************
+double EllipticFunction::F(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->F( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::E(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->E( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::Pi(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->Pi( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::D(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->D( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::G(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->G( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::H(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->H( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::deltaF(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->deltaF( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::deltaE(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->deltaE( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::deltaEinv(double stau, double ctau)
+{
+ return m_pEllipticFunction->deltaEinv( stau, ctau );
+}
+
+//*****************************************************************************
+double EllipticFunction::deltaPi(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->deltaPi( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::deltaD(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->deltaD( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::deltaG(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->deltaG( sn, cn, dn );
+}
+
+//*****************************************************************************
+double EllipticFunction::deltaH(double sn, double cn, double dn)
+{
+ return m_pEllipticFunction->deltaH( sn, cn, dn );
+}
+
+//*****************************************************************************
+void EllipticFunction::sncndn(double x,
+ [System::Runtime::InteropServices::Out] double% sn,
+ [System::Runtime::InteropServices::Out] double% cn,
+ [System::Runtime::InteropServices::Out] double% dn)
+{
+ double lsn, lcn, ldn;
+ m_pEllipticFunction->sncndn( x, lsn, lcn, ldn );
+ sn = lsn;
+ cn = lcn;
+ dn = ldn;
+}
+
+//*****************************************************************************
+double EllipticFunction::Delta(double sn, double cn)
+{
+ return m_pEllipticFunction->Delta( sn, cn );
+}
+
+//*****************************************************************************
+double EllipticFunction::RF(double x, double y, double z)
+{
+ return GeographicLib::EllipticFunction::RF( x, y, z );
+}
+
+//*****************************************************************************
+double EllipticFunction::RF(double x, double y)
+{
+ return GeographicLib::EllipticFunction::RF( x, y );
+}
+
+//*****************************************************************************
+double EllipticFunction::RC(double x, double y)
+{
+ return GeographicLib::EllipticFunction::RC( x, y );
+}
+
+//*****************************************************************************
+double EllipticFunction::RG(double x, double y, double z)
+{
+ return GeographicLib::EllipticFunction::RG( x, y, z );
+}
+
+//*****************************************************************************
+double EllipticFunction::RG(double x, double y)
+{
+ return GeographicLib::EllipticFunction::RG( x, y );
+}
+
+//*****************************************************************************
+double EllipticFunction::RJ(double x, double y, double z, double p)
+{
+ return GeographicLib::EllipticFunction::RJ( x, y, z, p );
+}
+
+//*****************************************************************************
+double EllipticFunction::RD(double x, double y, double z)
+{
+ return GeographicLib::EllipticFunction::RD( x, y, z );
+}
+
+//*****************************************************************************
+double EllipticFunction::k2::get()
+{ return m_pEllipticFunction->k2(); }
+
+//*****************************************************************************
+double EllipticFunction::kp2::get()
+{ return m_pEllipticFunction->kp2(); }
+
+//*****************************************************************************
+double EllipticFunction::alpha2::get()
+{ return m_pEllipticFunction->alpha2(); }
+
+//*****************************************************************************
+double EllipticFunction::alphap2::get()
+{ return m_pEllipticFunction->alpha2(); }
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/EllipticFunction.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/EllipticFunction.h
new file mode 100644
index 000000000..e62442a49
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/EllipticFunction.h
@@ -0,0 +1,698 @@
+/**
+ * \file NETGeographicLib/EllipticFunction.h
+ * \brief Header for NETGeographicLib::EllipticFunction class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+
+namespace NETGeographicLib
+{
+ /**
+ * \brief .NET wrapper for GeographicLib::EllipticFunction.
+ *
+ * This class allows .NET applications to access GeographicLib::EllipticFunction.
+ *
+ * This provides the elliptic functions and integrals needed for Ellipsoid,
+ * GeodesicExact, and TransverseMercatorExact. Two categories of function
+ * are provided:
+ * - \e static functions to compute symmetric elliptic integrals
+ * (http://dlmf.nist.gov/19.16.i)
+ * - \e member functions to compute Legrendre's elliptic
+ * integrals (http://dlmf.nist.gov/19.2.ii) and the
+ * Jacobi elliptic functions (http://dlmf.nist.gov/22.2).
+ * .
+ * In the latter case, an object is constructed giving the modulus \e k (and
+ * optionally the parameter α2). The modulus is always
+ * passed as its square k2 which allows \e k to be pure
+ * imaginary (k2 < 0). (Confusingly, Abramowitz and
+ * Stegun call \e m = k2 the "parameter" and \e n =
+ * α2 the "characteristic".)
+ *
+ * In geodesic applications, it is convenient to separate the incomplete
+ * integrals into secular and periodic components, e.g.,
+ * \f[
+ * E(\phi, k) = (2 E(\phi) / \pi) [ \phi + \delta E(\phi, k) ]
+ * \f]
+ * where δ\e E(φ, \e k) is an odd periodic function with period
+ * π.
+ *
+ * The computation of the elliptic integrals uses the algorithms given in
+ * - B. C. Carlson,
+ * Computation of real or
+ * complex elliptic integrals, Numerical Algorithms 10, 13--26 (1995)
+ * .
+ * with the additional optimizations given in http://dlmf.nist.gov/19.36.i.
+ * The computation of the Jacobi elliptic functions uses the algorithm given
+ * in
+ * - R. Bulirsch,
+ * Numerical Calculation of
+ * Elliptic Integrals and Elliptic Functions, Numericshe Mathematik 7,
+ * 78--90 (1965).
+ * .
+ * The notation follows http://dlmf.nist.gov/19 and http://dlmf.nist.gov/22
+ *
+ * C# Example:
+ * \include example-EllipticFunction.cs
+ * Managed C++ Example:
+ * \include example-EllipticFunction.cpp
+ * Visual Basic Example:
+ * \include example-EllipticFunction.vb
+ *
+ * INTERFACE DIFFERENCES:
+ * The k2, kp2, alpha2, and alphap2 functions are implemented as properties.
+ **********************************************************************/
+ public ref class EllipticFunction
+ {
+ private:
+ // a pointer to the unmanaged GeographicLib::EllipticFunction.
+ GeographicLib::EllipticFunction* m_pEllipticFunction;
+
+ // The finalizer frees the unmanaged memory.
+ !EllipticFunction();
+ public:
+ /** \name Constructor
+ **********************************************************************/
+ ///@{
+ /**
+ * Constructor specifying the modulus and parameter.
+ *
+ * @param[in] k2 the square of the modulus k2.
+ * k2 must lie in (-∞, 1). (No checking is
+ * done.)
+ * @param[in] alpha2 the parameter α2.
+ * α2 must lie in (-∞, 1). (No checking is done.)
+ *
+ * If only elliptic integrals of the first and second kinds are needed,
+ * then set α2 = 0 (the default value); in this case, we
+ * have Π(φ, 0, \e k) = \e F(φ, \e k), \e G(φ, 0, \e k) = \e
+ * E(φ, \e k), and \e H(φ, 0, \e k) = \e F(φ, \e k) - \e
+ * D(φ, \e k).
+ **********************************************************************/
+ EllipticFunction(double k2, double alpha2 );
+
+ /**
+ * Constructor specifying the modulus and parameter and their complements.
+ *
+ * @param[in] k2 the square of the modulus k2.
+ * k2 must lie in (-∞, 1). (No checking is
+ * done.)
+ * @param[in] alpha2 the parameter α2.
+ * α2 must lie in (-∞, 1). (No checking is done.)
+ * @param[in] kp2 the complementary modulus squared k'2 =
+ * 1 − k2.
+ * @param[in] alphap2 the complementary parameter α'2 = 1
+ * − α2.
+ *
+ * The arguments must satisfy \e k2 + \e kp2 = 1 and \e alpha2 + \e alphap2
+ * = 1. (No checking is done that these conditions are met.) This
+ * constructor is provided to enable accuracy to be maintained, e.g., when
+ * \e k is very close to unity.
+ **********************************************************************/
+ EllipticFunction(double k2, double alpha2, double kp2, double alphap2);
+
+ /**
+ * Destructor calls the finalizer.
+ **********************************************************************/
+ ~EllipticFunction()
+ { this->!EllipticFunction(); }
+
+ /**
+ * Reset the modulus and parameter.
+ *
+ * @param[in] k2 the new value of square of the modulus
+ * k2 which must lie in (-∞, 1). (No checking is
+ * done.)
+ * @param[in] alpha2 the new value of parameter α2.
+ * α2 must lie in (-∞, 1). (No checking is done.)
+ **********************************************************************/
+ void Reset(double k2, double alpha2 );
+
+ /**
+ * Reset the modulus and parameter supplying also their complements.
+ *
+ * @param[in] k2 the square of the modulus k2.
+ * k2 must lie in (-∞, 1). (No checking is
+ * done.)
+ * @param[in] alpha2 the parameter α2.
+ * α2 must lie in (-∞, 1). (No checking is done.)
+ * @param[in] kp2 the complementary modulus squared k'2 =
+ * 1 − k2.
+ * @param[in] alphap2 the complementary parameter α'2 = 1
+ * − α2.
+ *
+ * The arguments must satisfy \e k2 + \e kp2 = 1 and \e alpha2 + \e alphap2
+ * = 1. (No checking is done that these conditions are met.) This
+ * constructor is provided to enable accuracy to be maintained, e.g., when
+ * is very small.
+ **********************************************************************/
+ void Reset(double k2, double alpha2, double kp2, double alphap2);
+
+ ///@}
+
+ /** \name Inspector functions.
+ **********************************************************************/
+ ///@{
+ /**
+ * @return the square of the modulus k2.
+ **********************************************************************/
+ property double k2 { double get(); }
+
+ /**
+ * @return the square of the complementary modulus k'2 =
+ * 1 − k2.
+ **********************************************************************/
+ property double kp2 { double get(); }
+
+ /**
+ * @return the parameter α2.
+ **********************************************************************/
+ property double alpha2 { double get(); }
+
+ /**
+ * @return the complementary parameter α'2 = 1 −
+ * α2.
+ **********************************************************************/
+ property double alphap2 { double get(); }
+ ///@}
+
+ /** \name Complete elliptic integrals.
+ **********************************************************************/
+ ///@{
+ /**
+ * The complete integral of the first kind.
+ *
+ * @return \e K(\e k).
+ *
+ * \e K(\e k) is defined in http://dlmf.nist.gov/19.2.E4
+ * \f[
+ * K(k) = \int_0^{\pi/2} \frac1{\sqrt{1-k^2\sin^2\phi}}\,d\phi.
+ * \f]
+ **********************************************************************/
+ double K();
+
+ /**
+ * The complete integral of the second kind.
+ *
+ * @return \e E(\e k)
+ *
+ * \e E(\e k) is defined in http://dlmf.nist.gov/19.2.E5
+ * \f[
+ * E(k) = \int_0^{\pi/2} \sqrt{1-k^2\sin^2\phi}\,d\phi.
+ * \f]
+ **********************************************************************/
+ double E();
+
+ /**
+ * Jahnke's complete integral.
+ *
+ * @return \e D(\e k).
+ *
+ * \e D(\e k) is defined in http://dlmf.nist.gov/19.2.E6
+ * \f[
+ * D(k) = \int_0^{\pi/2} \frac{\sin^2\phi}{\sqrt{1-k^2\sin^2\phi}}\,d\phi.
+ * \f]
+ **********************************************************************/
+ double D();
+
+ /**
+ * The difference between the complete integrals of the first and second
+ * kinds.
+ *
+ * @return \e K(\e k) − \e E(\e k).
+ **********************************************************************/
+ double KE();
+
+ /**
+ * The complete integral of the third kind.
+ *
+ * @return Π(α2, \e k)
+ *
+ * Π(α2, \e k) is defined in
+ * http://dlmf.nist.gov/19.2.E7
+ * \f[
+ * \Pi(\alpha^2, k) = \int_0^{\pi/2}
+ * \frac1{\sqrt{1-k^2\sin^2\phi}(1 - \alpha^2\sin^2\phi_)}\,d\phi.
+ * \f]
+ **********************************************************************/
+ double Pi();
+
+ /**
+ * Legendre's complete geodesic longitude integral.
+ *
+ * @return \e G(α2, \e k)
+ *
+ * \e G(α2, \e k) is given by
+ * \f[
+ * G(\alpha^2, k) = \int_0^{\pi/2}
+ * \frac{\sqrt{1-k^2\sin^2\phi}}{1 - \alpha^2\sin^2\phi}\,d\phi.
+ * \f]
+ **********************************************************************/
+ double G();
+
+ /**
+ * Cayley's complete geodesic longitude difference integral.
+ *
+ * @return \e H(α2, \e k)
+ *
+ * \e H(α2, \e k) is given by
+ * \f[
+ * H(\alpha^2, k) = \int_0^{\pi/2}
+ * \frac{\cos^2\phi}{(1-\alpha^2\sin^2\phi)\sqrt{1-k^2\sin^2\phi}}
+ * \,d\phi.
+ * \f]
+ **********************************************************************/
+ double H();
+ ///@}
+
+ /** \name Incomplete elliptic integrals.
+ **********************************************************************/
+ ///@{
+ /**
+ * The incomplete integral of the first kind.
+ *
+ * @param[in] phi
+ * @return \e F(φ, \e k).
+ *
+ * \e F(φ, \e k) is defined in http://dlmf.nist.gov/19.2.E4
+ * \f[
+ * F(\phi, k) = \int_0^\phi \frac1{\sqrt{1-k^2\sin^2\theta}}\,d\theta.
+ * \f]
+ **********************************************************************/
+ double F(double phi);
+
+ /**
+ * The incomplete integral of the second kind.
+ *
+ * @param[in] phi
+ * @return \e E(φ, \e k).
+ *
+ * \e E(φ, \e k) is defined in http://dlmf.nist.gov/19.2.E5
+ * \f[
+ * E(\phi, k) = \int_0^\phi \sqrt{1-k^2\sin^2\theta}\,d\theta.
+ * \f]
+ **********************************************************************/
+ double E(double phi);
+
+ /**
+ * The incomplete integral of the second kind with the argument given in
+ * degrees.
+ *
+ * @param[in] ang in degrees.
+ * @return \e E(π ang/180, \e k).
+ **********************************************************************/
+ double Ed(double ang);
+
+ /**
+ * The inverse of the incomplete integral of the second kind.
+ *
+ * @param[in] x
+ * @return φ = E−1(\e x, \e k); i.e., the
+ * solution of such that \e E(φ, \e k) = \e x.
+ **********************************************************************/
+ double Einv(double x);
+
+ /**
+ * The incomplete integral of the third kind.
+ *
+ * @param[in] phi
+ * @return Π(φ, α2, \e k).
+ *
+ * Π(φ, α2, \e k) is defined in
+ * http://dlmf.nist.gov/19.2.E7
+ * \f[
+ * \Pi(\phi, \alpha^2, k) = \int_0^\phi
+ * \frac1{\sqrt{1-k^2\sin^2\theta}(1 - \alpha^2\sin^2\theta_)}\,d\theta.
+ * \f]
+ **********************************************************************/
+ double Pi(double phi);
+
+ /**
+ * Jahnke's incomplete elliptic integral.
+ *
+ * @param[in] phi
+ * @return \e D(φ, \e k).
+ *
+ * \e D(φ, \e k) is defined in http://dlmf.nist.gov/19.2.E4
+ * \f[
+ * D(\phi, k) = \int_0^\phi
+ * \frac{\sin^2\theta}{\sqrt{1-k^2\sin^2\theta}}\,d\theta.
+ * \f]
+ **********************************************************************/
+ double D(double phi);
+
+ /**
+ * Legendre's geodesic longitude integral.
+ *
+ * @param[in] phi
+ * @return \e G(φ, α2, \e k).
+ *
+ * \e G(φ, α2, \e k) is defined by
+ * \f[
+ * \begin{aligned}
+ * G(\phi, \alpha^2, k) &=
+ * \frac{k^2}{\alpha^2} F(\phi, k) +
+ * \biggl(1 - \frac{k^2}{\alpha^2}\biggr) \Pi(\phi, \alpha^2, k) \\
+ * &= \int_0^\phi
+ * \frac{\sqrt{1-k^2\sin^2\theta}}{1 - \alpha^2\sin^2\theta}\,d\theta.
+ * \end{aligned}
+ * \f]
+ *
+ * Legendre expresses the longitude of a point on the geodesic in terms of
+ * this combination of elliptic integrals in Exercices de Calcul
+ * Intégral, Vol. 1 (1811), p. 181,
+ * http://books.google.com/books?id=riIOAAAAQAAJ&pg=PA181.
+ *
+ * See \ref geodellip for the expression for the longitude in terms of this
+ * function.
+ **********************************************************************/
+ double G(double phi);
+
+ /**
+ * Cayley's geodesic longitude difference integral.
+ *
+ * @param[in] phi
+ * @return \e H(φ, α2, \e k).
+ *
+ * \e H(φ, α2, \e k) is defined by
+ * \f[
+ * \begin{aligned}
+ * H(\phi, \alpha^2, k) &=
+ * \frac1{\alpha^2} F(\phi, k) +
+ * \biggl(1 - \frac1{\alpha^2}\biggr) \Pi(\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.
+ * \end{aligned}
+ * \f]
+ *
+ * Cayley expresses the longitude difference of a point on the geodesic in
+ * terms of this combination of elliptic integrals in Phil. Mag. 40
+ * (1870), p. 333, http://books.google.com/books?id=Zk0wAAAAIAAJ&pg=PA333.
+ *
+ * See \ref geodellip for the expression for the longitude in terms of this
+ * function.
+ **********************************************************************/
+ double H(double phi);
+ ///@}
+
+ /** \name Incomplete integrals in terms of Jacobi elliptic functions.
+ **********************************************************************/
+ /**
+ * The incomplete integral of the first kind in terms of Jacobi elliptic
+ * functions.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return \e F(φ, \e k) as though φ ∈ (−π, π].
+ **********************************************************************/
+ double F(double sn, double cn, double dn);
+
+ /**
+ * The incomplete integral of the second kind in terms of Jacobi elliptic
+ * functions.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return \e E(φ, \e k) as though φ ∈ (−π, π].
+ **********************************************************************/
+ double E(double sn, double cn, double dn);
+
+ /**
+ * The incomplete integral of the third kind in terms of Jacobi elliptic
+ * functions.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return Π(φ, α2, \e k) as though φ ∈
+ * (−π, π].
+ **********************************************************************/
+ double Pi(double sn, double cn, double dn);
+
+ /**
+ * Jahnke's incomplete elliptic integral in terms of Jacobi elliptic
+ * functions.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return \e D(φ, \e k) as though φ ∈ (−π, π].
+ **********************************************************************/
+ double D(double sn, double cn, double dn);
+
+ /**
+ * Legendre's geodesic longitude integral in terms of Jacobi elliptic
+ * functions.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return \e G(φ, α2, \e k) as though φ ∈
+ * (−π, π].
+ **********************************************************************/
+ double G(double sn, double cn, double dn);
+
+ /**
+ * Cayley's geodesic longitude difference integral in terms of Jacobi
+ * elliptic functions.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return \e H(φ, α2, \e k) as though φ ∈
+ * (−π, π].
+ **********************************************************************/
+ double H(double sn, double cn, double dn);
+ ///@}
+
+ /** \name Periodic versions of incomplete elliptic integrals.
+ **********************************************************************/
+ ///@{
+ /**
+ * The periodic incomplete integral of the first kind.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return the periodic function π \e F(φ, \e k) / (2 \e K(\e k)) -
+ * φ
+ **********************************************************************/
+ double deltaF(double sn, double cn, double dn);
+
+ /**
+ * The periodic incomplete integral of the second kind.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return the periodic function π \e E(φ, \e k) / (2 \e E(\e k)) -
+ * φ
+ **********************************************************************/
+ double deltaE(double sn, double cn, double dn);
+
+ /**
+ * The periodic inverse of the incomplete integral of the second kind.
+ *
+ * @param[in] stau = sinτ
+ * @param[in] ctau = sinτ
+ * @return the periodic function E−1(τ (2 \e
+ * E(\e k)/π), \e k) - τ
+ **********************************************************************/
+ double deltaEinv(double stau, double ctau);
+
+ /**
+ * The periodic incomplete integral of the third kind.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return the periodic function π Π(φ, \e k) / (2 Π(\e k)) -
+ * φ
+ **********************************************************************/
+ double deltaPi(double sn, double cn, double dn);
+
+ /**
+ * The periodic Jahnke's incomplete elliptic integral.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return the periodic function π \e D(φ, \e k) / (2 \e D(\e k)) -
+ * φ
+ **********************************************************************/
+ double deltaD(double sn, double cn, double dn);
+
+ /**
+ * Legendre's periodic geodesic longitude integral.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return the periodic function π \e G(φ, \e k) / (2 \e G(\e k)) -
+ * φ
+ **********************************************************************/
+ double deltaG(double sn, double cn, double dn);
+
+ /**
+ * Cayley's periodic geodesic longitude difference integral.
+ *
+ * @param[in] sn = sinφ
+ * @param[in] cn = cosφ
+ * @param[in] dn = sqrt(1 − k2
+ * sin2φ)
+ * @return the periodic function π \e H(φ, \e k) / (2 \e H(\e k)) -
+ * φ
+ **********************************************************************/
+ double deltaH(double sn, double cn, double dn);
+ ///@}
+
+ /** \name Elliptic functions.
+ **********************************************************************/
+ ///@{
+ /**
+ * The Jacobi elliptic functions.
+ *
+ * @param[in] x the argument.
+ * @param[out] sn sn(\e x, \e k).
+ * @param[out] cn cn(\e x, \e k).
+ * @param[out] dn dn(\e x, \e k).
+ **********************************************************************/
+ void sncndn(double x,
+ [System::Runtime::InteropServices::Out] double% sn,
+ [System::Runtime::InteropServices::Out] double% cn,
+ [System::Runtime::InteropServices::Out] double% dn);
+
+ /**
+ * The Δ amplitude function.
+ *
+ * @param[in] sn sinφ
+ * @param[in] cn cosφ
+ * @return Δ = sqrt(1 − k2
+ * sin2φ)
+ **********************************************************************/
+ double Delta(double sn, double cn);
+ ///@}
+
+ /** \name Symmetric elliptic integrals.
+ **********************************************************************/
+ ///@{
+ /**
+ * Symmetric integral of the first kind RF.
+ *
+ * @param[in] x
+ * @param[in] y
+ * @param[in] z
+ * @return RF(\e x, \e y, \e z)
+ *
+ * RF is defined in http://dlmf.nist.gov/19.16.E1
+ * \f[ R_F(x, y, z) = \frac12
+ * \int_0^\infty\frac1{\sqrt{(t + x) (t + y) (t + z)}}\, dt \f]
+ * If one of the arguments is zero, it is more efficient to call the
+ * two-argument version of this function with the non-zero arguments.
+ **********************************************************************/
+ static double RF(double x, double y, double z);
+
+ /**
+ * Complete symmetric integral of the first kind, RF with
+ * one argument zero.
+ *
+ * @param[in] x
+ * @param[in] y
+ * @return RF(\e x, \e y, 0)
+ **********************************************************************/
+ static double RF(double x, double y);
+
+ /**
+ * Degenerate symmetric integral of the first kind RC.
+ *
+ * @param[in] x
+ * @param[in] y
+ * @return RC(\e x, \e y) = RF(\e x, \e
+ * y, \e y)
+ *
+ * RC is defined in http://dlmf.nist.gov/19.2.E17
+ * \f[ R_C(x, y) = \frac12
+ * \int_0^\infty\frac1{\sqrt{t + x}(t + y)}\,dt \f]
+ **********************************************************************/
+ static double RC(double x, double y);
+
+ /**
+ * Symmetric integral of the second kind RG.
+ *
+ * @param[in] x
+ * @param[in] y
+ * @param[in] z
+ * @return RG(\e x, \e y, \e z)
+ *
+ * RG is defined in Carlson, eq 1.5
+ * \f[ R_G(x, y, z) = \frac14
+ * \int_0^\infty[(t + x) (t + y) (t + z)]^{-1/2}
+ * \biggl(
+ * \frac x{t + x} + \frac y{t + y} + \frac z{t + z}
+ * \biggr)t\,dt \f]
+ * See also http://dlmf.nist.gov/19.16.E3.
+ * If one of the arguments is zero, it is more efficient to call the
+ * two-argument version of this function with the non-zero arguments.
+ **********************************************************************/
+ static double RG(double x, double y, double z);
+
+ /**
+ * Complete symmetric integral of the second kind, RG
+ * with one argument zero.
+ *
+ * @param[in] x
+ * @param[in] y
+ * @return RG(\e x, \e y, 0)
+ **********************************************************************/
+ static double RG(double x, double y);
+
+ /**
+ * Symmetric integral of the third kind RJ.
+ *
+ * @param[in] x
+ * @param[in] y
+ * @param[in] z
+ * @param[in] p
+ * @return RJ(\e x, \e y, \e z, \e p)
+ *
+ * RJ is defined in http://dlmf.nist.gov/19.16.E2
+ * \f[ R_J(x, y, z, p) = \frac32
+ * \int_0^\infty[(t + x) (t + y) (t + z)]^{-1/2} (t + p)^{-1}\, dt \f]
+ **********************************************************************/
+ static double RJ(double x, double y, double z, double p);
+
+ /**
+ * Degenerate symmetric integral of the third kind RD.
+ *
+ * @param[in] x
+ * @param[in] y
+ * @param[in] z
+ * @return RD(\e x, \e y, \e z) = RJ(\e
+ * x, \e y, \e z, \e z)
+ *
+ * RD is defined in http://dlmf.nist.gov/19.16.E5
+ * \f[ R_D(x, y, z) = \frac32
+ * \int_0^\infty[(t + x) (t + y)]^{-1/2} (t + z)^{-3/2}\, dt \f]
+ **********************************************************************/
+ static double RD(double x, double y, double z);
+ ///@}
+ };
+} // namespace NETGeographicLib
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/GeoCoords.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/GeoCoords.cpp
new file mode 100644
index 000000000..a060068a1
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/GeoCoords.cpp
@@ -0,0 +1,243 @@
+/**
+ * \file NETGeographicLib/GeoCoords.cpp
+ * \brief Implementation for NETGeographicLib::GeoCoords class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/GeoCoords.hpp"
+#include "GeoCoords.h"
+#include "UTMUPS.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+const char BADALLOC[] = "Failed to allocate memory for a GeographicLib::GeoCoords";
+
+//*****************************************************************************
+GeoCoords::!GeoCoords(void)
+{
+ if ( m_pGeoCoords != NULL )
+ {
+ delete m_pGeoCoords;
+ m_pGeoCoords = NULL;
+ }
+}
+
+//*****************************************************************************
+GeoCoords::GeoCoords()
+{
+ try
+ {
+ m_pGeoCoords = new GeographicLib::GeoCoords();
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+GeoCoords::GeoCoords(System::String^ s, bool centerp, bool swaplatlong )
+{
+ try
+ {
+ m_pGeoCoords = new GeographicLib::GeoCoords(StringConvert::ManagedToUnmanaged(s), centerp, swaplatlong);
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+ catch ( const std::exception& err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+}
+
+//*****************************************************************************
+GeoCoords::GeoCoords(double latitude, double longitude, int zone )
+{
+ try
+ {
+ m_pGeoCoords = new GeographicLib::GeoCoords(latitude, longitude, zone);
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+ catch ( const std::exception& err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+}
+
+//*****************************************************************************
+GeoCoords::GeoCoords(int zone, bool northp, double easting, double northing)
+{
+ try
+ {
+ m_pGeoCoords = new GeographicLib::GeoCoords(zone, northp, easting, northing);
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+ catch ( const std::exception& err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+}
+
+//*****************************************************************************
+void GeoCoords::Reset( System::String^ s, bool centerp, bool swaplatlong )
+{
+ try
+ {
+ m_pGeoCoords->Reset(StringConvert::ManagedToUnmanaged(s), centerp, swaplatlong);
+ }
+ catch ( const std::exception& err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+}
+
+//*****************************************************************************
+void GeoCoords::Reset(double latitude, double longitude, int zone)
+{
+ try
+ {
+ m_pGeoCoords->Reset(latitude, longitude, zone);
+ }
+ catch ( const std::exception& err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+}
+
+//*****************************************************************************
+void GeoCoords::Reset(int zone, bool northp, double easting, double northing)
+{
+ try
+ {
+ m_pGeoCoords->Reset(zone, northp, easting, northing);
+ }
+ catch ( const std::exception& err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+}
+
+//*****************************************************************************
+void GeoCoords::AltZone::set( int zone )
+{
+ try
+ {
+ m_pGeoCoords->SetAltZone(zone);
+ }
+ catch ( GeographicLib::GeographicErr err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+}
+
+//*****************************************************************************
+int GeoCoords::AltZone::get() { return m_pGeoCoords->AltZone(); }
+
+//*****************************************************************************
+double GeoCoords::Latitude::get() { return m_pGeoCoords->Latitude(); }
+
+//*****************************************************************************
+double GeoCoords::Longitude::get() { return m_pGeoCoords->Longitude(); }
+
+//*****************************************************************************
+double GeoCoords::Easting::get() { return m_pGeoCoords->Easting(); }
+
+//*****************************************************************************
+double GeoCoords::Northing::get() { return m_pGeoCoords->Northing(); }
+
+//*****************************************************************************
+double GeoCoords::Convergence::get() { return m_pGeoCoords->Convergence(); }
+
+//*****************************************************************************
+double GeoCoords::Scale::get() { return m_pGeoCoords->Scale(); }
+
+//*****************************************************************************
+bool GeoCoords::Northp::get() { return m_pGeoCoords->Northp(); }
+
+//*****************************************************************************
+char GeoCoords::Hemisphere::get() { return m_pGeoCoords->Hemisphere(); }
+
+//*****************************************************************************
+int GeoCoords::Zone::get() { return m_pGeoCoords->Zone(); }
+
+//*****************************************************************************
+double GeoCoords::AltEasting::get() { return m_pGeoCoords->AltEasting(); }
+
+//*****************************************************************************
+double GeoCoords::AltNorthing::get() { return m_pGeoCoords->AltNorthing(); }
+
+//*****************************************************************************
+double GeoCoords::AltConvergence::get()
+{ return m_pGeoCoords->AltConvergence(); }
+
+//*****************************************************************************
+double GeoCoords::AltScale::get() { return m_pGeoCoords->AltScale(); }
+
+//*****************************************************************************
+double GeoCoords::MajorRadius::get() { return UTMUPS::MajorRadius(); }
+
+//*****************************************************************************
+double GeoCoords::Flattening::get() { return UTMUPS::Flattening(); }
+
+//*****************************************************************************
+System::String^ GeoCoords::GeoRepresentation(int prec, bool swaplatlong )
+{
+ return gcnew System::String( m_pGeoCoords->GeoRepresentation(prec, swaplatlong).c_str() );
+}
+
+//*****************************************************************************
+System::String^ GeoCoords::DMSRepresentation(int prec, bool swaplatlong,
+ char dmssep )
+{
+ return gcnew System::String( m_pGeoCoords->DMSRepresentation(prec, swaplatlong, dmssep).c_str() );
+}
+
+//*****************************************************************************
+System::String^ GeoCoords::MGRSRepresentation(int prec)
+{
+ return gcnew System::String( m_pGeoCoords->MGRSRepresentation(prec).c_str() );
+}
+
+//*****************************************************************************
+System::String^ GeoCoords::UTMUPSRepresentation(int prec)
+{
+ return gcnew System::String( m_pGeoCoords->UTMUPSRepresentation(prec).c_str() );
+}
+
+//*****************************************************************************
+System::String^ GeoCoords::UTMUPSRepresentation(bool northp, int prec)
+{
+ return gcnew System::String( m_pGeoCoords->UTMUPSRepresentation(northp, prec).c_str() );
+}
+
+//*****************************************************************************
+System::String^ GeoCoords::AltMGRSRepresentation(int prec)
+{
+ return gcnew System::String( m_pGeoCoords->AltMGRSRepresentation(prec).c_str() );
+}
+
+//*****************************************************************************
+System::String^ GeoCoords::AltUTMUPSRepresentation(int prec)
+{
+ return gcnew System::String( m_pGeoCoords->AltUTMUPSRepresentation(prec).c_str() );
+}
+
+//*****************************************************************************
+System::String^ GeoCoords::AltUTMUPSRepresentation(bool northp, int prec)
+{
+ return gcnew System::String( m_pGeoCoords->AltUTMUPSRepresentation(northp, prec).c_str() );
+}
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/GeoCoords.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/GeoCoords.h
new file mode 100644
index 000000000..bbc012a17
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/GeoCoords.h
@@ -0,0 +1,474 @@
+/**
+ * \file NETGeographicLib/GeoCoords.h
+ * \brief Header for NETGeographicLib::GeoCoords class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+
+namespace NETGeographicLib
+{
+ /**
+ * \brief .NET wrapper for GeographicLib::GeoCoords.
+ *
+ * This class allows .NET applications to access GeographicLib::GeoCoords.
+ *
+ * This class stores a geographic position which may be set via the
+ * constructors or Reset via
+ * - latitude and longitude
+ * - UTM or UPS coordinates
+ * - a string representation of these or an MGRS coordinate string
+ *
+ * The state consists of the latitude and longitude and the supplied UTM or
+ * UPS coordinates (possibly derived from the MGRS coordinates). If latitude
+ * and longitude were given then the UTM/UPS coordinates follows the standard
+ * conventions.
+ *
+ * The mutable state consists of the UTM or UPS coordinates for a alternate
+ * zone. A method SetAltZone is provided to set the alternate UPS/UTM zone.
+ *
+ * Methods are provided to return the geographic coordinates, the input UTM
+ * or UPS coordinates (and associated meridian convergence and scale), or
+ * alternate UTM or UPS coordinates (and their associated meridian
+ * convergence and scale).
+ *
+ * Once the input string has been parsed, you can print the result out in any
+ * of the formats, decimal degrees, degrees minutes seconds, MGRS, UTM/UPS.
+ *
+ * C# Example:
+ * \include example-GeoCoords.cs
+ * Managed C++ Example:
+ * \include example-GeoCoords.cpp
+ * Visual Basic Example:
+ * \include example-GeoCoords.vb
+ *
+ * INTERFACE DIFFERENCES:
+ * The following functions are implemented as properties: MajorRadius,
+ * Flattening, Latitude, Longitude, Easting, Northing, Convergence,
+ * Scale, Northp, Hemisphere, Zone, AltZone, AltEasting, AltNorthing,
+ * AltConvergence, and AltScale.
+ **********************************************************************/
+ public ref class GeoCoords
+ {
+ private:
+ // pointer to the unmanaged GeographicLib::GeoCoords
+ GeographicLib::GeoCoords* m_pGeoCoords;
+
+ // The finalizer frees unmanaged memory when the object is destroyed.
+ !GeoCoords();
+ public:
+ /** \name Initializing the GeoCoords object
+ **********************************************************************/
+ ///@{
+ /**
+ * The default constructor is equivalent to \e latitude = 90°,
+ * \e longitude = 0°.
+ **********************************************************************/
+ GeoCoords();
+
+ /**
+ * Construct from a string.
+ *
+ * @param[in] s 1-element, 2-element, or 3-element string representation of
+ * the position.
+ * @param[in] centerp governs the interpretation of MGRS coordinates (see
+ * below).
+ * @param[in] swaplatlong governs the interpretation of geographic
+ * coordinates (see below).
+ * @exception GeographicErr if the \e s is malformed (see below).
+ *
+ * Parse as a string and interpret it as a geographic position. The input
+ * string is broken into space (or comma) separated pieces and Basic
+ * decision on which format is based on number of components
+ * -# MGRS
+ * -# "Lat Long" or "Long Lat"
+ * -# "Zone Easting Northing" or "Easting Northing Zone"
+ *
+ * The following inputs are approximately the same (Ar Ramadi Bridge, Iraq)
+ * - Latitude and Longitude
+ * - 33.44 43.27
+ * - N33d26.4' E43d16.2'
+ * - 43d16'12"E 33d26'24"N
+ * - 43:16:12E 33:26:24
+ * - MGRS
+ * - 38SLC301
+ * - 38SLC391014
+ * - 38SLC3918701405
+ * - 37SHT9708
+ * - UTM
+ * - 38N 339188 3701405
+ * - 897039 3708229 37N
+ *
+ * Latitude and Longitude parsing: Latitude precedes longitude,
+ * unless a N, S, E, W hemisphere designator is used on one or both
+ * coordinates. If \e swaplatlong = true (default is false), then
+ * longitude precedes latitude in the absence of a hemisphere designator.
+ * Thus (with \e swaplatlong = false)
+ * - 40 -75
+ * - N40 W75
+ * - -75 N40
+ * - 75W 40N
+ * - E-75 -40S
+ * .
+ * are all the same position. The coordinates may be given in
+ * decimal degrees, degrees and decimal minutes, degrees, minutes,
+ * seconds, etc. Use d, ', and " to mark off the degrees,
+ * minutes and seconds. Various alternative symbols for degrees, minutes,
+ * and seconds are allowed. Alternatively, use : to separate these
+ * components. (See DMS::Decode for details.) Thus
+ * - 40d30'30"
+ * - 40d30'30
+ * - 40°30'30
+ * - 40d30.5'
+ * - 40d30.5
+ * - 40:30:30
+ * - 40:30.5
+ * - 40.508333333
+ * .
+ * all specify the same angle. The leading sign applies to all components
+ * so -1d30 is -(1+30/60) = -1.5. Latitudes must be in the range
+ * [−90°, 90°] and longitudes in the range
+ * [−540°, 540°). Internally longitudes are reduced
+ * to the range [−180°, 180°).
+ *
+ * UTM/UPS parsing: For UTM zones (−80° ≤ Lat <
+ * 84°), the zone designator is made up of a zone number (for 1 to 60)
+ * and a hemisphere letter (N or S), e.g., 38N. The latitude zone designer
+ * ([C--M] in the southern hemisphere and [N--X] in the northern) should
+ * NOT be used. (This is part of the MGRS coordinate.) The zone
+ * designator for the poles (where UPS is employed) is a hemisphere letter
+ * by itself, i.e., N or S.
+ *
+ * MGRS parsing interprets the grid references as square area at the
+ * specified precision (1m, 10m, 100m, etc.). If \e centerp = true (the
+ * default), the center of this square is then taken to be the precise
+ * position; thus:
+ * - 38SMB = 38N 450000 3650000
+ * - 38SMB4484 = 38N 444500 3684500
+ * - 38SMB44148470 = 38N 444145 3684705
+ * .
+ * Otherwise, the "south-west" corner of the square is used, i.e.,
+ * - 38SMB = 38N 400000 3600000
+ * - 38SMB4484 = 38N 444000 3684000
+ * - 38SMB44148470 = 38N 444140 3684700
+ **********************************************************************/
+ GeoCoords(System::String^ s, bool centerp, bool swaplatlong );
+
+ /**
+ * Construct from geographic coordinates.
+ *
+ * @param[in] latitude (degrees).
+ * @param[in] longitude (degrees).
+ * @param[in] zone if specified, force the UTM/UPS representation to use a
+ * specified zone using the rules given in UTMUPS::zonespec.
+ * @exception GeographicErr if \e latitude is not in [−90°,
+ * 90°].
+ * @exception GeographicErr if \e longitude is not in [−540°,
+ * 540°).
+ * @exception GeographicErr if \e zone cannot be used for this location.
+ **********************************************************************/
+ GeoCoords(double latitude, double longitude, int zone );
+
+ /**
+ * Construct from UTM/UPS coordinates.
+ *
+ * @param[in] zone UTM zone (zero means UPS).
+ * @param[in] northp hemisphere (true means north, false means south).
+ * @param[in] easting (meters).
+ * @param[in] northing (meters).
+ * @exception GeographicErr if \e zone, \e easting, or \e northing is
+ * outside its allowed range.
+ **********************************************************************/
+ GeoCoords(int zone, bool northp, double easting, double northing);
+
+ /**
+ * The destructor calls the finalizer.
+ **********************************************************************/
+ ~GeoCoords() { this->!GeoCoords(); }
+
+ /**
+ * Reset the location from a string. See
+ * GeoCoords(const std::string& s, bool centerp, bool swaplatlong).
+ *
+ * @param[in] s 1-element, 2-element, or 3-element string representation of
+ * the position.
+ * @param[in] centerp governs the interpretation of MGRS coordinates.
+ * @param[in] swaplatlong governs the interpretation of geographic
+ * coordinates.
+ * @exception GeographicErr if the \e s is malformed.
+ **********************************************************************/
+ void Reset( System::String^ s, bool centerp, bool swaplatlong);
+
+ /**
+ * Reset the location in terms of geographic coordinates. See
+ * GeoCoords(double latitude, double longitude, int zone).
+ *
+ * @param[in] latitude (degrees).
+ * @param[in] longitude (degrees).
+ * @param[in] zone if specified, force the UTM/UPS representation to use a
+ * specified zone using the rules given in UTMUPS::zonespec.
+ * @exception GeographicErr if \e latitude is not in [−90°,
+ * 90°].
+ * @exception GeographicErr if \e longitude is not in [−540°,
+ * 540°).
+ * @exception GeographicErr if \e zone cannot be used for this location.
+ **********************************************************************/
+ void Reset(double latitude, double longitude, int zone ) ;
+
+ /**
+ * Reset the location in terms of UPS/UPS coordinates. See
+ * GeoCoords(int zone, bool northp, double easting, double northing).
+ *
+ * @param[in] zone UTM zone (zero means UPS).
+ * @param[in] northp hemisphere (true means north, false means south).
+ * @param[in] easting (meters).
+ * @param[in] northing (meters).
+ * @exception GeographicErr if \e zone, \e easting, or \e northing is
+ * outside its allowed range.
+ **********************************************************************/
+ void Reset(int zone, bool northp, double easting, double northing);
+ ///@}
+
+ /** \name Querying the GeoCoords object
+ **********************************************************************/
+ ///@{
+ /**
+ * @return latitude (degrees)
+ **********************************************************************/
+ property double Latitude { double get(); }
+
+ /**
+ * @return longitude (degrees)
+ **********************************************************************/
+ property double Longitude { double get(); }
+
+ /**
+ * @return easting (meters)
+ **********************************************************************/
+ property double Easting { double get(); }
+
+ /**
+ * @return northing (meters)
+ **********************************************************************/
+ property double Northing { double get(); }
+
+ /**
+ * @return meridian convergence (degrees) for the UTM/UPS projection.
+ **********************************************************************/
+ property double Convergence { double get(); }
+
+ /**
+ * @return scale for the UTM/UPS projection.
+ **********************************************************************/
+ property double Scale { double get(); }
+
+ /**
+ * @return hemisphere (false means south, true means north).
+ **********************************************************************/
+ property bool Northp { bool get(); }
+
+ /**
+ * @return hemisphere letter N or S.
+ **********************************************************************/
+ property char Hemisphere { char get(); }
+
+ /**
+ * @return the zone corresponding to the input (return 0 for UPS).
+ **********************************************************************/
+ property int Zone { int get(); }
+
+ /**
+ * Gets/Sets the current alternate zone (0 = UPS).
+ * @exception GeographicErr if \e zone cannot be used for this location.
+ *
+ * See UTMUPS::zonespec for more information on the interpretation of \e
+ * zone. Note that \e zone == UTMUPS::STANDARD (the default) use the
+ * standard UPS or UTM zone, UTMUPS::MATCH does nothing retaining the
+ * existing alternate representation. Before this is called the alternate
+ * zone is the input zone.
+ **********************************************************************/
+ property int AltZone
+ {
+ int get();
+ void set( int zone );
+ }
+ ///@}
+
+ /**
+ * @return easting (meters) for alternate zone.
+ **********************************************************************/
+ property double AltEasting { double get(); }
+
+ /**
+ * @return northing (meters) for alternate zone.
+ **********************************************************************/
+ property double AltNorthing { double get(); }
+
+ /**
+ * @return meridian convergence (degrees) for alternate zone.
+ **********************************************************************/
+ property double AltConvergence { double get(); }
+
+ /**
+ * @return scale for alternate zone.
+ **********************************************************************/
+ property double AltScale { double get(); }
+ ///@}
+
+ /** \name String representations of the GeoCoords object
+ **********************************************************************/
+ ///@{
+ /**
+ * String representation with latitude and longitude as signed decimal
+ * degrees.
+ *
+ * @param[in] prec precision (relative to about 1m).
+ * @param[in] swaplatlong if true give longitude first (default = false)
+ * @exception std::bad_alloc if memory for the string can't be allocated.
+ * @return decimal latitude/longitude string representation.
+ *
+ * Precision specifies accuracy of representation as follows:
+ * - prec = −5 (min), 1°
+ * - prec = 0, 10−5° (about 1m)
+ * - prec = 3, 10−8°
+ * - prec = 9 (max), 10−14°
+ **********************************************************************/
+ System::String^ GeoRepresentation(int prec, bool swaplatlong );
+
+ /**
+ * String representation with latitude and longitude as degrees, minutes,
+ * seconds, and hemisphere.
+ *
+ * @param[in] prec precision (relative to about 1m)
+ * @param[in] swaplatlong if true give longitude first (default = false)
+ * @param[in] dmssep if non-null, use as the DMS separator character
+ * (instead of d, ', " delimiters).
+ * @exception std::bad_alloc if memory for the string can't be allocated.
+ * @return DMS latitude/longitude string representation.
+ *
+ * Precision specifies accuracy of representation as follows:
+ * - prec = −5 (min), 1°
+ * - prec = −4, 0.1°
+ * - prec = −3, 1'
+ * - prec = −2, 0.1'
+ * - prec = −1, 1"
+ * - prec = 0, 0.1" (about 3m)
+ * - prec = 1, 0.01"
+ * - prec = 10 (max), 10−11"
+ **********************************************************************/
+ System::String^ DMSRepresentation(int prec, bool swaplatlong,
+ char dmssep );
+
+ /**
+ * MGRS string.
+ *
+ * @param[in] prec precision (relative to about 1m).
+ * @exception std::bad_alloc if memory for the string can't be allocated.
+ * @return MGRS string.
+ *
+ * This gives the coordinates of the enclosing grid square with size given
+ * by the precision. Thus 38N 444180 3684790 converted to a MGRS
+ * coordinate at precision −2 (100m) is 38SMB441847 and not
+ * 38SMB442848. \e prec specifies the precision of the MGRS string as
+ * follows:
+ * - prec = −5 (min), 100km
+ * - prec = −4, 10km
+ * - prec = −3, 1km
+ * - prec = −2, 100m
+ * - prec = −1, 10m
+ * - prec = 0, 1m
+ * - prec = 1, 0.1m
+ * - prec = 6 (max), 1μm
+ **********************************************************************/
+ System::String^ MGRSRepresentation(int prec);
+
+ /**
+ * UTM/UPS string.
+ *
+ * @param[in] prec precision (relative to about 1m)
+ * @exception std::bad_alloc if memory for the string can't be allocated.
+ * @return UTM/UPS string representation: zone designator, easting, and
+ * northing.
+ *
+ * Precision specifies accuracy of representation as follows:
+ * - prec = −5 (min), 100km
+ * - prec = −3, 1km
+ * - prec = 0, 1m
+ * - prec = 3, 1mm
+ * - prec = 6, 1μm
+ * - prec = 9 (max), 1nm
+ **********************************************************************/
+ System::String^ UTMUPSRepresentation(int prec);
+
+ /**
+ * UTM/UPS string with hemisphere override.
+ *
+ * @param[in] prec precision (relative to about 1m)
+ * @param[in] northp hemisphere override
+ * @exception GeographicErr if the hemisphere override attempts to change
+ * UPS N to UPS S or vice verse.
+ * @exception std::bad_alloc if memory for the string can't be allocated.
+ * @return UTM/UPS string representation: zone designator, easting, and
+ * northing.
+ **********************************************************************/
+ System::String^ UTMUPSRepresentation(bool northp, int prec);
+
+ /**
+ * MGRS string for the alternate zone. See GeoCoords::MGRSRepresentation.
+ *
+ * @param[in] prec precision (relative to about 1m).
+ * @exception std::bad_alloc if memory for the string can't be allocated.
+ * @return MGRS string.
+ **********************************************************************/
+ System::String^ AltMGRSRepresentation(int prec);
+
+ /**
+ * UTM/UPS string for the alternate zone. See
+ * GeoCoords::UTMUPSRepresentation.
+ *
+ * @param[in] prec precision (relative to about 1m)
+ * @exception std::bad_alloc if memory for the string can't be allocated.
+ * @return UTM/UPS string representation: zone designator, easting, and
+ * northing.
+ **********************************************************************/
+ System::String^ AltUTMUPSRepresentation(int prec);
+
+ /**
+ * UTM/UPS string for the alternate zone, with hemisphere override.
+ *
+ * @param[in] prec precision (relative to about 1m)
+ * @param[in] northp hemisphere override
+ * @exception GeographicErr if the hemisphere override attempts to change
+ * UPS N to UPS S or vice verse.
+ * @exception std::bad_alloc if memory for the string can't be allocated.
+ * @return UTM/UPS string representation: zone designator, easting, and
+ * northing.
+ **********************************************************************/
+ System::String^ AltUTMUPSRepresentation(bool northp, int prec);
+ ///@}
+
+ /** \name Inspector functions
+ **********************************************************************/
+ ///@{
+ /**
+ * @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
+ *
+ * (The WGS84 value is returned because the UTM and UPS projections are
+ * based on this ellipsoid.)
+ **********************************************************************/
+ property double MajorRadius { double get(); }
+
+ /**
+ * @return \e f the flattening of the WGS84 ellipsoid.
+ *
+ * (The WGS84 value is returned because the UTM and UPS projections are
+ * based on this ellipsoid.)
+ **********************************************************************/
+ property double Flattening { double get(); }
+ ///@}
+ };
+} //namespace NETGeographicLib
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geocentric.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geocentric.cpp
new file mode 100644
index 000000000..2bbfade68
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geocentric.cpp
@@ -0,0 +1,151 @@
+/**
+ * \file NETGeographicLib/Geocentric.cpp
+ * \brief Implementation for NETGeographicLib::Geocentric class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include "GeographicLib/Geocentric.hpp"
+#include "Geocentric.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+const char BADALLOC[] = "Unable to allocate memory for a GeographicLib::Geocentric";
+
+//*****************************************************************************
+Geocentric::!Geocentric()
+{
+ if ( m_pGeocentric != NULL )
+ {
+ delete m_pGeocentric;
+ m_pGeocentric = NULL;
+ }
+}
+
+//*****************************************************************************
+Geocentric::Geocentric(void)
+{
+ try
+ {
+ m_pGeocentric = new GeographicLib::Geocentric(
+ GeographicLib::Geocentric::WGS84 );
+ }
+ catch (std::bad_alloc)
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+Geocentric::Geocentric(double a, double f)
+{
+ try
+ {
+ m_pGeocentric = new GeographicLib::Geocentric( a, f );
+ }
+ catch (std::bad_alloc)
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+ catch (std::exception err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+}
+
+//*****************************************************************************
+Geocentric::Geocentric( const GeographicLib::Geocentric& g )
+{
+ try
+ {
+ m_pGeocentric = new GeographicLib::Geocentric( g );
+ }
+ catch (std::bad_alloc)
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+void Geocentric::Forward(double lat, double lon, double h,
+ [System::Runtime::InteropServices::Out] double% X,
+ [System::Runtime::InteropServices::Out] double% Y,
+ [System::Runtime::InteropServices::Out] double% Z)
+{
+ double lX, lY, lZ;
+ m_pGeocentric->Forward( lat, lon, h, lX, lY, lZ);
+ X = lX;
+ Y = lY;
+ Z = lZ;
+}
+
+//*****************************************************************************
+void Geocentric::Forward(double lat, double lon, double h,
+ [System::Runtime::InteropServices::Out] double% X,
+ [System::Runtime::InteropServices::Out] double% Y,
+ [System::Runtime::InteropServices::Out] double% Z,
+ [System::Runtime::InteropServices::Out] array^% M)
+{
+ double lX, lY, lZ;
+ std::vector lM(9);
+ m_pGeocentric->Forward( lat, lon, h, lX, lY, lZ, lM);
+ X = lX;
+ Y = lY;
+ Z = lZ;
+ M = gcnew array( 3, 3 );
+ for ( int i = 0; i < 3; i++ )
+ for ( int j = 0; j < 3; j++ )
+ M[i,j] = lM[3*i+j];
+}
+
+//*****************************************************************************
+void Geocentric::Reverse(double X, double Y, double Z,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ [System::Runtime::InteropServices::Out] double% h)
+{
+ double llat, llon, lh;
+ m_pGeocentric->Reverse(X, Y, Z, llat, llon, lh);
+ lat = llat;
+ lon = llon;
+ h = lh;
+}
+
+//*****************************************************************************
+void Geocentric::Reverse(double X, double Y, double Z,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ [System::Runtime::InteropServices::Out] double% h,
+ [System::Runtime::InteropServices::Out] array^% M)
+{
+ std::vector lM(9);
+ double llat, llon, lh;
+ m_pGeocentric->Reverse(X, Y, Z, llat, llon, lh, lM);
+ lat = llat;
+ lon = llon;
+ h = lh;
+ M = gcnew array( 3, 3 );
+ for ( int i = 0; i < 3; i++ )
+ for ( int j = 0; j < 3; j++ )
+ M[i,j] = lM[3*i+j];
+}
+
+//*****************************************************************************
+System::IntPtr^ Geocentric::GetUnmanaged()
+{
+ return gcnew System::IntPtr( const_cast(
+ reinterpret_cast(m_pGeocentric) ) );
+}
+
+//*****************************************************************************
+double Geocentric::MajorRadius::get()
+{ return m_pGeocentric->MajorRadius(); }
+
+//*****************************************************************************
+double Geocentric::Flattening::get()
+{ return m_pGeocentric->Flattening(); }
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geocentric.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geocentric.h
new file mode 100644
index 000000000..2052ac418
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geocentric.h
@@ -0,0 +1,227 @@
+/**
+ * \file NETGeographicLib/Geocentric.h
+ * \brief Header for NETGeographicLib::Geocentric class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+
+namespace NETGeographicLib
+{
+ /**
+ * \brief .NET wrapper for GeographicLib::Geocentric.
+ *
+ * This class allows .NET applications to access GeographicLib::Geocentric.
+ *
+ * Convert between geodetic coordinates latitude = \e lat, longitude = \e
+ * lon, height = \e h (measured vertically from the surface of the ellipsoid)
+ * to geocentric coordinates (\e X, \e Y, \e Z). The origin of geocentric
+ * coordinates is at the center of the earth. The \e Z axis goes thru the
+ * north pole, \e lat = 90°. The \e X axis goes thru \e lat = 0,
+ * \e lon = 0. %Geocentric coordinates are also known as earth centered,
+ * earth fixed (ECEF) coordinates.
+ *
+ * The conversion from geographic to geocentric coordinates is
+ * straightforward. For the reverse transformation we use
+ * - H. Vermeille,
+ * Direct
+ * transformation from geocentric coordinates to geodetic coordinates,
+ * J. Geodesy 76, 451--454 (2002).
+ * .
+ * Several changes have been made to ensure that the method returns accurate
+ * results for all finite inputs (even if \e h is infinite). The changes are
+ * described in Appendix B of
+ * - C. F. F. Karney,
+ * Geodesics
+ * on an ellipsoid of revolution,
+ * Feb. 2011;
+ * preprint
+ * arxiv:1102.1215v1.
+ * .
+ * See \ref geocentric for more information.
+ *
+ * The errors in these routines are close to round-off. Specifically, for
+ * points within 5000 km of the surface of the ellipsoid (either inside or
+ * outside the ellipsoid), the error is bounded by 7 nm (7 nanometers) for
+ * the WGS84 ellipsoid. See \ref geocentric for further information on the
+ * errors.
+ *
+ * C# Example:
+ * \include example-Geocentric.cs
+ * Managed C++ Example:
+ * \include example-Geocentric.cpp
+ * Visual Basic Example:
+ * \include example-Geocentric.vb
+ *
+ * INTERFACE DIFFERENCES:
+ * A default constructor is provided that assumes WGS84 parameters.
+ *
+ * The MajorRadius and Flattening functions are implemented as properties.
+ *
+ * The Forward and Reverse functions return rotation matrices as 2D,
+ * 3 × 3 arrays rather than vectors.
+ **********************************************************************/
+ public ref class Geocentric
+ {
+ private:
+ // pointer to the unmanaged GeographicLib::Geocentric
+ const GeographicLib::Geocentric* m_pGeocentric;
+
+ // The finalizer frees unmanaged memory when the object is destroyed.
+ !Geocentric();
+ public:
+ /**
+ * Constructor for a ellipsoid with
+ *
+ * @param[in] a equatorial radius (meters).
+ * @param[in] f flattening of ellipsoid. Setting \e f = 0 gives a sphere.
+ * Negative \e f gives a prolate ellipsoid. If \e f > 1, set flattening
+ * to 1/\e f.
+ * @exception GeographicErr if \e a or (1 − \e f ) \e a is not
+ * positive.
+ **********************************************************************/
+ Geocentric(double a, double f);
+
+ /**
+ * A default constructor which assumes WGS84.
+ **********************************************************************/
+ Geocentric();
+
+ /**
+ * A constructor that is initialized from an unmanaged
+ * GeographicLib::Geocentric. For internal use only.
+ * @param[in] g An existing GeographicLib::Geocentric.
+ **********************************************************************/
+ Geocentric( const GeographicLib::Geocentric& g );
+
+ /**
+ * The destructor calls the finalizer.
+ **********************************************************************/
+ ~Geocentric()
+ { this->!Geocentric(); }
+
+ /**
+ * Convert from geodetic to geocentric coordinates.
+ *
+ * @param[in] lat latitude of point (degrees).
+ * @param[in] lon longitude of point (degrees).
+ * @param[in] h height of point above the ellipsoid (meters).
+ * @param[out] X geocentric coordinate (meters).
+ * @param[out] Y geocentric coordinate (meters).
+ * @param[out] Z geocentric coordinate (meters).
+ *
+ * \e lat should be in the range [−90°, 90°]; \e lon
+ * should be in the range [−540°, 540°).
+ **********************************************************************/
+ void Forward(double lat, double lon, double h,
+ [System::Runtime::InteropServices::Out] double% X,
+ [System::Runtime::InteropServices::Out] double% Y,
+ [System::Runtime::InteropServices::Out] double% Z);
+
+ /**
+ * Convert from geodetic to geocentric coordinates and return rotation
+ * matrix.
+ *
+ * @param[in] lat latitude of point (degrees).
+ * @param[in] lon longitude of point (degrees).
+ * @param[in] h height of point above the ellipsoid (meters).
+ * @param[out] X geocentric coordinate (meters).
+ * @param[out] Y geocentric coordinate (meters).
+ * @param[out] Z geocentric coordinate (meters).
+ * @param[out] M a 3 × 3 rotation matrix.
+ *
+ * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
+ * express \e v as \e column vectors in one of two ways
+ * - in east, north, up coordinates (where the components are relative to a
+ * local coordinate system at (\e lat, \e lon, \e h)); call this
+ * representation \e v1.
+ * - in geocentric \e X, \e Y, \e Z coordinates; call this representation
+ * \e v0.
+ * .
+ * Then we have \e v0 = \e M ⋅ \e v1.
+ **********************************************************************/
+ void Forward(double lat, double lon, double h,
+ [System::Runtime::InteropServices::Out] double% X,
+ [System::Runtime::InteropServices::Out] double% Y,
+ [System::Runtime::InteropServices::Out] double% Z,
+ [System::Runtime::InteropServices::Out] array^% M);
+
+ /**
+ * Convert from geocentric to geodetic to coordinates.
+ *
+ * @param[in] X geocentric coordinate (meters).
+ * @param[in] Y geocentric coordinate (meters).
+ * @param[in] Z geocentric coordinate (meters).
+ * @param[out] lat latitude of point (degrees).
+ * @param[out] lon longitude of point (degrees).
+ * @param[out] h height of point above the ellipsoid (meters).
+ *
+ * In general there are multiple solutions and the result which maximizes
+ * \e h is returned. If there are still multiple solutions with different
+ * latitudes (applies only if \e Z = 0), then the solution with \e lat > 0
+ * is returned. If there are still multiple solutions with different
+ * longitudes (applies only if \e X = \e Y = 0) then \e lon = 0 is
+ * returned. The value of \e h returned satisfies \e h ≥ − \e a
+ * (1 − e2) / sqrt(1 − e2
+ * sin2\e lat). The value of \e lon returned is in the range
+ * [−180°, 180°).
+ **********************************************************************/
+ void Reverse(double X, double Y, double Z,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ [System::Runtime::InteropServices::Out] double% h);
+
+ /**
+ * Convert from geocentric to geodetic to coordinates.
+ *
+ * @param[in] X geocentric coordinate (meters).
+ * @param[in] Y geocentric coordinate (meters).
+ * @param[in] Z geocentric coordinate (meters).
+ * @param[out] lat latitude of point (degrees).
+ * @param[out] lon longitude of point (degrees).
+ * @param[out] h height of point above the ellipsoid (meters).
+ * @param[out] M a 3 × 3 rotation matrix.
+ *
+ * Let \e v be a unit vector located at (\e lat, \e lon, \e h). We can
+ * express \e v as \e column vectors in one of two ways
+ * - in east, north, up coordinates (where the components are relative to a
+ * local coordinate system at (\e lat, \e lon, \e h)); call this
+ * representation \e v1.
+ * - in geocentric \e X, \e Y, \e Z coordinates; call this representation
+ * \e v0.
+ * .
+ * Then we have \e v1 = \e MT ⋅ \e v0, where \e
+ * MT is the transpose of \e M.
+ **********************************************************************/
+ void Reverse(double X, double Y, double Z,
+ [System::Runtime::InteropServices::Out] double% lat,
+ [System::Runtime::InteropServices::Out] double% lon,
+ [System::Runtime::InteropServices::Out] double% h,
+ [System::Runtime::InteropServices::Out] array^% M);
+
+ /** \name Inspector functions
+ **********************************************************************/
+ ///@{
+ /**
+ * @return a pointer to the unmanaged GeographicLib::Geocentric.
+ **********************************************************************/
+ System::IntPtr^ GetUnmanaged();
+
+ /**
+ * @return \e a the equatorial radius of the ellipsoid (meters). This is
+ * the value used in the constructor.
+ **********************************************************************/
+ property double MajorRadius { double get(); }
+
+ /**
+ * @return \e f the flattening of the ellipsoid. This is the
+ * value used in the constructor.
+ **********************************************************************/
+ property double Flattening { double get(); }
+ ///@}
+ };
+} // namespace NETGeographicLib
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geodesic.cpp b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geodesic.cpp
new file mode 100644
index 000000000..dadd022c4
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geodesic.cpp
@@ -0,0 +1,483 @@
+/**
+ * \file NETGeographicLib/Geodesic.cpp
+ * \brief Implementation for NETGeographicLib::Geodesic class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#include "stdafx.h"
+#include
+#include "Geodesic.h"
+#include "GeodesicLine.h"
+#include "NETGeographicLib.h"
+
+using namespace NETGeographicLib;
+
+const char BADALLOC[] = "Failed to allocate memory for a GeographicLib::Geodesic";
+
+//*****************************************************************************
+Geodesic::!Geodesic()
+{
+ if ( m_pGeodesic != NULL )
+ {
+ delete m_pGeodesic;
+ m_pGeodesic = NULL;
+ }
+}
+
+//*****************************************************************************
+Geodesic::Geodesic(double a, double f)
+{
+ try
+ {
+ m_pGeodesic = new GeographicLib::Geodesic( a, f );
+ }
+ catch ( std::bad_alloc err )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+ catch ( GeographicLib::GeographicErr err )
+ {
+ throw gcnew GeographicErr( err.what() );
+ }
+}
+
+//*****************************************************************************
+Geodesic::Geodesic()
+{
+ try
+ {
+ m_pGeodesic = new GeographicLib::Geodesic( GeographicLib::Geodesic::WGS84 );
+ }
+ catch ( std::bad_alloc )
+ {
+ throw gcnew GeographicErr( BADALLOC );
+ }
+}
+
+//*****************************************************************************
+double Geodesic::Direct(double lat1, double lon1, double azi1, double s12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% m12,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21,
+ [System::Runtime::InteropServices::Out] double% S12)
+{
+ double llat2, llon2, lazi2, lm12, lM12, lM21, lS12;
+ double out = m_pGeodesic->Direct(lat1, lon1, azi1, s12,
+ llat2, llon2, lazi2, lm12, lM12, lM21, lS12);
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ m12 = lm12;
+ M12 = lM12;
+ M21 = lM21;
+ S12 = lS12;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Direct(double lat1, double lon1, double azi1, double s12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2)
+{
+ double llat2, llon2;
+ double out = m_pGeodesic->Direct(lat1, lon1, azi1, s12,
+ llat2, llon2 );
+ lat2 = llat2;
+ lon2 = llon2;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Direct(double lat1, double lon1, double azi1, double s12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2)
+{
+ double llat2, llon2, lazi2;
+ double out = m_pGeodesic->Direct(lat1, lon1, azi1, s12,
+ llat2, llon2, lazi2 );
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Direct(double lat1, double lon1, double azi1, double s12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% m12)
+{
+ double llat2, llon2, lazi2, lm12;
+ double out = m_pGeodesic->Direct(lat1, lon1, azi1, s12,
+ llat2, llon2, lazi2, lm12 );
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ m12 = lm12;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Direct(double lat1, double lon1, double azi1, double s12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21)
+{
+ double llat2, llon2, lazi2, lM12, lM21;
+ double out = m_pGeodesic->Direct(lat1, lon1, azi1, s12,
+ llat2, llon2, lazi2, lM12, lM21);
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ M12 = lM12;
+ M21 = lM21;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Direct(double lat1, double lon1, double azi1, double s12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% m12,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21)
+{
+ double llat2, llon2, lazi2, lm12, lM12, lM21;
+ double out = m_pGeodesic->Direct(lat1, lon1, azi1, s12,
+ llat2, llon2, lazi2, lm12, lM12, lM21 );
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ m12 = lm12;
+ M12 = lM12;
+ M21 = lM21;
+ return out;
+}
+
+//*****************************************************************************
+void Geodesic::ArcDirect(double lat1, double lon1, double azi1, double a12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% m12,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21,
+ [System::Runtime::InteropServices::Out] double% S12)
+{
+ double llat2, llon2, lazi2, ls12, lm12, lM12, lM21, lS12;
+ m_pGeodesic->ArcDirect(lat1, lon1, azi1, a12,
+ llat2, llon2, lazi2, ls12, lm12, lM12, lM21, lS12);
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ s12 = ls12;
+ m12 = lm12;
+ M12 = lM12;
+ M21 = lM21;
+ S12 = lS12;
+}
+
+//*****************************************************************************
+void Geodesic::ArcDirect(double lat1, double lon1, double azi1, double a12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2)
+{
+ double llat2, llon2;
+ m_pGeodesic->ArcDirect(lat1, lon1, azi1, a12, llat2, llon2 );
+ lat2 = llat2;
+ lon2 = llon2;
+}
+
+//*****************************************************************************
+void Geodesic::ArcDirect(double lat1, double lon1, double azi1, double a12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2)
+{
+ double llat2, llon2, lazi2;
+ m_pGeodesic->ArcDirect(lat1, lon1, azi1, a12, llat2, llon2, lazi2 );
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+}
+
+//*****************************************************************************
+void Geodesic::ArcDirect(double lat1, double lon1, double azi1, double a12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% s12)
+{
+ double llat2, llon2, lazi2, ls12;
+ m_pGeodesic->ArcDirect(lat1, lon1, azi1, a12,
+ llat2, llon2, lazi2, ls12 );
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ s12 = ls12;
+}
+
+//*****************************************************************************
+void Geodesic::ArcDirect(double lat1, double lon1, double azi1, double a12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% m12)
+{
+ double llat2, llon2, lazi2, ls12, lm12;
+ m_pGeodesic->ArcDirect(lat1, lon1, azi1, a12,
+ llat2, llon2, lazi2, ls12, lm12 );
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ s12 = ls12;
+ m12 = lm12;
+}
+
+//*****************************************************************************
+void Geodesic::ArcDirect(double lat1, double lon1, double azi1, double a12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21)
+{
+ double llat2, llon2, lazi2, ls12, lM12, lM21;
+ m_pGeodesic->ArcDirect(lat1, lon1, azi1, a12,
+ llat2, llon2, lazi2, ls12, lM12, lM21 );
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ s12 = ls12;
+ M12 = lM12;
+ M21 = lM21;
+}
+
+//*****************************************************************************
+void Geodesic::ArcDirect(double lat1, double lon1, double azi1, double a12,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% m12,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21)
+{
+ double llat2, llon2, lazi2, ls12, lm12, lM12, lM21;
+ m_pGeodesic->ArcDirect(lat1, lon1, azi1, a12,
+ llat2, llon2, lazi2, ls12, lm12, lM12, lM21);
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ m12 = lm12;
+ s12 = ls12;
+ M12 = lM12;
+ M21 = lM21;
+}
+
+//*****************************************************************************
+double Geodesic::GenDirect(double lat1, double lon1, double azi1,
+ bool arcmode, double s12_a12,
+ NETGeographicLib::Mask outmask,
+ [System::Runtime::InteropServices::Out] double% lat2,
+ [System::Runtime::InteropServices::Out] double% lon2,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% m12,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21,
+ [System::Runtime::InteropServices::Out] double% S12)
+{
+ double llat2, llon2, lazi2, lm12, lM12, lM21, ls12, lS12;
+ double out = m_pGeodesic->GenDirect(lat1, lon1, azi1, arcmode, s12_a12,
+ static_cast(outmask),
+ llat2, llon2, lazi2, ls12, lm12, lM12, lM21, lS12);
+ lat2 = llat2;
+ lon2 = llon2;
+ azi2 = lazi2;
+ m12 = lm12;
+ M12 = lM12;
+ M21 = lM21;
+ s12 = ls12;
+ S12 = lS12;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Inverse(double lat1, double lon1, double lat2, double lon2,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% azi1,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% m12,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21,
+ [System::Runtime::InteropServices::Out] double% S12)
+{
+ double ls12, lazi1, lazi2, lm12, lM12, lM21, lS12;
+ double out = m_pGeodesic->Inverse(lat1, lon1, lat2, lon2,
+ ls12, lazi1, lazi2, lm12, lM12, lM21, lS12);
+ s12 = ls12;
+ azi1 = lazi1;
+ azi2 = lazi2;
+ m12 = lm12;
+ M12 = lM12;
+ M21 = lM21;
+ S12 = lS12;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Inverse(double lat1, double lon1, double lat2, double lon2,
+ [System::Runtime::InteropServices::Out] double% s12)
+{
+ double ls12;
+ double out = m_pGeodesic->Inverse(lat1, lon1, lat2, lon2, ls12 );
+ s12 = ls12;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Inverse(double lat1, double lon1, double lat2, double lon2,
+ [System::Runtime::InteropServices::Out] double% azi1,
+ [System::Runtime::InteropServices::Out] double% azi2)
+{
+ double lazi1, lazi2;
+ double out = m_pGeodesic->Inverse(lat1, lon1, lat2, lon2, lazi1, lazi2);
+ azi1 = lazi1;
+ azi2 = lazi2;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Inverse(double lat1, double lon1, double lat2, double lon2,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% azi1,
+ [System::Runtime::InteropServices::Out] double% azi2)
+{
+ double ls12, lazi1, lazi2;
+ double out = m_pGeodesic->Inverse(lat1, lon1, lat2, lon2,
+ ls12, lazi1, lazi2 );
+ azi1 = lazi1;
+ azi2 = lazi2;
+ s12 = ls12;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Inverse(double lat1, double lon1, double lat2, double lon2,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% azi1,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% m12)
+{
+ double ls12, lazi1, lazi2, lm12;
+ double out = m_pGeodesic->Inverse(lat1, lon1, lat2, lon2,
+ ls12, lazi1, lazi2, lm12 );
+ azi1 = lazi1;
+ azi2 = lazi2;
+ s12 = ls12;
+ m12 = lm12;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Inverse(double lat1, double lon1, double lat2, double lon2,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% azi1,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21)
+{
+ double ls12, lazi1, lazi2, lM12, lM21;
+ double out = m_pGeodesic->Inverse(lat1, lon1, lat2, lon2,
+ ls12, lazi1, lazi2, lM12, lM21 );
+ azi1 = lazi1;
+ azi2 = lazi2;
+ s12 = ls12;
+ M12 = lM12;
+ M21 = lM21;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::Inverse(double lat1, double lon1, double lat2, double lon2,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% azi1,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% m12,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21)
+{
+ double ls12, lazi1, lazi2, lm12, lM12, lM21;
+ double out = m_pGeodesic->Inverse(lat1, lon1, lat2, lon2,
+ ls12, lazi1, lazi2, lm12, lM12, lM21 );
+ azi1 = lazi1;
+ azi2 = lazi2;
+ s12 = ls12;
+ m12 = lm12;
+ M12 = lM12;
+ M21 = lM21;
+ return out;
+}
+
+//*****************************************************************************
+double Geodesic::GenInverse(double lat1, double lon1, double lat2, double lon2,
+ NETGeographicLib::Mask outmask,
+ [System::Runtime::InteropServices::Out] double% s12,
+ [System::Runtime::InteropServices::Out] double% azi1,
+ [System::Runtime::InteropServices::Out] double% azi2,
+ [System::Runtime::InteropServices::Out] double% m12,
+ [System::Runtime::InteropServices::Out] double% M12,
+ [System::Runtime::InteropServices::Out] double% M21,
+ [System::Runtime::InteropServices::Out] double% S12)
+{
+ double ls12, lazi1, lazi2, lm12, lM12, lM21, lS12;
+ double out = m_pGeodesic->GenInverse(lat1, lon1, lat2, lon2,
+ static_cast(outmask),
+ ls12, lazi1, lazi2, lm12, lM12, lM21, lS12);
+ azi1 = lazi1;
+ azi2 = lazi2;
+ s12 = ls12;
+ m12 = lm12;
+ M12 = lM12;
+ M21 = lM21;
+ S12 = lS12;
+ return out;
+}
+
+//*****************************************************************************
+System::IntPtr^ Geodesic::GetUnmanaged()
+{
+ return gcnew System::IntPtr( const_cast(reinterpret_cast(m_pGeodesic)) );
+}
+
+//*****************************************************************************
+GeodesicLine^ Geodesic::Line(double lat1, double lon1, double azi1,
+ NETGeographicLib::Mask caps )
+{
+ return gcnew GeodesicLine( this, lat1, lon1, azi1, caps );
+}
+
+//*****************************************************************************
+double Geodesic::MajorRadius::get() { return m_pGeodesic->MajorRadius(); }
+
+//*****************************************************************************
+double Geodesic::Flattening::get() { return m_pGeodesic->Flattening(); }
+
+//*****************************************************************************
+double Geodesic::EllipsoidArea::get() { return m_pGeodesic->EllipsoidArea(); }
diff --git a/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geodesic.h b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geodesic.h
new file mode 100644
index 000000000..aba97e1ab
--- /dev/null
+++ b/gtsam/3rdparty/GeographicLib/dotnet/NETGeographicLib/Geodesic.h
@@ -0,0 +1,688 @@
+/**
+ * \file NETGeographicLib/Geodesic.h
+ * \brief Header for NETGeographicLib::Geodesic class
+ *
+ * NETGeographicLib is copyright (c) Scott Heiman (2013)
+ * GeographicLib is Copyright (c) Charles Karney (2010-2012)
+ * and licensed under the MIT/X11 License.
+ * For more information, see
+ * http://geographiclib.sourceforge.net/
+ **********************************************************************/
+#pragma once
+#include "NETGeographicLib.h"
+
+namespace NETGeographicLib
+{
+ ref class GeodesicLine;
+ /**
+ * \brief .NET wrapper for GeographicLib::Geodesic.
+ *
+ * This class allows .NET applications to access GeographicLib::Geodesic.
+ *
+ * The shortest path between two points on a ellipsoid at (\e lat1, \e lon1)
+ * and (\e lat2, \e lon2) is called the geodesic. Its length is \e s12 and
+ * the geodesic from point 1 to point 2 has azimuths \e azi1 and \e azi2 at
+ * the two end points. (The azimuth is the heading measured clockwise from
+ * north. \e azi2 is the "forward" azimuth, i.e., the heading that takes you
+ * beyond point 2 not back to point 1.)
+ *
+ * Given \e lat1, \e lon1, \e azi1, and \e s12, we can determine \e lat2, \e
+ * lon2, and \e azi2. This is the \e direct geodesic problem and its
+ * solution is given by the function Geodesic::Direct. (If \e s12 is
+ * sufficiently large that the geodesic wraps more than halfway around the
+ * earth, there will be another geodesic between the points with a smaller \e
+ * s12.)
+ *
+ * Given \e lat1, \e lon1, \e lat2, and \e lon2, we can determine \e azi1, \e
+ * azi2, and \e s12. This is the \e inverse geodesic problem, whose solution
+ * is given by Geodesic::Inverse. Usually, the solution to the inverse
+ * problem is unique. In cases where there are multiple solutions (all with
+ * the same \e s12, of course), all the solutions can be easily generated
+ * once a particular solution is provided.
+ *
+ * The standard way of specifying the direct problem is the specify the
+ * distance \e s12 to the second point. However it is sometimes useful
+ * instead to specify the arc length \e a12 (in degrees) on the auxiliary
+ * sphere. This is a mathematical construct used in solving the geodesic
+ * problems. The solution of the direct problem in this form is provided by
+ * Geodesic::ArcDirect. An arc length in excess of 180° indicates that
+ * the geodesic is not a shortest path. In addition, the arc length between
+ * an equatorial crossing and the next extremum of latitude for a geodesic is
+ * 90°.
+ *
+ * This class can also calculate several other quantities related to
+ * geodesics. These are:
+ * - reduced length. If we fix the first point and increase \e azi1
+ * by \e dazi1 (radians), the second point is displaced \e m12 \e dazi1 in
+ * the direction \e azi2 + 90°. The quantity \e m12 is called
+ * the "reduced length" and is symmetric under interchange of the two
+ * points. On a curved surface the reduced length obeys a symmetry
+ * relation, \e m12 + \e m21 = 0. On a flat surface, we have \e m12 = \e
+ * s12. The ratio s12/\e m12 gives the azimuthal scale for an
+ * azimuthal equidistant projection.
+ * - geodesic scale. Consider a reference geodesic and a second
+ * geodesic parallel to this one at point 1 and separated by a small
+ * distance \e dt. The separation of the two geodesics at point 2 is \e
+ * M12 \e dt where \e M12 is called the "geodesic scale". \e M21 is
+ * defined similarly (with the geodesics being parallel at point 2). On a
+ * flat surface, we have \e M12 = \e M21 = 1. The quantity 1/\e M12 gives
+ * the scale of the Cassini-Soldner projection.
+
+ * - area. The area between the geodesic from point 1 to point 2 and
+ * the equation is represented by \e S12; it is the area, measured
+ * counter-clockwise, of the geodesic quadrilateral with corners
+ * (lat1,lon1), (0,lon1), (0,lon2), and
+ * (lat2,lon2). It can be used to compute the area of any
+ * simple geodesic polygon.
+ *
+ * Overloaded versions of Geodesic::Direct, Geodesic::ArcDirect, and
+ * Geodesic::Inverse allow these quantities to be returned. In addition
+ * there are general functions Geodesic::GenDirect, and Geodesic::GenInverse
+ * which allow an arbitrary set of results to be computed. The quantities \e
+ * m12, \e M12, \e M21 which all specify the behavior of nearby geodesics
+ * obey addition rules. If points 1, 2, and 3 all lie on a single geodesic,
+ * then the following rules hold:
+ * - \e s13 = \e s12 + \e s23
+ * - \e a13 = \e a12 + \e a23
+ * - \e S13 = \e S12 + \e S23
+ * - \e m13 = \e m12 \e M23 + \e m23 \e M21
+ * - \e M13 = \e M12 \e M23 − (1 − \e M12 \e M21) \e m23 / \e m12
+ * - \e M31 = \e M32 \e M21 − (1 − \e M23 \e M32) \e m12 / \e m23
+ *
+ * Additional functionality is provided by the GeodesicLine class, which
+ * allows a sequence of points along a geodesic to be computed.
+ *
+ * The shortest distance returned by the solution of the inverse problem is
+ * (obviously) uniquely defined. However, in a few special cases there are
+ * multiple azimuths which yield the same shortest distance. Here is a
+ * catalog of those cases:
+ * - \e lat1 = −\e lat2 (with neither at a pole). If \e azi1 = \e
+ * azi2, the geodesic is unique. Otherwise there are two geodesics and the
+ * second one is obtained by setting [\e azi1, \e azi2] = [\e azi2, \e
+ * azi1], [\e M12, \e M21] = [\e M21, \e M12], \e S12 = −\e S12.
+ * (This occurs when the longitude difference is near ±180° for
+ * oblate ellipsoids.)
+ * - \e lon2 = \e lon1 ± 180° (with neither at a pole). If \e
+ * azi1 = 0° or ±180°, the geodesic is unique. Otherwise
+ * there are two geodesics and the second one is obtained by setting [\e
+ * azi1, \e azi2] = [−\e azi1, −\e azi2], \e S12 = −\e
+ * S12. (This occurs when the \e lat2 is near −\e lat1 for prolate
+ * ellipsoids.)
+ * - Points 1 and 2 at opposite poles. There are infinitely many geodesics
+ * which can be generated by setting [\e azi1, \e azi2] = [\e azi1, \e
+ * azi2] + [\e d, −\e d], for arbitrary \e d. (For spheres, this
+ * prescription applies when points 1 and 2 are antipodal.)
+ * - s12 = 0 (coincident points). There are infinitely many geodesics which
+ * can be generated by setting [\e azi1, \e azi2] = [\e azi1, \e azi2] +
+ * [\e d, \e d], for arbitrary \e d.
+ *
+ * The calculations are accurate to better than 15 nm (15 nanometers) for the
+ * WGS84 ellipsoid. See Sec. 9 of
+ * arXiv:1102.1215v1 for
+ * details. The algorithms used by this class are based on series expansions
+ * using the flattening \e f as a small parameter. These are only accurate
+ * for |f| < 0.02; however reasonably accurate results will be
+ * obtained for |f| < 0.2. Here is a table of the approximate
+ * maximum error (expressed as a distance) for an ellipsoid with the same
+ * major radius as the WGS84 ellipsoid and different values of the
+ * flattening.