[geographiclib] 01/03: Imported Upstream version 1.39

Ross Gammon ross-guest at moszumanska.debian.org
Sat Dec 13 12:36:18 UTC 2014


This is an automated email from the git hooks/post-receive script.

ross-guest pushed a commit to branch master
in repository geographiclib.

commit 43c25574c005b9f759a9f32151baeca1b589926b
Author: Ross Gammon <rossgammon at mail.dk>
Date:   Sat Dec 13 13:29:26 2014 +0100

    Imported Upstream version 1.39
---
 CMakeLists.txt                                     |   22 +-
 LICENSE.txt                                        |    2 +-
 NEWS                                               |   59 +-
 cmake/project-config-version.cmake.in              |   35 +-
 cmake/project-config.cmake.in                      |    5 +-
 configure                                          |   26 +-
 configure.ac                                       |    8 +-
 doc/GeographicLib.dox                              | 1284 ++++++++++++++++----
 doc/Makefile.am                                    |    4 +
 doc/Makefile.in                                    |    4 +
 doc/NETGeographicLib.dox                           |   12 +-
 doc/doxyfile-for.in                                |    3 +-
 doc/geodesic-c.dox                                 |   12 +-
 doc/geodesic-for.dox                               |   34 +-
 doc/scripts/GeographicLib/DMS.js                   |  120 +-
 doc/scripts/GeographicLib/Geodesic.js              |  223 ++--
 doc/scripts/GeographicLib/GeodesicLine.js          |   66 +-
 doc/scripts/GeographicLib/Interface.js             |   26 +-
 doc/scripts/GeographicLib/Math.js                  |   38 +-
 doc/scripts/GeographicLib/PolygonArea.js           |   56 +-
 dotnet/NETGeographicLib/CMakeLists.txt             |    6 +
 dotnet/NETGeographicLib/DMS.cpp                    |   13 -
 dotnet/NETGeographicLib/DMS.h                      |   12 -
 dotnet/NETGeographicLib/Geodesic.cpp               |    4 +-
 dotnet/NETGeographicLib/Geodesic.h                 |  130 +-
 dotnet/NETGeographicLib/GeodesicExact.cpp          |    4 +-
 dotnet/NETGeographicLib/GeodesicExact.h            |  136 ++-
 dotnet/NETGeographicLib/GeodesicLine.cpp           |    4 +-
 dotnet/NETGeographicLib/GeodesicLine.h             |  111 +-
 dotnet/NETGeographicLib/GeodesicLineExact.cpp      |    2 +-
 dotnet/NETGeographicLib/GeodesicLineExact.h        |  115 +-
 dotnet/NETGeographicLib/Geoid.h                    |    7 +
 dotnet/NETGeographicLib/GravityCircle.h            |    5 +-
 dotnet/NETGeographicLib/NETGeographicLib.h         |    7 +
 dotnet/NETGeographicLib/PolygonArea.cpp            |  113 ++
 dotnet/NETGeographicLib/PolygonArea.h              |  172 +++
 dotnet/NETGeographicLib/Rhumb.cpp                  |   92 ++
 dotnet/NETGeographicLib/Rhumb.h                    |  298 ++++-
 dotnet/Projections/GeodesicPanel.cs                |   16 +-
 dotnet/Projections/MiscPanel.cs                    |    1 -
 dotnet/Projections/PolyPanel.cs                    |    9 +
 dotnet/Projections/RhumbPanel.Designer.cs          |   13 +
 dotnet/Projections/RhumbPanel.cs                   |   39 +
 dotnet/examples/ManagedCPP/CMakeLists.txt          |    6 +
 .../examples/ManagedCPP/example-GeodesicLine.cpp   |    4 +-
 .../ManagedCPP/example-GeodesicLineExact.cpp       |    4 +-
 dotnet/examples/ManagedCPP/example-RhumbLine.cpp   |    4 +-
 examples/example-GeodesicLine.cpp                  |    4 +-
 examples/example-GeodesicLineExact.cpp             |    4 +-
 examples/example-RhumbLine.cpp                     |    4 +-
 include/GeographicLib/Config.h                     |    4 +-
 include/GeographicLib/Constants.hpp                |    5 +-
 include/GeographicLib/DMS.hpp                      |    2 +-
 include/GeographicLib/Geodesic.hpp                 |   21 +-
 include/GeographicLib/GeodesicExact.hpp            |   20 +-
 include/GeographicLib/GeodesicLine.hpp             |   22 +-
 include/GeographicLib/GeodesicLineExact.hpp        |   24 +-
 include/GeographicLib/Geohash.hpp                  |    2 +-
 include/GeographicLib/Geoid.hpp                    |    9 +-
 include/GeographicLib/GravityCircle.hpp            |    4 +-
 include/GeographicLib/LambertConformalConic.hpp    |    2 +-
 include/GeographicLib/PolygonArea.hpp              |   36 +-
 include/GeographicLib/Rhumb.hpp                    |  333 ++++-
 include/GeographicLib/Utility.hpp                  |   18 +-
 java/pom.xml                                       |    2 +-
 .../main/java/net/sf/geographiclib/Geodesic.java   |   17 +-
 .../java/net/sf/geographiclib/GeodesicLine.java    |   41 +-
 .../java/net/sf/geographiclib/GeodesicMask.java    |    8 +-
 .../java/net/sf/geographiclib/PolygonArea.java     |   22 +-
 .../java/net/sf/geographiclib/package-info.java    |   16 +-
 legacy/C/CMakeLists.txt                            |    2 +-
 legacy/C/geodesic.c                                |   68 +-
 legacy/C/geodesic.h                                |  114 +-
 legacy/Fortran/00README.txt                        |    5 +
 legacy/Fortran/CMakeLists.txt                      |   15 +-
 legacy/Fortran/geoddirect.for                      |    7 +-
 legacy/Fortran/geodesic.for                        |   57 +-
 legacy/Fortran/geodesic.inc                        |    5 +-
 legacy/Fortran/ngscommon.for                       |  806 ++++++++++++
 legacy/Fortran/ngsforward.for                      |  490 ++++++++
 legacy/Fortran/ngsinverse.for                      |  513 ++++++++
 man/CartConvert.1                                  |    2 +-
 man/CartConvert.usage                              |    2 +-
 man/ConicProj.1                                    |    2 +-
 man/ConicProj.usage                                |    2 +-
 man/GeoConvert.1                                   |    2 +-
 man/GeoConvert.usage                               |    2 +-
 man/GeodSolve.1                                    |    2 +-
 man/GeodSolve.usage                                |    2 +-
 man/GeodesicProj.1                                 |    2 +-
 man/GeodesicProj.usage                             |    2 +-
 man/GeoidEval.1                                    |   10 +-
 man/GeoidEval.1.html                               |    8 +
 man/GeoidEval.pod                                  |   10 +
 man/GeoidEval.usage                                |    8 +-
 man/Gravity.1                                      |    2 +-
 man/Gravity.usage                                  |    2 +-
 man/MagneticField.1                                |   22 +-
 man/MagneticField.1.html                           |    2 +-
 man/MagneticField.pod                              |   20 +-
 man/MagneticField.usage                            |   21 +-
 man/Planimeter.1                                   |   14 +-
 man/Planimeter.1.html                              |   16 +-
 man/Planimeter.pod                                 |   14 +-
 man/Planimeter.usage                               |   19 +-
 man/RhumbSolve.1                                   |   50 +-
 man/RhumbSolve.1.html                              |   10 +-
 man/RhumbSolve.pod                                 |   48 +-
 man/RhumbSolve.usage                               |   43 +-
 man/TransverseMercatorProj.1                       |    2 +-
 man/TransverseMercatorProj.usage                   |    2 +-
 matlab/Makefile.am                                 |    1 +
 matlab/Makefile.in                                 |    1 +
 matlab/gedistance.m                                |   72 +-
 matlab/gedoc.m                                     |   14 +-
 matlab/geoddoc.m                                   |    4 +-
 matlab/geodreckon.m                                |   71 +-
 matlab/gereckon.m                                  |   68 +-
 matlab/private/AngNormalize2.m                     |    2 +-
 matlab/private/C4f.m                               |    4 +-
 matlab/private/G4coeff.m                           |   33 +
 maxima/Makefile.mk                                 |    2 +-
 maxima/auxlat.mac                                  |  256 ++++
 maxima/gearea.mac                                  |  138 +++
 maxima/geod.mac                                    |    4 +-
 maxima/geodesic.mac                                |   29 +-
 maxima/rhumbarea.mac                               |  198 +++
 pom.xml                                            |   19 +-
 python/geographiclib/geodesic.py                   |  113 +-
 python/geographiclib/geodesiccapability.py         |   10 +-
 python/geographiclib/geodesicline.py               |   76 +-
 python/geographiclib/polygonarea.py                |   22 +-
 python/setup.py                                    |    2 +-
 src/CMakeLists.txt                                 |   18 +
 src/Geodesic.cpp                                   |    4 +-
 src/GeodesicLine.cpp                               |   54 +-
 src/GeodesicLineExact.cpp                          |   46 +-
 src/GeographicLib.pro                              |    8 +-
 src/Geohash.cpp                                    |   10 +-
 src/PolygonArea.cpp                                |    9 +-
 src/Rhumb.cpp                                      |  225 +++-
 src/TransverseMercator.cpp                         |   10 +-
 src/TransverseMercatorExact.cpp                    |    3 +-
 tools/CMakeLists.txt                               |   16 +-
 tools/CartConvert.cpp                              |   10 +-
 tools/ConicProj.cpp                                |   10 +-
 tools/GeoConvert.cpp                               |   13 +-
 tools/GeodSolve.cpp                                |   10 +-
 tools/GeodesicProj.cpp                             |   13 +-
 tools/GeoidEval.cpp                                |   14 +-
 tools/Gravity.cpp                                  |   15 +-
 tools/MagneticField.cpp                            |   22 +-
 tools/Planimeter.cpp                               |   63 +-
 tools/RhumbSolve.cpp                               |   72 +-
 tools/TransverseMercatorProj.cpp                   |    8 -
 tools/geographiclib-get-geoids.sh                  |    8 +-
 tools/geographiclib-get-gravity.sh                 |    8 +-
 tools/geographiclib-get-magnetic.sh                |    8 +-
 158 files changed, 6742 insertions(+), 1485 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index a935df2..06c445b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ project (GeographicLib)
 
 # Version information
 set (PROJECT_VERSION_MAJOR 1)
-set (PROJECT_VERSION_MINOR 38)
+set (PROJECT_VERSION_MINOR 39)
 set (PROJECT_VERSION_PATCH 0)
 set (PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
 if (PROJECT_VERSION_PATCH GREATER 0)
@@ -42,8 +42,8 @@ endif ()
 
 # The library version tracks the numbering given by libtool in the
 # autoconf set up.
-set (LIBVERSION 13)
-set (LIBVERSIONFULL 13.0.1)
+set (LIBVERSION 14)
+set (LIBVERSIONFULL 14.0.0)
 string (TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER)
 string (TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER)
 
@@ -213,8 +213,11 @@ endif ()
 if (NOT MSVC)
   # Set the run time path for shared libraries for non-Windows machines.
   # (1) include link path for external packages (not needed with
-  # GeographicLib because there are no external packages).
-  set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+  # GeographicLib because there are no external packages).  This only
+  # makes sense for native builds.
+  if (NOT CMAKE_CROSSCOMPILING)
+    set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+  endif ()
   # (2) include installed path for GeographicLib.
   if (NOT APPLE)
     # Use relative path so that package is relocatable
@@ -331,6 +334,9 @@ elseif (GEOGRAPHICLIB_PRECISION EQUAL 5)
     # Windows build only works with GEOGRAPHICLIB_LIB_TYPE=STATIC.
     # NOTE: mpfr, gmp, and mpir are covered by the LGPL; be sure to
     # abide by the terms of this license.
+    #
+    # Need Visual Studio 12 2013 or later, g++ 4.5 or later; not sure
+    # about clang.
     if (WIN32)
       if (MSVC AND NOT MSVC_VERSION LESS 1800)
         if (CMAKE_SIZEOF_VOID_P EQUAL 8)
@@ -355,7 +361,11 @@ elseif (GEOGRAPHICLIB_PRECISION EQUAL 5)
         include_directories (/usr/local/include)
         link_directories (/usr/local/lib)
       endif ()
-      set (MPFR_LIBRARIES mpfr gmp)
+      # g++ before 4.5 doesn't work (no explicit cast operator)
+      if (NOT (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND
+            CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.5))
+        set (MPFR_LIBRARIES mpfr gmp)
+      endif ()
     endif ()
   endif ()
   if (NOT MPFR_LIBRARIES)
diff --git a/LICENSE.txt b/LICENSE.txt
index e70861b..47af155 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
 This license applies to GeographicLib, versions 1.12 and later.
 
-Copyright (c) 2008-2013, Charles Karney
+Copyright (c) 2008-2014, Charles Karney
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
diff --git a/NEWS b/NEWS
index cccb58e..77ed646 100644
--- a/NEWS
+++ b/NEWS
@@ -4,7 +4,64 @@ For more information, see
 
     http://geographiclib.sourceforge.net/
 
-The current version of the library is 1.38.
+The current version of the library is 1.39.
+
+Changes between 1.39 (released 2014-11-11) and 1.38 versions:
+
+  * GeographicLib usually normalizes longitudes to the range [-180deg,
+    180deg).  However, when solving the direct geodesic and rhumb line
+    problems, it is sometimes necessary to know how many lines the line
+    encircled the earth by returning the longitude "unwrapped".  So the
+    following changes have been made:
+    + add a LONG_NOWRAP flag to mask enums for the outmask arguments for
+      Geodesic, GeodesicLine, Rhumb, and RhumbLine;
+    + similar changes have been made to the Python, Javascript, and
+      Java implementations of the geodesic routines;
+    + for the C, Fortran, and Matlab implementations the arcmode
+      argument to the routines was generalized to allow a combination of
+      ARCMODE and LONG_NOWRAP bits;
+    + the Maxima version now returns the longitude unwrapped.
+    These changes were necessary to fix the PolygonAreaT::AddEdge (see
+    the next item).
+
+  * Changes in area calculations:
+    + fix BUG in PolygonAreaT::AddEdge (also in C, Java, Javascript, and
+      Python implementations) which sometimes causes the wrong area to
+      be returned if the edge spanned more than 180deg;
+    + add area calculation to the Rhumb and RhumbLine classes and the
+      RhumbSolve utility;
+    + add PolygonAreaRhumb typedef for PolygonAreaT<Rhumb>;
+    + add -R option to Planimeter to use PolygonAreaRhumb (and -G option
+      for the default geodesic polygon);
+    + fix BLUNDER in area calculation in Matlab routine geodreckon;
+    + add area calculation to Matlab/Octave routines for great ellipses.
+
+  * Fix bad BUG in Geohash::Reverse; this was introduced in version 1.37
+    and affected all platforms where unsigned longs are 32-bits.  Thanks
+    to Christian Csar for reporting and diagnosing this.
+
+  * Binary installers for Windows are now built with Visual Studio 11
+    2012 (instead of Visual Studio 10 2010).  Compiled Matlab support
+    still with version 2013a (64-bit).
+
+  * Update GeographicLib.pro for builds with qmake to include all the
+    source files.
+
+  * Cmake updates:
+    + include cross-compiling checks in cmake config file;
+    + improve the way unsuitable versions are reported;
+    + include_directories (${GeographicLib_INCLUDE_DIRS}) is no longer
+      necessary with cmake 2.8.11 or later.
+
+  * legacy/Fortran now includes drop-in replacements for the geodesic
+    utilities from the NGS.
+
+  * geographiclib-get-{geoids,gravity,magnetic} with no arguments now
+    print the usage instead of loading the minimal sets.
+
+  * Utility::date(const std::string&, int&, int&, int&) and hence the
+    MagneticField utility accepts the string "now" as a legal time
+    (meaning today).
 
 Changes between 1.38 (released 2014-10-02) and 1.37 versions:
 
diff --git a/cmake/project-config-version.cmake.in b/cmake/project-config-version.cmake.in
index 7cd9628..3b3b9e8 100644
--- a/cmake/project-config-version.cmake.in
+++ b/cmake/project-config-version.cmake.in
@@ -9,24 +9,28 @@ if (NOT PACKAGE_FIND_NAME STREQUAL "@PROJECT_NAME@")
   # Check package name (in particular, because of the way cmake finds
   # package config files, the capitalization could easily be "wrong").
   # This is necessary to ensure that the automatically generated
-  # variables, e.g., <package>_FOUND, are consistently spelled.  Make
-  # this a WARNING, because this is a user error that needs to be fixed.
-  message (WARNING
-    "Mismatched package names: use find_package(@PROJECT_NAME@ ...) instead"
-    " of find_package(${PACKAGE_FIND_NAME} ...)")
+  # variables, e.g., <package>_FOUND, are consistently spelled.
+  set (REASON "package = @PROJECT_NAME@, NOT ${PACKAGE_FIND_NAME}")
   set (PACKAGE_VERSION_UNSUITABLE TRUE)
-elseif (NOT (APPLE OR CMAKE_SIZEOF_VOID_P EQUAL @CMAKE_SIZEOF_VOID_P@))
+elseif (NOT (APPLE OR (NOT DEFINED CMAKE_SIZEOF_VOID_P) OR
+      CMAKE_SIZEOF_VOID_P EQUAL @CMAKE_SIZEOF_VOID_P@))
   # Reject if there's a 32-bit/64-bit mismatch (not necessary with Apple
   # since a multi-architecture library is built for that platform).
-  message (STATUS
-    "${CMAKE_CURRENT_LIST_FILE} unsuitable because package built with "
-    "sizeof(*void) =  @CMAKE_SIZEOF_VOID_P@")
+  set (REASON "sizeof(*void) =  @CMAKE_SIZEOF_VOID_P@")
   set (PACKAGE_VERSION_UNSUITABLE TRUE)
 elseif (MSVC AND NOT MSVC_VERSION STREQUAL "@MSVC_VERSION@")
   # Reject if there's a mismatch in MSVC compiler versions
-  message (STATUS
-    "${CMAKE_CURRENT_LIST_FILE} unsuitable because package built with "
-    "_MSC_VER = @MSVC_VERSION@")
+  set (REASON "_MSC_VER = @MSVC_VERSION@")
+  set (PACKAGE_VERSION_UNSUITABLE TRUE)
+elseif (NOT CMAKE_CROSSCOMPILING STREQUAL "@CMAKE_CROSSCOMPILING@")
+  # Reject if there's a mismatch in ${CMAKE_CROSSCOMPILING}
+  set (REASON "cross-compiling = @CMAKE_CROSSCOMPILING@")
+  set (PACKAGE_VERSION_UNSUITABLE TRUE)
+elseif (CMAKE_CROSSCOMPILING AND
+    NOT (CMAKE_SYSTEM_NAME STREQUAL "@CMAKE_SYSTEM_NAME@" AND
+      CMAKE_SYSTEM_PROCESSOR STREQUAL "@CMAKE_SYSTEM_PROCESSOR@"))
+  # Reject if cross-compiling and there's a mismatch in the target system
+  set (REASON "target = @CMAKE_SYSTEM_NAME at -@CMAKE_SYSTEM_PROCESSOR@")
   set (PACKAGE_VERSION_UNSUITABLE TRUE)
 elseif (PACKAGE_FIND_VERSION)
   if (PACKAGE_FIND_VERSION VERSION_EQUAL PACKAGE_VERSION)
@@ -48,7 +52,14 @@ if (@PROJECT_NAME at _FIND_COMPONENTS)
   foreach (comp ${@PROJECT_NAME at _FIND_COMPONENTS})
     if (@PROJECT_NAME at _FIND_REQUIRED_${comp} AND
         NOT @PROJECT_NAME at _${comp}_FOUND)
+      set (REASON "without ${comp}")
       set (PACKAGE_VERSION_UNSUITABLE TRUE)
     endif ()
   endforeach ()
 endif ()
+
+# If unsuitable, append the reason to the package version so that it's
+# visible to the user.
+if (PACKAGE_VERSION_UNSUITABLE)
+  set (PACKAGE_VERSION "${PACKAGE_VERSION} (${REASON})")
+endif ()
diff --git a/cmake/project-config.cmake.in b/cmake/project-config.cmake.in
index 1f13aa1..92bee82 100644
--- a/cmake/project-config.cmake.in
+++ b/cmake/project-config.cmake.in
@@ -17,6 +17,10 @@
 #    @PROJECT_NAME at _DEFINITIONS = ${@PROJECT_NAME at _STATIC_DEFINITIONS}, if ON
 #  If only one of the libraries is provided, then
 #    @PROJECT_NAME at _USE_STATIC_LIBS is ignored.
+#
+# For cmake 2.8.11 or later, there's no need to include
+#   include_directories (${GeographicLib_INCLUDE_DIRS})
+#   add_definitions (${GeographicLib_DEFINITIONS})
 
 message (STATUS "Reading ${CMAKE_CURRENT_LIST_FILE}")
 # @PROJECT_NAME at _VERSION is set by version file
@@ -39,7 +43,6 @@ else ()
   set (@PROJECT_NAME at _LIBRARY_DIRS "${_ROOT}/lib")
   set (@PROJECT_NAME at _BINARY_DIRS "${_ROOT}/bin")
 endif ()
-message (STATUS "  include directory: \${@PROJECT_NAME at _INCLUDE_DIRS}")
 
 set (@PROJECT_NAME at _SHARED_LIBRARIES @PROJECT_SHARED_LIBRARIES@)
 set (@PROJECT_NAME at _STATIC_LIBRARIES @PROJECT_STATIC_LIBRARIES@)
diff --git a/configure b/configure
index cb530ff..4256930 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for GeographicLib 1.38.
+# Generated by GNU Autoconf 2.69 for GeographicLib 1.39.
 #
 # Report bugs to <charles at karney.com>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='GeographicLib'
 PACKAGE_TARNAME='geographiclib'
-PACKAGE_VERSION='1.38'
-PACKAGE_STRING='GeographicLib 1.38'
+PACKAGE_VERSION='1.39'
+PACKAGE_STRING='GeographicLib 1.39'
 PACKAGE_BUGREPORT='charles at karney.com'
 PACKAGE_URL=''
 
@@ -1343,7 +1343,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures GeographicLib 1.38 to adapt to many kinds of systems.
+\`configure' configures GeographicLib 1.39 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1414,7 +1414,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of GeographicLib 1.38:";;
+     short | recursive ) echo "Configuration of GeographicLib 1.39:";;
    esac
   cat <<\_ACEOF
 
@@ -1525,7 +1525,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-GeographicLib configure 1.38
+GeographicLib configure 1.39
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1966,7 +1966,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by GeographicLib $as_me 1.38, which was
+It was created by GeographicLib $as_me 1.39, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2943,7 +2943,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='geographiclib'
- VERSION='1.38'
+ VERSION='1.39'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2996,7 +2996,7 @@ am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
 
 
 GEOGRAPHICLIB_VERSION_MAJOR=1
-GEOGRAPHICLIB_VERSION_MINOR=38
+GEOGRAPHICLIB_VERSION_MINOR=39
 GEOGRAPHICLIB_VERSION_PATCH=0
 
 cat >>confdefs.h <<_ACEOF
@@ -3044,8 +3044,8 @@ fi
 ac_config_headers="$ac_config_headers include/GeographicLib/Config-ac.h"
 
 
-LT_CURRENT=13
-LT_REVISION=1
+LT_CURRENT=14
+LT_REVISION=0
 LT_AGE=0
 
 
@@ -16243,7 +16243,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by GeographicLib $as_me 1.38, which was
+This file was extended by GeographicLib $as_me 1.39, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -16309,7 +16309,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-GeographicLib config.status 1.38
+GeographicLib config.status 1.39
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 3370221..ede81da 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 dnl
 dnl Copyright (C) 2009, Francesco P. Lovergine <frankie at debian.org>
 
-AC_INIT([GeographicLib],[1.38],[charles at karney.com])
+AC_INIT([GeographicLib],[1.39],[charles at karney.com])
 AC_CANONICAL_SYSTEM
 AC_PREREQ(2.61)
 AC_CONFIG_SRCDIR(src/Geodesic.cpp)
@@ -9,7 +9,7 @@ AC_CONFIG_MACRO_DIR(m4)
 AM_INIT_AUTOMAKE
 
 GEOGRAPHICLIB_VERSION_MAJOR=1
-GEOGRAPHICLIB_VERSION_MINOR=38
+GEOGRAPHICLIB_VERSION_MINOR=39
 GEOGRAPHICLIB_VERSION_PATCH=0
 AC_DEFINE_UNQUOTED([GEOGRAPHICLIB_VERSION_MAJOR],
 	[$GEOGRAPHICLIB_VERSION_MAJOR],[major version number])
@@ -34,8 +34,8 @@ dnl Library code modified:              REVISION++
 dnl Interfaces changed/added/removed:   CURRENT++ REVISION=0
 dnl Interfaces added:                   AGE++
 dnl Interfaces removed:                 AGE=0
-LT_CURRENT=13
-LT_REVISION=1
+LT_CURRENT=14
+LT_REVISION=0
 LT_AGE=0
 AC_SUBST(LT_CURRENT)
 AC_SUBST(LT_REVISION)
diff --git a/doc/GeographicLib.dox b/doc/GeographicLib.dox
index 700a45a..f21316b 100644
--- a/doc/GeographicLib.dox
+++ b/doc/GeographicLib.dox
@@ -11,8 +11,8 @@ namespace GeographicLib {
 /**
 \mainpage GeographicLib library
 \author Charles F. F. Karney (charles at karney.com)
-\version 1.38
-\date 2014-10-02
+\version 1.39
+\date 2014-11-11
 
 \section abstract Abstract
 
@@ -45,18 +45,19 @@ The main project page is at
   http://sourceforge.net/projects/geographiclib </a>
 .
 The code is available for download at
-- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.38.tar.gz">
-  GeographicLib-1.38.tar.gz</a>
-- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.38.zip">
-  GeographicLib-1.38.zip</a>
+- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.39.tar.gz">
+  GeographicLib-1.39.tar.gz</a>
+- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.39.zip">
+  GeographicLib-1.39.zip</a>
 .
 as either a compressed tar file (tar.gz) or a zip file.  (The two
 archives have identical contents, except that the zip file has DOS
 line endings.)  Alternatively you can get the latest release using git
 \verbatim
-  git clone -b r1.38 git://git.code.sf.net/p/geographiclib/code geographiclib
+  git clone -b r1.39 git://git.code.sf.net/p/geographiclib/code geographiclib
 \endverbatim
-There are also binary installers available for some platforms.  See \ref binaryinst.
+There are also binary installers available for some platforms.  See \ref
+binaryinst.
 
 GeographicLib is licensed under the
 <a href="http://www.opensource.org/licenses/MIT">MIT/X11 License</a>;
@@ -79,6 +80,7 @@ For more information, see http://geographiclib.sourceforge.net/.
  - \ref greatellipse
  - \ref transversemercator
  - \ref geocentric
+ - \ref auxlat
  - \ref highprec
  - \ref changes
 
@@ -104,7 +106,7 @@ 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
+   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
@@ -180,14 +182,14 @@ GeographicLib has been developed under Linux with the g++ compiler
 2012, and 2013.  Earlier versions were tested also under Visual Studio
 2005 and 2008 and under Darwin and Solaris.  It should compile on a wide
 range of other systems.  First download either
-<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.38.tar.gz">
-GeographicLib-1.38.tar.gz</a> or
-<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.38.zip">
-GeographicLib-1.38.zip</a> (or
-<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.38-win32.exe">
-GeographicLib-1.38-win32.exe</a> or
-<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.38-win64.exe">
-GeographicLib-1.38-win64.exe</a> for binary installation under Windows).
+<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.39.tar.gz">
+GeographicLib-1.39.tar.gz</a> or
+<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.39.zip">
+GeographicLib-1.39.zip</a> (or
+<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.39-win32.exe">
+GeographicLib-1.39-win32.exe</a> or
+<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.39-win64.exe">
+GeographicLib-1.39-win64.exe</a> 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
@@ -263,10 +265,10 @@ work also for Visual Studio 12 Express (2013).
 
 Here are the steps to compile and install GeographicLib:
 - Unpack the source, running one of \verbatim
-  tar xfpz GeographicLib-1.38.tar.gz
-  unzip -q GeographicLib-1.38.zip \endverbatim
+  tar xfpz GeographicLib-1.39.tar.gz
+  unzip -q GeographicLib-1.39.zip \endverbatim
   then enter the directory created with one of \verbatim
-  cd GeographicLib-1.38 \endverbatim
+  cd GeographicLib-1.39 \endverbatim
 - Create a separate build directory and enter it, for example, \verbatim
   mkdir BUILD
   cd BUILD \endverbatim
@@ -274,8 +276,8 @@ Here are the steps to compile and install GeographicLib:
   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.38 ..
-  cmake -G "Visual Studio 9 2008" -D CMAKE_INSTALL_PREFIX=C:/pkg-vc9/GeographicLib-1.38 ..
+  cmake -G "Visual Studio 10" -D CMAKE_INSTALL_PREFIX=C:/pkg-vc10/GeographicLib-1.39 ..
+  cmake -G "Visual Studio 9 2008" -D CMAKE_INSTALL_PREFIX=C:/pkg-vc9/GeographicLib-1.39 ..
 \endverbatim
   The definitions of CMAKE_INSTALL_PREFIX are optional (see below).  The
   settings given above are recommended to ensure that packages that use
@@ -291,7 +293,7 @@ Here are the steps to compile and install GeographicLib:
     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.38.  The installation
+    name, e.g., C:/pkg/GeographicLib-1.39.  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:
@@ -306,7 +308,7 @@ Here are the steps to compile and install GeographicLib:
     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., <code>cmake -G "Visual Studio
-    10 Win64" -D CMAKE_INSTALL_PREFIX=C:/pkg-vc10-x64/GeographicLib-1.38
+    10 Win64" -D CMAKE_INSTALL_PREFIX=C:/pkg-vc10-x64/GeographicLib-1.39
     ..</code>).  If you just want to try the library to see if it suits
     your needs, pick, for example,
     <code>CMAKE_INSTALL_PREFIX</code>=/tmp/geographic.
@@ -403,9 +405,9 @@ Here are the steps to compile and install GeographicLib:
 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.38.tar.gz \endverbatim
+  tar xfpz GeographicLib-1.39.tar.gz \endverbatim
   then enter the directory created \verbatim
-  cd GeographicLib-1.38 \endverbatim
+  cd GeographicLib-1.39 \endverbatim
 - Create a separate build directory and enter it, for example, \verbatim
   mkdir BUILD
   cd BUILD \endverbatim
@@ -434,9 +436,9 @@ 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.38.tar.gz \endverbatim
+  tar xfpz GeographicLib-1.39.tar.gz \endverbatim
   then enter the directory created \verbatim
-  cd GeographicLib-1.38 \endverbatim
+  cd GeographicLib-1.39 \endverbatim
 - Edit \verbatim
   include/GeographicLib/Config.h \endverbatim
   If your C++ compiler does not recognize the long double type
@@ -467,8 +469,8 @@ 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.38.zip \endverbatim
-- Open GeographicLib-1.38/windows/GeographicLib-vc10.sln in Visual Studio
+  unzip -q GeographicLib-1.39.zip \endverbatim
+- Open GeographicLib-1.39/windows/GeographicLib-vc10.sln in Visual Studio
   2010 (for Visual Studio 2005 and 2008, replace -vc10 by -vc8 or -vc9;
   for Visual Studio Express 2010, replace -vc10 by -vc10x).
 - Pick the build type (e.g., Release), and select "Build Solution".
@@ -494,20 +496,20 @@ Binary installers are available for some platforms
 
 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
+provided; these can only be used by Visual Studio 11 2012 (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
-<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.38-win32.exe">
-GeographicLib-1.38-win32.exe</a> or
-<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.38-win64.exe">
-GeographicLib-1.38-win64.exe</a>:
+<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.39-win32.exe">
+GeographicLib-1.39-win32.exe</a> or
+<a href="http://sourceforge.net/projects/geographiclib/files/distrib/GeographicLib-1.39-win64.exe">
+GeographicLib-1.39-win64.exe</a>:
  - read the MIT/X11 License agreement,
  - select whether you want your PATH modified,
  - select the installation folder, by default
-   C:\\pkg-vc10\\GeographicLib-1.38 or C:\\pkg-vc10-x64\\GeographicLib-1.38,
+   C:\\pkg-vc10\\GeographicLib-1.39 or C:\\pkg-vc10-x64\\GeographicLib-1.39,
  - select the start menu folder,
  - and install.
  .
@@ -515,12 +517,12 @@ GeographicLib-1.38-win64.exe</a>:
 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.38/bin where the utilities are
+will include C:/pkg-vc11/GeographicLib-1.39/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
+using Visual Studio 11 2012 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.
@@ -580,7 +582,7 @@ Check the code out of git with \verbatim
 Here the "master" branch is checked out.  There are three branches in
 the git repository:
 - <b>master</b>: the main branch for code maintainence.  Releases are
-  tagged on this branch as, e.g., v1.38.
+  tagged on this branch as, e.g., v1.39.
 - <b>devel</b>: the development branch; changes made here are merged
   into master.
 - <b>release</b>: the release branch created by unpacking the source
@@ -590,7 +592,7 @@ the git repository:
   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.38.
+  possible).  Releases are tagged on this branch as, e.g., r1.39.
 .
 The autoconf configuration script and the formatted man pages are not
 checked into master branch of the repository.  In order to create the
@@ -606,8 +608,8 @@ In the case of cmake, you then run \verbatim
 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.38.tar.gz
-  GeographicLib-1.38.zip \endverbatim
+  GeographicLib-1.39.tar.gz
+  GeographicLib-1.39.zip \endverbatim
 Finally, \verbatim
   make package \endverbatim
 or building PACKAGE in Visual Studio will create a binary installer for
@@ -633,7 +635,7 @@ 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.38.tar.gz \endverbatim
+  geographiclib-1.39.tar.gz \endverbatim
 
 <center>
 Back to \ref intro.  Forward to \ref start.  Up to \ref contents.
@@ -670,8 +672,9 @@ In order to use GeographicLib from C++ code, you will need to
     add_definitions (${GeographicLib_DEFINITIONS})
     add_executable (program source1.cpp source2.cpp)
     target_link_libraries (program ${GeographicLib_LIBRARIES}) \endverbatim
-    (The <code>add_definitions</code> line is only needed for Windows
-    and can be omitted if you're using cmake version 2.8.11 or later.)
+    If you're using cmake version 2.8.11 or later, you can omit the
+    <code>include_directories </code> and <code>add_definitions</code>
+    lines.
   - configure your package, e.g., with \verbatim
     mkdir BUILD
     cd BUILD
@@ -723,7 +726,7 @@ In order to use GeographicLib from C++ code, you will need to
 
   If GeographicLib is found, then the following cmake variables are set:
   - <code>GeographicLib_FOUND</code> = 1
-  - <code>GeographicLib_VERSION</code> = 1.38
+  - <code>GeographicLib_VERSION</code> = 1.39
   - <code>GeographicLib_INCLUDE_DIRS</code>
   - <code>GeographicLib_LIBRARIES</code> = one of the following two:
   - <code>GeographicLib_SHARED_LIBRARIES</code> = GeographicLib
@@ -826,8 +829,10 @@ if (NOT MSVC)
   set (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
 endif ()
 
-include_directories (${GeographicLib_INCLUDE_DIRS})
-add_definitions (${GeographicLib_DEFINITIONS})
+if (CMAKE_VERSION VERSION_LESS 2.8.11)
+  include_directories (${GeographicLib_INCLUDE_DIRS})
+  add_definitions (${GeographicLib_DEFINITIONS})
+endif ()
 add_executable (${PROJECT_NAME} example-Geodesic-small.cpp)
 target_link_libraries (${PROJECT_NAME} ${GeographicLib_LIBRARIES})
 
@@ -857,19 +862,19 @@ The next steps are:
 
 Here's a list of some of the abbreviations used here with links to the
 corresponding Wikipedia articles:
- - <a href="http://en.wikipedia.org/wiki/WGS84">
+ - <a href="https://en.wikipedia.org/wiki/WGS84">
    WGS84</a>, World Geodetic System 1984.
- - <a href="http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system">
+ - <a href="https://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system">
    UTM</a>, Universal Transverse Mercator coordinate system.
- - <a href="http://en.wikipedia.org/wiki/Universal_Polar_Stereographic">
+ - <a href="https://en.wikipedia.org/wiki/Universal_Polar_Stereographic">
    UPS</a>, Universal Polar Stereographic coordinate system.
- - <a href="http://en.wikipedia.org/wiki/Military_grid_reference_system">
+ - <a href="https://en.wikipedia.org/wiki/Military_grid_reference_system">
    MGRS</a>, Military Grid Reference System.
- - <a href="http://en.wikipedia.org/wiki/Geoid">
+ - <a href="https://en.wikipedia.org/wiki/Geoid">
    EGM</a>, Earth Gravity Model.
- - <a href="http://en.wikipedia.org/wiki/World_Magnetic_Model">
+ - <a href="https://en.wikipedia.org/wiki/World_Magnetic_Model">
    WMM</a>, World Magnetic Model.
- - <a href="http://en.wikipedia.org/wiki/IGRF">
+ - <a href="https://en.wikipedia.org/wiki/IGRF">
    IGRF</a>, International Geomagnetic Reference Field.
 
 <center>
@@ -897,7 +902,7 @@ The utilities are
    Geodesic and GeodesicLine.  See \ref GeodSolve.cpp.
  - <a href="Planimeter.1.html">
    <b>Planimeter</b></a>: compute the area of geodesic polygons using
-   PolygonArea.  See \ref Planimeter.cpp.
+   PolygonAreaT.  See \ref Planimeter.cpp.
  - <a href="TransverseMercatorProj.1.html">
    <b>TransverseMercatorProj</b></a>: convert between geographic
    and transverse Mercator.  This is for testing
@@ -931,9 +936,9 @@ The utilities are
 The documentation for these utilities is in the form of man pages.  This
 documentation can be accessed by clicking on the utility name in the
 list above, running the man command on Unix-like systems, or by invoking
-the utility with the <code>--help</code> option.  A brief summary of
+the utility with the <code>\--help</code> option.  A brief summary of
 usage is given by invoking the utility with the <code>-h</code> option.
-The version of the utility is given by the <code>--version</code>
+The version of the utility is given by the <code>\--version</code>
 option.
 
 The utilities all accept data on standard input, transform it in some
@@ -1023,7 +1028,7 @@ all the information needed to specify a geodesic.  A const member
 function returns the coordinates a specified distance from the starting
 point.  <a href="GeodSolve.1.html">GeodSolve</a> is a simple command
 line utility to perform geodesic calculations.
-PolygonArea is a class which compute the area of geodesic
+PolygonAreaT is a class which compute the area of geodesic
 polygons using the Geodesic class and
 <a href="Planimeter.1.html">Planimeter</a> is a command line utility for
 the same purpose.  AzimuthalEquidistant,
@@ -1083,23 +1088,17 @@ for high degree models such as emm2010.)  These classes requires
 installation of data files for the various magnetic models; see \ref
 magneticinst for details.
 
-Constants, Math, Utility,
-DMS, are general utility class which are used
-internally by the library; in addition EllipticFunction
-is used by TransverseMercatorExact,
-Ellipsoid, and GeodesicExact, and
-GeodesicLineExact; Accumulator is used
-by PolygonArea, and SphericalEngine,
-CircularEngine, SphericalHarmonic,
-SphericalHarmonic1, and
-SphericalHarmonic2 facilitate the summation of
-spherical harmonic series which is needed by and
-MagneticModel and MagneticCircle.  One
-important definition is Math::real which is the type
-used for real numbers.  This allows the library to be easily switched
-to using floats, doubles, or long doubles.  However all the testing
-has been with real set to double and the library should be installed
-in this way.
+Constants, Math, Utility, DMS, are general utility class which are used
+internally by the library; in addition EllipticFunction is used by
+TransverseMercatorExact, Ellipsoid, and GeodesicExact, and
+GeodesicLineExact; Accumulator is used by PolygonAreaT, and
+SphericalEngine, CircularEngine, SphericalHarmonic, SphericalHarmonic1,
+and SphericalHarmonic2 facilitate the summation of spherical harmonic
+series which is needed by and MagneticModel and MagneticCircle.  One
+important definition is Math::real which is the type used for real
+numbers.  This allows the library to be easily switched to using floats,
+doubles, or long doubles.  However all the testing has been with real
+set to double and the library should be installed in this way.
 
 In general, the constructors for the classes in GeographicLib check
 their arguments and throw GeographicErr exceptions with a
@@ -1153,10 +1152,10 @@ can test the values of the macros GEOGRAPHICLIB_VERSION_MAJOR,
 GEOGRAPHICLIB_VERSION_MINOR, and GEOGRAPHICLIB_VERSION_PATCH; these
 expand to numbers (and the last one is usually 0); these macros appeared
 starting in version 1.31.  There's also a macro
-GEOGRAPHICLIB_VERSION_STRING which expands to, e.g., "1.38"; this macro
+GEOGRAPHICLIB_VERSION_STRING which expands to, e.g., "1.39"; this macro
 has been defined since version 1.9.  Since version 1.37, there's also
 been a macro GEOGRAPHICLIB_VERSION which encode the version as a single
-number, e.g, 1003700.  The macro GEOGRAPHICLIB_VERSION_NUM allows you to
+number, e.g, 1003900.  The macro GEOGRAPHICLIB_VERSION_NUM allows you to
 compare versions, e.g., \code
 #if GEOGRAPHICLIB_VERSION >= GEOGRAPHICLIB_VERSION_NUM(1,36,0)
 ... \endcode
@@ -1184,13 +1183,12 @@ Implementations of subsets of GeographicLib are available in other languages
 \section c-fortran C and Fortran implementation
 
 The directories <code>legacy/C</code> and <code>legacy/Fortran</code>
-contain implementations of Geodesic,
-GeodesicLine, and 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
+contain implementations of Geodesic, GeodesicLine, and PolygonAreaT 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
@@ -1199,12 +1197,11 @@ For documentation, see
 
 \section java Java implementation
 
-The directory <code>java</code> contains implementations of
-Geodesic, GeodesicLine, and
-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.
+The directory <code>java</code> contains implementations of Geodesic,
+GeodesicLine, and PolygonAreaT 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
  - <a href="java/index.html">Java library for geodesics</a>.
@@ -1216,7 +1213,7 @@ The directory doc/scripts/GeographicLib contains the classes
 - Accumulator
 - Geodesic
 - GeodesicLine
-- PolygonArea
+- PolygonAreaT
 - DMS
 .
 translated into JavaScript.  See Interface.js for a simple JavaScript
@@ -1247,7 +1244,7 @@ otherwise).  This contains implementations of the classes
 - Accumulator
 - Geodesic
 - GeodesicLine
-- PolygonArea
+- PolygonAreaT
 .
 You can also download the python interface independent of the rest of
 GeographicLib from
@@ -1311,7 +1308,7 @@ The <code>matlab</code> directory Matlab and Octave implementations of
 some of the functions of GeographicLib.  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.38/libexec/GeographicLib/matlab'
+   addpath 'C:/pkg-vc10-x64/GeographicLib-1.39/libexec/GeographicLib/matlab'
    \endverbatim
 
 The functions fall into the following groups
@@ -1360,7 +1357,8 @@ The functions fall into the following groups
    - <a href="http://www.mathworks.com/matlabcentral/fileexchange/47898">
      http://www.mathworks.com/matlabcentral/fileexchange/47898</a>
    .
-   (This requires that package 39108 also be installed.)
+   (This requires that package 39108 also be installed.)  Background on
+   this problem is provided in \ref greatellipse.
  - Finally, interface code so that some GeographicLib classes can be
    accessed directly from Matlab or Octave.  The rest of this section
    describes how to compile and use these interfaces.
@@ -1400,9 +1398,9 @@ There are two ways of compiling the interface code: (1) using cmake and
  - <b>Invoking the compiler from Matlab or Octave:</b> Start Matlab or
    Octave and run, e.g., \code
    mex -setup
-   cd 'C:/pkg-vc10-x64/GeographicLib-1.38/matlab'
+   cd 'C:/pkg-vc10-x64/GeographicLib-1.39/matlab'
    help geographiclibinterface
-   geographiclibinterface('C:/pkg-vc10/GeographicLib-1.38');
+   geographiclibinterface('C:/pkg-vc10/GeographicLib-1.39');
    addpath(pwd);
    \endcode
    The first command allows you to select the compiler to use (which
@@ -1411,7 +1409,7 @@ There are two ways of compiling the interface code: (1) using cmake and
 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.38/libexec/GeographicLib/matlab'
+  addpath 'C:/pkg-vc10-x64/GeographicLib-1.39/libexec/GeographicLib/matlab'
 \endverbatim
 in Octave or Matlab.  The available functions are:
  - geodesicdirect: solve direct geodesic problem
@@ -1421,7 +1419,7 @@ in Octave or Matlab.  The available functions are:
  - geodesicline: compute points along a geodesic
    (see GeodesicLine::Position)
  - polygonarea: compute area of a geodesic polygon
-   (see PolygonArea)
+   (see PolygonAreaT)
  - utmupsforward: convert geographic coordinates to UTM/UPS
    (see UTMUPS::Forward)
  - utmupsreverse: convert UTM/UPS coordinates to geographic
@@ -1492,8 +1490,8 @@ 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.
+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:
@@ -1510,8 +1508,14 @@ 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.)
 
+The geoid height, \e N, can be used to convert a height above the
+ellipsoid, \e h, to the corresponding height above the geoid (roughly,
+the height above mean sea level), \e H, using the relations
+
+   \e h = \e N + \e H;   \e H = −\e N + \e h.
+
 Unlike other components of GeographicLib, there is a appreciable error
-in the results obtained (at best, the RMS error is 1 mm).  However the
+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
@@ -1725,8 +1729,8 @@ PGM simple graphic format with the following properties
   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
+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
@@ -1856,7 +1860,7 @@ 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 Geoid; instead it is
 implemented as
-<a href="http://en.wikipedia.org/wiki/Maxima_(software)">Maxima</a>
+<a href="https://en.wikipedia.org/wiki/Maxima_(software)">Maxima</a>
 code which is used to precompute the matrices to convert the function
 values on the stencil into the coefficients from the cubic polynomial.
 This code is included as a comment in Geoid.cpp.
@@ -1909,12 +1913,12 @@ The errors are with respect to the specific NGA earth gravity model
 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.)
+EGM2008 is about 0.5 m.  The RMS difference between EGM84 and EGM96 is
+about 1.5 m.)
 
 The errors in the table above include the quantization errors that arise
 because the height data that Geoid uses are quantized to
-3 mm.  If, instead, Geoid were to use data files without
+3 mm.  If, instead, Geoid were to use data files without
 such quantization artifacts, the overall error would be reduced <i>but
 only modestly</i> as shown in the following table, where only the
 changed rows are included and where the changed entries are given in
@@ -2351,14 +2355,14 @@ issues that I encountered using the NGA code:
     1 part in 10<sup>9</sup>), there should be a 1/\e r contribution to
     the disturbing potential \e T.  However, this term is set to zero in
     hsynth_WGS84 (effectively altering the normal potential).  This
-    shifts the surface \e W = <i>U</i><sub>0</sub> outward by about 5 mm.
-    Note too that the reference ellipsoid is no longer a level surface of
-    the effective normal potential.
+    shifts the surface \e W = <i>U</i><sub>0</sub> outward by about
+    5 mm.  Note too that the reference ellipsoid is no longer a
+    level surface of the effective normal potential.
  -# Subroutine <code>radgrav</code> computes the ellipsoidal coordinate
     β incorrectly.  This leads to small errors in the deflection
     of the vertical, ξ and η, when the height above the
     ellipsoid, \e h, is non-zero (about 10<sup>−7</sup> arcsec at
-    \e h = 400 km).
+    \e h = 400 km).
  -# There are several expressions which will return inaccurate results
     due to cancellation.  For example, subroutine <code>grs</code>
     computes the flattening using \e f = 1 − sqrt(1 −
@@ -2366,7 +2370,7 @@ issues that I encountered using the NGA code:
     <i>e</i><sup>2</sup>/(1 + sqrt(1 − <i>e</i><sup>2</sup>)).  The
     expressions for \e q and \e q' in <code>grs</code> and
     <code>radgrav</code> suffer from similar problems.  The resulting
-    errors are tiny (about 50 pm in the geoid height); however, given
+    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
@@ -2405,16 +2409,16 @@ to use a consistent definition of the geoid height.
  - The surface \e W = <i>U</i><sub>0</sub> is determined by Bruns'
    formula, which is roughly equivalent to a single iteration of
    Newton's method.  The RMS error in this approximation is about 1.5mm
-   with a maximum error of about 10 mm.
+   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 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
@@ -2491,13 +2495,14 @@ The value of \e GM includes the mass of the atmosphere and so strictly
 only applies above the earth's atmosphere.  Near the surface of the
 earth, the value of \e g will be less (in absolute value) than the value
 predicted by these models by about δ\e g = (4π<i>G</i>/\e
-g) \e A = 8.552 × 10<sup>−11</sup> \e A m<sup>2</sup>/kg,
-where \e G is the gravitational constant, \e g is the earth's gravity,
-and \e A is the pressure of the atmosphere.  At sea level we have \e A =
-101.3 kPa, and δ\e g = 8.7 × 10<sup>−6</sup> m
-s<sup>−2</sup>, approximately.  (In other words the effect is
-about 1 part in a million; by way of comparison, buoyancy effects
-are about 100 times larger.)
+g) \e A = 8.552 × 10<sup>−11</sup> \e
+A m<sup>2</sup>/kg, where \e G is the gravitational constant, \e g
+is the earth's gravity, and \e A is the pressure of the atmosphere.  At
+sea level we have \e A = 101.3 kPa, and δ\e g =
+8.7−×−10<sup>−6</sup> m s<sup>−2</sup>,
+approximately.  (In other words the effect is about 1 part in a
+million; by way of comparison, buoyancy effects are about 100 times
+larger.)
 
 \section gravityparallel Geoid heights on a multi-processor system
 
@@ -2507,7 +2512,7 @@ for example it takes about 78 ms to compute the geoid height at a single
 point.  There are two ways to speed up this computation:
  - Use a GravityCircle to compute the geoid height at
    several points on a circle of latitude.  This reduces the cost per
-   point to about 92 μs (a reduction by a factor of over 800).
+   point to about 92 μs (a reduction by a factor of over 800).
  - Compute the values on several circles of latitude in parallel.  One
    of the simplest ways of doing this is with
    <a href="http://openmp.org"> OpenMP</a>; on an 8-processor system,
@@ -2873,6 +2878,8 @@ References:
  - J. Danielsen,
    The Area under the Geodesic,
    Survey Review 30(232), 61--66 (1989).
+   DOI: <a href="http://dx.doi.org/10.1179/003962689791474267">
+   10.1179/003962689791474267</a>
  - C. F. F. Karney,
    <a href="http://dx.doi.org/10.1007/s00190-012-0578-z">
    Algorithms for geodesics</a>,
@@ -2886,7 +2893,7 @@ References:
  - A collection of some papers on geodesics is available at
    http://geographiclib.sourceforge.net/geodesic-papers/biblio.html
  - The wikipedia page,
-   <a href="http://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid">
+   <a href="https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid">
    Geodesics on an ellipsoid</a>.
 
 \section testgeod Test data for geodesics
@@ -2914,9 +2921,9 @@ Each line of the test set gives 10 space delimited numbers
  - geodesic distance from point 1 to point 2, \e s12 (meters, exact)
  - arc distance on the auxiliary sphere, \e a12 (degrees, accurate to
    10<sup>−18</sup> deg)
- - reduced length of the geodesic, \e m12 (meters, accurate to 0.1 pm)
+ - reduced length of the geodesic, \e m12 (meters, accurate to 0.1 pm)
  - the area under the geodesic, \e S12 (m<sup>2</sup>, accurate to
-   1 mm<sup>2</sup>)
+   1 mm<sup>2</sup>)
  .
 These are computed using as direct geodesic calculations with the given
 \e lat1, \e lon1, \e azi1, and \e s12.  The distance \e s12 always
@@ -2926,13 +2933,14 @@ simplicity and without loss of generality, \e lat1 is chosen in
 [0°, 90°], \e lon1 is taken to be zero, \e azi1 is
 chosen in [0°, 180°].  Furthermore, \e lat1 and \e
 azi1 are taken to be multiples of 10<sup>−12</sup> deg and \e s12
-is a multiple of 0.1 μm in [0 m, 20003931.4586254 m].  This results \e
-lon2 in [0°, 180°] and \e azi2 in [0°, 180°].
+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 <i>f</i><sup>30</sup> (approximately 1 part in 10<sup>50</sup>)
 and is computed with with
-<a href="http://en.wikipedia.org/wiki/Maxima_(software)">Maxima</a>'s
+<a href="https://en.wikipedia.org/wiki/Maxima_(software)">Maxima</a>'s
 bfloats and fpprec set to 100 (so the errors in the data are probably
 1/2 of the values quoted above).
 
@@ -2948,7 +2956,7 @@ The contents of the file are as follows:
  - 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
+running between vertices are truncated to a multiple of 0.1 pm and this
 is used to determine point 2.
 
 This data can be fed to the <a href="GeodSolve.1.html">GeodSolve</a>
@@ -2991,7 +2999,7 @@ GeodesicExact).
 We give here the series expansions for the various geodesic integrals
 valid to order <i>f</i><sup>10</sup>.  In this release of the code, we
 use a 6th-order expansions.  This is sufficient to maintain accuracy
-for doubles for the SRMmax ellipsoid (\e a = 6400 km, \e f = 1/150).
+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
@@ -3712,8 +3720,8 @@ In assessing the accuracy of these methods we use two metrics:
  .
 (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
+that the one or other of the errors fall below 1 mm (an "engineering"
+definition of accurate) or 1 nm (1 nanometer, about the round-off
 limit).
 
 <center>
@@ -3764,15 +3772,15 @@ bounds</caption>
 </center>
 
 For example, if you're only interested in measuring distances and an
-accuracy of 1 mm is sufficient, then Bowring's improved method can be
-used for distances up to 180 km.  On the other hand, GeographicLib uses
-Bessel's auxiliary sphere and we require both the distance and the
-azimuth to be accurate, so the great circle approximation can only be
-used for distances less than 1.7 m.  The reason that GeographicLib does
-not use Bowring's method is that the information necessary for auxiliary
-sphere method is already available as part of the general solution and,
-as much as possible, we allow all geodesics to be computed by the
-general method.
+accuracy of 1 mm is sufficient, then Bowring's improved method can
+be used for distances up to 180 km.  On the other hand,
+GeographicLib uses Bessel's auxiliary sphere and we require both the
+distance and the azimuth to be accurate, so the great circle
+approximation can only be used for distances less than 1.7 m.  The
+reason that GeographicLib does not use Bowring's method is that the
+information necessary for auxiliary sphere method is already available
+as part of the general solution and, as much as possible, we allow all
+geodesics to be computed by the general method.
 
 <center>
 Back to \ref magnetic.  Forward to \ref triaxial.  Up to \ref contents.
@@ -3794,7 +3802,7 @@ the inverse problem.
 
 See also
  - The wikipedia page,
-   <a href="http://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid#Geodesics_on_a_triaxial_ellipsoid">
+   <a href="https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid#Geodesics_on_a_triaxial_ellipsoid">
    Geodesics on  a triaxial ellipsoid</a>.
 
 Go to
@@ -4348,6 +4356,7 @@ here are:
 Go to
  - \ref rhumbform
  - \ref rhumblat
+ - \ref rhumbarea
  - \ref divideddiffs
  - \ref dividedclenshaw
 
@@ -4576,6 +4585,117 @@ These relations allow inter-conversions between the various latitudes
 out simply and accurately.  The approaches using series apply only if
 \f$f\f$ is small.  The others apply for arbitrary values of \f$f\f$.
 
+\section rhumbarea The area under a rhumb line
+
+The area between a rhumb line and the equator is given by
+\f[
+S_{12} = \int_{\lambda_1}^{\lambda_2} c^2 \sin\xi \,d\lambda,
+\f]
+where \f$c\f$ is the authalic radius and \f$\xi\f$ is the authalic
+latitude.  Express \f$\sin\xi\f$ in terms of the conformal latitude
+\f$\chi\f$ and expand as a series in the third flattening \f$n\f$.  This
+can be expressed in terms of powers of \f$\sin\chi\f$.  Substitute
+\f$\sin\chi=\tanh\psi\f$, where \f$\psi\f$ is the isometric latitude.
+For a rhumb line we have
+\f[
+\begin{align}
+\psi &= m(\lambda-\lambda_0),\\
+m &= \frac{\psi_2 - \psi_1}{\lambda_2 - \lambda_1}.
+\end{align}
+\f]
+Performing the integral over \f$\lambda\f$ gives
+\f[
+S_{12} = c^2 \lambda_{12} \left<\sin\xi\right>_{12},
+\f]
+where \f$\left<\sin\xi\right>_{12}\f$ is the mean value of \f$\sin\xi\f$
+given by
+\f[
+\left<\sin\xi\right>_{12} = \frac{S(\chi_2) - S(\chi_1)}{\psi_2 - \psi_1},
+\f]
+with
+\f[
+S(\chi) = \log\sec\chi + \sum_{l=1} R_l\cos(2l\chi),
+\f]
+and \f$R_l = O(n^l)\f$ is given as a series in \f$n\f$ below.  In the
+spherical limit, the sum vanishes.
+
+Note the simple way that longitude enters into the expression for the
+area.  In the limit \f$\chi_2 \rightarrow \chi_1\f$, we can apply
+l'Hôpital's rule
+\f[
+\left<\sin\xi\right>_{12}
+\rightarrow \frac{dS(\chi_1)/d\chi_1}{\sec\chi_1}
+=\sin\xi_1,
+\f]
+as expected.
+
+In order to maintain accuracy, particularly for rhumb lines which nearly
+follow a parallel, evaluate \f$\left<\sin\xi\right>_{12}\f$ using
+divided differences (see the \ref divideddiffs "next section") and use
+Clenshaw summation to evaluate the sum (see the \ref dividedclenshaw
+"last section").
+
+Here is the series expansion accurate to 10th order, found by <a
+href="rhumbarea.mac">rhumbarea.mac</a>:
+
+\verbatim
+R[1] = - 1/3 * n
+       + 22/45 * n^2
+       - 356/945 * n^3
+       + 1772/14175 * n^4
+       + 41662/467775 * n^5
+       - 114456994/638512875 * n^6
+       + 258618446/1915538625 * n^7
+       - 1053168268/37574026875 * n^8
+       - 9127715873002/194896477400625 * n^9
+       + 33380126058386/656284056553125 * n^10;
+R[2] = - 2/15 * n^2
+       + 106/315 * n^3
+       - 1747/4725 * n^4
+       + 18118/155925 * n^5
+       + 51304574/212837625 * n^6
+       - 248174686/638512875 * n^7
+       + 2800191349/14801889375 * n^8
+       + 10890707749202/64965492466875 * n^9
+       - 3594078400868794/10719306257034375 * n^10;
+R[3] = - 31/315 * n^3
+       + 104/315 * n^4
+       - 23011/51975 * n^5
+       + 1554472/14189175 * n^6
+       + 114450437/212837625 * n^7
+       - 8934064508/10854718875 * n^8
+       + 4913033737121/21655164155625 * n^9
+       + 591251098891888/714620417135625 * n^10;
+R[4] = - 41/420 * n^4
+       + 274/693 * n^5
+       - 1228489/2027025 * n^6
+       + 3861434/42567525 * n^7
+       + 1788295991/1550674125 * n^8
+       - 215233237178/123743795175 * n^9
+       + 95577582133463/714620417135625 * n^10;
+R[5] = - 668/5775 * n^5
+       + 1092376/2027025 * n^6
+       - 3966679/4343625 * n^7
+       + 359094172/10854718875 * n^8
+       + 7597613999411/3093594879375 * n^9
+       - 378396252233936/102088631019375 * n^10;
+R[6] = - 313076/2027025 * n^6
+       + 4892722/6081075 * n^7
+       - 1234918799/834978375 * n^8
+       - 74958999806/618718975875 * n^9
+       + 48696857431916/9280784638125 * n^10;
+R[7] = - 3189007/14189175 * n^7
+       + 930092876/723647925 * n^8
+       - 522477774212/206239658625 * n^9
+       - 2163049830386/4331032831125 * n^10;
+R[8] = - 673429061/1929727800 * n^8
+       + 16523158892/7638505875 * n^9
+       - 85076917909/18749059875 * n^10;
+R[9] = - 39191022457/68746552875 * n^9
+       + 260863656866/68746552875 * n^10;
+R[10] = - 22228737368/22915517625 * n^10;
+\endverbatim
+
 \section divideddiffs Use of divided differences
 
 Despite our ability to compute latitudes accurately, the way that
@@ -4589,7 +4709,7 @@ However this is not entirely satisfactory: you have to pick the
 transition point where the derivative takes over from the ratio of
 differences; and, near this transition point, many bits of accuracy will
 be lost (I estimate that about 1/3 of bits are lost, leading to errors
-on the order of 0.1 mm for double precision).  Note too that this
+on the order of 0.1 mm for double precision).  Note too that this
 problem crops up even in the spherical limit.
 
 It turns out that we can do substantially better than this and maintain
@@ -4664,8 +4784,8 @@ limits the applicability of the method to \f$\left|f\right|\lt 0.01\f$.
 If we want to extend the method to arbitrary flattening we need to
 compute \f$\Delta[E](x,y;k)\f$.  The necessary relation is the "addition
 theorem" for the incomplete elliptic integral of the second kind given
-in http://dlmf.nist.gov/19.11.E2.  This can be converted in the followinging divided
-difference formula
+in http://dlmf.nist.gov/19.11.E2.  This can be converted in the
+followinging divided difference formula
 \f[
 \Delta[E](x,y;k)
 =\begin{cases}
@@ -4696,7 +4816,7 @@ rhumb lines for any flattening with full double precision accuracy (the
 maximum error is about 10 nanometers).  I've kept the implementation
 simple, which results in rather a lot of repeated evaluations of
 quantities.  However, in this case, the need for clarity trumps the
-desire for speed..
+desire for speed.
 
 \section dividedclenshaw Clenshaw evaluation of differenced sums
 
@@ -4759,6 +4879,39 @@ where \f$\mathsf B_k\f$ are \f$2\times2\f$ matrices.  The divided
 difference \f$\Delta[g](x,y)\f$ is given by the second element of
 \f$\mathsf G(x,y)\f$.
 
+The same basic recursion applies to the more general case,
+\f[
+g(x) = \sum_{k=0}^N c_k \sin\bigl( (k+k_0)x + x_0\bigr).
+\f]
+For example, the sum area arising in the computation of geodesic areas,
+\f[
+\sum_{k=0}^N c_k\cos\bigl((2k+1)\sigma)
+\f]
+is given by \f$x=2\sigma\f$, \f$x_0=\frac12\pi\f$, \f$k_0=\frac12\f$.
+Again we consider the matrix sum,
+\f[
+\mathsf G(x,y) = \begin{bmatrix}
+(g(x) + g(y)) / 2\\
+(g(x) - g(y)) / (x - y)
+\end{bmatrix} = \sum_{k=0}^N c_k \mathsf F_k(x,y),
+\f]
+where
+\f[
+\mathsf F_k(x,y)=
+\begin{bmatrix}
+     \cos\bigl( (k+k_0)d \bigr) \sin \bigl( (k+k_0)p + x_0 \bigr)\\
+     \frac{\sin\bigl( (k+k_0)d \bigr)}d \cos \bigl( (k+k_0)p + x_0 \bigr)
+\end{bmatrix}.
+\f]
+The recursion for \f$\mathsf B_k\f$ is identical to the previous case;
+in particular, the expression for \f$\mathsf A(x,y)\f$ remains
+unchanged.  The result for the sum is
+\f[
+\mathsf G(x,y) =
+  (c_0\mathsf I - \mathsf B_2) \mathsf F_0(x,y)
+  + \mathsf B_1 \mathsf F_1(x,y).
+\f]
+
 <center>
 Back to \ref triaxial.  Forward to \ref greatellipse.  Up to
 \ref contents.
@@ -4830,9 +4983,12 @@ References:
    Direct and Inverse Solutions of Geodesics on the Ellipsoid with
    Application of Nested Equations</a>,
    Survey Review 23(176), 88--93 (1975).
+ - Wikipedia page, <a href="https://en.wikipedia.org/wiki/Great_ellipse">
+   Great ellipse</a>.
 
 Go to
  - \ref geformulation
+ - \ref gearea
  - \ref gevsgeodesic
 
 \section geformulation Solution of great ellipse problems
@@ -4882,10 +5038,12 @@ The full parametric mapping is:
    and the quadrants of \f$\alpha\f$ and \f$\gamma\f$ are the same.
  - Positions on the great circle of radius \f$a\f$ are parametrized by
    arc length \f$\sigma\f$ measured from the northward crossing of the
-   equator.  The great ellipse has a semi-axes \f$a\f$ and \f$a \sqrt{1 -
-   e^2\cos^2\gamma_0}\f$, where \f$\gamma_0\f$ is the great-circle
-   azimuth at the northward equator crossing, and \f$\sigma\f$ is the
-   parametric angle on the ellipse.
+   equator.  The great ellipse has semi-axes \f$a\f$ and
+   \f$a\sqrt{1-e^2\cos^2\gamma_0}\f$, where \f$\gamma_0\f$ is the
+   great-circle azimuth at the northward equator crossing, and
+   \f$\sigma\f$ is the parametric angle on the ellipse.  [In constrast,
+   the ellipse giving distances on a geodesic has semi-axes
+   \f$b\sqrt{1+e'^2\cos^2\alpha_0}\f$ and \f$b\f$.]
  .
 To determine the distance along the ellipse in terms of \f$\sigma\f$ and
 vice versa, the series for distance \f$s\f$ and for \f$\tau\f$ given in
@@ -4894,6 +5052,121 @@ problems are now simply solved by mapping the problem to the sphere,
 solving the resulting great circle problem, and mapping this back onto
 the ellipsoid.
 
+\section gearea The area under a great ellipse
+
+The area between the segment of a great ellipse and the equator can be
+found by very similar methods to those used for geodesic areas; see <a
+href="http://dx.doi.org/10.1179/003962689791474267"> Danielsen
+(1989)</a>.  The notation here is similar to that employed by
+<a href="http://dx.doi.org/10.1007/s00190-012-0578-z"> Karney
+(2013)</a>.
+\f[
+\begin{align}
+S_{12} &= S(\sigma_2) - S(\sigma_1) \\
+S(\sigma) &= c^2\gamma + e^2 a^2 \cos\gamma_0 \sin\gamma_0 I_4(\sigma)\\
+c^2 &= {\textstyle\frac12}\bigl(a^2 + b^2 (\tanh^{-1}e)/e\bigr)
+\end{align}
+\f]
+\f[
+I_4(\sigma) = - \sqrt{1+e'^2}\int
+\frac{r(e'^2) - r(k^2\sin^2\sigma)}{e'^2 - k^2\sin^2\sigma}
+\frac{\sin\sigma}2 \,d\sigma
+\f]
+\f[
+\begin{align}
+k &= e' \cos\gamma_0,\\
+r(x) &= \sqrt{1+x} + (\sinh^{-1}\sqrt x)/\sqrt x.
+\end{align}
+\f]
+Expand in terms of the third flattening of the ellipsoid, \f$n\f$, and the
+third flattening of the great ellipse, \f$\epsilon\f$, by substituting
+\f[
+\begin{align}
+e'&=\frac{2\sqrt n}{1-n},\\
+k&=\frac{1+n}{1-n} \frac{2\sqrt{\epsilon}}{1+\epsilon},
+\end{align}
+\f]
+to give
+\f[
+I_4(\sigma) = \sum_{l = 0}^\infty G_{4l}\cos \bigl((2l+1)\sigma\bigr).
+\f]
+Compared to the area under a geodesic, we have
+- \f$\gamma\f$ and \f$\gamma_0\f$ instead of \f$\alpha\f$ and
+  \f$\alpha_0\f$.  In both cases, these are azimuths on the auxiliary
+  sphere; however, for the geodesic, they are also the azimuths on the
+  ellipsoid.
+- \f$r(x) = \bigl(1+t(x)\bigr)/\sqrt{1+x}\f$ instead of \f$t(x)\f$ with
+  a balancing factor of \f$\sqrt{1+e'^2}\f$ appearing in front of the
+  integral.  These changes are because expressing
+  \f$\sin\phi\,d\lambda\f$ in terms of \f$\sigma\f$ is a little more
+  complicated with great ellipses.  (Don't worry about the addition of
+  \f$1\f$ to \f$t(x)\f$; that's immaterial.)
+- the factors involving \f$n\f$ in the expression for \f$k\f$ in terms
+  of \f$\epsilon\f$.  This is because \f$k\f$ is defined in terms of
+  \f$e'\f$, whereas it is \f$e\cos\gamma_0\f$ that plays the role of the
+  eccentricity for the great ellipse.
+
+Here is the series expansion accurate to 10th order, found by <a
+href="gearea.mac">gearea.mac</a>:
+
+\verbatim
+G4[0] = + (1/6 + 7/30 * n + 8/105 * n^2 + 4/315 * n^3 + 16/3465 * n^4 + 20/9009 * n^5 + 8/6435 * n^6 + 28/36465 * n^7 + 32/62985 * n^8 + 4/11305 * n^9)
+        - (3/40 + 12/35 * n + 589/840 * n^2 + 1063/1155 * n^3 + 14743/15015 * n^4 + 14899/15015 * n^5 + 254207/255255 * n^6 + 691127/692835 * n^7 + 1614023/1616615 * n^8) * eps
+        + (67/280 + 7081/5040 * n + 5519/1320 * n^2 + 6417449/720720 * n^3 + 708713/45045 * n^4 + 2700154/109395 * n^5 + 519037063/14549535 * n^6 + 78681626/1616615 * n^7) * eps^2
+        - (29597/40320 + 30013/5280 * n + 33759497/1441440 * n^2 + 100611307/1441440 * n^3 + 16639623457/98017920 * n^4 + 3789780779/10581480 * n^5 + 1027832503/1511640 * n^6) * eps^3
+        + (357407/147840 + 19833349/823680 * n + 61890679/480480 * n^2 + 97030756063/196035840 * n^3 + 2853930388817/1862340480 * n^4 + 15123282583393/3724680960 * n^5) * eps^4
+        - (13200233/1537536 + 306285589/2882880 * n + 26279482199/37340160 * n^2 + 3091446335399/931170240 * n^3 + 93089556575647/7449361920 * n^4) * eps^5
+        + (107042267/3294720 + 253176989449/522762240 * n + 57210830762263/14898723840 * n^2 + 641067300459403/29797447680 * n^3) * eps^6
+        - (51544067373/398295040 + 38586720036247/17027112960 * n + 104152290127363/4966241280 * n^2) * eps^7
+        + (369575321823/687964160 + 1721481081751393/158919720960 * n) * eps^8
+        - 10251814360817/4445306880 * eps^9;
+G4[1] = + (1/120 + 4/105 * n + 589/7560 * n^2 + 1063/10395 * n^3 + 14743/135135 * n^4 + 14899/135135 * n^5 + 254207/2297295 * n^6 + 691127/6235515 * n^7 + 1614023/14549535 * n^8) * eps
+        - (53/1680 + 847/4320 * n + 102941/166320 * n^2 + 1991747/1441440 * n^3 + 226409/90090 * n^4 + 3065752/765765 * n^5 + 24256057/4157010 * n^6 + 349229428/43648605 * n^7) * eps^2
+        + (4633/40320 + 315851/332640 * n + 5948333/1441440 * n^2 + 11046565/864864 * n^3 + 9366910279/294053760 * n^4 + 23863367599/349188840 * n^5 + 45824943037/349188840 * n^6) * eps^3
+        - (8021/18480 + 39452953/8648640 * n + 3433618/135135 * n^2 + 29548772933/294053760 * n^3 + 44355142973/139675536 * n^4 + 4771229132843/5587021440 * n^5) * eps^4
+        + (2625577/1537536 + 5439457/247104 * n + 353552588953/2352430080 * n^2 + 405002114215/558702144 * n^3 + 61996934629789/22348085760 * n^4) * eps^5
+        - (91909777/13178880 + 2017395395921/18819440640 * n + 51831652526149/59594895360 * n^2 + 1773086701957889/357569372160 * n^3) * eps^6
+        + (35166639971/1194885120 + 26948019211109/51081338880 * n + 7934238355871/1596291840 * n^2) * eps^7
+        - (131854991623/1031946240 + 312710596037369/119189790720 * n) * eps^8
+        + 842282436291/1481768960 * eps^9;
+G4[2] = + (1/560 + 29/2016 * n + 1027/18480 * n^2 + 203633/1441440 * n^3 + 124051/450450 * n^4 + 1738138/3828825 * n^5 + 98011493/145495350 * n^6 + 4527382/4849845 * n^7) * eps^2
+        - (533/40320 + 14269/110880 * n + 908669/1441440 * n^2 + 15253627/7207200 * n^3 + 910103119/163363200 * n^4 + 2403810527/193993800 * n^5 + 746888717/30630600 * n^6) * eps^3
+        + (2669/36960 + 2443153/2882880 * n + 1024791/200200 * n^2 + 10517570057/490089600 * n^3 + 164668999127/2327925600 * n^4 + 1826633124599/9311702400 * n^5) * eps^4
+        - (5512967/15375360 + 28823749/5765760 * n + 31539382001/871270400 * n^2 + 1699098121381/9311702400 * n^3 + 287618085731/398361600 * n^4) * eps^5
+        + (22684703/13178880 + 25126873327/896163840 * n + 10124249914577/42567782400 * n^2 + 836412216748957/595948953600 * n^3) * eps^6
+        - (3259030001/398295040 + 2610375232847/17027112960 * n + 2121882247763/1418926080 * n^2) * eps^7
+        + (13387413913/343982080 + 939097138279/1135140864 * n) * eps^8
+        - 82722916855/444530688 * eps^9;
+G4[3] = + (5/8064 + 23/3168 * n + 1715/41184 * n^2 + 76061/480480 * n^3 + 812779/1782144 * n^4 + 9661921/8953560 * n^5 + 40072069/18106088 * n^6) * eps^3
+        - (409/59136 + 10211/109824 * n + 46381/73920 * n^2 + 124922951/43563520 * n^3 + 12524132449/1241560320 * n^4 + 30022391821/1022461440 * n^5) * eps^4
+        + (22397/439296 + 302399/384384 * n + 461624513/74680320 * n^2 + 1375058687/41385344 * n^3 + 4805085120841/34763688960 * n^4) * eps^5
+        - (14650421/46126080 + 17533571183/3136573440 * n + 1503945368767/29797447680 * n^2 + 43536234862451/139054755840 * n^3) * eps^6
+        + (5074867067/2788065280 + 479752611137/13243310080 * n + 1228808683449/3310827520 * n^2) * eps^7
+        - (12004715823/1203937280 + 17671119291563/79459860480 * n) * eps^8
+        + 118372499107/2222653440 * eps^9;
+G4[4] = + (7/25344 + 469/109824 * n + 13439/411840 * n^2 + 9282863/56010240 * n^3 + 37558503/59121920 * n^4 + 44204289461/22348085760 * n^5) * eps^4
+        - (5453/1317888 + 58753/823680 * n + 138158857/224040960 * n^2 + 191056103/53209728 * n^3 + 712704605341/44696171520 * n^4) * eps^5
+        + (28213/732160 + 331920271/448081920 * n + 2046013913/283785216 * n^2 + 11489035343/241274880 * n^3) * eps^6
+        - (346326947/1194885120 + 11716182499/1891901440 * n + 860494893431/12770334720 * n^2) * eps^7
+        + (750128501/386979840 + 425425087409/9287516160 * n) * eps^8
+        - 80510858479/6667960320 * eps^9;
+G4[5] = + (21/146432 + 23/8320 * n + 59859/2263040 * n^2 + 452691/2687360 * n^3 + 21458911/26557440 * n^4) * eps^5
+        - (3959/1464320 + 516077/9052160 * n + 51814927/85995520 * n^2 + 15444083489/3611811840 * n^3) * eps^6
+        + (1103391/36208640 + 120920041/171991040 * n + 18522863/2263040 * n^2) * eps^7
+        - (92526613/343982080 + 24477436759/3611811840 * n) * eps^8
+        + 1526273559/740884480 * eps^9;
+G4[6] = + (11/133120 + 1331/696320 * n + 145541/6615040 * n^2 + 46863487/277831680 * n^3) * eps^6
+        - (68079/36208640 + 621093/13230080 * n + 399883/680960 * n^2) * eps^7
+        + (658669/26460160 + 186416197/277831680 * n) * eps^8
+        - 748030679/2963537920 * eps^9;
+G4[7] = + (143/2785280 + 11011/7938048 * n + 972829/52093440 * n^2) * eps^7
+        - (434863/317521920 + 263678129/6667960320 * n) * eps^8
+        + 185257501/8890613760 * eps^9;
+G4[8] = + (715/21168128 + 27313/26148864 * n) * eps^8
+        - 1838551/1778122752 * eps^9;
+G4[9] = + 2431/104595456 * eps^9;
+\endverbatim
+
 \section gevsgeodesic Great ellipses vs geodesics
 
 Some papers advocating the use of great ellipses for navigation exhibit
@@ -4915,7 +5188,7 @@ algorithms for geodesics, by Vincenty (1975), come with some
 "asterisks":
  - no derivation was given (although they follow in a straightforward
    fashion from classic 19th century methods);
- - the accuracy is "only" 0.5 mm or so, surely good enough for most
+ - the accuracy is "only" 0.5 mm or so, surely good enough for most
    applications, but still a reason for a user to worry and a spur to
    numerous studies "validating" the algorithms;
  - no indication is given for how to extend the series to improve the
@@ -4936,24 +5209,25 @@ some way to handle this problem.
 For these reasons, substitution of a great ellipse for the geodesic
 makes some sense.  The solution of the great ellipse is, in principle,
 no more difficult than solving for the great circle and, for paths of
-less then 10000 km, the error in the distance is less than 13.5 m.
+less then 10000 km, the error in the distance is less than
+13.5 m.
 
 Now (2014), however, the situation has reversed.  The algorithms given
 by Karney (2013)—and used in GeographicLib since
 2009—explicitly resolve the issues with Vincenty's algorithm.  The
 geodesic problem is conveniently bundled into a library.  Users can call
 this with an assurance of an accurate result much as they would when
-evaluating \f$\sin x\f$.  On the other, great ellipses come with their
-own set of asterisks:
+evaluating \f$\sin x\f$.  On the other hand, great ellipses come with
+their own set of asterisks:
  - To the extent that they are regarded as approximations to geodesics,
    the errors need to be quantified, the limits of allowable use
    documented, etc.
  - The user is now left with decisions on when to trust the results and
    to find alternative solutions if necessary.
- - Even though the great ellipse is no more that 13.5 m longer than a
-   10000 km geodesic, the path of the great ellipse can deviate from the
-   geodesic by as much as 8.3 km.  This disqualifies great ellipses from
-   use in congested air corridors where the
+ - Even though the great ellipse is no more that 13.5 m longer than
+   a 10000 km geodesic, the path of the great ellipse can deviate
+   from the geodesic by as much as 8.3 km.  This disqualifies great
+   ellipses from use in congested air corridors where the
    <a href="https://en.wikipedia.org/wiki/Strategic_lateral_offset_procedure">
    strategic lateral offset procedure</a> is in effect and in any
    situation which demands coordination in the routes of vessels.
@@ -4972,10 +5246,10 @@ al. given above:
    maintain because it allows the results to be used reliably in more
    complex problems (e.g., in the determination of maritime boundaries).
  - "unnecessary consumption of computing power": The solution of the
-   inverse geodesic problem takes 2.3 μs; multiple points on a
-   geodesic can be computed at a rate of one point per 0.4 μs.  The
-   actual power consumed in these calculations is miniscule compared to
-   the power needed to drive the display of a navigational computer.
+   inverse geodesic problem takes 2.3 μs; multiple points on a
+   geodesic can be computed at a rate of one point per 0.4 μs.
+   The actual power consumed in these calculations is miniscule compared
+   to the power needed to drive the display of a navigational computer.
  - "formulas that are much too complex": There's no question that the
    solution of the geodesic problem is more complex than for great
    ellipses.  However this complexity is only an issue when
@@ -4986,13 +5260,13 @@ al. given above:
    <blockquote>"The shortest path is found."</blockquote>
    And here is the corresponding documentation for great ellipses:
    <blockquote>"A path which closely approximates the shortest path is
-   found.  Provided that the distance is less than 10000 km, the error
-   in distance is no more than 14 m and the deviation the route from
-   that of the shortest path is no more than 9 km.  These bounds apply
-   to the WGS84 ellipsoid.  The deviation of the path means that it
-   should be used with caution when planning routes.  In addition, great
-   ellipses do not obey the triangle inequality; this disqualifies them
-   from use in some applications."</blockquote>
+   found.  Provided that the distance is less than 10000 km, the
+   error in distance is no more than 14 m and the deviation the
+   route from that of the shortest path is no more than 9 km.
+   These bounds apply to the WGS84 ellipsoid.  The deviation of the path
+   means that it should be used with caution when planning routes.  In
+   addition, great ellipses do not obey the triangle inequality; this
+   disqualifies them from use in some applications."</blockquote>
 
 Having all the geodesic functions bundled up into a reliable "black box"
 enables users to concentrate on how to solve problems using geodesics
@@ -5010,7 +5284,7 @@ Back to \ref rhumb.  Forward to \ref transversemercator.  Up to
 \page transversemercator Transverse Mercator projection
 
 <center>
-Back to \ref rhumb.  Forward to \ref geocentric.  Up to \ref contents.
+Back to \ref greatellipse.  Forward to \ref geocentric.  Up to \ref contents.
 </center>
 
 TransverseMercator and TransverseMercatorExact provide accurate
@@ -5067,13 +5341,13 @@ 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.
+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)
+ - easting (meters, accurate to 0.1 pm)
+ - northing (meters, accurate to 0.1 pm)
  - meridian convergence (degrees, accurate to 10<sup>−18</sup> deg)
  - scale (accurate to 10<sup>−20</sup>)
  .
@@ -5081,7 +5355,7 @@ The latitude and longitude are all multiples of 10<sup>−12</sup>
 deg and should be regarded as exact, except that longitude =
 82.63627282416406551 should be interpreted as exactly 90 (1 - \e e)
 degrees.  These results are computed using Lee's formulas with
-<a href="http://en.wikipedia.org/wiki/Maxima_(software)">Maxima</a>'s
+<a href="https://en.wikipedia.org/wiki/Maxima_(software)">Maxima</a>'s
 bfloats and fpprec set to 80 (so the errors in the data are probably 1/2
 of the values quoted above).  The Maxima code,
 <a href="tm.mac">tm.mac</a> and <a href="ellint.mac">ellint.mac</a>,
@@ -5126,7 +5400,7 @@ 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
+Mercator projection.  This is accurate to about 200 nm (200
 nanometers) within the UTM domain.  Here we present the series
 extended to 10th order.  By default, TransverseMercator
 uses the 6th-order approximation. The preprocessor macro
@@ -5380,14 +5654,14 @@ projection (Fig. 3(a)).  The extended Thompson projection figure has
 reflection symmetry on all the four sides of Fig. 3(c).
 
 <center>
-Back to \ref rhumb.  Forward to \ref geocentric.  Up to \ref contents.
+Back to \ref greatellipse.  Forward to \ref geocentric.  Up to \ref contents.
 </center>
 **********************************************************************/
 /**
 \page geocentric Geocentric coordinates
 
 <center>
-Back to \ref transversemercator.  Forward to \ref highprec.  Up to
+Back to \ref transversemercator.  Forward to \ref auxlat.  Up to
 \ref contents.
 </center>
 
@@ -5434,8 +5708,8 @@ Geocentric::WGS84.Forward which uses long doubles (including using long
 doubles for the WGS84 parameters).  Generate random (long double)
 geodetic coordinates (\e lat0, \e lon0, \e h0) and use the "long double"
 WGS84.Forward to obtain the corresponding (long double) geocentric
-coordinates (\e x0, \e y0, \e z0).  [We restrict \e h0 so that
-\e h0 ≥ − \e a (1 − <i>e</i><sup>2</sup>) / sqrt(1 −
+coordinates (\e x0, \e y0, \e z0).  [We restrict \e h0 so that \e h0
+≥ − \e a (1 − <i>e</i><sup>2</sup>) / sqrt(1 −
 <i>e</i><sup>2</sup> sin<sup>2</sup>\e lat0), which ensures that (\e
 lat0, \e lon0, \e h0) is the principal geodetic inverse of (\e x0, \e
 y0, \e z0).]  Because the forward calculation is numerically stable and
@@ -5447,22 +5721,23 @@ Apply the double version of WGS84.Reverse to (\e x0, \e y0, \e z0) to
 compute the approximate geodetic coordinates (\e lat1, \e lon1, \e h1).
 Convert (\e lat1 − \e lat0, \e lon1 − \e lon0) to a
 distance, \e ds, on the surface of the ellipsoid and define \e err =
-hypot(\e ds, \e h1 − \e h0).  For |<i>h0</i>| < 5000 km, we have \e
-err < 7 nm (7 nanometers).
+hypot(\e ds, \e h1 − \e h0).  For |<i>h0</i>| < 5000 km, we
+have \e err < 7 nm (7 nanometers).
 
 This methodology is not very useful very far from the globe, because the
 absolute errors in the approximate geodetic height become large, or
-within 50 km of the center of the earth, because of errors in computing
-the approximate geodetic latitude.  To illustrate the second issue, the
-maximum value of \e err for \e h0 < 0 is about 80 mm.  The error is
-maximum close to the circle given by geocentric coordinates satisfying
-hypot(\e x, \e y) = \e a <i>e</i><sup>2</sup> (= 42.7 km), \e z = 0.
-(This is the center of meridional curvature for \e lat = 0.)  The
-geodetic latitude for these points is \e lat = 0.  However, if we move 1
-nm towards the center of the earth, the geodetic latitude becomes 0.04",
-a distance of 1.4 m from the equator.  If, instead, we move 1 nm up, the
-geodetic latitude becomes 7.45", a distance of 229 m from the equator.
-In light of this, Reverse does quite well in this vicinity.
+within 50 km of the center of the earth, because of errors in
+computing the approximate geodetic latitude.  To illustrate the second
+issue, the maximum value of \e err for \e h0 < 0 is about 80 mm.
+The error is maximum close to the circle given by geocentric coordinates
+satisfying hypot(\e x, \e y) = \e a <i>e</i><sup>2</sup> (=
+42.7 km), \e z = 0.  (This is the center of meridional curvature
+for \e lat = 0.)  The geodetic latitude for these points is \e lat = 0.
+However, if we move 1 nm towards the center of the earth, the
+geodetic latitude becomes 0.04", a distance of 1.4 m from the
+equator.  If, instead, we move 1 nm up, the geodetic latitude
+becomes 7.45", a distance of 229 m from the equator.  In light of
+this, Reverse does quite well in this vicinity.
 
 To obtain a practical measure of the error for the general case we define
 - <i>err</i><sub>h</sub> = |\e h1 − <i>h0</i>| / max(1, \e h0 / \e a)
@@ -5472,8 +5747,9 @@ To obtain a practical measure of the error for the general case we define
   <i>err</i><sub>in</sub> = hypot(\e x1 − \e x0, \e y1 − \e
   y0, \e z1 − \e z0).
 .
-We then find <i>err</i><sub>h</sub> < 8 nm, <i>err</i><sub>out</sub> < 4 nm,
-and <i>err</i><sub>in</sub> < 7 nm.  (1 nm = 1 nanometer.)
+We then find <i>err</i><sub>h</sub> < 8 nm,
+<i>err</i><sub>out</sub> < 4 nm, and <i>err</i><sub>in</sub> <
+7 nm.  (1 nm = 1 nanometer.)
 
 The testing has been confined to the WGS84 ellipsoid.  The method will
 work for all ellipsoids used in terrestrial geodesy.  However, the
@@ -5496,7 +5772,549 @@ However the choice of independent variables in these methods leads
 to a loss of accuracy for points near the equatorial plane.
 
 <center>
-Back to \ref transversemercator.  Forward to \ref highprec.  Up to
+Back to \ref transversemercator.  Forward to \ref auxlat.  Up to
+\ref contents.
+
+</center>
+**********************************************************************/
+/**
+\page auxlat Auxiliary latitudes
+
+<center>
+Back to \ref geocentric.  Forward to \ref highprec.  Up to
+\ref contents.
+</center>
+
+Six latitudes are used by GeographicLib:
+- φ, the (geographic) latitude;
+- β, the parametric latitude;
+- θ, the geocentric latitude;
+- μ, the rectifying latitude;
+- χ, the conformal latitude;
+- ξ, the authalic latitude.
+.
+The last five of these are called <i>auxiliary latitudes</i>.  These
+quantities are all defined in the
+<a href="https://en.wikipedia.org/wiki/Latitude#Auxiliary_latitudes">
+Wikipedia article on latitudes</a>.  (In addition there's the isometric
+latitude, ψ = sinh<sup>−1</sup> tanχ; but this is not
+an angle-like variable and we don't consider it further here.)  The
+relations between φ, β, and θ are all simple elementary
+functions.  The latitudes χ and ξ can be expressed as elementary
+functions of φ; however, these functions can only be inverted
+iteratively.  The rectifying latitude μ as a function of φ (or
+β) involves the incomplete elliptic integral of the second kind
+(which is not an elementary function) and this needs to be inverted
+iteratively.  The Ellipsoid class evaluates all the auxiliary latitudes
+(and the corresponding inverse relations) in terms of their basic
+definitions.
+
+An alternative method of evaluating these auxiliary latitudes is in
+terms of trigonometric series.  This offers some advantages:
+- these series give a uniform way of expressing any latitude in terms of
+  any other latitude;
+- the evaluation may be faster, particularly if Clenshaw summation is
+  used;
+- provided that the flattening is sufficiently small, the result may be
+  more accurate.
+
+Here we give the complete matrix of relations between all six latitudes;
+there are 30 (= 6 × 5) such relations.  The
+expansions are in terms of the third flattening <i>n</i> =
+(<i>a</i> − <i>b</i>)/(<i>a</i> + <i>b</i>).
+This results in expansions in which half the coefficients vanish for all
+relations between φ, β, θ, and μ.  In addition, the
+expansions converge for <i>b</i>/<i>a</i> ∈ (0, ∞).
+(Some authors use the eccentricity as the expansion parameter, but the
+resulting series only converge for <i>b</i>/<i>a</i> ∈
+(0, √2).  These expansions were obtained with the the maxima
+code, <a href="auxlat.mac">auxlat.mac</a>.
+
+Here are the relations between φ, β, θ, and μ carried
+out to 4th order in <i>n</i>:
+\f[
+\begin{align}
+\beta-\phi&=\textstyle{}
+-n\sin 2\phi
++\frac{1}{2}n^{2}\sin 4\phi
+-\frac{1}{3}n^{3}\sin 6\phi
++\frac{1}{4}n^{4}\sin 8\phi
+-\ldots\\
+\phi-\beta&=\textstyle{}
++n\sin 2\beta
++\frac{1}{2}n^{2}\sin 4\beta
++\frac{1}{3}n^{3}\sin 6\beta
++\frac{1}{4}n^{4}\sin 8\beta
++\ldots\\
+\theta-\phi&=\textstyle{}
+-\bigl(2n-2n^{3}\bigr)\sin 2\phi
++\bigl(2n^{2}-4n^{4}\bigr)\sin 4\phi
+-\frac{8}{3}n^{3}\sin 6\phi
++4n^{4}\sin 8\phi
+-\ldots\\
+\phi-\theta&=\textstyle{}
++\bigl(2n-2n^{3}\bigr)\sin 2\theta
++\bigl(2n^{2}-4n^{4}\bigr)\sin 4\theta
++\frac{8}{3}n^{3}\sin 6\theta
++4n^{4}\sin 8\theta
++\ldots\\
+\theta-\beta&=\textstyle{}
+-n\sin 2\beta
++\frac{1}{2}n^{2}\sin 4\beta
+-\frac{1}{3}n^{3}\sin 6\beta
++\frac{1}{4}n^{4}\sin 8\beta
+-\ldots\\
+\beta-\theta&=\textstyle{}
++n\sin 2\theta
++\frac{1}{2}n^{2}\sin 4\theta
++\frac{1}{3}n^{3}\sin 6\theta
++\frac{1}{4}n^{4}\sin 8\theta
++\ldots\\
+\mu-\phi&=\textstyle{}
+-\bigl(\frac{3}{2}n-\frac{9}{16}n^{3}\bigr)\sin 2\phi
++\bigl(\frac{15}{16}n^{2}-\frac{15}{32}n^{4}\bigr)\sin 4\phi
+-\frac{35}{48}n^{3}\sin 6\phi
++\frac{315}{512}n^{4}\sin 8\phi
+-\ldots\\
+\phi-\mu&=\textstyle{}
++\bigl(\frac{3}{2}n-\frac{27}{32}n^{3}\bigr)\sin 2\mu
++\bigl(\frac{21}{16}n^{2}-\frac{55}{32}n^{4}\bigr)\sin 4\mu
++\frac{151}{96}n^{3}\sin 6\mu
++\frac{1097}{512}n^{4}\sin 8\mu
++\ldots\\
+\mu-\beta&=\textstyle{}
+-\bigl(\frac{1}{2}n-\frac{3}{16}n^{3}\bigr)\sin 2\beta
+-\bigl(\frac{1}{16}n^{2}-\frac{1}{32}n^{4}\bigr)\sin 4\beta
+-\frac{1}{48}n^{3}\sin 6\beta
+-\frac{5}{512}n^{4}\sin 8\beta
+-\ldots\\
+\beta-\mu&=\textstyle{}
++\bigl(\frac{1}{2}n-\frac{9}{32}n^{3}\bigr)\sin 2\mu
++\bigl(\frac{5}{16}n^{2}-\frac{37}{96}n^{4}\bigr)\sin 4\mu
++\frac{29}{96}n^{3}\sin 6\mu
++\frac{539}{1536}n^{4}\sin 8\mu
++\ldots\\
+\mu-\theta&=\textstyle{}
++\bigl(\frac{1}{2}n+\frac{13}{16}n^{3}\bigr)\sin 2\theta
+-\bigl(\frac{1}{16}n^{2}-\frac{33}{32}n^{4}\bigr)\sin 4\theta
+-\frac{5}{16}n^{3}\sin 6\theta
+-\frac{261}{512}n^{4}\sin 8\theta
+-\ldots\\
+\theta-\mu&=\textstyle{}
+-\bigl(\frac{1}{2}n+\frac{23}{32}n^{3}\bigr)\sin 2\mu
++\bigl(\frac{5}{16}n^{2}-\frac{5}{96}n^{4}\bigr)\sin 4\mu
++\frac{1}{32}n^{3}\sin 6\mu
++\frac{283}{1536}n^{4}\sin 8\mu
++\ldots\\
+\end{align}
+\f]
+
+Here are the remaining relations (including χ and ξ) carried out
+to 3th order in <i>n</i>:
+\f[
+\begin{align}
+\chi-\phi&=\textstyle{}
+-\bigl(2n-\frac{2}{3}n^{2}-\frac{4}{3}n^{3}\bigr)\sin 2\phi
++\bigl(\frac{5}{3}n^{2}-\frac{16}{15}n^{3}\bigr)\sin 4\phi
+-\frac{26}{15}n^{3}\sin 6\phi
++\ldots\\
+\phi-\chi&=\textstyle{}
++\bigl(2n-\frac{2}{3}n^{2}-2n^{3}\bigr)\sin 2\chi
++\bigl(\frac{7}{3}n^{2}-\frac{8}{5}n^{3}\bigr)\sin 4\chi
++\frac{56}{15}n^{3}\sin 6\chi
++\ldots\\
+\chi-\beta&=\textstyle{}
+-\bigl(n-\frac{2}{3}n^{2}\bigr)\sin 2\beta
++\bigl(\frac{1}{6}n^{2}-\frac{2}{5}n^{3}\bigr)\sin 4\beta
+-\frac{1}{15}n^{3}\sin 6\beta
++\ldots\\
+\beta-\chi&=\textstyle{}
++\bigl(n-\frac{2}{3}n^{2}-\frac{1}{3}n^{3}\bigr)\sin 2\chi
++\bigl(\frac{5}{6}n^{2}-\frac{14}{15}n^{3}\bigr)\sin 4\chi
++\frac{16}{15}n^{3}\sin 6\chi
++\ldots\\
+\chi-\theta&=\textstyle{}
++\bigl(\frac{2}{3}n^{2}+\frac{2}{3}n^{3}\bigr)\sin 2\theta
+-\bigl(\frac{1}{3}n^{2}-\frac{4}{15}n^{3}\bigr)\sin 4\theta
+-\frac{2}{5}n^{3}\sin 6\theta
+-\ldots\\
+\theta-\chi&=\textstyle{}
+-\bigl(\frac{2}{3}n^{2}+\frac{2}{3}n^{3}\bigr)\sin 2\chi
++\bigl(\frac{1}{3}n^{2}-\frac{4}{15}n^{3}\bigr)\sin 4\chi
++\frac{2}{5}n^{3}\sin 6\chi
++\ldots\\
+\chi-\mu&=\textstyle{}
+-\bigl(\frac{1}{2}n-\frac{2}{3}n^{2}+\frac{37}{96}n^{3}\bigr)\sin 2\mu
+-\bigl(\frac{1}{48}n^{2}+\frac{1}{15}n^{3}\bigr)\sin 4\mu
+-\frac{17}{480}n^{3}\sin 6\mu
+-\ldots\\
+\mu-\chi&=\textstyle{}
++\bigl(\frac{1}{2}n-\frac{2}{3}n^{2}+\frac{5}{16}n^{3}\bigr)\sin 2\chi
++\bigl(\frac{13}{48}n^{2}-\frac{3}{5}n^{3}\bigr)\sin 4\chi
++\frac{61}{240}n^{3}\sin 6\chi
++\ldots\\
+\xi-\phi&=\textstyle{}
+-\bigl(\frac{4}{3}n+\frac{4}{45}n^{2}-\frac{88}{315}n^{3}\bigr)\sin 2\phi
++\bigl(\frac{34}{45}n^{2}+\frac{8}{105}n^{3}\bigr)\sin 4\phi
+-\frac{1532}{2835}n^{3}\sin 6\phi
++\ldots\\
+\phi-\xi&=\textstyle{}
++\bigl(\frac{4}{3}n+\frac{4}{45}n^{2}-\frac{16}{35}n^{3}\bigr)\sin 2\xi
++\bigl(\frac{46}{45}n^{2}+\frac{152}{945}n^{3}\bigr)\sin 4\xi
++\frac{3044}{2835}n^{3}\sin 6\xi
++\ldots\\
+\xi-\beta&=\textstyle{}
+-\bigl(\frac{1}{3}n+\frac{4}{45}n^{2}-\frac{32}{315}n^{3}\bigr)\sin 2\beta
+-\bigl(\frac{7}{90}n^{2}+\frac{4}{315}n^{3}\bigr)\sin 4\beta
+-\frac{83}{2835}n^{3}\sin 6\beta
+-\ldots\\
+\beta-\xi&=\textstyle{}
++\bigl(\frac{1}{3}n+\frac{4}{45}n^{2}-\frac{46}{315}n^{3}\bigr)\sin 2\xi
++\bigl(\frac{17}{90}n^{2}+\frac{68}{945}n^{3}\bigr)\sin 4\xi
++\frac{461}{2835}n^{3}\sin 6\xi
++\ldots\\
+\xi-\theta&=\textstyle{}
++\bigl(\frac{2}{3}n-\frac{4}{45}n^{2}+\frac{62}{105}n^{3}\bigr)\sin 2\theta
++\bigl(\frac{4}{45}n^{2}-\frac{32}{315}n^{3}\bigr)\sin 4\theta
+-\frac{524}{2835}n^{3}\sin 6\theta
+-\ldots\\
+\theta-\xi&=\textstyle{}
+-\bigl(\frac{2}{3}n-\frac{4}{45}n^{2}+\frac{158}{315}n^{3}\bigr)\sin 2\xi
++\bigl(\frac{16}{45}n^{2}-\frac{16}{945}n^{3}\bigr)\sin 4\xi
+-\frac{232}{2835}n^{3}\sin 6\xi
++\ldots\\
+\xi-\mu&=\textstyle{}
++\bigl(\frac{1}{6}n-\frac{4}{45}n^{2}-\frac{817}{10080}n^{3}\bigr)\sin 2\mu
++\bigl(\frac{49}{720}n^{2}-\frac{2}{35}n^{3}\bigr)\sin 4\mu
++\frac{4463}{90720}n^{3}\sin 6\mu
++\ldots\\
+\mu-\xi&=\textstyle{}
+-\bigl(\frac{1}{6}n-\frac{4}{45}n^{2}-\frac{121}{1680}n^{3}\bigr)\sin 2\xi
+-\bigl(\frac{29}{720}n^{2}-\frac{26}{945}n^{3}\bigr)\sin 4\xi
+-\frac{1003}{45360}n^{3}\sin 6\xi
+-\ldots\\
+\xi-\chi&=\textstyle{}
++\bigl(\frac{2}{3}n-\frac{34}{45}n^{2}+\frac{46}{315}n^{3}\bigr)\sin 2\chi
++\bigl(\frac{19}{45}n^{2}-\frac{256}{315}n^{3}\bigr)\sin 4\chi
++\frac{248}{567}n^{3}\sin 6\chi
++\ldots\\
+\chi-\xi&=\textstyle{}
+-\bigl(\frac{2}{3}n-\frac{34}{45}n^{2}+\frac{88}{315}n^{3}\bigr)\sin 2\xi
++\bigl(\frac{1}{45}n^{2}-\frac{184}{945}n^{3}\bigr)\sin 4\xi
+-\frac{106}{2835}n^{3}\sin 6\xi
+-\ldots\\
+\end{align}
+\f]
+
+Finally, this is a listing of all the coefficients for the expansions
+carried out to 8th order in <i>n</i>.  Here's how to interpret this
+data: the 5th line for φ − θ is <tt>[32/5, 0,
+-32, 0]</tt>; this means that the coefficient of sin(10θ) is
+[(32/5)<i>n</i><sup>5</sup> −
+32<i>n</i><sup>7</sup> + <i>O</i>(<i>n</i><sup>9</sup>)].
+<p>β − φ:<br><tt><small>
+   [-1, 0, 0, 0, 0, 0, 0, 0]<br>
+   [1/2, 0, 0, 0, 0, 0, 0]<br>
+   [-1/3, 0, 0, 0, 0, 0]<br>
+   [1/4, 0, 0, 0, 0]<br>
+   [-1/5, 0, 0, 0]<br>
+   [1/6, 0, 0]<br>
+   [-1/7, 0]<br>
+   [1/8]<br>
+</small></tt>
+<p>φ − β:<br><tt><small>
+   [1, 0, 0, 0, 0, 0, 0, 0]<br>
+   [1/2, 0, 0, 0, 0, 0, 0]<br>
+   [1/3, 0, 0, 0, 0, 0]<br>
+   [1/4, 0, 0, 0, 0]<br>
+   [1/5, 0, 0, 0]<br>
+   [1/6, 0, 0]<br>
+   [1/7, 0]<br>
+   [1/8]<br>
+</small></tt>
+<p>θ − φ:<br><tt><small>
+   [-2, 0, 2, 0, -2, 0, 2, 0]<br>
+   [2, 0, -4, 0, 6, 0, -8]<br>
+   [-8/3, 0, 8, 0, -16, 0]<br>
+   [4, 0, -16, 0, 40]<br>
+   [-32/5, 0, 32, 0]<br>
+   [32/3, 0, -64]<br>
+   [-128/7, 0]<br>
+   [32]<br>
+</small></tt>
+<p>φ − θ:<br><tt><small>
+   [2, 0, -2, 0, 2, 0, -2, 0]<br>
+   [2, 0, -4, 0, 6, 0, -8]<br>
+   [8/3, 0, -8, 0, 16, 0]<br>
+   [4, 0, -16, 0, 40]<br>
+   [32/5, 0, -32, 0]<br>
+   [32/3, 0, -64]<br>
+   [128/7, 0]<br>
+   [32]<br>
+</small></tt>
+<p>θ − β:<br><tt><small>
+   [-1, 0, 0, 0, 0, 0, 0, 0]<br>
+   [1/2, 0, 0, 0, 0, 0, 0]<br>
+   [-1/3, 0, 0, 0, 0, 0]<br>
+   [1/4, 0, 0, 0, 0]<br>
+   [-1/5, 0, 0, 0]<br>
+   [1/6, 0, 0]<br>
+   [-1/7, 0]<br>
+   [1/8]<br>
+</small></tt>
+<p>β − θ:<br><tt><small>
+   [1, 0, 0, 0, 0, 0, 0, 0]<br>
+   [1/2, 0, 0, 0, 0, 0, 0]<br>
+   [1/3, 0, 0, 0, 0, 0]<br>
+   [1/4, 0, 0, 0, 0]<br>
+   [1/5, 0, 0, 0]<br>
+   [1/6, 0, 0]<br>
+   [1/7, 0]<br>
+   [1/8]<br>
+</small></tt>
+<p>μ − φ:<br><tt><small>
+   [-3/2, 0, 9/16, 0, -3/32, 0, 57/2048, 0]<br>
+   [15/16, 0, -15/32, 0, 135/2048, 0, -105/4096]<br>
+   [-35/48, 0, 105/256, 0, -105/2048, 0]<br>
+   [315/512, 0, -189/512, 0, 693/16384]<br>
+   [-693/1280, 0, 693/2048, 0]<br>
+   [1001/2048, 0, -1287/4096]<br>
+   [-6435/14336, 0]<br>
+   [109395/262144]<br>
+</small></tt>
+<p>φ − μ:<br><tt><small>
+   [3/2, 0, -27/32, 0, 269/512, 0, -6607/24576, 0]<br>
+   [21/16, 0, -55/32, 0, 6759/4096, 0, -155113/122880]<br>
+   [151/96, 0, -417/128, 0, 87963/20480, 0]<br>
+   [1097/512, 0, -15543/2560, 0, 2514467/245760]<br>
+   [8011/2560, 0, -69119/6144, 0]<br>
+   [293393/61440, 0, -5962461/286720]<br>
+   [6459601/860160, 0]<br>
+   [332287993/27525120]<br>
+</small></tt>
+<p>μ − β:<br><tt><small>
+   [-1/2, 0, 3/16, 0, -1/32, 0, 19/2048, 0]<br>
+   [-1/16, 0, 1/32, 0, -9/2048, 0, 7/4096]<br>
+   [-1/48, 0, 3/256, 0, -3/2048, 0]<br>
+   [-5/512, 0, 3/512, 0, -11/16384]<br>
+   [-7/1280, 0, 7/2048, 0]<br>
+   [-7/2048, 0, 9/4096]<br>
+   [-33/14336, 0]<br>
+   [-429/262144]<br>
+</small></tt>
+<p>β − μ:<br><tt><small>
+   [1/2, 0, -9/32, 0, 205/1536, 0, -4879/73728, 0]<br>
+   [5/16, 0, -37/96, 0, 1335/4096, 0, -86171/368640]<br>
+   [29/96, 0, -75/128, 0, 2901/4096, 0]<br>
+   [539/1536, 0, -2391/2560, 0, 1082857/737280]<br>
+   [3467/7680, 0, -28223/18432, 0]<br>
+   [38081/61440, 0, -733437/286720]<br>
+   [459485/516096, 0]<br>
+   [109167851/82575360]<br>
+</small></tt>
+<p>μ − θ:<br><tt><small>
+   [1/2, 0, 13/16, 0, -15/32, 0, 509/2048, 0]<br>
+   [-1/16, 0, 33/32, 0, -1673/2048, 0, 2599/4096]<br>
+   [-5/16, 0, 349/256, 0, -2989/2048, 0]<br>
+   [-261/512, 0, 963/512, 0, -43531/16384]<br>
+   [-921/1280, 0, 5545/2048, 0]<br>
+   [-6037/6144, 0, 16617/4096]<br>
+   [-19279/14336, 0]<br>
+   [-490925/262144]<br>
+</small></tt>
+<p>θ − μ:<br><tt><small>
+   [-1/2, 0, -23/32, 0, 499/1536, 0, -14321/73728, 0]<br>
+   [5/16, 0, -5/96, 0, 6565/12288, 0, -201467/368640]<br>
+   [1/32, 0, -77/128, 0, 2939/4096, 0]<br>
+   [283/1536, 0, -4037/7680, 0, 1155049/737280]<br>
+   [1301/7680, 0, -19465/18432, 0]<br>
+   [17089/61440, 0, -442269/286720]<br>
+   [198115/516096, 0]<br>
+   [48689387/82575360]<br>
+</small></tt>
+<p>χ − φ:<br><tt><small>
+   [-2, 2/3, 4/3, -82/45, 32/45, 4642/4725, -8384/4725, 1514/1323]<br>
+   [5/3, -16/15, -13/9, 904/315, -1522/945, -2288/1575, 142607/42525]<br>
+   [-26/15, 34/21, 8/5, -12686/2835, 44644/14175, 120202/51975]<br>
+   [1237/630, -12/5, -24832/14175, 1077964/155925, -1097407/187110]<br>
+   [-734/315, 109598/31185, 1040/567, -12870194/1216215]<br>
+   [444337/155925, -941912/184275, -126463/72765]<br>
+   [-2405834/675675, 3463678/467775]<br>
+   [256663081/56756700]<br>
+</small></tt>
+<p>φ − χ:<br><tt><small>
+   [2, -2/3, -2, 116/45, 26/45, -2854/675, 16822/4725, 189416/99225]<br>
+   [7/3, -8/5, -227/45, 2704/315, 2323/945, -31256/1575, 141514/8505]<br>
+   [56/15, -136/35, -1262/105, 73814/2835, 98738/14175, -2363828/31185]<br>
+   [4279/630, -332/35, -399572/14175, 11763988/155925, 14416399/935550]<br>
+   [4174/315, -144838/6237, -2046082/31185, 258316372/1216215]<br>
+   [601676/22275, -115444544/2027025, -2155215124/14189175]<br>
+   [38341552/675675, -170079376/1216215]<br>
+   [1383243703/11351340]<br>
+</small></tt>
+<p>χ − β:<br><tt><small>
+   [-1, 2/3, 0, -16/45, 2/5, -998/4725, -34/4725, 1384/11025]<br>
+   [1/6, -2/5, 19/45, -22/105, -2/27, 1268/4725, -12616/42525]<br>
+   [-1/15, 16/105, -22/105, 116/567, -1858/14175, 1724/51975]<br>
+   [17/1260, -8/105, 2123/14175, -26836/155925, 115249/935550]<br>
+   [-1/105, 128/4455, -424/6237, 140836/1216215]<br>
+   [149/311850, -31232/2027025, 210152/4729725]<br>
+   [-499/225225, 30208/6081075]<br>
+   [-68251/113513400]<br>
+</small></tt>
+<p>β − χ:<br><tt><small>
+   [1, -2/3, -1/3, 38/45, -1/3, -3118/4725, 4769/4725, -25666/99225]<br>
+   [5/6, -14/15, -7/9, 50/21, -247/270, -14404/4725, 193931/42525]<br>
+   [16/15, -34/21, -5/3, 17564/2835, -36521/14175, -1709614/155925]<br>
+   [2069/1260, -28/9, -49877/14175, 2454416/155925, -637699/85050]<br>
+   [883/315, -28244/4455, -20989/2835, 48124558/1216215]<br>
+   [797222/155925, -2471888/184275, -16969807/1091475]<br>
+   [2199332/225225, -1238578/42525]<br>
+   [87600385/4540536]<br>
+</small></tt>
+<p>χ − θ:<br><tt><small>
+   [0, 2/3, 2/3, -2/9, -14/45, 1042/4725, 18/175, -1738/11025]<br>
+   [-1/3, 4/15, 43/45, -4/45, -712/945, 332/945, 23159/42525]<br>
+   [-2/5, 2/105, 124/105, 274/2835, -1352/945, 13102/31185]<br>
+   [-55/126, -16/105, 21068/14175, 1528/4725, -2414843/935550]<br>
+   [-22/45, -9202/31185, 20704/10395, 60334/93555]<br>
+   [-90263/155925, -299444/675675, 40458083/14189175]<br>
+   [-8962/12285, -3818498/6081075]<br>
+   [-4259027/4365900]<br>
+</small></tt>
+<p>θ − χ:<br><tt><small>
+   [0, -2/3, -2/3, 4/9, 2/9, -3658/4725, 76/225, 64424/99225]<br>
+   [1/3, -4/15, -23/45, 68/45, 61/135, -2728/945, 2146/1215]<br>
+   [2/5, -24/35, -46/35, 9446/2835, 428/945, -95948/10395]<br>
+   [83/126, -80/63, -34712/14175, 4472/525, 29741/85050]<br>
+   [52/45, -2362/891, -17432/3465, 280108/13365]<br>
+   [335882/155925, -548752/96525, -48965632/4729725]<br>
+   [51368/12285, -197456/15795]<br>
+   [1461335/174636]<br>
+</small></tt>
+<p>χ − μ:<br><tt><small>
+   [-1/2, 2/3, -37/96, 1/360, 81/512, -96199/604800, 5406467/38707200, -7944359/67737600]<br>
+   [-1/48, -1/15, 437/1440, -46/105, 1118711/3870720, -51841/1209600, -24749483/348364800]<br>
+   [-17/480, 37/840, 209/4480, -5569/90720, -9261899/58060800, 6457463/17740800]<br>
+   [-4397/161280, 11/504, 830251/7257600, -466511/2494800, -324154477/7664025600]<br>
+   [-4583/161280, 108847/3991680, 8005831/63866880, -22894433/124540416]<br>
+   [-20648693/638668800, 16363163/518918400, 2204645983/12915302400]<br>
+   [-219941297/5535129600, 497323811/12454041600]<br>
+   [-191773887257/3719607091200]<br>
+</small></tt>
+<p>μ − χ:<br><tt><small>
+   [1/2, -2/3, 5/16, 41/180, -127/288, 7891/37800, 72161/387072, -18975107/50803200]<br>
+   [13/48, -3/5, 557/1440, 281/630, -1983433/1935360, 13769/28800, 148003883/174182400]<br>
+   [61/240, -103/140, 15061/26880, 167603/181440, -67102379/29030400, 79682431/79833600]<br>
+   [49561/161280, -179/168, 6601661/7257600, 97445/49896, -40176129013/7664025600]<br>
+   [34729/80640, -3418889/1995840, 14644087/9123840, 2605413599/622702080]<br>
+   [212378941/319334400, -30705481/10378368, 175214326799/58118860800]<br>
+   [1522256789/1383782400, -16759934899/3113510400]<br>
+   [1424729850961/743921418240]<br>
+</small></tt>
+<p>ξ − φ:<br><tt><small>
+   [-4/3, -4/45, 88/315, 538/4725, 20824/467775, -44732/2837835, -86728/16372125, -88002076/13956067125]<br>
+   [34/45, 8/105, -2482/14175, -37192/467775, -12467764/212837625, -895712/147349125, -2641983469/488462349375]<br>
+   [-1532/2835, -898/14175, 54968/467775, 100320856/1915538625, 240616/4209975, 8457703444/488462349375]<br>
+   [6007/14175, 24496/467775, -5884124/70945875, -4832848/147349125, -4910552477/97692469875]<br>
+   [-23356/66825, -839792/19348875, 816824/13395375, 9393713176/488462349375]<br>
+   [570284222/1915538625, 1980656/54729675, -4532926649/97692469875]<br>
+   [-496894276/1915538625, -14848113968/488462349375]<br>
+   [224557742191/976924698750]<br>
+</small></tt>
+<p>φ − ξ:<br><tt><small>
+   [4/3, 4/45, -16/35, -2582/14175, 60136/467775, 28112932/212837625, 22947844/1915538625, -1683291094/37574026875]<br>
+   [46/45, 152/945, -11966/14175, -21016/51975, 251310128/638512875, 1228352/3007125, -14351220203/488462349375]<br>
+   [3044/2835, 3802/14175, -94388/66825, -8797648/10945935, 138128272/147349125, 505559334506/488462349375]<br>
+   [6059/4725, 41072/93555, -1472637812/638512875, -45079184/29469825, 973080708361/488462349375]<br>
+   [768272/467775, 455935736/638512875, -550000184/147349125, -1385645336626/488462349375]<br>
+   [4210684958/1915538625, 443810768/383107725, -2939205114427/488462349375]<br>
+   [387227992/127702575, 101885255158/54273594375]<br>
+   [1392441148867/325641566250]<br>
+</small></tt>
+<p>ξ − β:<br><tt><small>
+   [-1/3, -4/45, 32/315, 34/675, 2476/467775, -70496/8513505, -18484/4343625, 29232878/97692469875]<br>
+   [-7/90, -4/315, 74/2025, 3992/467775, 53836/212837625, -4160804/1915538625, -324943819/488462349375]<br>
+   [-83/2835, 2/14175, 7052/467775, -661844/1915538625, 237052/383107725, -168643106/488462349375]<br>
+   [-797/56700, 934/467775, 1425778/212837625, -2915326/1915538625, 113042383/97692469875]<br>
+   [-3673/467775, 390088/212837625, 6064888/1915538625, -558526274/488462349375]<br>
+   [-18623681/3831077250, 41288/29469825, 155665021/97692469875]<br>
+   [-6205669/1915538625, 504234982/488462349375]<br>
+   [-8913001661/3907698795000]<br>
+</small></tt>
+<p>β − ξ:<br><tt><small>
+   [1/3, 4/45, -46/315, -1082/14175, 11824/467775, 7947332/212837625, 9708931/1915538625, -5946082372/488462349375]<br>
+   [17/90, 68/945, -338/2025, -16672/155925, 39946703/638512875, 164328266/1915538625, 190673521/69780335625]<br>
+   [461/2835, 1102/14175, -101069/467775, -255454/1563705, 236067184/1915538625, 86402898356/488462349375]<br>
+   [3161/18900, 1786/18711, -189032762/638512875, -98401826/383107725, 110123070361/488462349375]<br>
+   [88868/467775, 80274086/638512875, -802887278/1915538625, -200020620676/488462349375]<br>
+   [880980241/3831077250, 66263486/383107725, -296107325077/488462349375]<br>
+   [37151038/127702575, 4433064236/18091198125]<br>
+   [495248998393/1302566265000]<br>
+</small></tt>
+<p>ξ − θ:<br><tt><small>
+   [2/3, -4/45, 62/105, 778/4725, -193082/467775, -4286228/42567525, 53702182/212837625, 182466964/8881133625]<br>
+   [4/45, -32/315, 12338/14175, 92696/467775, -61623938/70945875, -32500616/273648375, 367082779691/488462349375]<br>
+   [-524/2835, -1618/14175, 612536/467775, 427003576/1915538625, -663111728/383107725, -42668482796/488462349375]<br>
+   [-5933/14175, -8324/66825, 427770788/212837625, 421877252/1915538625, -327791986997/97692469875]<br>
+   [-320044/467775, -9153184/70945875, 6024982024/1915538625, 74612072536/488462349375]<br>
+   [-1978771378/1915538625, -46140784/383107725, 489898512247/97692469875]<br>
+   [-2926201612/1915538625, -42056042768/488462349375]<br>
+   [-2209250801969/976924698750]<br>
+</small></tt>
+<p>θ − ξ:<br><tt><small>
+   [-2/3, 4/45, -158/315, -2102/14175, 109042/467775, 216932/2627625, -189115382/1915538625, -230886326/6343666875]<br>
+   [16/45, -16/945, 934/14175, -7256/155925, 117952358/638512875, 288456008/1915538625, -11696145869/69780335625]<br>
+   [-232/2835, 922/14175, -25286/66825, -7391576/54729675, 478700902/1915538625, 91546732346/488462349375]<br>
+   [719/4725, 268/18711, -67048172/638512875, -67330724/383107725, 218929662961/488462349375]<br>
+   [14354/467775, 46774256/638512875, -117954842/273648375, -129039188386/488462349375]<br>
+   [253129538/1915538625, 2114368/34827975, -178084928947/488462349375]<br>
+   [13805944/127702575, 6489189398/54273594375]<br>
+   [59983985827/325641566250]<br>
+</small></tt>
+<p>ξ − μ:<br><tt><small>
+   [1/6, -4/45, -817/10080, 1297/18900, 7764059/239500800, -9292991/302702400, -25359310709/1743565824000, 39534358147/2858202547200]<br>
+   [49/720, -2/35, -29609/453600, 35474/467775, 36019108271/871782912000, -14814966289/245188944000, -13216941177599/571640509440000]<br>
+   [4463/90720, -2917/56700, -4306823/59875200, 3026004511/30648618000, 99871724539/1569209241600, -27782109847927/250092722880000]<br>
+   [331799/7257600, -102293/1871100, -368661577/4036032000, 2123926699/15324309000, 168979300892599/1600593426432000]<br>
+   [11744233/239500800, -875457073/13621608000, -493031379277/3923023104000, 1959350112697/9618950880000]<br>
+   [453002260127/7846046208000, -793693009/9807557760, -145659994071373/800296713216000]<br>
+   [103558761539/1426553856000, -53583096419057/500185445760000]<br>
+   [12272105438887727/128047474114560000]<br>
+</small></tt>
+<p>μ − ξ:<br><tt><small>
+   [-1/6, 4/45, 121/1680, -1609/28350, -384229/14968800, 12674323/851350500, 7183403063/560431872000, -375027460897/125046361440000]<br>
+   [-29/720, 26/945, 16463/453600, -431/17325, -31621753811/1307674368000, 1117820213/122594472000, 30410873385097/2000741783040000]<br>
+   [-1003/45360, 449/28350, 3746047/119750400, -32844781/1751349600, -116359346641/3923023104000, 151567502183/17863765920000]<br>
+   [-40457/2419200, 629/53460, 10650637121/326918592000, -13060303/766215450, -317251099510901/8002967132160000]<br>
+   [-1800439/119750400, 205072597/20432412000, 146875240637/3923023104000, -2105440822861/125046361440000]<br>
+   [-59109051671/3923023104000, 228253559/24518894400, 91496147778023/2000741783040000]<br>
+   [-4255034947/261534873600, 126430355893/13894040160000]<br>
+   [-791820407649841/42682491371520000]<br>
+</small></tt>
+<p>ξ − χ:<br><tt><small>
+   [2/3, -34/45, 46/315, 2458/4725, -55222/93555, 2706758/42567525, 16676974/30405375, -64724382148/97692469875]<br>
+   [19/45, -256/315, 3413/14175, 516944/467775, -340492279/212837625, 158999572/1915538625, 85904355287/37574026875]<br>
+   [248/567, -15958/14175, 206834/467775, 4430783356/1915538625, -7597644214/1915538625, 2986003168/37574026875]<br>
+   [16049/28350, -832976/467775, 62016436/70945875, 851209552/174139875, -375566203/39037950]<br>
+   [15602/18711, -651151712/212837625, 3475643362/1915538625, 5106181018156/488462349375]<br>
+   [2561772812/1915538625, -10656173804/1915538625, 34581190223/8881133625]<br>
+   [873037408/383107725, -5150169424688/488462349375]<br>
+   [7939103697617/1953849397500]<br>
+</small></tt>
+<p>χ − ξ:<br><tt><small>
+   [-2/3, 34/45, -88/315, -2312/14175, 27128/93555, -55271278/212837625, 308365186/1915538625, -17451293242/488462349375]<br>
+   [1/45, -184/945, 6079/14175, -65864/155925, 106691108/638512875, 149984636/1915538625, -101520127208/488462349375]<br>
+   [-106/2835, 772/14175, -14246/467775, 5921152/54729675, -99534832/383107725, 10010741462/37574026875]<br>
+   [-167/9450, -5312/467775, 75594328/638512875, -35573728/273648375, 1615002539/75148053750]<br>
+   [-248/13365, 2837636/638512875, 130601488/1915538625, -3358119706/488462349375]<br>
+   [-34761247/1915538625, -3196/3553875, 46771947158/488462349375]<br>
+   [-2530364/127702575, -18696014/18091198125]<br>
+   [-14744861191/651283132500]<br>
+</small></tt>
+
+<center>
+Back to \ref geocentric.  Forward to \ref highprec.  Up to
 \ref contents.
 
 </center>
@@ -5505,7 +6323,7 @@ Back to \ref transversemercator.  Forward to \ref highprec.  Up to
 \page highprec Support for high precision arithmetic
 
 <center>
-Back to \ref geocentric.  Forward to \ref changes.  Up to \ref contents.
+Back to \ref auxlat.  Forward to \ref changes.  Up to \ref contents.
 </center>
 
 One of the goals with the algorithms in GeographicLib is to deliver
@@ -5525,9 +6343,11 @@ Here's what you should know:
    or later) and the quadmath library (which requires the use of g++).
  - Configuring with <code>-D GEOGRAPHICLIB_PRECISION=5</code> gives
    arbitrary precision via mpfr::mpreal; this requires
-   <a href="http://www.mpfr.org"> MPFR</a> (version 3.0 or later) and
+   <a href="http://www.mpfr.org"> MPFR</a> (version 3.0 or later),
    <a href="http://www.holoborodko.com/pavel/mpfr"> MPFR C++</a>
-   (version 3.5.9 or later).
+   (version 3.5.9 or later), and a compiler which supports the explicit
+   cast operator (e.g., g++ 4.5 or later, Visual Studio 12 2013 or
+   later).
  - MPFR, MPFR C++, and Boost all come with their own licenses.  Be sure
    to respect these.
  - The indicated precision is used for <b>all</b> floating point
@@ -5761,7 +6581,7 @@ The following steps needed to be taken
        separate file.
 
 <center>
-Back to \ref geocentric.  Forward to \ref changes.  Up to \ref contents.
+Back to \ref auxlat.  Forward to \ref changes.  Up to \ref contents.
 
 </center>
 **********************************************************************/
@@ -5790,6 +6610,58 @@ been migrated to the archive subdirectory).  All the releases are
 available as tags “r<i>m.nn</i>” in the the "release" branch
 of the git repository for GeographicLib.
 
+ - <a href="http://geographiclib.sf.net/1.39">Version 1.39</a>
+   (released 2014-11-11)
+   - GeographicLib usually normalizes longitudes to the range
+     [−180°, 180°).  However, when solving the direct
+     geodesic and rhumb line problems, it is sometimes necessary to know
+     how many lines the line encircled the earth by returning the
+     longitude "unwrapped".  So the following changes have been made:
+     - add a LONG_NOWRAP flag to \e mask enums for the \e outmask
+       arguments for Geodesic, GeodesicLine, Rhumb, and RhumbLine;
+     - similar changes have been made to the Python, Javascript, and
+       Java implementations of the geodesic routines;
+     - for the C, Fortran, and Matlab implementations the \e arcmode
+       argument to the routines was generalized to allow a combination
+       of ARCMODE and LONG_NOWRAP bits;
+     - the Maxima version now returns the longitude unwrapped.
+     .
+     These changes were necessary to fix the PolygonAreaT::AddEdge (see
+     the next item).
+   - Changes in area calculations:
+     - fix BUG in PolygonAreaT::AddEdge (also in C, Java, Javascript,
+       and Python implementations) which sometimes causes the wrong area
+       to be returned if the edge spanned more than 180°;
+     - add area calculation to the Rhumb and RhumbLine classes and the
+       <a href="RhumbSolve.1.html">RhumbSolve</a> utility (see \ref
+       rhumbarea);
+     - add PolygonAreaRhumb typedef for PolygonAreaT<Rhumb>;
+     - add -R option to <a href="Planimeter.1.html">Planimeter</a> to use
+       PolygonAreaRhumb (and -G option for the default geodesic polygon);
+     - fix BLUNDER in area calculation in Matlab routine geodreckon;
+     - add area calculation to Matlab/Octave routines for great ellipses
+       (see \ref gearea).
+   - Fix bad BUG in Geohash::Reverse; this was introduced in version
+     1.37 and affected all platforms where unsigned longs are 32-bits.
+     Thanks to Christian Csar for reporting and diagnosing this.
+   - Binary installers for Windows are now built with Visual Studio 11
+     2012 (instead of Visual Studio 10 2010).  Compiled Matlab support
+     still with version 2013a (64-bit).
+   - Update GeographicLib.pro for builds with qmake to include all the
+     source files.
+   - Cmake updates:
+     - include cross-compiling checks in cmake config file;
+     - improve the way unsuitable versions are reported;
+     - include_directories (${GeographicLib_INCLUDE_DIRS}) is no longer
+       necessary with cmake 2.8.11 or later.
+   - legacy/Fortran now includes drop-in replacements for the geodesic
+     utilities from the NGS.
+   - geographiclib-get-{geoids,gravity,magnetic} with no arguments now
+     print the usage instead of loading the minimal sets.
+   - Utility::date(const std::string&, int&, int&, int&) and hence the
+     <a href="MagneticField.1.html">MagneticField</a> utility accepts
+     the string "now" as a legal time (meaning today).
+
  - <a href="http://geographiclib.sf.net/1.38">Version 1.38</a>
    (released 2014-10-02)
    - On MacOSX, the installed package is relocatable (for cmake version
@@ -6207,7 +7079,7 @@ of the git repository for GeographicLib.
    - Slight improvement in Geodesic::Inverse for very
      short lines.
    - Fix argument checking tests in MGRS::Forward.
-   - Add --comment-delimiter and --line-separator options to the \ref
+   - 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.
@@ -6399,7 +7271,7 @@ of the git repository for GeographicLib.
    - Provide cmake support:
      - build binary installer for Windows;
      - include regression tests;
-     - add --input-string, --input-file, --output-file options to the
+     - add \--input-string, \--input-file, \--output-file options to the
        \ref utilities to support tests.
    - Rename utility EquidistantTest as <a href="GeodesicProj.1.html">
      GeodesicProj</a> and TransverseMercatorTest as
@@ -6416,7 +7288,7 @@ of the git repository for GeographicLib.
    - Optionally return rotation matrix from Geocentric and
      LocalCartesian.
    - For the \ref utilities, supply man pages, -h prints the synopsis,
-     --help prints the man page, --version prints the version.
+     \--help prints the man page, \--version prints the version.
    - Use accurate summation in <a href="Planimeter.1.html">Planimeter</a>.
    - Add 64-bit targets for Visual Studio 2010.
    - Use templates for defining math functions and some constants.
@@ -6425,7 +7297,7 @@ of the git repository for GeographicLib.
        Geoid::DefaultGeoidName;
      - <a href="GeoidEval.1.html">GeoidEval</a> uses environment variable
        GEOGRAPHICLIB_GEOID_NAME as the default geoid;
-     - Add --msltohae and --haetomsl as
+     - Add \--msltohae and \--haetomsl as
        <a href="GeoidEval.1.html">GeoidEval</a> options (and don't
        document the single hyphen versions).
    - Remove documentation that duplicates papers on transverse Mercator
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 34bd403..167ac69 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -94,6 +94,7 @@ MANPAGES = \
 	../man/Gravity.1.html \
 	../man/MagneticField.1.html \
 	../man/Planimeter.1.html \
+	../man/RhumbSolve.1.html \
 	../man/TransverseMercatorProj.1.html
 
 LEGACYFILES = \
@@ -106,6 +107,9 @@ LEGACYFILES = \
 	$(top_srcdir)/legacy/Fortran/geodesic.inc \
 	$(top_srcdir)/legacy/Fortran/geoddirect.for \
 	$(top_srcdir)/legacy/Fortran/geodinverse.for \
+	$(top_srcdir)/legacy/Fortran/ngscommon.for \
+	$(top_srcdir)/legacy/Fortran/ngsforward.for \
+	$(top_srcdir)/legacy/Fortran/ngsinverse.for \
 	$(top_srcdir)/legacy/Fortran/planimeter.for
 
 doc: html/index.html
diff --git a/doc/Makefile.in b/doc/Makefile.in
index 5c83147..934da26 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -341,6 +341,7 @@ MANPAGES = \
 	../man/Gravity.1.html \
 	../man/MagneticField.1.html \
 	../man/Planimeter.1.html \
+	../man/RhumbSolve.1.html \
 	../man/TransverseMercatorProj.1.html
 
 LEGACYFILES = \
@@ -353,6 +354,9 @@ LEGACYFILES = \
 	$(top_srcdir)/legacy/Fortran/geodesic.inc \
 	$(top_srcdir)/legacy/Fortran/geoddirect.for \
 	$(top_srcdir)/legacy/Fortran/geodinverse.for \
+	$(top_srcdir)/legacy/Fortran/ngscommon.for \
+	$(top_srcdir)/legacy/Fortran/ngsforward.for \
+	$(top_srcdir)/legacy/Fortran/ngsinverse.for \
 	$(top_srcdir)/legacy/Fortran/planimeter.for
 
 all: all-am
diff --git a/doc/NETGeographicLib.dox b/doc/NETGeographicLib.dox
index d0fe26d..f616374 100644
--- a/doc/NETGeographicLib.dox
+++ b/doc/NETGeographicLib.dox
@@ -11,8 +11,8 @@
 /**
 \mainpage NETGeographicLib library
 \author Scott Heiman (mrmtdew2 at outlook.com)
-\version 1.37
-\date 2014-08-08
+\version 1.39
+\date 2014-11-11
 
 \section abstract Abstract
 
@@ -26,14 +26,14 @@ to the GeographicLib classes.  GeographicLib and NETGeographicLib is an
 integrated product.
 
 The NETGeographic project in the GeographicLib-vc10.sln file located in
-\<install folder\>/GeographicLib-1.37/windows will create the NETGeographicLib
+\<install folder\>/GeographicLib-1.39/windows will create the NETGeographicLib
 DLL.  The source code for NETGeographicLib is located in
-\<install folder\>/GeographicLib-1.37/dotnet/NETGeographicLib.  NETGeographicLib
+\<install folder\>/GeographicLib-1.39/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
-\<install folder\>/GeographicLib-1.37/dotnet/examples.
+\<install folder\>/GeographicLib-1.39/dotnet/examples.
 
 \section differences Differences between NETGeographicLib and GeographicLib
 
@@ -135,7 +135,7 @@ to any Visual Basic source that uses NETGeographicLib classes.
 
 A C# sample application is provided that demonstrates NETGeographicLib classes.
 The source code for the sample application is located in
-\<install folder\>/GeographicLib-1.37/dotnet/Projections.  The sample
+\<install folder\>/GeographicLib-1.39/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.
 
diff --git a/doc/doxyfile-for.in b/doc/doxyfile-for.in
index 79ff746..d2490a2 100644
--- a/doc/doxyfile-for.in
+++ b/doc/doxyfile-for.in
@@ -666,8 +666,7 @@ INPUT_ENCODING         = UTF-8
 # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
 # *.f90 *.f *.for *.vhd *.vhdl
 
-FILE_PATTERNS          = *.for \
-                         *.inc
+FILE_PATTERNS          = geod*.for planimeter.for geodesic.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.
diff --git a/doc/geodesic-c.dox b/doc/geodesic-c.dox
index d07fb61..3a62436 100644
--- a/doc/geodesic-c.dox
+++ b/doc/geodesic-c.dox
@@ -11,7 +11,7 @@
 /**
 \mainpage Geodesic routines implemented in C
 \author Charles F. F. Karney (charles at karney.com)
-\version 1.32
+\version 1.39
 
 \section abstract Abstract
 
@@ -27,13 +27,13 @@ about any C compiler.
 \section download Downloading the source
 
 The C library is part of %GeographicLib which available for download at
-- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.32.tar.gz">
-  GeographicLib-1.32.tar.gz</a>
-- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.32.zip">
-  GeographicLib-1.32.zip</a>
+- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.39.tar.gz">
+  GeographicLib-1.39.tar.gz</a>
+- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.39.zip">
+  GeographicLib-1.39.zip</a>
 .
 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 source, the C library can be found in GeographicLib-1.39/legacy/C.
 The library consists of two files geodesic.c and geodesic.h.
 
 The library is also included as part of
diff --git a/doc/geodesic-for.dox b/doc/geodesic-for.dox
index 1ebc598..ce03d24 100644
--- a/doc/geodesic-for.dox
+++ b/doc/geodesic-for.dox
@@ -11,7 +11,7 @@
 /**
 \mainpage Geodesic routines implemented in Fortran
 \author Charles F. F. Karney (charles at karney.com)
-\version 1.31
+\version 1.39
 
 \section abstract Abstract
 
@@ -25,14 +25,14 @@ 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
-- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.31.tar.gz">
-  GeographicLib-1.31.tar.gz</a>
-- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.31.zip">
-  GeographicLib-1.31.zip</a>
+- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.39.tar.gz">
+  GeographicLib-1.39.tar.gz</a>
+- <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.39.zip">
+  GeographicLib-1.39.zip</a>
 .
 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
+GeographicLib-1.39/legacy/Fortran.  The library consists of the file
 geodesic.for.
 
 \section doc Library documentation
@@ -63,6 +63,28 @@ cmake ..
 make
 echo 30 0 29.5 179.5 | ./geodinverse \endverbatim
 
+Finally, the two programs
+ - ngsforward
+ - ngsinverse
+ .
+which are also built with cmake, provide drop-in replacements for
+replacements for the NGS tools FORWARD and INVERSE available from
+http://www.ngs.noaa.gov/PC_PROD/Inv_Fwd/.
+These cure two problems of the Vincenty algorithms used by NGS:
+ - the accuracy is "only" 0.1 mm;
+ - the inverse program sometimes goes into an infinite loop.
+ .
+The corresponding source files
+ - ngsforward.for
+ - ngsinverse.for
+ - ngscommon.for
+ .
+are derived from the NGS source files
+ - forward.for, version 2.0, dated 2002-10-28
+ - inverse.for, version 3.0, dated 2012-11-27
+ .
+and are therefore in the public domain.
+
 \section library Using the library
 
 - Optionall put @verbatim
diff --git a/doc/scripts/GeographicLib/DMS.js b/doc/scripts/GeographicLib/DMS.js
index 0be8dfa..be4833a 100644
--- a/doc/scripts/GeographicLib/DMS.js
+++ b/doc/scripts/GeographicLib/DMS.js
@@ -17,11 +17,11 @@ 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";
@@ -69,8 +69,8 @@ GeographicLib.DMS = {};
       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() ==
+          if (ind1 !== d.NONE) {
+            if (dmsa.charAt(beg - 1).toUpperCase() ===
                 dmsa.charAt(end - 1).toUpperCase())
               errormsg = "Repeated hemisphere indicators " +
               dmsa.charAt(beg - 1) + " in " +
@@ -92,7 +92,7 @@ GeographicLib.DMS = {};
           ++beg;
         }
       }
-      if (end == beg) {
+      if (end === beg) {
         errormsg = "Empty or incomplete DMS string " + dmsa;
         break;
       }
@@ -109,40 +109,40 @@ GeographicLib.DMS = {};
         var x = dmsa.charAt(p++);
         if ((k = d.lookup(d.digits_, x)) >= 0) {
           ++ncurrent;
-          if (digcount > 0)
+          if (digcount > 0) {
             ++digcount;         // Count of decimal digits
-          else {
+          } else {
             icurrent = 10 * icurrent + k;
             ++intcount;
           }
-        } else if (x == '.') {
+        } else if (x === '.') {
           if (pointseen) {
-            errormsg = "Multiple decimal points in "
-              + dmsa.substr(beg, end - beg);
+            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) {
+            if (p === end) {
               errormsg = "Illegal for : to appear at the end of " +
                 dmsa.substr(beg, end - beg);
               break;
             }
             k = npiece;
           }
-          if (k == npiece - 1) {
+          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);
+            errormsg = d.components_[k] + " component follows " +
+              d.components_[npiece - 1] + " component in " +
+              dmsa.substr(beg, end - beg);
             break;
           }
-          if (ncurrent == 0) {
+          if (ncurrent === 0) {
             errormsg = "Missing numbers in " + d.components_[k] +
               " component of " + dmsa.substr(beg, end - beg);
             break;
@@ -160,12 +160,12 @@ GeographicLib.DMS = {};
             ncurrent = digcount = intcount = 0;
           }
         } else if (d.lookup(d.signs_, x) >= 0) {
-          errormsg = "Internal sign in DMS string "
-            + dmsa.substr(beg, end - beg);
+          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);
+          errormsg = "Illegal character " + x + " in DMS string " +
+            dmsa.substr(beg, end - beg);
           break;
         }
       }
@@ -173,13 +173,13 @@ GeographicLib.DMS = {};
         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);
+          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);
+        if (ncurrent === 0) {
+          errormsg = "Missing numbers in trailing component of " +
+            dmsa.substr(beg, end - beg);
           break;
         }
         if (digcount > 1) {
@@ -190,9 +190,9 @@ GeographicLib.DMS = {};
         ipieces[npiece] = icurrent;
         fpieces[npiece] = icurrent + fcurrent;
       }
-      if (pointseen && digcount == 0) {
-        errormsg = "Decimal point in non-terminal component of "
-          + dmsa.substr(beg, end - beg);
+      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.
@@ -211,31 +211,31 @@ GeographicLib.DMS = {};
       return vals;
     } while (false);
     vals.val = d.NumMatch(dmsa);
-    if (vals.val == 0)
+    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 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")
+    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")
+    else if (t === "INF" || t === "1.#INF")
       return sign * Number.POSITIVE_INFINITY;
     return 0;
-  }
+  };
 
   // return lat, lon
   d.DecodeLatLon = function(stra, strb, swaplatlong) {
@@ -245,19 +245,19 @@ GeographicLib.DMS = {};
     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) {
+    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)
+    } else if (ia === d.NONE)
       ia = d.LATITUDE + d.LONGITUDE - ib;
-    else if (ib == d.NONE)
+    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 (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)
@@ -266,28 +266,28 @@ GeographicLib.DMS = {};
     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");
+    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 (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
@@ -305,7 +305,7 @@ GeographicLib.DMS = {};
       scale *= 60;
     for (i = 0; i < prec; ++i)
       scale *= 10;
-    if (ind == d.AZIMUTH)
+    if (ind === d.AZIMUTH)
       angle -= Math.floor(angle/360) * 360;
     var sign = angle < 0 ? -1 : 1;
     angle *= sign;
@@ -329,18 +329,18 @@ GeographicLib.DMS = {};
     }
     pieces[0] += idegree;
     var s = new String("");
-    if (ind == d.NONE && sign < 0)
+    if (ind === d.NONE && sign < 0)
       s += '-';
     switch (trailing) {
     case d.DEGREE:
       s += d.zerofill(pieces[0].toFixed(prec),
-                      ind == d.NONE ? 0 :
+                      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)) +
+                      ind === d.NONE ? 0 : 1 + Math.min(ind, 2)) +
         d.dmsindicatorsu_.charAt(0);
       switch (trailing) {
       case d.MINUTE:
@@ -356,10 +356,10 @@ GeographicLib.DMS = {};
         break;
       }
     }
-    if (ind != d.NONE && ind != d.AZIMUTH)
-      s += d.hemispheres_.charAt((ind == d.LATITUDE ? 0 : 2) +
+    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/doc/scripts/GeographicLib/Geodesic.js b/doc/scripts/GeographicLib/Geodesic.js
index cf05912..3c34841 100644
--- a/doc/scripts/GeographicLib/Geodesic.js
+++ b/doc/scripts/GeographicLib/Geodesic.js
@@ -12,7 +12,7 @@
  *    http://dx.doi.org/10.1007/s00190-012-0578-z
  *    Addenda: http://geographiclib.sf.net/geod-addenda.html
  *
- * Copyright (c) Charles Karney (2011-2013) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -54,7 +54,9 @@ GeographicLib.GeodesicLine = {};
   g.CAP_C3   = 1<<3;
   g.CAP_C4   = 1<<4;
   g.CAP_ALL  = 0x1F;
+  g.CAP_MASK = g.CAP_ALL;
   g.OUT_ALL  = 0x7F80;
+  g.OUT_MASK = 0xFF80;          // Includes LONG_NOWRAP
   g.NONE          = 0;
   g.LATITUDE      = 1<<7  | g.CAP_NONE;
   g.LONGITUDE     = 1<<8  | g.CAP_C3;
@@ -64,6 +66,7 @@ GeographicLib.GeodesicLine = {};
   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.LONG_NOWRAP   = 1<<15;
   g.ALL           = g.OUT_ALL| g.CAP_ALL;
 
   g.SinCosSeries = function(sinp, sinx, cosx, c, n) {
@@ -83,10 +86,9 @@ GeographicLib.GeodesicLine = {};
       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)
-  }
+    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
@@ -99,7 +101,7 @@ GeographicLib.GeodesicLine = {};
     // 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.
@@ -108,7 +110,7 @@ GeographicLib.GeodesicLine = {};
     p = m.sq(x),
     q = m.sq(y),
     r = (p + q - 1) / 6;
-    if ( !(q == 0 && r <= 0) ) {
+    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.
@@ -125,12 +127,12 @@ GeographicLib.GeodesicLine = {};
         // 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
+        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);
+        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));
@@ -153,14 +155,14 @@ GeographicLib.GeodesicLine = {};
       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
@@ -177,7 +179,7 @@ GeographicLib.GeodesicLine = {};
     c[5] = -7*d/1280;
     d *= eps;
     c[6] = -7*d/2048;
-  }
+  };
 
   g.C1pf = function(eps, c) {
     var
@@ -194,14 +196,14 @@ GeographicLib.GeodesicLine = {};
     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
@@ -218,7 +220,7 @@ GeographicLib.GeodesicLine = {};
     c[5] = 63*d/1280;
     d *= eps;
     c[6] = 77*d/2048;
-  }
+  };
 
   g.Geodesic = function(a, f) {
     this._a = a;
@@ -230,7 +232,7 @@ GeographicLib.GeodesicLine = {};
     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 ? 1 :
                  (this._e2 > 0 ? m.atanh(Math.sqrt(this._e2)) :
                   Math.atan(Math.sqrt(-this._e2))) /
                  Math.sqrt(Math.abs(this._e2))))/2;
@@ -256,7 +258,7 @@ GeographicLib.GeodesicLine = {};
     this.A3coeff();
     this.C3coeff();
     this.C4coeff();
-  }
+  };
 
   g.Geodesic.prototype.A3coeff = function() {
     var _n = this._n;
@@ -266,7 +268,7 @@ GeographicLib.GeodesicLine = {};
     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;
@@ -285,7 +287,7 @@ GeographicLib.GeodesicLine = {};
     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;
@@ -310,7 +312,7 @@ GeographicLib.GeodesicLine = {};
     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
@@ -318,12 +320,13 @@ GeographicLib.GeodesicLine = {};
     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 j, k;
+    for (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];
@@ -331,16 +334,17 @@ GeographicLib.GeodesicLine = {};
     }
 
     var mult = 1;
-    for (var k = 1; k < g.nC3_; ) {
+    for (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 j, k;
+    for (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];
@@ -348,11 +352,11 @@ GeographicLib.GeodesicLine = {};
     }
 
     var mult = 1;
-    for (var k = 1; k < g.nC4_; ) {
+    for (k = 1; k < g.nC4_; ) {
       mult *= eps;
       c[k++] *= mult;
     }
-  }
+  };
 
   // return s12b, m12b, m0, M12, M21
   g.Geodesic.prototype.Lengths = function(eps, sig12,
@@ -378,8 +382,8 @@ GeographicLib.GeodesicLine = {};
     // 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;
+    vals.m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
+      csig1 * csig2 * J12;
     // Missing a factor of _b
     vals.s12b = (1 + A1m1) * sig12 + AB1;
     if (scalep) {
@@ -389,7 +393,7 @@ GeographicLib.GeodesicLine = {};
       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,
@@ -430,7 +434,7 @@ GeographicLib.GeodesicLine = {};
       sbet12 + cbet2 * sbet1 * m.sq(somg12) / (1 + comg12) :
       sbet12a - cbet2 * sbet1 * m.sq(somg12) / (1 - comg12);
 
-    var
+    var t,
     ssig12 = m.hypot(vals.salp1, vals.calp1),
     csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12;
 
@@ -440,13 +444,13 @@ GeographicLib.GeodesicLine = {};
       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;
+      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
+      0; // 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.
@@ -457,12 +461,10 @@ GeographicLib.GeodesicLine = {};
       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;
-        }
+        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;
@@ -543,12 +545,12 @@ GeographicLib.GeodesicLine = {};
     }
     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;
+      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,
@@ -556,12 +558,12 @@ GeographicLib.GeodesicLine = {};
                                            salp1, calp1, diffp,
                                            C1a, C2a, C3a) {
     var vals = {};
-    if (sbet1 == 0 && calp1 == 0)
+    if (sbet1 === 0 && calp1 === 0)
       // Break degeneracy of equatorial line.  This case has already been
       // handled.
       calp1 = -g.tiny_;
 
-    var
+    var t,
     // sin(alp1) * cos(bet1) = sin(alp0)
     salp0 = salp1 * cbet1,
     calp0 = m.hypot(calp1, salp1 * sbet1); // calp0 > 0
@@ -572,29 +574,29 @@ GeographicLib.GeodesicLine = {};
     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;
+    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;
+    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 ?
+    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);
+                                       (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;
+    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]
@@ -616,7 +618,7 @@ GeographicLib.GeodesicLine = {};
     vals.lam12 = omg12 + vals.domg12;
 
     if (diffp) {
-      if (vals.calp2 == 0)
+      if (vals.calp2 === 0)
         vals.dlam12 = - 2 * this._f1 * dn1 / sbet1;
       else {
         var nvals = this.Lengths(vals.eps, vals.sig12,
@@ -628,12 +630,12 @@ GeographicLib.GeodesicLine = {};
       }
     }
     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;
+    outmask &= g.OUT_MASK;
     // 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.
@@ -647,10 +649,10 @@ GeographicLib.GeodesicLine = {};
     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;
+    var t, swapp = Math.abs(lat1) >= Math.abs(lat2) ? 1 : -1;
     if (swapp < 0) {
       lonsign *= -1;
-      var t = lat1;
+      t = lat1;
       lat1 = lat2;
       lat2 = t;
       // swap(lat1, lat2);
@@ -676,16 +678,16 @@ GeographicLib.GeodesicLine = {};
     phi = lat1 * m.degree;
     // Ensure cbet1 = +epsilon at poles
     sbet1 = this._f1 * Math.sin(phi);
-    cbet1 = lat1 == -90 ? g.tiny_ : Math.cos(phi);
+    cbet1 = lat1 === -90 ? g.tiny_ : Math.cos(phi);
     // SinCosNorm(sbet1, cbet1);
-    var t = m.hypot(sbet1, cbet1); sbet1 /= t; cbet1 /= t;
+    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);
+    cbet2 = Math.abs(lat2) === 90 ? g.tiny_ : Math.cos(phi);
     // SinCosNorm(sbet2, cbet2);
-    var t = m.hypot(sbet2, cbet2); sbet2 /= t; cbet2 /= t;
+    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
@@ -696,10 +698,10 @@ GeographicLib.GeodesicLine = {};
     // which failed with Visual Studio 10 (Release and Debug)
 
     if (cbet1 < -sbet1) {
-      if (cbet2 == cbet1)
+      if (cbet2 === cbet1)
         sbet2 = sbet2 < 0 ? sbet1 : -sbet1;
     } else {
-      if (Math.abs(sbet2) == -sbet1)
+      if (Math.abs(sbet2) === -sbet1)
         cbet2 = cbet1;
     }
 
@@ -709,7 +711,7 @@ GeographicLib.GeodesicLine = {};
 
     var
     lam12 = lon12 * m.degree,
-    slam12 = lon12 == 180 ? 0 : Math.sin(lam12),
+    slam12 = lon12 === 180 ? 0 : Math.sin(lam12),
     clam12 = Math.cos(lam12);   // lon12 == 90 isn't interesting
 
     var sig12, calp1, salp1, calp2, salp2;
@@ -719,8 +721,9 @@ GeographicLib.GeodesicLine = {};
     C2a = new Array(g.nC2_ + 1),
     C3a = new Array(g.nC3_);
 
-    var meridian = lat1 == -90 || slam12 == 0;
+    var meridian = lat1 === -90 || slam12 === 0, nvals;
 
+    var ssig1, csig1, ssig2, csig2, eps;
     if (meridian) {
 
       // Endpoints are on a single full meridian, so the geodesic might
@@ -729,26 +732,23 @@ GeographicLib.GeodesicLine = {};
       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;
+      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;
-        }
+      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
@@ -768,7 +768,7 @@ GeographicLib.GeodesicLine = {};
 
     var omg12;
     if (!meridian &&
-        sbet1 == 0 &&           // and sbet2 == 0
+        sbet1 === 0 &&           // and sbet2 == 0
         // Mimic the way Lambda12 works with calp1 = 0
         (this._f <= 0 || lam12 <= Math.PI - this._f * Math.PI)) {
 
@@ -787,7 +787,7 @@ GeographicLib.GeodesicLine = {};
       // 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,
+      nvals = this.InverseStart(sbet1, cbet1, dn1, sbet2, cbet2, dn2, lam12,
                                     C1a, C2a);
       sig12 = nvals.sig12;
       salp1 = nvals.salp1;
@@ -818,7 +818,6 @@ GeographicLib.GeodesicLine = {};
         // 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;
@@ -826,9 +825,9 @@ GeographicLib.GeodesicLine = {};
           // 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);
+          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;
@@ -862,7 +861,7 @@ GeographicLib.GeodesicLine = {};
               calp1 = calp1 * cdalp1 - salp1 * sdalp1;
               salp1 = Math.max(0, nsalp1);
               // SinCosNorm(salp1, calp1);
-              var t = m.hypot(salp1, calp1); salp1 /= t; calp1 /= t;
+              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).
@@ -881,24 +880,22 @@ GeographicLib.GeodesicLine = {};
           salp1 = (salp1a + salp1b)/2;
           calp1 = (calp1a + calp1b)/2;
           // SinCosNorm(salp1, calp1);
-          var t = m.hypot(salp1, calp1); salp1 /= t; calp1 /= t;
+          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;
-          }
+        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;
@@ -919,19 +916,18 @@ GeographicLib.GeodesicLine = {};
       salp0 = salp1 * cbet1,
       calp0 = m.hypot(calp1, salp1 * sbet1); // calp0 > 0
       var alp12;
-      if (calp0 != 0 && salp0 != 0) {
-        var
+      if (calp0 !== 0 && salp0 !== 0) {
         // From Lambda12: tan(bet) = tan(sig) * cos(alp)
-        ssig1 = sbet1, csig1 = calp1 * cbet1,
-        ssig2 = sbet2, csig2 = calp2 * cbet2,
-        k2 = m.sq(calp0) * this._ep2,
+        ssig1 = sbet1; csig1 = calp1 * cbet1;
+        ssig2 = sbet2; csig2 = calp2 * cbet2;
+        var 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;
+        t = m.hypot(ssig1, csig1); ssig1 /= t; csig1 /= t;
         // SinCosNorm(ssig2, csig2);
-        var t = m.hypot(ssig2, csig2); ssig2 /= t; csig2 /= t;
+        t = m.hypot(ssig2, csig2); ssig2 /= t; csig2 /= t;
         var C4a = new Array(g.nC4_);
         this.C4f(eps, C4a);
         var
@@ -961,7 +957,7 @@ GeographicLib.GeodesicLine = {};
         // 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) {
+        if (salp12 === 0 && calp12 < 0) {
           salp12 = g.tiny_ * calp1;
           calp12 = -1;
         }
@@ -975,16 +971,16 @@ GeographicLib.GeodesicLine = {};
 
     // Convert calp, salp to azimuth accounting for lonsign, swapp, latsign.
     if (swapp < 0) {
-      var t = salp1;
+      t = salp1;
       salp1 = salp2;
       salp2 = t;
       // swap(salp1, salp2);
-      var t = calp1;
+      t = calp1;
       calp1 = calp2;
       calp2 = t;
       // swap(calp1, calp2);
       if (outmask & g.GEODESICSCALE) {
-        var t = vals.M12;
+        t = vals.M12;
         vals.M12 = vals.M21;
         vals.M21 = t;
         // swap(vals.M12, vals.M21);
@@ -1002,17 +998,16 @@ GeographicLib.GeodesicLine = {};
 
     // 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,
+    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/doc/scripts/GeographicLib/GeodesicLine.js b/doc/scripts/GeographicLib/GeodesicLine.js
index b2df9c1..6699c50 100644
--- a/doc/scripts/GeographicLib/GeodesicLine.js
+++ b/doc/scripts/GeographicLib/GeodesicLine.js
@@ -12,7 +12,7 @@
  *    http://dx.doi.org/10.1007/s00190-012-0578-z
  *    Addenda: http://geographiclib.sf.net/geod-addenda.html
  *
- * Copyright (c) Charles Karney (2011-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -33,7 +33,6 @@
     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;
@@ -41,13 +40,13 @@
     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);
+    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);
+    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));
@@ -68,9 +67,9 @@
     // 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;
+      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);
+    t = m.hypot(this._ssig1, this._csig1);
     this._ssig1 /= t; this._csig1 /= t;
     // SinCosNorm(this._somg1, this._comg1); -- don't need to normalize!
 
@@ -92,7 +91,7 @@
     }
 
     if (this._caps & g.CAP_C1p) {
-      this._C1pa = new Array(g.nC1p_ + 1),
+      this._C1pa = new Array(g.nC1p_ + 1);
       g.C1pf(eps, this._C1pa);
     }
 
@@ -120,28 +119,28 @@
       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) )) {
+    outmask &= this._caps & g.OUT_MASK;
+    if (!( arcmode || (this._caps & g.DISTANCE_IN & g.OUT_MASK) )) {
       // 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;
+    var sig12, ssig12, csig12, B12 = 0, AB1 = 0, ssig2, csig2;
     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);
+      ssig12 = s12a ===  0 ? 0 : Math.sin(sig12);
+      csig12 = s12a === 90 ? 0 : Math.cos(sig12);
     } else {
       // Interpret s12_a12 as distance
       var
@@ -177,9 +176,8 @@
         //      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;
+        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;
@@ -190,7 +188,7 @@
     }
 
     var omg12, lam12, lon12;
-    var ssig2, csig2, sbet2, cbet2, somg2, comg2, salp2, calp2;
+    var sbet2, cbet2, somg2, comg2, salp2, calp2;
     // sig2 = sig1 + sig12
     ssig2 = this._ssig1 * csig12 + this._csig1 * ssig12;
     csig2 = this._csig1 * csig12 - this._ssig1 * ssig12;
@@ -204,28 +202,32 @@
     sbet2 = this._calp0 * ssig2;
     // Alt: cbet2 = hypot(csig2, salp0 * ssig2);
     cbet2 = m.hypot(this._salp0, this._calp0 * csig2);
-    if (cbet2 == 0)
+    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) {
+      // tan(omg2) = sin(alp0) * tan(sig2)
+      somg2 = this._salp0 * ssig2; comg2 = csig2; // No need to normalize
+      // omg12 = omg2 - omg1
+      omg12 = outmask & g.LONG_NOWRAP ? sig12 -
+        (Math.atan2(ssig2, csig2) - Math.atan2(this._ssig1, this._csig1)) +
+        (Math.atan2(somg2, comg2) - Math.atan2(this._somg1, this._comg1)) :
+        Math.atan2(somg2 * this._comg1 - comg2 * this._somg1,
+                     comg2 * this._comg1 + somg2 * this._somg1);
       lam12 = omg12 + this._A3c *
-        ( sig12 + (g.SinCosSeries(true, ssig2, csig2, this._C3a, g.nC3_-1)
-                   - this._B31));
+        ( 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);
+      vals.lon2 = outmask & g.LONG_NOWRAP ? this._lon1 + lon12 :
+        m.AngNormalize(m.AngNormalize(this._lon1) + m.AngNormalize2(lon12));
     }
 
     if (outmask & g.LATITUDE)
@@ -244,8 +246,8 @@
         // 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);
+                               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);
@@ -258,14 +260,14 @@
       var
       B42 = g.SinCosSeries(false, ssig2, csig2, this._C4a, g.nC4_);
       var salp12, calp12;
-      if (this._calp0 == 0 || this._salp0 == 0) {
+      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) {
+        if (salp12 === 0 && calp12 < 0) {
           salp12 = g.tiny_ * this._calp1;
           calp12 = -1;
         }
@@ -289,6 +291,6 @@
 
     vals.a12 = arcmode ? s12_a12 : sig12 / m.degree;
     return vals;
-  }
+  };
 
 })();
diff --git a/doc/scripts/GeographicLib/Interface.js b/doc/scripts/GeographicLib/Interface.js
index 55a2308..1ab1b27 100644
--- a/doc/scripts/GeographicLib/Interface.js
+++ b/doc/scripts/GeographicLib/Interface.js
@@ -17,7 +17,7 @@
  *    http://dx.doi.org/10.1007/s00190-012-0578-z
  *    Addenda: http://geographiclib.sf.net/geod-addenda.html
  *
- * Copyright (c) Charles Karney (2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************
@@ -106,18 +106,18 @@
     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;
@@ -129,7 +129,7 @@
     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;
@@ -142,14 +142,14 @@
     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")
+      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);
@@ -167,14 +167,14 @@
       }
     }
     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")
+      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);
@@ -192,7 +192,7 @@
       }
     }
     return points;
-  }
+  };
 
   g.Geodesic.prototype.Circle = function(lat1, lon1, azi1, s12, k) {
     if (!(Math.abs(lat1) <= 90))
@@ -216,7 +216,7 @@
       points[i] = {lat: vals.lat2, lon: vals.lon2};
     }
     return points;
-  }
+  };
 
   g.Geodesic.prototype.Envelope = function(lat1, lon1, k, ord) {
     if (!(Math.abs(lat1) <= 90))
@@ -248,10 +248,10 @@
       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/doc/scripts/GeographicLib/Math.js b/doc/scripts/GeographicLib/Math.js
index c13dd2c..b50d220 100644
--- a/doc/scripts/GeographicLib/Math.js
+++ b/doc/scripts/GeographicLib/Math.js
@@ -3,7 +3,7 @@
  * Transcription of Math.hpp, Constants.hpp, and Accumulator.hpp into
  * JavaScript.
  *
- * Copyright (c) Charles Karney (2011) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -12,19 +12,19 @@ var GeographicLib; if (!GeographicLib) GeographicLib = {};
 
 GeographicLib.Math = {};
 
-GeographicLib.Math.sq = function(x) { return x * x; }
+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
@@ -34,14 +34,14 @@ GeographicLib.Math.log1p = function(x) {
   // 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;
-}
+  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
@@ -54,17 +54,17 @@ GeographicLib.Math.sum = function(u, v) {
   // 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);
-}
+  return GeographicLib.Math.AngNormalize(x % 360.0);
+};
 
 GeographicLib.Math.AngDiff = function(x, y) {
   // Compute y - x and reduce to [-180,180] accurately.
@@ -83,7 +83,7 @@ GeographicLib.Math.AngDiff = function(x, y) {
   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;
@@ -99,18 +99,18 @@ GeographicLib.Accumulator = {};
 
   a.Accumulator = function(y) {
     this.Set(y);
-  }
+  };
 
   a.Accumulator.prototype.Set = function(y) {
     if (!y) y = 0;
-    if (y.constructor == a.Accumulator) {
+    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...
@@ -148,11 +148,11 @@ GeographicLib.Accumulator = {};
     // [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,
+    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)
@@ -162,11 +162,11 @@ GeographicLib.Accumulator = {};
       b.Add(y);
       return b._s;
     }
-  }
+  };
 
   a.Accumulator.prototype.Negate = function() {
     this._s *= -1;
     this._t *= -1;
-  }
+  };
 
 })();
diff --git a/doc/scripts/GeographicLib/PolygonArea.js b/doc/scripts/GeographicLib/PolygonArea.js
index e1e07f6..f720842 100644
--- a/doc/scripts/GeographicLib/PolygonArea.js
+++ b/doc/scripts/GeographicLib/PolygonArea.js
@@ -12,7 +12,7 @@
  *    http://dx.doi.org/10.1007/s00190-012-0578-z
  *    Addenda: http://geographiclib.sf.net/geod-addenda.html
  *
- * Copyright (c) Charles Karney (2011-2013) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -38,19 +38,31 @@ GeographicLib.PolygonArea = {};
       lon1 < 0 && lon2 >= 0 && lon12 > 0 ? 1 :
       (lon2 < 0 && lon1 >= 0 && lon12 < 0 ? -1 : 0);
     return cross;
-  }
+  };
+
+  // an alternate version of transit to deal with longitudes in the direct
+  // problem.
+  p.transitdirect = function(lon1, lon2) {
+    // We want to compute exactly
+    //   int(floor(lon2 / 360)) - int(floor(lon1 / 360))
+    // Since we only need the parity of the result we can use std::remquo but
+    // this is buggy with g++ 4.8.3 and requires C++11.  So instead we do
+    lon1 = lon1 % 720.0; lon2 = lon2 % 720.0;
+    return ( ((lon2 >= 0 && lon2 < 360) || lon2 < -360 ? 0 : 1) -
+             ((lon1 >= 0 && lon1 < 360) || lon1 < -360 ? 0 : 1) );
+  };
 
   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);
+          (this._polyline ? g.NONE : g.AREA | g.LONG_NOWRAP);
     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;
@@ -59,10 +71,10 @@ GeographicLib.PolygonArea = {};
       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) {
+    if (this._num === 0) {
       this._lat0 = this._lat1 = lat;
       this._lon0 = this._lon1 = lon;
     } else {
@@ -76,7 +88,7 @@ GeographicLib.PolygonArea = {};
       this._lon1 = lon;
     }
     ++this._num;
-  }
+  };
 
   p.PolygonArea.prototype.AddEdge = function(azi, s) {
     if (this._num) {
@@ -84,13 +96,13 @@ GeographicLib.PolygonArea = {};
       this._perimetersum.Add(s);
       if (!this._polyline) {
         this._areasum.Add(t.S12);
-        this._crossings += p.transit(this._lon1, t.lon2);
+        this._crossings += p.transitdirect(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) {
@@ -131,12 +143,12 @@ GeographicLib.PolygonArea = {};
     }
     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) {
+    if (this._num === 0) {
       vals.perimeter = 0;
       if (!this._polyline)
         vals.area = 0;
@@ -147,15 +159,15 @@ GeographicLib.PolygonArea = {};
     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,
+      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);
+        crossings += p.transit(i === 0 ? this._lon1 : lon,
+                               i !== 0 ? this._lon0 : lon);
       }
     }
 
@@ -182,12 +194,12 @@ GeographicLib.PolygonArea = {};
     }
     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)
+    if (this._num === 0)
       return vals;
     vals.perimeter = this._perimetersum.Sum() + s;
     if (this._polyline)
@@ -198,7 +210,7 @@ GeographicLib.PolygonArea = {};
     var t;
     t = this._earth.Direct(this._lat1, this._lon1, azi, s, this._mask);
     tempsum += t.S12;
-    crossings += p.transit(this._lon1, t.lon2);
+    crossings += p.transitdirect(this._lon1, t.lon2);
     t = this._earth(t.lat2, t.lon2, this._lat0, this._lon0, this._mask);
     perimeter += t.s12;
     tempsum += t.S12;
@@ -224,18 +236,18 @@ GeographicLib.PolygonArea = {};
     }
     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/dotnet/NETGeographicLib/CMakeLists.txt b/dotnet/NETGeographicLib/CMakeLists.txt
index 64e5ed2..7100d84 100644
--- a/dotnet/NETGeographicLib/CMakeLists.txt
+++ b/dotnet/NETGeographicLib/CMakeLists.txt
@@ -11,6 +11,12 @@ set_target_properties (${NETGEOGRAPHICLIB_LIBRARIES}
 string (REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
 string (REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
 
+if (MSVC AND NOT MSVC_VERSION GREATER 1600)
+  # Disable "already imported" and "unsupported default parameter"
+  # warnings with VS 10
+  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4945 /wd4564")
+endif ()
+
 add_definitions (${PROJECT_DEFINITIONS})
 target_link_libraries (${NETGEOGRAPHICLIB_LIBRARIES} ${PROJECT_LIBRARIES})
 
diff --git a/dotnet/NETGeographicLib/DMS.cpp b/dotnet/NETGeographicLib/DMS.cpp
index 8271b7f..38bed3b 100644
--- a/dotnet/NETGeographicLib/DMS.cpp
+++ b/dotnet/NETGeographicLib/DMS.cpp
@@ -33,19 +33,6 @@ double DMS::Decode( System::String^ dms,
 }
 
 //*****************************************************************************
-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,
diff --git a/dotnet/NETGeographicLib/DMS.h b/dotnet/NETGeographicLib/DMS.h
index a0c37fe..5b796ca 100644
--- a/dotnet/NETGeographicLib/DMS.h
+++ b/dotnet/NETGeographicLib/DMS.h
@@ -169,18 +169,6 @@ public:
     static double Decode(double d, double m, double s )
     { return d + (m + s/double(60))/double(60); }
 
-    /// \cond SKIP
-    /**
-     * <b>DEPRECATED</b> (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.
      *
diff --git a/dotnet/NETGeographicLib/Geodesic.cpp b/dotnet/NETGeographicLib/Geodesic.cpp
index e78fdce..1fbb6a8 100644
--- a/dotnet/NETGeographicLib/Geodesic.cpp
+++ b/dotnet/NETGeographicLib/Geodesic.cpp
@@ -293,7 +293,7 @@ void Geodesic::ArcDirect(double lat1, double lon1, double azi1, double a12,
 //*****************************************************************************
 double Geodesic::GenDirect(double lat1, double lon1, double azi1,
                         bool arcmode, double s12_a12,
-                        NETGeographicLib::Mask outmask,
+                        Geodesic::mask outmask,
                         [System::Runtime::InteropServices::Out] double% lat2,
                         [System::Runtime::InteropServices::Out] double% lon2,
                         [System::Runtime::InteropServices::Out] double% azi2,
@@ -437,7 +437,7 @@ double Geodesic::Inverse(double lat1, double lon1, double lat2, double lon2,
 
 //*****************************************************************************
 double Geodesic::GenInverse(double lat1, double lon1, double lat2, double lon2,
-                        NETGeographicLib::Mask outmask,
+                        Geodesic::mask outmask,
                         [System::Runtime::InteropServices::Out] double% s12,
                         [System::Runtime::InteropServices::Out] double% azi1,
                         [System::Runtime::InteropServices::Out] double% azi2,
diff --git a/dotnet/NETGeographicLib/Geodesic.h b/dotnet/NETGeographicLib/Geodesic.h
index aba97e1..250a2b6 100644
--- a/dotnet/NETGeographicLib/Geodesic.h
+++ b/dotnet/NETGeographicLib/Geodesic.h
@@ -24,7 +24,11 @@ namespace NETGeographicLib
    * 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.)
+   * beyond point 2 not back to point 1.)  In the figure below, latitude if
+   * labeled φ, longitude λ (with λ<sub>12</sub> =
+   * λ<sub>2</sub> − λ<sub>1</sub>), and azimuth α.
+   *
+   * <img src="http://upload.wikimedia.org/wikipedia/commons/c/cb/Geodesic_problem_on_an_ellipsoid.svg" width=250 alt="spheroidal triangle">
    *
    * 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
@@ -67,7 +71,6 @@ namespace NETGeographicLib
    *   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.
-
    * - <i>area</i>.  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
@@ -96,17 +99,17 @@ namespace NETGeographicLib
    * (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
+   * - \e lat1 = −\e lat2 (with neither point 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
+   * - \e lon2 = \e lon1 ± 180° (with neither point 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
+   *   S12.  (This occurs when \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
@@ -173,7 +176,77 @@ namespace NETGeographicLib
         // Frees the unmanaged memory when this object is destroyed.
         !Geodesic();
     public:
-        /** \name Constructor
+        /**
+         * Bit masks for what calculations to do.  These masks do double duty.
+         * They signify to the GeodesicLine::GeodesicLine constructor and to
+         * Geodesic::Line what capabilities should be included in the GeodesicLine
+         * object.  They also specify which results to return in the general
+         * routines Geodesic::GenDirect and Geodesic::GenInverse routines.
+         * GeodesicLine::mask is a duplication of this enum.
+         **********************************************************************/
+        enum class mask {
+         /**
+          * No capabilities, no output.
+          * @hideinitializer
+          **********************************************************************/
+         NONE          = 0U,
+         /**
+          * Calculate latitude \e lat2.  (It's not necessary to include this as a
+          * capability to GeodesicLine because this is included by default.)
+          * @hideinitializer
+          **********************************************************************/
+         LATITUDE      = 1U<<7  | unsigned(captype::CAP_NONE),
+         /**
+          * Calculate longitude \e lon2.
+          * @hideinitializer
+          **********************************************************************/
+         LONGITUDE     = 1U<<8  | unsigned(captype::CAP_C3),
+         /**
+          * Calculate azimuths \e azi1 and \e azi2.  (It's not necessary to
+          * include this as a capability to GeodesicLine because this is included
+          * by default.)
+          * @hideinitializer
+          **********************************************************************/
+         AZIMUTH       = 1U<<9  | unsigned(captype::CAP_NONE),
+         /**
+          * Calculate distance \e s12.
+          * @hideinitializer
+          **********************************************************************/
+         DISTANCE      = 1U<<10 | unsigned(captype::CAP_C1),
+         /**
+          * Allow distance \e s12 to be used as input in the direct geodesic
+          * problem.
+          * @hideinitializer
+          **********************************************************************/
+         DISTANCE_IN   = 1U<<11 | unsigned(captype::CAP_C1) | unsigned(captype::CAP_C1p),
+         /**
+          * Calculate reduced length \e m12.
+          * @hideinitializer
+          **********************************************************************/
+         REDUCEDLENGTH = 1U<<12 | unsigned(captype::CAP_C1) | unsigned(captype::CAP_C2),
+         /**
+          * Calculate geodesic scales \e M12 and \e M21.
+          * @hideinitializer
+          **********************************************************************/
+         GEODESICSCALE = 1U<<13 | unsigned(captype::CAP_C1) | unsigned(captype::CAP_C2),
+         /**
+          * Calculate area \e S12.
+          * @hideinitializer
+          **********************************************************************/
+         AREA          = 1U<<14 | unsigned(captype::CAP_C4),
+         /**
+          * Do not wrap the \e lon2 in the direct calculation.
+          * @hideinitializer
+          **********************************************************************/
+         LONG_NOWRAP   = 1U<<15,
+         /**
+          * All capabilities, calculate everything.  (LONG_NOWRAP is not
+          * included in this mask.)
+          * @hideinitializer
+          **********************************************************************/
+         ALL           = unsigned(captype::OUT_ALL)| unsigned(captype::CAP_ALL),
+       };
+       /** \name Constructor
          **********************************************************************/
         ///@{
         /**
@@ -415,7 +488,7 @@ namespace NETGeographicLib
          * @param[in] s12_a12 if \e arcmode is false, this is the distance between
          *   point 1 and point 2 (meters); otherwise it is the arc length between
          *   point 1 and point 2 (degrees); it can be negative.
-         * @param[in] outmask a bitor'ed combination of NETGeographicLib::Mask values
+         * @param[in] outmask a bitor'ed combination of Geodesic::mask values
          *   specifying which of the following parameters should be set.
          * @param[out] lat2 latitude of point 2 (degrees).
          * @param[out] lon2 longitude of point 2 (degrees).
@@ -429,28 +502,35 @@ namespace NETGeographicLib
          * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
          * @return \e a12 arc length of between point 1 and point 2 (degrees).
          *
-         * The NETGeographicLib::Mask values possible for \e outmask are
-         * - \e outmask |= NETGeographicLib::Mask::LATITUDE for the latitude \e lat2;
-         * - \e outmask |= NETGeographicLib::Mask::LONGITUDE for the latitude \e lon2;
-         * - \e outmask |= NETGeographicLib::Mask::AZIMUTH for the latitude \e azi2;
-         * - \e outmask |= NETGeographicLib::Mask::DISTANCE for the distance \e s12;
-         * - \e outmask |= NETGeographicLib::Mask::REDUCEDLENGTH for the reduced length \e
+         * The Geodesic::mask values possible for \e outmask are
+         * - \e outmask |= Geodesic::LATITUDE for the latitude \e lat2;
+         * - \e outmask |= Geodesic::LONGITUDE for the latitude \e lon2;
+         * - \e outmask |= Geodesic::AZIMUTH for the latitude \e azi2;
+         * - \e outmask |= Geodesic::DISTANCE for the distance \e s12;
+         * - \e outmask |= Geodesic::REDUCEDLENGTH for the reduced length \e
          *   m12;
-         * - \e outmask |= NETGeographicLib::Mask::GEODESICSCALE for the geodesic scales \e
+         * - \e outmask |= Geodesic::GEODESICSCALE for the geodesic scales \e
          *   M12 and \e M21;
-         * - \e outmask |= NETGeographicLib::Mask::AREA for the area \e S12;
-         * - \e outmask |= NETGeographicLib::Mask::ALL for all of the above.
+         * - \e outmask |= Geodesic::AREA for the area \e S12;
+         * - \e outmask |= Geodesic::ALL for all of the above;
+         * - \e outmask |= Geodesic::LONG_NOWRAP stops the returned value of \e
+         *   lon2 being wrapped into the range [−180°, 180°).
          * .
          * The function value \e a12 is always computed and returned and this
          * equals \e s12_a12 is \e arcmode is true.  If \e outmask includes
-         * NETGeographicLib::Mask::DISTANCE and \e arcmode is false, then
-         * \e s12 = \e s12_a12.  It is not necessary to include
-         * NETGeographicLib::Mask::DISTANCE_IN in \e outmask; this is
-         * automatically included is \e arcmode is false.
+         * Geodesic::DISTANCE and \e arcmode is false, then \e s12 = \e s12_a12.
+         * It is not necessary to include Geodesic::DISTANCE_IN in \e outmask; this
+         * is automatically included is \e arcmode is false.
+         *
+         * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+         * indicates how many times the geodesic wrapped around the ellipsoid.
+         * Because \e lon2 might be outside the normal allowed range for
+         * longitudes, [−540°, 540°), be sure to normalize it with
+         * Math::AngNormalize2 before using it in other GeographicLib calls.
          **********************************************************************/
         double GenDirect(double lat1, double lon1, double azi1,
                         bool arcmode, double s12_a12,
-                        NETGeographicLib::Mask outmask,
+                        Geodesic::mask outmask,
                         [System::Runtime::InteropServices::Out] double% lat2,
                         [System::Runtime::InteropServices::Out] double% lon2,
                         [System::Runtime::InteropServices::Out] double% azi2,
@@ -598,7 +678,7 @@ namespace NETGeographicLib
          * The arc length is always computed and returned as the function value.
          **********************************************************************/
         double GenInverse(double lat1, double lon1, double lat2, double lon2,
-                        NETGeographicLib::Mask outmask,
+                        Geodesic::mask outmask,
                         [System::Runtime::InteropServices::Out] double% s12,
                         [System::Runtime::InteropServices::Out] double% azi1,
                         [System::Runtime::InteropServices::Out] double% azi2,
diff --git a/dotnet/NETGeographicLib/GeodesicExact.cpp b/dotnet/NETGeographicLib/GeodesicExact.cpp
index 2824191..9ebea6e 100644
--- a/dotnet/NETGeographicLib/GeodesicExact.cpp
+++ b/dotnet/NETGeographicLib/GeodesicExact.cpp
@@ -294,7 +294,7 @@ void GeodesicExact::ArcDirect(double lat1, double lon1, double azi1, double a12,
 //*****************************************************************************
 double GeodesicExact::GenDirect(double lat1, double lon1, double azi1,
                         bool arcmode, double s12_a12,
-                        NETGeographicLib::Mask outmask,
+                        GeodesicExact::mask outmask,
                         [System::Runtime::InteropServices::Out] double% lat2,
                         [System::Runtime::InteropServices::Out] double% lon2,
                         [System::Runtime::InteropServices::Out] double% azi2,
@@ -439,7 +439,7 @@ double GeodesicExact::Inverse(double lat1, double lon1, double lat2, double lon2
 
 //*****************************************************************************
 double GeodesicExact::GenInverse(double lat1, double lon1, double lat2, double lon2,
-                        NETGeographicLib::Mask outmask,
+                        GeodesicExact::mask outmask,
                         [System::Runtime::InteropServices::Out] double% s12,
                         [System::Runtime::InteropServices::Out] double% azi1,
                         [System::Runtime::InteropServices::Out] double% azi2,
diff --git a/dotnet/NETGeographicLib/GeodesicExact.h b/dotnet/NETGeographicLib/GeodesicExact.h
index f52a0eb..ebc86ab 100644
--- a/dotnet/NETGeographicLib/GeodesicExact.h
+++ b/dotnet/NETGeographicLib/GeodesicExact.h
@@ -85,13 +85,97 @@ namespace NETGeographicLib
    **********************************************************************/
     public ref class GeodesicExact
     {
-        private:
+    private:
+        enum class captype {
+          CAP_NONE = 0U,
+          CAP_E    = 1U<<0,
+          // Skip 1U<<1 for compatibility with Geodesic (not required)
+          CAP_D    = 1U<<2,
+          CAP_H    = 1U<<3,
+          CAP_C4   = 1U<<4,
+          CAP_ALL  = 0x1FU,
+          CAP_MASK = CAP_ALL,
+          OUT_ALL  = 0x7F80U,
+          OUT_MASK = 0xFF80U,       // Includes LONG_NOWRAP
+        };
         // pointer to the unmanaged GeographicLib::GeodesicExact.
         const GeographicLib::GeodesicExact* m_pGeodesicExact;
 
         // the finalizer deletes the unmanaged memory.
         !GeodesicExact();
     public:
+        /**
+         * Bit masks for what calculations to do.  These masks do double duty.
+         * They signify to the GeodesicLineExact::GeodesicLineExact constructor and
+         * to GeodesicExact::Line what capabilities should be included in the
+         * GeodesicLineExact object.  They also specify which results to return in
+         * the general routines GeodesicExact::GenDirect and
+         * GeodesicExact::GenInverse routines.  GeodesicLineExact::mask is a
+         * duplication of this enum.
+         **********************************************************************/
+        enum class mask {
+          /**
+           * No capabilities, no output.
+           * @hideinitializer
+           **********************************************************************/
+          NONE          = 0U,
+          /**
+           * Calculate latitude \e lat2.  (It's not necessary to include this as a
+           * capability to GeodesicLineExact because this is included by default.)
+           * @hideinitializer
+           **********************************************************************/
+          LATITUDE      = 1U<<7  | unsigned(captype::CAP_NONE),
+          /**
+           * Calculate longitude \e lon2.
+           * @hideinitializer
+           **********************************************************************/
+          LONGITUDE     = 1U<<8  | unsigned(captype::CAP_H),
+          /**
+           * Calculate azimuths \e azi1 and \e azi2.  (It's not necessary to
+           * include this as a capability to GeodesicLineExact because this is
+           * included by default.)
+           * @hideinitializer
+           **********************************************************************/
+          AZIMUTH       = 1U<<9  | unsigned(captype::CAP_NONE),
+          /**
+           * Calculate distance \e s12.
+           * @hideinitializer
+           **********************************************************************/
+          DISTANCE      = 1U<<10 | unsigned(captype::CAP_E),
+          /**
+           * Allow distance \e s12 to be used as input in the direct geodesic
+           * problem.
+           * @hideinitializer
+           **********************************************************************/
+          DISTANCE_IN   = 1U<<11 | unsigned(captype::CAP_E),
+          /**
+           * Calculate reduced length \e m12.
+           * @hideinitializer
+           **********************************************************************/
+          REDUCEDLENGTH = 1U<<12 | unsigned(captype::CAP_D),
+          /**
+           * Calculate geodesic scales \e M12 and \e M21.
+           * @hideinitializer
+           **********************************************************************/
+          GEODESICSCALE = 1U<<13 | unsigned(captype::CAP_D),
+          /**
+           * Calculate area \e S12.
+           * @hideinitializer
+           **********************************************************************/
+          AREA          = 1U<<14 | unsigned(captype::CAP_C4),
+          /**
+           * Do not wrap the \e lon2 in the direct calculation.
+           * @hideinitializer
+           **********************************************************************/
+          LONG_NOWRAP   = 1U<<15,
+          /**
+           * All capabilities, calculate everything.  (LONG_NOWRAP is not
+           * included in this mask.)
+           * @hideinitializer
+           **********************************************************************/
+          ALL           = unsigned(captype::OUT_ALL)| unsigned(captype::CAP_ALL),
+        };
+
         /** \name Constructor
          **********************************************************************/
         ///@{
@@ -335,7 +419,7 @@ namespace NETGeographicLib
          * @param[in] s12_a12 if \e arcmode is false, this is the distance between
          *   point 1 and point 2 (meters); otherwise it is the arc length between
          *   point 1 and point 2 (degrees); it can be signed.
-         * @param[in] outmask a bitor'ed combination of  NETGeographicLib::Mask values
+         * @param[in] outmask a bitor'ed combination of GeodesicExact::mask values
          *   specifying which of the following parameters should be set.
          * @param[out] lat2 latitude of point 2 (degrees).
          * @param[out] lon2 longitude of point 2 (degrees).
@@ -349,26 +433,34 @@ namespace NETGeographicLib
          * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
          * @return \e a12 arc length of between point 1 and point 2 (degrees).
          *
-         * The  NETGeographicLib::Mask values possible for \e outmask are
-         * - \e outmask |= NETGeographicLib::Mask::LATITUDE for the latitude \e lat2;
-         * - \e outmask |= NETGeographicLib::Mask::LONGITUDE for the latitude \e lon2;
-         * - \e outmask |= NETGeographicLib::Mask::AZIMUTH for the latitude \e azi2;
-         * - \e outmask |= NETGeographicLib::Mask::DISTANCE for the distance \e s12;
-         * - \e outmask |= NETGeographicLib::Mask::REDUCEDLENGTH for the reduced length \e
+         * The GeodesicExact::mask values possible for \e outmask are
+         * - \e outmask |= GeodesicExact::LATITUDE for the latitude \e lat2;
+         * - \e outmask |= GeodesicExact::LONGITUDE for the latitude \e lon2;
+         * - \e outmask |= GeodesicExact::AZIMUTH for the latitude \e azi2;
+         * - \e outmask |= GeodesicExact::DISTANCE for the distance \e s12;
+         * - \e outmask |= GeodesicExact::REDUCEDLENGTH for the reduced length \e
          *   m12;
-         * - \e outmask |= NETGeographicLib::Mask::GEODESICSCALE for the geodesic scales \e
+         * - \e outmask |= GeodesicExact::GEODESICSCALE for the geodesic scales \e
          *   M12 and \e M21;
-         * - \e outmask |= NETGeographicLib::Mask::AREA for the area \e S12;
-         * - \e outmask |= NETGeographicLib::Mask::ALL for all of the above.
+         * - \e outmask |= GeodesicExact::AREA for the area \e S12;
+         * - \e outmask |= GeodesicExact::ALL for all of the above;
+         * - \e outmask |= GeodesicExact::LONG_NOWRAP stops the returned value of
+         *   \e lon2 being wrapped into the range [−180°, 180°).
          * .
          * The function value \e a12 is always computed and returned and this
          * equals \e s12_a12 is \e arcmode is true.  If \e outmask includes
          * GeodesicExact::DISTANCE and \e arcmode is false, then \e s12 = \e
-         * s12_a12.  It is not necessary to include  NETGeographicLib::Mask::DISTANCE_IN in
+         * s12_a12.  It is not necessary to include GeodesicExact::DISTANCE_IN in
          * \e outmask; this is automatically included is \e arcmode is false.
+         *
+         * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+         * indicates how many times the geodesic wrapped around the ellipsoid.
+         * Because \e lon2 might be outside the normal allowed range for
+         * longitudes, [−540°, 540°), be sure to normalize it with
+         * Math::AngNormalize2 before using it in other GeographicLib calls.
          **********************************************************************/
         double GenDirect(double lat1, double lon1, double azi1,
-                        bool arcmode, double s12_a12, NETGeographicLib::Mask outmask,
+                        bool arcmode, double s12_a12, GeodesicExact::mask outmask,
                         [System::Runtime::InteropServices::Out] double% lat2,
                         [System::Runtime::InteropServices::Out] double% lon2,
                         [System::Runtime::InteropServices::Out] double% azi2,
@@ -485,7 +577,7 @@ namespace NETGeographicLib
          * @param[in] lon1 longitude of point 1 (degrees).
          * @param[in] lat2 latitude of point 2 (degrees).
          * @param[in] lon2 longitude of point 2 (degrees).
-         * @param[in] outmask a bitor'ed combination of  NETGeographicLib::Mask values
+         * @param[in] outmask a bitor'ed combination of GeodesicExact::mask values
          *   specifying which of the following parameters should be set.
          * @param[out] s12 distance between point 1 and point 2 (meters).
          * @param[out] azi1 azimuth at point 1 (degrees).
@@ -498,20 +590,20 @@ namespace NETGeographicLib
          * @param[out] S12 area under the geodesic (meters<sup>2</sup>).
          * @return \e a12 arc length of between point 1 and point 2 (degrees).
          *
-         * The NETGeographicLib::Mask values possible for \e outmask are
-         * - \e outmask |= NETGeographicLib::Mask::DISTANCE for the distance \e s12;
-         * - \e outmask |= NETGeographicLib::Mask::AZIMUTH for the latitude \e azi2;
-         * - \e outmask |= NETGeographicLib::Mask::REDUCEDLENGTH for the reduced length \e
+         * The GeodesicExact::mask values possible for \e outmask are
+         * - \e outmask |= GeodesicExact::DISTANCE for the distance \e s12;
+         * - \e outmask |= GeodesicExact::AZIMUTH for the latitude \e azi2;
+         * - \e outmask |= GeodesicExact::REDUCEDLENGTH for the reduced length \e
          *   m12;
-         * - \e outmask |= NETGeographicLib::Mask::GEODESICSCALE for the geodesic scales \e
+         * - \e outmask |= GeodesicExact::GEODESICSCALE for the geodesic scales \e
          *   M12 and \e M21;
-         * - \e outmask |= NETGeographicLib::Mask::AREA for the area \e S12;
-         * - \e outmask |= NETGeographicLib::Mask::ALL for all of the above.
+         * - \e outmask |= GeodesicExact::AREA for the area \e S12;
+         * - \e outmask |= GeodesicExact::ALL for all of the above.
          * .
          * The arc length is always computed and returned as the function value.
          **********************************************************************/
         double GenInverse(double lat1, double lon1, double lat2, double lon2,
-                        NETGeographicLib::Mask outmask,
+                        GeodesicExact::mask outmask,
                         [System::Runtime::InteropServices::Out] double% s12,
                         [System::Runtime::InteropServices::Out] double% azi1,
                         [System::Runtime::InteropServices::Out] double% azi2,
diff --git a/dotnet/NETGeographicLib/GeodesicLine.cpp b/dotnet/NETGeographicLib/GeodesicLine.cpp
index 6b59ed5..fedda12 100644
--- a/dotnet/NETGeographicLib/GeodesicLine.cpp
+++ b/dotnet/NETGeographicLib/GeodesicLine.cpp
@@ -291,7 +291,7 @@ void GeodesicLine::ArcPosition(double a12,
 
 //*****************************************************************************
 double GeodesicLine::GenPosition(bool arcmode, double s12_a12,
-    NETGeographicLib::Mask outmask,
+    GeodesicLine::mask outmask,
     [System::Runtime::InteropServices::Out] double% lat2,
     [System::Runtime::InteropServices::Out] double% lon2,
     [System::Runtime::InteropServices::Out] double% azi2,
@@ -346,5 +346,5 @@ NETGeographicLib::Mask GeodesicLine::Capabilities()
 { return static_cast<NETGeographicLib::Mask>(m_pGeodesicLine->Capabilities()); }
 
 //*****************************************************************************
-bool GeodesicLine::Capabilities(NETGeographicLib::Mask testcaps)
+bool GeodesicLine::Capabilities(GeodesicLine::mask testcaps)
 { return m_pGeodesicLine->Capabilities( static_cast<unsigned>(testcaps) ); }
diff --git a/dotnet/NETGeographicLib/GeodesicLine.h b/dotnet/NETGeographicLib/GeodesicLine.h
index b2a916c..940efe1 100644
--- a/dotnet/NETGeographicLib/GeodesicLine.h
+++ b/dotnet/NETGeographicLib/GeodesicLine.h
@@ -77,6 +77,75 @@ namespace NETGeographicLib
         // The finalizer frees the unmanaged memory when this object is destroyed.
         !GeodesicLine(void);
     public:
+
+        /**
+         * Bit masks for what calculations to do.  They signify to the
+         * GeodesicLine::GeodesicLine constructor and to Geodesic::Line what
+         * capabilities should be included in the GeodesicLine object.  This is
+         * merely a duplication of Geodesic::mask.
+         **********************************************************************/
+        enum class mask {
+         /**
+          * No capabilities, no output.
+          * @hideinitializer
+          **********************************************************************/
+         NONE          = 0U,
+         /**
+          * Calculate latitude \e lat2.  (It's not necessary to include this as a
+          * capability to GeodesicLine because this is included by default.)
+          * @hideinitializer
+          **********************************************************************/
+         LATITUDE      = 1U<<7  | unsigned(captype::CAP_NONE),
+         /**
+          * Calculate longitude \e lon2.
+          * @hideinitializer
+          **********************************************************************/
+         LONGITUDE     = 1U<<8  | unsigned(captype::CAP_C3),
+         /**
+          * Calculate azimuths \e azi1 and \e azi2.  (It's not necessary to
+          * include this as a capability to GeodesicLine because this is included
+          * by default.)
+          * @hideinitializer
+          **********************************************************************/
+         AZIMUTH       = 1U<<9  | unsigned(captype::CAP_NONE),
+         /**
+          * Calculate distance \e s12.
+          * @hideinitializer
+          **********************************************************************/
+         DISTANCE      = 1U<<10 | unsigned(captype::CAP_C1),
+         /**
+          * Allow distance \e s12 to be used as input in the direct geodesic
+          * problem.
+          * @hideinitializer
+          **********************************************************************/
+         DISTANCE_IN   = 1U<<11 | unsigned(captype::CAP_C1) | unsigned(captype::CAP_C1p),
+         /**
+          * Calculate reduced length \e m12.
+          * @hideinitializer
+          **********************************************************************/
+         REDUCEDLENGTH = 1U<<12 | unsigned(captype::CAP_C1) | unsigned(captype::CAP_C2),
+         /**
+          * Calculate geodesic scales \e M12 and \e M21.
+          * @hideinitializer
+          **********************************************************************/
+         GEODESICSCALE = 1U<<13 | unsigned(captype::CAP_C1) | unsigned(captype::CAP_C2),
+         /**
+          * Calculate area \e S12.
+          * @hideinitializer
+          **********************************************************************/
+         AREA          = 1U<<14 | unsigned(captype::CAP_C4),
+         /**
+          * Do not wrap the \e lon2 in the direct calculation.
+          * @hideinitializer
+          **********************************************************************/
+         LONG_NOWRAP   = 1U<<15,
+         /**
+          * All capabilities, calculate everything.  (LONG_NOWRAP is not
+          * included in this mask.)
+          * @hideinitializer
+          **********************************************************************/
+         ALL           = unsigned(captype::OUT_ALL)| unsigned(captype::CAP_ALL),
+        };
         /** \name Constructors
          **********************************************************************/
         ///@{
@@ -358,49 +427,57 @@ namespace NETGeographicLib
          * @param[in] s12_a12 if \e arcmode is false, this is the distance between
          *   point 1 and point 2 (meters); otherwise it is the arc length between
          *   point 1 and point 2 (degrees); it can be negative.
-         * @param[in] outmask a bitor'ed combination of NETGeographicLib::Mask values
+         * @param[in] outmask a bitor'ed combination of GeodesicLine::mask values
          *   specifying which of the following parameters should be set.
          * @param[out] lat2 latitude of point 2 (degrees).
          * @param[out] lon2 longitude of point 2 (degrees); requires that the
          *   GeodesicLine object was constructed with \e caps |=
-         *   NETGeographicLib::Mask::LONGITUDE.
+         *   GeodesicLine::LONGITUDE.
          * @param[out] azi2 (forward) azimuth at point 2 (degrees).
          * @param[out] s12 distance between point 1 and point 2 (meters); requires
          *   that the GeodesicLine object was constructed with \e caps |=
-         *   NETGeographicLib::Mask::DISTANCE.
+         *   GeodesicLine::DISTANCE.
          * @param[out] m12 reduced length of geodesic (meters); requires that the
          *   GeodesicLine object was constructed with \e caps |=
-         *   NETGeographicLib::Mask::REDUCEDLENGTH.
+         *   GeodesicLine::REDUCEDLENGTH.
          * @param[out] M12 geodesic scale of point 2 relative to point 1
          *   (dimensionless); requires that the GeodesicLine object was constructed
-         *   with \e caps |= NETGeographicLib::Mask::GEODESICSCALE.
+         *   with \e caps |= GeodesicLine::GEODESICSCALE.
          * @param[out] M21 geodesic scale of point 1 relative to point 2
          *   (dimensionless); requires that the GeodesicLine object was constructed
-         *   with \e caps |= NETGeographicLib::Mask::GEODESICSCALE.
+         *   with \e caps |= GeodesicLine::GEODESICSCALE.
          * @param[out] S12 area under the geodesic (meters<sup>2</sup>); requires
          *   that the GeodesicLine object was constructed with \e caps |=
-         *   NETGeographicLib::Mask::AREA.
+         *   GeodesicLine::AREA.
          * @return \e a12 arc length of between point 1 and point 2 (degrees).
          *
          * The GeodesicLine::mask values possible for \e outmask are
-         * - \e outmask |= NETGeographicLib::Mask::LATITUDE for the latitude \e lat2;
-         * - \e outmask |= NETGeographicLib::Mask::LONGITUDE for the latitude \e lon2;
-         * - \e outmask |= NETGeographicLib::Mask::AZIMUTH for the latitude \e azi2;
-         * - \e outmask |= NETGeographicLib::Mask::DISTANCE for the distance \e s12;
-         * - \e outmask |= NETGeographicLib::Mask::REDUCEDLENGTH for the reduced length \e
+         * - \e outmask |= GeodesicLine::LATITUDE for the latitude \e lat2;
+         * - \e outmask |= GeodesicLine::LONGITUDE for the latitude \e lon2;
+         * - \e outmask |= GeodesicLine::AZIMUTH for the latitude \e azi2;
+         * - \e outmask |= GeodesicLine::DISTANCE for the distance \e s12;
+         * - \e outmask |= GeodesicLine::REDUCEDLENGTH for the reduced length \e
          *   m12;
-         * - \e outmask |= NETGeographicLib::Mask::GEODESICSCALE for the geodesic scales \e
+         * - \e outmask |= GeodesicLine::GEODESICSCALE for the geodesic scales \e
          *   M12 and \e M21;
-         * - \e outmask |= NETGeographicLib::Mask::AREA for the area \e S12;
-         * - \e outmask |= NETGeographicLib::Mask::ALL for all of the above.
+         * - \e outmask |= GeodesicLine::AREA for the area \e S12;
+         * - \e outmask |= GeodesicLine::ALL for all of the above;
+         * - \e outmask |= GeodesicLine::LONG_NOWRAP stops the returned value of \e
+         *   lon2 being wrapped into the range [−180°, 180°).
          * .
          * Requesting a value which the GeodesicLine object is not capable of
          * computing is not an error; the corresponding argument will not be
          * altered.  Note, however, that the arc length is always computed and
          * returned as the function value.
+         *
+         * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+         * indicates how many times the geodesic wrapped around the ellipsoid.
+         * Because \e lon2 might be outside the normal allowed range for
+         * longitudes, [−540°, 540°), be sure to normalize it with
+         * Math::AngNormalize2 before using it in other GeographicLib calls.
          **********************************************************************/
         double GenPosition(bool arcmode, double s12_a12,
-                    NETGeographicLib::Mask outmask,
+                    GeodesicLine::mask outmask,
                     [System::Runtime::InteropServices::Out] double% lat2,
                     [System::Runtime::InteropServices::Out] double% lon2,
                     [System::Runtime::InteropServices::Out] double% azi2,
@@ -465,7 +542,7 @@ namespace NETGeographicLib
          * @param[in] testcaps a set of bitor'ed GeodesicLine::mask values.
          * @return true if the GeodesicLine object has all these capabilities.
          **********************************************************************/
-        bool Capabilities(NETGeographicLib::Mask testcaps);
+        bool Capabilities(GeodesicLine::mask testcaps);
         ///@}
     };
 } // namespace NETGeographicLib
diff --git a/dotnet/NETGeographicLib/GeodesicLineExact.cpp b/dotnet/NETGeographicLib/GeodesicLineExact.cpp
index e3f1518..8792b02 100644
--- a/dotnet/NETGeographicLib/GeodesicLineExact.cpp
+++ b/dotnet/NETGeographicLib/GeodesicLineExact.cpp
@@ -292,7 +292,7 @@ void GeodesicLineExact::ArcPosition(double a12,
 
 //*****************************************************************************
 double GeodesicLineExact::GenPosition(bool arcmode, double s12_a12,
-    NETGeographicLib::Mask outmask,
+    GeodesicLineExact::mask outmask,
     [System::Runtime::InteropServices::Out] double% lat2,
     [System::Runtime::InteropServices::Out] double% lon2,
     [System::Runtime::InteropServices::Out] double% azi2,
diff --git a/dotnet/NETGeographicLib/GeodesicLineExact.h b/dotnet/NETGeographicLib/GeodesicLineExact.h
index 750bf8a..27828d3 100644
--- a/dotnet/NETGeographicLib/GeodesicLineExact.h
+++ b/dotnet/NETGeographicLib/GeodesicLineExact.h
@@ -45,13 +45,96 @@ namespace NETGeographicLib
    **********************************************************************/
     public ref class GeodesicLineExact
     {
-        private:
+    private:
+        enum class captype {
+          CAP_NONE = 0U,
+          CAP_E    = 1U<<0,
+          // Skip 1U<<1 for compatibility with Geodesic (not required)
+          CAP_D    = 1U<<2,
+          CAP_H    = 1U<<3,
+          CAP_C4   = 1U<<4,
+          CAP_ALL  = 0x1FU,
+          CAP_MASK = CAP_ALL,
+          OUT_ALL  = 0x7F80U,
+          OUT_MASK = 0xFF80U,       // Includes LONG_NOWRAP
+        };
         // a pointer to the GeographicLib::GeodesicLineExact.
         const GeographicLib::GeodesicLineExact* m_pGeodesicLineExact;
 
         // the finalizer frees the unmanaged memory when the object is destroyed.
         !GeodesicLineExact(void);
     public:
+        /**
+         * Bit masks for what calculations to do.  These masks do double duty.
+         * They signify to the GeodesicLineExact::GeodesicLineExact constructor and
+         * to GeodesicExact::Line what capabilities should be included in the
+         * GeodesicLineExact object.  They also specify which results to return in
+         * the general routines GeodesicExact::GenDirect and
+         * GeodesicExact::GenInverse routines.  GeodesicLineExact::mask is a
+         * duplication of this enum.
+         **********************************************************************/
+        enum class mask {
+          /**
+           * No capabilities, no output.
+           * @hideinitializer
+           **********************************************************************/
+          NONE          = 0U,
+          /**
+           * Calculate latitude \e lat2.  (It's not necessary to include this as a
+           * capability to GeodesicLineExact because this is included by default.)
+           * @hideinitializer
+           **********************************************************************/
+          LATITUDE      = 1U<<7  | unsigned(captype::CAP_NONE),
+          /**
+           * Calculate longitude \e lon2.
+           * @hideinitializer
+           **********************************************************************/
+          LONGITUDE     = 1U<<8  | unsigned(captype::CAP_H),
+          /**
+           * Calculate azimuths \e azi1 and \e azi2.  (It's not necessary to
+           * include this as a capability to GeodesicLineExact because this is
+           * included by default.)
+           * @hideinitializer
+           **********************************************************************/
+          AZIMUTH       = 1U<<9  | unsigned(captype::CAP_NONE),
+          /**
+           * Calculate distance \e s12.
+           * @hideinitializer
+           **********************************************************************/
+          DISTANCE      = 1U<<10 | unsigned(captype::CAP_E),
+          /**
+           * Allow distance \e s12 to be used as input in the direct geodesic
+           * problem.
+           * @hideinitializer
+           **********************************************************************/
+          DISTANCE_IN   = 1U<<11 | unsigned(captype::CAP_E),
+          /**
+           * Calculate reduced length \e m12.
+           * @hideinitializer
+           **********************************************************************/
+          REDUCEDLENGTH = 1U<<12 | unsigned(captype::CAP_D),
+          /**
+           * Calculate geodesic scales \e M12 and \e M21.
+           * @hideinitializer
+           **********************************************************************/
+          GEODESICSCALE = 1U<<13 | unsigned(captype::CAP_D),
+          /**
+           * Calculate area \e S12.
+           * @hideinitializer
+           **********************************************************************/
+          AREA          = 1U<<14 | unsigned(captype::CAP_C4),
+          /**
+           * Do not wrap the \e lon2 in the direct calculation.
+           * @hideinitializer
+           **********************************************************************/
+          LONG_NOWRAP   = 1U<<15,
+          /**
+           * All capabilities, calculate everything.  (LONG_NOWRAP is not
+           * included in this mask.)
+           * @hideinitializer
+           **********************************************************************/
+          ALL           = unsigned(captype::OUT_ALL)| unsigned(captype::CAP_ALL),
+        };
 
         /** \name Constructors
          **********************************************************************/
@@ -335,7 +418,7 @@ namespace NETGeographicLib
          * @param[in] s12_a12 if \e arcmode is false, this is the distance between
          *   point 1 and point 2 (meters); otherwise it is the arc length between
          *   point 1 and point 2 (degrees); it can be signed.
-         * @param[in] outmask a bitor'ed combination of NETGeographicLib::Mask
+         * @param[in] outmask a bitor'ed combination of GeodesicLineExact::mask
          *   values specifying which of the following parameters should be set.
          * @param[out] lat2 latitude of point 2 (degrees).
          * @param[out] lon2 longitude of point 2 (degrees); requires that the
@@ -359,25 +442,33 @@ namespace NETGeographicLib
          *   GeodesicLineExact::AREA.
          * @return \e a12 arc length of between point 1 and point 2 (degrees).
          *
-         * The NETGeographicLib::Mask values possible for \e outmask are
-         * - \e outmask |= NETGeographicLib::Mask::LATITUDE for the latitude \e lat2;
-         * - \e outmask |= NETGeographicLib::Mask::LONGITUDE for the latitude \e lon2;
-         * - \e outmask |= NETGeographicLib::Mask::AZIMUTH for the latitude \e azi2;
-         * - \e outmask |= NETGeographicLib::Mask::DISTANCE for the distance \e s12;
-         * - \e outmask |= NETGeographicLib::Mask::REDUCEDLENGTH for the reduced length
+         * The GeodesicLineExact::mask values possible for \e outmask are
+         * - \e outmask |= GeodesicLineExact::LATITUDE for the latitude \e lat2;
+         * - \e outmask |= GeodesicLineExact::LONGITUDE for the latitude \e lon2;
+         * - \e outmask |= GeodesicLineExact::AZIMUTH for the latitude \e azi2;
+         * - \e outmask |= GeodesicLineExact::DISTANCE for the distance \e s12;
+         * - \e outmask |= GeodesicLineExact::REDUCEDLENGTH for the reduced length
          *   \e m12;
-         * - \e outmask |= NETGeographicLib::Mask::GEODESICSCALE for the geodesic scales
+         * - \e outmask |= GeodesicLineExact::GEODESICSCALE for the geodesic scales
          *   \e M12 and \e M21;
-         * - \e outmask |= NETGeographicLib::Mask::AREA for the area \e S12;
-         * - \e outmask |= NETGeographicLib::Mask::ALL for all of the above.
+         * - \e outmask |= GeodesicLineExact::AREA for the area \e S12;
+         * - \e outmask |= GeodesicLineExact::ALL for all of the above;
+         * - \e outmask |= GeodesicLineExact::LONG_NOWRAP stops the returned value
+         *   of \e lon2 being wrapped into the range [−180°, 180°).
          * .
          * Requesting a value which the GeodesicLineExact object is not capable of
          * computing is not an error; the corresponding argument will not be
          * altered.  Note, however, that the arc length is always computed and
          * returned as the function value.
+         *
+         * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+         * indicates how many times the geodesic wrapped around the ellipsoid.
+         * Because \e lon2 might be outside the normal allowed range for
+         * longitudes, [−540°, 540°), be sure to normalize it with
+         * Math::AngNormalize2 before using it in other GeographicLib calls.
          **********************************************************************/
         double GenPosition(bool arcmode, double s12_a12,
-                NETGeographicLib::Mask outmask,
+                GeodesicLineExact::mask outmask,
                 [System::Runtime::InteropServices::Out] double% lat2,
                 [System::Runtime::InteropServices::Out] double% lon2,
                 [System::Runtime::InteropServices::Out] double% azi2,
diff --git a/dotnet/NETGeographicLib/Geoid.h b/dotnet/NETGeographicLib/Geoid.h
index eb45f35..864c392 100644
--- a/dotnet/NETGeographicLib/Geoid.h
+++ b/dotnet/NETGeographicLib/Geoid.h
@@ -32,6 +32,13 @@ namespace NETGeographicLib
    * this class evaluates the height by interpolation into a grid of
    * precomputed values.
    *
+   * The geoid height, \e N, can be used to convert a height above the
+   * ellipsoid, \e h, to the corresponding height above the geoid (roughly the
+   * height above mean sea level), \e H, using the relations
+   *
+   *    \e h = \e N + \e H;
+   *   \e H = −\e N + \e h.
+   *
    * See \ref geoid for details of how to install the data sets, the data
    * format, estimates of the interpolation errors, and how to use caching.
    *
diff --git a/dotnet/NETGeographicLib/GravityCircle.h b/dotnet/NETGeographicLib/GravityCircle.h
index 8a789f6..35b16d8 100644
--- a/dotnet/NETGeographicLib/GravityCircle.h
+++ b/dotnet/NETGeographicLib/GravityCircle.h
@@ -23,7 +23,10 @@ namespace NETGeographicLib
    * different longitudes to be evaluated rapidly.
    *
    * Use GravityModel::Circle to create a GravityCircle object.  (The
-   * constructor for this class is for internal use only.)
+   * constructor for this class is private.)
+   *
+   * See \ref gravityparallel for an example of using GravityCircle (together
+   * with OpenMP) to speed up the computation of geoid heights.
    *
    * C# Example:
    * \include example-GravityCircle.cs
diff --git a/dotnet/NETGeographicLib/NETGeographicLib.h b/dotnet/NETGeographicLib/NETGeographicLib.h
index 720af11..d3c4aee 100644
--- a/dotnet/NETGeographicLib/NETGeographicLib.h
+++ b/dotnet/NETGeographicLib/NETGeographicLib.h
@@ -23,7 +23,9 @@ namespace NETGeographicLib
       CAP_C3   = 1U<<3,
       CAP_C4   = 1U<<4,
       CAP_ALL  = 0x1FU,
+      CAP_MASK = CAP_ALL,
       OUT_ALL  = 0x7F80U,
+      OUT_MASK = 0xFF80U,
     };
 
     /**
@@ -87,6 +89,11 @@ namespace NETGeographicLib
        **********************************************************************/
       AREA          = 1U<<14 | unsigned(captype::CAP_C4),
       /**
+       * Do not wrap the \e lon2 in the direct calculation.
+       * @hideinitializer
+       **********************************************************************/
+      LONG_NOWRAP   = 1U<<15,
+      /**
        * All capabilities, calculate everything.
        * @hideinitializer
        **********************************************************************/
diff --git a/dotnet/NETGeographicLib/PolygonArea.cpp b/dotnet/NETGeographicLib/PolygonArea.cpp
index 1211c69..5fa9439 100644
--- a/dotnet/NETGeographicLib/PolygonArea.cpp
+++ b/dotnet/NETGeographicLib/PolygonArea.cpp
@@ -13,6 +13,7 @@
 #include "PolygonArea.h"
 #include "Geodesic.h"
 #include "GeodesicExact.h"
+#include "Rhumb.h"
 #include "NETGeographicLib.h"
 
 using namespace NETGeographicLib;
@@ -239,3 +240,115 @@ double PolygonAreaExact::MajorRadius::get()
 //*****************************************************************************
 double PolygonAreaExact::Flattening::get()
 { return m_pPolygonArea->Flattening(); }
+
+//*****************************************************************************
+// PolygonAreaRhumb
+//*****************************************************************************
+PolygonAreaRhumb::!PolygonAreaRhumb(void)
+{
+    if ( m_pPolygonArea != NULL )
+    {
+        delete m_pPolygonArea;
+        m_pPolygonArea = NULL;
+    }
+}
+
+//*****************************************************************************
+PolygonAreaRhumb::PolygonAreaRhumb(Rhumb^ earth, bool polyline )
+{
+    try
+    {
+        const GeographicLib::Rhumb* pGeodesic =
+            reinterpret_cast<const GeographicLib::Rhumb*>(
+                earth->GetUnmanaged()->ToPointer() );
+        m_pPolygonArea = new GeographicLib::PolygonAreaRhumb( *pGeodesic, polyline );
+    }
+    catch (std::bad_alloc)
+    {
+        throw gcnew GeographicErr( BADALLOC );
+    }
+}
+
+//*****************************************************************************
+PolygonAreaRhumb::PolygonAreaRhumb(const bool polyline )
+{
+    try
+    {
+        m_pPolygonArea = new GeographicLib::PolygonAreaRhumb(
+            GeographicLib::Rhumb::WGS84(), polyline );
+    }
+    catch (std::bad_alloc)
+    {
+        throw gcnew GeographicErr( BADALLOC );
+    }
+}
+
+//*****************************************************************************
+void PolygonAreaRhumb::Clear() { m_pPolygonArea->Clear(); }
+
+//*****************************************************************************
+void PolygonAreaRhumb::AddPoint(double lat, double lon)
+{
+    m_pPolygonArea->AddPoint( lat, lon );
+}
+
+//*****************************************************************************
+void PolygonAreaRhumb::AddEdge(double azi, double s)
+{
+    m_pPolygonArea->AddEdge( azi, s );
+}
+
+//*****************************************************************************
+unsigned PolygonAreaRhumb::Compute(bool reverse, bool sign,
+                    [System::Runtime::InteropServices::Out] double% perimeter,
+                    [System::Runtime::InteropServices::Out] double% area)
+{
+    double lperimeter, larea;
+    unsigned out = m_pPolygonArea->Compute( reverse, sign, lperimeter, larea );
+    perimeter = lperimeter;
+    area = larea;
+    return out;
+}
+
+//*****************************************************************************
+unsigned PolygonAreaRhumb::TestPoint(double lat, double lon, bool reverse, bool sign,
+                    [System::Runtime::InteropServices::Out] double% perimeter,
+                    [System::Runtime::InteropServices::Out] double% area)
+{
+    double lperimeter, larea;
+    unsigned out = m_pPolygonArea->TestPoint( lat, lon, reverse, sign, lperimeter, larea );
+    perimeter = lperimeter;
+    area = larea;
+    return out;
+}
+
+//*****************************************************************************
+unsigned PolygonAreaRhumb::TestEdge(double azi, double s, bool reverse, bool sign,
+                    [System::Runtime::InteropServices::Out] double% perimeter,
+                    [System::Runtime::InteropServices::Out] double% area)
+{
+    double lperimeter, larea;
+    unsigned out = m_pPolygonArea->TestEdge( azi, s, reverse, sign, lperimeter, larea );
+    perimeter = lperimeter;
+    area = larea;
+    return out;
+}
+
+//*****************************************************************************
+void PolygonAreaRhumb::CurrentPoint(
+    [System::Runtime::InteropServices::Out] double% lat,
+    [System::Runtime::InteropServices::Out] double% lon)
+{
+    double llat, llon;
+    m_pPolygonArea->CurrentPoint( llat, llon );
+    lat = llat;
+    lon = llon;
+}
+
+//*****************************************************************************
+double PolygonAreaRhumb::MajorRadius::get()
+{ return m_pPolygonArea->MajorRadius(); }
+
+//*****************************************************************************
+double PolygonAreaRhumb::Flattening::get()
+{ return m_pPolygonArea->Flattening(); }
diff --git a/dotnet/NETGeographicLib/PolygonArea.h b/dotnet/NETGeographicLib/PolygonArea.h
index 7e8faef..b5e1138 100644
--- a/dotnet/NETGeographicLib/PolygonArea.h
+++ b/dotnet/NETGeographicLib/PolygonArea.h
@@ -384,4 +384,176 @@ namespace NETGeographicLib
                           [System::Runtime::InteropServices::Out] double% lon);
         ///@}
     };
+
+    //*************************************************************************
+    // PolygonAreaRhumb
+    //*************************************************************************
+    ref class Rhumb;
+
+    public ref class PolygonAreaRhumb
+    {
+        private:
+        // a pointer to the unmanaged GeographicLib::PolygonArea
+        GeographicLib::PolygonAreaRhumb* m_pPolygonArea;
+
+        // the finalize frees the unmanaged memory when the object is destroyed.
+        !PolygonAreaRhumb(void);
+    public:
+
+        /**
+         * Constructor for PolygonArea.
+         *
+         * @param[in] earth the Geodesic object to use for geodesic calculations.
+         * @param[in] polyline if true that treat the points as defining a polyline
+         *   instead of a polygon.
+         **********************************************************************/
+        PolygonAreaRhumb(Rhumb^ earth, bool polyline );
+
+        /**
+         * Constructor for PolygonArea that assumes a WGS84 ellipsoid.
+         *
+         * @param[in] polyline if true that treat the points as defining a polyline
+         *   instead of a polygon.
+         **********************************************************************/
+        PolygonAreaRhumb(const bool polyline );
+
+        /**
+         * The destructor calls the finalizer.
+         **********************************************************************/
+        ~PolygonAreaRhumb()
+        { this->!PolygonAreaRhumb(); }
+
+        /**
+         * Clear PolygonArea, allowing a new polygon to be started.
+         **********************************************************************/
+        void Clear();
+
+        /**
+         * Add a point to the polygon or polyline.
+         *
+         * @param[in] lat the latitude of the point (degrees).
+         * @param[in] lon the longitude of the point (degrees).
+         *
+         * \e lat should be in the range [−90°, 90°] and \e
+         * lon should be in the range [−540°, 540°).
+         **********************************************************************/
+        void AddPoint(double lat, double lon);
+
+        /**
+         * Add an edge to the polygon or polyline.
+         *
+         * @param[in] azi azimuth at current point (degrees).
+         * @param[in] s distance from current point to next point (meters).
+         *
+         * \e azi should be in the range [−540°, 540°).  This does
+         * nothing if no points have been added yet.  Use PolygonArea::CurrentPoint
+         * to determine the position of the new vertex.
+         **********************************************************************/
+        void AddEdge(double azi, double s);
+
+        /**
+         * Return the results so far.
+         *
+         * @param[in] reverse if true then clockwise (instead of counter-clockwise)
+         *   traversal counts as a positive area.
+         * @param[in] sign if true then return a signed result for the area if
+         *   the polygon is traversed in the "wrong" direction instead of returning
+         *   the area for the rest of the earth.
+         * @param[out] perimeter the perimeter of the polygon or length of the
+         *   polyline (meters).
+         * @param[out] area the area of the polygon (meters<sup>2</sup>); only set
+         *   if \e polyline is false in the constructor.
+         * @return the number of points.
+         **********************************************************************/
+        unsigned Compute(bool reverse, bool sign,
+                [System::Runtime::InteropServices::Out] double% perimeter,
+                [System::Runtime::InteropServices::Out] double% area);
+
+        /**
+         * Return the results assuming a tentative final test point is added;
+         * however, the data for the test point is not saved.  This lets you report
+         * a running result for the perimeter and area as the user moves the mouse
+         * cursor.  Ordinary floating point arithmetic is used to accumulate the
+         * data for the test point; thus the area and perimeter returned are less
+         * accurate than if PolygonArea::AddPoint and PolygonArea::Compute are
+         * used.
+         *
+         * @param[in] lat the latitude of the test point (degrees).
+         * @param[in] lon the longitude of the test point (degrees).
+         * @param[in] reverse if true then clockwise (instead of counter-clockwise)
+         *   traversal counts as a positive area.
+         * @param[in] sign if true then return a signed result for the area if
+         *   the polygon is traversed in the "wrong" direction instead of returning
+         *   the area for the rest of the earth.
+         * @param[out] perimeter the approximate perimeter of the polygon or length
+         *   of the polyline (meters).
+         * @param[out] area the approximate area of the polygon
+         *   (meters<sup>2</sup>); only set if polyline is false in the
+         *   constructor.
+         * @return the number of points.
+         *
+         * \e lat should be in the range [−90°, 90°] and \e
+         * lon should be in the range [−540°, 540°).
+         **********************************************************************/
+        unsigned TestPoint(double lat, double lon, bool reverse, bool sign,
+                [System::Runtime::InteropServices::Out] double% perimeter,
+                [System::Runtime::InteropServices::Out] double% area);
+
+        /**
+         * Return the results assuming a tentative final test point is added via an
+         * azimuth and distance; however, the data for the test point is not saved.
+         * This lets you report a running result for the perimeter and area as the
+         * user moves the mouse cursor.  Ordinary floating point arithmetic is used
+         * to accumulate the data for the test point; thus the area and perimeter
+         * returned are less accurate than if PolygonArea::AddEdge and
+         * PolygonArea::Compute are used.
+         *
+         * @param[in] azi azimuth at current point (degrees).
+         * @param[in] s distance from current point to final test point (meters).
+         * @param[in] reverse if true then clockwise (instead of counter-clockwise)
+         *   traversal counts as a positive area.
+         * @param[in] sign if true then return a signed result for the area if
+         *   the polygon is traversed in the "wrong" direction instead of returning
+         *   the area for the rest of the earth.
+         * @param[out] perimeter the approximate perimeter of the polygon or length
+         *   of the polyline (meters).
+         * @param[out] area the approximate area of the polygon
+         *   (meters<sup>2</sup>); only set if polyline is false in the
+         *   constructor.
+         * @return the number of points.
+         *
+         * \e azi should be in the range [−540°, 540°).
+         **********************************************************************/
+        unsigned TestEdge(double azi, double s, bool reverse, bool sign,
+                [System::Runtime::InteropServices::Out] double% perimeter,
+                [System::Runtime::InteropServices::Out] double% area);
+
+        /** \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(); }
+
+        /**
+         * Report the previous vertex added to the polygon or polyline.
+         *
+         * @param[out] lat the latitude of the point (degrees).
+         * @param[out] lon the longitude of the point (degrees).
+         *
+         * If no points have been added, then NaNs are returned.  Otherwise, \e lon
+         * will be in the range [−180°, 180°).
+         **********************************************************************/
+        void CurrentPoint([System::Runtime::InteropServices::Out] double% lat,
+                          [System::Runtime::InteropServices::Out] double% lon);
+        ///@}
+    };
 } // namespace NETGeographicLib
diff --git a/dotnet/NETGeographicLib/Rhumb.cpp b/dotnet/NETGeographicLib/Rhumb.cpp
index 61e36aa..2096876 100644
--- a/dotnet/NETGeographicLib/Rhumb.cpp
+++ b/dotnet/NETGeographicLib/Rhumb.cpp
@@ -45,6 +45,19 @@ Rhumb::Rhumb(double a, double f, bool exact)
 //*****************************************************************************
 void Rhumb::Direct(double lat1, double lon1, double azi12, double s12,
             [System::Runtime::InteropServices::Out] double% lat2,
+            [System::Runtime::InteropServices::Out] double% lon2,
+            [System::Runtime::InteropServices::Out] double% S12)
+{
+    double ilat2, ilon2, iS12;
+    m_pRhumb->Direct( lat1, lon1, azi12, s12, ilat2, ilon2, iS12 );
+    lat2 = ilat2;
+    lon2 = ilon2;
+    S12 = iS12;
+}
+
+//*****************************************************************************
+void Rhumb::Direct(double lat1, double lon1, double azi12, double s12,
+            [System::Runtime::InteropServices::Out] double% lat2,
             [System::Runtime::InteropServices::Out] double% lon2)
 {
     double ilat2, ilon2;
@@ -54,6 +67,34 @@ void Rhumb::Direct(double lat1, double lon1, double azi12, double s12,
 }
 
 //*****************************************************************************
+void Rhumb::GenDirect(double lat1, double lon1, double azi12, double s12,
+                Rhumb::mask outmask,
+                [System::Runtime::InteropServices::Out] double% lat2,
+                [System::Runtime::InteropServices::Out] double% lon2,
+                [System::Runtime::InteropServices::Out] double% S12)
+{
+    double ilat2, ilon2, iS12;
+    unsigned int iMask = (unsigned int)outmask;
+    m_pRhumb->GenDirect( lat1, lon1, azi12, s12, iMask, ilat2, ilon2, iS12 );
+    lat2 = ilat2;
+    lon2 = ilon2;
+    S12 = iS12;
+}
+
+//*****************************************************************************
+void Rhumb::Inverse(double lat1, double lon1, double lat2, double lon2,
+            [System::Runtime::InteropServices::Out] double% s12,
+            [System::Runtime::InteropServices::Out] double% azi12,
+            [System::Runtime::InteropServices::Out] double% S12)
+{
+    double is12, iazi12, iS12;
+    m_pRhumb->Inverse( lat1, lon1, lat2, lon2, is12, iazi12, iS12 );
+    s12 = is12;
+    azi12 = iazi12;
+    S12 = iS12;
+}
+
+//*****************************************************************************
 void Rhumb::Inverse(double lat1, double lon1, double lat2, double lon2,
                 [System::Runtime::InteropServices::Out] double% s12,
                 [System::Runtime::InteropServices::Out] double% azi12)
@@ -65,6 +106,21 @@ void Rhumb::Inverse(double lat1, double lon1, double lat2, double lon2,
 }
 
 //*****************************************************************************
+void Rhumb::GenInverse(double lat1, double lon1, double lat2, double lon2,
+                Rhumb::mask outmask,
+                [System::Runtime::InteropServices::Out] double% s12,
+                [System::Runtime::InteropServices::Out] double% azi12,
+                [System::Runtime::InteropServices::Out] double% S12)
+{
+    double is12, iazi12, iS12;
+    unsigned int iMask = (unsigned int)outmask;
+    m_pRhumb->GenInverse( lat1, lon1, lat2, lon2, iMask, is12, iazi12, iS12 );
+    s12 = is12;
+    azi12 = iazi12;
+    S12 = iS12;
+}
+
+//*****************************************************************************
 RhumbLine^ Rhumb::Line(double lat1, double lon1, double azi12)
 {
     return gcnew RhumbLine( new GeographicLib::RhumbLine(m_pRhumb->Line( lat1, lon1, azi12 )) );
@@ -77,6 +133,9 @@ double Rhumb::MajorRadius::get() { return m_pRhumb->MajorRadius(); }
 double Rhumb::Flattening::get() { return m_pRhumb->Flattening(); }
 
 //*****************************************************************************
+double Rhumb::EllipsoidArea::get() { return m_pRhumb->EllipsoidArea(); }
+
+//*****************************************************************************
 Rhumb^ Rhumb::WGS84()
 {
     return gcnew Rhumb( GeographicLib::Constants::WGS84_a(),
@@ -84,6 +143,12 @@ Rhumb^ Rhumb::WGS84()
 }
 
 //*****************************************************************************
+System::IntPtr^ Rhumb::GetUnmanaged()
+{
+    return gcnew System::IntPtr( const_cast<void*>(reinterpret_cast<const void*>(m_pRhumb)) );
+}
+
+//*****************************************************************************
 // RhumbLine functions
 //*****************************************************************************
 RhumbLine::!RhumbLine(void)
@@ -105,6 +170,19 @@ RhumbLine::RhumbLine( GeographicLib::RhumbLine* pRhumbLine )
 
 //*****************************************************************************
 void RhumbLine::Position(double s12,
+              [System::Runtime::InteropServices::Out] double% lat2,
+              [System::Runtime::InteropServices::Out] double% lon2,
+              [System::Runtime::InteropServices::Out] double% S12)
+{
+    double ilat2, ilon2, iS12;
+    m_pRhumbLine->Position( s12, ilat2, ilon2, iS12);
+    lat2 = ilat2;
+    lon2 = ilon2;
+    S12 = iS12;
+}
+
+//*****************************************************************************
+void RhumbLine::Position(double s12,
         [System::Runtime::InteropServices::Out] double% lat2,
         [System::Runtime::InteropServices::Out] double% lon2)
 {
@@ -115,6 +193,20 @@ void RhumbLine::Position(double s12,
 }
 
 //*****************************************************************************
+void RhumbLine::GenPosition(double s12, RhumbLine::mask outmask,
+                 [System::Runtime::InteropServices::Out] double% lat2,
+                 [System::Runtime::InteropServices::Out] double% lon2,
+                 [System::Runtime::InteropServices::Out] double% S12)
+{
+    double ilat2, ilon2, iS12;
+    unsigned int iMask = (unsigned int)outmask;
+    m_pRhumbLine->GenPosition( s12, iMask, ilat2, ilon2, iS12);
+    lat2 = ilat2;
+    lon2 = ilon2;
+    S12 = iS12;
+}
+
+//*****************************************************************************
 double RhumbLine::Latitude::get()
 {
     return m_pRhumbLine->Latitude();
diff --git a/dotnet/NETGeographicLib/Rhumb.h b/dotnet/NETGeographicLib/Rhumb.h
index 33135c5..84ee262 100644
--- a/dotnet/NETGeographicLib/Rhumb.h
+++ b/dotnet/NETGeographicLib/Rhumb.h
@@ -23,17 +23,24 @@ namespace NETGeographicLib {
    *
    * The path of constant azimuth between two points on a ellipsoid at (\e
    * lat1, \e lon1) and (\e lat2, \e lon2) is called the rhumb line (also
-   * called the loxodrome).  Its length is \e s12 and its azimuth is \e azi12
-   * and \e azi2.  (The azimuth is the heading measured clockwise from north.)
+   * called the loxodrome).  Its length is \e s12 and its azimuth is \e azi12.
+   * (The azimuth is the heading measured clockwise from north.)
    *
    * Given \e lat1, \e lon1, \e azi12, and \e s12, we can determine \e lat2,
    * and \e lon2.  This is the \e direct rhumb problem and its solution is
    * given by the function Rhumb::Direct.
    *
    * Given \e lat1, \e lon1, \e lat2, and \e lon2, we can determine \e azi12
-   * and \e s12.  This is the \e inverse rhumb problem, whose solution is
-   * given by Rhumb::Inverse.  This finds the shortest such rhumb line, i.e.,
-   * the one that wraps no more than half way around the earth .
+   * and \e s12.  This is the \e inverse rhumb problem, whose solution is given
+   * by Rhumb::Inverse.  This finds the shortest such rhumb line, i.e., the one
+   * that wraps no more than half way around the earth.  If the end points are
+   * on opposite meridians, there are two shortest rhumb lines and the
+   * east-going one is chosen.
+   *
+   * These routines also optionally calculate the area under the rhumb line, \e
+   * S12.  This is the area, measured counter-clockwise, of the rhumb line
+   * quadrilateral with corners (<i>lat1</i>,<i>lon1</i>), (0,<i>lon1</i>),
+   * (0,<i>lon2</i>), and (<i>lat2</i>,<i>lon2</i>).
    *
    * Note that rhumb lines may be appreciably longer (up to 50%) than the
    * corresponding Geodesic.  For example the distance between London Heathrow
@@ -42,6 +49,8 @@ namespace NETGeographicLib {
    *
    * For more information on rhumb lines see \ref rhumb.
    *
+   * For more information on rhumb lines see \ref rhumb.
+   *
    * C# Example:
    * \include example-Rhumb.cs
    * Managed C++ Example:
@@ -61,6 +70,53 @@ namespace NETGeographicLib {
     // The finalizer destroys m_pRhumb when this object is destroyed.
     !Rhumb(void);
   public:
+    /**
+     * Bit masks for what calculations to do.  They specify which results to
+     * return in the general routines Rhumb::GenDirect and Rhumb::GenInverse
+     * routines.  RhumbLine::mask is a duplication of this enum.
+     **********************************************************************/
+    enum class mask {
+      /**
+       * No output.
+       * @hideinitializer
+       **********************************************************************/
+      NONE          = 0U,
+      /**
+       * Calculate latitude \e lat2.
+       * @hideinitializer
+       **********************************************************************/
+      LATITUDE      = 1U<<7,
+      /**
+       * Calculate longitude \e lon2.
+       * @hideinitializer
+       **********************************************************************/
+      LONGITUDE     = 1U<<8,
+      /**
+       * Calculate azimuth \e azi12.
+       * @hideinitializer
+       **********************************************************************/
+      AZIMUTH       = 1U<<9,
+      /**
+       * Calculate distance \e s12.
+       * @hideinitializer
+       **********************************************************************/
+      DISTANCE      = 1U<<10,
+      /**
+       * Calculate area \e S12.
+       * @hideinitializer
+       **********************************************************************/
+      AREA          = 1U<<14,
+      /**
+       * Do not wrap the \e lon2 in the direct calculation.
+       * @hideinitializer
+       **********************************************************************/
+      LONG_NOWRAP   = 1U<<15,
+      /**
+       * Calculate everything.  (LONG_NOWRAP is not included in this mask.)
+       * @hideinitializer
+       **********************************************************************/
+      ALL           = 0x7F80U,
+    };
 
     /**
      * Constructor for a ellipsoid with
@@ -85,7 +141,35 @@ namespace NETGeographicLib {
     ~Rhumb() { this->!Rhumb(); }
 
     /**
-     * Solve the direct rhumb problem.
+     * Solve the direct rhumb problem returning also the area.
+     *
+     * @param[in] lat1 latitude of point 1 (degrees).
+     * @param[in] lon1 longitude of point 1 (degrees).
+     * @param[in] azi12 azimuth of the rhumb line (degrees).
+     * @param[in] s12 distance between point 1 and point 2 (meters); it can be
+     *   negative.
+     * @param[out] lat2 latitude of point 2 (degrees).
+     * @param[out] lon2 longitude of point 2 (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
+     *
+     * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
+     * azi12 should be in the range [−540°, 540°).  The value of
+     * \e lon2 returned is in the range [−180°, 180°).
+     *
+     * If point 1 is a pole, the cosine of its latitude is taken to be
+     * 1/ε<sup>2</sup> (where ε is 2<sup>-52</sup>).  This
+     * position, which is extremely close to the actual pole, allows the
+     * calculation to be carried out in finite terms.  If \e s12 is large
+     * enough that the rhumb line crosses a pole, the longitude of point 2
+     * is indeterminate (a NaN is returned for \e lon2 and \e S12).
+     **********************************************************************/
+    void Direct(double lat1, double lon1, double azi12, double s12,
+                [System::Runtime::InteropServices::Out] double% lat2,
+                [System::Runtime::InteropServices::Out] double% lon2,
+                [System::Runtime::InteropServices::Out] double% S12);
+
+    /**
+     * Solve the direct rhumb problem without the area.
      *
      * @param[in] lat1 latitude of point 1 (degrees).
      * @param[in] lon1 longitude of point 1 (degrees).
@@ -112,7 +196,70 @@ namespace NETGeographicLib {
                 [System::Runtime::InteropServices::Out] double% lon2);
 
     /**
-     * Solve the inverse rhumb problem.
+     * The general direct rhumb problem.  Rhumb::Direct is defined in terms
+     * of this function.
+     *
+     * @param[in] lat1 latitude of point 1 (degrees).
+     * @param[in] lon1 longitude of point 1 (degrees).
+     * @param[in] azi12 azimuth of the rhumb line (degrees).
+     * @param[in] s12 distance between point 1 and point 2 (meters); it can be
+     *   negative.
+     * @param[in] outmask a bitor'ed combination of Rhumb::mask values
+     *   specifying which of the following parameters should be set.
+     * @param[out] lat2 latitude of point 2 (degrees).
+     * @param[out] lon2 longitude of point 2 (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
+     *
+     * The Rhumb::mask values possible for \e outmask are
+     * - \e outmask |= Rhumb.LATITUDE for the latitude \e lat2;
+     * - \e outmask |= Rhumb.LONGITUDE for the latitude \e lon2;
+     * - \e outmask |= Rhumb.AREA for the area \e S12;
+     * - \e outmask |= Rhumb:.ALL for all of the above;
+     * - \e outmask |= Rhumb.LONG_NOWRAP stops the returned value of \e
+     *   lon2 being wrapped into the range [−180°, 180°).
+     * .
+     * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+     * indicates how many times the rhumb line wrapped around the ellipsoid.
+     * Because \e lon2 might be outside the normal allowed range for
+     * longitudes, [−540°, 540°), be sure to normalize it with
+     * Math::AngNormalize2 before using it in other GeographicLib calls.
+     **********************************************************************/
+    void GenDirect(double lat1, double lon1, double azi12, double s12,
+                   Rhumb::mask outmask,
+                   [System::Runtime::InteropServices::Out] double% lat2,
+                   [System::Runtime::InteropServices::Out] double% lon2,
+                   [System::Runtime::InteropServices::Out] double% S12);
+
+    /**
+     * Solve the inverse rhumb problem returning also the area.
+     *
+     * @param[in] lat1 latitude of point 1 (degrees).
+     * @param[in] lon1 longitude of point 1 (degrees).
+     * @param[in] lat2 latitude of point 2 (degrees).
+     * @param[in] lon2 longitude of point 2 (degrees).
+     * @param[out] s12 rhumb distance between point 1 and point 2 (meters).
+     * @param[out] azi12 azimuth of the rhumb line (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
+     *
+     * The shortest rhumb line is found.  If the end points are on opposite
+     * meridians, there are two shortest rhumb lines and the east-going one is
+     * chosen.  \e lat1 and \e lat2 should be in the range [−90°,
+     * 90°]; \e lon1 and \e lon2 should be in the range [−540°,
+     * 540°).  The value of \e azi12 returned is in the range
+     * [−180°, 180°).
+     *
+     * If either point is a pole, the cosine of its latitude is taken to be
+     * 1/ε<sup>2</sup> (where ε is 2<sup>-52</sup>).  This
+     * position, which is extremely close to the actual pole, allows the
+     * calculation to be carried out in finite terms.
+     **********************************************************************/
+    void Inverse(double lat1, double lon1, double lat2, double lon2,
+                 [System::Runtime::InteropServices::Out] double% s12,
+                 [System::Runtime::InteropServices::Out] double% azi12,
+                 [System::Runtime::InteropServices::Out] double% S12);
+
+    /**
+     * Solve the inverse rhumb problem without the area.
      *
      * @param[in] lat1 latitude of point 1 (degrees).
      * @param[in] lon1 longitude of point 1 (degrees).
@@ -136,6 +283,32 @@ namespace NETGeographicLib {
                  [System::Runtime::InteropServices::Out] double% azi12);
 
     /**
+     * The general inverse rhumb problem.  Rhumb::Inverse is defined in terms
+     * of this function.
+     *
+     * @param[in] lat1 latitude of point 1 (degrees).
+     * @param[in] lon1 longitude of point 1 (degrees).
+     * @param[in] lat2 latitude of point 2 (degrees).
+     * @param[in] lon2 longitude of point 2 (degrees).
+     * @param[in] outmask a bitor'ed combination of Rhumb::mask values
+     *   specifying which of the following parameters should be set.
+     * @param[out] s12 rhumb distance between point 1 and point 2 (meters).
+     * @param[out] azi12 azimuth of the rhumb line (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
+     *
+     * The Rhumb::mask values possible for \e outmask are
+     * - \e outmask |= Rhumb::DISTANCE for the latitude \e s12;
+     * - \e outmask |= Rhumb::AZIMUTH for the latitude \e azi12;
+     * - \e outmask |= Rhumb::AREA for the area \e S12;
+     * - \e outmask |= Rhumb::ALL for all of the above;
+     **********************************************************************/
+    void GenInverse(double lat1, double lon1, double lat2, double lon2,
+                    Rhumb::mask outmask,
+                    [System::Runtime::InteropServices::Out] double% s12,
+                    [System::Runtime::InteropServices::Out] double% azi12,
+                    [System::Runtime::InteropServices::Out] double% S12);
+
+    /**
      * Set up to compute several points on a single rhumb line.
      *
      * @param[in] lat1 latitude of point 1 (degrees).
@@ -170,6 +343,18 @@ namespace NETGeographicLib {
     property double Flattening { double get(); }
 
     /**
+     * @return the  area of the ellipsoid.
+     **********************************************************************/
+    property double EllipsoidArea { double get(); }
+
+    /**
+     * %return The unmanaged pointer to the GeographicLib::Geodesic.
+     *
+     * This function is for internal use only.
+     **********************************************************************/
+    System::IntPtr^ GetUnmanaged();
+
+    /**
      * A global instantiation of Rhumb with the parameters for the WGS84
      * ellipsoid.
      **********************************************************************/
@@ -203,6 +388,48 @@ namespace NETGeographicLib {
     // The finalizer destroys m_pRhumbLine when this object is destroyed.
     !RhumbLine(void);
   public:
+    enum class mask {
+      /**
+       * No output.
+       * @hideinitializer
+       **********************************************************************/
+      NONE          = 0, //NETGeographicLib::Rhumb::NONE,
+      /**
+       * Calculate latitude \e lat2.
+       * @hideinitializer
+       **********************************************************************/
+      LATITUDE      = 1U<<7, //Rhumb::LATITUDE,
+      /**
+       * Calculate longitude \e lon2.
+       * @hideinitializer
+       **********************************************************************/
+      LONGITUDE     = 1U<<8, //Rhumb::LONGITUDE,
+      /**
+       * Calculate azimuth \e azi12.
+       * @hideinitializer
+       **********************************************************************/
+      AZIMUTH       = 1U<<9, //Rhumb::AZIMUTH,
+      /**
+       * Calculate distance \e s12.
+       * @hideinitializer
+       **********************************************************************/
+      DISTANCE      = 1U<<10, //Rhumb::DISTANCE,
+      /**
+       * Calculate area \e S12.
+       * @hideinitializer
+       **********************************************************************/
+      AREA          = 1U<<14, //Rhumb::AREA,
+      /**
+       * Do wrap the \e lon2 in the direct calculation.
+       * @hideinitializer
+       **********************************************************************/
+      LONG_NOWRAP   = 1U<<14, //Rhumb::LONG_NOWRAP,
+      /**
+       * Calculate everything.  (LONG_NOWRAP is not included in this mask.)
+       * @hideinitializer
+       **********************************************************************/
+      ALL           = 0x7F80U, //Rhumb::ALL,
+    };
     /**
      * \brief Constructor.
      *
@@ -218,6 +445,28 @@ namespace NETGeographicLib {
 
     /**
      * Compute the position of point 2 which is a distance \e s12 (meters) from
+     * point 1.  The area is also computed.
+     *
+     * @param[in] s12 distance between point 1 and point 2 (meters); it can be
+     *   negative.
+     * @param[out] lat2 latitude of point 2 (degrees).
+     * @param[out] lon2 longitude of point 2 (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
+     *
+     * The value of \e lon2 returned is in the range [−180°,
+     * 180°).
+     *
+     * If \e s12 is large enough that the rhumb line crosses a pole, the
+     * longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and
+     * \e S12).
+     **********************************************************************/
+    void Position(double s12,
+        [System::Runtime::InteropServices::Out] double% lat2,
+        [System::Runtime::InteropServices::Out] double% lon2,
+        [System::Runtime::InteropServices::Out] double% S12);
+
+    /**
+     * Compute the position of point 2 which is a distance \e s12 (meters) from
      * point 1.
      *
      * @param[in] s12 distance between point 1 and point 2 (meters); it can be
@@ -235,6 +484,41 @@ namespace NETGeographicLib {
                   [System::Runtime::InteropServices::Out] double% lat2,
                   [System::Runtime::InteropServices::Out] double% lon2);
 
+    /**
+     * The general position routine.  RhumbLine::Position is defined in term so
+     * this function.
+     *
+     * @param[in] s12 distance between point 1 and point 2 (meters); it can be
+     *   negative.
+     * @param[in] outmask a bitor'ed combination of Rhumb::mask values
+     *   specifying which of the following parameters should be set.
+     * @param[out] lat2 latitude of point 2 (degrees).
+     * @param[out] lon2 longitude of point 2 (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
+     *
+     * The Rhumb::mask values possible for \e outmask are
+     * - \e outmask |= Rhumb::LATITUDE for the latitude \e lat2;
+     * - \e outmask |= Rhumb::LONGITUDE for the latitude \e lon2;
+     * - \e outmask |= Rhumb::AREA for the area \e S12;
+     * - \e outmask |= Rhumb::ALL for all of the above;
+     * - \e outmask |= Rhumb::LONG_NOWRAP stops the returned value of \e
+     *   lon2 being wrapped into the range [−180°, 180°).
+     * .
+     * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+     * indicates how many times the rhumb line wrapped around the ellipsoid.
+     * Because \e lon2 might be outside the normal allowed range for
+     * longitudes, [−540°, 540°), be sure to normalize it with
+     * Math::AngNormalize2 before using it in other GeographicLib calls.
+     *
+     * If \e s12 is large enough that the rhumb line crosses a pole, the
+     * longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and
+     * \e S12).
+     **********************************************************************/
+    void GenPosition(double s12, RhumbLine::mask outmask,
+                     [System::Runtime::InteropServices::Out] double% lat2,
+                     [System::Runtime::InteropServices::Out] double% lon2,
+                     [System::Runtime::InteropServices::Out] double% S12);
+
     /** \name Inspector functions
      **********************************************************************/
     ///@{
diff --git a/dotnet/Projections/GeodesicPanel.cs b/dotnet/Projections/GeodesicPanel.cs
index 24e78ee..89d7bad 100644
--- a/dotnet/Projections/GeodesicPanel.cs
+++ b/dotnet/Projections/GeodesicPanel.cs
@@ -369,7 +369,7 @@ namespace Projections
                     faz != finalAzimuth || frd != reducedLength || fm12 != M12 || fm21 != M21)
                     throw new Exception("Geodesic.Direct #5 failed");
                 double outd = 0.0;
-                fad = g.GenDirect(32.0, -86.0, 45.0, false, 20000.0, Mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
+                fad = g.GenDirect(32.0, -86.0, 45.0, false, 20000.0, Geodesic.mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
                 if (fad != arcDistance || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || frd != reducedLength || fm12 != M12 || fm21 != M21 ||
                     outd != 20000.0 || fs12 != S12)
@@ -394,7 +394,7 @@ namespace Projections
                 if (flat != finalLatitude || flon != finalLongitude || faz != finalAzimuth ||
                     fad != arcDistance || fm12 != M12 || fm21 != M21)
                     throw new Exception("Geodesic.ArcDirect #5 failed");
-                fad = g.GenDirect(32.0, -86.0, 45.0, true, 1.0, Mask.ALL, out flat, out flon,
+                fad = g.GenDirect(32.0, -86.0, 45.0, true, 1.0, Geodesic.mask.ALL, out flat, out flon,
                     out faz, out outd, out frd, out fm12, out fm21, out fs12);
                 if (outd != arcDistance || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || frd != reducedLength || fm12 != M12 || fm21 != M21 ||
@@ -449,7 +449,7 @@ namespace Projections
                 if (fad != arcDistance || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || fm12 != M12 || fm21 != M21 || frd != reducedLength )
                     throw new Exception("GeodesicLine.Position #5 failed");
-                fad = gl.GenPosition(false, 10000.0, Mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
+                fad = gl.GenPosition(false, 10000.0, GeodesicLine.mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
                 if (fad != arcDistance || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || outd != 10000.0 || fm12 != M12 || fm21 != M21 ||
                     frd != reducedLength || fs12 != S12 )
@@ -478,7 +478,7 @@ namespace Projections
                 if (flat != finalLatitude || flon != finalLongitude || faz != finalAzimuth ||
                     outd != distance || fm12 != M12 || fm21 != M21 || frd != reducedLength)
                     throw new Exception("GeodesicLine.ArcPosition #6 failed");
-                fad = gl.GenPosition(true, 1.0, Mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
+                fad = gl.GenPosition(true, 1.0, GeodesicLine.mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
                 if (fad != 1.0 || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || outd != distance || fm12 != M12 || fm21 != M21 ||
                     frd != reducedLength || fs12 != S12)
@@ -508,7 +508,7 @@ namespace Projections
                 if (fad != arcDistance || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || frd != reducedLength || fm12 != M12 || fm21 != M21)
                     throw new Exception("GeodesicExact.Direct #5 failed");
-                fad = ge.GenDirect(32.0, -86.0, 45.0, false, 20000.0, Mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
+                fad = ge.GenDirect(32.0, -86.0, 45.0, false, 20000.0, GeodesicExact.mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
                 if (fad != arcDistance || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || frd != reducedLength || fm12 != M12 || fm21 != M21 ||
                     outd != 20000.0 || fs12 != S12)
@@ -533,7 +533,7 @@ namespace Projections
                 if (flat != finalLatitude || flon != finalLongitude || faz != finalAzimuth ||
                     fad != arcDistance || fm12 != M12 || fm21 != M21)
                     throw new Exception("GeodesicExact.ArcDirect #5 failed");
-                fad = ge.GenDirect(32.0, -86.0, 45.0, true, 1.0, Mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
+                fad = ge.GenDirect(32.0, -86.0, 45.0, true, 1.0, GeodesicExact.mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
                 if (outd != arcDistance || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || frd != reducedLength || fm12 != M12 || fm21 != M21 ||
                     fad != 1.0 || fs12 != S12)
@@ -586,7 +586,7 @@ namespace Projections
                 if (fad != arcDistance || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || fm12 != M12 || fm21 != M21 || frd != reducedLength)
                     throw new Exception("GeodesicLineExact.Position #5 failed");
-                fad = gle.GenPosition(false, 10000.0, Mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
+                fad = gle.GenPosition(false, 10000.0, GeodesicLineExact.mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
                 if (fad != arcDistance || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || outd != 10000.0 || fm12 != M12 || fm21 != M21 ||
                     frd != reducedLength || fs12 != S12)
@@ -615,7 +615,7 @@ namespace Projections
                 if (flat != finalLatitude || flon != finalLongitude || faz != finalAzimuth ||
                     outd != distance || fm12 != M12 || fm21 != M21 || frd != reducedLength)
                     throw new Exception("GeodesicLineExact.ArcPosition #6 failed");
-                fad = gle.GenPosition(true, 1.0, Mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
+                fad = gle.GenPosition(true, 1.0, GeodesicLineExact.mask.ALL, out flat, out flon, out faz, out outd, out frd, out fm12, out fm21, out fs12);
                 if (fad != 1.0 || flat != finalLatitude || flon != finalLongitude ||
                     faz != finalAzimuth || outd != distance || fm12 != M12 || fm21 != M21 ||
                     frd != reducedLength || fs12 != S12)
diff --git a/dotnet/Projections/MiscPanel.cs b/dotnet/Projections/MiscPanel.cs
index 0fcb990..1a5385d 100644
--- a/dotnet/Projections/MiscPanel.cs
+++ b/dotnet/Projections/MiscPanel.cs
@@ -90,7 +90,6 @@ namespace Projections
                 DMS.Flag ind;
                 int len;
                 string tmp;
-                DMS.Decode("34.245");
                 DMS.Decode("34d22\'34.567\"", out ind);
                 DMS.Decode(-86.0, 32.0, 34.214);
                 DMS.DecodeAngle("-67.4532");
diff --git a/dotnet/Projections/PolyPanel.cs b/dotnet/Projections/PolyPanel.cs
index 6450648..b26f9cc 100644
--- a/dotnet/Projections/PolyPanel.cs
+++ b/dotnet/Projections/PolyPanel.cs
@@ -128,6 +128,15 @@ namespace Projections
                 p2.TestEdge(-70.0, 5000.0, false, false, out perim, out area);
                 p2.TestPoint(31.0, -86.5, false, false, out perim, out area);
 
+                PolygonAreaRhumb p3 = new PolygonAreaRhumb(Rhumb.WGS84(), false);
+                p3.AddPoint(32.0, -86.0);
+                p3.AddEdge(20.0, 10000.0);
+                p3.AddEdge(-45.0, 10000.0);
+                p3.CurrentPoint(out lat, out lon);
+                p3.Compute(false, false, out perim, out area);
+                p3.TestEdge(-70.0, 5000.0, false, false, out perim, out area);
+                p3.TestPoint(31.0, -86.5, false, false, out perim, out area);
+
                 MessageBox.Show("No errors detected", "OK", MessageBoxButtons.OK, MessageBoxIcon.Information);
             }
             catch (Exception xcpt)
diff --git a/dotnet/Projections/RhumbPanel.Designer.cs b/dotnet/Projections/RhumbPanel.Designer.cs
index 66b56c6..7bc8514 100644
--- a/dotnet/Projections/RhumbPanel.Designer.cs
+++ b/dotnet/Projections/RhumbPanel.Designer.cs
@@ -46,6 +46,7 @@ namespace Projections
             this.m_pointsView = new System.Windows.Forms.ListView();
             this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
             this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this.button3 = new System.Windows.Forms.Button();
             this.SuspendLayout();
             //
             // label1
@@ -196,10 +197,21 @@ namespace Projections
             this.columnHeader2.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
             this.columnHeader2.Width = 120;
             //
+            // button3
+            //
+            this.button3.Location = new System.Drawing.Point(309, 177);
+            this.button3.Name = "button3";
+            this.button3.Size = new System.Drawing.Size(75, 23);
+            this.button3.TabIndex = 16;
+            this.button3.Text = "Validate";
+            this.button3.UseVisualStyleBackColor = true;
+            this.button3.Click += new System.EventHandler(this.OnValidate);
+            //
             // RhumbPanel
             //
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.button3);
             this.Controls.Add(this.m_pointsView);
             this.Controls.Add(this.label7);
             this.Controls.Add(this.button2);
@@ -243,5 +255,6 @@ namespace Projections
         private System.Windows.Forms.ListView m_pointsView;
         private System.Windows.Forms.ColumnHeader columnHeader1;
         private System.Windows.Forms.ColumnHeader columnHeader2;
+        private System.Windows.Forms.Button button3;
     }
 }
diff --git a/dotnet/Projections/RhumbPanel.cs b/dotnet/Projections/RhumbPanel.cs
index 91e80bf..f8ce366 100644
--- a/dotnet/Projections/RhumbPanel.cs
+++ b/dotnet/Projections/RhumbPanel.cs
@@ -77,5 +77,44 @@ namespace Projections
                 m_pointsView.Items.Add(item);
             }
         }
+
+        private void OnValidate(object sender, EventArgs e)
+        {
+            try
+            {
+                Rhumb r = new Rhumb(NETGeographicLib.Constants.WGS84.MajorRadius, NETGeographicLib.Constants.WGS84.Flattening, true);
+                double lat1 = 32.0, lon1 = -86.0, azi12 = 45.0, s12 = 5000.0;
+                double lat2, lon2, _s12, _azi12, Area, _Area;
+                r.Direct(lat1, lon1, azi12, s12, out lat2, out lon2);
+                r.Inverse(lat1, lon1, lat2, lon2, out _s12, out _azi12);
+                if ( Test(s12,_s12) || Test(azi12,_azi12))
+                    throw new Exception(String.Format("Inverse != Direct: S12 -> {0}, {1}, azi12 -> {2}, {3}", s12, _s12, azi12, _azi12));
+                r.Direct(lat1, lon1, azi12, s12, out lat2, out lon2, out Area);
+                r.Inverse(lat1, lon1, lat2, lon2, out _s12, out _azi12, out _Area);
+                if (Test(s12, _s12) || Test(azi12, _azi12) || Test(Area,_Area))
+                    throw new Exception(String.Format("Inverse != Direct: S12 -> {0}, {1}, azi12 -> {2}, {3}, Area -> {4}, {5}", s12, _s12, azi12, _azi12, Area, _Area));
+
+                double _lat2, _lon2;
+                RhumbLine l = r.Line(lat1, lon1, azi12);
+                l.Position(s12, out _lat2, out _lon2);
+                if (Test(lat2,_lat2) || Test(lon2, _lon2))
+                    throw new Exception(String.Format("Latitude -> {0}, {1}, Longitude -> {2}, {3}", lat2, _lat2, lon2, _lon2));
+                l.Position(s12, out _lat2, out _lon2, out _Area);
+                if (Test(lat2, _lat2) || Test(lon2, _lon2) || Test(Area, _Area))
+                    throw new Exception(String.Format("Latitude -> {0}, {1}, Longitude -> {2}, {3}, Area -> {4}, {5}", lat2, _lat2, lon2, _lon2, Area, _Area));
+
+                MessageBox.Show("No exceptions detected", "OK", MessageBoxButtons.OK, MessageBoxIcon.Information);
+            }
+            catch ( Exception xcpt )
+            {
+                MessageBox.Show( xcpt.Message, "Exception thrown", MessageBoxButtons.OK, MessageBoxIcon.Error );
+            }
+        }
+
+        bool Test(double a, double b)
+        {
+            double delta = a != 0.0 ? Math.Abs((a - b) / a) : Math.Abs(a - b);
+            return delta > 1.0e-12;
+        }
     }
 }
diff --git a/dotnet/examples/ManagedCPP/CMakeLists.txt b/dotnet/examples/ManagedCPP/CMakeLists.txt
index 00c3fcf..44e3334 100644
--- a/dotnet/examples/ManagedCPP/CMakeLists.txt
+++ b/dotnet/examples/ManagedCPP/CMakeLists.txt
@@ -23,6 +23,12 @@ endforeach ()
 string (REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
 string (REPLACE "/EHsc" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
 
+if (MSVC AND NOT MSVC_VERSION GREATER 1600)
+  # Disable "already imported" and "unsupported default parameter"
+  # warnings with VS 10
+  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4945 /wd4564")
+endif ()
+
 add_custom_target (netexamples DEPENDS ${EXAMPLES})
 
 get_target_property (_LIBTYPE ${PROJECT_LIBRARIES} TYPE)
diff --git a/dotnet/examples/ManagedCPP/example-GeodesicLine.cpp b/dotnet/examples/ManagedCPP/example-GeodesicLine.cpp
index a57b903..799ce9a 100644
--- a/dotnet/examples/ManagedCPP/example-GeodesicLine.cpp
+++ b/dotnet/examples/ManagedCPP/example-GeodesicLine.cpp
@@ -14,8 +14,8 @@ int main(array<System::String ^> ^/*args*/)
         GeodesicLine^ line = gcnew GeodesicLine(geod, lat1, lon1, azi1, Mask::ALL);
         // Alternatively
         // const GeographicLib::GeodesicLine line = geod.Line(lat1, lon1, azi1);
-        double ds = 500e3;          // Nominal distance between points = 500 km
-        int num = int(Math::Ceiling(s12 / ds)); // The number of intervals
+        double ds0 = 500e3;     // Nominal distance between points = 500 km
+        int num = int(Math::Ceiling(s12 / ds0)); // The number of intervals
         {
             // Use intervals of equal length
             double ds = s12 / num;
diff --git a/dotnet/examples/ManagedCPP/example-GeodesicLineExact.cpp b/dotnet/examples/ManagedCPP/example-GeodesicLineExact.cpp
index 54a8fc7..5621108 100644
--- a/dotnet/examples/ManagedCPP/example-GeodesicLineExact.cpp
+++ b/dotnet/examples/ManagedCPP/example-GeodesicLineExact.cpp
@@ -14,8 +14,8 @@ int main(array<System::String ^> ^/*args*/)
         GeodesicLineExact^ line = gcnew GeodesicLineExact(geod, lat1, lon1, azi1, Mask::ALL);
         // Alternatively
         // const GeographicLib::GeodesicLine line = geod.Line(lat1, lon1, azi1);
-        double ds = 500e3;          // Nominal distance between points = 500 km
-        int num = int(Math::Ceiling(s12 / ds)); // The number of intervals
+        double ds0 = 500e3;     // Nominal distance between points = 500 km
+        int num = int(Math::Ceiling(s12 / ds0)); // The number of intervals
         {
             // Use intervals of equal length
             double ds = s12 / num;
diff --git a/dotnet/examples/ManagedCPP/example-RhumbLine.cpp b/dotnet/examples/ManagedCPP/example-RhumbLine.cpp
index 50e2c83..889d014 100644
--- a/dotnet/examples/ManagedCPP/example-RhumbLine.cpp
+++ b/dotnet/examples/ManagedCPP/example-RhumbLine.cpp
@@ -15,8 +15,8 @@ int main(array<System::String ^> ^/*args*/)
     RhumbLine^ line = rhumb->Line(lat1, lon1, azi12);
     // Alternatively
     // const GeographicLib::RhumbLine line = rhumb.Line(lat1, lon1, azi1);
-    double ds = 500e3;          // Nominal distance between points = 500 km
-    int num = int(Math::Ceiling(s12 / ds)); // The number of intervals
+    double ds0 = 500e3;         // Nominal distance between points = 500 km
+    int num = int(Math::Ceiling(s12 / ds0)); // The number of intervals
     {
       // Use intervals of equal length
       double ds = s12 / num;
diff --git a/examples/example-GeodesicLine.cpp b/examples/example-GeodesicLine.cpp
index 438696c..0f31587 100644
--- a/examples/example-GeodesicLine.cpp
+++ b/examples/example-GeodesicLine.cpp
@@ -24,8 +24,8 @@ int main() {
     const GeographicLib::GeodesicLine line(geod, lat1, lon1, azi1);
     // Alternatively
     // const GeographicLib::GeodesicLine line = geod.Line(lat1, lon1, azi1);
-    double ds = 500e3;          // Nominal distance between points = 500 km
-    int num = int(ceil(s12 / ds)); // The number of intervals
+    double ds0 = 500e3;             // Nominal distance between points = 500 km
+    int num = int(ceil(s12 / ds0)); // The number of intervals
     cout << fixed << setprecision(3);
     {
       // Use intervals of equal length
diff --git a/examples/example-GeodesicLineExact.cpp b/examples/example-GeodesicLineExact.cpp
index 4a17471..5567ad3 100644
--- a/examples/example-GeodesicLineExact.cpp
+++ b/examples/example-GeodesicLineExact.cpp
@@ -24,8 +24,8 @@ int main() {
     const GeographicLib::GeodesicLineExact line(geod, lat1, lon1, azi1);
     // Alternatively
     // const GeographicLib::GeodesicLineExact line = geod.Line(lat1,lon1,azi1);
-    double ds = 500e3;          // Nominal distance between points = 500 km
-    int num = int(ceil(s12 / ds)); // The number of intervals
+    double ds0 = 500e3;             // Nominal distance between points = 500 km
+    int num = int(ceil(s12 / ds0)); // The number of intervals
     cout << fixed << setprecision(3);
     {
       // Use intervals of equal length
diff --git a/examples/example-RhumbLine.cpp b/examples/example-RhumbLine.cpp
index cf33c65..80b0729 100644
--- a/examples/example-RhumbLine.cpp
+++ b/examples/example-RhumbLine.cpp
@@ -23,8 +23,8 @@ int main() {
     const GeographicLib::RhumbLine line = rhumb.Line(lat1, lon1, azi12);
     // Alternatively
     // const GeographicLib::RhumbLine line = rhumb.Line(lat1, lon1, azi1);
-    double ds = 500e3;          // Nominal distance between points = 500 km
-    int num = int(ceil(s12 / ds)); // The number of intervals
+    double ds0 = 500e3;             // Nominal distance between points = 500 km
+    int num = int(ceil(s12 / ds0)); // The number of intervals
     cout << fixed << setprecision(3);
     {
       // Use intervals of equal length
diff --git a/include/GeographicLib/Config.h b/include/GeographicLib/Config.h
index c2eaf69..db6f773 100644
--- a/include/GeographicLib/Config.h
+++ b/include/GeographicLib/Config.h
@@ -1,8 +1,8 @@
 // This will be overwritten by ./configure
 
-#define GEOGRAPHICLIB_VERSION_STRING "1.38"
+#define GEOGRAPHICLIB_VERSION_STRING "1.39"
 #define GEOGRAPHICLIB_VERSION_MAJOR 1
-#define GEOGRAPHICLIB_VERSION_MINOR 38
+#define GEOGRAPHICLIB_VERSION_MINOR 39
 #define GEOGRAPHICLIB_VERSION_PATCH 0
 
 // Undefine HAVE_LONG_DOUBLE if this type is unknown to the compiler
diff --git a/include/GeographicLib/Constants.hpp b/include/GeographicLib/Constants.hpp
index 73ef374..0bd2af8 100644
--- a/include/GeographicLib/Constants.hpp
+++ b/include/GeographicLib/Constants.hpp
@@ -34,9 +34,7 @@
  * A compile-time assert.  Use C++11 static_assert, if available.
  **********************************************************************/
 #if !defined(GEOGRAPHICLIB_STATIC_ASSERT)
-#  if __cplusplus >= 201103
-#    define GEOGRAPHICLIB_STATIC_ASSERT static_assert
-#  elif defined(__GXX_EXPERIMENTAL_CXX0X__)
+#  if __cplusplus >= 201103 || defined(__GXX_EXPERIMENTAL_CXX0X__)
 #    define GEOGRAPHICLIB_STATIC_ASSERT static_assert
 #  elif defined(_MSC_VER) && _MSC_VER >= 1600
 // For reference, here is a table of Visual Studio and _MSC_VER
@@ -50,6 +48,7 @@
 //   1600     vc10  (2010)
 //   1700     vc11  (2012)
 //   1800     vc12  (2013)
+//   1900     vc14
 #    define GEOGRAPHICLIB_STATIC_ASSERT static_assert
 #  else
 #    define GEOGRAPHICLIB_STATIC_ASSERT(cond,reason) \
diff --git a/include/GeographicLib/DMS.hpp b/include/GeographicLib/DMS.hpp
index 72b2ce4..eeb97ed 100644
--- a/include/GeographicLib/DMS.hpp
+++ b/include/GeographicLib/DMS.hpp
@@ -150,7 +150,7 @@ namespace GeographicLib {
      * <b>NOTE:</b> 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
-     * <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8</a> encoding.  (The
+     * <a href="https://en.wikipedia.org/wiki/UTF-8">UTF-8</a> encoding.  (The
      * JavaScript implementation of this class uses unicode natively, of
      * course.)
      *
diff --git a/include/GeographicLib/Geodesic.hpp b/include/GeographicLib/Geodesic.hpp
index 71507a9..47f99d7 100644
--- a/include/GeographicLib/Geodesic.hpp
+++ b/include/GeographicLib/Geodesic.hpp
@@ -82,7 +82,6 @@ namespace GeographicLib {
    *   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.
-
    * - <i>area</i>.  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
@@ -196,7 +195,9 @@ namespace GeographicLib {
       CAP_C3   = 1U<<3,
       CAP_C4   = 1U<<4,
       CAP_ALL  = 0x1FU,
+      CAP_MASK = CAP_ALL,
       OUT_ALL  = 0x7F80U,
+      OUT_MASK = 0xFF80U,       // Includes LONG_NOWRAP
     };
 
     static real SinCosSeries(bool sinp,
@@ -322,7 +323,13 @@ namespace GeographicLib {
        **********************************************************************/
       AREA          = 1U<<14 | CAP_C4,
       /**
-       * All capabilities, calculate everything.
+       * Do not wrap the \e lon2 in the direct calculation.
+       * @hideinitializer
+       **********************************************************************/
+      LONG_NOWRAP   = 1U<<15,
+      /**
+       * All capabilities, calculate everything.  (LONG_NOWRAP is not
+       * included in this mask.)
        * @hideinitializer
        **********************************************************************/
       ALL           = OUT_ALL| CAP_ALL,
@@ -620,13 +627,21 @@ namespace GeographicLib {
      * - \e outmask |= Geodesic::GEODESICSCALE for the geodesic scales \e
      *   M12 and \e M21;
      * - \e outmask |= Geodesic::AREA for the area \e S12;
-     * - \e outmask |= Geodesic::ALL for all of the above.
+     * - \e outmask |= Geodesic::ALL for all of the above;
+     * - \e outmask |= Geodesic::LONG_NOWRAP stops the returned value of \e
+     *   lon2 being wrapped into the range [−180°, 180°).
      * .
      * The function value \e a12 is always computed and returned and this
      * equals \e s12_a12 is \e arcmode is true.  If \e outmask includes
      * Geodesic::DISTANCE and \e arcmode is false, then \e s12 = \e s12_a12.
      * It is not necessary to include Geodesic::DISTANCE_IN in \e outmask; this
      * is automatically included is \e arcmode is false.
+     *
+     * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+     * indicates how many times the geodesic wrapped around the ellipsoid.
+     * Because \e lon2 might be outside the normal allowed range for
+     * longitudes, [−540°, 540°), be sure to normalize it with
+     * Math::AngNormalize2 before using it in other GeographicLib calls.
      **********************************************************************/
     Math::real GenDirect(real lat1, real lon1, real azi1,
                          bool arcmode, real s12_a12, unsigned outmask,
diff --git a/include/GeographicLib/GeodesicExact.hpp b/include/GeographicLib/GeodesicExact.hpp
index c60adfe..80573e4 100644
--- a/include/GeographicLib/GeodesicExact.hpp
+++ b/include/GeographicLib/GeodesicExact.hpp
@@ -95,7 +95,9 @@ namespace GeographicLib {
       CAP_H    = 1U<<3,
       CAP_C4   = 1U<<4,
       CAP_ALL  = 0x1FU,
+      CAP_MASK = CAP_ALL,
       OUT_ALL  = 0x7F80U,
+      OUT_MASK = 0xFF80U,       // Includes LONG_NOWRAP
     };
 
     static real CosSeries(real sinx, real cosx, const real c[], int n);
@@ -219,7 +221,13 @@ namespace GeographicLib {
        **********************************************************************/
       AREA          = 1U<<14 | CAP_C4,
       /**
-       * All capabilities, calculate everything.
+       * Do not wrap the \e lon2 in the direct calculation.
+       * @hideinitializer
+       **********************************************************************/
+      LONG_NOWRAP   = 1U<<15,
+      /**
+       * All capabilities, calculate everything.  (LONG_NOWRAP is not
+       * included in this mask.)
        * @hideinitializer
        **********************************************************************/
       ALL           = OUT_ALL| CAP_ALL,
@@ -517,13 +525,21 @@ namespace GeographicLib {
      * - \e outmask |= GeodesicExact::GEODESICSCALE for the geodesic scales \e
      *   M12 and \e M21;
      * - \e outmask |= GeodesicExact::AREA for the area \e S12;
-     * - \e outmask |= GeodesicExact::ALL for all of the above.
+     * - \e outmask |= GeodesicExact::ALL for all of the above;
+     * - \e outmask |= GeodesicExact::LONG_NOWRAP stops the returned value of
+     *   \e lon2 being wrapped into the range [−180°, 180°).
      * .
      * The function value \e a12 is always computed and returned and this
      * equals \e s12_a12 is \e arcmode is true.  If \e outmask includes
      * GeodesicExact::DISTANCE and \e arcmode is false, then \e s12 = \e
      * s12_a12.  It is not necessary to include GeodesicExact::DISTANCE_IN in
      * \e outmask; this is automatically included is \e arcmode is false.
+     *
+     * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+     * indicates how many times the geodesic wrapped around the ellipsoid.
+     * Because \e lon2 might be outside the normal allowed range for
+     * longitudes, [−540°, 540°), be sure to normalize it with
+     * Math::AngNormalize2 before using it in other GeographicLib calls.
      **********************************************************************/
     Math::real GenDirect(real lat1, real lon1, real azi1,
                          bool arcmode, real s12_a12, unsigned outmask,
diff --git a/include/GeographicLib/GeodesicLine.hpp b/include/GeographicLib/GeodesicLine.hpp
index 2660893..49df02b 100644
--- a/include/GeographicLib/GeodesicLine.hpp
+++ b/include/GeographicLib/GeodesicLine.hpp
@@ -2,7 +2,7 @@
  * \file GeodesicLine.hpp
  * \brief Header for GeographicLib::GeodesicLine class
  *
- * Copyright (c) Charles Karney (2009-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -84,7 +84,9 @@ namespace GeographicLib {
       CAP_C3   = Geodesic::CAP_C3,
       CAP_C4   = Geodesic::CAP_C4,
       CAP_ALL  = Geodesic::CAP_ALL,
+      CAP_MASK = Geodesic::CAP_MASK,
       OUT_ALL  = Geodesic::OUT_ALL,
+      OUT_MASK = Geodesic::OUT_MASK,
     };
   public:
 
@@ -145,7 +147,13 @@ namespace GeographicLib {
        **********************************************************************/
       AREA          = Geodesic::AREA,
       /**
-       * All capabilities, calculate everything.
+       * Do not wrap \e lon2 in the direct calculation.
+       * @hideinitializer
+       **********************************************************************/
+      LONG_NOWRAP   = Geodesic::LONG_NOWRAP,
+      /**
+       * All capabilities, calculate everything.  (LONG_NOWRAP is not
+       * included in this mask.)
        * @hideinitializer
        **********************************************************************/
       ALL           = Geodesic::ALL,
@@ -493,12 +501,20 @@ namespace GeographicLib {
      * - \e outmask |= GeodesicLine::GEODESICSCALE for the geodesic scales \e
      *   M12 and \e M21;
      * - \e outmask |= GeodesicLine::AREA for the area \e S12;
-     * - \e outmask |= GeodesicLine::ALL for all of the above.
+     * - \e outmask |= GeodesicLine::ALL for all of the above;
+     * - \e outmask |= GeodesicLine::LONG_NOWRAP stops the returned value of \e
+     *   lon2 being wrapped into the range [−180°, 180°).
      * .
      * Requesting a value which the GeodesicLine object is not capable of
      * computing is not an error; the corresponding argument will not be
      * altered.  Note, however, that the arc length is always computed and
      * returned as the function value.
+     *
+     * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+     * indicates how many times the geodesic wrapped around the ellipsoid.
+     * Because \e lon2 might be outside the normal allowed range for
+     * longitudes, [−540°, 540°), be sure to normalize it with
+     * Math::AngNormalize2 before using it in other GeographicLib calls.
      **********************************************************************/
     Math::real GenPosition(bool arcmode, real s12_a12, unsigned outmask,
                            real& lat2, real& lon2, real& azi2,
diff --git a/include/GeographicLib/GeodesicLineExact.hpp b/include/GeographicLib/GeodesicLineExact.hpp
index 364b6c1..26828f0 100644
--- a/include/GeographicLib/GeodesicLineExact.hpp
+++ b/include/GeographicLib/GeodesicLineExact.hpp
@@ -2,8 +2,8 @@
  * \file GeodesicLineExact.hpp
  * \brief Header for GeographicLib::GeodesicLineExact class
  *
- * Copyright (c) Charles Karney (2012) <charles at karney.com> and licensed under
- * the MIT/X11 License.  For more information, see
+ * Copyright (c) Charles Karney (2012-2014) <charles at karney.com> and licensed
+ * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
 
@@ -55,7 +55,9 @@ namespace GeographicLib {
       CAP_H    = GeodesicExact::CAP_H,
       CAP_C4   = GeodesicExact::CAP_C4,
       CAP_ALL  = GeodesicExact::CAP_ALL,
+      CAP_MASK = GeodesicExact::CAP_MASK,
       OUT_ALL  = GeodesicExact::OUT_ALL,
+      OUT_MASK = GeodesicExact::OUT_MASK,
     };
   public:
 
@@ -117,7 +119,13 @@ namespace GeographicLib {
        **********************************************************************/
       AREA          = GeodesicExact::AREA,
       /**
-       * All capabilities, calculate everything.
+       * Do not wrap \e lon2 in the direct calculation.
+       * @hideinitializer
+       **********************************************************************/
+      LONG_NOWRAP = GeodesicExact::LONG_NOWRAP,
+      /**
+       * All capabilities, calculate everything.  (LONG_NOWRAP is not
+       * included in this mask.)
        * @hideinitializer
        **********************************************************************/
       ALL           = GeodesicExact::ALL,
@@ -467,12 +475,20 @@ namespace GeographicLib {
      * - \e outmask |= GeodesicLineExact::GEODESICSCALE for the geodesic scales
      *   \e M12 and \e M21;
      * - \e outmask |= GeodesicLineExact::AREA for the area \e S12;
-     * - \e outmask |= GeodesicLine::ALL for all of the above.
+     * - \e outmask |= GeodesicLineExact::ALL for all of the above;
+     * - \e outmask |= GeodesicLineExact::LONG_NOWRAP stops the returned value
+     *   of \e lon2 being wrapped into the range [−180°, 180°).
      * .
      * Requesting a value which the GeodesicLineExact object is not capable of
      * computing is not an error; the corresponding argument will not be
      * altered.  Note, however, that the arc length is always computed and
      * returned as the function value.
+     *
+     * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+     * indicates how many times the geodesic wrapped around the ellipsoid.
+     * Because \e lon2 might be outside the normal allowed range for
+     * longitudes, [−540°, 540°), be sure to normalize it with
+     * Math::AngNormalize2 before using it in other GeographicLib calls.
      **********************************************************************/
     Math::real GenPosition(bool arcmode, real s12_a12, unsigned outmask,
                            real& lat2, real& lon2, real& azi2,
diff --git a/include/GeographicLib/Geohash.hpp b/include/GeographicLib/Geohash.hpp
index f7a7d38..575e825 100644
--- a/include/GeographicLib/Geohash.hpp
+++ b/include/GeographicLib/Geohash.hpp
@@ -24,7 +24,7 @@ namespace GeographicLib {
    * \brief Conversions for geohashes
    *
    * Geohashes are described in
-   * - http://en.wikipedia.org/wiki/Geohash
+   * - https://en.wikipedia.org/wiki/Geohash
    * - http://geohash.org/
    * .
    * They provide a compact string representation of a particular geographic
diff --git a/include/GeographicLib/Geoid.hpp b/include/GeographicLib/Geoid.hpp
index 4617bc6..b4b4255 100644
--- a/include/GeographicLib/Geoid.hpp
+++ b/include/GeographicLib/Geoid.hpp
@@ -2,7 +2,7 @@
  * \file Geoid.hpp
  * \brief Header for GeographicLib::Geoid class
  *
- * Copyright (c) Charles Karney (2009-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -51,6 +51,13 @@ namespace GeographicLib {
    * this class evaluates the height by interpolation into a grid of
    * precomputed values.
    *
+   * The geoid height, \e N, can be used to convert a height above the
+   * ellipsoid, \e h, to the corresponding height above the geoid (roughly the
+   * height above mean sea level), \e H, using the relations
+   *
+   *    \e h = \e N + \e H;
+   *   \e H = −\e N + \e h.
+   *
    * See \ref geoid for details of how to install the data sets, the data
    * format, estimates of the interpolation errors, and how to use caching.
    *
diff --git a/include/GeographicLib/GravityCircle.hpp b/include/GeographicLib/GravityCircle.hpp
index 731b700..6f9986e 100644
--- a/include/GeographicLib/GravityCircle.hpp
+++ b/include/GeographicLib/GravityCircle.hpp
@@ -287,8 +287,8 @@ namespace GeographicLib {
     unsigned Capabilities() const { return _caps; }
 
     /**
-     * @param[in] testcaps a set of bitor'ed GeodesicLine::mask values.
-     * @return true if the GeodesicLine object has all these capabilities.
+     * @param[in] testcaps a set of bitor'ed GravityModel::mask values.
+     * @return true if the GravityCircle object has all these capabilities.
      **********************************************************************/
     bool Capabilities(unsigned testcaps) const {
       return (_caps & testcaps) == testcaps;
diff --git a/include/GeographicLib/LambertConformalConic.hpp b/include/GeographicLib/LambertConformalConic.hpp
index 99ecb33..48a59af 100644
--- a/include/GeographicLib/LambertConformalConic.hpp
+++ b/include/GeographicLib/LambertConformalConic.hpp
@@ -96,7 +96,7 @@ namespace GeographicLib {
       return t > 0 ? (x + y) * Math::sq( (sx * sy)/t ) / (sx + sy) :
         (x - y != 0 ? (sx - sy) / (x - y) : 1);
     }
-    // Dlog1p(x,y) = log1p((x-y)/(1+y)/(x-y)
+    // Dlog1p(x,y) = log1p((x-y)/(1+y))/(x-y)
     static inline real Dlog1p(real x, real y) {
       real t = x - y; if (t < 0) { t = -t; y = x; }
       return t ? Math::log1p(t / (1 + y)) / t : 1 / (1 + x);
diff --git a/include/GeographicLib/PolygonArea.hpp b/include/GeographicLib/PolygonArea.hpp
index aad39ae..84c0e03 100644
--- a/include/GeographicLib/PolygonArea.hpp
+++ b/include/GeographicLib/PolygonArea.hpp
@@ -1,6 +1,6 @@
 /**
  * \file PolygonArea.hpp
- * \brief Header for GeographicLib::PolygonArea class
+ * \brief Header for GeographicLib::PolygonAreaT class
  *
  * Copyright (c) Charles Karney (2010-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
@@ -12,6 +12,7 @@
 
 #include <GeographicLib/Geodesic.hpp>
 #include <GeographicLib/GeodesicExact.hpp>
+#include <GeographicLib/Rhumb.hpp>
 #include <GeographicLib/Accumulator.hpp>
 
 namespace GeographicLib {
@@ -39,15 +40,16 @@ namespace GeographicLib {
    * vertex or add the edge ''as'' an edge (by defining its direction and
    * length).
    *
-   * The area and perimeter are accumulated in two times the standard floating
+   * The area and perimeter are accumulated at two times the standard floating
    * point precision to guard against the loss of accuracy with many-sided
    * polygons.  At any point you can ask for the perimeter and area so far.
    * There's an option to treat the points as defining a polyline instead of a
    * polygon; in that case, only the perimeter is computed.
    *
-   * This is a templated class to allow it to be used with either Geodesic and
-   * GeodesicExact.  GeographicLib::PolygonArea and
-   * GeographicLib::PolygonAreaExact are typedefs for these two cases.
+   * This is a templated class to allow it to be used with Geodesic,
+   * GeodesicExact, and Rhumb.  GeographicLib::PolygonArea,
+   * GeographicLib::PolygonAreaExact, and GeographicLib::PolygonAreaRhumb are
+   * typedefs for these cases.
    *
    * @tparam GeodType the geodesic class to use.
    *
@@ -55,7 +57,7 @@ namespace GeographicLib {
    * \include example-PolygonArea.cpp
    *
    * <a href="Planimeter.1.html">Planimeter</a> is a command-line utility
-   * providing access to the functionality of PolygonArea.
+   * providing access to the functionality of PolygonAreaT.
    **********************************************************************/
 
   template <class GeodType = Geodesic>
@@ -82,6 +84,18 @@ namespace GeographicLib {
         (lon2 < 0 && lon1 >= 0 && lon12 < 0 ? -1 : 0);
       return cross;
     }
+    // an alternate version of transit to deal with longitudes in the direct
+    // problem.
+    static inline int transitdirect(real lon1, real lon2) {
+      using std::fmod;
+      // We want to compute exactly
+      //   int(floor(lon2 / 360)) - int(floor(lon1 / 360))
+      // Since we only need the parity of the result we can use std::remquo but
+      // this is buggy with g++ 4.8.3 and requires C++11.  So instead we do
+      lon1 = fmod(lon1, real(720)); lon2 = fmod(lon2, real(720));
+      return ( ((lon2 >= 0 && lon2 < 360) || lon2 < -360 ? 0 : 1) -
+               ((lon1 >= 0 && lon1 < 360) || lon1 < -360 ? 0 : 1) );
+    }
   public:
 
     /**
@@ -96,7 +110,8 @@ namespace GeographicLib {
       , _area0(_earth.EllipsoidArea())
       , _polyline(polyline)
       , _mask(GeodType::LATITUDE | GeodType::LONGITUDE | GeodType::DISTANCE |
-              (_polyline ? GeodType::NONE : GeodType::AREA))
+              (_polyline ? GeodType::NONE :
+               GeodType::AREA | GeodType::LONG_NOWRAP))
     { Clear(); }
 
     /**
@@ -265,6 +280,13 @@ namespace GeographicLib {
    **********************************************************************/
   typedef PolygonAreaT<GeodesicExact> PolygonAreaExact;
 
+  /**
+   * @relates PolygonAreaT
+   *
+   * Polygon areas using Rhumb.
+   **********************************************************************/
+  typedef PolygonAreaT<Rhumb> PolygonAreaRhumb;
+
 } // namespace GeographicLib
 
 #endif  // GEOGRAPHICLIB_POLYGONAREA_HPP
diff --git a/include/GeographicLib/Rhumb.hpp b/include/GeographicLib/Rhumb.hpp
index 499e12a..a629be4 100644
--- a/include/GeographicLib/Rhumb.hpp
+++ b/include/GeographicLib/Rhumb.hpp
@@ -13,26 +13,44 @@
 #include <GeographicLib/Constants.hpp>
 #include <GeographicLib/Ellipsoid.hpp>
 
+#if !defined(GEOGRAPHICLIB_RHUMBAREA_ORDER)
+/**
+ * The order of the series approximation used in rhumb area calculations.
+ * GEOGRAPHICLIB_RHUMBAREA_ORDER can be set to any integer in [4, 8].
+ **********************************************************************/
+#  define GEOGRAPHICLIB_RHUMBAREA_ORDER \
+  (GEOGRAPHICLIB_PRECISION == 2 ? 6 : \
+   (GEOGRAPHICLIB_PRECISION == 1 ? 4 : 8))
+#endif
+
 namespace GeographicLib {
 
   class RhumbLine;
+  template <class T> class PolygonAreaT;
 
   /**
    * \brief Solve of the direct and inverse rhumb problems.
    *
    * The path of constant azimuth between two points on a ellipsoid at (\e
    * lat1, \e lon1) and (\e lat2, \e lon2) is called the rhumb line (also
-   * called the loxodrome).  Its length is \e s12 and its azimuth is \e azi12
-   * and \e azi2.  (The azimuth is the heading measured clockwise from north.)
+   * called the loxodrome).  Its length is \e s12 and its azimuth is \e azi12.
+   * (The azimuth is the heading measured clockwise from north.)
    *
    * Given \e lat1, \e lon1, \e azi12, and \e s12, we can determine \e lat2,
    * and \e lon2.  This is the \e direct rhumb problem and its solution is
    * given by the function Rhumb::Direct.
    *
    * Given \e lat1, \e lon1, \e lat2, and \e lon2, we can determine \e azi12
-   * and \e s12.  This is the \e inverse rhumb problem, whose solution is
-   * given by Rhumb::Inverse.  This finds the shortest such rhumb line, i.e.,
-   * the one that wraps no more than half way around the earth .
+   * and \e s12.  This is the \e inverse rhumb problem, whose solution is given
+   * by Rhumb::Inverse.  This finds the shortest such rhumb line, i.e., the one
+   * that wraps no more than half way around the earth.  If the end points are
+   * on opposite meridians, there are two shortest rhumb lines and the
+   * east-going one is chosen.
+   *
+   * These routines also optionally calculate the area under the rhumb line, \e
+   * S12.  This is the area, measured counter-clockwise, of the rhumb line
+   * quadrilateral with corners (<i>lat1</i>,<i>lon1</i>), (0,<i>lon1</i>),
+   * (0,<i>lon2</i>), and (<i>lat2</i>,<i>lon2</i>).
    *
    * Note that rhumb lines may be appreciably longer (up to 50%) than the
    * corresponding Geodesic.  For example the distance between London Heathrow
@@ -49,9 +67,14 @@ namespace GeographicLib {
   private:
     typedef Math::real real;
     friend class RhumbLine;
+    template <class T> friend class PolygonAreaT;
     Ellipsoid _ell;
     bool _exact;
+    real _c2;
     static const int tm_maxord = GEOGRAPHICLIB_TRANSVERSEMERCATOR_ORDER;
+    static const int maxpow_ = GEOGRAPHICLIB_RHUMBAREA_ORDER;
+    // _R[0] unused
+    real _R[maxpow_ + 1];
     static inline real overflow() {
       // Overflow value s.t. atan(overflow_) = pi/2
       static const real
@@ -78,6 +101,10 @@ namespace GeographicLib {
     //   http://dx.doi.org/10.1145/334714.334716
     //   http://www.cs.berkeley.edu/~fateman/papers/divdiff.pdf
 
+    static inline real Dlog(real x, real y) {
+      real t = x - y;
+      return t ? 2 * Math::atanh(t / (x + y)) / t : 1 / x;
+    }
     static inline real Dtan(real x, real y) {
       real d = x - y, tx = tano(x), ty = tano(y), txy = tx * ty;
       return d ? (2 * txy > -1 ? (1 + txy) * tano(d) : tx - ty) / d :
@@ -91,13 +118,18 @@ namespace GeographicLib {
     }
     static inline real Dsin(real x, real y) {
       using std::sin; using std::cos;
-      real d = (x - y)/2;
+      real d = (x - y) / 2;
       return cos((x + y)/2) * (d ? sin(d) / d : 1);
     }
     static inline real Dsinh(real x, real y) {
       using std::sinh; using std::cosh;
-      real d = (x - y)/2;
-      return cosh((x + y)/2) * (d ? sinh(d) / d : 1);
+      real d = (x - y) / 2;
+      return cosh((x + y) / 2) * (d ? sinh(d) / d : 1);
+    }
+    static inline real Dcosh(real x, real y) {
+      using std::sinh;
+      real d = (x - y) / 2;
+      return sinh((x + y) / 2) * (d ? sinh(d) / d : 1);
     }
     static inline real Dasinh(real x, real y) {
       real d = x - y,
@@ -135,7 +167,8 @@ namespace GeographicLib {
     real DIsometric(real latx, real laty) const;
 
     // (sum(c[j]*sin(2*j*x),j=1..n) - sum(c[j]*sin(2*j*x),j=1..n)) / (x - y)
-    static real SinSeries(real x, real y, const real c[], int n);
+    static real SinCosSeries(bool sinp,
+                             real x, real y, const real c[], int n);
     // (mux - muy) / (chix - chiy) using Krueger's series
     real DConformalToRectifying(real chix, real chiy) const;
     // (chix - chiy) / (mux - muy) using Krueger's series
@@ -146,9 +179,73 @@ namespace GeographicLib {
     // (psix - psiy) / (mux - muy)
     real DRectifyingToIsometric(real mux, real muy) const;
 
+    real MeanSinXi(real psi1, real psi2) const;
+
+    // The following two functions (with lots of ignored arguments) mimic the
+    // interface to the corresponding Geodesic function.  These are needed by
+    // PolygonAreaT.
+    void GenDirect(real lat1, real lon1, real azi12,
+                   bool, real s12, unsigned outmask,
+                   real& lat2, real& lon2, real&, real&, real&, real&, real&,
+                   real& S12) const {
+      GenDirect(lat1, lon1, azi12, s12, outmask, lat2, lon2, S12);
+    }
+    void GenInverse(real lat1, real lon1, real lat2, real lon2,
+                    unsigned outmask, real& s12, real& azi12,
+                    real&, real& , real& , real& , real& S12) const {
+      GenInverse(lat1, lon1, lat2, lon2, outmask, s12, azi12, S12);
+    }
   public:
 
     /**
+     * Bit masks for what calculations to do.  They specify which results to
+     * return in the general routines Rhumb::GenDirect and Rhumb::GenInverse
+     * routines.  RhumbLine::mask is a duplication of this enum.
+     **********************************************************************/
+    enum mask {
+      /**
+       * No output.
+       * @hideinitializer
+       **********************************************************************/
+      NONE          = 0U,
+      /**
+       * Calculate latitude \e lat2.
+       * @hideinitializer
+       **********************************************************************/
+      LATITUDE      = 1U<<7,
+      /**
+       * Calculate longitude \e lon2.
+       * @hideinitializer
+       **********************************************************************/
+      LONGITUDE     = 1U<<8,
+      /**
+       * Calculate azimuth \e azi12.
+       * @hideinitializer
+       **********************************************************************/
+      AZIMUTH       = 1U<<9,
+      /**
+       * Calculate distance \e s12.
+       * @hideinitializer
+       **********************************************************************/
+      DISTANCE      = 1U<<10,
+      /**
+       * Calculate area \e S12.
+       * @hideinitializer
+       **********************************************************************/
+      AREA          = 1U<<14,
+      /**
+       * Do not wrap the \e lon2 in the direct calculation.
+       * @hideinitializer
+       **********************************************************************/
+      LONG_NOWRAP   = 1U<<15,
+      /**
+       * Calculate everything.  (LONG_NOWRAP is not included in this mask.)
+       * @hideinitializer
+       **********************************************************************/
+      ALL           = 0x7F80U,
+    };
+
+    /**
      * Constructor for a ellipsoid with
      *
      * @param[in] a equatorial radius (meters).
@@ -163,10 +260,10 @@ namespace GeographicLib {
      *
      * See \ref rhumb, for a detailed description of the \e exact parameter.
      **********************************************************************/
-    Rhumb(real a, real f, bool exact = true) : _ell(a, f), _exact(exact) {}
+    Rhumb(real a, real f, bool exact = true);
 
     /**
-     * Solve the direct rhumb problem.
+     * Solve the direct rhumb problem returning also the area.
      *
      * @param[in] lat1 latitude of point 1 (degrees).
      * @param[in] lon1 longitude of point 1 (degrees).
@@ -175,24 +272,68 @@ namespace GeographicLib {
      *   negative.
      * @param[out] lat2 latitude of point 2 (degrees).
      * @param[out] lon2 longitude of point 2 (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
      *
      * \e lat1 should be in the range [−90°, 90°]; \e lon1 and \e
-     * azi1 should be in the range [−540°, 540°).  The values of
-     * \e lon2 and \e azi2 returned are in the range [−180°,
-     * 180°).
+     * azi12 should be in the range [−540°, 540°).  The value of
+     * \e lon2 returned is in the range [−180°, 180°).
      *
      * If point 1 is a pole, the cosine of its latitude is taken to be
      * 1/ε<sup>2</sup> (where ε is 2<sup>-52</sup>).  This
      * position, which is extremely close to the actual pole, allows the
      * calculation to be carried out in finite terms.  If \e s12 is large
      * enough that the rhumb line crosses a pole, the longitude of point 2
-     * is indeterminate (a NaN is returned for \e lon2).
+     * is indeterminate (a NaN is returned for \e lon2 and \e S12).
      **********************************************************************/
     void Direct(real lat1, real lon1, real azi12, real s12,
-                real& lat2, real& lon2) const;
+                real& lat2, real& lon2, real& S12) const {
+      GenDirect(lat1, lon1, azi12, s12,
+                LATITUDE | LONGITUDE | AREA, lat2, lon2, S12);
+    }
 
     /**
-     * Solve the inverse rhumb problem.
+     * Solve the direct rhumb problem without the area.
+     **********************************************************************/
+    void Direct(real lat1, real lon1, real azi12, real s12,
+                real& lat2, real& lon2) const {
+      real t;
+      GenDirect(lat1, lon1, azi12, s12, LATITUDE | LONGITUDE, lat2, lon2, t);
+    }
+
+    /**
+     * The general direct rhumb problem.  Rhumb::Direct is defined in terms
+     * of this function.
+     *
+     * @param[in] lat1 latitude of point 1 (degrees).
+     * @param[in] lon1 longitude of point 1 (degrees).
+     * @param[in] azi12 azimuth of the rhumb line (degrees).
+     * @param[in] s12 distance between point 1 and point 2 (meters); it can be
+     *   negative.
+     * @param[in] outmask a bitor'ed combination of Rhumb::mask values
+     *   specifying which of the following parameters should be set.
+     * @param[out] lat2 latitude of point 2 (degrees).
+     * @param[out] lon2 longitude of point 2 (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
+     *
+     * The Rhumb::mask values possible for \e outmask are
+     * - \e outmask |= Rhumb::LATITUDE for the latitude \e lat2;
+     * - \e outmask |= Rhumb::LONGITUDE for the latitude \e lon2;
+     * - \e outmask |= Rhumb::AREA for the area \e S12;
+     * - \e outmask |= Rhumb::ALL for all of the above;
+     * - \e outmask |= Rhumb::LONG_NOWRAP stops the returned value of \e
+     *   lon2 being wrapped into the range [−180°, 180°).
+     * .
+     * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+     * indicates how many times the rhumb line wrapped around the ellipsoid.
+     * Because \e lon2 might be outside the normal allowed range for
+     * longitudes, [−540°, 540°), be sure to normalize it with
+     * Math::AngNormalize2 before using it in other GeographicLib calls.
+     **********************************************************************/
+    void GenDirect(real lat1, real lon1, real azi12, real s12, unsigned outmask,
+                   real& lat2, real& lon2, real& S12) const;
+
+    /**
+     * Solve the inverse rhumb problem returning also the area.
      *
      * @param[in] lat1 latitude of point 1 (degrees).
      * @param[in] lon1 longitude of point 1 (degrees).
@@ -200,11 +341,14 @@ namespace GeographicLib {
      * @param[in] lon2 longitude of point 2 (degrees).
      * @param[out] s12 rhumb distance between point 1 and point 2 (meters).
      * @param[out] azi12 azimuth of the rhumb line (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
      *
-     * The shortest rhumb line is found.  \e lat1 and \e lat2 should be in the
-     * range [−90°, 90°]; \e lon1 and \e lon2 should be in the
-     * range [−540°, 540°).  The value of \e azi12 returned is in
-     * the range [−180°, 180°).
+     * The shortest rhumb line is found.  If the end points are on opposite
+     * meridians, there are two shortest rhumb lines and the east-going one is
+     * chosen.  \e lat1 and \e lat2 should be in the range [−90°,
+     * 90°]; \e lon1 and \e lon2 should be in the range [−540°,
+     * 540°).  The value of \e azi12 returned is in the range
+     * [−180°, 180°).
      *
      * If either point is a pole, the cosine of its latitude is taken to be
      * 1/ε<sup>2</sup> (where ε is 2<sup>-52</sup>).  This
@@ -212,7 +356,43 @@ namespace GeographicLib {
      * calculation to be carried out in finite terms.
      **********************************************************************/
     void Inverse(real lat1, real lon1, real lat2, real lon2,
-                 real& s12, real& azi12) const;
+                 real& s12, real& azi12, real& S12) const {
+      GenInverse(lat1, lon1, lat2, lon2,
+                 DISTANCE | AZIMUTH | AREA, s12, azi12, S12);
+    }
+
+    /**
+     * Solve the inverse rhumb problem without the area.
+     **********************************************************************/
+    void Inverse(real lat1, real lon1, real lat2, real lon2,
+                 real& s12, real& azi12) const {
+      real t;
+      GenInverse(lat1, lon1, lat2, lon2, DISTANCE | AZIMUTH, s12, azi12, t);
+    }
+
+    /**
+     * The general inverse rhumb problem.  Rhumb::Inverse is defined in terms
+     * of this function.
+     *
+     * @param[in] lat1 latitude of point 1 (degrees).
+     * @param[in] lon1 longitude of point 1 (degrees).
+     * @param[in] lat2 latitude of point 2 (degrees).
+     * @param[in] lon2 longitude of point 2 (degrees).
+     * @param[in] outmask a bitor'ed combination of Rhumb::mask values
+     *   specifying which of the following parameters should be set.
+     * @param[out] s12 rhumb distance between point 1 and point 2 (meters).
+     * @param[out] azi12 azimuth of the rhumb line (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
+     *
+     * The Rhumb::mask values possible for \e outmask are
+     * - \e outmask |= Rhumb::DISTANCE for the latitude \e s12;
+     * - \e outmask |= Rhumb::AZIMUTH for the latitude \e azi12;
+     * - \e outmask |= Rhumb::AREA for the area \e S12;
+     * - \e outmask |= Rhumb::ALL for all of the above;
+     **********************************************************************/
+    void GenInverse(real lat1, real lon1, real lat2, real lon2,
+                    unsigned outmask,
+                    real& s12, real& azi12, real& S12) const;
 
     /**
      * Set up to compute several points on a single rhumb line.
@@ -248,6 +428,8 @@ namespace GeographicLib {
      **********************************************************************/
     Math::real Flattening() const { return _ell.Flattening(); }
 
+    Math::real EllipsoidArea() const { return _ell.Area(); }
+
     /**
      * A global instantiation of Rhumb with the parameters for the WGS84
      * ellipsoid.
@@ -261,9 +443,10 @@ namespace GeographicLib {
    * RhumbLine facilitates the determination of a series of points on a single
    * rhumb line.  The starting point (\e lat1, \e lon1) and the azimuth \e
    * azi12 are specified in the call to Rhumb::Line which returns a RhumbLine
-   * object.  RhumbLine.Position returns the location of point 2 a distance \e
-   * s12 along the rhumb line.
-
+   * object.  RhumbLine.Position returns the location of point 2 (and,
+   * optionally, the corresponding area, \e S12) a distance \e s12 along the
+   * rhumb line.
+   *
    * There is no public constructor for this class.  (Use Rhumb::Line to create
    * an instance.)  The Rhumb object used to create a RhumbLine must stay in
    * scope as long as the RhumbLine.
@@ -283,22 +466,112 @@ namespace GeographicLib {
     RhumbLine(const Rhumb& rh, real lat1, real lon1, real azi12,
               bool exact);
   public:
+
+    enum mask {
+      /**
+       * No output.
+       * @hideinitializer
+       **********************************************************************/
+      NONE          = Rhumb::NONE,
+      /**
+       * Calculate latitude \e lat2.
+       * @hideinitializer
+       **********************************************************************/
+      LATITUDE      = Rhumb::LATITUDE,
+      /**
+       * Calculate longitude \e lon2.
+       * @hideinitializer
+       **********************************************************************/
+      LONGITUDE     = Rhumb::LONGITUDE,
+      /**
+       * Calculate azimuth \e azi12.
+       * @hideinitializer
+       **********************************************************************/
+      AZIMUTH       = Rhumb::AZIMUTH,
+      /**
+       * Calculate distance \e s12.
+       * @hideinitializer
+       **********************************************************************/
+      DISTANCE      = Rhumb::DISTANCE,
+      /**
+       * Calculate area \e S12.
+       * @hideinitializer
+       **********************************************************************/
+      AREA          = Rhumb::AREA,
+      /**
+       * Do wrap the \e lon2 in the direct calculation.
+       * @hideinitializer
+       **********************************************************************/
+      LONG_NOWRAP   = Rhumb::LONG_NOWRAP,
+      /**
+       * Calculate everything.  (LONG_NOWRAP is not included in this mask.)
+       * @hideinitializer
+       **********************************************************************/
+      ALL           = Rhumb::ALL,
+    };
+
     /**
      * Compute the position of point 2 which is a distance \e s12 (meters) from
-     * point 1.
+     * point 1.  The area is also computed.
      *
      * @param[in] s12 distance between point 1 and point 2 (meters); it can be
      *   negative.
      * @param[out] lat2 latitude of point 2 (degrees).
      * @param[out] lon2 longitude of point 2 (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
      *
-     * The values of \e lon2 and \e azi2 returned are in the range
-     * [−180°, 180°).
+     * The value of \e lon2 returned is in the range [−180°,
+     * 180°).
+     *
+     * If \e s12 is large enough that the rhumb line crosses a pole, the
+     * longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and
+     * \e S12).
+     **********************************************************************/
+    void Position(real s12, real& lat2, real& lon2, real& S12) const {
+      GenPosition(s12, LATITUDE | LONGITUDE | AREA, lat2, lon2, S12);
+    }
+
+    /**
+     * Compute the position of point 2 which is a distance \e s12 (meters) from
+     * point 1.  The area is not computed.
+     **********************************************************************/
+    void Position(real s12, real& lat2, real& lon2) const {
+      real t;
+      GenPosition(s12, LATITUDE | LONGITUDE, lat2, lon2, t);
+    }
+
+    /**
+     * The general position routine.  RhumbLine::Position is defined in term so
+     * this function.
+     *
+     * @param[in] s12 distance between point 1 and point 2 (meters); it can be
+     *   negative.
+     * @param[in] outmask a bitor'ed combination of Rhumb::mask values
+     *   specifying which of the following parameters should be set.
+     * @param[out] lat2 latitude of point 2 (degrees).
+     * @param[out] lon2 longitude of point 2 (degrees).
+     * @param[out] S12 area under the rhumb line (meters<sup>2</sup>).
+     *
+     * The Rhumb::mask values possible for \e outmask are
+     * - \e outmask |= Rhumb::LATITUDE for the latitude \e lat2;
+     * - \e outmask |= Rhumb::LONGITUDE for the latitude \e lon2;
+     * - \e outmask |= Rhumb::AREA for the area \e S12;
+     * - \e outmask |= Rhumb::ALL for all of the above;
+     * - \e outmask |= Rhumb::LONG_NOWRAP stops the returned value of \e
+     *   lon2 being wrapped into the range [−180°, 180°).
+     * .
+     * With the LONG_NOWRAP bit set, the quantity \e lon2 − \e lon1
+     * indicates how many times the rhumb line wrapped around the ellipsoid.
+     * Because \e lon2 might be outside the normal allowed range for
+     * longitudes, [−540°, 540°), be sure to normalize it with
+     * Math::AngNormalize2 before using it in other GeographicLib calls.
      *
      * If \e s12 is large enough that the rhumb line crosses a pole, the
-     * longitude of point 2 is indeterminate (a NaN is returned for \e lon2).
+     * longitude of point 2 is indeterminate (a NaN is returned for \e lon2 and
+     * \e S12).
      **********************************************************************/
-    void Position(real s12, real& lat2, real& lon2) const;
+    void GenPosition(real s12, unsigned outmask,
+                     real& lat2, real& lon2, real& S12) const;
 
     /** \name Inspector functions
      **********************************************************************/
diff --git a/include/GeographicLib/Utility.hpp b/include/GeographicLib/Utility.hpp
index a84d401..f44cad1 100644
--- a/include/GeographicLib/Utility.hpp
+++ b/include/GeographicLib/Utility.hpp
@@ -2,7 +2,7 @@
  * \file Utility.hpp
  * \brief Header for GeographicLib::Utility class
  *
- * Copyright (c) Charles Karney (2011-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -15,11 +15,12 @@
 #include <vector>
 #include <sstream>
 #include <cctype>
+#include <ctime>
 
 #if defined(_MSC_VER)
-// Squelch warnings about constant conditional expressions
+// Squelch warnings about constant conditional expressions and unsafe gmtime
 #  pragma warning (push)
-#  pragma warning (disable: 4127)
+#  pragma warning (disable: 4127 4996)
 #endif
 
 namespace GeographicLib {
@@ -165,7 +166,8 @@ namespace GeographicLib {
     /**
      * Given a date as a string in the format yyyy, yyyy-mm, or yyyy-mm-dd,
      * return the numeric values for the year, month, and day.  No checking is
-     * done on these values.
+     * done on these values.  The string "now" is interpreted as the present
+     * date (in UTC).
      *
      * @param[in] s the date in string format.
      * @param[out] y the year.
@@ -174,6 +176,14 @@ namespace GeographicLib {
      * @exception GeographicErr is \e s is malformed.
      **********************************************************************/
     static void date(const std::string& s, int& y, int& m, int& d) {
+      if (s == "now") {
+        std::time_t t = std::time(0);
+        struct tm* now = gmtime(&t);
+        y = now->tm_year + 1900;
+        m = now->tm_mon + 1;
+        d = now->tm_mday;
+        return;
+      }
       int y1, m1 = 1, d1 = 1;
       const char* digits = "0123456789";
       std::string::size_type p1 = s.find_first_not_of(digits);
diff --git a/java/pom.xml b/java/pom.xml
index e6af2e0..22f3bb5 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -8,7 +8,7 @@
     <groupId>net.sf.geographiclib</groupId>
     <artifactId>GeographicLib</artifactId>
     <name>GeographicLib</name>
-    <version>1.31</version>
+    <version>1.39</version>
 
     <packaging>jar</packaging>
 
diff --git a/java/src/main/java/net/sf/geographiclib/Geodesic.java b/java/src/main/java/net/sf/geographiclib/Geodesic.java
index 4fe5a96..337e71f 100644
--- a/java/src/main/java/net/sf/geographiclib/Geodesic.java
+++ b/java/src/main/java/net/sf/geographiclib/Geodesic.java
@@ -1,7 +1,7 @@
 /**
  * Implementation of the net.sf.geographiclib.Geodesic class
  *
- * Copyright (c) Charles Karney (2013) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2013-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -355,7 +355,9 @@ public class Geodesic {
    *   <i>outmask</i> computed.
    * <p>
    * <i>lat1</i>, <i>lon1</i>, <i>azi1</i>, <i>s12</i>, and <i>a12</i> are
-   * always included in the returned result.
+   * always included in the returned result.  The value of <i>lon2</i> returned
+   * is in the range [−180°, 180°), unless the <i>outmask</i>
+   * includes the {@link GeodesicMask#LONG_NOWRAP} flag.
    **********************************************************************/
   public GeodesicData Direct(double lat1, double lon1,
                              double azi1, double s12, int outmask) {
@@ -410,7 +412,9 @@ public class Geodesic {
    *   <i>outmask</i> computed.
    * <p>
    * <i>lat1</i>, <i>lon1</i>, <i>azi1</i>, and <i>a12</i> are always included
-   * in the returned result.
+   * in the returned result.  The value of <i>lon2</i> returned is in the range
+   * [−180°, 180°), unless the <i>outmask</i> includes the {@link
+   * GeodesicMask#LONG_NOWRAP} flag.
    **********************************************************************/
   public GeodesicData ArcDirect(double lat1, double lon1,
                                 double azi1, double a12, int outmask) {
@@ -453,7 +457,10 @@ public class Geodesic {
    * <li>
    *   <i>outmask</i> |= GeodesicMask.AREA for the area <i>S12</i>;
    * <li>
-   *   <i>outmask</i> |= GeodesicMask.ALL for all of the above.
+   *   <i>outmask</i> |= GeodesicMask.ALL for all of the above;
+   * <li>
+   *   <i>outmask</i> |= GeodesicMask.LONG_NOWRAP to stop <i>lon2</i> from
+   *   being reduced to the range [−180°, 180°).
    * </ul>
    * <p>
    * The function value <i>a12</i> is always computed and returned and this
@@ -540,7 +547,7 @@ public class Geodesic {
    **********************************************************************/
   public GeodesicData Inverse(double lat1, double lon1,
                               double lat2, double lon2, int outmask) {
-    outmask &= GeodesicMask.OUT_ALL;
+    outmask &= GeodesicMask.OUT_MASK;
     GeodesicData r = new GeodesicData();
     lon1 = GeoMath.AngNormalize(lon1);
     lon2 = GeoMath.AngNormalize(lon2);
diff --git a/java/src/main/java/net/sf/geographiclib/GeodesicLine.java b/java/src/main/java/net/sf/geographiclib/GeodesicLine.java
index 61d29de..35d8202 100644
--- a/java/src/main/java/net/sf/geographiclib/GeodesicLine.java
+++ b/java/src/main/java/net/sf/geographiclib/GeodesicLine.java
@@ -1,7 +1,7 @@
 /**
  * Implementation of the net.sf.geographiclib.GeodesicLine class
  *
- * Copyright (c) Charles Karney (2013) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2013-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -174,7 +174,6 @@ public class GeodesicLine {
 
     // Guard against underflow in salp0
     azi1 = Geodesic.AngRound(GeoMath.AngNormalize(azi1));
-    lon1 = GeoMath.AngNormalize(lon1);
     _lat1 = lat1;
     _lon1 = lon1;
     _azi1 = azi1;
@@ -302,7 +301,9 @@ public class GeodesicLine {
    * The GeodesicLine object <i>must</i> have been constructed with <i>caps</i>
    * |= {@link GeodesicMask#DISTANCE_IN}; otherwise no parameters are set.
    * Requesting a value which the GeodesicLine object is not capable of
-   * computing is not an error (no parameters will be set).
+   * computing is not an error (no parameters will be set).  The value of
+   * <i>lon2</i> returned is in the range [−180°, 180°), unless
+   * the <i>outmask</i> includes the {@link GeodesicMask#LONG_NOWRAP} flag.
    **********************************************************************/
   public GeodesicData Position(double s12, int outmask) {
     return Position(false, s12, outmask);
@@ -344,7 +345,9 @@ public class GeodesicLine {
    * The GeodesicLine object <i>must</i> have been constructed with <i>caps</i>
    * |= {@link GeodesicMask#DISTANCE_IN}; otherwise no parameters are set.
    * Requesting a value which the GeodesicLine object is not capable of
-   * computing is not an error (no parameters will be set).
+   * computing is not an error (no parameters will be set).  The value of
+   * <i>lon2</i> returned is in the range [−180°, 180°), unless
+   * the <i>outmask</i> includes the {@link GeodesicMask#LONG_NOWRAP} flag.
    **********************************************************************/
   public GeodesicData ArcPosition(double a12, int outmask) {
     return Position(true, a12, outmask);
@@ -382,7 +385,10 @@ public class GeodesicLine {
    *   <i>outmask</i> |= GeodesicMask.GEODESICSCALE for the geodesic scales
    *   <i>M12</i> and <i>M21</i>.
    * <li>
-   *   <i>outmask</i> |= GeodesicMask.AREA for the area <i>S12</i>.
+   *   <i>outmask</i> |= GeodesicMask.ALL for all of the above;
+   * <li>
+   *   <i>outmask</i> |= GeodesicMask.LONG_NOWRAP to stop <i>lon2</i> from
+   *   being reduced to the range [−180°, 180°).
    * </ul>
    * <p>
    * Requesting a value which the GeodesicLine object is not capable of
@@ -390,14 +396,16 @@ public class GeodesicLine {
    **********************************************************************/
   public GeodesicData Position(boolean arcmode, double s12_a12,
                                int outmask) {
-    outmask &= _caps & GeodesicMask.OUT_ALL;
+    outmask &= _caps & GeodesicMask.OUT_MASK;
     GeodesicData r = new GeodesicData();
     if (!( Init() &&
            (arcmode ||
-            (_caps & GeodesicMask.DISTANCE_IN & GeodesicMask.OUT_ALL) != 0) ))
+            (_caps & GeodesicMask.DISTANCE_IN & GeodesicMask.OUT_MASK) != 0) ))
       // Uninitialized or impossible distance calculation requested
       return r;
-    r.lat1 = _lat1; r.lon1 = _lon1; r.azi1 = _azi1;
+    r.lat1 = _lat1; r.azi1 = _azi1;
+    r.lon1 = ((outmask & GeodesicMask.LONG_NOWRAP) != 0) ? _lon1 :
+      GeoMath.AngNormalize(_lon1);
 
     // Avoid warning about uninitialized B12.
     double sig12, ssig12, csig12, B12 = 0, AB1 = 0;
@@ -476,26 +484,29 @@ public class GeodesicLine {
     if (cbet2 == 0)
       // I.e., salp0 = 0, csig2 = 0.  Break the degeneracy in this case
       cbet2 = csig2 = Geodesic.tiny_;
-    // tan(omg2) = sin(alp0) * tan(sig2)
-    somg2 = _salp0 * ssig2; comg2 = csig2;  // No need to normalize
     // tan(alp0) = cos(sig2)*tan(alp2)
     salp2 = _salp0; calp2 = _calp0 * csig2; // No need to normalize
-    // omg12 = omg2 - omg1
-    omg12 = Math.atan2(somg2 * _comg1 - comg2 * _somg1,
-                  comg2 * _comg1 + somg2 * _somg1);
 
     if ((outmask & GeodesicMask.DISTANCE) != 0 && arcmode)
       r.s12 = _b * ((1 + _A1m1) * sig12 + AB1);
 
     if ((outmask & GeodesicMask.LONGITUDE) != 0) {
+      // tan(omg2) = sin(alp0) * tan(sig2)
+      somg2 = _salp0 * ssig2; comg2 = csig2;  // No need to normalize
+      // omg12 = omg2 - omg1
+      omg12 = ((outmask & GeodesicMask.LONG_NOWRAP) != 0) ? sig12
+        - (Math.atan2(ssig2, csig2) - Math.atan2(_ssig1, _csig1))
+        + (Math.atan2(somg2, comg2) - Math.atan2(_somg1, _comg1))
+        : Math.atan2(somg2 * _comg1 - comg2 * _somg1,
+                     comg2 * _comg1 + somg2 * _somg1);
       lam12 = omg12 + _A3c *
         ( sig12 + (Geodesic.SinCosSeries(true, ssig2, csig2, _C3a)
                    - _B31));
       lon12 = lam12 / GeoMath.degree;
       // Use GeoMath.AngNormalize2 because longitude might have wrapped
       // multiple times.
-      lon12 = GeoMath.AngNormalize2(lon12);
-      r.lon2 = GeoMath.AngNormalize(_lon1 + lon12);
+      r.lon2 = ((outmask & GeodesicMask.LONG_NOWRAP) != 0) ? _lon1 + lon12 :
+        GeoMath.AngNormalize(r.lon1 + GeoMath.AngNormalize2(lon12));
     }
 
     if ((outmask & GeodesicMask.LATITUDE) != 0)
diff --git a/java/src/main/java/net/sf/geographiclib/GeodesicMask.java b/java/src/main/java/net/sf/geographiclib/GeodesicMask.java
index 6b72ea7..19066ed 100644
--- a/java/src/main/java/net/sf/geographiclib/GeodesicMask.java
+++ b/java/src/main/java/net/sf/geographiclib/GeodesicMask.java
@@ -1,7 +1,7 @@
 /**
  * Implementation of the net.sf.geographiclib.GeodesicMask class
  *
- * Copyright (c) Charles Karney (2013) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2013-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -28,7 +28,9 @@ public class GeodesicMask {
   protected static final int CAP_C3   = 1<<3;
   protected static final int CAP_C4   = 1<<4;
   protected static final int CAP_ALL  = 0x1F;
+  protected static final int CAP_MASK = CAP_ALL;
   protected static final int OUT_ALL  = 0x7F80;
+  protected static final int OUT_MASK = 0xFF80; // Include LONG_NOWRAP
 
   /**
    * No capabilities, no output.
@@ -71,6 +73,10 @@ public class GeodesicMask {
    **********************************************************************/
   public static final int AREA          = 1<<14 | CAP_C4;
   /**
+   * Do not wrap <i>lon2</i>.
+   **********************************************************************/
+  public static final int LONG_NOWRAP   = 1<<15;
+  /**
    * All capabilities, calculate everything.
    **********************************************************************/
   public static final int ALL           = OUT_ALL| CAP_ALL;
diff --git a/java/src/main/java/net/sf/geographiclib/PolygonArea.java b/java/src/main/java/net/sf/geographiclib/PolygonArea.java
index 75cb09a..1163df4 100644
--- a/java/src/main/java/net/sf/geographiclib/PolygonArea.java
+++ b/java/src/main/java/net/sf/geographiclib/PolygonArea.java
@@ -1,7 +1,7 @@
 /**
  * Implementation of the net.sf.geographiclib.PolygonArea class
  *
- * Copyright (c) Charles Karney (2013) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2013-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
@@ -25,7 +25,7 @@ package net.sf.geographiclib;
  * </ul>
  * <p>
  * This class lets you add vertices one at a time to the polygon.  The area
- * and perimeter are accumulated in two times the standard floating point
+ * and perimeter are accumulated at two times the standard floating point
  * precision to guard against the loss of accuracy with many-sided polygons.
  * At any point you can ask for the perimeter and area so far.  There's an
  * option to treat the points as defining a polyline instead of a polygon; in
@@ -81,6 +81,17 @@ public class PolygonArea {
       (lon2 < 0 && lon1 >= 0 && lon12 < 0 ? -1 : 0);
     return cross;
   }
+  // an alternate version of transit to deal with longitudes in the direct
+  // problem.
+  private static int transitdirect(double lon1, double lon2) {
+    // We want to compute exactly
+    //   int(floor(lon2 / 360)) - int(floor(lon1 / 360))
+    // Since we only need the parity of the result we can use std::remquo but
+    // this is buggy with g++ 4.8.3 and requires C++11.  So instead we do
+    lon1 = lon1 % 720.0; lon2 = lon2 % 720.0;
+    return ( ((lon2 >= 0 && lon2 < 360) || lon2 < -360 ? 0 : 1) -
+             ((lon1 >= 0 && lon1 < 360) || lon1 < -360 ? 0 : 1) );
+    }
 
   /**
    * Constructor for PolygonArea.
@@ -95,7 +106,8 @@ public class PolygonArea {
     _polyline = polyline;
      _mask = GeodesicMask.LATITUDE | GeodesicMask.LONGITUDE |
        GeodesicMask.DISTANCE |
-       (_polyline ? GeodesicMask.NONE : GeodesicMask.AREA);
+       (_polyline ? GeodesicMask.NONE :
+        GeodesicMask.AREA | GeodesicMask.LONG_NOWRAP);
      _perimetersum = new Accumulator(0);
      if (!_polyline)
        _areasum = new Accumulator(0);
@@ -155,7 +167,7 @@ public class PolygonArea {
       _perimetersum.Add(g.s12);
       if (!_polyline) {
         _areasum.Add(g.S12);
-        _crossings += transit(_lon1, g.lon2);
+        _crossings += transitdirect(_lon1, g.lon2);
       }
       _lat1 = g.lat2; _lon1 = g.lon2;
       ++_num;
@@ -329,7 +341,7 @@ public class PolygonArea {
       GeodesicData g =
         _earth.Direct(_lat1, _lon1, azi, false, s, _mask);
       tempsum += g.S12;
-      crossings += transit(_lon1, g.lon2);
+      crossings += transitdirect(_lon1, g.lon2);
       g = _earth.Inverse(g.lat2, g.lon2, _lat0, _lon0, _mask);
       perimeter += g.s12;
       tempsum += g.S12;
diff --git a/java/src/main/java/net/sf/geographiclib/package-info.java b/java/src/main/java/net/sf/geographiclib/package-info.java
index 6bceb8f..77894b8 100644
--- a/java/src/main/java/net/sf/geographiclib/package-info.java
+++ b/java/src/main/java/net/sf/geographiclib/package-info.java
@@ -1,7 +1,7 @@
 /**
  * <h1>Geodesic routines from GeographicLib implemented in Java</h1>
  * @author Charles F. F. Karney (charles at karney.com)
- * @version 1.31
+ * @version 1.39
  *
  * <h2>Abstract</h2>
  * <p>
@@ -16,15 +16,15 @@
  * The Java library is part of GeographicLib which available for download at
  * <ul>
  * <li>
- *   <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.31.tar.gz">
- *   GeographicLib-1.31.tar.gz</a>
+ *   <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.39.tar.gz">
+ *   GeographicLib-1.39.tar.gz</a>
  * <li>
- *   <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.31.zip">
- *   GeographicLib-1.31.zip</a>
+ *   <a href="http://sf.net/projects/geographiclib/files/distrib/GeographicLib-1.39.zip">
+ *   GeographicLib-1.39.zip</a>
  * </ul>
  * <p>
  * as either a compressed tar file (tar.gz) or a zip file.  After unpacking
- * the source, the Java library can be found in GeographicLib-1.31/java.  (This
+ * the source, the Java library can be found in GeographicLib-1.39/java.  (This
  * library is completely independent from the rest of GeodegraphicLib.)  The
  * library consists of the files in the src/main/java/net/sf/geographiclib
  * subdirectory.
@@ -88,9 +88,9 @@
  * some additional packages to your local repository.)  Then compile and run
  * Inverse.java with <pre>
  * cd inverse/src/main/java
- * javac -cp .:../../../../target/GeographicLib-1.31.jar Inverse.java
+ * javac -cp .:../../../../target/GeographicLib-1.39.jar Inverse.java
  * echo -30 0 29.5 179.5 |
- *   java -cp .:../../../../target/GeographicLib-1.31.jar Inverse </pre>
+ *   java -cp .:../../../../target/GeographicLib-1.39.jar Inverse </pre>
  * <h3>Using maven to build and run {@code Inverse.java}</h3>
  * Use <a href="http://maven.apache.org/">maven</a> to install GeographicLib by
  * running (in the main java directory) <pre>
diff --git a/legacy/C/CMakeLists.txt b/legacy/C/CMakeLists.txt
index 3f0a8b9..8fda0ef 100644
--- a/legacy/C/CMakeLists.txt
+++ b/legacy/C/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.4)
 
 project (GeographicLib-legacy-C C)
 
diff --git a/legacy/C/geodesic.c b/legacy/C/geodesic.c
index f46a6ff..0244267 100644
--- a/legacy/C/geodesic.c
+++ b/legacy/C/geodesic.c
@@ -18,7 +18,7 @@
  *
  * See the comments in geodesic.h for documentation.
  *
- * Copyright (c) Charles Karney (2012-2013) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2012-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  */
@@ -222,6 +222,7 @@ static void C1pf(real eps, real c[]);
 static real A2m1f(real eps);
 static void C2f(real eps, real c[]);
 static int transit(real lon1, real lon2);
+static int transitdirect(real lon1, real lon2);
 static void accini(real s[]);
 static void acccopy(const real s[], real t[]);
 static void accadd(real s[], real y);
@@ -271,18 +272,16 @@ void geod_lineinit(struct geod_geodesicline* l,
   l->caps = (caps ? caps : GEOD_DISTANCE_IN | GEOD_LONGITUDE) |
     GEOD_LATITUDE | GEOD_AZIMUTH; /* Always allow latitude and azimuth */
 
-  /* Guard against underflow in salp0 */
-  azi1 = AngRound(AngNormalize(azi1));
-  lon1 = AngNormalize(lon1);
   l->lat1 = lat1;
   l->lon1 = lon1;
-  l->azi1 = azi1;
+  /* Guard against underflow in salp0 */
+  l->azi1 = AngRound(AngNormalize(azi1));
   /* alp1 is in [0, pi] */
-  alp1 = azi1 * degree;
+  alp1 = l->azi1 * degree;
   /* Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
    * problems directly than to skirt them. */
-  l->salp1 =      azi1  == -180 ? 0 : sin(alp1);
-  l->calp1 = fabs(azi1) ==   90 ? 0 : cos(alp1);
+  l->salp1 =      l->azi1  == -180 ? 0 : sin(alp1);
+  l->calp1 = fabs(l->azi1) ==   90 ? 0 : cos(alp1);
   phi = lat1 * degree;
   /* Ensure cbet1 = +epsilon at poles */
   sbet1 = l->f1 * sin(phi);
@@ -349,7 +348,7 @@ void geod_lineinit(struct geod_geodesicline* l,
 }
 
 real geod_genposition(const struct geod_geodesicline* l,
-                      boolx arcmode, real s12_a12,
+                      unsigned flags, real s12_a12,
                       real* plat2, real* plon2, real* pazi2,
                       real* ps12, real* pm12,
                       real* pM12, real* pM21,
@@ -371,11 +370,11 @@ real geod_genposition(const struct geod_geodesicline* l,
 
   outmask &= l->caps & OUT_ALL;
   if (!( TRUE /*Init()*/ &&
-         (arcmode || (l->caps & GEOD_DISTANCE_IN & OUT_ALL)) ))
+         (flags & GEOD_ARCMODE || (l->caps & GEOD_DISTANCE_IN & OUT_ALL)) ))
     /* Uninitialized or impossible distance calculation requested */
     return NaN;
 
-  if (arcmode) {
+  if (flags & GEOD_ARCMODE) {
     real s12a;
     /* Interpret s12_a12 as spherical arc length */
     sig12 = s12_a12 * degree;
@@ -435,7 +434,7 @@ real geod_genposition(const struct geod_geodesicline* l,
   csig2 = l->csig1 * csig12 - l->ssig1 * ssig12;
   dn2 = sqrt(1 + l->k2 * sq(ssig2));
   if (outmask & (GEOD_DISTANCE | GEOD_REDUCEDLENGTH | GEOD_GEODESICSCALE)) {
-    if (arcmode || fabs(l->f) > 0.01)
+    if (flags & GEOD_ARCMODE || fabs(l->f) > 0.01)
       B12 = SinCosSeries(TRUE, ssig2, csig2, l->C1a, nC1);
     AB1 = (1 + l->A1m1) * (B12 - l->B11);
   }
@@ -446,26 +445,29 @@ real geod_genposition(const struct geod_geodesicline* l,
   if (cbet2 == 0)
     /* I.e., salp0 = 0, csig2 = 0.  Break the degeneracy in this case */
     cbet2 = csig2 = tiny;
-  /* tan(omg2) = sin(alp0) * tan(sig2) */
-  somg2 = l->salp0 * ssig2; comg2 = csig2;  /* No need to normalize */
   /* tan(alp0) = cos(sig2)*tan(alp2) */
   salp2 = l->salp0; calp2 = l->calp0 * csig2; /* No need to normalize */
-  /* omg12 = omg2 - omg1 */
-  omg12 = atan2(somg2 * l->comg1 - comg2 * l->somg1,
-                comg2 * l->comg1 + somg2 * l->somg1);
 
   if (outmask & GEOD_DISTANCE)
-    s12 = arcmode ? l->b * ((1 + l->A1m1) * sig12 + AB1) : s12_a12;
+    s12 = flags & GEOD_ARCMODE ? l->b * ((1 + l->A1m1) * sig12 + AB1) : s12_a12;
 
   if (outmask & GEOD_LONGITUDE) {
+    /* tan(omg2) = sin(alp0) * tan(sig2) */
+    somg2 = l->salp0 * ssig2; comg2 = csig2;  /* No need to normalize */
+    /* omg12 = omg2 - omg1 */
+    omg12 = flags & GEOD_LONG_NOWRAP ? sig12
+      - (atan2(ssig2, csig2) - atan2(l->ssig1, l->csig1))
+      + (atan2(somg2, comg2) - atan2(l->somg1, l->comg1))
+      : atan2(somg2 * l->comg1 - comg2 * l->somg1,
+              comg2 * l->comg1 + somg2 * l->somg1);
     lam12 = omg12 + l->A3c *
       ( sig12 + (SinCosSeries(TRUE, ssig2, csig2, l->C3a, nC3-1)
                  - l->B31));
     lon12 = lam12 / degree;
     /* Use AngNormalize2 because longitude might have wrapped multiple
      * times. */
-    lon12 = AngNormalize2(lon12);
-    lon2 = AngNormalize(l->lon1 + lon12);
+    lon2 = flags & GEOD_LONG_NOWRAP ? l->lon1 + lon12 :
+      AngNormalize(AngNormalize(l->lon1) + AngNormalize2(lon12));
   }
 
   if (outmask & GEOD_LATITUDE)
@@ -542,7 +544,7 @@ real geod_genposition(const struct geod_geodesicline* l,
   if (outmask & GEOD_AREA)
     *pS12 = S12;
 
-  return arcmode ? s12_a12 : sig12 / degree;
+  return flags & GEOD_ARCMODE ? s12_a12 : sig12 / degree;
 }
 
 void geod_position(const struct geod_geodesicline* l, real s12,
@@ -552,7 +554,7 @@ void geod_position(const struct geod_geodesicline* l, real s12,
 
 real geod_gendirect(const struct geod_geodesic* g,
                     real lat1, real lon1, real azi1,
-                    boolx arcmode, real s12_a12,
+                    unsigned flags, real s12_a12,
                     real* plat2, real* plon2, real* pazi2,
                     real* ps12, real* pm12, real* pM12, real* pM21,
                     real* pS12) {
@@ -568,8 +570,9 @@ real geod_gendirect(const struct geod_geodesic* g,
 
   geod_lineinit(&l, g, lat1, lon1, azi1,
                 /* Automatically supply GEOD_DISTANCE_IN if necessary */
-                outmask | (arcmode ? GEOD_NONE : GEOD_DISTANCE_IN));
-  return geod_genposition(&l, arcmode, s12_a12,
+                outmask |
+                (flags & GEOD_ARCMODE ? GEOD_NONE : GEOD_DISTANCE_IN));
+  return geod_genposition(&l, flags, s12_a12,
                           plat2, plon2, pazi2, ps12, pm12, pM12, pM21, pS12);
 }
 
@@ -577,7 +580,7 @@ void geod_direct(const struct geod_geodesic* g,
                  real lat1, real lon1, real azi1,
                  real s12,
                  real* plat2, real* plon2, real* pazi2) {
-  geod_gendirect(g, lat1, lon1, azi1, FALSE, s12, plat2, plon2, pazi2,
+  geod_gendirect(g, lat1, lon1, azi1, GEOD_NOFLAGS, s12, plat2, plon2, pazi2,
                  0, 0, 0, 0, 0);
 }
 
@@ -1516,6 +1519,13 @@ int transit(real lon1, real lon2) {
     (lon2 < 0 && lon1 >= 0 && lon12 < 0 ? -1 : 0);
 }
 
+int transitdirect(real lon1, real lon2) {
+  lon1 = fmod(lon1, (real)(720));
+  lon2 = fmod(lon2, (real)(720));
+  return ( ((lon2 >= 0 && lon2 < 360) || lon2 < -360 ? 0 : 1) -
+           ((lon1 >= 0 && lon1 < 360) || lon1 < -360 ? 0 : 1) );
+}
+
 void accini(real s[]) {
   /* Initialize an accumulator; this is an array with two elements. */
   s[0] = s[1] = 0;
@@ -1583,13 +1593,13 @@ void geod_polygon_addedge(const struct geod_geodesic* g,
                           real azi, real s) {
   if (p->num) {                 /* Do nothing is num is zero */
     real lat, lon, S12;
-    geod_gendirect(g, p->lat, p->lon, azi, FALSE, s,
+    geod_gendirect(g, p->lat, p->lon, azi, GEOD_LONG_NOWRAP, s,
                    &lat, &lon, 0,
                    0, 0, 0, 0, p->polyline ? 0 : &S12);
     accadd(p->P, s);
     if (!p->polyline) {
       accadd(p->A, S12);
-      p->crossings += transit(p->lon, lon);
+      p->crossings += transitdirect(p->lon, lon);
     }
     p->lat = lat; p->lon = lon;
     ++p->num;
@@ -1720,11 +1730,11 @@ unsigned geod_polygon_testedge(const struct geod_geodesic* g,
   crossings = p->crossings;
   {
     real lat, lon, s12, S12;
-    geod_gendirect(g, p->lat, p->lon, azi, FALSE, s,
+    geod_gendirect(g, p->lat, p->lon, azi, GEOD_LONG_NOWRAP, s,
                    &lat, &lon, 0,
                    0, 0, 0, 0, &S12);
     tempsum += S12;
-    crossings += transit(p->lon, lon);
+    crossings += transitdirect(p->lon, lon);
     geod_geninverse(g, lat,  lon, p->lat0,  p->lon0,
                     &s12, 0, 0, 0, 0, 0, &S12);
     perimeter += s12;
diff --git a/legacy/C/geodesic.h b/legacy/C/geodesic.h
index 5efa63f..a92323b 100644
--- a/legacy/C/geodesic.h
+++ b/legacy/C/geodesic.h
@@ -75,18 +75,18 @@
  * (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 point at a pole).  If \e azi1 = \e
- *   azi2, the geodesic is unique.  Otherwise there are two geodesics
+ * - \e lat1 = −\e lat2 (with neither point 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 point at a pole).  If
- *   \e azi1 = 0° or ±180°, the geodesic is unique.
+ * - \e lon2 = \e lon1 ± 180° (with neither point 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 \e lat2 is near
- *   −\e lat1 for prolate ellipsoids.)
+ *   setting [\e azi1, \e azi2] = [−\e azi1, −\e azi2], \e S12
+ *   = −\e S12.  (This occurs when \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
@@ -103,17 +103,17 @@
  * to the member functions.  Most of the internal comments have been retained.
  * However, in the process of transcription some documentation has been lost
  * and the documentation for the C++ classes, GeographicLib::Geodesic,
- * GeographicLib::GeodesicLine, and GeographicLib::PolygonArea, should be
+ * GeographicLib::GeodesicLine, and GeographicLib::PolygonAreaT, should be
  * consulted.  The C++ code remains the "reference implementation".  Think
  * twice about restructuring the internals of the C code since this may make
  * porting fixes from the C++ code more difficult.
  *
- * Copyright (c) Charles Karney (2012-2013) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2012-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
  * This library was distributed with
- * <a href="../index.html">GeographicLib</a> 1.32.
+ * <a href="../index.html">GeographicLib</a> 1.39.
  **********************************************************************/
 
 #if !defined(GEODESIC_H)
@@ -128,7 +128,7 @@
  * The minor version of the geodesic library.  (This tracks the version of
  * GeographicLib.)
  **********************************************************************/
-#define GEODESIC_VERSION_MINOR 32
+#define GEODESIC_VERSION_MINOR 39
 /**
  * The patch level of the geodesic library.  (This tracks the version of
  * GeographicLib.)
@@ -381,11 +381,13 @@ extern "C" {
    * @param[in] lat1 latitude of point 1 (degrees).
    * @param[in] lon1 longitude of point 1 (degrees).
    * @param[in] azi1 azimuth at point 1 (degrees).
-   * @param[in] arcmode flag determining the meaning of the \e
-   *   s12_a12.
-   * @param[in] s12_a12 if \e arcmode is 0, this is the distance between
-   *   point 1 and point 2 (meters); otherwise it is the arc length between
-   *   point 1 and point 2 (degrees); it can be negative.
+   * @param[in] flags bitor'ed combination of geod_flags(); \e flags &
+   *   GEOD_ARCMODE determines the meaning of \e s12_a12 and \e flags &
+   *   GEOD_LONG_NOWRAP prevents the value of \e lon2 being wrapped into
+   *   the range [−180°, 180°).
+   * @param[in] s12_a12 if \e flags & GEOD_ARCMODE is 0, this is the distance
+   *   between point 1 and point 2 (meters); otherwise it is the arc length
+   *   between point 1 and point 2 (degrees); it can be negative.
    * @param[out] plat2 pointer to the latitude of point 2 (degrees).
    * @param[out] plon2 pointer to the longitude of point 2 (degrees).
    * @param[out] pazi2 pointer to the (forward) azimuth at point 2 (degrees).
@@ -402,14 +404,21 @@ extern "C" {
    *
    * \e g must have been initialized with a call to geod_init().  \e lat1
    * should be in the range [−90°, 90°]; \e lon1 and \e azi1
-   * should be in the range [−540°, 540°).  The function value \e
-   * a12 equals \e s12_a12 is \e arcmode is non-zero.  Any of the "return"
-   * arguments \e plat2, etc., may be replaced by 0, if you do not need some
-   * quantities computed.
+   * should be in the range [−540°, 540°).  The function
+   * value \e a12 equals \e s12_a12 if \e flags & GEOD_ARCMODE.  Any of the
+   * "return" arguments \e plat2, etc., may be replaced by 0, if you do not
+   * need some quantities computed.
+   *
+   * With \e flags & GEOD_LONG_NOWRAP bit set, the quantity \e lon2 −
+   * \e lon1 indicates how many times the geodesic wrapped around the
+   * ellipsoid.  Because \e lon2 might be outside the normal allowed range
+   * for longitudes, [−540°, 540°), be sure to normalize it,
+   * e.g., with fmod(\e lon2, 360.0) before using it in subsequent
+   * calculations
    **********************************************************************/
   double geod_gendirect(const struct geod_geodesic* g,
                         double lat1, double lon1, double azi1,
-                        int arcmode, double s12_a12,
+                        unsigned flags, double s12_a12,
                         double* plat2, double* plon2, double* pazi2,
                         double* ps12, double* pm12, double* pM12, double* pM21,
                         double* pS12);
@@ -453,12 +462,16 @@ extern "C" {
    *
    * @param[in] l a pointer to the geod_geodesicline object specifying the
    *   geodesic line.
-   * @param[in] arcmode flag determining the meaning of the second parameter;
-   *   if arcmode is 0, then \e l must have been initialized with \e caps |=
+   * @param[in] flags bitor'ed combination of geod_flags(); \e flags &
+   *   GEOD_ARCMODE determines the meaning of \e s12_a12 and \e flags &
+   *   GEOD_LONG_NOWRAP prevents the value of \e lon2 being wrapped into
+   *   the range [−180°, 180°); if \e flags & GEOD_ARCMODE is
+   *   0, then \e l must have been initialized with \e caps |=
    *   GEOD_DISTANCE_IN.
-   * @param[in] s12_a12 if \e arcmode is 0, this is the distance between
-   *   point 1 and point 2 (meters); otherwise it is the arc length between
-   *   point 1 and point 2 (degrees); it can be negative.
+   * @param[in] s12_a12 if \e flags & GEOD_ARCMODE is 0, this is the
+   *   distance between point 1 and point 2 (meters); otherwise it is the
+   *   arc length between point 1 and point 2 (degrees); it can be
+   *   negative.
    * @param[out] plat2 pointer to the latitude of point 2 (degrees).
    * @param[out] plon2 pointer to the longitude of point 2 (degrees); requires
    *   that \e l was initialized with \e caps |= GEOD_LONGITUDE.
@@ -480,11 +493,18 @@ extern "C" {
    * @return \e a12 arc length of between point 1 and point 2 (degrees).
    *
    * \e l must have been initialized with a call to geod_lineinit() with \e
-   * caps |= GEOD_DISTANCE_IN.  The values of \e lon2 and \e azi2 returned are
-   * in the range [−180°, 180°).  Any of the "return" arguments
-   * \e plat2, etc., may be replaced by 0, if you do not need some quantities
-   * computed.  Requesting a value which \e l is not capable of computing is
-   * not an error; the corresponding argument will not be altered.
+   * caps |= GEOD_DISTANCE_IN.  The value \e azi2 returned is in the range
+   * [−180°, 180°).  Any of the "return" arguments \e plat2,
+   * etc., may be replaced by 0, if you do not need some quantities
+   * computed.  Requesting a value which \e l is not capable of computing
+   * is not an error; the corresponding argument will not be altered.
+   *
+   * With \e flags & GEOD_LONG_NOWRAP bit set, the quantity \e lon2 −
+   * \e lon1 indicates how many times the geodesic wrapped around the
+   * ellipsoid.  Because \e lon2 might be outside the normal allowed range
+   * for longitudes, [−540°, 540°), be sure to normalize it,
+   * e.g., with fmod(\e lon2, 360.0) before using it in subsequent
+   * calculations
    *
    * Example, compute way points between JFK and Singapore Changi Airport
    * using geod_genposition().  In this example, the points are evenly space in
@@ -494,7 +514,7 @@ extern "C" {
    @code
    struct geod_geodesic g;
    struct geod_geodesicline l;
-   double a12, azi1, lat[101],lon[101];
+   double a12, azi1, lat[101], lon[101];
    int i;
    geod_init(&g, 6378137, 1/298.257223563);
    a12 = geod_geninverse(&g, 40.64, -73.78, 1.36, 103.99,
@@ -508,7 +528,7 @@ extern "C" {
    @endcode
    **********************************************************************/
   double geod_genposition(const struct geod_geodesicline* l,
-                          int arcmode, double s12_a12,
+                          unsigned flags, double s12_a12,
                           double* plat2, double* plon2, double* pazi2,
                           double* ps12, double* pm12,
                           double* pM12, double* pM21,
@@ -526,6 +546,10 @@ extern "C" {
    * polylinep is non-zero, then the vertices and edges define a polyline and
    * only the perimeter is returned by geod_polygon_compute().
    *
+   * The area and perimeter are accumulated at two times the standard floating
+   * point precision to guard against the loss of accuracy with many-sided
+   * polygons.  At any point you can ask for the perimeter and area so far.
+   *
    * An example of the use of this function is given in the documentation for
    * geod_polygon_compute().
    **********************************************************************/
@@ -592,10 +616,12 @@ extern "C" {
    *   polyline (meters).
    * @return the number of points.
    *
-   * Only simple polygons (which are not self-intersecting) are allowed.
-   * There's no need to "close" the polygon by repeating the first vertex.  Set
-   * \e pA or \e pP to zero, if you do not want the corresponding quantity
-   * returned.
+   * The area and perimeter are accumulated at two times the standard floating
+   * point precision to guard against the loss of accuracy with many-sided
+   * polygons.  Only simple polygons (which are not self-intersecting) are
+   * allowed.  There's no need to "close" the polygon by repeating the first
+   * vertex.  Set \e pA or \e pP to zero, if you do not want the corresponding
+   * quantity returned.
    *
    * Example, compute the perimeter and area of the geodesic triangle with
    * vertices (0°N,0°E), (0°N,90°E), (90°N,0°E).
@@ -704,7 +730,7 @@ extern "C" {
    * area returned is signed with counter-clockwise traversal being treated as
    * positive.
    *
-   * Example, compute the area of Antarctic:
+   * Example, compute the area of Antarctica:
    @code
    double
      lats[] = {-72.9, -71.9, -74.9, -74.3, -77.5, -77.4, -71.7, -65.9, -65.7,
@@ -723,7 +749,7 @@ extern "C" {
                         double* pA, double* pP);
 
   /**
-   * mask values for the the \e caps argument to geod_lineinit().
+   * mask values for the \e caps argument to geod_lineinit().
    **********************************************************************/
   enum geod_mask {
     GEOD_NONE         = 0U,                     /**< Calculate nothing */
@@ -738,6 +764,16 @@ extern "C" {
     GEOD_ALL          = 0x7F80U| 0x1FU          /**< Calculate everything */
   };
 
+  /**
+   * flag values for the \e flags argument to geod_gendirect() and
+   * geod_genposition()
+   **********************************************************************/
+  enum geod_flags {
+    GEOD_NOFLAGS      = 0U,     /**< No flags */
+    GEOD_ARCMODE      = 1U<<0,  /**< Position given in terms of arc distance */
+    GEOD_LONG_NOWRAP  = 1U<<15  /**< Don't wrap longitude */
+  };
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/legacy/Fortran/00README.txt b/legacy/Fortran/00README.txt
index ecc4027..de2f01f 100644
--- a/legacy/Fortran/00README.txt
+++ b/legacy/Fortran/00README.txt
@@ -25,3 +25,8 @@ Linux systems you might do:
   cmake ..
   make
   echo 30 0 29.5 179.5 | ./geodinverse
+
+The two tools ngsforward and ngsinverse are replacements for the NGS
+tools FORWARD and INVERSE available from
+
+  http://www.ngs.noaa.gov/PC_PROD/Inv_Fwd/
diff --git a/legacy/Fortran/CMakeLists.txt b/legacy/Fortran/CMakeLists.txt
index 5006446..80ce998 100644
--- a/legacy/Fortran/CMakeLists.txt
+++ b/legacy/Fortran/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.4)
 
 project (GeographicLib-legacy-Fortran Fortran)
 
@@ -8,13 +8,16 @@ if (NOT CMAKE_CONFIGURATION_TYPES AND NOT CMAKE_BUILD_TYPE)
   set (CMAKE_BUILD_TYPE Release)
 endif ()
 
-set (CMAKE_Fortran_FLAGS
-  "${CMAKE_Fortran_FLAGS} -Wall -Wextra -pedantic -std=f95 -fimplicit-none")
-# -Wextra now turns on warnings about comparing reals for equality
-set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -Wno-compare-reals")
-
 set (TOOLS geoddirect geodinverse planimeter)
 
 foreach (TOOL ${TOOLS})
   add_executable (${TOOL} ${TOOL}.for geodesic.for geodesic.inc)
 endforeach ()
+set_target_properties (${TOOLS} PROPERTIES COMPILE_FLAGS
+  "-Wall -Wextra -pedantic -std=f95 -fimplicit-none -Wno-compare-reals")
+
+# Work alikes for NGS geodesic tools.  This uses legacy code from NGS
+# and so they trigger multiple errors and warnings if compiled with the
+# compile flags above.
+add_executable (ngsforward ngsforward.for ngscommon.for geodesic.for)
+add_executable (ngsinverse ngsinverse.for ngscommon.for geodesic.for)
diff --git a/legacy/Fortran/geoddirect.for b/legacy/Fortran/geoddirect.for
index 98c5e80..4cc9048 100644
--- a/legacy/Fortran/geoddirect.for
+++ b/legacy/Fortran/geoddirect.for
@@ -13,19 +13,18 @@
 
       double precision a, f, lat1, lon1, azi1, lat2, lon2, azi2, s12,
      +    dummy
-      logical arcmod
-      integer omask
+      integer flags, omask
 
 * WGS84 values
       a = 6378137d0
       f = 1/298.257223563d0
 
-      arcmod = .false.
+      flags = 0
       omask = 0
 
  10   continue
       read(*, *, end=90, err=90) lat1, lon1, azi1, s12
-      call direct(a, f, lat1, lon1, azi1, s12, arcmod,
+      call direct(a, f, lat1, lon1, azi1, s12, flags,
      +    lat2, lon2, azi2, omask, dummy, dummy, dummy, dummy, dummy)
       print 20, lat2, lon2, azi2
  20   format(f20.15, 1x, f20.15, 1x, f20.15)
diff --git a/legacy/Fortran/geodesic.for b/legacy/Fortran/geodesic.for
index aaef081..8873cbc 100644
--- a/legacy/Fortran/geodesic.for
+++ b/legacy/Fortran/geodesic.for
@@ -107,17 +107,17 @@
 *! However, in the process of transcription some documentation has been
 *! lost and the documentation for the C++ classes,
 *! GeographicLib::Geodesic, GeographicLib::GeodesicLine, and
-*! GeographicLib::PolygonArea, should be consulted.  The C++ code
+*! GeographicLib::PolygonAreaT, should be consulted.  The C++ code
 *! remains the "reference implementation".  Think twice about
 *! restructuring the internals of the Fortran code since this may make
 *! porting fixes from the C++ code more difficult.
 *!
-*! Copyright (c) Charles Karney (2012-2013) <charles at karney.com> and
+*! Copyright (c) Charles Karney (2012-2014) <charles at karney.com> and
 *! licensed under the MIT/X11 License.  For more information, see
 *! http://geographiclib.sourceforge.net/
 *!
 *! This library was distributed with
-*! <a href="../index.html">GeographicLib</a> 1.31.
+*! <a href="../index.html">GeographicLib</a> 1.39.
 
 *> Solve the direct geodesic problem
 *!
@@ -127,17 +127,17 @@
 *! @param[in] lat1 latitude of point 1 (degrees).
 *! @param[in] lon1 longitude of point 1 (degrees).
 *! @param[in] azi1 azimuth at point 1 (degrees).
-*! @param[in] s12a12 if \e arcmod is false, this is the distance between
-*!   point 1 and point 2 (meters); otherwise it is the arc length
-*!   between point 1 and point 2 (degrees); it can be negative.
-*! @param[in] arcmod logical flag determining the meaning of the \e
-*!   s12a12.
+*! @param[in] s12a12 if \e arcmode is not set, this is the distance
+*!   between point 1 and point 2 (meters); otherwise it is the arc
+*!   length between point 1 and point 2 (degrees); it can be negative.
+*! @param[in] flags a bitor'ed combination of the \e arcmode and \e
+*!   nowrap flags.
 *! @param[out] lat2 latitude of point 2 (degrees).
 *! @param[out] lon2 longitude of point 2 (degrees).
 *! @param[out] azi2 (forward) azimuth at point 2 (degrees).
 *! @param[in] omask a bitor'ed combination of mask values
 *!   specifying which of the following parameters should be set.
-*! @param[out] a12s12 if \e arcmod is false, this is the arc length
+*! @param[out] a12s12 if \e arcmode is not set, this is the arc length
 *!   between point 1 and point 2 (degrees); otherwise it is the distance
 *!   between point 1 and point 2 (meters).
 *! @param[out] m12 reduced length of geodesic (meters).
@@ -147,6 +147,20 @@
 *!   (dimensionless).
 *! @param[out] SS12 area under the geodesic (meters<sup>2</sup>).
 *!
+*! \e flags is an integer in [0, 4) whose binary bits are interpreted
+*! as follows
+*! - 1 the \e arcmode flag
+*! - 2 the \e nowrap flag
+*! .
+*! If \e arcmode is not set, \e s12a12 is \e s12 and \e a12s12 is \e
+*! a12; otherwise, \e s12a12 is \e a12 and \e a12s12 is \e s12.  It \e
+*! nowrap is not set, the value \e lon2 returned is in the range
+*! [−180°, 180°); otherwise \e lon2 &minus \e lon1
+*! indicates how many times the geodesic wrapped around the ellipsoid.
+*! Because \e lon2 might be outside the normal allowed range for
+*! longitudes, [−540°, 540°), be sure to reduces its range
+*! with mod(\e lon2, 360d0) before using it in other calls.
+*!
 *! \e omask is an integer in [0, 16) whose binary bits are interpreted
 *! as follows
 *! - 1 return \e a12
@@ -156,8 +170,7 @@
 *!
 *! \e lat1 should be in the range [−90°, 90°]; \e lon1 and
 *! \e azi1 should be in the range [−540°, 540°).  The
-*! values of \e lon2 and \e azi2 returned are in the range
-*! [−180°, 180°).
+*! value \e azi2 returned is in the range [−180°, 180°).
 *!
 *! If either point is at a pole, the azimuth is defined by keeping the
 *! longitude fixed, writing \e lat = \e lat = ±(90° −
@@ -167,12 +180,11 @@
 *! for a shortest path: the longitudinal extent must not exceed of
 *! 180°.)
 
-      subroutine direct(a, f, lat1, lon1, azi1, s12a12, arcmod,
+      subroutine direct(a, f, lat1, lon1, azi1, s12a12, flags,
      +    lat2, lon2, azi2, omask, a12s12, m12, MM12, MM21, SS12)
 * input
       double precision a, f, lat1, lon1, azi1, s12a12
-      logical arcmod
-      integer omask
+      integer flags, omask
 * output
       double precision lat2, lon2, azi2
 * optional output
@@ -188,7 +200,7 @@
 
       double precision csmgt, atanhx, hypotx,
      +    AngNm, AngNm2, AngRnd, TrgSum, A1m1f, A2m1f, A3f
-      logical arcp, redlp, scalp, areap
+      logical arcmod, nowrap, arcp, redlp, scalp, areap
       double precision e2, f1, ep2, n, b, c2,
      +    lon1x, azi1x, phi, alp1, salp0, calp0, k2, eps,
      +    salp1, calp1, ssig1, csig1, cbet1, sbet1, dn1, somg1, comg1,
@@ -214,6 +226,9 @@
       b = a * f1
       c2 = 0
 
+      arcmod = mod(flags/1, 2) == 1
+      nowrap = mod(flags/2, 2) == 1
+
       arcp = mod(omask/1, 2) == 1
       redlp = mod(omask/2, 2) == 1
       scalp = mod(omask/4, 2) == 1
@@ -394,8 +409,12 @@
       salp2 = salp0
       calp2 = calp0 * csig2
 * omg12 = omg2 - omg1
-      omg12 = atan2(somg2 * comg1 - comg2 * somg1,
-     +    comg2 * comg1 + somg2 * somg1)
+      omg12 = csmgt(sig12
+     +    - (atan2(ssig2, csig2) - atan2(ssig1, csig1))
+     +    + (atan2(somg2, comg2) - atan2(somg1, comg1)),
+     +    atan2(somg2 * comg1 - comg2 * somg1,
+     +    comg2 * comg1 + somg2 * somg1),
+     +    nowrap)
 
       lam12 = omg12 + A3c *
      +    ( sig12 + (TrgSum(.true., ssig2, csig2, C3a, nC3-1)
@@ -403,8 +422,7 @@
       lon12 = lam12 / degree
 * Use Math::AngNm2 because longitude might have wrapped multiple
 * times.
-      lon12 = AngNm2(lon12)
-      lon2 = AngNm(lon1x + lon12)
+      lon2 = csmgt(lon1 + lon12, AngNm(lon1x + AngNm2(lon12)), nowrap)
       lat2 = atan2(sbet2, f1 * cbet2) / degree
 * minus signs give range [-180, 180). 0- converts -0 to +0.
       azi2 = 0 - atan2(-salp2, calp2) / degree
@@ -1997,4 +2015,5 @@
 *    SinCosSeries  TrgSum
 *    xthresh       xthrsh
 *    transit       trnsit
+*    LONG_NOWRAP   nowrap
 *> @endcond SKIP
diff --git a/legacy/Fortran/geodesic.inc b/legacy/Fortran/geodesic.inc
index 9b68660..0106b34 100644
--- a/legacy/Fortran/geodesic.inc
+++ b/legacy/Fortran/geodesic.inc
@@ -9,11 +9,10 @@
 
       interface
 
-        subroutine direct(a, f, lat1, lon1, azi1, s12a12, arcmod,
+        subroutine direct(a, f, lat1, lon1, azi1, s12a12, flags,
      +      lat2, lon2, azi2, omask, a12s12, m12, MM12, MM21, SS12)
         double precision, intent(in) :: a, f, lat1, lon1, azi1, s12a12
-        logical, intent(in) :: arcmod
-        integer, intent(in) :: omask
+        integer, intent(in) :: flags, omask
         double precision, intent(out) :: lat2, lon2, azi2
         double precision, intent(out) :: a12s12, m12, MM12, MM21, SS12
         end subroutine direct
diff --git a/legacy/Fortran/ngscommon.for b/legacy/Fortran/ngscommon.for
new file mode 100644
index 0000000..96e5bab
--- /dev/null
+++ b/legacy/Fortran/ngscommon.for
@@ -0,0 +1,806 @@
+      subroutine bufdms (buff,lgh,hem,dd,dm,ds,ierror)
+      implicit double precision (a-h, o-z)
+      implicit integer (i-n)
+c
+      logical     done,flag
+c
+      character*1 buff(*),abuf(21)
+      character*1 ch
+      character*1 hem
+      integer*4   ll,lgh
+      integer*4   i4,id,im,is,icond,ierror
+      real*8      x(5)
+c
+c     set the "error flag"
+c
+      ierror = 0
+      icond  = 0
+c
+c     set defaults for dd,dm,ds
+c
+      dd = 0.0d0
+      dm = 0.0d0
+      ds = 0.0d0
+c
+c     set default limits for "hem" flag
+c
+      if(     hem.eq.'N' .or. hem.eq.'S' )then
+        ddmax = 90.0d0
+      elseif( hem.eq.'E' .or. hem.eq.'W' )then
+        ddmax = 360.0d0
+      elseif( hem.eq.'A' )then
+        ddmax = 360.0d0
+      elseif( hem.eq.'Z' )then
+        ddmax = 180.0d0
+      elseif( hem.eq.'*' )then
+        ddmax  = 0.0d0
+        ierror = 1
+      else
+        ddmax = 360.0d0
+      endif
+c
+      do 1 i=1,5
+        x(i) = 0.0d0
+    1 continue
+c
+      icolon = 0
+      ipoint = 0
+      icount = 0
+      flag   = .true.
+      jlgh   = lgh
+c
+      do 2 i=1,jlgh
+        if( buff(i).eq.':' )then
+          icolon = icolon+1
+        endif
+        if( buff(i).eq.'.' )then
+          ipoint = ipoint+1
+          flag   = .false.
+        endif
+        if( flag )then
+          icount = icount+1
+        endif
+    2 continue
+c
+      if( ipoint.eq.1 .and. icolon.eq.0 )then
+c
+c       load temp buffer
+c
+        do 3 i=1,jlgh
+          abuf(i) = buff(i)
+    3   continue
+        abuf(jlgh+1) = '$'
+        ll = jlgh
+c
+        call gvalr8 (abuf,ll,r8,icond)
+c
+        if( icount.ge.5 )then
+c
+c         value is a packed decimal of ==>  DDMMSS.sssss
+c
+          ss = r8/10000.0d0
+          id = idint( ss )
+c
+          r8 = r8-10000.0d0*dble(float(id))
+          ss = r8/100.0d0
+          im = idint( ss )
+c
+          r8 = r8-100.0d0*dble(float(im))
+        else
+c
+c         value is a decimal of ==>  .xx   X.xxx   X.
+c
+          id = idint( r8 )
+          r8 = (r8-id)*60.0d0
+          im = idint( r8 )
+          r8 = (r8-im)*60.0d0
+        endif
+c
+c       account for rounding error
+c
+        is = idnint( r8*1.0d5 )
+        if( is.ge.6000000 )then
+           r8 = 0.0d0
+           im = im+1
+        endif
+c
+        if( im.ge.60 )then
+          im = 0
+          id = id+1
+        endif
+c
+        dd = dble( float( id ) )
+        dm = dble( float( im ) )
+        ds = r8
+      else
+c
+c       buff() value is a d,m,s of ==>  NN:NN:XX.xxx
+c
+        k    = 0
+        next = 1
+        done = .false.
+        ie   = jlgh
+c
+        do 100 j=1,5
+          ib = next
+          do 90 i=ib,ie
+            ch   = buff(i)
+            last = i
+            if( i.eq.jlgh .or. ch.eq.':' )then
+              if( i.eq.jlgh )then
+                done = .true.
+              endif
+              if( ch.eq.':' )then
+                last = i-1
+              endif
+              goto 91
+            endif
+   90     continue
+          goto 98
+c
+   91     ipoint = 0
+          ik     = 0
+          do 92 i=next,last
+            ik = ik+1
+            ch = buff(i)
+            if( ch.eq.'.' )then
+              ipoint = ipoint+1
+            endif
+            abuf(ik) = buff(i)
+   92     continue
+          abuf(ik+1) = '$'
+c
+          ll = ik
+          if( ipoint.eq.0 )then
+            call gvali4 (abuf,ll,i4,icond)
+            r8 = dble(float( i4 ))
+          else
+            call gvalr8 (abuf,ll,r8,icond)
+          endif
+c
+          k    = k+1
+          x(k) = r8
+c
+   98     if( done )then
+            goto 101
+          endif
+c
+          next = last
+   99     next = next+1
+          if( buff(next).eq.':' )then
+            goto 99
+          endif
+  100   continue
+c
+c       load dd,dm,ds
+c
+  101   if( k.ge.1 )then
+          dd = x(1)
+        endif
+c
+        if( k.ge.2 )then
+          dm = x(2)
+        endif
+c
+        if( k.ge.3 )then
+          ds = x(3)
+        endif
+      endif
+c
+      if( dd.gt.ddmax  .or.
+     1    dm.ge.60.0d0 .or.
+     1    ds.ge.60.0d0 )then
+        ierror = 1
+        dd = 0.0d0
+        dm = 0.0d0
+        ds = 0.0d0
+      endif
+c
+      if( icond.ne.0 )then
+        ierror = 1
+      endif
+c
+      return
+      end
+
+      subroutine elipss (elips)
+      implicit double precision(a-h,o-z)
+      character*1  answer
+      character*30 elips
+      common/elipsoid/a,f
+      write(*,*) '  Other Ellipsoids.'
+      write(*,*) '  -----------------'
+      write(*,*) '  '
+      write(*,*) '  A) Airy 1858'
+      write(*,*) '  B) Airy Modified'
+      write(*,*) '  C) Australian National'
+      write(*,*) '  D) Bessel 1841'
+      write(*,*) '  E) Clarke 1880'
+      write(*,*) '  F) Everest 1830'
+      write(*,*) '  G) Everest Modified'
+      write(*,*) '  H) Fisher 1960'
+      write(*,*) '  I) Fisher 1968'
+      write(*,*) '  J) Hough 1956'
+      write(*,*) '  K) International (Hayford)'
+      write(*,*) '  L) Krassovsky 1938'
+      write(*,*) '  M) NWL-9D (WGS 66)'
+      write(*,*) '  N) South American 1969'
+      write(*,*) '  O) Soviet Geod. System 1985'
+      write(*,*) '  P) WGS 72'
+      write(*,*) '  Q-Z) User defined.'
+      write(*,*) '  '
+      write(*,*) '  Enter choice : '
+      read(*,10) answer
+   10 format(a1)
+c
+      if(answer.eq.'A'.or.answer.eq.'a') then
+        a=6377563.396d0
+        f=1.d0/299.3249646d0
+        elips='Airy 1858'
+      elseif(answer.eq.'B'.or.answer.eq.'b') then
+        a=6377340.189d0
+        f=1.d0/299.3249646d0
+        elips='Airy Modified'
+      elseif(answer.eq.'C'.or.answer.eq.'c') then
+        a=6378160.d0
+        f=1.d0/298.25d0
+        elips='Australian National'
+      elseif(answer.eq.'D'.or.answer.eq.'d') then
+        a=6377397.155d0
+        f=1.d0/299.1528128d0
+        elips='Bessel 1841'
+      elseif(answer.eq.'E'.or.answer.eq.'e') then
+        a=6378249.145d0
+        f=1.d0/293.465d0
+        elips='Clarke 1880'
+      elseif(answer.eq.'F'.or.answer.eq.'f') then
+        a=6377276.345d0
+        f=1.d0/300.8017d0
+        elips='Everest 1830'
+      elseif(answer.eq.'G'.or.answer.eq.'g') then
+        a=6377304.063d0
+        f=1.d0/300.8017d0
+        elips='Everest Modified'
+      elseif(answer.eq.'H'.or.answer.eq.'h') then
+        a=6378166.d0
+        f=1.d0/298.3d0
+        elips='Fisher 1960'
+      elseif(answer.eq.'I'.or.answer.eq.'i') then
+        a=6378150.d0
+        f=1.d0/298.3d0
+        elips='Fisher 1968'
+      elseif(answer.eq.'J'.or.answer.eq.'j') then
+        a=6378270.d0
+        f=1.d0/297.d0
+        elips='Hough 1956'
+      elseif(answer.eq.'K'.or.answer.eq.'k') then
+        a=6378388.d0
+        f=1.d0/297.d0
+        elips='International (Hayford)'
+      elseif(answer.eq.'L'.or.answer.eq.'l') then
+        a=6378245.d0
+        f=1.d0/298.3d0
+        elips='Krassovsky 1938'
+      elseif(answer.eq.'M'.or.answer.eq.'m') then
+        a=6378145.d0
+        f=1.d0/298.25d0
+        elips='NWL-9D  (WGS 66)'
+      elseif(answer.eq.'N'.or.answer.eq.'n') then
+        a=6378160.d0
+        f=1.d0/298.25d0
+        elips='South American 1969'
+      elseif(answer.eq.'O'.or.answer.eq.'o') then
+        a=6378136.d0
+        f=1.d0/298.257d0
+        elips='Soviet Geod. System 1985'
+      elseif(answer.eq.'P'.or.answer.eq.'p') then
+        a=6378135.d0
+        f=1.d0/298.26d0
+        elips='WGS 72'
+      else
+        elips = 'User defined.'
+c
+        write(*,*) '  Enter Equatorial axis,   a : '
+        read(*,*) a
+        a = dabs(a)
+c
+        write(*,*) '  Enter either Polar axis, b or '
+        write(*,*) '  Reciprocal flattening,   1/f : '
+        read(*,*) ss
+        ss = dabs(ss)
+c
+        f = 0.0d0
+        if( 200.0d0.le.ss .and. ss.le.310.0d0 )then
+          f = 1.d0/ss
+        elseif( 6000000.0d0.lt.ss .and. ss.lt.a )then
+          f = (a-ss)/a
+        else
+          elips = 'Error: default GRS80 used.'
+          a     = 6378137.0d0
+          f     = 1.0d0/298.25722210088d0
+        endif
+      endif
+c
+      return
+      end
+
+      subroutine fixdms (ideg, min, sec, tol )
+c
+      implicit double precision (a-h, o-z)
+      implicit integer (i-n)
+c
+c     test for seconds near 60.0-tol
+c
+      if( sec.ge.( 60.0d0-tol ) )then
+        sec  = 0.0d0
+        min  = min+1
+      endif
+c
+c     test for minutes near 60
+c
+      if( min.ge.60 )then
+        min  = 0
+        ideg = ideg+1
+      endif
+c
+c     test for degrees near 360
+c
+      if( ideg.ge.360 )then
+        ideg = 0
+      endif
+c
+      return
+      end
+
+      subroutine hem_ns ( lat_sn, hem )
+      implicit integer (i-n)
+      character*6  hem
+c
+      if( lat_sn.eq.1 ) then
+        hem = 'North '
+      else
+        hem = 'South '
+      endif
+c
+      return
+      end
+
+      subroutine hem_ew ( lon_sn, hem )
+      implicit integer (i-n)
+      character*6  hem
+c
+      if( lon_sn.eq.1 ) then
+        hem = 'East  '
+      else
+        hem = 'West  '
+      endif
+c
+      return
+      end
+
+      subroutine getdeg(d,m,sec,isign,val)
+
+*** comvert deg, min, sec to degrees
+
+      implicit double precision(a-h,j-z)
+
+      val=(d+m/60.d0+sec/3600.d0)
+      val=dble(isign)*val
+
+      return
+      end
+
+      subroutine gvali4 (buff,ll,vali4,icond)
+      implicit     integer (i-n)
+c
+      logical      plus,sign,done,error
+      character*1  buff(*)
+      character*1  ch
+c
+c     integer*2    i
+c     integer*2    l1
+c
+      integer*4    ich,icond
+      integer*4    ll
+      integer*4    vali4
+c
+      l1    = ll
+      vali4 = 0
+      icond = 0
+      plus  = .true.
+      sign  = .false.
+      done  = .false.
+      error = .false.
+c
+      i = 0
+   10 i = i+1
+      if( i.gt.l1 .or. done )then
+        go to 1000
+      else
+        ch  = buff(i)
+        ich = ichar( buff(i) )
+      endif
+c
+      if(     ch.eq.'+' )then
+c
+c       enter on plus sign
+c
+        if( sign )then
+          goto 150
+        else
+          sign = .true.
+          goto 10
+        endif
+      elseif( ch.eq.'-' )then
+c
+c       enter on minus sign
+c
+        if( sign )then
+          goto 150
+        else
+          sign = .true.
+          plus = .false.
+          goto 10
+        endif
+      elseif( ch.ge.'0' .and. ch.le.'9' )then
+        goto 100
+      elseif( ch.eq.' ' )then
+c
+c       enter on space -- ignore leading spaces
+c
+        if( .not.sign )then
+          goto 10
+        else
+          buff(i) = '0'
+          ich = 48
+          goto 100
+        endif
+      elseif( ch.eq.':' )then
+c
+c       enter on colon -- ignore
+c
+        if( .not.sign )then
+          goto 10
+        else
+          goto 1000
+        endif
+      elseif( ch.eq.'$' )then
+c
+c       enter on dollar "$"
+c
+        done = .true.
+        goto 10
+      else
+c
+c       something wrong
+c
+        goto 150
+      endif
+c
+c     enter on numeric
+c
+  100 vali4 = 10*vali4+(ich-48)
+      sign  = .true.
+      goto 10
+c
+c     treat illegal character
+c
+  150 buff(i) = '0'
+      vali4 = 0
+      icond = 1
+c
+ 1000 if( .not.plus )then
+        vali4 = -vali4
+      endif
+c
+      return
+      end
+
+      subroutine gvalr8 (buff,ll,valr8,icond)
+      implicit     integer (i-n)
+c
+      logical      plus,sign,dpoint,done
+c
+      character*1  buff(*)
+      character*1  ch
+c
+c     integer*2    i, ip
+c     integer*2    l1
+c     integer*2    nn, num, n48
+c
+      integer*4    ich,icond
+      integer*4    ll
+c
+      real*8       ten
+      real*8       valr8
+      real*8       zero
+c
+      data zero,ten/0.0d0,10.0d0/
+c
+      n48     =  48
+      l1      =  ll
+      icond   =   0
+      valr8   =  zero
+      plus    = .true.
+      sign    = .false.
+      dpoint  = .false.
+      done    = .false.
+c
+c     start loop thru buffer
+c
+      i = 0
+   10 i = i+1
+      if( i.gt.l1 .or. done )then
+        go to 1000
+      else
+        ch  = buff(i)
+        nn  = ichar( ch )
+        ich = nn
+      endif
+c
+      if(     ch.eq.'+' )then
+c
+c       enter on plus sign
+c
+        if( sign )then
+          goto 150
+        else
+          sign = .true.
+          goto 10
+        endif
+      elseif( ch.eq.'-' )then
+c
+c       enter on minus sign
+c
+        if( sign )then
+          goto 150
+        else
+          sign = .true.
+          plus = .false.
+          goto 10
+        endif
+      elseif( ch.eq.'.' )then
+c
+c       enter on decimal point
+c
+        ip     = 0
+        sign   = .true.
+        dpoint = .true.
+        goto 10
+      elseif( ch.ge.'0' .and. ch.le.'9' )then
+        goto 100
+      elseif( ch.eq.' ' )then
+c
+c       enter on space
+c
+        if( .not.sign )then
+          goto 10
+        else
+          buff(i) = '0'
+          ich = 48
+          goto 100
+        endif
+      elseif( ch.eq.':' .or. ch.eq.'$' )then
+c
+c       enter on colon or "$" sign
+c
+        done = .true.
+        goto 10
+      else
+c
+c       something wrong
+c
+        goto 150
+      endif
+c
+c     enter on numeric
+c
+  100 sign = .true.
+      if( dpoint )then
+        ip = ip+1
+      endif
+c
+      num   = ich
+      valr8 = ten*valr8+dble(float( num-n48 ))
+      goto 10
+c
+c     treat illegal character
+c
+  150 buff(i) = '0'
+      valr8   =  0.0d0
+      icond   =  1
+c
+ 1000 if( dpoint )then
+        valr8 =  valr8/(ten**ip)
+      endif
+c
+      if( .not.plus )then
+        valr8 = -valr8
+      endif
+c
+      return
+      end
+
+      subroutine todmsp(val,id,im,s,isign)
+
+*** convert position degrees to deg,min,sec
+*** range is [-180 to +180]
+
+      implicit double precision(a-h,o-z)
+
+    1 if(val.gt.180) then
+        val=val-180-180
+        go to 1
+      endif
+
+    2 if(val.lt.-180) then
+        val=val+180+180
+        go to 2
+      endif
+
+      if(val.lt.0.d0) then
+        isign=-1
+      else
+        isign=+1
+      endif
+
+      s=dabs(val)
+      id=idint(s)
+      s=(s-id)*60.d0
+      im=idint(s)
+      s=(s-im)*60.d0
+
+*** account for rounding error
+
+      is=idnint(s*1.d5)
+      if(is.ge.6000000) then
+        s=0.d0
+        im=im+1
+      endif
+      if(im.ge.60) then
+        im=0
+        id=id+1
+      endif
+
+      return
+      end
+
+      subroutine trim (buff,lgh,hem)
+c
+      implicit integer (i-n)
+      character*1 ch,hem
+      character*1 buff(*)
+      integer*4   lgh
+c
+      ibeg = 1
+      do 10 i=1,50
+        if( buff(i).ne.' ' )then
+          goto 11
+        endif
+        ibeg = ibeg+1
+   10 continue
+   11 continue
+      if( ibeg.ge.50 )then
+        ibeg = 1
+        buff(ibeg) = '0'
+      endif
+c
+      iend = 50
+      do 20 i=1,50
+        j = 51-i
+        if( buff(j).eq.' ' )then
+          iend = iend-1
+        else
+          goto 21
+        endif
+   20 continue
+   21 continue
+c
+      ch = buff(ibeg)
+      if( hem.eq.'N' )then
+        if( ch.eq.'N' .or. ch.eq.'n' .or. ch.eq.'+' )then
+          hem = 'N'
+          ibeg = ibeg+1
+        endif
+        if( ch.eq.'S' .or. ch.eq.'s' .or. ch.eq.'-' )then
+          hem = 'S'
+          ibeg = ibeg+1
+        endif
+c
+c       check for wrong hemisphere entry
+c
+        if( ch.eq.'E' .or. ch.eq.'e' )then
+          hem = '*'
+          ibeg = ibeg+1
+        endif
+        if( ch.eq.'W' .or. ch.eq.'w' )then
+          hem = '*'
+          ibeg = ibeg+1
+        endif
+      elseif( hem.eq.'W' )then
+        if( ch.eq.'E' .or. ch.eq.'e' .or. ch.eq.'+' )then
+          hem = 'E'
+          ibeg = ibeg+1
+        endif
+        if( ch.eq.'W' .or. ch.eq.'w' .or. ch.eq.'-' )then
+          hem = 'W'
+          ibeg = ibeg+1
+        endif
+c
+c       check for wrong hemisphere entry
+c
+        if( ch.eq.'N' .or. ch.eq.'n' )then
+          hem = '*'
+          ibeg = ibeg+1
+        endif
+        if( ch.eq.'S' .or. ch.eq.'s' )then
+          hem = '*'
+          ibeg = ibeg+1
+        endif
+      elseif( hem.eq.'A' )then
+        if( .not.('0'.le.ch .and. ch.le.'9') )then
+          hem = '*'
+          ibeg = ibeg+1
+        endif
+      else
+c        do nothing
+      endif
+c
+c
+      do 30 i=ibeg,iend
+        ch = buff(i)
+c
+        if(     ch.eq.':' .or. ch.eq.'.' )then
+          goto 30
+        elseif( ch.eq.' ' .or. ch.eq.',' )then
+          buff(i) = ':'
+        elseif( '0'.le.ch .and. ch.le.'9' )then
+          goto 30
+        else
+          buff(i) = ':'
+        endif
+c
+   30 continue
+c
+c     left justify buff() array to its first character position
+c     also check for a ":" char in the starting position,
+c     if found!!  skip it
+c
+      j  = 0
+      ib = ibeg
+      ie = iend
+c
+      do 40 i=ib,ie
+        if( i.eq.ibeg .and. buff(i).eq.':' )then
+c
+c         move the 1st position pointer to the next char &
+c         do not put ":" char in buff(j) array where j=1
+c
+          ibeg = ibeg+1
+          goto 40
+        endif
+        j = j+1
+        buff(j) = buff(i)
+   40 continue
+c
+c
+      lgh = iend-ibeg+1
+      j   = lgh+1
+      buff(j) = '$'
+c
+c     clean-up the rest of the buff() array
+c
+      do 50 i=j+1,50
+        buff(i) = ' '
+   50 continue
+c
+c     save a maximum of 20 characters
+c
+      if( lgh.gt.20 )then
+        lgh = 20
+        j   = lgh+1
+        buff(j) = '$'
+      endif
+c
+      return
+      end
diff --git a/legacy/Fortran/ngsforward.for b/legacy/Fortran/ngsforward.for
new file mode 100644
index 0000000..a279b95
--- /dev/null
+++ b/legacy/Fortran/ngsforward.for
@@ -0,0 +1,490 @@
+cb::forward
+c
+      program forward
+c
+c********1*********2*********3*********4*********5*********6*********7**
+c
+c name:      forward
+c version:   201211.29
+c author:    stephen j. frakes
+c last mod:  Charles Karney
+c purpose:   to compute a geodetic forward (direct problem)
+c            and then display output information
+c
+c input parameters:
+c -----------------
+c
+c output parameters:
+c ------------------
+c
+c local variables and constants:
+c ------------------------------
+c answer           user prompt response
+c arc              meridional arc distance latitude p1 to p2 (meters)
+c b                semiminor axis polar (in meters)
+c baz              azimuth back (in radians)
+c blimit           geodetic distance allowed on ellipsoid (in meters)
+c buff             input char buffer array
+c dd,dm,ds         temporary values for degrees, minutes, seconds
+c dmt,d_mt         char constants for units (in meters)
+c dd_max           maximum ellipsoid distance -1 (in meters)
+c edist            ellipsoid distance (in meters)
+c elips            ellipsoid choice
+c esq              eccentricity squared for reference ellipsoid
+c faz              azimuth forward (in radians)
+c filout           output file name
+c finv             reciprocal flattening
+c hem              hemisphere flag for lat & lon entry
+c ierror           error condition flag with d,m,s conversion
+c lgh              length of buff() array
+c option           user prompt response
+c r1,r2            temporary variables
+c ss               temporary value for ellipsoid distance
+c tol              tolerance for conversion of seconds
+c
+c name1            name of station one
+c ld1,lm1,sl1      latitude  sta one - degrees,minutes,seconds
+c ald1,alm1,sl1    latitude  sta one - degrees,minutes,seconds
+c lat1sn           latitude  sta one - sign (+/- 1)
+c d_ns1            latitude  sta one - char ('N','S')
+c lod1,lom1,slo1   longitude sta one - degrees,minutes,seconds
+c alod1,alom1,slo1 longitude sta one - degrees,minutes,seconds
+c lon1sn           longitude sta one - sign (+/- 1)
+c d_ew1            longitude sta one - char ('E','W')
+c iaz1,maz1,saz1   forward azimuth   - degrees,minutes,seconds
+c isign1           forward azimuth   - flag  (+/- 1)
+c azd1,azm1,saz1   forward azimuth   - degrees,minutes,seconds
+c iazsn            forward azimuth   - flag  (+/- 1)
+c glat1,glon1      station one       - (lat & lon in radians )
+c
+c name2            name of station two
+c ld2,lm2,sl2      latitude  sta two - degrees,minutes,seconds
+c lat2sn           latitude  sta two - sign (+/- 1)
+c d_ns2            latitude  sta two - char ('N','S')
+c lod2,lom2,slo2   longitude sta two - degrees,minutes,seconds
+c lon2sn           longitude sta two - sign (+/- 1)
+c d_ew2            longitude sta two - char ('E','W')
+c iaz2,maz2,saz2   back azimuth      - degrees,minutes,seconds
+c isign2           back azimuth      - flag  (+/- 1)
+c glat2,glon2      station two       - (lat & lon in radians )
+c
+c global variables and constants:
+c -------------------------------
+c a                semimajor axis equatorial (in meters)
+c f                flattening
+c pi               constant 3.14159....
+c rad              constant 180.0/pi
+c
+c    this module called by:  n/a
+c
+c    this module calls:      elipss, getdeg, dirct1, todmsp
+c    gethem, trim,   bufdms, gvalr8, gvali4, fixdms
+c    datan,  write,  read,   dabs,   open,   stop
+c
+c    include files used:     n/a
+c
+c    common blocks used:     const, elipsoid
+c
+c    references:             see comments within subroutines
+c
+c    comments:
+c
+c********1*********2*********3*********4*********5*********6*********7**
+c::modification history
+c::1990mm.dd, sjf, creation of program
+c::199412.15, bmt, creation of program on viper
+c::200203.08, crs, modified by c.schwarz to correct spelling of Clarke
+c::                at request of Dave Doyle
+c::200207.18, rws, modified i/o & standardized program documentation
+c::                added subs trim, bufdms, gethem, gvali4, gvalr8
+c::200207.23, rws, added sub gpnarc
+c::200208.15, rws, fixed an error in bufdms
+c::              - renamed ellips to elipss "common error" with dirct2
+c::              - added FAZ & BAZ to printed output
+c::200208.19, rws, added more error flags for web interface
+c::              - added logical nowebb
+c::200208.xx, sjf, program version number 2.0
+c::201211.29, cffk, program version number 3.1
+c::              - drop in replacement routines from
+c::                "Algorithms for Geodesics"
+c********1*********2*********3*********4*********5*********6*********7**
+ce::forward
+c
+      implicit double precision (a-h, o-z)
+      implicit integer (i-n)
+c
+      logical  nowebb
+c
+      character*1  answer,option,dmt,buff(50),hem
+      character*6  d_ns1, d_ew1, d_ns2, d_ew2, d_mt
+      character*30 filout,name1,name2,elips
+c
+      integer*4    ierror
+      integer*4    lgh
+c
+      common/const/pi,rad
+      common/elipsoid/a,f
+c
+c     ms_unix      0 = web version
+c                  1 = ms_dos or unix
+c
+      parameter   ( ms_unix = 0 )
+c
+      pi=4.d0*datan(1.d0)
+      rad=180.d0/pi
+      dmt='m'
+      d_mt='Meters'
+c
+      if( ms_unix.eq.1 )then
+        nowebb = .true.
+      else
+        nowebb = .false.
+      endif
+c
+    1 do 2 i=1,25
+        write(*,*) '  '
+    2 continue
+
+    5 write(*,*) '  Program Forward  -  Version 3.1 '
+      write(*,*) '  '
+      write(*,*) '  Ellipsoid options : '
+      write(*,*) '  '
+      write(*,*) '  1) GRS80 / WGS84  (NAD83) '
+      write(*,*) '  2) Clarke 1866    (NAD27) '
+      write(*,*) '  3) Any other ellipsoid '
+      write(*,*) '  '
+      write(*,*) '  Enter choice : '
+      read(*,10) option
+   10 format(a1)
+c
+      if(option.eq.'1') then
+        a=6378137.d0
+        f=1.d0/298.25722210088d0
+        elips='GRS80 / WGS84  (NAD83)'
+      elseif(option.eq.'2') then
+        a=6378206.4d0
+        f=1.d0/294.9786982138d0
+        elips='Clarke 1866    (NAD27)'
+      elseif(option.eq.'3') then
+        call elipss (elips)
+      else
+        write(*,*) '  Enter 1, 2, or 3 !   Try again --'
+        goto 5
+      endif
+c
+      esq = f*(2.0d0-f)
+c
+c     compute the geodetic limit distance (blimit), it is equal
+c     to twice the equatorial circumference minus one meter
+c
+      blimit = 2*pi*a-1.0d0
+c
+c     maximum distance allowed on ellipsoid
+c
+      dd_max = blimit
+c
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+c
+   15 write(*,*) '  Enter First Station '
+      write(*,16)
+   16 format(18x,'(Separate D,M,S by blanks or commas)')
+      write(*,*) 'hDD MM SS.sssss  Latitude :        (h default = N )'
+c
+   11 format(50a1)
+c
+   22 hem='N'
+      read(*,11) buff
+      call trim (buff,lgh,hem)
+      call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
+c
+      if( ierror.eq.0 )then
+        irlat1 = 0
+      else
+        irlat1 = 1
+        write(*,*) ' Invalid Latitude ... Please re-enter it '
+        write(*,*) '  '
+        if( nowebb )then
+          goto 22
+        endif
+      endif
+c
+      ald1 = dd
+      alm1 = dm
+      sl1  = ds
+c
+      if( hem.eq.'N' ) then
+        lat1sn = +1
+      else
+        lat1sn = -1
+      endif
+c
+      write(*,*) 'hDDD MM SS.sssss Longitude :       (h default = W )'
+c
+   23 hem='W'
+      read(*,11) buff
+      call trim (buff,lgh,hem)
+      call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
+c
+      if( ierror.eq.0 )then
+        irlon1 = 0
+      else
+        irlon1 = 1
+        write(*,*) ' Invalid Longitude ... Please re-enter it '
+        write(*,*) '  '
+        if( nowebb )then
+          goto 23
+        endif
+      endif
+c
+      alod1 = dd
+      alom1 = dm
+      slo1  = ds
+c
+      if( hem.eq.'E' ) then
+        lon1sn = +1
+      else
+        lon1sn = -1
+      endif
+c
+      call getdeg(ald1, alm1, sl1, lat1sn, glat1)
+      call getdeg(alod1,alom1,slo1,lon1sn, glon1)
+c
+   20 write(*,*) 'DDD MM SS.sss    Forward Azimuth :     (from north)'
+c
+   24 hem='A'
+      read(*,11) buff
+      call trim (buff,lgh,hem)
+      call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
+c
+      if( ierror.eq.0 )then
+        iazsn  = 1
+        irazi1 = 0
+      else
+        irazi1 = 1
+        write(*,*) ' Invalid Azimuth  ... Please re-enter it '
+        write(*,*) '  '
+        if( nowebb )then
+          goto 24
+        endif
+      endif
+c
+      azd1 = dd
+      azm1 = dm
+      saz1 = ds
+c
+      call getdeg(azd1,azm1,saz1,iazsn,faz)
+c
+      write(*,*) 'DDDDDD.dddd      Ellipsoidal Distance : (in meters)'
+c
+   25 ss = 0.0d0
+      read(*,*) ss
+      ss = dabs(ss)
+c
+      if( ss.lt.dd_max )then
+        edist  = ss
+        irdst1 = 0
+      else
+        irdst1 = 1
+        write(*,*) ' Invalid Distance ... Please re-enter it '
+        write(*,*) '  '
+        if( nowebb )then
+          goto 25
+        endif
+        edist  = 0.001d0
+      endif
+c
+      call direct (a, f, glat1, glon1, faz, edist, 0,
+     +    glat2, glon2, baz, 0, dummy, dummy, dummy, dummy, dummy)
+      if (baz .ge. 0) then
+        baz = baz - 180
+      else
+        baz = baz + 180
+      end if
+c
+c     set the azimuth seconds tolerance
+c
+      tol = 0.00005d0
+c
+      call todmsp(faz,iaz1,maz1,saz1,isign1)
+      if(isign1.lt.0) then
+        iaz1=359-iaz1
+        maz1=59-maz1
+        saz1=60.d0-saz1
+      endif
+      call fixdms ( iaz1, maz1, saz1, tol )
+c
+      call todmsp(baz,iaz2,maz2,saz2,isign2)
+      if(isign2.lt.0) then
+        iaz2=359-iaz2
+        maz2=59-maz2
+        saz2=60.d0-saz2
+      endif
+      call fixdms ( iaz2, maz2, saz2, tol )
+c
+      call todmsp(glat1, ld1,  lm1,  sl1,  lat1sn)
+      call todmsp(glon1, lod1, lom1, slo1, lon1sn)
+      call todmsp(glat2, ld2,  lm2,  sl2,  lat2sn)
+      call todmsp(glon2, lod2, lom2, slo2, lon2sn)
+c
+      call hem_ns ( lat1sn, d_ns1 )
+      call hem_ew ( lon1sn, d_ew1 )
+      call hem_ns ( lat2sn, d_ns2 )
+      call hem_ew ( lon2sn, d_ew2 )
+c
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,49) elips
+   49 format('  Ellipsoid : ',a30)
+      finv=1.d0/f
+      b=a*(1.d0-f)
+      write(*,50) a,b,finv
+   50 format('  Equatorial axis,    a   = ',f15.4,/,
+     *       '  Polar axis,         b   = ',f15.4,/,
+     *       '  Inverse flattening, 1/f = ',f16.11)
+c
+   18 format('    LAT = ',i3,1x,i2,1x,f8.5,1x,a6)
+   19 format('    LON = ',i3,1x,i2,1x,f8.5,1x,a6)
+c
+      write(*,*) '  '
+      write(*,*) '  First  Station : '
+      write(*,*) '  ---------------- '
+      write(*,18) ld1, lm1, sl1, d_ns1
+      write(*,19) lod1,lom1,slo1,d_ew1
+c
+      write(*,*) '  '
+      write(*,*) '  Second Station : '
+      write(*,*) '  ---------------- '
+      write(*,18) ld2, lm2, sl2, d_ns2
+      write(*,19) lod2,lom2,slo2,d_ew2
+c
+c
+   32 format('  Ellipsoidal distance     S = ',f14.4,1x,a1)
+   34 format('  Forward azimuth        FAZ = ',i3,1x,i2,1x,f7.4,
+     1       ' From North')
+   35 format('  Back azimuth           BAZ = ',i3,1x,i2,1x,f7.4,
+     1       ' From North')
+c
+      write(*,*) '  '
+      write(*,34) iaz1,maz1,saz1
+      write(*,35) iaz2,maz2,saz2
+      write(*,32) edist,dmt
+      write(*,*) '  '
+      write(*,*) '  Do you want to save this output into a file (y/n)?'
+      read(*,10) answer
+c
+      if( answer.eq.'Y'.or.answer.eq.'y' )then
+   39   write(*,*) '  Enter the output filename : '
+        read(*,40) filout
+   40   format(a30)
+        open(3,file=filout,status='new',err=99)
+        goto 98
+c
+   99   write(*,*) '  File already exists, try again.'
+        go to 39
+c
+   98   continue
+        write(3,*) '  '
+        write(3,49) elips
+        write(3,50) a,b,finv
+        write(*,*) '  Enter the First Station name : '
+        read(*,40) name1
+        write(*,*) '  Enter the Second Station name : '
+        read(*,40) name2
+c
+   41   format('  First  Station : ',a30)
+   42   format('  Second Station : ',a30)
+   84   format('  Error:  First  Station ... Invalid Latitude  ')
+   85   format('  Error:  First  Station ... Invalid Longitude ')
+   86   format('  Error:  Forward Azimuth .. Invalid Entry     ')
+   87   format('  Error:  Ellipsoid Distance .. Invalid Entry  ')
+   88   format(1x,65(1h*))
+   91   format('          DD(0-89) MM(0-59) SS(0-59.999...)    ')
+   92   format('          DDD(0-359) MM(0-59) SS(0-59.999...)  ')
+   93   format('          Geodetic distance is too long        ')
+c
+        write(3,*) '  '
+        write(3,41) name1
+        write(3,*) '  ---------------- '
+c
+        if( irlat1.eq.0 )then
+          write(3,18) ld1, lm1, sl1, d_ns1
+        else
+          write(3,88)
+          write(3,84)
+          write(3,91)
+          write(3,88)
+        endif
+c
+        if( irlon1.eq.0 )then
+          write(3,19) lod1,lom1,slo1,d_ew1
+        else
+          write(3,88)
+          write(3,85)
+          write(3,92)
+          write(3,88)
+        endif
+c
+        write(3,*) '  '
+        write(3,42) name2
+        write(3,*) '  ---------------- '
+        write(3,18) ld2, lm2, sl2, d_ns2
+        write(3,19) lod2,lom2,slo2,d_ew2
+c
+        write(3,*) '  '
+        if( irazi1.eq.0 )then
+          write(3,34) iaz1,maz1,saz1
+        else
+          write(3,88)
+          write(3,86)
+          write(3,92)
+          write(3,88)
+        endif
+c
+        write(3,35) iaz2,maz2,saz2
+c
+        if( irdst1.eq.0 )then
+          write(3,32) edist,dmt
+        else
+          write(3,88)
+          write(3,87)
+          write(3,93)
+          write(3,88)
+        endif
+c
+        write(3,*) '  '
+      endif
+c
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  1) Another forward, different ellipsoid.'
+      write(*,*) '  2) Same ellipsoid, two new stations.'
+      write(*,*) '  3) Same ellipsoid, same First Station.'
+      write(*,*) '  4) Let the Second Station be the First Station.'
+      write(*,*) '  5) Done.'
+      write(*,*) '  '
+      write(*,*) '  Enter choice : '
+      read(*,10) answer
+c
+      if(    answer.eq.'1')then
+        goto 1
+      elseif(answer.eq.'2')then
+        goto 15
+      elseif(answer.eq.'3')then
+        goto 20
+      elseif(answer.eq.'4')then
+        glat1 = glat2
+        glon1 = glon2
+        goto 20
+      else
+        write(*,*) '  Thats all, folks!'
+      endif
+c
+c     stop
+      end
diff --git a/legacy/Fortran/ngsinverse.for b/legacy/Fortran/ngsinverse.for
new file mode 100644
index 0000000..e6c1d7e
--- /dev/null
+++ b/legacy/Fortran/ngsinverse.for
@@ -0,0 +1,513 @@
+cb::inverse
+c
+      program inverse
+c
+c********1*********2*********3*********4*********5*********6*********7**
+c
+c name:      inverse
+c version:   201211.29
+c author:    stephen j. frakes
+c last mod:  Charles Karney
+c purpose:   to compute a geodetic inverse
+c            and then display output information
+c
+c input parameters:
+c -----------------
+c
+c output parameters:
+c ------------------
+c
+c local variables and constants:
+c ------------------------------
+c answer           user prompt response
+c b                semiminor axis polar (in meters)
+c baz              azimuth back (in radians)
+c buff             input char buffer array
+c dd,dm,ds         temporary values for degrees, minutes, seconds
+c dlon             temporary value for difference in longitude (radians)
+c dmt,d_mt         char constants for meter units
+c edist            ellipsoid distance (in meters)
+c elips            ellipsoid choice
+c esq              eccentricity squared for reference ellipsoid
+c faz              azimuth forward (in radians)
+c filout           output file name
+c finv             reciprocal flattening
+c hem              hemisphere flag for lat & lon entry
+c ierror           error condition flag with d,m,s conversion
+c lgh              length of buff() array
+c option           user prompt response
+c r1,r2            temporary variables
+c ss               temporary variable
+c tol              tolerance for conversion of seconds
+c
+c name1            name of station one
+c ld1,lm1,sl1      latitude  sta one - degrees,minutes,seconds
+c ald1,alm1,sl1    latitude  sta one - degrees,minutes,seconds
+c lat1sn           latitude  sta one - sign (+/- 1)
+c d_ns1            latitude  sta one - char ('N','S')
+c lod1,lom1,slo1   longitude sta one - degrees,minutes,seconds
+c alod1,alom1,slo1 longitude sta one - degrees,minutes,seconds
+c lon1sn           longitude sta one - sign (+/- 1)
+c d_ew1            longitude sta one - char ('E','W')
+c iaz1,maz1,saz1   forward azimuth   - degrees,minutes,seconds
+c isign1           forward azimuth   - flag  (+/- 1)
+c glat1,glon1      station one       - (lat & lon in radians )
+c p1,e1            standpoint one    - (lat & lon in radians )
+c
+c name2            name of station two
+c ld2,lm2,sl2      latitude  sta two - degrees,minutes,seconds
+c ald2,alm2,sl2    latitude  sta two - degrees,minutes,seconds
+c lat2sn           latitude  sta two - sign (+/- 1)
+c d_ns2            latitude  sta two - char ('N','S')
+c lod2,lom2,slo2   longitude sta two - degrees,minutes,seconds
+c alod2,alom2,slo2 longitude sta one - degrees,minutes,seconds
+c lon2sn           longitude sta two - sign (+/- 1)
+c d_ew2            longitude sta two - char ('E','W')
+c iaz2,maz2,saz2   back azimuth      - degrees,minutes,seconds
+c isign2           back azimuth      - flag  (+/- 1)
+c glat2,glon2      station two       - (lat & lon in radians )
+c p2,e2            forepoint two     - (lat & lon in radians )
+c
+c global variables and constants:
+c -------------------------------
+c a                semimajor axis equatorial (in meters)
+c f                flattening
+c pi               constant 3.14159....
+c rad              constant 180.0/pi
+c
+c    this module called by:  n/a
+c
+c    this module calls:      elipss, getdeg, inver1, todmsp
+c    gethem, trim,   bufdms, gvalr8, gvali4, fixdms, gpnhri ***********
+c    gethem, trim,   bufdms, gvalr8, gvali4, fixdms, invers <----------
+c    datan,  write,  read,   dabs,   open,   stop
+c
+c    include files used:     n/a
+c
+c    common blocks used:     const, elipsoid
+c
+c    references:             see comments within subroutines
+c
+c    comments:
+c
+c********1*********2*********3*********4*********5*********6*********7**
+c::modification history
+c::1990mm.dd, sjf, creation of program
+c::199412.15, bmt, creation of program on viper
+c::200203.08, crs, modified by c.schwarz to correct spelling of Clarke
+c::200207.15, rws, modified i/o & standardized program documentation
+c::                added subs trim, bufdms, gethem, gvali4, gvalr8
+c::200207.23, rws, replaced sub inver1 with gpnarc, gpnloa, gpnhri
+c::200208.15, rws, fixed an error in bufdms
+c::              - renamed ellips to elipss "common error" with dirct2
+c::              - added FAZ & BAZ to printed output
+c::200208.19, rws, added more error flags for web interface code
+c::              - added logical nowebb
+c::200208.xx, sjf, program version number 2.0
+c::201105.xx, dgm, program version number 3.0
+c::              - replaced sub gpnarc, gpnloa, gpnhri with invers
+c::              - tested for valid antipodal solutions (+/- 0.1 mm)
+c::              - tested for polar solutions (+/- 0.1 mm)
+c::              - needs improvement for long-line/antipodal boundary
+c::201211.29, cffk, program version numer 3.1
+c::              - drop in replacement routines from
+c::                "Algorithms for Geodesics"
+c********1*********2*********3*********4*********5*********6*********7**
+ce::inverse
+c
+      implicit double precision (a-h, o-z)
+      implicit integer (i-n)
+c
+      logical  nowebb
+c
+      character*1  answer,option,dmt,buff(50),hem
+      character*6  d_ns1, d_ew1, d_ns2, d_ew2, d_mt
+      character*30 filout,name1,name2,elips
+c
+      integer*4    ierror
+      integer*4    lgh
+c
+      common/const/pi,rad
+      common/elipsoid/a,f
+c
+c     ms_unix      0 = web version
+c                  1 = ms_dos or unix version
+c
+      parameter   ( ms_unix = 0 )
+c
+      pi   = 4.d0*datan(1.d0)
+      rad  = 180.d0/pi
+      dmt  = 'm'
+      d_mt = 'Meters'
+c
+      if( ms_unix.eq.1 )then
+        nowebb = .true.
+      else
+        nowebb = .false.
+      endif
+c
+    1 do 2 i=1,25
+        write(*,*) '  '
+    2 continue
+c
+    5 write(*,*) '  Program Inverse  -  Version 3.1 '
+      write(*,*) '  '
+      write(*,*) '  Ellipsoid options : '
+      write(*,*) '  '
+      write(*,*) '  1) GRS80 / WGS84  (NAD83) '
+      write(*,*) '  2) Clarke 1866    (NAD27) '
+      write(*,*) '  3) Any other ellipsoid '
+      write(*,*) '  '
+      write(*,*) '  Enter choice : '
+      read(*,10) option
+   10 format(a1)
+c
+      if(option.eq.'1') then
+        a=6378137.d0
+        f=1.d0/298.257222100882711243162836600094d0
+        elips='GRS80 / WGS84  (NAD83)'
+      elseif(option.eq.'2') then
+        a=6378206.4d0
+        f=1.d0/294.9786982138d0
+        elips='Clarke 1866    (NAD27)'
+      elseif(option.eq.'3') then
+        call elipss (elips)
+      else
+        write(*,*) '  Enter 1, 2, or 3 !   Try again --'
+        goto 5
+      endif
+c
+      esq = f*(2.0d0-f)
+c
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+c
+   15 write(*,*) '  Enter First Station '
+      write(*,16)
+   16 format(18x,'(Separate D,M,S by blanks or commas)')
+      write(*,*) 'hDD MM SS.sssss  Latitude :        (h default = N )'
+   11 format(50a1)
+c
+   22 hem='N'
+      read(*,11) buff
+      call trim (buff,lgh,hem)
+      call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
+c
+      if( ierror.eq.0 )then
+        irlat1 = 0
+      else
+        irlat1 = 1
+        write(*,*) ' Invalid Latitude ... Please re-enter it '
+        write(*,*) '  '
+        if( nowebb )then
+          goto 22
+        endif
+      endif
+c
+      ald1 = dd
+      alm1 = dm
+      sl1  = ds
+c
+      if( hem.eq.'N' ) then
+        lat1sn = +1
+      else
+        lat1sn = -1
+      endif
+c
+      write(*,*) 'hDDD MM SS.sssss Longitude :       (h default = W )'
+c
+   23 hem='W'
+      read(*,11) buff
+      call trim (buff,lgh,hem)
+      call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
+c
+      if( ierror.eq.0 )then
+        irlon1 = 0
+      else
+        irlon1 = 1
+        write(*,*) ' Invalid Longitude ... Please re-enter it '
+        write(*,*) '  '
+        if( nowebb )then
+          goto 23
+        endif
+      endif
+c
+      alod1 = dd
+      alom1 = dm
+      slo1  = ds
+c
+      if( hem.eq.'E' ) then
+        lon1sn = +1
+      else
+        lon1sn = -1
+      endif
+c
+      call getdeg(ald1, alm1, sl1, lat1sn, glat1)
+      call getdeg(alod1,alom1,slo1,lon1sn, glon1)
+c
+      write(*,*) '  '
+      write(*,*) '  '
+c
+   20 write(*,*) '  Enter Second Station '
+      write(*,16)
+      write(*,*) 'hDD MM SS.sssss  Latitude :        (h default = N )'
+c
+   24 hem='N'
+      read(*,11) buff
+      call trim (buff,lgh,hem)
+      call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
+c
+      if( ierror.eq.0 )then
+        irlat2 = 0
+      else
+        irlat2 = 1
+        write(*,*) ' Invalid Latitude ... Please re-enter it '
+        write(*,*) '  '
+        if( nowebb )then
+          goto 24
+        endif
+      endif
+c
+      ald2 = dd
+      alm2 = dm
+      sl2  = ds
+c
+      if( hem.eq.'N' ) then
+        lat2sn = +1
+      else
+        lat2sn = -1
+      endif
+c
+      write(*,*) 'hDDD MM SS.sssss Longitude :       (h default = W )'
+c
+   25 hem='W'
+      read(*,11) buff
+      call trim (buff,lgh,hem)
+      call bufdms (buff,lgh,hem,dd,dm,ds,ierror)
+c
+      if( ierror.eq.0 )then
+        irlon2 = 0
+      else
+        irlon2 = 1
+        write(*,*) ' Invalid Longitude ... Please re-enter it '
+        write(*,*) '  '
+        if( nowebb )then
+          goto 25
+        endif
+      endif
+c
+      alod2 = dd
+      alom2 = dm
+      slo2  = ds
+c
+      if( hem.eq.'E' )then
+        lon2sn = +1
+      else
+        lon2sn = -1
+      endif
+c
+      call getdeg(ald2, alm2, sl2, lat2sn, glat2)
+      call getdeg(alod2,alom2,slo2,lon2sn, glon2)
+c
+      p1 = glat1
+      e1 = glon1
+      p2 = glat2
+      e2 = glon2
+c
+      if( e1.lt.0.0d0 )then
+        e1 = e1+2.0d0*pi
+      endif
+      if( e2.lt.0.0d0 )then
+        e2 = e2+2.0d0*pi
+      endif
+c
+c     compute the geodetic inverse
+c
+      call invers(a, f, p1, e1, p2, e2,
+     +    edist, faz, baz, 0, dummy, dummy, dummy, dummy, dummy)
+      if (baz .ge. 0) then
+        baz = baz - 180
+      else
+        baz = baz + 180
+      end if
+c
+c     set the tolerance (in seconds) for the azimuth conversion
+c
+      tol = 0.00005d0
+c
+      call todmsp(faz,iaz1,maz1,saz1,isign1)
+      if(isign1.lt.0) then
+        iaz1=359-iaz1
+        maz1=59-maz1
+        saz1=60.d0-saz1
+      endif
+      call fixdms ( iaz1, maz1, saz1, tol )
+c
+      call todmsp(baz,iaz2,maz2,saz2,isign2)
+      if(isign2.lt.0) then
+        iaz2=359-iaz2
+        maz2=59-maz2
+        saz2=60.d0-saz2
+      endif
+      call fixdms ( iaz2, maz2, saz2, tol )
+c
+      call todmsp(glat1, ld1,  lm1,  sl1,  lat1sn)
+      call todmsp(glon1, lod1, lom1, slo1, lon1sn)
+      call todmsp(glat2, ld2,  lm2,  sl2,  lat2sn)
+      call todmsp(glon2, lod2, lom2, slo2, lon2sn)
+c
+      call hem_ns ( lat1sn, d_ns1 )
+      call hem_ew ( lon1sn, d_ew1 )
+      call hem_ns ( lat2sn, d_ns2 )
+      call hem_ew ( lon2sn, d_ew2 )
+c
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,49) elips
+   49 format('  Ellipsoid : ',a30)
+      finv=1.d0/f
+      b=a*(1.d0-f)
+      write(*,50) a,b,finv
+   50 format('  Equatorial axis,    a   = ',f15.4,/,
+     *       '  Polar axis,         b   = ',f15.4,/,
+     *       '  Inverse flattening, 1/f = ',f16.11)
+c
+   18 format('    LAT = ',i3,1x,i2,1x,f8.5,1x,a6)
+   19 format('    LON = ',i3,1x,i2,1x,f8.5,1x,a6)
+c
+      write(*,*) '  '
+      write(*,*) '  First  Station : '
+      write(*,*) '  ---------------- '
+      write(*,18) ld1, lm1, sl1, d_ns1
+      write(*,19) lod1,lom1,slo1,d_ew1
+c
+      write(*,*) '  '
+      write(*,*) '  Second Station : '
+      write(*,*) '  ---------------- '
+      write(*,18) ld2, lm2, sl2, d_ns2
+      write(*,19) lod2,lom2,slo2,d_ew2
+c
+   32 format('  Ellipsoidal distance     S = ',f14.4,1x,a1)
+   34 format('  Forward azimuth        FAZ = ',i3,1x,i2,1x,f7.4,
+     1       ' From North')
+   35 format('  Back azimuth           BAZ = ',i3,1x,i2,1x,f7.4,
+     1       ' From North')
+c
+      write(*,*) '  '
+      write(*,34) iaz1,maz1,saz1
+      write(*,35) iaz2,maz2,saz2
+      write(*,32) edist,dmt
+      write(*,*) '  '
+      write(*,*) '  Do you want to save this output into a file (y/n)?'
+      read(*,10) answer
+c
+      if( answer.eq.'Y'.or.answer.eq.'y' )then
+   39   write(*,*) '  Enter the output filename : '
+        read(*,40) filout
+   40   format(a30)
+        open(3,file=filout,status='new',err=99)
+        goto 98
+c
+   99   write(*,*) '  File already exists, try again.'
+        go to 39
+c
+   98   continue
+        write(3,*) '  '
+        write(3,49) elips
+        finv=1.d0/f
+        b=a*(1.d0-f)
+        write(3,50) a,b,finv
+        write(*,*) '  Enter the First Station name : '
+        read(*,40) name1
+        write(*,*) '  Enter the Second Station name : '
+        read(*,40) name2
+c
+   41   format('  First  Station : ',a30)
+   42   format('  Second Station : ',a30)
+   84   format('  Error: First  Station ... Invalid Latitude  ')
+   85   format('  Error: First  Station ... Invalid Longitude ')
+   86   format('  Error: Second Station ... Invalid Latitude  ')
+   87   format('  Error: Second Station ... Invalid Longitude ')
+   88   format(1x,65(1h*))
+   91   format('         DD(0-89) MM(0-59) SS(0-59.999...)  ')
+   92   format('         DDD(0-359) MM(0-59) SS(0-59.999...)  ')
+c
+        write(3,*) '  '
+        write(3,41) name1
+        write(3,*) '  ---------------- '
+
+        if( irlat1.eq.0 )then
+          write(3,18) ld1, lm1, sl1, d_ns1
+        else
+          write(3,88)
+          write(3,84)
+          write(3,91)
+          write(3,88)
+        endif
+c
+        if( irlon1.eq.0 )then
+          write(3,19) lod1,lom1,slo1,d_ew1
+        else
+          write(3,88)
+          write(3,85)
+          write(3,92)
+          write(3,88)
+        endif
+c
+        write(3,*) '  '
+        write(3,42) name2
+        write(3,*) '  ---------------- '
+c
+        if( irlat2.eq.0 )then
+          write(3,18) ld2, lm2, sl2, d_ns2
+        else
+          write(3,88)
+          write(3,86)
+          write(3,91)
+          write(3,88)
+        endif
+c
+        if( irlon2.eq.0 )then
+          write(3,19) lod2,lom2,slo2,d_ew2
+        else
+          write(3,88)
+          write(3,87)
+          write(3,92)
+          write(3,88)
+        endif
+c
+        write(3,*) '  '
+        write(3,34) iaz1,maz1,saz1
+        write(3,35) iaz2,maz2,saz2
+        write(3,32) edist,dmt
+        write(3,*) '  '
+      endif
+c
+   80 write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  '
+      write(*,*) '  1) Another inverse, different ellipsoid.'
+      write(*,*) '  2) Same ellipsoid, two new stations.'
+      write(*,*) '  3) Same ellipsoid, same First Station.'
+      write(*,*) '  4) Done.'
+      write(*,*) '  '
+      write(*,*) '  Enter choice : '
+      read(*,10) answer
+c
+      if(     answer.eq.'1' )then
+        goto 1
+      elseif( answer.eq.'2' )then
+        goto 15
+      elseif( answer.eq.'3' )then
+        goto 20
+      else
+        write(*,*) '  Thats all, folks!'
+      endif
+
+c     stop
+      end
diff --git a/man/CartConvert.1 b/man/CartConvert.1
index 3fa227a..a53ecd0 100644
--- a/man/CartConvert.1
+++ b/man/CartConvert.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "CARTCONVERT 1"
-.TH CARTCONVERT 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH CARTCONVERT 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff --git a/man/CartConvert.usage b/man/CartConvert.usage
index 324111a..6f12b5c 100644
--- a/man/CartConvert.usage
+++ b/man/CartConvert.usage
@@ -9,7 +9,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    CartConvert --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/CartConvert.1.html\n";
+"    http://geographiclib.sf.net/1.39/CartConvert.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
diff --git a/man/ConicProj.1 b/man/ConicProj.1
index e4b8024..39d3d1b 100644
--- a/man/ConicProj.1
+++ b/man/ConicProj.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "CONICPROJ 1"
-.TH CONICPROJ 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH CONICPROJ 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff --git a/man/ConicProj.usage b/man/ConicProj.usage
index ed6a03f..0c128c9 100644
--- a/man/ConicProj.usage
+++ b/man/ConicProj.usage
@@ -9,7 +9,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    ConicProj --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/ConicProj.1.html\n";
+"    http://geographiclib.sf.net/1.39/ConicProj.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
diff --git a/man/GeoConvert.1 b/man/GeoConvert.1
index 7582022..5b8ce77 100644
--- a/man/GeoConvert.1
+++ b/man/GeoConvert.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "GEOCONVERT 1"
-.TH GEOCONVERT 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH GEOCONVERT 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff --git a/man/GeoConvert.usage b/man/GeoConvert.usage
index b2a8449..1d54eae 100644
--- a/man/GeoConvert.usage
+++ b/man/GeoConvert.usage
@@ -9,7 +9,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    GeoConvert --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/GeoConvert.1.html\n";
+"    http://geographiclib.sf.net/1.39/GeoConvert.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
diff --git a/man/GeodSolve.1 b/man/GeodSolve.1
index 22c180d..d658b71 100644
--- a/man/GeodSolve.1
+++ b/man/GeodSolve.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "GEODSOLVE 1"
-.TH GEODSOLVE 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH GEODSOLVE 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff --git a/man/GeodSolve.usage b/man/GeodSolve.usage
index 3d46fd1..4632a85 100644
--- a/man/GeodSolve.usage
+++ b/man/GeodSolve.usage
@@ -9,7 +9,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    GeodSolve --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/GeodSolve.1.html\n";
+"    http://geographiclib.sf.net/1.39/GeodSolve.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
diff --git a/man/GeodesicProj.1 b/man/GeodesicProj.1
index 61c7430..57807cc 100644
--- a/man/GeodesicProj.1
+++ b/man/GeodesicProj.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "GEODESICPROJ 1"
-.TH GEODESICPROJ 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH GEODESICPROJ 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff --git a/man/GeodesicProj.usage b/man/GeodesicProj.usage
index 30f8358..79c06e1 100644
--- a/man/GeodesicProj.usage
+++ b/man/GeodesicProj.usage
@@ -9,7 +9,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    GeodesicProj --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/GeodesicProj.1.html\n";
+"    http://geographiclib.sf.net/1.39/GeodesicProj.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
diff --git a/man/GeoidEval.1 b/man/GeoidEval.1
index 2f78343..50e3263 100644
--- a/man/GeoidEval.1
+++ b/man/GeoidEval.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "GEOIDEVAL 1"
-.TH GEOIDEVAL 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH GEOIDEVAL 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -166,6 +166,14 @@ eastings and northings in a single zone to be used as standard input.
 .PP
 More accurate results for the geoid height are provided by \fIGravity\fR\|(1).
 This utility can also compute the direction of gravity accurately.
+.PP
+The geoid height, \fIN\fR, can be used to convert a height above the
+ellipsoid, \fIh\fR, to the corresponding height above the geoid (roughly
+the height above mean sea level), \fIH\fR, using the relations
+.Sp
+.RS 4
+\&\fIh\fR = \fIN\fR + \fIH\fR, \ \ \fIH\fR = \-\fIN\fR + \fIh\fR.
+.RE
 .SH "OPTIONS"
 .IX Header "OPTIONS"
 .IP "\fB\-n\fR" 4
diff --git a/man/GeoidEval.1.html b/man/GeoidEval.1.html
index bfbe5a1..9e725e1 100644
--- a/man/GeoidEval.1.html
+++ b/man/GeoidEval.1.html
@@ -27,6 +27,14 @@
 
 <p>More accurate results for the geoid height are provided by Gravity(1). This utility can also compute the direction of gravity accurately.</p>
 
+<p>The geoid height, <i>N</i>, can be used to convert a height above the ellipsoid, <i>h</i>, to the corresponding height above the geoid (roughly the height above mean sea level), <i>H</i>, using the relations</p>
+
+<ul>
+
+<p><i>h</i> = <i>N</i> + <i>H</i>,   <i>H</i> = -<i>N</i> + <i>h</i>.</p>
+
+</ul>
+
 <h1 id="OPTIONS">OPTIONS</h1>
 
 <dl>
diff --git a/man/GeoidEval.pod b/man/GeoidEval.pod
index 7b445ff..22c83cb 100644
--- a/man/GeoidEval.pod
+++ b/man/GeoidEval.pod
@@ -30,6 +30,16 @@ eastings and northings in a single zone to be used as standard input.
 More accurate results for the geoid height are provided by Gravity(1).
 This utility can also compute the direction of gravity accurately.
 
+The geoid height, I<N>, can be used to convert a height above the
+ellipsoid, I<h>, to the corresponding height above the geoid (roughly
+the height above mean sea level), I<H>, using the relations
+
+=over
+
+I<h> = I<N> + I<H>, E<nbsp>E<nbsp>I<H> = -I<N> + I<h>.
+
+=back
+
 =head1 OPTIONS
 
 =over
diff --git a/man/GeoidEval.usage b/man/GeoidEval.usage
index af0b387..cdc6a93 100644
--- a/man/GeoidEval.usage
+++ b/man/GeoidEval.usage
@@ -10,7 +10,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    GeoidEval --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/GeoidEval.1.html\n";
+"    http://geographiclib.sf.net/1.39/GeoidEval.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
@@ -38,6 +38,12 @@ int usage(int retval, bool brief) {
 "       More accurate results for the geoid height are provided by Gravity(1).\n"
 "       This utility can also compute the direction of gravity accurately.\n"
 "\n"
+"       The geoid height, N, can be used to convert a height above the\n"
+"       ellipsoid, h, to the corresponding height above the geoid (roughly the\n"
+"       height above mean sea level), H, using the relations\n"
+"\n"
+"           h = N + H,   H = -N + h.\n"
+"\n"
 "OPTIONS\n"
 "       -n  use geoid name instead of the default \"egm96-5\".  See \"GEOIDS\".\n"
 "\n"
diff --git a/man/Gravity.1 b/man/Gravity.1
index 7435190..7b2e762 100644
--- a/man/Gravity.1
+++ b/man/Gravity.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "GRAVITY 1"
-.TH GRAVITY 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH GRAVITY 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff --git a/man/Gravity.usage b/man/Gravity.usage
index 014214a..7cbd1db 100644
--- a/man/Gravity.usage
+++ b/man/Gravity.usage
@@ -9,7 +9,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    Gravity --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/Gravity.1.html\n";
+"    http://geographiclib.sf.net/1.39/Gravity.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
diff --git a/man/MagneticField.1 b/man/MagneticField.1
index 9d183d9..8df049c 100644
--- a/man/MagneticField.1
+++ b/man/MagneticField.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "MAGNETICFIELD 1"
-.TH MAGNETICFIELD 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH MAGNETICFIELD 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -158,16 +158,16 @@ prints out the geomagnetic field on standard output and, optionally, its
 rate of change.
 .PP
 The input line is of the form \fItime\fR \fIlat\fR \fIlon\fR \fIh\fR. \fItime\fR is a
-date of the form 2012\-07\-03 or a fractional year such as 2012.5.  \fIlat\fR
-and \fIlon\fR are the latitude and longitude expressed as decimal degrees
-or degrees, minutes, and seconds; see \fIGeoConvert\fR\|(1) for details.  \fIh\fR
-is the height above the ellipsoid in meters; this is optional and
-defaults to zero.  Alternatively, \fItime\fR can be given on the command
-line as the argument to the \fB\-t\fR option, in which case it should not be
-included on the input lines.  Finally, the magnetic field can be
-computed at various points on a circle of latitude (constant \fItime\fR,
-\&\fIlat\fR, and \fIh\fR) via the \fB\-c\fR option; in this case only the longitude
-should be given on the input lines.
+date of the form 2012\-07\-03, a fractional year such as 2012.5, or the
+string \*(L"now\*(R".  \fIlat\fR and \fIlon\fR are the latitude and longitude
+expressed as decimal degrees or degrees, minutes, and seconds; see
+\&\fIGeoConvert\fR\|(1) for details.  \fIh\fR is the height above the ellipsoid in
+meters; this is optional and defaults to zero.  Alternatively, \fItime\fR
+can be given on the command line as the argument to the \fB\-t\fR option, in
+which case it should not be included on the input lines.  Finally, the
+magnetic field can be computed at various points on a circle of latitude
+(constant \fItime\fR, \fIlat\fR, and \fIh\fR) via the \fB\-c\fR option; in this case
+only the longitude should be given on the input lines.
 .PP
 The output consists of the following 7 items:
 .PP
diff --git a/man/MagneticField.1.html b/man/MagneticField.1.html
index 5f735ba..7cd0282 100644
--- a/man/MagneticField.1.html
+++ b/man/MagneticField.1.html
@@ -23,7 +23,7 @@
 
 <p><b>MagneticField</b> reads in times and positions on standard input and prints out the geomagnetic field on standard output and, optionally, its rate of change.</p>
 
-<p>The input line is of the form <i>time</i> <i>lat</i> <i>lon</i> <i>h</i>. <i>time</i> is a date of the form 2012-07-03 or a fractional year such as 2012.5. <i>lat</i> and <i>lon</i> are the latitude and longitude expressed as decimal degrees or degrees, minutes, and seconds; see GeoConvert(1) for details. <i>h</i> is the height above the ellipsoid in meters; this is optional and defaults to zero. Alternatively, <i>time</i> can be given on the command line as the argument to the <b>-t< [...]
+<p>The input line is of the form <i>time</i> <i>lat</i> <i>lon</i> <i>h</i>. <i>time</i> is a date of the form 2012-07-03, a fractional year such as 2012.5, or the string "now". <i>lat</i> and <i>lon</i> are the latitude and longitude expressed as decimal degrees or degrees, minutes, and seconds; see GeoConvert(1) for details. <i>h</i> is the height above the ellipsoid in meters; this is optional and defaults to zero. Alternatively, <i>time</i> can be given on the command line  [...]
 
 <p>The output consists of the following 7 items:</p>
 
diff --git a/man/MagneticField.pod b/man/MagneticField.pod
index d85e5e9..7bbc580 100644
--- a/man/MagneticField.pod
+++ b/man/MagneticField.pod
@@ -21,16 +21,16 @@ prints out the geomagnetic field on standard output and, optionally, its
 rate of change.
 
 The input line is of the form I<time> I<lat> I<lon> I<h>. I<time> is a
-date of the form 2012-07-03 or a fractional year such as 2012.5.  I<lat>
-and I<lon> are the latitude and longitude expressed as decimal degrees
-or degrees, minutes, and seconds; see GeoConvert(1) for details.  I<h>
-is the height above the ellipsoid in meters; this is optional and
-defaults to zero.  Alternatively, I<time> can be given on the command
-line as the argument to the B<-t> option, in which case it should not be
-included on the input lines.  Finally, the magnetic field can be
-computed at various points on a circle of latitude (constant I<time>,
-I<lat>, and I<h>) via the B<-c> option; in this case only the longitude
-should be given on the input lines.
+date of the form 2012-07-03, a fractional year such as 2012.5, or the
+string "now".  I<lat> and I<lon> are the latitude and longitude
+expressed as decimal degrees or degrees, minutes, and seconds; see
+GeoConvert(1) for details.  I<h> is the height above the ellipsoid in
+meters; this is optional and defaults to zero.  Alternatively, I<time>
+can be given on the command line as the argument to the B<-t> option, in
+which case it should not be included on the input lines.  Finally, the
+magnetic field can be computed at various points on a circle of latitude
+(constant I<time>, I<lat>, and I<h>) via the B<-c> option; in this case
+only the longitude should be given on the input lines.
 
 The output consists of the following 7 items:
 
diff --git a/man/MagneticField.usage b/man/MagneticField.usage
index 1ffd044..bde21b3 100644
--- a/man/MagneticField.usage
+++ b/man/MagneticField.usage
@@ -10,7 +10,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    MagneticField --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/MagneticField.1.html\n";
+"    http://geographiclib.sf.net/1.39/MagneticField.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
@@ -29,15 +29,16 @@ int usage(int retval, bool brief) {
 "       of change.\n"
 "\n"
 "       The input line is of the form time lat lon h. time is a date of the\n"
-"       form 2012-07-03 or a fractional year such as 2012.5.  lat and lon are\n"
-"       the latitude and longitude expressed as decimal degrees or degrees,\n"
-"       minutes, and seconds; see GeoConvert(1) for details.  h is the height\n"
-"       above the ellipsoid in meters; this is optional and defaults to zero.\n"
-"       Alternatively, time can be given on the command line as the argument to\n"
-"       the -t option, in which case it should not be included on the input\n"
-"       lines.  Finally, the magnetic field can be computed at various points\n"
-"       on a circle of latitude (constant time, lat, and h) via the -c option;\n"
-"       in this case only the longitude should be given on the input lines.\n"
+"       form 2012-07-03, a fractional year such as 2012.5, or the string \"now\".\n"
+"       lat and lon are the latitude and longitude expressed as decimal degrees\n"
+"       or degrees, minutes, and seconds; see GeoConvert(1) for details.  h is\n"
+"       the height above the ellipsoid in meters; this is optional and defaults\n"
+"       to zero.  Alternatively, time can be given on the command line as the\n"
+"       argument to the -t option, in which case it should not be included on\n"
+"       the input lines.  Finally, the magnetic field can be computed at\n"
+"       various points on a circle of latitude (constant time, lat, and h) via\n"
+"       the -c option; in this case only the longitude should be given on the\n"
+"       input lines.\n"
 "\n"
 "       The output consists of the following 7 items:\n"
 "\n"
diff --git a/man/Planimeter.1 b/man/Planimeter.1
index 167112d..c835217 100644
--- a/man/Planimeter.1
+++ b/man/Planimeter.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "PLANIMETER 1"
-.TH PLANIMETER 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH PLANIMETER 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -143,7 +143,7 @@ Planimeter \-\- compute the area of geodesic polygons
 .SH "SYNOPSIS"
 .IX Header "SYNOPSIS"
 \&\fBPlanimeter\fR [ \fB\-r\fR ] [ \fB\-s\fR ] [ \fB\-l\fR ] [ \fB\-e\fR \fIa\fR \fIf\fR ]
-[ \fB\-p\fR \fIprec\fR ] [ \fB\-E\fR ] [ \fB\-Q\fR ]
+[ \fB\-p\fR \fIprec\fR ] [ \fB\-G\fR | \fB\-E\fR | \fB\-Q\fR | \fB\-R\fR ]
 [ \fB\-\-comment\-delimiter\fR \fIcommentdelim\fR ]
 [ \fB\-\-version\fR | \fB\-h\fR | \fB\-\-help\fR ]
 [ \fB\-\-input\-file\fR \fIinfile\fR | \fB\-\-input\-string\fR \fIinstring\fR ]
@@ -216,20 +216,26 @@ coordinates to latitude and longitude always uses the \s-1WGS84\s0 parameters.
 set the output precision to \fIprec\fR (default 6); the perimeter is given
 (in meters) with \fIprec\fR digits after the decimal point; the area is
 given (in meters^2) with (\fIprec\fR \- 5) digits after the decimal point.
+.IP "\fB\-G\fR" 4
+.IX Item "-G"
+use the series formulation for the geodesics.  This is the default
+option and recommened for terrestrial applications.
 .IP "\fB\-E\fR" 4
 .IX Item "-E"
 use \*(L"exact\*(R" algorithms (based on elliptic integrals) for the geodesic
 calculations.  These are more accurate than the (default) series
 expansions for |\fIf\fR| > 0.02.  (But note that the implementation of
 areas in GeodesicExact uses a high order series and this is only
-accurate for modest flattenings.)  \fB\-E\fR and \fB\-Q\fR are mutually
-exclusive.
+accurate for modest flattenings.)
 .IP "\fB\-Q\fR" 4
 .IX Item "-Q"
 perform the calculation on the authalic sphere.  The area calculation is
 accurate even if the flattening is large, \fIprovided\fR the edges are
 sufficiently short.  The perimeter calculation is not accurate.  \fB\-E\fR
 and \fB\-Q\fR are mutually exclusive.
+.IP "\fB\-R\fR" 4
+.IX Item "-R"
+The lines joining the vertices are rhumb lines instead of geodesics.
 .IP "\fB\-\-comment\-delimiter\fR" 4
 .IX Item "--comment-delimiter"
 set the comment delimiter to \fIcommentdelim\fR (e.g., \*(L"#\*(R" or \*(L"//\*(R").  If
diff --git a/man/Planimeter.1.html b/man/Planimeter.1.html
index ff2a7dc..eac96b9 100644
--- a/man/Planimeter.1.html
+++ b/man/Planimeter.1.html
@@ -17,7 +17,7 @@
 
 <h1 id="SYNOPSIS">SYNOPSIS</h1>
 
-<p><b>Planimeter</b> [ <b>-r</b> ] [ <b>-s</b> ] [ <b>-l</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-p</b> <i>prec</i> ] [ <b>-E</b> ] [ <b>-Q</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
+<p><b>Planimeter</b> [ <b>-r</b> ] [ <b>-s</b> ] [ <b>-l</b> ] [ <b>-e</b> <i>a</i> <i>f</i> ] [ <b>-p</b> <i>prec</i> ] [ <b>-G</b> | <b>-E</b> | <b>-Q</b> | <b>-R</b> ] [ <b>--comment-delimiter</b> <i>commentdelim</i> ] [ <b>--version</b> | <b>-h</b> | <b>--help</b> ] [ <b>--input-file</b> <i>infile</i> | <b>--input-string</b> <i>instring</i> ] [ <b>--line-separator</b> <i>linesep</i> ] [ <b>--output-file</b> <i>outfile</i> ]</p>
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
@@ -65,10 +65,16 @@
 <p>set the output precision to <i>prec</i> (default 6); the perimeter is given (in meters) with <i>prec</i> digits after the decimal point; the area is given (in meters^2) with (<i>prec</i> - 5) digits after the decimal point.</p>
 
 </dd>
+<dt id="G"><b>-G</b></dt>
+<dd>
+
+<p>use the series formulation for the geodesics. This is the default option and recommened for terrestrial applications.</p>
+
+</dd>
 <dt id="E"><b>-E</b></dt>
 <dd>
 
-<p>use "exact" algorithms (based on elliptic integrals) for the geodesic calculations. These are more accurate than the (default) series expansions for |<i>f</i>| > 0.02. (But note that the implementation of areas in GeodesicExact uses a high order series and this is only accurate for modest flattenings.) <b>-E</b> and <b>-Q</b> are mutually exclusive.</p>
+<p>use "exact" algorithms (based on elliptic integrals) for the geodesic calculations. These are more accurate than the (default) series expansions for |<i>f</i>| > 0.02. (But note that the implementation of areas in GeodesicExact uses a high order series and this is only accurate for modest flattenings.)</p>
 
 </dd>
 <dt id="Q"><b>-Q</b></dt>
@@ -77,6 +83,12 @@
 <p>perform the calculation on the authalic sphere. The area calculation is accurate even if the flattening is large, <i>provided</i> the edges are sufficiently short. The perimeter calculation is not accurate. <b>-E</b> and <b>-Q</b> are mutually exclusive.</p>
 
 </dd>
+<dt id="R"><b>-R</b></dt>
+<dd>
+
+<p>The lines joining the vertices are rhumb lines instead of geodesics.</p>
+
+</dd>
 <dt id="comment-delimiter"><b>--comment-delimiter</b></dt>
 <dd>
 
diff --git a/man/Planimeter.pod b/man/Planimeter.pod
index 6ea2e72..58e143a 100644
--- a/man/Planimeter.pod
+++ b/man/Planimeter.pod
@@ -5,7 +5,7 @@ Planimeter -- compute the area of geodesic polygons
 =head1 SYNOPSIS
 
 B<Planimeter> [ B<-r> ] [ B<-s> ] [ B<-l> ] [ B<-e> I<a> I<f> ]
-[ B<-p> I<prec> ] [ B<-E> ] [ B<-Q> ]
+[ B<-p> I<prec> ] [ B<-G> | B<-E> | B<-Q> | B<-R> ]
 [ B<--comment-delimiter> I<commentdelim> ]
 [ B<--version> | B<-h> | B<--help> ]
 [ B<--input-file> I<infile> | B<--input-string> I<instring> ]
@@ -87,14 +87,18 @@ set the output precision to I<prec> (default 6); the perimeter is given
 (in meters) with I<prec> digits after the decimal point; the area is
 given (in meters^2) with (I<prec> - 5) digits after the decimal point.
 
+=item B<-G>
+
+use the series formulation for the geodesics.  This is the default
+option and recommened for terrestrial applications.
+
 =item B<-E>
 
 use "exact" algorithms (based on elliptic integrals) for the geodesic
 calculations.  These are more accurate than the (default) series
 expansions for |I<f>| E<gt> 0.02.  (But note that the implementation of
 areas in GeodesicExact uses a high order series and this is only
-accurate for modest flattenings.)  B<-E> and B<-Q> are mutually
-exclusive.
+accurate for modest flattenings.)
 
 =item B<-Q>
 
@@ -103,6 +107,10 @@ accurate even if the flattening is large, I<provided> the edges are
 sufficiently short.  The perimeter calculation is not accurate.  B<-E>
 and B<-Q> are mutually exclusive.
 
+=item B<-R>
+
+The lines joining the vertices are rhumb lines instead of geodesics.
+
 =item B<--comment-delimiter>
 
 set the comment delimiter to I<commentdelim> (e.g., "#" or "//").  If
diff --git a/man/Planimeter.usage b/man/Planimeter.usage
index f874241..1228a81 100644
--- a/man/Planimeter.usage
+++ b/man/Planimeter.usage
@@ -1,23 +1,23 @@
 int usage(int retval, bool brief) {
   if (brief)
     ( retval ? std::cerr : std::cout ) << "Usage:\n"
-"    Planimeter [ -r ] [ -s ] [ -l ] [ -e a f ] [ -p prec ] [ -E ] [ -Q ] [\n"
-"    --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
+"    Planimeter [ -r ] [ -s ] [ -l ] [ -e a f ] [ -p prec ] [ -G | -E | -Q |\n"
+"    -R ] [ --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
 "    --input-file infile | --input-string instring ] [ --line-separator\n"
 "    linesep ] [ --output-file outfile ]\n"
 "\n"
 "For full documentation type:\n"
 "    Planimeter --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/Planimeter.1.html\n";
+"    http://geographiclib.sf.net/1.39/Planimeter.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
 "       Planimeter -- compute the area of geodesic polygons\n"
 "\n"
 "SYNOPSIS\n"
-"       Planimeter [ -r ] [ -s ] [ -l ] [ -e a f ] [ -p prec ] [ -E ] [ -Q ] [\n"
-"       --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
+"       Planimeter [ -r ] [ -s ] [ -l ] [ -e a f ] [ -p prec ] [ -G | -E | -Q |\n"
+"       -R ] [ --comment-delimiter commentdelim ] [ --version | -h | --help ] [\n"
 "       --input-file infile | --input-string instring ] [ --line-separator\n"
 "       linesep ] [ --output-file outfile ]\n"
 "\n"
@@ -84,18 +84,23 @@ int usage(int retval, bool brief) {
 "           area is given (in meters^2) with (prec - 5) digits after the\n"
 "           decimal point.\n"
 "\n"
+"       -G  use the series formulation for the geodesics.  This is the default\n"
+"           option and recommened for terrestrial applications.\n"
+"\n"
 "       -E  use \"exact\" algorithms (based on elliptic integrals) for the\n"
 "           geodesic calculations.  These are more accurate than the (default)\n"
 "           series expansions for |f| > 0.02.  (But note that the\n"
 "           implementation of areas in GeodesicExact uses a high order series\n"
-"           and this is only accurate for modest flattenings.)  -E and -Q are\n"
-"           mutually exclusive.\n"
+"           and this is only accurate for modest flattenings.)\n"
 "\n"
 "       -Q  perform the calculation on the authalic sphere.  The area\n"
 "           calculation is accurate even if the flattening is large, provided\n"
 "           the edges are sufficiently short.  The perimeter calculation is not\n"
 "           accurate.  -E and -Q are mutually exclusive.\n"
 "\n"
+"       -R  The lines joining the vertices are rhumb lines instead of\n"
+"           geodesics.\n"
+"\n"
 "       --comment-delimiter\n"
 "           set the comment delimiter to commentdelim (e.g., \"#\" or \"//\").  If\n"
 "           set, the input lines will be scanned for this delimiter and, if\n"
diff --git a/man/RhumbSolve.1 b/man/RhumbSolve.1
index 699cbca..b2f38db 100644
--- a/man/RhumbSolve.1
+++ b/man/RhumbSolve.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "RHUMBSOLVE 1"
-.TH RHUMBSOLVE 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH RHUMBSOLVE 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -155,29 +155,35 @@ RhumbSolve \-\- perform rhumb line calculations
 The path with constant heading between two points on the ellipsoid at
 (\fIlat1\fR, \fIlon1\fR) and (\fIlat2\fR, \fIlon2\fR) is called the rhumb line or
 loxodrome.  Its length is \fIs12\fR and the rhumb line has a forward
-azimuth \fIazi12\fR along its length.  A point at a pole is treated as a
-point a tiny distance away from the pole on the given line of longitude.
-The longitude becomes indeterminate when a rhumb line passes through a
-pole, and \fBRhumbSolve\fR reports NaNs for the longitude in this case.
+azimuth \fIazi12\fR along its length.  Also computed is \fIS12\fR is the area
+between the rhumb line from point 1 to point 2 and the equator; i.e., it
+is the area, measured counter-clockwise, of the geodesic quadrilateral
+with corners (\fIlat1\fR,\fIlon1\fR), (0,\fIlon1\fR), (0,\fIlon2\fR), and
+(\fIlat2\fR,\fIlon2\fR).  A point at a pole is treated as a point a tiny
+distance away from the pole on the given line of longitude.  The
+longitude becomes indeterminate when a rhumb line passes through a pole,
+and \fBRhumbSolve\fR reports NaNs for the longitude and the area in this
+case.
 .PP
 \&\fB\s-1NOTE:\s0\fR the rhumb line is \fBnot\fR the shortest path between two points;
 that is the geodesic and it is calculated by \fIGeodSolve\fR\|(1).
 .PP
 \&\fBRhumbSolve\fR operates in one of three modes:
 .IP "1." 4
-By default, \fBRhumbSolve\fR accepts lines on the standard input
-containing \fIlat1\fR \fIlon1\fR \fIazi12\fR \fIs12\fR and prints \fIlat2\fR \fIlon2\fR on
+By default, \fBRhumbSolve\fR accepts lines on the standard input containing
+\&\fIlat1\fR \fIlon1\fR \fIazi12\fR \fIs12\fR and prints \fIlat2\fR \fIlon2\fR \fIS12\fR on
 standard output.  This is the direct calculation.
 .IP "2." 4
 Command line arguments \fB\-l\fR \fIlat1\fR \fIlon1\fR \fIazi12\fR specify a rhumb
 line.  \fBRhumbSolve\fR then accepts a sequence of \fIs12\fR values (one per
-line) on standard input and prints \fIlat2\fR \fIlon2\fR for each.  This
-generates a sequence of points on a rhumb line.
+line) on standard input and prints \fIlat2\fR \fIlon2\fR \fIS12\fR for each.
+This generates a sequence of points on a rhumb line.
 .IP "3." 4
 With the \fB\-i\fR command line argument, \fBRhumbSolve\fR performs the inverse
 calculation.  It reads lines containing \fIlat1\fR \fIlon1\fR \fIlat2\fR \fIlon2\fR
-and prints the values of \fIazi12\fR \fIs12\fR for the corresponding shortest
-rhumb lines
+and prints the values of \fIazi12\fR \fIs12\fR \fIS12\fR for the corresponding
+shortest rhumb lines.  If the end points are on opposite meridians,
+there are two shortest rhumb lines and the east-going one is chosen.
 .SH "OPTIONS"
 .IX Header "OPTIONS"
 .IP "\fB\-i\fR" 4
@@ -250,17 +256,17 @@ write output to the file \fIoutfile\fR instead of to standard output; a
 file name of \*(L"\-\*(R" stands for standard output.
 .SH "INPUT"
 .IX Header "INPUT"
-\&\fBRhumbSolve\fR measures all angles in degrees and all lengths (\fIs12\fR)
-in meters.  On input angles (latitude, longitude, azimuth) can be as
-decimal degrees or degrees (d), minutes ('), seconds (\*(L").  A decimal
-point can only appear in the least significant component and the
-designator (d, ', or \*(R") for this component is optional; thus \f(CW\*(C`40d30\*(C'\fR,
-\&\f(CW\*(C`40d30\*(Aq\*(C'\fR, \f(CW\*(C`40.5d\*(C'\fR, and \f(CW40.5\fR are all equivalent.  By default,
-latitude precedes longitude for each point; however on input either
-may be given first by appending (or prepending) \fIN\fR or \fIS\fR to the
-latitude and \fIE\fR or \fIW\fR to the longitude.  Azimuths are measured
-clockwise from north; however this may be overridden with \fIE\fR or
-\&\fIW\fR.
+\&\fBRhumbSolve\fR measures all angles in degrees, all lengths (\fIs12\fR) in
+meters, and all areas (\fIS12\fR) in meters^2.  On input angles (latitude,
+longitude, azimuth) can be as decimal degrees or degrees (d), minutes
+('), seconds (\*(L").  A decimal point can only appear in the least
+significant component and the designator (d, ', or \*(R") for this component
+is optional; thus \f(CW\*(C`40d30\*(C'\fR, \f(CW\*(C`40d30\*(Aq\*(C'\fR, \f(CW\*(C`40.5d\*(C'\fR, and \f(CW40.5\fR are all
+equivalent.  By default, latitude precedes longitude for each point;
+however on input either may be given first by appending (or prepending)
+\&\fIN\fR or \fIS\fR to the latitude and \fIE\fR or \fIW\fR to the longitude.
+Azimuths are measured clockwise from north; however this may be
+overridden with \fIE\fR or \fIW\fR.
 .PP
 See the \f(CW\*(C`QUOTING\*(C'\fR section of \fIGeoConvert\fR\|(1) for how to quote the \s-1DMS\s0
 designators ' and ".
diff --git a/man/RhumbSolve.1.html b/man/RhumbSolve.1.html
index daffce5..e936680 100644
--- a/man/RhumbSolve.1.html
+++ b/man/RhumbSolve.1.html
@@ -21,7 +21,7 @@
 
 <h1 id="DESCRIPTION">DESCRIPTION</h1>
 
-<p>The path with constant heading between two points on the ellipsoid at (<i>lat1</i>, <i>lon1</i>) and (<i>lat2</i>, <i>lon2</i>) is called the rhumb line or loxodrome. Its length is <i>s12</i> and the rhumb line has a forward azimuth <i>azi12</i> along its length. A point at a pole is treated as a point a tiny distance away from the pole on the given line of longitude. The longitude becomes indeterminate when a rhumb line passes through a pole, and <b>RhumbSolve</b> reports NaNs for th [...]
+<p>The path with constant heading between two points on the ellipsoid at (<i>lat1</i>, <i>lon1</i>) and (<i>lat2</i>, <i>lon2</i>) is called the rhumb line or loxodrome. Its length is <i>s12</i> and the rhumb line has a forward azimuth <i>azi12</i> along its length. Also computed is <i>S12</i> is the area between the rhumb line from point 1 to point 2 and the equator; i.e., it is the area, measured counter-clockwise, of the geodesic quadrilateral with corners (<i>lat1</i>,<i>lon1</i>), ( [...]
 
 <p><b>NOTE:</b> the rhumb line is <b>not</b> the shortest path between two points; that is the geodesic and it is calculated by GeodSolve(1).</p>
 
@@ -29,13 +29,13 @@
 
 <ol>
 
-<li><p>By default, <b>RhumbSolve</b> accepts lines on the standard input containing <i>lat1</i> <i>lon1</i> <i>azi12</i> <i>s12</i> and prints <i>lat2</i> <i>lon2</i> on standard output. This is the direct calculation.</p>
+<li><p>By default, <b>RhumbSolve</b> accepts lines on the standard input containing <i>lat1</i> <i>lon1</i> <i>azi12</i> <i>s12</i> and prints <i>lat2</i> <i>lon2</i> <i>S12</i> on standard output. This is the direct calculation.</p>
 
 </li>
-<li><p>Command line arguments <b>-l</b> <i>lat1</i> <i>lon1</i> <i>azi12</i> specify a rhumb line. <b>RhumbSolve</b> then accepts a sequence of <i>s12</i> values (one per line) on standard input and prints <i>lat2</i> <i>lon2</i> for each. This generates a sequence of points on a rhumb line.</p>
+<li><p>Command line arguments <b>-l</b> <i>lat1</i> <i>lon1</i> <i>azi12</i> specify a rhumb line. <b>RhumbSolve</b> then accepts a sequence of <i>s12</i> values (one per line) on standard input and prints <i>lat2</i> <i>lon2</i> <i>S12</i> for each. This generates a sequence of points on a rhumb line.</p>
 
 </li>
-<li><p>With the <b>-i</b> command line argument, <b>RhumbSolve</b> performs the inverse calculation. It reads lines containing <i>lat1</i> <i>lon1</i> <i>lat2</i> <i>lon2</i> and prints the values of <i>azi12</i> <i>s12</i> for the corresponding shortest rhumb lines</p>
+<li><p>With the <b>-i</b> command line argument, <b>RhumbSolve</b> performs the inverse calculation. It reads lines containing <i>lat1</i> <i>lon1</i> <i>lat2</i> <i>lon2</i> and prints the values of <i>azi12</i> <i>s12</i> <i>S12</i> for the corresponding shortest rhumb lines. If the end points are on opposite meridians, there are two shortest rhumb lines and the east-going one is chosen.</p>
 
 </li>
 </ol>
@@ -138,7 +138,7 @@
 
 <h1 id="INPUT">INPUT</h1>
 
-<p><b>RhumbSolve</b> measures all angles in degrees and all lengths (<i>s12</i>) in meters. On input angles (latitude, longitude, azimuth) can be as decimal degrees or degrees (d), minutes ('), seconds ("). A decimal point can only appear in the least significant component and the designator (d, ', or ") for this component is optional; thus <code>40d30</code>, <code>40d30'</code>, <code>40.5d</code>, and <code>40.5</code> are all equivalent. By default, latitude pre [...]
+<p><b>RhumbSolve</b> measures all angles in degrees, all lengths (<i>s12</i>) in meters, and all areas (<i>S12</i>) in meters^2. On input angles (latitude, longitude, azimuth) can be as decimal degrees or degrees (d), minutes ('), seconds ("). A decimal point can only appear in the least significant component and the designator (d, ', or ") for this component is optional; thus <code>40d30</code>, <code>40d30'</code>, <code>40.5d</code>, and <code>40.5</code> are all [...]
 
 <p>See the <code>QUOTING</code> section of GeoConvert(1) for how to quote the DMS designators ' and ".</p>
 
diff --git a/man/RhumbSolve.pod b/man/RhumbSolve.pod
index 61ef335..d8ae8bd 100644
--- a/man/RhumbSolve.pod
+++ b/man/RhumbSolve.pod
@@ -18,10 +18,15 @@ B<RhumbSolve> [ B<-i> | B<-l> I<lat1> I<lon1> I<azi12> ]
 The path with constant heading between two points on the ellipsoid at
 (I<lat1>, I<lon1>) and (I<lat2>, I<lon2>) is called the rhumb line or
 loxodrome.  Its length is I<s12> and the rhumb line has a forward
-azimuth I<azi12> along its length.  A point at a pole is treated as a
-point a tiny distance away from the pole on the given line of longitude.
-The longitude becomes indeterminate when a rhumb line passes through a
-pole, and B<RhumbSolve> reports NaNs for the longitude in this case.
+azimuth I<azi12> along its length.  Also computed is I<S12> is the area
+between the rhumb line from point 1 to point 2 and the equator; i.e., it
+is the area, measured counter-clockwise, of the geodesic quadrilateral
+with corners (I<lat1>,I<lon1>), (0,I<lon1>), (0,I<lon2>), and
+(I<lat2>,I<lon2>).  A point at a pole is treated as a point a tiny
+distance away from the pole on the given line of longitude.  The
+longitude becomes indeterminate when a rhumb line passes through a pole,
+and B<RhumbSolve> reports NaNs for the longitude and the area in this
+case.
 
 B<NOTE:> the rhumb line is B<not> the shortest path between two points;
 that is the geodesic and it is calculated by GeodSolve(1).
@@ -32,23 +37,24 @@ B<RhumbSolve> operates in one of three modes:
 
 =item 1.
 
-By default, B<RhumbSolve> accepts lines on the standard input
-containing I<lat1> I<lon1> I<azi12> I<s12> and prints I<lat2> I<lon2> on
+By default, B<RhumbSolve> accepts lines on the standard input containing
+I<lat1> I<lon1> I<azi12> I<s12> and prints I<lat2> I<lon2> I<S12> on
 standard output.  This is the direct calculation.
 
 =item 2.
 
 Command line arguments B<-l> I<lat1> I<lon1> I<azi12> specify a rhumb
 line.  B<RhumbSolve> then accepts a sequence of I<s12> values (one per
-line) on standard input and prints I<lat2> I<lon2> for each.  This
-generates a sequence of points on a rhumb line.
+line) on standard input and prints I<lat2> I<lon2> I<S12> for each.
+This generates a sequence of points on a rhumb line.
 
 =item 3.
 
 With the B<-i> command line argument, B<RhumbSolve> performs the inverse
 calculation.  It reads lines containing I<lat1> I<lon1> I<lat2> I<lon2>
-and prints the values of I<azi12> I<s12> for the corresponding shortest
-rhumb lines
+and prints the values of I<azi12> I<s12> I<S12> for the corresponding
+shortest rhumb lines.  If the end points are on opposite meridians,
+there are two shortest rhumb lines and the east-going one is chosen.
 
 =back
 
@@ -143,17 +149,17 @@ file name of "-" stands for standard output.
 
 =head1 INPUT
 
-B<RhumbSolve> measures all angles in degrees and all lengths (I<s12>)
-in meters.  On input angles (latitude, longitude, azimuth) can be as
-decimal degrees or degrees (d), minutes ('), seconds (").  A decimal
-point can only appear in the least significant component and the
-designator (d, ', or ") for this component is optional; thus C<40d30>,
-C<40d30'>, C<40.5d>, and C<40.5> are all equivalent.  By default,
-latitude precedes longitude for each point; however on input either
-may be given first by appending (or prepending) I<N> or I<S> to the
-latitude and I<E> or I<W> to the longitude.  Azimuths are measured
-clockwise from north; however this may be overridden with I<E> or
-I<W>.
+B<RhumbSolve> measures all angles in degrees, all lengths (I<s12>) in
+meters, and all areas (I<S12>) in meters^2.  On input angles (latitude,
+longitude, azimuth) can be as decimal degrees or degrees (d), minutes
+('), seconds (").  A decimal point can only appear in the least
+significant component and the designator (d, ', or ") for this component
+is optional; thus C<40d30>, C<40d30'>, C<40.5d>, and C<40.5> are all
+equivalent.  By default, latitude precedes longitude for each point;
+however on input either may be given first by appending (or prepending)
+I<N> or I<S> to the latitude and I<E> or I<W> to the longitude.
+Azimuths are measured clockwise from north; however this may be
+overridden with I<E> or I<W>.
 
 See the C<QUOTING> section of GeoConvert(1) for how to quote the DMS
 designators ' and ".
diff --git a/man/RhumbSolve.usage b/man/RhumbSolve.usage
index b2d40e4..bf75b2e 100644
--- a/man/RhumbSolve.usage
+++ b/man/RhumbSolve.usage
@@ -9,7 +9,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    RhumbSolve --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/RhumbSolve.1.html\n";
+"    http://geographiclib.sf.net/1.39/RhumbSolve.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
@@ -25,10 +25,14 @@ int usage(int retval, bool brief) {
 "       The path with constant heading between two points on the ellipsoid at\n"
 "       (lat1, lon1) and (lat2, lon2) is called the rhumb line or loxodrome.\n"
 "       Its length is s12 and the rhumb line has a forward azimuth azi12 along\n"
-"       its length.  A point at a pole is treated as a point a tiny distance\n"
-"       away from the pole on the given line of longitude.  The longitude\n"
-"       becomes indeterminate when a rhumb line passes through a pole, and\n"
-"       RhumbSolve reports NaNs for the longitude in this case.\n"
+"       its length.  Also computed is S12 is the area between the rhumb line\n"
+"       from point 1 to point 2 and the equator; i.e., it is the area, measured\n"
+"       counter-clockwise, of the geodesic quadrilateral with corners\n"
+"       (lat1,lon1), (0,lon1), (0,lon2), and (lat2,lon2).  A point at a pole is\n"
+"       treated as a point a tiny distance away from the pole on the given line\n"
+"       of longitude.  The longitude becomes indeterminate when a rhumb line\n"
+"       passes through a pole, and RhumbSolve reports NaNs for the longitude\n"
+"       and the area in this case.\n"
 "\n"
 "       NOTE: the rhumb line is not the shortest path between two points; that\n"
 "       is the geodesic and it is calculated by GeodSolve(1).\n"
@@ -36,18 +40,19 @@ int usage(int retval, bool brief) {
 "       RhumbSolve operates in one of three modes:\n"
 "\n"
 "       1.  By default, RhumbSolve accepts lines on the standard input\n"
-"           containing lat1 lon1 azi12 s12 and prints lat2 lon2 on standard\n"
+"           containing lat1 lon1 azi12 s12 and prints lat2 lon2 S12 on standard\n"
 "           output.  This is the direct calculation.\n"
 "\n"
 "       2.  Command line arguments -l lat1 lon1 azi12 specify a rhumb line.\n"
 "           RhumbSolve then accepts a sequence of s12 values (one per line) on\n"
-"           standard input and prints lat2 lon2 for each.  This generates a\n"
+"           standard input and prints lat2 lon2 S12 for each.  This generates a\n"
 "           sequence of points on a rhumb line.\n"
 "\n"
 "       3.  With the -i command line argument, RhumbSolve performs the inverse\n"
 "           calculation.  It reads lines containing lat1 lon1 lat2 lon2 and\n"
-"           prints the values of azi12 s12 for the corresponding shortest rhumb\n"
-"           lines\n"
+"           prints the values of azi12 s12 S12 for the corresponding shortest\n"
+"           rhumb lines.  If the end points are on opposite meridians, there\n"
+"           are two shortest rhumb lines and the east-going one is chosen.\n"
 "\n"
 "OPTIONS\n"
 "       -i  perform an inverse calculation (see 3 above).\n"
@@ -113,16 +118,16 @@ int usage(int retval, bool brief) {
 "           file name of \"-\" stands for standard output.\n"
 "\n"
 "INPUT\n"
-"       RhumbSolve measures all angles in degrees and all lengths (s12) in\n"
-"       meters.  On input angles (latitude, longitude, azimuth) can be as\n"
-"       decimal degrees or degrees (d), minutes ('), seconds (\").  A decimal\n"
-"       point can only appear in the least significant component and the\n"
-"       designator (d, ', or \") for this component is optional; thus \"40d30\",\n"
-"       \"40d30'\", \"40.5d\", and 40.5 are all equivalent.  By default, latitude\n"
-"       precedes longitude for each point; however on input either may be given\n"
-"       first by appending (or prepending) N or S to the latitude and E or W to\n"
-"       the longitude.  Azimuths are measured clockwise from north; however\n"
-"       this may be overridden with E or W.\n"
+"       RhumbSolve measures all angles in degrees, all lengths (s12) in meters,\n"
+"       and all areas (S12) in meters^2.  On input angles (latitude, longitude,\n"
+"       azimuth) can be as decimal degrees or degrees (d), minutes ('), seconds\n"
+"       (\").  A decimal point can only appear in the least significant\n"
+"       component and the designator (d, ', or \") for this component is\n"
+"       optional; thus \"40d30\", \"40d30'\", \"40.5d\", and 40.5 are all equivalent.\n"
+"       By default, latitude precedes longitude for each point; however on\n"
+"       input either may be given first by appending (or prepending) N or S to\n"
+"       the latitude and E or W to the longitude.  Azimuths are measured\n"
+"       clockwise from north; however this may be overridden with E or W.\n"
 "\n"
 "       See the \"QUOTING\" section of GeoConvert(1) for how to quote the DMS\n"
 "       designators ' and \".\n"
diff --git a/man/TransverseMercatorProj.1 b/man/TransverseMercatorProj.1
index 79db8ef..3bee655 100644
--- a/man/TransverseMercatorProj.1
+++ b/man/TransverseMercatorProj.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "TRANSVERSEMERCATORPROJ 1"
-.TH TRANSVERSEMERCATORPROJ 1 "2014-10-02" "GeographicLib 1.38" "GeographicLib Utilities"
+.TH TRANSVERSEMERCATORPROJ 1 "2014-11-11" "GeographicLib 1.39" "GeographicLib Utilities"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff --git a/man/TransverseMercatorProj.usage b/man/TransverseMercatorProj.usage
index 2076b91..d9cc7c4 100644
--- a/man/TransverseMercatorProj.usage
+++ b/man/TransverseMercatorProj.usage
@@ -9,7 +9,7 @@ int usage(int retval, bool brief) {
 "For full documentation type:\n"
 "    TransverseMercatorProj --help\n"
 "or visit:\n"
-"    http://geographiclib.sf.net/1.38/TransverseMercatorProj.1.html\n";
+"    http://geographiclib.sf.net/1.39/TransverseMercatorProj.1.html\n";
   else
     ( retval ? std::cerr : std::cout ) << "Man page:\n"
 "NAME\n"
diff --git a/matlab/Makefile.am b/matlab/Makefile.am
index ef345de..7e86512 100644
--- a/matlab/Makefile.am
+++ b/matlab/Makefile.am
@@ -74,6 +74,7 @@ $(srcdir)/private/C2f.m \
 $(srcdir)/private/C3coeff.m \
 $(srcdir)/private/C3f.m \
 $(srcdir)/private/C4coeff.m \
+$(srcdir)/private/G4coeff.m \
 $(srcdir)/private/C4f.m \
 $(srcdir)/private/cbrt.m \
 $(srcdir)/private/cvmgt.m \
diff --git a/matlab/Makefile.in b/matlab/Makefile.in
index 8fe4b49..9fe2954 100644
--- a/matlab/Makefile.in
+++ b/matlab/Makefile.in
@@ -321,6 +321,7 @@ $(srcdir)/private/C2f.m \
 $(srcdir)/private/C3coeff.m \
 $(srcdir)/private/C3f.m \
 $(srcdir)/private/C4coeff.m \
+$(srcdir)/private/G4coeff.m \
 $(srcdir)/private/C4f.m \
 $(srcdir)/private/cbrt.m \
 $(srcdir)/private/cvmgt.m \
diff --git a/matlab/gedistance.m b/matlab/gedistance.m
index aba7b1c..765c118 100644
--- a/matlab/gedistance.m
+++ b/matlab/gedistance.m
@@ -1,8 +1,8 @@
-function [s12, azi1, azi2] = gedistance(lat1, lon1, lat2, lon2, ellipsoid)
+function [s12, azi1, azi2, S12] = gedistance(lat1, lon1, lat2, lon2, ellipsoid)
 %GEDISTANCE  Great ellipse distance between points on an ellipsoid
 %
 %   [s12, azi1, azi2] = GEDISTANCE(lat1, lon1, lat2, lon2)
-%   [s12, azi1, azi2] = GEDISTANCE(lat1, lon1, lat2, lon2, ellipsoid)
+%   [s12, azi1, azi2, S12] = GEDISTANCE(lat1, lon1, lat2, lon2, ellipsoid)
 %
 %   solves the inverse great ellipse problem of finding of length and
 %   azimuths of the great ellipse between points specified by lat1, lon1,
@@ -13,9 +13,10 @@ function [s12, azi1, azi2] = gedistance(lat1, lon1, lat2, lon2, ellipsoid)
 %   omitted, the WGS84 ellipsoid (more precisely, the value returned by
 %   DEFAULTELLIPSOID) is used.  The output s12 is the distance in meters
 %   and azi1 and azi2 are the forward azimuths at the end points in
-%   degrees.  GEDOC gives an example and provides additional background
-%   information.  GEDOC also gives the restrictions on the allowed ranges
-%   of the arguments.
+%   degrees.  The optional output S12 is the area between the great ellipse
+%   and the equator (in meters^2).  GEDOC gives an example and provides
+%   additional background information.  GEDOC also gives the restrictions
+%   on the allowed ranges of the arguments.
 %
 %   When given a combination of scalar and array inputs, the scalar inputs
 %   are automatically expanded to match the size of the arrays.
@@ -36,7 +37,7 @@ function [s12, azi1, azi2] = gedistance(lat1, lon1, lat2, lon2, ellipsoid)
 
 % Copyright (c) Charles Karney (2014) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.38.
+% This file was distributed with GeographicLib 1.39.
 
   if nargin < 4, error('Too few input arguments'), end
   if nargin < 5, ellipsoid = defaultellipsoid; end
@@ -62,6 +63,8 @@ function [s12, azi1, azi2] = gedistance(lat1, lon1, lat2, lon2, ellipsoid)
 
   f1 = 1 - f;
 
+  areap = nargout >= 4;
+
   lon12 = AngDiff(AngNormalize(lon1(:)), AngNormalize(lon2(:)));
   lon12 = AngRound(lon12);
 
@@ -77,32 +80,59 @@ function [s12, azi1, azi2] = gedistance(lat1, lon1, lat2, lon2, ellipsoid)
   slam12 = sin(lam12); slam12(lon12 == 180) = 0; clam12 = cos(lam12);
 
   % Solve great circle
-  salp1 = cbet2 .* slam12; calp1 = +cbet1 .* sbet2 - sbet1 .* cbet2 .* clam12;
-  salp2 = cbet1 .* slam12; calp2 = -sbet1 .* cbet2 + cbet1 .* sbet2 .* clam12;
-  ssig12 = hypot(salp1, calp1);
+  sgam1 = cbet2 .* slam12; cgam1 = +cbet1 .* sbet2 - sbet1 .* cbet2 .* clam12;
+  sgam2 = cbet1 .* slam12; cgam2 = -sbet1 .* cbet2 + cbet1 .* sbet2 .* clam12;
+  ssig12 = hypot(sgam1, cgam1);
   csig12 = sbet1 .* sbet2 + cbet1 .* cbet2 .* clam12;
-  [salp1, calp1] = SinCosNorm(salp1, calp1);
-  [salp2, calp2] = SinCosNorm(salp2, calp2);
+  [sgam1, cgam1] = SinCosNorm(sgam1, cgam1);
+  [sgam2, cgam2] = SinCosNorm(sgam2, cgam2);
   % no need to normalize [ssig12, csig12]
 
-  calp0 = hypot(calp1, salp1 .* sbet1);
+  cgam0 = hypot(cgam1, sgam1 .* sbet1);
 
-  ssig1 = sbet1; csig1 = cbet1 .* calp1;
+  ssig1 = sbet1; csig1 = cbet1 .* cgam1;
   [ssig1, csig1] = SinCosNorm(ssig1, csig1);
   ssig2 = ssig1 .* csig12 + csig1 .* ssig12;
   csig2 = csig1 .* csig12 - ssig1 .* ssig12;
 
-  k2 = e2 * calp0.^2;
-  n = k2 ./ (2 * (1 + sqrt(1 - k2)) - k2);
-  C1a = C1f(n);
-  A1 = a * (1 + A1m1f(n)) .* (1 - n)./(1 + n);
+  k2 = e2 * cgam0.^2;
+  epsi = k2 ./ (2 * (1 + sqrt(1 - k2)) - k2);
+  C1a = C1f(epsi);
+  A1 = a * (1 + A1m1f(epsi)) .* (1 - epsi)./(1 + epsi);
   s12 = A1 .* (atan2(ssig12, csig12) + ...
                (SinCosSeries(true, ssig2, csig2, C1a) - ...
                 SinCosSeries(true, ssig1, csig1, C1a)));
-  calp1 = calp1 .* sqrt(1 - e2 * cbet1.^2);
-  calp2 = calp2 .* sqrt(1 - e2 * cbet2.^2);
-  azi1 = atan2(salp1, calp1) / degree;
-  azi2 = atan2(salp2, calp2) / degree;
+  azi1 = atan2(sgam1, cgam1 .* sqrt(1 - e2 * cbet1.^2)) / degree;
+  azi2 = atan2(sgam2, cgam2 .* sqrt(1 - e2 * cbet2.^2)) / degree;
 
   s12 = reshape(s12, S); azi1 = reshape(azi1, S); azi2 = reshape(azi2, S);
+
+  if areap
+    sgam0 = sgam1 .* cbet1;
+    A4 = (a^2 * e2) * cgam0 .* sgam0;
+
+    n = f / (2 - f);
+    G4x = G4coeff(n);
+    G4a = C4f(epsi, G4x);
+    B41 = SinCosSeries(false, ssig1, csig1, G4a);
+    B42 = SinCosSeries(false, ssig2, csig2, G4a);
+    S12 = A4 .* (B42 - B41);
+    S12(cgam0 == 0 | sgam0 == 0) = 0;
+
+    sgam12 = sgam2 .* cgam1 - cgam2 .* sgam1;
+    cgam12 = cgam2 .* cgam1 + sgam2 .* sgam1;
+    s = sgam12 == 0 & cgam12 < 0;
+    sgam12(s) = tiny * cgam1(s); cgam12(s) = -1;
+    gam12 = atan2(sgam12, cgam12);
+
+    l = abs(gam12) < 1;
+    dlam12 = 1 + clam12(l); dbet1 = 1 + cbet1(l); dbet2 = 1 + cbet2(l);
+    gam12(l) = ...
+        2 * atan2(slam12(l) .* (sbet1(l) .* dbet2 + sbet2(l) .* dbet1), ...
+                  dlam12    .* (sbet1(l) .* sbet2(l) + dbet1 .* dbet2));
+
+    c2 = a^2 * (1 + (1 - e2) * atanhee(1, e2)) / 2;
+    S12 = S12 + c2 * gam12;
+    S12 = reshape(S12, S);
+  end
 end
diff --git a/matlab/gedoc.m b/matlab/gedoc.m
index 7eefba9..1c5df18 100644
--- a/matlab/gedoc.m
+++ b/matlab/gedoc.m
@@ -5,7 +5,7 @@ function gedoc
 %   the inverse and direct problems for great ellipses on the surface of an
 %   ellipsoid of revolution.  For more information, see
 %
-%     http://geographiclib.sf.net/1.38/greatellipse.html
+%     http://geographiclib.sf.net/html/greatellipse.html
 %
 %   Great ellipses are sometimes proposed as alternatives to computing
 %   ellipsoidal geodesics.  However geodesic calculations are easy to
@@ -45,6 +45,12 @@ function gedoc
 %     * the inverse problem -- given lat1, lon1, lat2, lon2, determine s12,
 %       azi1, and azi2.  This is solved by GEDISTANCE.
 %
+%   The routines also optionally calculate S12 ,the area between the great
+%   ellipse from point 1 to point 2 and the equator; i.e., it is the area,
+%   measured counter-clockwise, of the quadrilateral with corners
+%   (lat1,lon1), (0,lon1), (0,lon2), and (lat2,lon2).  It is given in
+%   meters^2.
+%
 %   The parameters of the ellipsoid are specified by the optional ELLIPSOID
 %   argument to the routines.  This is a two-element vector of the form
 %   [a,e], where a is the equatorial radius, e is the eccentricity e =
@@ -72,7 +78,9 @@ function gedoc
 %   Restrictions on the inputs:
 %     * All latitudes must lie in [-90, 90].
 %     * All longitudes and azimuths must lie in [-540, 540).  On output,
-%       these quantities lie in [-180, 180).
+%       these quantities lie in [-180, 180).  It is however possible to
+%       prevent this normalization of the longitude in geodreckon by
+%       setting the long_nowrap bit in the optional flags argument.
 %     * The distance s12 is unrestricted.  This allows great ellipses to wrap
 %       around the ellipsoid.
 %     * The equatorial radius, a, must be positive.
@@ -123,7 +131,7 @@ function gedoc
 
 % Copyright (c) Charles Karney (2014) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.38.
+% This file was distributed with GeographicLib 1.39.
 
   help gedoc
 end
diff --git a/matlab/geoddoc.m b/matlab/geoddoc.m
index 234938e..415f587 100644
--- a/matlab/geoddoc.m
+++ b/matlab/geoddoc.m
@@ -159,7 +159,7 @@ function geoddoc
 %   GEODDISTANCE, GEODRECKON, and GEODAREA are native implementations which
 %   will work on any MATLAB platform.  They are fully vectorized so that
 %   their speed is competitive with the compiled C++ code.  Implementations
-%   of these routines in Python and Javascript are also available; see
+%   of these routines in Python and JavaScript are also available; see
 %
 %     http://geographiclib.sf.net/html/other.html
 %
@@ -192,7 +192,7 @@ function geoddoc
 
 % Copyright (c) Charles Karney (2012-2014) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.38.
+% This file was distributed with GeographicLib 1.39.
 
   help geoddoc
 end
diff --git a/matlab/geodreckon.m b/matlab/geodreckon.m
index bdd152a..a810e5b 100644
--- a/matlab/geodreckon.m
+++ b/matlab/geodreckon.m
@@ -1,10 +1,10 @@
 function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
-      (lat1, lon1, s12_a12, azi1, ellipsoid, arcmode)
+      (lat1, lon1, s12_a12, azi1, ellipsoid, flags)
 %GEODRECKON  Point at specified azimuth, range on an ellipsoid
 %
 %   [lat2, lon2, azi2] = GEODRECKON(lat1, lon1, s12, azi1)
 %   [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] =
-%     GEODRECKON(lat1, lon1, s12_a12, azi1, ellipsoid, arcmode)
+%     GEODRECKON(lat1, lon1, s12_a12, azi1, ellipsoid, flags)
 %
 %   solves the direct geodesic problem of finding the final point and
 %   azimuth given lat1, lon1, s12, and azi1.  The input arguments lat1,
@@ -18,15 +18,27 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
 %   in GEODDOC.  GEODDOC also gives the restrictions on the allowed ranges
 %   of the arguments.
 %
-%   If arcmode if false (the default), then, in the long form of the call,
+%   flags (default 0) is a combination of 2 flags:
+%      arcmode = bitand(flags, 1)
+%      long_nowrap = bitand(flags, 2)
+%
+%   If arcmode is unset (the default), then, in the long form of the call,
 %   the input argument s12_a12 is the distance s12 (in meters) and the
 %   final output variable a12_s12 is the arc length on the auxiliary sphere
-%   a12 (in degrees).  If arcmode is true, then the roles of s12_a12 and
+%   a12 (in degrees).  If arcmode is set, then the roles of s12_a12 and
 %   a12_s12 are reversed; s12_a12 is interpreted as the arc length on the
 %   auxiliary sphere a12 (in degrees) and the corresponding distance s12 is
-%   returned in the final output variable a12_s12 (in meters).  The two
-%   optional arguments, ellispoid and arcmode, may be given in any order
-%   and either or both may be omitted.
+%   returned in the final output variable a12_s12 (in meters).
+%
+%   If long_nowrap is unset (the default), then the value lon2 is in the
+%   range [-180,180).  If long_nowrap is set, the quantity lon2 - lon1
+%   indicates how many times the geodesic wrapped around the ellipsoid.
+%   Because lon2 might be outside the normal allowed range for longitudes,
+%   [-540, 540), be sure to normalize it with rem(lon2, 360) before using
+%   it in other calls.
+%
+%   The two optional arguments, ellipsoid and flags, may be given in any
+%   order and either or both may be omitted.
 %
 %   When given a combination of scalar and array inputs, GEODRECKON behaves
 %   as though the inputs were expanded to match the size of the arrays.
@@ -57,9 +69,9 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
 %   See also GEODDOC, GEODDISTANCE, GEODAREA, GEODESICDIRECT, GEODESICLINE,
 %     DEFAULTELLIPSOID.
 
-% Copyright (c) Charles Karney (2012) <charles at karney.com>.
+% Copyright (c) Charles Karney (2012-2014) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.31.
+% This file was distributed with GeographicLib 1.39.
 %
 % This is a straightforward transcription of the C++ implementation in
 % GeographicLib and the C++ source should be consulted for additional
@@ -74,30 +86,31 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
     error('lat1, lon1, s12, azi1 have incompatible sizes')
   end
   if nargin <= 4
-    ellipsoid = defaultellipsoid; arcmode = false;
+    ellipsoid = defaultellipsoid; flags = 0;
   elseif nargin == 5
     arg5 = ellipsoid(:);
     if length(arg5) == 2
-      ellipsoid = arg5; arcmode = false;
+      ellipsoid = arg5; flags = 0;
     else
-      arcmode = arg5; ellipsoid = defaultellipsoid;
+      flags = arg5; ellipsoid = defaultellipsoid;
     end
   else
     arg5 = ellipsoid(:);
-    arg6 = arcmode;
+    arg6 = flags;
     if length(arg5) == 2
-      ellipsoid = arg5; arcmode = arg6;
+      ellipsoid = arg5; flags = arg6;
     else
-      arcmode = arg5; ellipsoid = arg6;
+      flags = arg5; ellipsoid = arg6;
     end
   end
   if length(ellipsoid) ~= 2
     error('ellipsoid must be a vector of size 2')
   end
-  arcmode = logical(arcmode);
-  if ~isscalar(arcmode)
-    error('arcmode must be true or false')
+  if ~isscalar(flags)
+    error('flags must be a scalar')
   end
+  arcmode = bitand(flags, 1);
+  long_nowrap = bitand(flags, 2);
 
   degree = pi/180;
   tiny = sqrt(realmin);
@@ -118,7 +131,7 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
   C3x = C3coeff(n);
 
   lat1 = lat1(:);
-  lon1 = AngNormalize(lon1(:));
+  lon1 = lon1(:);
   azi1 = AngRound(AngNormalize(azi1(:)));
   s12_a12 = s12_a12(:);
 
@@ -188,13 +201,23 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
   cbet2(cbet2 == 0) = tiny;
   somg2 = salp0 .* ssig2; comg2 = csig2;
   salp2 = salp0; calp2 = calp0 .* csig2;
-  omg12 = atan2(somg2 .* comg1 - comg2 .* somg1, ...
-                comg2 .* comg1 + somg2 .* somg1);
+  if long_nowrap
+    omg12 = sig12 ...
+            - (atan2(ssig2, csig2) - atan2(ssig1, csig1)) ...
+            + (atan2(somg2, comg2) - atan2(somg1, comg1));
+  else
+    omg12 = atan2(somg2 .* comg1 - comg2 .* somg1, ...
+                  comg2 .* comg1 + somg2 .* somg1);
+  end
   lam12 = omg12 + ...
           A3c .* ( sig12 + (SinCosSeries(true, ssig2, csig2, C3a) - B31));
   lon12 = lam12 / degree;
-  lon12 = AngNormalize2(lon12);
-  lon2 = AngNormalize(lon1 + lon12);
+  if long_nowrap
+    lon2 = lon1 + lon12;
+  else
+    lon12 = AngNormalize2(lon12);
+    lon2 = AngNormalize(AngNormalize(lon1) + lon12);
+  end
   lat2 = atan2(sbet2, f1 * cbet2) / degree;
   azi2 = 0 - atan2(-salp2, calp2) / degree;
   if arcmode
@@ -225,7 +248,7 @@ function [lat2, lon2, azi2, S12, m12, M12, M21, a12_s12] = geodreckon ...
 
   if areap
     C4x = C4coeff(n);
-    C4a = C4f(eps, C4x);
+    C4a = C4f(epsi, C4x);
     A4 = (a^2 * e2) * calp0 .* salp0;
     B41 = SinCosSeries(false, ssig1, csig1, C4a);
     B42 = SinCosSeries(false, ssig2, csig2, C4a);
diff --git a/matlab/gereckon.m b/matlab/gereckon.m
index 2ee0df2..0272643 100644
--- a/matlab/gereckon.m
+++ b/matlab/gereckon.m
@@ -1,8 +1,8 @@
-function [lat2, lon2, azi2] = gereckon(lat1, lon1, s12, azi1, ellipsoid)
+function [lat2, lon2, azi2, S12] = gereckon(lat1, lon1, s12, azi1, ellipsoid)
 %GERECKON  Point along great ellipse at specified azimuth and range
 %
 %   [lat2, lon2, azi2] = GERECKON(lat1, lon1, s12, azi1)
-%   [lat2, lon2, azi2] = GERECKON(lat1, lon1, s12, azi1, ellipsoid)
+%   [lat2, lon2, azi2, S12] = GERECKON(lat1, lon1, s12, azi1, ellipsoid)
 %
 %   solves the direct great ellipse problem of finding the final point and
 %   azimuth given lat1, lon1, s12, and azi1.  The input arguments lat1,
@@ -12,9 +12,10 @@ function [lat2, lon2, azi2] = gereckon(lat1, lon1, s12, azi1, ellipsoid)
 %   the eccentricity.  If ellipsoid is omitted, the WGS84 ellipsoid (more
 %   precisely, the value returned by DEFAULTELLIPSOID) is used.  lat2,
 %   lon2, and azi2 give the position and forward azimuths at the end point
-%   in degrees.  GEDOC gives an example and provides additional background
-%   information.  GEDOC also gives the restrictions on the allowed ranges
-%   of the arguments.
+%   in degrees.  The optional output S12 is the area between the great
+%   ellipse and the equator (in meters^2).  GEDOC gives an example and
+%   provides additional background information.  GEDOC also gives the
+%   restrictions on the allowed ranges of the arguments.
 %
 %   When given a combination of scalar and array inputs, GERECKON behaves
 %   as though the inputs were expanded to match the size of the arrays.
@@ -40,7 +41,7 @@ function [lat2, lon2, azi2] = gereckon(lat1, lon1, s12, azi1, ellipsoid)
 
 % Copyright (c) Charles Karney (2014) <charles at karney.com>.
 %
-% This file was distributed with GeographicLib 1.38.
+% This file was distributed with GeographicLib 1.39.
 
   if nargin < 4, error('Too few input arguments'), end
   if nargin < 5, ellipsoid = defaultellipsoid; end
@@ -61,33 +62,35 @@ function [lat2, lon2, azi2] = gereckon(lat1, lon1, s12, azi1, ellipsoid)
   f = e2 / (1 + sqrt(1 - e2));
   f1 = 1 - f;
 
+  areap = nargout >= 4;
+
   lat1 = lat1(:);
   lon1 = AngNormalize(lon1(:));
   azi1 = AngRound(AngNormalize(azi1(:)));
   s12 = s12(:);
 
   alp1 = azi1 * degree;
-  salp1 = sin(alp1); salp1(azi1 == -180) = 0;
-  calp1 = cos(alp1); calp1(abs(azi1) == 90) = 0;
+  sgam1 = sin(alp1); sgam1(azi1 == -180) = 0;
+  cgam1 = cos(alp1); cgam1(abs(azi1) == 90) = 0;
   phi = lat1 * degree;
   sbet1 = f1 * sin(phi);
   cbet1 = cos(phi); cbet1(abs(lat1) == 90) = tiny;
   [sbet1, cbet1] = SinCosNorm(sbet1, cbet1);
-  [salp1, calp1] = SinCosNorm(salp1 .* sqrt(1 - e2 * cbet1.^2), calp1);
-  salp0 = salp1 .* cbet1; calp0 = hypot(calp1, salp1 .* sbet1);
-  ssig1 = sbet1; slam1 = salp0 .* sbet1;
-  csig1 = cbet1 .* calp1; csig1(sbet1 == 0 & calp1 == 0) = 1; clam1 = csig1;
+  [sgam1, cgam1] = SinCosNorm(sgam1 .* sqrt(1 - e2 * cbet1.^2), cgam1);
+  sgam0 = sgam1 .* cbet1; cgam0 = hypot(cgam1, sgam1 .* sbet1);
+  ssig1 = sbet1; slam1 = sgam0 .* sbet1;
+  csig1 = cbet1 .* cgam1; csig1(sbet1 == 0 & cgam1 == 0) = 1; clam1 = csig1;
   [ssig1, csig1] = SinCosNorm(ssig1, csig1);
 
-  k2 = e2 * calp0.^2;
-  n = k2 ./ (2 * (1 + sqrt(1 - k2)) - k2);
-  A1 = a * (1 + A1m1f(n)) .* (1 - n)./(1 + n);
-  C1a = C1f(n);
+  k2 = e2 * cgam0.^2;
+  epsi = k2 ./ (2 * (1 + sqrt(1 - k2)) - k2);
+  A1 = a * (1 + A1m1f(epsi)) .* (1 - epsi)./(1 + epsi);
+  C1a = C1f(epsi);
   B11 = SinCosSeries(true, ssig1, csig1, C1a);
   s = sin(B11); c = cos(B11);
   stau1 = ssig1 .* c + csig1 .* s; ctau1 = csig1 .* c - ssig1 .* s;
 
-  C1pa = C1pf(n);
+  C1pa = C1pf(epsi);
   tau12 = s12 ./ A1;
   s = sin(tau12); c = cos(tau12);
   B12 = - SinCosSeries(true,  stau1 .* c + ctau1 .* s, ...
@@ -105,21 +108,42 @@ function [lat2, lon2, azi2] = gereckon(lat1, lon1, s12, azi1, ellipsoid)
 
   ssig2 = ssig1 .* csig12 + csig1 .* ssig12;
   csig2 = csig1 .* csig12 - ssig1 .* ssig12;
-  sbet2 = calp0 .* ssig2;
-  cbet2 = hypot(salp0, calp0 .* csig2);
+  sbet2 = cgam0 .* ssig2;
+  cbet2 = hypot(sgam0, cgam0 .* csig2);
   cbet2(cbet2 == 0) = tiny;
-  slam2 = salp0 .* ssig2; clam2 = csig2;
-  salp2 = salp0; calp2 = calp0 .* csig2  .* sqrt(1 - e2 * cbet2.^2);
+  slam2 = sgam0 .* ssig2; clam2 = csig2;
+  sgam2 = sgam0; cgam2 = cgam0 .* csig2;
   lam12 = atan2(slam2 .* clam1 - clam2 .* slam1, ...
                 clam2 .* clam1 + slam2 .* slam1);
   lon12 = lam12 / degree;
   lon12 = AngNormalize2(lon12);
   lon2 = AngNormalize(lon1 + lon12);
   lat2 = atan2(sbet2, f1 * cbet2) / degree;
-  azi2 = 0 - atan2(-salp2, calp2) / degree;
+  azi2 = 0 - atan2(-sgam2, cgam2 .* sqrt(1 - e2 * cbet2.^2)) / degree;
 
   lat2 = reshape(lat2, S);
   lon2 = reshape(lon2, S);
   azi2 = reshape(azi2, S);
 
+  if areap
+    n = f / (2 - f);
+    G4x = G4coeff(n);
+    G4a = C4f(epsi, G4x);
+    A4 = (a^2 * e2) * cgam0 .* sgam0;
+    B41 = SinCosSeries(false, ssig1, csig1, G4a);
+    B42 = SinCosSeries(false, ssig2, csig2, G4a);
+    sgam12 = cgam0 .* sgam0 .* ...
+             cvmgt(csig1 .* (1 - csig12) + ssig12 .* ssig1, ...
+                   ssig12 .* (csig1 .* ssig12 ./ (1 + csig12) + ssig1), ...
+                   csig12 <= 0);
+    cgam12 = sgam0.^2 + cgam0.^2 .* csig1 .* csig2;
+    s = cgam0 == 0 | sgam0 == 0;
+    sgam12(s) = sgam2(s) .* cgam1(s) - cgam2(s) .* sgam1(s);
+    cgam12(s) = cgam2(s) .* cgam1(s) + sgam2(s) .* sgam1(s);
+    s = s & sgam12 == 0 & cgam12 < 0;
+    sgam12(s) = tiny * cgam1(s); cgam12(s) = -1;
+    c2 = a^2 * (1 + (1 - e2) * atanhee(1, e2)) / 2;
+    S12 = c2 * atan2(sgam12, cgam12) + A4 .* (B42 - B41);
+  end
+
 end
diff --git a/matlab/private/AngNormalize2.m b/matlab/private/AngNormalize2.m
index f872d43..6cc5a99 100644
--- a/matlab/private/AngNormalize2.m
+++ b/matlab/private/AngNormalize2.m
@@ -4,5 +4,5 @@ function x = AngNormalize2(x)
 %   X = ANGNORMALIZE(X) reduces arbitrary angles to the range [-180, 180).
 %   X can be any shape.
 
-  x = AngNormalize(mod(x, 360));
+  x = AngNormalize(rem(x, 360));
 end
diff --git a/matlab/private/C4f.m b/matlab/private/C4f.m
index d17f107..c481b7f 100644
--- a/matlab/private/C4f.m
+++ b/matlab/private/C4f.m
@@ -3,8 +3,8 @@ function C4 = C4f(epsi, C4x)
 %
 %   C4 = C4F(EPSI, C4X) evaluates C_{4,l} in the expansion for the area
 %   (Eq. (65) expressed in terms of n and epsi) using the coefficient
-%   vector C4X.  K2 is a K x 1 array.  C4X is a 1 x 15 array.  C4 is a K x
-%   5 array.
+%   vector C4X.  EPSI is a K x 1 array.  C4X is a 1 x 21 array.  C4 is a
+%   K x 6 array.
 
   nC4 = 6;
   nC4x = size(C4x, 2);
diff --git a/matlab/private/G4coeff.m b/matlab/private/G4coeff.m
new file mode 100644
index 0000000..d0ca864
--- /dev/null
+++ b/matlab/private/G4coeff.m
@@ -0,0 +1,33 @@
+function G4x = G4coeff(n)
+%G4COEFF  Evaluate coefficients for C_4 for great ellipse
+%
+%   G4x = G4COEFF(N) evaluates the coefficients of epsilon^l in expansion
+%   of the greate ellipse area (expressed in terms of n and epsi).  N is a
+%   scalar.  G4x is a 1 x 21 array.
+
+  nG4 = 6;
+  nG4x = (nG4 * (nG4 + 1)) / 2;
+  G4x = zeros(1, nG4x);
+  G4x(0+1) = (n*(n*(n*(n*(200*n+416)+1144)+6864)+21021)+15015)/90090;
+  G4x(1+1) = (n*(n*((-117944*n-110552)*n-84227)-41184)-9009)/120120;
+  G4x(2+1) = (n*(n*(6417449*n+3013374)+1012583)+172458)/720720;
+  G4x(3+1) = ((-135037988*n-32774196)*n-4232371)/5765760;
+  G4x(4+1) = (138833443*n+13938873)/5765760;
+  G4x(5+1) = -13200233/1537536;
+  G4x(6+1) = (n*(n*(n*(117944*n+110552)+84227)+41184)+9009)/1081080;
+  G4x(7+1) = (n*((-5975241*n-2676466)*n-847847)-136422)/4324320;
+  G4x(8+1) = (n*(71379996*n+16424252)+1987557)/17297280;
+  G4x(9+1) = (-39452953*n-3753828)/8648640;
+  G4x(10+1) = 2625577/1537536;
+  G4x(11+1) = (n*(n*(203633*n+80106)+20735)+2574)/1441440;
+  G4x(12+1) = ((-3634676*n-741988)*n-76219)/5765760;
+  G4x(13+1) = (2443153*n+208182)/2882880;
+  G4x(14+1) = -5512967/15375360;
+  G4x(15+1) = (n*(48020*n+8372)+715)/1153152;
+  G4x(16+1) = (-71477*n-5317)/768768;
+  G4x(17+1) = 22397/439296;
+  G4x(18+1) = (1407*n+91)/329472;
+  G4x(19+1) = -5453/1317888;
+  G4x(20+1) = 21/146432;
+end
+
diff --git a/maxima/Makefile.mk b/maxima/Makefile.mk
index dba8c12..ac6d123 100644
--- a/maxima/Makefile.mk
+++ b/maxima/Makefile.mk
@@ -1,4 +1,4 @@
-MAXIMA = tm ellint tmseries geod
+MAXIMA = tm ellint tmseries geod geodesic auxlat
 MAXIMASOURCES = $(addsuffix .mac,$(MAXIMA))
 
 all:
diff --git a/maxima/auxlat.mac b/maxima/auxlat.mac
new file mode 100644
index 0000000..15b09db
--- /dev/null
+++ b/maxima/auxlat.mac
@@ -0,0 +1,256 @@
+/*
+Compute series expansions for the auxiliary latitudes.
+
+Copyright (c) Charles Karney (2014) <charles at karney.com> and licensed
+under the MIT/X11 License.  For more information, see
+http://geographiclib.sourceforge.net/
+
+This maxima program compute the coefficients for trigonometric series
+relating the six latitudes
+
+  phi     geographic
+  beta    parametric
+  theta   geocentric
+  mu      rectifying
+  chi     conformal
+  xi      authalic
+
+All 30 inter-relations are found.  The coefficients are expressed as
+Taylor series in the third flattening n.  This generates the series
+given on the page
+
+  http://geographiclib.sourceforge.net/html/auxlat.html
+
+Instructions:
+
+ * [optional] edit to set the desired value of maxpow (currently 8)
+ * start maxima and run
+     batch("auxlat.mac")$
+     writefile("auxlat.txt")$
+     dispall()$
+     closefile()$
+
+*/
+
+/*
+    revert
+       var2 = expr(var1) = series in eps
+    to
+       var1 = revertexpr(var2) = series in eps
+
+Require that expr(var1) = var1 to order eps^0.  This throws in a
+trigreduce to convert to multiple angle trig functions.
+*/
+maxpow:8$
+reverta(expr,var1,var2,eps,pow):=block([tauacc:1,sigacc:0,dsig],
+  dsig:ratdisrep(taylor(expr-var1,eps,0,pow)),
+  dsig:subst([var1=var2],dsig),
+  for n:1 thru pow do (tauacc:trigreduce(ratdisrep(taylor(
+    -dsig*tauacc/n,eps,0,pow))),
+    sigacc:sigacc+expand(diff(tauacc,var2,n-1))),
+  var2+sigacc)$
+
+/* beta in terms of phi */
+beta_phi:taylor(atan((1-n)/(1+n)*tan(phi)),n,0,maxpow)$
+beta_phi:subst([atan(tan(phi))=phi,tan(phi)=sin(phi)/cos(phi)],
+  ratdisrep(beta_phi))$
+beta_phi:trigreduce(ratsimp(beta_phi))$
+/* phi in terms of beta */
+phi_beta:subst([n=-n,phi=beta],beta_phi)$
+/* Alt:
+  beta_phi:reverta(beta_phi,phi,beta,n,maxpow)$
+*/
+/* theta in terms of beta */
+theta_beta:subst([phi=beta],beta_phi)$
+/* theta in terms of phi */
+theta_phi:subst([beta=beta_phi],theta_beta)$
+theta_phi:trigreduce(taylor(theta_phi,n,0,maxpow))$
+/* phi in terms of theta */
+phi_theta:subst([n=-n,phi=theta],theta_phi)$
+
+/* chi in terms of phi */
+atanexp(x,eps):=''(ratdisrep(taylor(atan(x+eps),eps,0,maxpow)))$
+chi_phi:block([psiv,tanchi,chiv,qq,e],
+    /* Here qq = atanh(sin(phi)) = asinh(tan(phi)) */
+    psiv:qq-e*atanh(e*tanh(qq)),
+    psiv:subst([e=sqrt(4*n/(1+n)^2),qq=atanh(sin(phi))],
+      ratdisrep(taylor(psiv,e,0,2*maxpow)))
+    +asinh(sin(phi)/cos(phi))-atanh(sin(phi)),
+    tanchi:subst([abs(cos(phi))=cos(phi),sqrt(sin(phi)^2+cos(phi)^2)=1],
+      ratdisrep(taylor(sinh(psiv),n,0,maxpow)))+tan(phi)-sin(phi)/cos(phi),
+    chiv:atanexp(tan(phi),tanchi-tan(phi)),
+    chiv:subst([atan(tan(phi))=phi,
+      tan(phi)=sin(phi)/cos(phi)],
+      (chiv-phi)/cos(phi))*cos(phi)+phi,
+    chiv:ratdisrep(taylor(chiv,n,0,maxpow)),
+    expand(trigreduce(chiv)))$
+
+/* phi in terms of chi */
+phi_chi:reverta(chi_phi,phi,chi,n,maxpow)$
+
+df[i]:=if i<0 then df[i+2]/(i+2) else i!!$
+/* df[-1] = 1; df[-3] = -1 */
+c(k,maxpow):=sum(n^(k+2*j)*(df[2*j-3]*df[2*j+2*k-3])/(df[2*j]*df[2*j+2*k]),
+  j,0,(maxpow-k)/2)$
+
+/* mu in terms of beta */
+mu_beta:expand(ratdisrep(
+    taylor(beta+sum(c(i,maxpow)/i*sin(2*i*beta),i,1,maxpow)/c(0,maxpow),
+      n,0,maxpow)))$
+/* beta in terms of mu */
+beta_mu:reverta(mu_beta,beta,mu,n,maxpow)$
+
+asinexp(x,eps):=''(sqrt(1-x^2)*
+  sum(ratsimp(diff(asin(x),x,i)/i!/sqrt(1-x^2))*eps^i,i,0,maxpow))$
+sinxi:(sin(phi)/2*(1/(1-e^2*sin(phi)^2) + atanh(e*sin(phi))/(e*sin(phi))))/
+(1/2*(1/(1-e^2) + atanh(e)/e))$
+sinxi:ratdisrep(taylor(sinxi,e,0,2*maxpow))$
+sinxi:subst([e=2*sqrt(n)/(1+n)],sinxi)$
+sinxi:expand(trigreduce(ratdisrep(taylor(sinxi,n,0,maxpow))))$
+xi_phi:asinexp(sin(phi),sinxi-sin(phi))$
+xi_phi:taylor(subst([sqrt(1-sin(phi)^2)=cos(phi),asin(sin(phi))=phi],
+    xi_phi),n,0,maxpow)$
+xi_phi:expand(ratdisrep(coeff(xi_phi,n,0))+sum(
+  ratsimp(trigreduce(sin(phi)*ratsimp(
+        subst([sin(phi)=sqrt(1-cos(phi)^2)],
+          ratsimp(trigexpand(ratdisrep(coeff(xi_phi,n,i)))/sin(phi))))))*n^i,
+  i,1,maxpow))$
+phi_xi:reverta(xi_phi,phi,xi,n,maxpow)$
+mu_phi:expand(trigreduce(taylor(subst([beta=beta_phi],mu_beta),n,0,maxpow)))$
+phi_mu:expand(trigreduce(taylor(subst([beta=beta_mu],phi_beta),n,0,maxpow)))$
+chi_mu:expand(trigreduce(taylor(subst([phi=phi_mu],chi_phi),n,0,maxpow)))$
+mu_chi:expand(trigreduce(taylor(subst([phi=phi_chi],mu_phi),n,0,maxpow)))$
+beta_chi:expand(trigreduce(taylor(subst([phi=phi_chi],beta_phi),n,0,maxpow)))$
+chi_beta:expand(trigreduce(taylor(subst([phi=phi_beta],chi_phi),n,0,maxpow)))$
+beta_theta:expand(trigreduce
+  (taylor(subst([phi=phi_theta],beta_phi),n,0,maxpow)))$
+beta_xi:expand(trigreduce(taylor(subst([phi=phi_xi],beta_phi),n,0,maxpow)))$
+chi_theta:expand(trigreduce(taylor(subst([phi=phi_theta],chi_phi),n,0,maxpow)))$
+chi_xi:expand(trigreduce(taylor(subst([phi=phi_xi],chi_phi),n,0,maxpow)))$
+mu_theta:expand(trigreduce(taylor(subst([phi=phi_theta],mu_phi),n,0,maxpow)))$
+mu_xi:expand(trigreduce(taylor(subst([phi=phi_xi],mu_phi),n,0,maxpow)))$
+theta_chi:expand(trigreduce(taylor(subst([phi=phi_chi],theta_phi),n,0,maxpow)))$
+theta_mu:expand(trigreduce(taylor(subst([phi=phi_mu],theta_phi),n,0,maxpow)))$
+theta_xi:expand(trigreduce(taylor(subst([phi=phi_xi],theta_phi),n,0,maxpow)))$
+xi_beta:expand(trigreduce(taylor(subst([phi=phi_beta],xi_phi),n,0,maxpow)))$
+xi_chi:expand(trigreduce(taylor(subst([phi=phi_chi],xi_phi),n,0,maxpow)))$
+xi_mu:expand(trigreduce(taylor(subst([phi=phi_mu],xi_phi),n,0,maxpow)))$
+xi_theta:expand(trigreduce(taylor(subst([phi=phi_theta],xi_phi),n,0,maxpow)))$
+
+norm(x):=block([z:subst([n=0],x)],
+  z+sum(coeff(expand(x),sin(2*i*z))*sin(2*i*z),i,1,maxpow))$
+
+(
+tx[beta,chi]:norm(beta_chi),
+tx[beta,mu]:norm(beta_mu),
+tx[beta,phi]:norm(beta_phi),
+tx[beta,theta]:norm(beta_theta),
+tx[beta,xi]:norm(beta_xi),
+
+tx[chi,beta]:norm(chi_beta),
+tx[chi,mu]:norm(chi_mu),
+tx[chi,phi]:norm(chi_phi),
+tx[chi,theta]:norm(chi_theta),
+tx[chi,xi]:norm(chi_xi),
+
+tx[mu,beta]:norm(mu_beta),
+tx[mu,chi]:norm(mu_chi),
+tx[mu,phi]:norm(mu_phi),
+tx[mu,theta]:norm(mu_theta),
+tx[mu,xi]:norm(mu_xi),
+
+tx[phi,beta]:norm(phi_beta),
+tx[phi,chi]:norm(phi_chi),
+tx[phi,mu]:norm(phi_mu),
+tx[phi,theta]:norm(phi_theta),
+tx[phi,xi]:norm(phi_xi),
+
+tx[theta,beta]:norm(theta_beta),
+tx[theta,chi]:norm(theta_chi),
+tx[theta,mu]:norm(theta_mu),
+tx[theta,phi]:norm(theta_phi),
+tx[theta,xi]:norm(theta_xi),
+
+tx[xi,beta]:norm(xi_beta),
+tx[xi,chi]:norm(xi_chi),
+tx[xi,mu]:norm(xi_mu),
+tx[xi,phi]:norm(xi_phi),
+tx[xi,theta]:norm(xi_theta))$
+
+ll1:[
+[beta,phi],
+[theta,phi],
+[theta,beta],
+[mu,phi],
+[mu,beta],
+[mu,theta]]$
+ll2:[
+[chi,phi],
+[chi,beta],
+[chi,theta],
+[chi,mu],
+[xi,phi],
+[xi,beta],
+[xi,theta],
+[xi,mu],
+[xi,chi]]$
+
+tt[i,j]:=if i=j then [] else
+block([v:tx[i,j],x:j,l:[]],
+  for i:1 thru maxpow do block([l1:[],c:coeff(v,sin(2*i*x))],
+    for j:i thru maxpow do l1:endcons(coeff(c,n,j),l1),
+    l:endcons(l1,l)),
+  l)$
+texa(i,j,pow):=block([x:j,y:i,v:tt[i,j],s:"\\",sn:"\\sin "],
+  x:concat(s,x), y:concat(s,y),
+  print(concat(y, "-",  x, "&=\\textstyle{}")),
+  for k:1 thru pow do block([t:v[k],sgn,nterm:0,str:""],
+    sgn:0,
+    for l:1 thru pow-k+1 do block([m:t[l]],
+      if m # 0 then (nterm:nterm+1,
+        if sgn = 0 then sgn:if m>0 then 1 else -1) ),
+    t:sgn*t,
+    if sgn # 0 then block([f:true],
+      str:concat(str,if sgn > 0 then "+" else "-"),
+      if nterm > 1 then str:concat(str,"\\bigl("),
+      for l:1 thru pow-k+1 do block([c:t[l]],
+      if c # 0 then (sgn:if c > 0 then 1 else -1, c:sgn*c,
+        if not f and nterm > 1 then
+        str:concat(str,if sgn > 0 then "+" else "-"),
+        f:false,
+        if c # 1 then if integerp(c) then str:concat(str,c) else
+        str:concat(str,"\\frac{",num(c),"}{",denom(c),"}"),
+        if l+k-1 > 1 then
+        str:concat(str,"n^{",l+k-1,"}")
+        else
+        str:concat(str,"n"))),
+    if nterm > 1 then str:concat(str,"\\bigr)"),
+    str:concat(str,sn,2*k,x)),
+  print(str)),
+print(concat(if v[pow+1][1] < 0 then "-" else "+","\\ldots\\\\")))$
+cf(i,j):= (
+  print(concat("<p>&",i,"; − &",j,";:<br><tt><small>")),
+  for x in tt[i,j] do block([str:"   ["],
+    for i:1 thru length(x) do
+    str:concat(str,string(x[i]),if i<length(x) then ", " else "]<br>"),
+    print(str)),
+  print("</small></tt>"))$
+
+disptex(ll,pow):=
+block([linel:1000],
+  print("\\f["),
+  print("\\begin{align}"),
+  for xx in ll do (texa(xx[1],xx[2],pow),texa(xx[2],xx[1],pow)),
+  print("\\end{align}"),
+  print("\\f]"))$
+dispcoeffs(ll):=
+block([linel:1000],
+  for xx in ll do (cf(xx[1],xx[2]),cf(xx[2],xx[1])))$
+dispall():=(
+  print(""),
+  disptex(ll1,4),
+  print(""),
+  disptex(ll2,3),
+  print(""),
+  dispcoeffs(append(ll1,ll2)),
+  print(""))$
diff --git a/maxima/gearea.mac b/maxima/gearea.mac
new file mode 100644
index 0000000..8463901
--- /dev/null
+++ b/maxima/gearea.mac
@@ -0,0 +1,138 @@
+/*
+Compute the series expansion for the great ellipse area.
+
+Copyright (c) Charles Karney (2014) <charles at karney.com> and licensed
+under the MIT/X11 License.  For more information, see
+http://geographiclib.sourceforge.net/
+
+Area of great ellipse quad
+
+area from equator to phi
+dA = dlambda*b^2*sin(phi)/2*
+       (1/(1-e^2*sin(phi)^2) + atanh(e*sin(phi))/(e*sin(phi)))
+Total area = 2*pi*(a^2 + b^2*atanh(e)/e)
+
+convert to beta using
+  sin(phi)^2 = sin(beta)^2/(1-e^2*cos(beta)^2)
+
+dA = dlambda*sin(beta)/2*
+  ( a^2*sqrt(1-e^2*cos(beta)^2)
+  + b^2*atanh(e*sin(beta)/sqrt(1-e^2*cos(beta)^2))
+          /(e*sin(beta))) )
+
+subst for great ellipse
+  sin(beta) = cos(gamma0)*sin(sigma)
+  dlambda = dsigma * sin(gamma0) / (1 - cos(gamma0)^2*sin(sigma)^2)
+  (1-e^2*cos(beta)^2) = (1-e^2)*(1+k^2*sin(sigma)^2)
+  k^2 = ep^2*cos(gamma0)^2
+  e*sin(beta) = sqrt(1-e^2)*k*sin(sigma)
+
+dA = dsigma*sin(gamma0)*cos(gamma0)*sin(sigma)/2*e^2*a^2*sqrt(1+ep^2)*
+    ( (1+k^2*sin(sigma)^2)
+    + atanh(k*sin(sigma)/sqrt(1+k^2*sin(sigma)^2)) / (k*sin(sigma))) )
+    / (ep^2 - k^2*sin(sigma)^2)
+
+Spherical case radius c, c^2 = a^2/2 + b^2/2*atanh(e)/e
+dA0 = dsigma*sin(gamma0)*cos(gamma0)*sin(sigma)/2*
+    ( a^2 + b^2*atanh(e)/e)
+    / (1 - cos(gamma0)^2*sin(sigma)^2)
+   = dsigma*sin(gamma0)*cos(gamma0)*sin(sigma)/2*e^2*a^2*sqrt(1+ep^2)
+    ( sqrt(1+ep^2) + atanh(ep/sqrt(1+ep^2))/ep )
+    / (ep^2 - k^2*sin(sigma)^2)
+
+dA-dA0 = dsigma*sin(gamma0)*cos(gamma0)*sin(sigma)/2*e^2*a^2*sqrt(1+ep^2)*
+    -( ( sqrt(1+ep^2)
+        + atanh(ep/sqrt(1+ep^2))/ep ) -
+       ( sqrt(1+k^2*sin(sigma)^2)
+        + atanh(k*sin(sigma)/sqrt(1+k^2*sin(sigma)^2)) / (k*sin(sigma)) ) ) /
+     / (ep^2 - k^2*sin(sigma)^2)
+
+atanh(y/sqrt(1+y^2)) = asinh(y)
+
+dA-dA0 = dsigma*sin(gamma0)*cos(gamma0)*sin(sigma)/2*e^2*a^2*
+    - ( ( sqrt(1+ep^2) + asinh(ep)/ep ) -
+        ( sqrt(1+k^2*sin(sigma)^2)
+         + asinh(k*sin(sigma)) / (k*sin(sigma)) ) ) /
+      / (ep^2 - k^2*sin(sigma)^2)
+
+r(x) = sqrt(1+x) + asinh(sqrt(x))/sqrt(x)
+dA-dA0 = e^2*a^2*dsigma*sin(gamma0)*cos(gamma0)*
+    - ( r(ep^2) - r(k^2*sin(sigma)^2)) /
+      (   ep^2  -   k^2*sin(sigma)^2 ) *
+      sin(sigma)/2*sqrt(1+ep^2)*
+
+subst
+  ep^2=4*n/(1-n)^2 -- second eccentricity in terms of third flattening
+  ellipse semi axes = [a, a * sqrt(1-e^2*cos(gamma0)^2)]
+  third flattening for ellipsoid
+  eps = (1 - sqrt(1-e^2*cos(gamma0)^2)) / (1 + sqrt(1-e^2*cos(gamma0)^2))
+  e^2*cos(gamma0)^2 = 4*eps/(1+eps)^2 -- 1st ecc in terms of 3rd flattening
+  k2=((1+n)/(1-n))^2 * 4*eps/(1+eps)^2
+
+Taylor expand in n and eps, integrate, trigreduce
+*/
+
+taylordepth:5$
+jtaylor(expr,var1,var2,ord):=block([zz],expand(subst([zz=1],
+    ratdisrep(taylor(subst([var1=zz*var1,var2=zz*var2],expr),zz,0,ord)))))$
+
+/* Great ellipse via r */
+computeG4(maxpow):=block([int,r,intexp,area, x,ep2,k2],
+  maxpow:maxpow-1,
+  r : sqrt(1+x) + asinh(sqrt(x))/sqrt(x),
+  int:-(rf(ep2) - rf(k2*sin(sigma)^2)) / (ep2 - k2*sin(sigma)^2)
+  * sin(sigma)/2*sqrt(1+ep2),
+  int:subst([rf(ep2)=subst([x=ep2],r),
+    rf(k2*sin(sigma)^2)=subst([x=k2*sin(sigma)^2],r)],
+    int),
+  int:subst([abs(sin(sigma))=sin(sigma)],int),
+  int:subst([k2=((1+n)/(1-n))^2 * 4*eps/(1+eps)^2,ep2=4*n/(1-n)^2],int),
+  intexp:jtaylor(int,n,eps,maxpow),
+  area:trigreduce(integrate(intexp,sigma)),
+  area:expand(area-subst(sigma=%pi/2,area)),
+  for i:0 thru maxpow do G4[i]:coeff(area,cos((2*i+1)*sigma)),
+  if expand(area-sum(G4[i]*cos((2*i+1)*sigma),i,0,maxpow)) # 0
+  then error("left over terms in G4"),
+  'done)$
+
+codeG4(maxpow):=block([tab1:"  ",nn:maxpow,c],
+  c:0,
+  for m:0 thru nn-1 do block(
+    [q:jtaylor(G4[m],n,eps,nn-1), linel:1200],
+    for j:m thru nn-1 do (
+      print(concat(tab1,"G4x(",c,"+1) = ",
+          string(horner(coeff(q,eps,j))),";")),
+      c:c+1)
+    ),
+  'done)$
+dispG4(ord):=(ord:ord-1,for i:0 thru ord do
+block([tt:jtaylor(G4[i],n,eps,ord),
+  ttt,t4,linel:1200],
+  for j:i thru ord do (
+    ttt:coeff(tt,eps,j),
+    if ttt # 0 then block([a:taylor(ttt+n^(ord+1),n,0,ord+1),paren,s],
+      paren : is(length(a) > 2),
+      s:if j = i then concat("G4[",i,"] = ") else "        ",
+      if subst([n=1],part(a,1)) > 0 then s:concat(s,"+ ")
+      else (s:concat(s,"- "), a:-a),
+      if paren then s:concat(s,"("),
+      for k:1 thru length(a)-1 do block([term:part(a,k),nn],
+        nn:subst([n=1],term),
+        term:term/nn,
+        if nn > 0 and k > 1 then s:concat(s," + ")
+        else if nn < 0 then (s:concat(s," - "), nn:-nn),
+        if lopow(term,n) = 0 then s:concat(s,string(nn))
+        else (
+          if nn # 1 then s:concat(s,string(nn)," * "),
+          s:concat(s,string(term))
+          )),
+      if paren then s:concat(s,")"),
+      if j>0 then s:concat(s," * ", string(eps^j)),
+      print(concat(s,if j = ord then ";" else ""))))))$
+
+maxpow:6$
+(computeG4(maxpow),
+  print(""),
+  codeG4(maxpow),
+  print(""),
+  dispG4(maxpow))$
diff --git a/maxima/geod.mac b/maxima/geod.mac
index bbdb78b..445dd7e 100644
--- a/maxima/geod.mac
+++ b/maxima/geod.mac
@@ -34,8 +34,8 @@ To run the code, start Maxima and enter
 
 taylordepth:5$
 ataylor(expr,var,ord):=expand(ratdisrep(taylor(expr,var,0,ord)))$
-jtaylor(expr,var1,var2,ord):=expand(subst([zz=1],
-    ratdisrep(taylor(subst([var1=zz*var1,var2=zz*var2],expr),zz,0,ord))))$
+jtaylor(expr,var1,var2,ord):=block([zz],expand(subst([zz=1],
+    ratdisrep(taylor(subst([var1=zz*var1,var2=zz*var2],expr),zz,0,ord)))))$
 
 /*
 
diff --git a/maxima/geodesic.mac b/maxima/geodesic.mac
index c1c202c..4be3538 100644
--- a/maxima/geodesic.mac
+++ b/maxima/geodesic.mac
@@ -1,8 +1,8 @@
 /*
 Solve the direct and inverse geodesic problems accurately.
 
-Copyright (c) Charles Karney (2013) <charles at karney.com> and licensed
-under the MIT/X11 License.  For more information, see
+Copyright (c) Charles Karney (2013-2014) <charles at karney.com> and
+licensed under the MIT/X11 License.  For more information, see
 http://geographiclib.sourceforge.net/
 
 References:
@@ -19,10 +19,10 @@ Note that the area calculation always uses the series expansion (I don't
 know how to express the integrals in terms of elliptic integrals).
 
 Before running this file, you need to compute and save the series
-expansions by editing god.mac setting maxpow appropriately (near the end
-of the file) and uncommenting the last line (to save the results).  If
-you're testing the accuracy of the series expansions (exact : false) or
-if you're interested in accurate results for the area, that pick a
+expansions by editing geod.mac setting maxpow appropriately (near the
+end of the file) and uncommenting the last line (to save the results).
+If you're testing the accuracy of the series expansions (exact : false)
+or if you're interested in accurate results for the area, that pick a
 largish value of maxpow (e.g., 20).  This program can truncate the
 series to a smaller power.  If you just want to compute accurate
 geodesics and are not interested in the area, then use elliptic
@@ -290,7 +290,7 @@ geod_lineinit(g,lat1,lon1,azi1):=block([a, f,
   GEOD_LATITUDE | GEOD_AZIMUTH, Always allow latitude and azimuth
   Guard against underflow in salp0 */
   azi1 : AngRound(AngNormalize(azi1)),
-  lon1 : AngNormalize(lon1),
+  /* Don't normalizing lon1... */
   /* alp1 is in [0, pi] */
   alp1 : azi1 * degree,
   /* Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
@@ -461,8 +461,9 @@ geod_genposition(l, arcmode,  s12_a12):=block(
   salp2 : l[l_salp0], calp2 : l[l_calp0] * csig2, /* No need to normalize */
   if not exact then
   /* omg12 = omg2 - omg1 */
-  omg12 : atan2x(somg2 * l[l_comg1] - comg2 * l[l_somg1],
-    comg2 * l[l_comg1] + somg2 * l[l_somg1]),
+  omg12 : sig12
+  - (atan2x(ssig2, csig2) - atan2x(l[l_ssig1], l[l_csig1]))
+  + (atan2x(somg2, comg2) - atan2x(l[l_somg1], l[l_comg1])),
   s12 : if arcmode then l[l_b] *
   ((if exact then l[l_E0] else (1 + l[l_A1m1])) * sig12 + AB1) else s12_a12,
   if exact then block([somg2:l[l_salp0] * ssig2,
@@ -470,17 +471,17 @@ geod_genposition(l, arcmode,  s12_a12):=block(
     cchi2],
     /* Without normalization we have schi2 = somg2. */
     cchi2 : l[l_f1] * dn2 *  comg2,
-    lam12 : atan2x(somg2 * l[l_cchi1] - cchi2 * l[l_somg1],
-      cchi2 * l[l_cchi1] + somg2 * l[l_somg1]) -
+    lam12 : (sig12
+      - (atan2x(ssig2, csig2) - atan2x(l[l_ssig1], l[l_csig1]))
+      + (atan2x(somg2, cchi2) - atan2x(l[l_somg1], l[l_cchi1]))) -
     l[l_e2]/l[l_f1] * l[l_salp0] * l[l_H0] *
     (sig12 + deltah(ssig2, csig2, dn2,
         l[l_E][e_k2], l[l_E][e_alpha2], l[l_E][e_hc]) - l[l_H1] ) )
   else lam12 : omg12 + l[l_A3c] *
   ( sig12 + (SinCosSeries(true, ssig2, csig2, l[l_C3a]) - l[l_B31])),
   lon12 : lam12 / degree,
-  /* Use AngNormalize2 because longitude might have wrapped multiple times. */
-  lon12 : AngNormalize2(lon12),
-  lon2 : AngNormalize(l[l_lon1] + lon12),
+  /* Don't normalize lon2... */
+  lon2 : l[l_lon1] + lon12,
   lat2 : atan2x(sbet2, l[l_f1] * cbet2) / degree,
   /* minus signs give range [-180, 180). 0- converts -0 to +0. */
   azi2 : 0 - atan2x(-salp2, calp2) / degree,
diff --git a/maxima/rhumbarea.mac b/maxima/rhumbarea.mac
new file mode 100644
index 0000000..0272a10
--- /dev/null
+++ b/maxima/rhumbarea.mac
@@ -0,0 +1,198 @@
+/*
+Compute the series expansion for the rhumb area.
+
+Copyright (c) Charles Karney (2014) <charles at karney.com> and licensed
+under the MIT/X11 License.  For more information, see
+http://geographiclib.sourceforge.net/
+
+Instructions: edit the value of maxpow near the end of this file.  Then
+load the file into maxima.
+
+Area of rhumb quad
+
+dA = c^2 sin(xi) * dlambda
+c = authalic radius
+xi = authalic latitude
+Express sin(xi) in terms of chi and expand for small n
+this can be written in terms of powers of sin(chi)
+Subst sin(chi) = tanh(psi) = tanh(m*lambda)
+Integrate over lambda to give
+
+A = c^2 * S(chi)/m
+
+S(chi) = log(sec(chi)) + sum(R[i]*cos(2*i*chi),i,0,maxpow)
+
+R[0] = + 1/3 * n
+       - 16/45 * n^2
+       + 131/945 * n^3
+       + 691/56700 * n^4
+R[1] = - 1/3 * n
+       + 22/45 * n^2
+       - 356/945 * n^3
+       + 1772/14175 * n^4;
+R[2] = - 2/15 * n^2
+       + 106/315 * n^3
+       - 1747/4725 * n^4;
+R[3] = - 31/315 * n^3
+       + 104/315 * n^4;
+R[4] = - 41/420 * n^4;
+
+i=0 term is just the integration const so can be dropped.  However
+including this terms gives S(0) = 0.
+
+Evaluate A between limits lam1 and lam2 gives
+
+A = c^2 * (lam2 - lam1) *
+ (S(chi2) - S(chi1)) / (atanh(sin(chi2)) - atanh(sin(chi1)))
+
+In limit chi2 -> chi, chi1 -> chi
+
+diff(atanh(sin(chi)),chi) = sec(chi)
+diff(log(sec(chi)),chi) = tan(chi)
+
+c^2 * (lam2 - lam1) * [
+  (1-R[1]) * sin(chi)
+- (R[1]+2*R[2]) * sin(3*chi)
+- (2*R[2]+3*R[3]) * sin(5*chi)
+- (3*R[3]+4*R[4]) * sin(7*chi)
+...
+]
+which is expansion of c^2 * (lam2 - lam1) * sin(xi) in terms of sin(chi)
+Note:
+ limit chi->0 = 0
+ limit chi->pi/2 = c^2 * (lam2-lam1)
+
+Express in terms of psi
+A = c^2 * (lam2 - lam1) *
+ (S(chi(psi2)) - S(chi(psi2))) / (psi2 - psi1)
+
+sum(R[i]*cos(2*i*chi),i,0,maxpow) = sum(sin(chi),cos(chi))
+S(chi(psi)) = log(cosh(psi)) + sum(tanh(psi),sech(psi))
+
+(S(chi(psi2)) - S(chi(psi2))) / (psi2 - psi1)
+  = Dlog(cosh(psi1),cosh(psi2)) * Dcosh(psi1,psi2)
+    + Dsum(chi1,chi2) * Dgd(psi1,psi2)
+
+*/
+
+reverta(expr,var1,var2,eps,pow):=block([tauacc:1,sigacc:0,dsig],
+  dsig:ratdisrep(taylor(expr-var1,eps,0,pow)),
+  dsig:subst([var1=var2],dsig),
+  for n:1 thru pow do (tauacc:trigreduce(ratdisrep(taylor(
+    -dsig*tauacc/n,eps,0,pow))),
+    sigacc:sigacc+expand(diff(tauacc,var2,n-1))),
+  var2+sigacc)$
+
+/* chi in terms of phi -- from auxlat.mac*/
+chi_phi(maxpow):=block([psiv,tanchi,chiv,qq,e,atanexp,x,eps],
+    /* Here qq = atanh(sin(phi)) = asinh(tan(phi)) */
+    psiv:qq-e*atanh(e*tanh(qq)),
+    psiv:subst([e=sqrt(4*n/(1+n)^2),qq=atanh(sin(phi))],
+      ratdisrep(taylor(psiv,e,0,2*maxpow)))
+    +asinh(sin(phi)/cos(phi))-atanh(sin(phi)),
+    tanchi:subst([abs(cos(phi))=cos(phi),sqrt(sin(phi)^2+cos(phi)^2)=1],
+      ratdisrep(taylor(sinh(psiv),n,0,maxpow)))+tan(phi)-sin(phi)/cos(phi),
+    atanexp:ratdisrep(taylor(atan(x+eps),eps,0,maxpow)),
+    chiv:subst([x=tan(phi),eps=tanchi-tan(phi)],atanexp),
+    chiv:subst([atan(tan(phi))=phi,
+      tan(phi)=sin(phi)/cos(phi)],
+      (chiv-phi)/cos(phi))*cos(phi)+phi,
+    chiv:ratdisrep(taylor(chiv,n,0,maxpow)),
+    expand(trigreduce(chiv)))$
+
+/* phi in terms of chi -- from auxlat.mac */
+phi_chi(maxpow):=reverta(chi_phi(maxpow),phi,chi,n,maxpow)$
+
+/* xi in terms of phi */
+xi_phi(maxpow):=block([sinxi,asinexp,x,eps,v],
+  sinxi:(sin(phi)/2*(1/(1-e^2*sin(phi)^2) + atanh(e*sin(phi))/(e*sin(phi))))/
+  (1/2*(1/(1-e^2) + atanh(e)/e)),
+  sinxi:ratdisrep(taylor(sinxi,e,0,2*maxpow)),
+  sinxi:subst([e=2*sqrt(n)/(1+n)],sinxi),
+  sinxi:expand(trigreduce(ratdisrep(taylor(sinxi,n,0,maxpow)))),
+  asinexp:sqrt(1-x^2)*
+  sum(ratsimp(diff(asin(x),x,i)/i!/sqrt(1-x^2))*eps^i,i,0,maxpow),
+  v:subst([x=sin(phi),eps=sinxi-sin(phi)],asinexp),
+  v:taylor(subst([sqrt(1-sin(phi)^2)=cos(phi),asin(sin(phi))=phi],
+      v),n,0,maxpow),
+  v:expand(ratdisrep(coeff(v,n,0))+sum(
+      ratsimp(trigreduce(sin(phi)*ratsimp(
+            subst([sin(phi)=sqrt(1-cos(phi)^2)],
+              ratsimp(trigexpand(ratdisrep(coeff(v,n,i)))/sin(phi))))))
+      *n^i,
+      i,1,maxpow)))$
+
+xi_chi(maxpow):=
+expand(trigreduce(taylor(subst([phi=phi_chi(maxpow)],xi_phi(maxpow)),
+      n,0,maxpow)))$
+
+computeR(maxpow):=block([xichi,xxn,inttanh,yy,m,yyi,yyj,s],
+  local(inttanh),
+  xichi:xi_chi(maxpow),
+  xxn:expand(subst([cos(chi)=sqrt(1-sin(chi)^2)],
+      trigexpand(taylor(sin(xichi),n,0,maxpow)))),
+  /* integrals of tanh(x)^l.  Use tanh(x)^2 + sech(x)^2 = 1. */
+  inttanh[0](x):=x, /* Not needed -- only odd l occurs in this problem */
+  inttanh[1](x):=log(cosh(x)),
+  inttanh[l](x):=inttanh[l-2](x) - tanh(x)^(l-1)/(l-1),
+  yy:subst([sin(chi)=tanh(m*lambda)],xxn),
+  /*
+  psi = atanh(sin(chi)) = m*lambda
+  sin(chi)=tanh(m*lambda)
+  sech(m*lambda) = sqrt(1-tanh(m*lambda))^2 = cos(chi)
+  cosh(m*lambda) = sec(chi)
+  m=(atanh(sin(chi2))-atanh(sin(chi1)))/(lam2-lam1)
+  */
+  yyi:block([v:yy/m,ii],
+    local(ii),
+    for j:2*maxpow+1 step -2 thru 1 do
+    v:subst([tanh(m*lambda)^j=ii[j](m*lambda)],v),
+    for j:2*maxpow+1 step -2 thru 1 do
+    v:subst([ii[j](m*lambda)=inttanh[j](m*lambda)],v),
+    expand(v)),
+  yyj:expand(m*trigreduce(
+      subst([tanh(m*lambda)=sin(chi),cosh(m*lambda)=sec(chi)],yyi)))/
+  ( (atanh(sin(chi2))-atanh(sin(chi1)))/(lam2-lam1) ),
+  s:( (atanh(sin(chi2))-atanh(sin(chi1)))/(lam2-lam1) )*yyj-log(sec(chi)),
+  for i:1 thru maxpow do R[i]:coeff(s,cos(2*i*chi)),
+  R[0]:s-expand(sum(R[i]*cos(2*i*chi),i,1,maxpow)),
+  if expand(s-sum(R[i]*cos(2*i*chi),i,0,maxpow)) # 0 then
+  error("Left over terms in R"),
+  if expand(trigreduce(expand(
+        diff(sum(R[i]*cos(2*i*chi),i,0,maxpow),chi)*cos(chi)+sin(chi))))-
+  expand(trigreduce(expand(xxn))) # 0 then
+  error("Derivative error in R"),
+  'done)$
+
+ataylor(expr,var,ord):=expand(ratdisrep(taylor(expr,var,0,ord)))$
+dispR(ord):=for i:1 thru ord do
+block([tt:ataylor(R[i],n,ord),ttt,linel:1200],
+  print(),
+  for j:max(i,1) step 1 thru ord do (ttt:coeff(tt,n,j), print(concat(
+        if j = max(i,1) then concat("R[",string(i),"] = ") else "       ",
+        if ttt<0 then "- " else "+ ",
+        string(abs(ttt)), " * ", string(n^j),
+        if j=ord then ";" else ""))))$
+
+codeR(minpow,maxpow):=block([tab2:"    ",tab3:"      "],
+  print("  // The coefficients R[l] in the Fourier expansion of rhumb area
+    real nx = n;
+    switch (maxpow_) {"),
+  for k:minpow thru maxpow do (
+    print(concat(tab2,"case ",string(k),":")),
+    for m:1 thru k do block([q:nx*horner(
+        ataylor(R[m],n,k)/n^m),
+      linel:1200],
+      if m>1 then print(concat(tab3,"nx *= n;")),
+      print(concat(tab3,"c[",string(m),"] = ",string(q),";"))),
+    print(concat(tab3,"break;"))),
+  print(concat(tab2,"default:")),
+  print(concat(tab3,"GEOGRAPHICLIB_STATIC_ASSERT(maxpow_ >= ",string(minpow),
+      " && maxpow_ <= ",string(maxpow),", \"Bad value of maxpow_\");")),
+  print("    }"),
+'done)$
+
+maxpow:6$
+computeR(maxpow)$
+dispR(maxpow)$
+codeR(4,maxpow)$
diff --git a/pom.xml b/pom.xml
index 1fd3287..5e45a6b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,18 +1,19 @@
 <project
     xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                        http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <parent>
     <groupId>com.sri.vt.majic</groupId>
     <artifactId>majic-parent</artifactId>
-    <version>0.1.11</version>
+    <version>0.2.1-SNAPSHOT</version>
   </parent>
 
   <groupId>com.sri.vt</groupId>
   <artifactId>geographiclib</artifactId>
-  <version>1.38-SNAPSHOT</version>
+  <version>1.39-SNAPSHOT</version>
   <packaging>majic-cmake</packaging>
   <name>GeographicLib</name>
 
@@ -41,14 +42,6 @@
     </profile>
   </profiles>
 
-  <repositories>
-    <repository>
-      <id>artifactory-vt</id>
-      <name>SRI VT Repository</name>
-      <url>https://artifactory-vt.sarnoff.internal/artifactory/repo</url>
-    </repository>
-  </repositories>
-
   <build>
     <plugins>
       <plugin>
@@ -62,7 +55,9 @@
                 <GEOGRAPHICLIB_LIB_TYPE>BOTH</GEOGRAPHICLIB_LIB_TYPE>
                 <MATLAB_COMPILER>OFF</MATLAB_COMPILER>
                 <GEOGRAPHICLIB_DOCUMENTATION>OFF</GEOGRAPHICLIB_DOCUMENTATION>
-                <BUILD_NETGEOGRAPHICLIB>${build.netgeographiclib}</BUILD_NETGEOGRAPHICLIB>
+                <BUILD_NETGEOGRAPHICLIB>
+                  ${build.netgeographiclib}
+                </BUILD_NETGEOGRAPHICLIB>
               </options>
             </configuration>
           </execution>
diff --git a/python/geographiclib/geodesic.py b/python/geographiclib/geodesic.py
index fc46ca7..39dc02c 100644
--- a/python/geographiclib/geodesic.py
+++ b/python/geographiclib/geodesic.py
@@ -13,7 +13,7 @@
 #    http://dx.doi.org/10.1007/s00190-012-0578-z
 #    Addenda: http://geographiclib.sf.net/geod-addenda.html
 #
-# Copyright (c) Charles Karney (2011-2013) <charles at karney.com> and licensed
+# Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
 # under the MIT/X11 License.  For more information, see
 # http://geographiclib.sourceforge.net/
 ######################################################################
@@ -24,8 +24,7 @@ from geographiclib.constants import Constants
 from geographiclib.geodesiccapability import GeodesicCapability
 
 class Geodesic(object):
-  """
-  Solve geodesic problems.  The following illustrates its use
+  """Solve geodesic problems.  The following illustrates its use
 
     import sys
     sys.path.append("/usr/local/lib/python/site-packages")
@@ -56,9 +55,10 @@ class Geodesic(object):
     help(line.Position)
     help(Geodesic.Area)
 
-  All angles (latitudes, longitudes, azimuths, spherical arc lengths) are
-  measured in degrees.  All lengths (distance, reduced length) are measured in
-  meters.  All areas are measures in square meters.
+  All angles (latitudes, longitudes, azimuths, spherical arc lengths)
+  are measured in degrees.  All lengths (distance, reduced length) are
+  measured in meters.  All areas are measures in square meters.
+
   """
 
   GEOGRAPHICLIB_GEODESIC_ORDER = 6
@@ -85,22 +85,25 @@ class Geodesic(object):
 
   CAP_NONE = GeodesicCapability.CAP_NONE
   CAP_C1   = GeodesicCapability.CAP_C1
-  CAP_C1p  = 1 << 1
-  CAP_C2   = 1 << 2
-  CAP_C3   = 1 << 3
-  CAP_C4   = 1 << 4
-  CAP_ALL  = 0x1F
-  OUT_ALL  = 0x7F80
-  EMPTY         = 0
-  LATITUDE      = 1 << 7  | CAP_NONE
-  LONGITUDE     = 1 << 8  | CAP_C3
-  AZIMUTH       = 1 << 9  | CAP_NONE
-  DISTANCE      = 1 << 10 | CAP_C1
-  DISTANCE_IN   = 1 << 11 | CAP_C1 | CAP_C1p
-  REDUCEDLENGTH = 1 << 12 | CAP_C1 | CAP_C2
-  GEODESICSCALE = 1 << 13 | CAP_C1 | CAP_C2
-  AREA          = 1 << 14 | CAP_C4
-  ALL           = OUT_ALL | CAP_ALL
+  CAP_C1p  = GeodesicCapability.CAP_C1p
+  CAP_C2   = GeodesicCapability.CAP_C2
+  CAP_C3   = GeodesicCapability.CAP_C3
+  CAP_C4   = GeodesicCapability.CAP_C4
+  CAP_ALL  = GeodesicCapability.CAP_ALL
+  CAP_MASK = GeodesicCapability.CAP_MASK
+  OUT_ALL  = GeodesicCapability.OUT_ALL
+  OUT_MASK = GeodesicCapability.OUT_MASK
+  EMPTY         = GeodesicCapability.EMPTY
+  LATITUDE      = GeodesicCapability.LATITUDE
+  LONGITUDE     = GeodesicCapability.LONGITUDE
+  AZIMUTH       = GeodesicCapability.AZIMUTH
+  DISTANCE      = GeodesicCapability.DISTANCE
+  DISTANCE_IN   = GeodesicCapability.DISTANCE_IN
+  REDUCEDLENGTH = GeodesicCapability.REDUCEDLENGTH
+  GEODESICSCALE = GeodesicCapability.GEODESICSCALE
+  AREA          = GeodesicCapability.AREA
+  LONG_NOWRAP   = GeodesicCapability.LONG_NOWRAP
+  ALL           = GeodesicCapability.ALL
 
   def SinCosSeries(sinp, sinx, cosx, c, n):
     """Private: Evaluate a trig series using Clenshaw summation."""
@@ -260,9 +263,9 @@ class Geodesic(object):
   C2f = staticmethod(C2f)
 
   def __init__(self, a, f):
-    """
-    Construct a Geodesic object for ellipsoid with major radius a and
+    """Construct a Geodesic object for ellipsoid with major radius a and
     flattening f.
+
     """
 
     self._a = float(a)
@@ -651,7 +654,7 @@ class Geodesic(object):
     """Private: General version of the inverse problem"""
     a12 = s12 = azi1 = azi2 = m12 = M12 = M21 = S12 = Math.nan # return vals
 
-    outmask &= Geodesic.OUT_ALL
+    outmask &= Geodesic.OUT_MASK
     # 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.
@@ -972,10 +975,9 @@ class Geodesic(object):
   CheckDistance = staticmethod(CheckDistance)
 
   def Inverse(self, lat1, lon1, lat2, lon2, outmask = DISTANCE | AZIMUTH):
-    """
-    Solve the inverse geodesic problem.  Compute geodesic between
-    (lat1, lon1) and (lat2, lon2).  Return a dictionary with (some) of
-    the following entries:
+    """Solve the inverse geodesic problem.  Compute geodesic between (lat1,
+    lon1) and (lat2, lon2).  Return a dictionary with (some) of the
+    following entries:
 
       lat1 latitude of point 1
       lon1 longitude of point 1
@@ -994,14 +996,13 @@ class Geodesic(object):
     omitted, then only the basic geodesic fields are computed.  The mask
     is an or'ed combination of the following values
 
-      Geodesic.LATITUDE
-      Geodesic.LONGITUDE
       Geodesic.AZIMUTH
       Geodesic.DISTANCE
       Geodesic.REDUCEDLENGTH
       Geodesic.GEODESICSCALE
       Geodesic.AREA
       Geodesic.ALL
+
     """
 
     lon1 = Geodesic.CheckPosition(lat1, lon1)
@@ -1010,7 +1011,7 @@ class Geodesic(object):
     result = {'lat1': lat1, 'lon1': lon1, 'lat2': lat2, 'lon2': lon2}
     a12, s12, azi1, azi2, m12, M12, M21, S12 = self.GenInverse(
       lat1, lon1, lat2, lon2, outmask)
-    outmask &= Geodesic.OUT_ALL
+    outmask &= Geodesic.OUT_MASK
     result['a12'] = a12
     if outmask & Geodesic.DISTANCE: result['s12'] = s12
     if outmask & Geodesic.AZIMUTH:
@@ -1033,8 +1034,7 @@ class Geodesic(object):
 
   def Direct(self, lat1, lon1, azi1, s12,
              outmask = LATITUDE | LONGITUDE | AZIMUTH):
-    """
-    Solve the direct geodesic problem.  Compute geodesic starting at
+    """Solve the direct geodesic problem.  Compute geodesic starting at
     (lat1, lon1) with azimuth azi1 and length s12.  Return a dictionary
     with (some) of the following entries:
 
@@ -1052,8 +1052,10 @@ class Geodesic(object):
       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
+    omitted, then only the basic geodesic fields are computed.  The
+    LONG_NOWRAP bit prevents the longitudes being reduced to the range
+    [-180,180).  The mask is an or'ed combination of the following
+    values
 
       Geodesic.LATITUDE
       Geodesic.LONGITUDE
@@ -1062,16 +1064,21 @@ class Geodesic(object):
       Geodesic.GEODESICSCALE
       Geodesic.AREA
       Geodesic.ALL
+      Geodesic.LONG_NOWRAP
+
     """
 
-    lon1 = Geodesic.CheckPosition(lat1, lon1)
+    if outmask & Geodesic.LONG_NOWRAP:
+      Geodesic.CheckPosition(lat1, lon1)
+    else:
+      lon1 = Geodesic.CheckPosition(lat1, lon1)
     azi1 = Geodesic.CheckAzimuth(azi1)
     Geodesic.CheckDistance(s12)
 
     result = {'lat1': lat1, 'lon1': lon1, 'azi1': azi1, 's12': s12}
     a12, lat2, lon2, azi2, s12, m12, M12, M21, S12 = self.GenDirect(
       lat1, lon1, azi1, False, s12, outmask)
-    outmask &= Geodesic.OUT_ALL
+    outmask &= Geodesic.OUT_MASK
     result['a12'] = a12
     if outmask & Geodesic.LATITUDE: result['lat2'] = lat2
     if outmask & Geodesic.LONGITUDE: result['lon2'] = lon2
@@ -1084,10 +1091,9 @@ class Geodesic(object):
 
   def ArcDirect(self, lat1, lon1, azi1, a12,
                 outmask = LATITUDE | LONGITUDE | AZIMUTH | DISTANCE):
-    """
-    Solve the direct geodesic problem.  Compute geodesic starting at
-    (lat1, lon1) with azimuth azi1 and spherical arc length a12.
-    Return a dictionary with (some) of the following entries:
+    """Solve the direct geodesic problem.  Compute geodesic starting at
+    (lat1, lon1) with azimuth azi1 and spherical arc length a12.  Return
+    a dictionary with (some) of the following entries:
 
       lat1 latitude of point 1
       lon1 longitude of point 1
@@ -1103,8 +1109,10 @@ class Geodesic(object):
       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
+    omitted, then only the basic geodesic fields are computed.  The
+    LONG_NOWRAP bit prevents the longitudes being reduced to the range
+    [-180,180).  The mask is an or'ed combination of the following
+    values
 
       Geodesic.LATITUDE
       Geodesic.LONGITUDE
@@ -1114,16 +1122,21 @@ class Geodesic(object):
       Geodesic.GEODESICSCALE
       Geodesic.AREA
       Geodesic.ALL
+      Geodesic.LONG_NOWRAP
+
     """
 
-    lon1 = Geodesic.CheckPosition(lat1, lon1)
+    if outmask & Geodesic.LONG_NOWRAP:
+      Geodesic.CheckPosition(lat1, lon1)
+    else:
+      lon1 = Geodesic.CheckPosition(lat1, lon1)
     azi1 = Geodesic.CheckAzimuth(azi1)
     Geodesic.CheckDistance(a12)
 
     result = {'lat1': lat1, 'lon1': lon1, 'azi1': azi1, 'a12': a12}
     a12, lat2, lon2, azi2, s12, m12, M12, M21, S12 = self.GenDirect(
       lat1, lon1, azi1, True, a12, outmask)
-    outmask &= Geodesic.OUT_ALL
+    outmask &= Geodesic.OUT_MASK
     if outmask & Geodesic.DISTANCE: result['s12'] = s12
     if outmask & Geodesic.LATITUDE: result['lat2'] = lat2
     if outmask & Geodesic.LONGITUDE: result['lon2'] = lon2
@@ -1135,8 +1148,7 @@ class Geodesic(object):
     return result
 
   def Line(self, lat1, lon1, azi1, caps = ALL):
-    """
-    Return a GeodesicLine object to compute points along a geodesic
+    """Return a GeodesicLine object to compute points along a geodesic
     starting at lat1, lon1, with azimuth azi1.  caps is an or'ed
     combination of bit the following values indicating the capabilities
     of the return object
@@ -1150,6 +1162,7 @@ class Geodesic(object):
       Geodesic.AREA
       Geodesic.DISTANCE_IN
       Geodesic.ALL
+
     """
 
     from geographiclib.geodesicline import GeodesicLine
@@ -1161,8 +1174,7 @@ class Geodesic(object):
       caps | Geodesic.DISTANCE_IN)
 
   def Area(self, points, polyline = False):
-    """
-    Compute the area of a geodesic polygon given by points, an array of
+    """Compute the area of a geodesic polygon given by points, an array of
     dictionaries with entries lat and lon.  Return a dictionary with
     entries
 
@@ -1173,6 +1185,7 @@ class Geodesic(object):
     There is no need to "close" the polygon.  If polyline is set to
     True, then the points define a polyline instead of a polygon, the
     length is returned as the perimeter, and the area is not returned.
+
     """
 
     from geographiclib.polygonarea import PolygonArea
diff --git a/python/geographiclib/geodesiccapability.py b/python/geographiclib/geodesiccapability.py
index 1c7c0e7..5dda33d 100644
--- a/python/geographiclib/geodesiccapability.py
+++ b/python/geographiclib/geodesiccapability.py
@@ -7,8 +7,8 @@
 #
 #    http://geographiclib.sourceforge.net/html/annotated.html
 #
-# Copyright (c) Charles Karney (2011) <charles at karney.com> and licensed under
-# the MIT/X11 License.  For more information, see
+# Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
+# under the MIT/X11 License.  For more information, see
 # http://geographiclib.sourceforge.net/
 ######################################################################
 
@@ -24,7 +24,9 @@ class GeodesicCapability(object):
   CAP_C3   = 1 << 3
   CAP_C4   = 1 << 4
   CAP_ALL  = 0x1F
+  CAP_MASK = CAP_ALL
   OUT_ALL  = 0x7F80
+  OUT_MASK = 0xFF80             # Includes LONG_NOWRAP
   EMPTY         = 0
   LATITUDE      = 1 << 7  | CAP_NONE
   LONGITUDE     = 1 << 8  | CAP_C3
@@ -34,5 +36,5 @@ class GeodesicCapability(object):
   REDUCEDLENGTH = 1 << 12 | CAP_C1 | CAP_C2
   GEODESICSCALE = 1 << 13 | CAP_C1 | CAP_C2
   AREA          = 1 << 14 | CAP_C4
-  ALL           = OUT_ALL | CAP_ALL
-
+  LONG_NOWRAP   = 1 << 15
+  ALL           = OUT_ALL | CAP_ALL # Does not include LONG_NOWRAP
diff --git a/python/geographiclib/geodesicline.py b/python/geographiclib/geodesicline.py
index 6d2589b..2872e28 100644
--- a/python/geographiclib/geodesicline.py
+++ b/python/geographiclib/geodesicline.py
@@ -13,7 +13,7 @@
 #    http://dx.doi.org/10.1007/s00190-012-0578-z
 #    Addenda: http://geographiclib.sf.net/geod-addenda.html
 #
-# Copyright (c) Charles Karney (2011-2013) <charles at karney.com> and licensed
+# Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
 # under the MIT/X11 License.  For more information, see
 # http://geographiclib.sourceforge.net/
 ######################################################################
@@ -36,7 +36,6 @@ class GeodesicLine(object):
 
     # Guard against underflow in salp0
     azi1 = Geodesic.AngRound(Math.AngNormalize(azi1))
-    lon1 = Math.AngNormalize(lon1)
     self._lat1 = lat1
     self._lon1 = lon1
     self._azi1 = azi1
@@ -123,8 +122,9 @@ class GeodesicLine(object):
     """Private: General solution of position along geodesic"""
     from geographiclib.geodesic import Geodesic
     a12 = lat2 = lon2 = azi2 = s12 = m12 = M12 = M21 = S12 = Math.nan
-    outmask &= self._caps & Geodesic.OUT_ALL
-    if not (arcmode or (self._caps & Geodesic.DISTANCE_IN & Geodesic.OUT_ALL)):
+    outmask &= self._caps & Geodesic.OUT_MASK
+    if not (arcmode or
+            (self._caps & Geodesic.DISTANCE_IN & Geodesic.OUT_MASK)):
       # Uninitialized or impossible distance calculation requested
       return a12, lat2, lon2, azi2, s12, m12, M12, M21, S12
 
@@ -199,18 +199,24 @@ class GeodesicLine(object):
     if cbet2 == 0:
       # I.e., salp0 = 0, csig2 = 0.  Break the degeneracy in this case
       cbet2 = csig2 = Geodesic.tiny_
-    # tan(omg2) = sin(alp0) * tan(sig2)
-    somg2 = self._salp0 * ssig2; comg2 = csig2 # No need to normalize
     # tan(alp0) = cos(sig2)*tan(alp2)
     salp2 = self._salp0; calp2 = self._calp0 * csig2 # No need to normalize
-    # omg12 = omg2 - omg1
-    omg12 = math.atan2(somg2 * self._comg1 - comg2 * self._somg1,
-                  comg2 * self._comg1 + somg2 * self._somg1)
 
     if outmask & Geodesic.DISTANCE:
       s12 = self._b * ((1 + self._A1m1) * sig12 + AB1) if arcmode else s12_a12
 
     if outmask & Geodesic.LONGITUDE:
+      # tan(omg2) = sin(alp0) * tan(sig2)
+      somg2 = self._salp0 * ssig2; comg2 = csig2 # No need to normalize
+      # omg12 = omg2 - omg1
+      omg12 = (sig12
+               - (math.atan2(ssig2, csig2) -
+                  math.atan2(self._ssig1, self._csig1))
+               + (math.atan2(somg2, comg2) -
+                  math.atan2(self._somg1, self._comg1))
+               if outmask & Geodesic.LONG_NOWRAP
+               else math.atan2(somg2 * self._comg1 - comg2 * self._somg1,
+                               comg2 * self._comg1 + somg2 * self._somg1))
       lam12 = omg12 + self._A3c * (
         sig12 + (Geodesic.SinCosSeries(True, ssig2, csig2,
                                        self._C3a, Geodesic.nC3_-1)
@@ -218,8 +224,9 @@ class GeodesicLine(object):
       lon12 = lam12 / Math.degree
       # Use Math.AngNormalize2 because longitude might have wrapped
       # multiple times.
-      lon12 = Math.AngNormalize2(lon12)
-      lon2 = Math.AngNormalize(self._lon1 + lon12)
+      lon2 = (self._lon1 + lon12 if outmask & Geodesic.LONG_NOWRAP else
+              Math.AngNormalize(Math.AngNormalize(self._lon1) +
+                                Math.AngNormalize2(lon12)))
 
     if outmask & Geodesic.LATITUDE:
       lat2 = math.atan2(sbet2, self._f1 * cbet2) / Math.degree
@@ -245,7 +252,8 @@ class GeodesicLine(object):
         M21 = csig12 - (t * self._ssig1 - self._csig1 * J12) * ssig2 / dn2
 
     if outmask & Geodesic.AREA:
-      B42 = Geodesic.SinCosSeries(False, ssig2, csig2, self._C4a, Geodesic.nC4_)
+      B42 = Geodesic.SinCosSeries(False,
+                                  ssig2, csig2, self._C4a, Geodesic.nC4_)
       # real salp12, calp12
       if self._calp0 == 0 or self._salp0 == 0:
         # alp12 = alp2 - alp1, used in atan2 so no need to normalized
@@ -271,7 +279,8 @@ class GeodesicLine(object):
           else ssig12 * (self._csig1 * ssig12 / (1 + csig12) + self._ssig1))
         calp12 = (Math.sq(self._salp0) +
                   Math.sq(self._calp0) * self._csig1 * csig2)
-      S12 = self._c2 * math.atan2(salp12, calp12) + self._A4 * (B42 - self._B41)
+      S12 = (self._c2 * math.atan2(salp12, calp12) +
+             self._A4 * (B42 - self._B41))
 
     a12 = s12_a12 if arcmode else sig12 / Math.degree
     return a12, lat2, lon2, azi2, s12, m12, M12, M21, S12
@@ -279,9 +288,8 @@ class GeodesicLine(object):
   def Position(self, s12,
                outmask = GeodesicCapability.LATITUDE |
                GeodesicCapability.LONGITUDE | GeodesicCapability.AZIMUTH):
-    """
-    Return the point a distance s12 along the geodesic line.  Return
-    a dictionary with (some) of the following entries:
+    """Return the point a distance s12 along the geodesic line.  Return a
+    dictionary with (some) of the following entries:
 
       lat1 latitude of point 1
       lon1 longitude of point 1
@@ -297,8 +305,10 @@ class GeodesicLine(object):
       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
+    omitted, then only the basic geodesic fields are computed.  The
+    LONG_NOWRAP bit prevents the longitudes being reduced to the range
+    [-180,180).  The mask is an or'ed combination of the following
+    values
 
       Geodesic.LATITUDE
       Geodesic.LONGITUDE
@@ -307,15 +317,19 @@ class GeodesicLine(object):
       Geodesic.GEODESICSCALE
       Geodesic.AREA
       Geodesic.ALL
+      Geodesic.LONG_NOWRAP
+
     """
 
     from geographiclib.geodesic import Geodesic
     Geodesic.CheckDistance(s12)
-    result = {'lat1': self._lat1, 'lon1': self._lon1, 'azi1': self._azi1,
-              's12': s12}
+    result = {'lat1': self._lat1,
+              'lon1': self._lon1 if outmask & Geodesic.LONG_NOWRAP else
+              Math.AngNormalize(self._lon1),
+              'azi1': self._azi1, 's12': s12}
     a12, lat2, lon2, azi2, s12, m12, M12, M21, S12 = self.GenPosition(
       False, s12, outmask)
-    outmask &= Geodesic.OUT_ALL
+    outmask &= Geodesic.OUT_MASK
     result['a12'] = a12
     if outmask & Geodesic.LATITUDE: result['lat2'] = lat2
     if outmask & Geodesic.LONGITUDE: result['lon2'] = lon2
@@ -330,8 +344,7 @@ class GeodesicLine(object):
                   outmask = GeodesicCapability.LATITUDE |
                   GeodesicCapability.LONGITUDE | GeodesicCapability.AZIMUTH |
                   GeodesicCapability.DISTANCE):
-    """
-    Return the point a spherical arc length a12 along the geodesic line.
+    """Return the point a spherical arc length a12 along the geodesic line.
     Return a dictionary with (some) of the following entries:
 
       lat1 latitude of point 1
@@ -348,8 +361,10 @@ class GeodesicLine(object):
       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
+    omitted, then only the basic geodesic fields are computed.  The
+    LONG_NOWRAP bit prevents the longitudes being reduced to the range
+    [-180,180).  The mask is an or'ed combination of the following
+    values
 
       Geodesic.LATITUDE
       Geodesic.LONGITUDE
@@ -359,15 +374,19 @@ class GeodesicLine(object):
       Geodesic.GEODESICSCALE
       Geodesic.AREA
       Geodesic.ALL
+      Geodesic.LONG_NOWRAP
+
     """
 
     from geographiclib.geodesic import Geodesic
     Geodesic.CheckDistance(a12)
-    result = {'lat1': self._lat1, 'lon1': self._lon1, 'azi1': self._azi1,
-              'a12': a12}
+    result = {'lat1': self._lat1,
+              'lon1': self._lon1 if outmask & Geodesic.LONG_NOWRAP else
+              Math.AngNormalize(self._lon1),
+              'azi1': self._azi1, 'a12': a12}
     a12, lat2, lon2, azi2, s12, m12, M12, M21, S12 = self.GenPosition(
       True, a12, outmask)
-    outmask &= Geodesic.OUT_ALL
+    outmask &= Geodesic.OUT_MASK
     if outmask & Geodesic.DISTANCE: result['s12'] = s12
     if outmask & Geodesic.LATITUDE: result['lat2'] = lat2
     if outmask & Geodesic.LONGITUDE: result['lon2'] = lon2
@@ -377,4 +396,3 @@ class GeodesicLine(object):
       result['M12'] = M12; result['M21'] = M21
     if outmask & Geodesic.AREA: result['S12'] = S12
     return result
-
diff --git a/python/geographiclib/polygonarea.py b/python/geographiclib/polygonarea.py
index d3a2436..070a918 100644
--- a/python/geographiclib/polygonarea.py
+++ b/python/geographiclib/polygonarea.py
@@ -13,7 +13,7 @@
 #    http://dx.doi.org/10.1007/s00190-012-0578-z
 #    Addenda: http://geographiclib.sf.net/geod-addenda.html
 #
-# Copyright (c) Charles Karney (2011-2013) <charles at karney.com> and licensed
+# Copyright (c) Charles Karney (2011-2014) <charles at karney.com> and licensed
 # under the MIT/X11 License.  For more information, see
 # http://geographiclib.sourceforge.net/
 ######################################################################
@@ -26,7 +26,7 @@ class PolygonArea(object):
   """Area of a geodesic polygon"""
 
   def transit(lon1, lon2):
-    """Count crossings of prime meridian."""
+    """Count crossings of prime meridian for AddPoint."""
     # Return 1 or -1 if crossing prime meridian in east or west direction.
     # Otherwise return zero.
     # Compute lon12 the same way as Geodesic::Inverse.
@@ -38,6 +38,17 @@ class PolygonArea(object):
     return cross
   transit = staticmethod(transit)
 
+  def transitdirect(lon1, lon2):
+    """Count crossings of prime meridian for AddEdge."""
+    # We want to compute exactly
+    #   int(floor(lon2 / 360)) - int(floor(lon1 / 360))
+    # Since we only need the parity of the result we can use std::remquo but
+    # this is buggy with g++ 4.8.3 and requires C++11.  So instead we do
+    lon1 = math.fmod(lon1, 720.0); lon2 = math.fmod(lon2, 720.0)
+    return ( (0 if ((lon2 >= 0 and lon2 < 360) or lon2 < -360) else 1) -
+             (0 if ((lon1 >= 0 and lon1 < 360) or lon1 < -360) else 1) )
+  transitdirect = staticmethod(transitdirect)
+
   def __init__(self, earth, polyline = False):
     from geographiclib.geodesic import Geodesic
     self._earth = earth
@@ -45,7 +56,8 @@ class PolygonArea(object):
     self._polyline = polyline
     self._mask = (Geodesic.LATITUDE | Geodesic.LONGITUDE |
                   Geodesic.DISTANCE |
-                  (Geodesic.EMPTY if self._polyline else Geodesic.AREA))
+                  (Geodesic.EMPTY if self._polyline else
+                   Geodesic.AREA | Geodesic.LONG_NOWRAP))
     if not self._polyline: self._areasum = Accumulator()
     self._perimetersum = Accumulator()
     self.Clear()
@@ -82,7 +94,7 @@ class PolygonArea(object):
       self._perimetersum.Add(s)
       if not self._polyline:
         self._areasum.Add(S12)
-        self._crossings += PolygonArea.transit(self._lon1, lon)
+        self._crossings += PolygonArea.transitdirect(self._lon1, lon)
       self._lat1 = lat
       self._lon1 = lon
       self._num += 1
@@ -191,7 +203,7 @@ class PolygonArea(object):
     _, lat, lon, _, _, _, _, _, S12 = self._earth.GenDirect(
       self._lat1, self._lon1, azi, False, s, self._mask)
     tempsum += S12
-    crossings += PolygonArea.transit(self._lon1, lon)
+    crossings += PolygonArea.transitdirect(self._lon1, lon)
     _, s12, _, _, _, _, _, S12 = self._earth.GenInverse(
       lat, lon, self._lat0, self._lon0, self._mask)
     perimeter += s12
diff --git a/python/setup.py b/python/setup.py
index c03e307..253e92e 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -15,7 +15,7 @@
 from distutils.core import setup
 
 setup(name="geographiclib",
-      version="1.34",
+      version="1.39",
       description=
         "A translation of the GeographicLib::Geodesic class to Python",
       author="Charles Karney",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 43afb2b..26fa357 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -54,9 +54,27 @@ else ()
   endif ()
 endif ()
 
+if (NOT CMAKE_VERSION VERSION_LESS 2.8.11)
+  if (GEOGRAPHICLIB_SHARED_LIB)
+    target_include_directories (${PROJECT_SHARED_LIBRARIES} INTERFACE
+      $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
+      $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+      $<INSTALL_INTERFACE:include>)
+  endif ()
+  if (GEOGRAPHICLIB_STATIC_LIB)
+    target_include_directories (${PROJECT_STATIC_LIBRARIES} INTERFACE
+      $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
+      $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
+      $<INSTALL_INTERFACE:include>)
+  endif ()
+endif ()
+
 # Specify where the library is installed, adding it to the export targets
 install (TARGETS ${PROJECT_SHARED_LIBRARIES} ${PROJECT_STATIC_LIBRARIES}
   EXPORT targets
+  # A potentially useful option.  However it's only supported in recent
+  # versions of cmake (2.8.12 and later?).  So comment out for now.
+  # INCLUDES DESTINATION include
   RUNTIME DESTINATION bin
   LIBRARY DESTINATION lib${LIB_SUFFIX}
   ARCHIVE DESTINATION lib${LIB_SUFFIX})
diff --git a/src/Geodesic.cpp b/src/Geodesic.cpp
index 732da0b..a428ae4 100644
--- a/src/Geodesic.cpp
+++ b/src/Geodesic.cpp
@@ -139,7 +139,7 @@ namespace GeographicLib {
                                   real& s12, real& azi1, real& azi2,
                                   real& m12, real& M12, real& M21, real& S12)
     const {
-    outmask &= OUT_ALL;
+    outmask &= OUT_MASK;
     // 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.
@@ -411,7 +411,7 @@ namespace GeographicLib {
 
       if (!meridian &&
           omg12 < real(0.75) * Math::pi() && // Long difference too big
-          sbet2 - sbet1 < real(1.75)) {            // Lat difference too big
+          sbet2 - sbet1 < real(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))
diff --git a/src/GeodesicLine.cpp b/src/GeodesicLine.cpp
index 6282d3e..b9be956 100644
--- a/src/GeodesicLine.cpp
+++ b/src/GeodesicLine.cpp
@@ -2,7 +2,7 @@
  * \file GeodesicLine.cpp
  * \brief Implementation for GeographicLib::GeodesicLine class
  *
- * Copyright (c) Charles Karney (2009-2012) <charles at karney.com> and licensed
+ * Copyright (c) Charles Karney (2009-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
@@ -36,6 +36,10 @@ namespace GeographicLib {
                              real lat1, real lon1, real azi1,
                              unsigned caps)
     : tiny_(g.tiny_)
+    , _lat1(lat1)
+    , _lon1(lon1)
+    // Guard against underflow in salp0
+    , _azi1(Geodesic::AngRound(Math::AngNormalize(azi1)))
     , _a(g._a)
     , _f(g._f)
     , _b(g._b)
@@ -44,18 +48,11 @@ namespace GeographicLib {
       // Always allow latitude and azimuth
     , _caps(caps | LATITUDE | AZIMUTH)
   {
-    // Guard against underflow in salp0
-    azi1 = Geodesic::AngRound(Math::AngNormalize(azi1));
-    lon1 = Math::AngNormalize(lon1);
-    _lat1 = lat1;
-    _lon1 = lon1;
-    _azi1 = azi1;
-    // alp1 is in [0, pi]
-    real alp1 = azi1 * Math::degree();
+    real alp1 = _azi1 * Math::degree();
     // Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
     // problems directly than to skirt them.
-    _salp1 =     azi1  == -180 ? 0 : sin(alp1);
-    _calp1 = abs(azi1) ==   90 ? 0 : cos(alp1);
+    _salp1 =     _azi1  == -180 ? 0 : sin(alp1);
+    _calp1 = abs(_azi1) ==   90 ? 0 : cos(alp1);
     real cbet1, sbet1, phi;
     phi = lat1 * Math::degree();
     // Ensure cbet1 = +epsilon at poles
@@ -128,8 +125,8 @@ namespace GeographicLib {
                                        real& M12, real& M21,
                                        real& S12)
   const {
-    outmask &= _caps & OUT_ALL;
-    if (!( Init() && (arcmode || (_caps & DISTANCE_IN & OUT_ALL)) ))
+    outmask &= _caps & OUT_MASK;
+    if (!( Init() && (arcmode || (_caps & DISTANCE_IN & OUT_MASK)) ))
       // Uninitialized or impossible distance calculation requested
       return Math::NaN();
 
@@ -188,8 +185,7 @@ namespace GeographicLib {
       }
     }
 
-    real omg12, lam12, lon12;
-    real ssig2, csig2, sbet2, cbet2, somg2, comg2, salp2, calp2;
+    real ssig2, csig2, sbet2, cbet2, salp2, calp2;
     // sig2 = sig1 + sig12
     ssig2 = _ssig1 * csig12 + _csig1 * ssig12;
     csig2 = _csig1 * csig12 - _ssig1 * ssig12;
@@ -206,26 +202,30 @@ namespace GeographicLib {
     if (cbet2 == 0)
       // I.e., salp0 = 0, csig2 = 0.  Break the degeneracy in this case
       cbet2 = csig2 = tiny_;
-    // tan(omg2) = sin(alp0) * tan(sig2)
-    somg2 = _salp0 * ssig2; comg2 = csig2;  // No need to normalize
     // tan(alp0) = cos(sig2)*tan(alp2)
     salp2 = _salp0; calp2 = _calp0 * csig2; // No need to normalize
-    // omg12 = omg2 - omg1
-    omg12 = atan2(somg2 * _comg1 - comg2 * _somg1,
-                  comg2 * _comg1 + somg2 * _somg1);
 
     if (outmask & DISTANCE)
       s12 = arcmode ? _b * ((1 + _A1m1) * sig12 + AB1) : s12_a12;
 
     if (outmask & LONGITUDE) {
-      lam12 = omg12 + _A3c *
+      // tan(omg2) = sin(alp0) * tan(sig2)
+      real somg2 = _salp0 * ssig2, comg2 = csig2;  // No need to normalize
+      // omg12 = omg2 - omg1
+      real omg12 = outmask & LONG_NOWRAP ? sig12
+        - (atan2(ssig2, csig2) - atan2(_ssig1, _csig1))
+        + (atan2(somg2, comg2) - atan2(_somg1, _comg1))
+        : atan2(somg2 * _comg1 - comg2 * _somg1,
+                comg2 * _comg1 + somg2 * _somg1);
+      real lam12 = omg12 + _A3c *
         ( sig12 + (Geodesic::SinCosSeries(true, ssig2, csig2, _C3a, nC3_-1)
                    - _B31));
-      lon12 = lam12 / Math::degree();
-      // Use Math::AngNormalize2 because longitude might have wrapped multiple
-      // times.
-      lon12 = Math::AngNormalize2(lon12);
-      lon2 = Math::AngNormalize(_lon1 + lon12);
+      real lon12 = lam12 / Math::degree();
+      // Use Math::AngNormalize2 because longitude might have wrapped
+      // multiple times.
+      lon2 = outmask & LONG_NOWRAP ? _lon1 + lon12 :
+        Math::AngNormalize(Math::AngNormalize(_lon1) +
+                           Math::AngNormalize2(lon12));
     }
 
     if (outmask & LATITUDE)
@@ -257,7 +257,7 @@ namespace GeographicLib {
         B42 = Geodesic::SinCosSeries(false, ssig2, csig2, _C4a, nC4_);
       real salp12, calp12;
       if (_calp0 == 0 || _salp0 == 0) {
-        // alp12 = alp2 - alp1, used in atan2 so no need to normalized
+        // alp12 = alp2 - alp1, used in atan2 so no need to normalize
         salp12 = salp2 * _calp1 - calp2 * _salp1;
         calp12 = calp2 * _calp1 + salp2 * _salp1;
         // The right thing appears to happen if alp1 = +/-180 and alp2 = 0, viz
diff --git a/src/GeodesicLineExact.cpp b/src/GeodesicLineExact.cpp
index 09d783e..02d6c9c 100644
--- a/src/GeodesicLineExact.cpp
+++ b/src/GeodesicLineExact.cpp
@@ -2,8 +2,8 @@
  * \file GeodesicLineExact.cpp
  * \brief Implementation for GeographicLib::GeodesicLineExact class
  *
- * Copyright (c) Charles Karney (2012) <charles at karney.com> and licensed under
- * the MIT/X11 License.  For more information, see
+ * Copyright (c) Charles Karney (2012-2014) <charles at karney.com> and licensed
+ * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
  * This is a reformulation of the geodesic problem.  The notation is as
@@ -36,6 +36,10 @@ namespace GeographicLib {
                                        real lat1, real lon1, real azi1,
                                        unsigned caps)
     : tiny_(g.tiny_)
+    , _lat1(lat1)
+    , _lon1(lon1)
+    // Guard against underflow in salp0
+    , _azi1(GeodesicExact::AngRound(Math::AngNormalize(azi1)))
     , _a(g._a)
     , _f(g._f)
     , _b(g._b)
@@ -46,17 +50,11 @@ namespace GeographicLib {
       // Always allow latitude and azimuth
     , _caps(caps | LATITUDE | AZIMUTH)
   {
-    azi1 = GeodesicExact::AngRound(Math::AngNormalize(azi1));
-    lon1 = Math::AngNormalize(lon1);
-    _lat1 = lat1;
-    _lon1 = lon1;
-    _azi1 = azi1;
-    // alp1 is in [0, pi]
-    real alp1 = azi1 * Math::degree();
+    real alp1 = _azi1 * Math::degree();
     // Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
     // problems directly than to skirt them.
-    _salp1 =     azi1  == -180 ? 0 : sin(alp1);
-    _calp1 = abs(azi1) ==   90 ? 0 : cos(alp1);
+    _salp1 =     _azi1  == -180 ? 0 : sin(alp1);
+    _calp1 = abs(_azi1) ==   90 ? 0 : cos(alp1);
     real cbet1, sbet1, phi;
     phi = lat1 * Math::degree();
     // Ensure cbet1 = +epsilon at poles
@@ -128,8 +126,8 @@ namespace GeographicLib {
                                             real& M12, real& M21,
                                             real& S12)
   const {
-    outmask &= _caps & OUT_ALL;
-    if (!( Init() && (arcmode || (_caps & DISTANCE_IN & OUT_ALL)) ))
+    outmask &= _caps & OUT_MASK;
+    if (!( Init() && (arcmode || (_caps & DISTANCE_IN & OUT_MASK)) ))
       // Uninitialized or impossible distance calculation requested
       return Math::NaN();
 
@@ -155,7 +153,6 @@ namespace GeographicLib {
       csig12 = cos(sig12);
     }
 
-    real lam12, lon12;
     real ssig2, csig2, sbet2, cbet2, salp2, calp2;
     // sig2 = sig1 + sig12
     ssig2 = _ssig1 * csig12 + _csig1 * ssig12;
@@ -184,14 +181,19 @@ namespace GeographicLib {
       real somg2 = _salp0 * ssig2, comg2 = csig2;  // No need to normalize
       // Without normalization we have schi2 = somg2.
       real cchi2 =  _f1 * dn2 *  comg2;
-      lam12 = atan2(somg2 * _cchi1 - cchi2 * _somg1,
-                    cchi2 * _cchi1 + somg2 * _somg1) -
+      real chi12 = outmask & LONG_NOWRAP ? sig12
+        - (atan2(ssig2, csig2) - atan2(_ssig1, _csig1))
+        + (atan2(somg2, cchi2) - atan2(_somg1, _cchi1))
+        : atan2(somg2 * _cchi1 - cchi2 * _somg1,
+                cchi2 * _cchi1 + somg2 * _somg1);
+      real lam12 = chi12 -
         _e2/_f1 * _salp0 * _H0 * (sig12 + _E.deltaH(ssig2, csig2, dn2) - _H1 );
-      lon12 = lam12 / Math::degree();
-      // Use Math::AngNormalize2 because longitude might have wrapped multiple
-      // times.
-      lon12 = Math::AngNormalize2(lon12);
-      lon2 = Math::AngNormalize(_lon1 + lon12);
+      real lon12 = lam12 / Math::degree();
+      // Use Math::AngNormalize2 because longitude might have wrapped
+      // multiple times.
+      lon2 = outmask & LONG_NOWRAP ? _lon1 + lon12 :
+        Math::AngNormalize(Math::AngNormalize(_lon1) +
+                           Math::AngNormalize2(lon12));
     }
 
     if (outmask & LATITUDE)
@@ -220,7 +222,7 @@ namespace GeographicLib {
         B42 = GeodesicExact::CosSeries(ssig2, csig2, _C4a, nC4_);
       real salp12, calp12;
       if (_calp0 == 0 || _salp0 == 0) {
-        // alp12 = alp2 - alp1, used in atan2 so no need to normalized
+        // alp12 = alp2 - alp1, used in atan2 so no need to normalize
         salp12 = salp2 * _calp1 - calp2 * _salp1;
         calp12 = calp2 * _calp1 + salp2 * _salp1;
         // The right thing appears to happen if alp1 = +/-180 and alp2 = 0, viz
diff --git a/src/GeographicLib.pro b/src/GeographicLib.pro
index 1f3d036..0d3e8e0 100644
--- a/src/GeographicLib.pro
+++ b/src/GeographicLib.pro
@@ -1,10 +1,11 @@
-VERSION = 9.2.4
+VERSION = 14.0.0
 
 TEMPLATE = lib
 
 INCLUDEPATH = ../include
 INCLUDEDIR = $$INCLUDEPATH/GeographicLib
 
+SOURCES += Accumulator.cpp
 SOURCES += AlbersEqualArea.cpp
 SOURCES += AzimuthalEquidistant.cpp
 SOURCES += CassiniSoldner.cpp
@@ -15,7 +16,10 @@ SOURCES += EllipticFunction.cpp
 SOURCES += GeoCoords.cpp
 SOURCES += Geocentric.cpp
 SOURCES += Geodesic.cpp
+SOURCES += GeodesicExact.cpp
+SOURCES += GeodesicExactC4.cpp
 SOURCES += GeodesicLine.cpp
+SOURCES += GeodesicLineExact.cpp
 SOURCES += Geohash.cpp
 SOURCES += Geoid.cpp
 SOURCES += Gnomonic.cpp
@@ -49,7 +53,9 @@ HEADERS += $$INCLUDEDIR/EllipticFunction.hpp
 HEADERS += $$INCLUDEDIR/GeoCoords.hpp
 HEADERS += $$INCLUDEDIR/Geocentric.hpp
 HEADERS += $$INCLUDEDIR/Geodesic.hpp
+HEADERS += $$INCLUDEDIR/GeodesicExact.hpp
 HEADERS += $$INCLUDEDIR/GeodesicLine.hpp
+HEADERS += $$INCLUDEDIR/GeodesicLineExact.hpp
 HEADERS += $$INCLUDEDIR/Geohash.hpp
 HEADERS += $$INCLUDEDIR/Geoid.hpp
 HEADERS += $$INCLUDEDIR/Gnomonic.hpp
diff --git a/src/Geohash.cpp b/src/Geohash.cpp
index 00942aa..9b56b76 100644
--- a/src/Geohash.cpp
+++ b/src/Geohash.cpp
@@ -2,8 +2,8 @@
  * \file Geohash.cpp
  * \brief Implementation for GeographicLib::Geohash class
  *
- * Copyright (c) Charles Karney (2012) <charles at karney.com> and licensed under
- * the MIT/X11 License.  For more information, see
+ * Copyright (c) Charles Karney (2012-2014) <charles at karney.com> and licensed
+ * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  **********************************************************************/
 
@@ -73,7 +73,7 @@ namespace GeographicLib {
       int byte = Utility::lookup(ucdigits_, geohash[k]);
       if (byte < 0)
         throw GeographicErr("Illegal character in geohash " + geohash);
-      for (unsigned i = 0, m = 16; i < 5; ++i, m >>= 1) {
+      for (unsigned m = 16; m; m >>= 1) {
         if (j == 0)
           ulon = (ulon << 1) + unsigned((byte & m) != 0);
         else
@@ -89,8 +89,8 @@ namespace GeographicLib {
     int s = 5 * (maxlen_ - len);
     ulon <<=     (s / 2);
     ulat <<= s - (s / 2);
-    lon = (unsigned long)(ulon) * loneps() - 180;
-    lat = (unsigned long)(ulat) * lateps() - 90;
+    lon = ulon * loneps() - 180;
+    lat = ulat * lateps() - 90;
   }
 
 } // namespace GeographicLib
diff --git a/src/PolygonArea.cpp b/src/PolygonArea.cpp
index e191f4d..df0d7d3 100644
--- a/src/PolygonArea.cpp
+++ b/src/PolygonArea.cpp
@@ -1,6 +1,6 @@
 /**
  * \file PolygonArea.cpp
- * \brief Implementation for GeographicLib::PolygonArea class
+ * \brief Implementation for GeographicLib::PolygonAreaT class
  *
  * Copyright (c) Charles Karney (2010-2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
@@ -41,7 +41,8 @@ namespace GeographicLib {
       _perimetersum += s;
       if (!_polyline) {
         _areasum += S12;
-        _crossings += transit(_lon1, lon);
+        _crossings += transitdirect(_lon1, lon);
+        lon = Math::AngNormalize2(lon);
       }
       _lat1 = lat; _lon1 = lon;
       ++_num;
@@ -165,7 +166,8 @@ namespace GeographicLib {
       _earth.GenDirect(_lat1, _lon1, azi, false, s, _mask,
                        lat, lon, t, t, t, t, t, S12);
       tempsum += S12;
-      crossings += transit(_lon1, lon);
+      crossings += transitdirect(_lon1, lon);
+      lon = Math::AngNormalize2(lon);
       _earth.GenInverse(lat, lon, _lat0, _lon0, _mask, s12, t, t, t, t, t, S12);
       perimeter += s12;
       tempsum += S12;
@@ -196,5 +198,6 @@ namespace GeographicLib {
 
   template class GEOGRAPHICLIB_EXPORT PolygonAreaT<Geodesic>;
   template class GEOGRAPHICLIB_EXPORT PolygonAreaT<GeodesicExact>;
+  template class GEOGRAPHICLIB_EXPORT PolygonAreaT<Rhumb>;
 
 } // namespace GeographicLib
diff --git a/src/Rhumb.cpp b/src/Rhumb.cpp
index 4cde164..4cea566 100644
--- a/src/Rhumb.cpp
+++ b/src/Rhumb.cpp
@@ -15,31 +15,129 @@ namespace GeographicLib {
 
   using namespace std;
 
+  Rhumb::Rhumb(real a, real f, bool exact)
+    : _ell(a, f)
+    , _exact(exact)
+    , _c2(_ell.Area() / 720)
+  {
+    real n = _ell._n, nx = n;
+    switch (maxpow_) {
+    case 4:
+      _R[1] = nx*(n*(n*(1772*n-5340)+6930)-4725)/14175;
+      nx *= n;
+      _R[2] = nx*((1590-1747*n)*n-630)/4725;
+      nx *= n;
+      _R[3] = nx*(104*n-31)/315;
+      nx *= n;
+      _R[4] = -41*nx/420;
+      break;
+    case 5:
+      _R[1] = nx*(n*(n*(n*(41662*n+58476)-176220)+228690)-155925)/467775;
+      nx *= n;
+      _R[2] = nx*(n*(n*(18118*n-57651)+52470)-20790)/155925;
+      nx *= n;
+      _R[3] = nx*((17160-23011*n)*n-5115)/51975;
+      nx *= n;
+      _R[4] = nx*(5480*n-1353)/13860;
+      nx *= n;
+      _R[5] = -668*nx/5775;
+      break;
+    case 6:
+      _R[1] = nx*(n*(n*(n*((56868630-114456994*n)*n+79819740)-240540300)+
+                     312161850)-212837625)/638512875;
+      nx *= n;
+      _R[2] = nx*(n*(n*(n*(51304574*n+24731070)-78693615)+71621550)-28378350)/
+        212837625;
+      nx *= n;
+      _R[3] = nx*(n*(n*(1554472*n-6282003)+4684680)-1396395)/14189175;
+      nx *= n;
+      _R[4] = nx*((3205800-4913956*n)*n-791505)/8108100;
+      nx *= n;
+      _R[5] = nx*(1092376*n-234468)/2027025;
+      nx *= n;
+      _R[6] = -313076*nx/2027025;
+      break;
+    case 7:
+      _R[1] = nx*(n*(n*(n*(n*(n*(258618446*n-343370982)+170605890)+239459220)-
+                        721620900)+936485550)-638512875)/1915538625;
+      nx *= n;
+      _R[2] = nx*(n*(n*(n*((153913722-248174686*n)*n+74193210)-236080845)+
+                     214864650)-85135050)/638512875;
+      nx *= n;
+      _R[3] = nx*(n*(n*(n*(114450437*n+23317080)-94230045)+70270200)-20945925)/
+        212837625;
+      nx *= n;
+      _R[4] = nx*(n*(n*(15445736*n-103193076)+67321800)-16621605)/170270100;
+      nx *= n;
+      _R[5] = nx*((16385640-27766753*n)*n-3517020)/30405375;
+      nx *= n;
+      _R[6] = nx*(4892722*n-939228)/6081075;
+      nx *= n;
+      _R[7] = -3189007*nx/14189175;
+      break;
+    case 8:
+      _R[1] = nx*(n*(n*(n*(n*(n*((65947703730LL-13691187484LL*n)*n-
+                                 87559600410LL)+43504501950LL)+61062101100LL)-
+                        184013329500LL)+238803815250LL)-162820783125LL)/
+        488462349375LL;
+      nx *= n;
+      _R[2] = nx*(n*(n*(n*(n*(n*(30802104839LL*n-63284544930LL)+39247999110LL)+
+                           18919268550LL)-60200615475LL)+54790485750LL)-
+                  21709437750LL)/162820783125LL;
+      nx *= n;
+      _R[3] = nx*(n*(n*(n*((5836972287LL-8934064508LL*n)*n+1189171080)-
+                        4805732295LL)+3583780200LL)-1068242175)/10854718875LL;
+      nx *= n;
+      _R[4] = nx*(n*(n*(n*(50072287748LL*n+3938662680LL)-26314234380LL)+
+                     17167059000LL)-4238509275LL)/43418875500LL;
+      nx *= n;
+      _R[5] = nx*(n*(n*(359094172*n-9912730821LL)+5849673480LL)-1255576140)/
+        10854718875LL;
+      nx *= n;
+      _R[6] = nx*((8733508770LL-16053944387LL*n)*n-1676521980)/10854718875LL;
+      nx *= n;
+      _R[7] = nx*(930092876*n-162639357)/723647925;
+      nx *= n;
+      _R[8] = -673429061*nx/1929727800;
+      break;
+    default:
+      GEOGRAPHICLIB_STATIC_ASSERT(maxpow_ >= 4 && maxpow_ <= 8,
+                                  "Bad value of maxpow_");
+    }
+  }
+
   const Rhumb& Rhumb::WGS84() {
     static const Rhumb wgs84(Constants::WGS84_a(), Constants::WGS84_f(), false);
     return wgs84;
   }
 
-  void Rhumb::Inverse(real lat1, real lon1, real lat2, real lon2,
-                      real& s12, real& azi12) const {
+  void Rhumb::GenInverse(real lat1, real lon1, real lat2, real lon2,
+                         unsigned outmask,
+                         real& s12, real& azi12, real& S12) const {
     real
       lon12 = Math::AngDiff(Math::AngNormalize(lon1), Math::AngNormalize(lon2)),
       psi1 = _ell.IsometricLatitude(lat1),
       psi2 = _ell.IsometricLatitude(lat2),
       psi12 = psi2 - psi1,
       h = Math::hypot(lon12, psi12);
-    azi12 = 0 - atan2(-lon12, psi12) / Math::degree();
-    real dmudpsi = DIsometricToRectifying(psi2 * Math::degree(),
-                                          psi1 * Math::degree());
-    s12 = h * dmudpsi * _ell.QuarterMeridian() / 90;
+    if (outmask & AZIMUTH)
+      azi12 = 0 - atan2(-lon12, psi12) / Math::degree();
+    psi1 *= Math::degree();
+    psi2 *= Math::degree();
+    real dmudpsi = DIsometricToRectifying(psi2, psi1);
+    if (outmask & DISTANCE)
+      s12 = h * dmudpsi * _ell.QuarterMeridian() / 90;
+    if (outmask & AREA)
+      S12 = _c2 * lon12 * MeanSinXi(psi2, psi1);
   }
 
   RhumbLine Rhumb::Line(real lat1, real lon1, real azi12) const
   { return RhumbLine(*this, lat1, lon1, azi12, _exact); }
 
-  void Rhumb::Direct(real lat1, real lon1, real azi12, real s12,
-                     real& lat2, real& lon2) const
-  { Line(lat1, lon1, azi12).Position(s12, lat2, lon2); }
+  void Rhumb::GenDirect(real lat1, real lon1, real azi12, real s12,
+                        unsigned outmask,
+                        real& lat2, real& lon2, real& S12) const
+  { Line(lat1, lon1, azi12).GenPosition(s12, outmask, lat2, lon2, S12); }
 
   Math::real Rhumb::DE(real x, real y) const {
     const EllipticFunction& ei = _ell._ell;
@@ -86,27 +184,30 @@ namespace GeographicLib {
       - Deatanhe(sin(phix), sin(phiy)) * Dsin(phix, phiy);
   }
 
-  Math::real Rhumb::SinSeries(real x, real y, const real c[], int n) {
+  Math::real Rhumb::SinCosSeries(bool sinp,
+                                 real x, real y, const real c[], int n) {
     // N.B. n >= 0 and c[] has n+1 elements 0..n, of which c[0] is ignored.
     //
     // Use Clenshaw summation to evaluate
     //   m = (g(x) + g(y)) / 2         -- mean value
     //   s = (g(x) - g(y)) / (x - y)   -- average slope
     // where
-    //   g(x) = sum(c[j]*sin(2*j*x), j = 1..n)
+    //   g(x) = sum(c[j]*SC(2*j*x), j = 1..n)
+    //   SC = sinp ? sin : cos
+    //   CS = sinp ? cos : sin
     //
-    // This function returns only s and m is discarded.
+    // This function returns only s; m is discarded.
     //
     // Write
     //   t = [m; s]
     //   t = sum(c[j] * f[j](x,y), j = 1..n)
     // where
-    //   f[j](x,y) = [ (sin(2*j*x)+sin(2*j*y))/2 ]
-    //               [ (sin(2*j*x)-sin(2*j*y))/d ]
+    //   f[j](x,y) = [ (SC(2*j*x)+SC(2*j*y))/2 ]
+    //               [ (SC(2*j*x)-SC(2*j*y))/d ]
     //
-    //             = [       sin(j*p)*cos(j*d) ]
-    //               [ (2/d)*sin(j*d)*cos(j*p) ]
-    // and
+    //             = [       cos(j*d)*SC(j*p)    ]
+    //               [ +/-(2/d)*sin(j*d)*CS(j*p) ]
+    // (+/- = sinp ? + : -) and
     //    p = x+y, d = x-y
     //
     //   f[j+1](x,y) = A * f[j](x,y) - f[j-1](x,y)
@@ -116,7 +217,8 @@ namespace GeographicLib {
     //
     // Let b[n+1] = b[n+2] = [0 0; 0 0]
     //     b[j] = A * b[j+1] - b[j+2] + c[j] * I for j = n..1
-    //    t =  b[1] * f[1](x,y)
+    //    t =  (c[0] * I  - b[2]) * f[0](x,y) + b[1] * f[1](x,y)
+    // c[0] is not accessed for s = t[2]
     real p = x + y, d = x - y,
       cp = cos(p), cd =     cos(d),
       sp = sin(p), sd = d ? sin(d)/d : 1,
@@ -125,32 +227,42 @@ namespace GeographicLib {
     const real a[4] = {m, -s * d * d, -4 * s, m};
     real ba[4] = {0, 0, 0, 0};
     real bb[4] = {0, 0, 0, 0};
-    real* b0 = ba;
-    real* b1 = bb;
-    if (n > 0) b0[0] = b0[3] = c[n];
+    real* b1 = ba;
+    real* b2 = bb;
+    if (n > 0) b1[0] = b1[3] = c[n];
     for (int j = n - 1; j > 0; --j) { // j = n-1 .. 1
-      std::swap(b0, b1);
-      // b0 = A * b1 - b0 + c[j] * I
-      b0[0] = a[0] * b1[0] + a[1] * b1[2] - b0[0] + c[j];
-      b0[1] = a[0] * b1[1] + a[1] * b1[3] - b0[1];
-      b0[2] = a[2] * b1[0] + a[3] * b1[2] - b0[2];
-      b0[3] = a[2] * b1[1] + a[3] * b1[3] - b0[3] + c[j];
+      std::swap(b1, b2);
+      // b1 = A * b2 - b1 + c[j] * I
+      b1[0] = a[0] * b2[0] + a[1] * b2[2] - b1[0] + c[j];
+      b1[1] = a[0] * b2[1] + a[1] * b2[3] - b1[1];
+      b1[2] = a[2] * b2[0] + a[3] * b2[2] - b1[2];
+      b1[3] = a[2] * b2[1] + a[3] * b2[3] - b1[3] + c[j];
+    }
+    // Here are the full expressions for m and s
+    // m =   (c[0] - b2[0]) * f01 - b2[1] * f02 + b1[0] * f11 + b1[1] * f12;
+    // s = - b2[2] * f01 + (c[0] - b2[3]) * f02 + b1[2] * f11 + b1[3] * f12;
+    if (sinp) {
+      // real f01 = 0, f02 = 0;
+      real f11 = cd * sp, f12 = 2 * sd * cp;
+      // m = b1[0] * f11 + b1[1] * f12;
+      s = b1[2] * f11 + b1[3] * f12;
+    } else {
+      // real f01 = 1, f02 = 0;
+      real f11 = cd * cp, f12 = - 2 * sd * sp;
+      // m = c[0] - b2[0] + b1[0] * f11 + b1[1] * f12;
+      s = - b2[2] + b1[2] * f11 + b1[3] * f12;
     }
-    b1[0] = sp * cd; b1[2] = 2 * sd * cp;
-    // Here is the (unused) expression for m
-    // m = b0[0] * b1[0] + b0[1] * b1[2];
-    s = b0[2] * b1[0] + b0[3] * b1[2];
     return s;
   }
 
   Math::real Rhumb::DConformalToRectifying(real chix, real chiy) const {
-    return 1 + SinSeries(chix, chiy,
-                         _ell.ConformalToRectifyingCoeffs(), tm_maxord);
+    return 1 + SinCosSeries(true, chix, chiy,
+                            _ell.ConformalToRectifyingCoeffs(), tm_maxord);
   }
 
   Math::real Rhumb::DRectifyingToConformal(real mux, real muy) const {
-    return 1 - SinSeries(mux, muy,
-                         _ell.RectifyingToConformalCoeffs(), tm_maxord);
+    return 1 - SinCosSeries(true, mux, muy,
+                            _ell.RectifyingToConformalCoeffs(), tm_maxord);
   }
 
   Math::real Rhumb::DIsometricToRectifying(real psix, real psiy) const {
@@ -174,45 +286,62 @@ namespace GeographicLib {
       DRectifyingToConformal(mux, muy);
   }
 
+  Math::real Rhumb::MeanSinXi(real psix, real psiy) const {
+    return Dlog(cosh(psix), cosh(psiy)) * Dcosh(psix, psiy)
+      + SinCosSeries(false, gd(psix), gd(psiy), _R, maxpow_) * Dgd(psix, psiy);
+  }
+
   RhumbLine::RhumbLine(const Rhumb& rh, real lat1, real lon1, real azi12,
                        bool exact)
     : _rh(rh)
     , _exact(exact)
     , _lat1(lat1)
-    , _lon1(Math::AngNormalize(lon1))
+    , _lon1(lon1)
     , _azi12(Math::AngNormalize(azi12))
   {
-    real alp12 = azi12 * Math::degree();
-    _salp =     azi12  == -180 ? 0 : sin(alp12);
-    _calp = abs(azi12) ==   90 ? 0 : cos(alp12);
+    real alp12 = _azi12 * Math::degree();
+    _salp =     _azi12  == -180 ? 0 : sin(alp12);
+    _calp = abs(_azi12) ==   90 ? 0 : cos(alp12);
     _mu1 = _rh._ell.RectifyingLatitude(lat1);
     _psi1 = _rh._ell.IsometricLatitude(lat1);
     _r1 = _rh._ell.CircleRadius(lat1);
   }
 
-  void RhumbLine::Position(real s12, real& lat2, real& lon2) const {
+  void RhumbLine::GenPosition(real s12, unsigned outmask,
+                              real& lat2, real& lon2, real& S12) const {
     real
       mu12 = s12 * _calp * 90 / _rh._ell.QuarterMeridian(),
       mu2 = _mu1 + mu12;
+    real psi2, lat2x, lon2x;
     if (abs(mu2) <= 90) {
       if (_calp) {
-        lat2 = _rh._ell.InverseRectifyingLatitude(mu2);
-        real psi12 = _rh.DRectifyingToIsometric( mu2 * Math::degree(),
+        lat2x = _rh._ell.InverseRectifyingLatitude(mu2);
+        real psi12 = _rh.DRectifyingToIsometric(  mu2 * Math::degree(),
                                                  _mu1 * Math::degree()) * mu12;
-        lon2 = _salp * psi12 / _calp;
+        lon2x = _salp * psi12 / _calp;
+        psi2 = _psi1 + psi12;
       } else {
-        lat2 = _lat1;
-        lon2 = _salp * s12 / (_r1 * Math::degree());
+        lat2x = _lat1;
+        lon2x = _salp * s12 / (_r1 * Math::degree());
+        psi2 = _psi1;
       }
-      lon2 = Math::AngNormalize2(_lon1 + lon2);
+      if (outmask & AREA)
+        S12 = _rh._c2 * lon2x *
+          _rh.MeanSinXi(_psi1 * Math::degree(), psi2 * Math::degree());
+      lon2x = outmask & LONG_NOWRAP ? _lon1 + lon2x :
+        Math::AngNormalize2(Math::AngNormalize(_lon1) + lon2x);
     } else {
       // Reduce to the interval [-180, 180)
       mu2 = Math::AngNormalize2(mu2);
       // Deal with points on the anti-meridian
       if (abs(mu2) > 90) mu2 = Math::AngNormalize(180 - mu2);
-      lat2 = _rh._ell.InverseRectifyingLatitude(mu2);
-      lon2 = Math::NaN();
+      lat2x = _rh._ell.InverseRectifyingLatitude(mu2);
+      lon2x = Math::NaN();
+      if (outmask & AREA)
+        S12 = Math::NaN();
     }
+    if (outmask & LATITUDE) lat2 = lat2x;
+    if (outmask & LONGITUDE) lon2 = lon2x;
   }
 
 } // namespace GeographicLib
diff --git a/src/TransverseMercator.cpp b/src/TransverseMercator.cpp
index ee91d5e..85ab16c 100644
--- a/src/TransverseMercator.cpp
+++ b/src/TransverseMercator.cpp
@@ -290,10 +290,12 @@ namespace GeographicLib {
       return taup;
     real
       // To lowest order in e^2, taup = (1 - e^2) * tau = _e2m * tau; so use
-      // tau = taup/_e2m as a starting guess.  Only 1 iteration is needed for
-      // |lat| < 3.35 deg, otherwise 2 iterations are needed.  If, instead, tau
-      // = taup is used the mean number of iterations increases to 1.99 (2
-      // iterations are needed except near tau = 0).
+      // tau = taup/_e2m as a starting guess.  (This starting guess is the
+      // geocentric latitude which, to first order in the flattening, is equal
+      // to the conformal latitude.)  Only 1 iteration is needed for |lat| <
+      // 3.35 deg, otherwise 2 iterations are needed.  If, instead, tau = taup
+      // is used the mean number of iterations increases to 1.99 (2 iterations
+      // are needed except near tau = 0).
       tau = taup/_e2m,
       stol = tol_ * max(real(1), abs(taup));
     // min iterations = 1, max iterations = 2; mean = 1.94
diff --git a/src/TransverseMercatorExact.cpp b/src/TransverseMercatorExact.cpp
index a69ee68..9be13a5 100644
--- a/src/TransverseMercatorExact.cpp
+++ b/src/TransverseMercatorExact.cpp
@@ -93,7 +93,8 @@ namespace GeographicLib {
 
   Math::real TransverseMercatorExact::taupinv(real taup) const {
     real
-      // See comment in TransverseMercator.cpp about the initial guess
+      // See comment in implementation of TransverseMercator::tauf about the
+      // initial guess
       tau = taup/_mv,
       stol = tol_ * max(real(1), abs(taup));
     // min iterations = 1, max iterations = 2; mean = 1.94
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 319ef1e..ef7664a 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -91,7 +91,7 @@ if (NOT (MSVC AND MSVC_VERSION MATCHES "1[78].."))
   # This test is known to fail for VS 11 and 12 bug reported 2013-01-10
   # http://connect.microsoft.com/VisualStudio/feedback/details/776287
   # OK to skip this test for these compilers because this is a question
-  # of accuracy of the least significant bit.
+  # of accuracy of the least significant bit.  The bug is fixed in VS 14.
   add_test (NAME GeoConvert6 COMMAND GeoConvert -p 9
     --input-string "0 179.99999999999998578")
   set_tests_properties (GeoConvert6
@@ -210,6 +210,20 @@ add_test (NAME Planimeter9
   COMMAND Planimeter -p 8 --input-string "9 -0.00000000000001;9 0;9 180")
 set_tests_properties (Planimeter6 Planimeter7 Planimeter8 Planimeter9
   PROPERTIES PASS_REGULAR_EXPRESSION "3 36026861\\.[0-9]+ -?0.0[0-9]+")
+# Area of Wyoming
+add_test (NAME Planimeter10 COMMAND Planimeter -R
+  --input-string "41N 111:3W; 41N 104:3W; 45N 104:3W; 45N 111:3W")
+set_tests_properties (Planimeter10
+  PROPERTIES PASS_REGULAR_EXPRESSION "4 2029616.[0-9]+ 2535883763..\\.")
+# Area of arctic circle
+add_test (NAME Planimeter11
+  COMMAND Planimeter -R --input-string "66:33:44 0; 66:33:44 180")
+set_tests_properties (Planimeter11
+  PROPERTIES PASS_REGULAR_EXPRESSION "2 15985058.[0-9]+ 212084182523..\\.")
+add_test (NAME Planimeter12
+  COMMAND Planimeter --input-string "66:33:44 0; 66:33:44 180")
+set_tests_properties (Planimeter12
+  PROPERTIES PASS_REGULAR_EXPRESSION "2 10465729.[0-9]+ -?0.0")
 
 # Check fix for AlbersEqualArea::Reverse bug found 2011-05-01
 add_test (NAME ConicProj0 COMMAND
diff --git a/tools/CartConvert.cpp b/tools/CartConvert.cpp
index f2d90b7..8ad77ac 100644
--- a/tools/CartConvert.cpp
+++ b/tools/CartConvert.cpp
@@ -6,15 +6,7 @@
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
- * Compile and link with
- *   g++ -g -O3 -I../include -I../man -o CartConvert \
- *       CartConvert.cpp \
- *       ../src/DMS.cpp \
- *       ../src/Geocentric.cpp \
- *       ../src/LocalCartesian.cpp
- *
- * See the <a href="CartConvert.1.html">man page</a> for usage
- * information.
+ * See the <a href="CartConvert.1.html">man page</a> for usage information.
  **********************************************************************/
 
 #include <iostream>
diff --git a/tools/ConicProj.cpp b/tools/ConicProj.cpp
index 583ec69..8d0c130 100644
--- a/tools/ConicProj.cpp
+++ b/tools/ConicProj.cpp
@@ -6,15 +6,7 @@
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
- * Compile and link with
- *   g++ -g -O3 -I../include -I../man -o ConicProj \
- *       ConicProj.cpp \
- *       ../src/AlbersEqualArea.cpp \
- *       ../src/DMS.cpp \
- *       ../src/LambertConformalConic.cpp
- *
- * See the <a href="ConicProj.1.html">man page</a> for usage
- * information.
+ * See the <a href="ConicProj.1.html">man page</a> for usage information.
  **********************************************************************/
 
 #include <iostream>
diff --git a/tools/GeoConvert.cpp b/tools/GeoConvert.cpp
index b6a8dde..f77d8e3 100644
--- a/tools/GeoConvert.cpp
+++ b/tools/GeoConvert.cpp
@@ -6,18 +6,7 @@
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
- * Compile and link with
- *   g++ -g -O3 -I../include -I../man -o GeoConvert \
- *       GeoConvert.cpp \
- *       ../src/DMS.cpp \
- *       ../src/GeoCoords.cpp \
- *       ../src/MGRS.cpp \
- *       ../src/PolarStereographic.cpp \
- *       ../src/TransverseMercator.cpp \
- *       ../src/UTMUPS.cpp
- *
- * See the <a href="GeoConvert.1.html">man page</a> for usage
- * information.
+ * See the <a href="GeoConvert.1.html">man page</a> for usage information.
  **********************************************************************/
 
 #include <iostream>
diff --git a/tools/GeodSolve.cpp b/tools/GeodSolve.cpp
index 3fcd964..6c67a28 100644
--- a/tools/GeodSolve.cpp
+++ b/tools/GeodSolve.cpp
@@ -6,15 +6,7 @@
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
- * Compile and link with
- *   g++ -g -O3 -I../include -I../man -o GeodSolve \
- *       GeodSolve.cpp \
- *       ../src/DMS.cpp \
- *       ../src/Geodesic.cpp \
- *       ../src/GeodesicLine.cpp
- *
- * See the <a href="GeodSolve.1.html">man page</a> for usage
- * information.
+ * See the <a href="GeodSolve.1.html">man page</a> for usage information.
  **********************************************************************/
 
 #include <iostream>
diff --git a/tools/GeodesicProj.cpp b/tools/GeodesicProj.cpp
index 1912de5..4077214 100644
--- a/tools/GeodesicProj.cpp
+++ b/tools/GeodesicProj.cpp
@@ -6,18 +6,7 @@
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
- * Compile and link with
- *   g++ -g -O3 -I../include -I../man -o GeodesicProj \
- *       GeodesicProj.cpp \
- *       ../src/AzimuthalEquidistant.cpp \
- *       ../src/CassiniSoldner.cpp \
- *       ../src/DMS.cpp \
- *       ../src/Geodesic.cpp \
- *       ../src/GeodesicLine.cpp \
- *       ../src/Gnomonic.cpp
- *
- * See the <a href="GeodesicProj.1.html">man page</a> for usage
- * information.
+ * See the <a href="GeodesicProj.1.html">man page</a> for usage information.
  **********************************************************************/
 
 #include <iostream>
diff --git a/tools/GeoidEval.cpp b/tools/GeoidEval.cpp
index 40700ff..caab02c 100644
--- a/tools/GeoidEval.cpp
+++ b/tools/GeoidEval.cpp
@@ -6,19 +6,7 @@
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
- * Compile and link with
- *   g++ -g -O3 -I../include -I../man -o GeoidEval \
- *       GeoidEval.cpp \
- *       ../src/DMS.cpp \
- *       ../src/GeoCoords.cpp \
- *       ../src/Geoid.cpp \
- *       ../src/MGRS.cpp \
- *       ../src/PolarStereographic.cpp \
- *       ../src/TransverseMercator.cpp \
- *       ../src/UTMUPS.cpp
- *
- * See the <a href="GeoidEval.1.html">man page</a> for usage
- * information.
+ * See the <a href="GeoidEval.1.html">man page</a> for usage information.
  **********************************************************************/
 
 #include <iostream>
diff --git a/tools/Gravity.cpp b/tools/Gravity.cpp
index 8073168..3377da2 100644
--- a/tools/Gravity.cpp
+++ b/tools/Gravity.cpp
@@ -6,20 +6,7 @@
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
- * Compile and link with
- *   g++ -g -O3 -I../include -I../man -o Gravity \
- *       Gravity.cpp \
- *       ../src/CircularEngine.cpp \
- *       ../src/DMS.cpp \
- *       ../src/Geocentric.cpp \
- *       ../src/GravityCircle.cpp \
- *       ../src/GravityModel.cpp \
- *       ../src/NormalGravity.cpp \
- *       ../src/SphericalEngine.cpp \
- *       ../src/Utility.cpp
- *
- * See the <a href="Gravity.1.html">man page</a> for usage
- * information.
+ * See the <a href="Gravity.1.html">man page</a> for usage information.
  **********************************************************************/
 
 #include <iostream>
diff --git a/tools/MagneticField.cpp b/tools/MagneticField.cpp
index 69753b4..9537bda 100644
--- a/tools/MagneticField.cpp
+++ b/tools/MagneticField.cpp
@@ -6,19 +6,7 @@
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
- * Compile and link with
- *   g++ -g -O3 -I../include -I../man -o MagneticField \
- *       MagneticField.cpp \
- *       ../src/CircularEngine.cpp \
- *       ../src/DMS.cpp \
- *       ../src/Geocentric.cpp \
- *       ../src/MagneticCircle.cpp \
- *       ../src/MagneticModel.cpp \
- *       ../src/SphericalEngine.cpp \
- *       ../src/Utility.cpp
- *
- * See the <a href="MagneticField.1.html">man page</a> for usage
- * information.
+ * See the <a href="MagneticField.1.html">man page</a> for usage information.
  **********************************************************************/
 
 #include <iostream>
@@ -248,10 +236,10 @@ int main(int argc, char* argv[]) {
         try {
           std::string eol("\n");
           if (!cdelim.empty()) {
-            std::string::size_type m = s.find(cdelim);
-            if (m != std::string::npos) {
-              eol = " " + s.substr(m) + "\n";
-              s = s.substr(0, m);
+            std::string::size_type n = s.find(cdelim);
+            if (n != std::string::npos) {
+              eol = " " + s.substr(n) + "\n";
+              s = s.substr(0, n);
             }
           }
           std::istringstream str(s);
diff --git a/tools/Planimeter.cpp b/tools/Planimeter.cpp
index 84062c4..45f4b8e 100644
--- a/tools/Planimeter.cpp
+++ b/tools/Planimeter.cpp
@@ -6,21 +6,7 @@
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
- * Compile and link with
- *   g++ -g -O3 -I../include -I../man -o Planimeter \
- *       Planimeter.cpp \
- *       ../src/DMS.cpp \
- *       ../src/GeoCoords.cpp \
- *       ../src/Geodesic.cpp \
- *       ../src/GeodesicLine.cpp \
- *       ../src/MGRS.cpp \
- *       ../src/PolarStereographic.cpp \
- *       ../src/PolygonArea.cpp \
- *       ../src/TransverseMercator.cpp \
- *       ../src/UTMUPS.cpp
- *
- * See the <a href="Planimeter.1.html">man page</a> for usage
- * information.
+ * See the <a href="Planimeter.1.html">man page</a> for usage information.
  **********************************************************************/
 
 #include <iostream>
@@ -45,11 +31,12 @@ int main(int argc, char* argv[]) {
     using namespace GeographicLib;
     typedef Math::real real;
     Utility::set_digits();
+    enum { GEODESIC, EXACT, AUTHALIC, RHUMB };
     real
       a = Constants::WGS84_a(),
       f = Constants::WGS84_f();
-    bool reverse = false, sign = true, polyline = false,
-      exact = false, authalic = false;
+    bool reverse = false, sign = true, polyline = false;
+    int linetype = GEODESIC;
     int prec = 6;
     std::string istring, ifile, ofile, cdelim;
     char lsep = ';';
@@ -82,13 +69,15 @@ int main(int argc, char* argv[]) {
           std::cerr << "Precision " << argv[m] << " is not a number\n";
           return 1;
         }
-      } else if (arg == "-E") {
-        exact = true;
-        authalic = false;
-      } else if (arg == "-Q") {
-        exact = false;
-        authalic = true;
-      } else if (arg == "--input-string") {
+      } else if (arg == "-G")
+        linetype = GEODESIC;
+      else if (arg == "-E")
+        linetype = EXACT;
+      else if (arg == "-Q")
+        linetype = AUTHALIC;
+      else if (arg == "-R")
+        linetype = RHUMB;
+      else if (arg == "--input-string") {
         if (++m == argc) return usage(1, true);
         istring = argv[m];
       } else if (arg == "--input-file") {
@@ -154,15 +143,17 @@ int main(int argc, char* argv[]) {
     std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
 
     const Ellipsoid ellip(a, f);
-    if (authalic) {
+    if (linetype == AUTHALIC) {
       using std::sqrt;
       a = sqrt(ellip.Area() / (4 * Math::pi()));
       f = 0;
     }
     const Geodesic geod(a, f);
     const GeodesicExact geode(a, f);
+    const Rhumb rhumb(a, f);
     PolygonArea poly(geod, polyline);
     PolygonAreaExact polye(geode, polyline);
+    PolygonAreaRhumb polyr(rhumb, polyline);
     GeoCoords p;
 
     // Max precision = 10: 0.1 nm in distance, 10^-15 deg (= 0.11 nm),
@@ -192,8 +183,10 @@ int main(int argc, char* argv[]) {
         }
       }
       if (endpoly) {
-        num = exact ? polye.Compute(reverse, sign, perimeter, area) :
-          poly.Compute(reverse, sign, perimeter, area);
+        num =
+          linetype == EXACT ? polye.Compute(reverse, sign, perimeter, area) :
+          linetype == RHUMB ? polyr.Compute(reverse, sign, perimeter, area) :
+          poly.Compute(reverse, sign, perimeter, area); // geodesic + authalic
         if (num > 0) {
           *output << num << " " << Utility::str(perimeter, prec);
           if (!polyline) {
@@ -201,16 +194,21 @@ int main(int argc, char* argv[]) {
           }
           *output << eol;
         }
-        exact ? polye.Clear() : poly.Clear();
+        linetype == EXACT ? polye.Clear() :
+          linetype == RHUMB ? polyr.Clear() : poly.Clear();
         eol = "\n";
       } else {
-        exact ? polye.AddPoint(p.Latitude(), p.Longitude()) :
-          poly.AddPoint(authalic ? ellip.AuthalicLatitude(p.Latitude()) :
+        linetype == EXACT ? polye.AddPoint(p.Latitude(), p.Longitude()) :
+          linetype == RHUMB ? polyr.AddPoint(p.Latitude(), p.Longitude()) :
+          poly.AddPoint(linetype == AUTHALIC ?
+                        ellip.AuthalicLatitude(p.Latitude()) :
                         p.Latitude(),
                         p.Longitude());
       }
     }
-    num = exact ? polye.Compute(reverse, sign, perimeter, area):
+    num =
+      linetype == EXACT ? polye.Compute(reverse, sign, perimeter, area) :
+      linetype == RHUMB ? polyr.Compute(reverse, sign, perimeter, area) :
       poly.Compute(reverse, sign, perimeter, area);
     if (num > 0) {
       *output << num << " " << Utility::str(perimeter, prec);
@@ -219,7 +217,8 @@ int main(int argc, char* argv[]) {
       }
       *output << eol;
     }
-    exact ? polye.Clear() : poly.Clear();
+    linetype == EXACT ? polye.Clear() :
+      linetype == RHUMB ? polyr.Clear() : poly.Clear();
     eol = "\n";
     return 0;
   }
diff --git a/tools/RhumbSolve.cpp b/tools/RhumbSolve.cpp
index c695d93..19b0faf 100644
--- a/tools/RhumbSolve.cpp
+++ b/tools/RhumbSolve.cpp
@@ -5,6 +5,8 @@
  * Copyright (c) Charles Karney (2014) <charles at karney.com> and licensed
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
+ *
+ * See the <a href="RhumbSolve.1.html">man page</a> for usage information.
  **********************************************************************/
 
 #include <iostream>
@@ -49,7 +51,7 @@ int main(int argc, char* argv[]) {
     real
       a = Constants::WGS84_a(),
       f = Constants::WGS84_f();
-    real lat1, lon1, azi12 = Math::NaN(), lat2, lon2, s12;
+    real lat1, lon1, azi12 = Math::NaN(), lat2, lon2, s12, S12;
     int prec = 3;
     std::string istring, ifile, ofile, cdelim;
     char lsep = ';', dmssep = char(0);
@@ -168,34 +170,34 @@ int main(int argc, char* argv[]) {
     std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
 
     const Rhumb rh(a, f, exact);
+    const RhumbLine rhl(linecalc ? rh.Line(lat1, lon1, azi12) :
+                        rh.Line(0, 0, 90));
     // Max precision = 10: 0.1 nm in distance, 10^-15 deg (= 0.11 nm),
     // 10^-11 sec (= 0.3 nm).
     prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
     int retval = 0;
     std::string s;
-    if (linecalc) {
-      const RhumbLine rhl(rh.Line(lat1, lon1, azi12));
-      while (std::getline(*input, s)) {
-        try {
-          std::istringstream str(s);
+    while (std::getline(*input, s)) {
+      try {
+        std::string eol("\n");
+        if (!cdelim.empty()) {
+          std::string::size_type m = s.find(cdelim);
+          if (m != std::string::npos) {
+            eol = " " + s.substr(m) + "\n";
+            s = s.substr(0, m);
+          }
+        }
+        std::istringstream str(s);
+        if (linecalc) {
           if (!(str >> s12))
             throw GeographicErr("Incomplete input: " + s);
           std::string strc;
           if (str >> strc)
             throw GeographicErr("Extraneous input: " + strc);
-          rhl.Position(s12, lat2, lon2);
-          *output << LatLonString(lat2, lon2, prec, dms, dmssep) << "\n";
-        }
-        catch (const std::exception& e) {
-          // Write error message cout so output lines match input lines
-          *output << "ERROR: " << e.what() << "\n";
-          retval = 1;
-        }
-      }
-    } else if (inverse) {
-      while (std::getline(*input, s)) {
-        try {
-          std::istringstream str(s);
+          rhl.Position(s12, lat2, lon2, S12);
+          *output << LatLonString(lat2, lon2, prec, dms, dmssep) << " "
+                  << Utility::str(S12, std::max(prec-7, 0)) << eol;
+        } else if (inverse) {
           std::string slat1, slon1, slat2, slon2;
           if (!(str >> slat1 >> slon1 >> slat2 >> slon2))
             throw GeographicErr("Incomplete input: " + s);
@@ -204,20 +206,11 @@ int main(int argc, char* argv[]) {
             throw GeographicErr("Extraneous input: " + strc);
           DMS::DecodeLatLon(slat1, slon1, lat1, lon1);
           DMS::DecodeLatLon(slat2, slon2, lat2, lon2);
-          rh.Inverse(lat1, lon1, lat2, lon2, s12, azi12);
+          rh.Inverse(lat1, lon1, lat2, lon2, s12, azi12, S12);
           *output << AzimuthString(azi12, prec, dms, dmssep) << " "
-                  << Utility::str(s12, prec) << "\n";
-        }
-        catch (const std::exception& e) {
-          // Write error message cout so output lines match input lines
-          *output << "ERROR: " << e.what() << "\n";
-          retval = 1;
-        }
-      }
-    } else {
-      while (std::getline(*input, s)) {
-        try {
-          std::istringstream str(s);
+                  << Utility::str(s12, prec) << " "
+                  << Utility::str(S12, std::max(prec-7, 0)) << eol;
+        } else {                // direct
           std::string slat1, slon1, sazi;
           if (!(str >> slat1 >> slon1 >> sazi >> s12))
             throw GeographicErr("Incomplete input: " + s);
@@ -226,15 +219,16 @@ int main(int argc, char* argv[]) {
             throw GeographicErr("Extraneous input: " + strc);
           DMS::DecodeLatLon(slat1, slon1, lat1, lon1);
           azi12 = DMS::DecodeAzimuth(sazi);
-          rh.Direct(lat1, lon1, azi12, s12, lat2, lon2);
-          *output << LatLonString(lat2, lon2, prec, dms, dmssep) << "\n";
-        }
-        catch (const std::exception& e) {
-          // Write error message cout so output lines match input lines
-          *output << "ERROR: " << e.what() << "\n";
-          retval = 1;
+          rh.Direct(lat1, lon1, azi12, s12, lat2, lon2, S12);
+          *output << LatLonString(lat2, lon2, prec, dms, dmssep) << " "
+                  << Utility::str(S12, std::max(prec-7, 0)) << eol;
         }
       }
+      catch (const std::exception& e) {
+        // Write error message cout so output lines match input lines
+        *output << "ERROR: " << e.what() << "\n";
+        retval = 1;
+      }
     }
     return retval;
   }
diff --git a/tools/TransverseMercatorProj.cpp b/tools/TransverseMercatorProj.cpp
index 8cfc0b4..24c5d96 100644
--- a/tools/TransverseMercatorProj.cpp
+++ b/tools/TransverseMercatorProj.cpp
@@ -6,14 +6,6 @@
  * under the MIT/X11 License.  For more information, see
  * http://geographiclib.sourceforge.net/
  *
- * Compile and link with
- *   g++ -g -O3 -I../include -I../man -o TransverseMercatorProj \
- *       TransverseMercatorProj.cpp \
- *       ../src/DMS.cpp \
- *       ../src/EllipticFunction.cpp \
- *       ../src/TransverseMercator.cpp \
- *       ../src/TransverseMercatorExact.cpp
- *
  * See the <a href="TransverseMercatorProj.1.html">man page</a> for usage
  * information.
  **********************************************************************/
diff --git a/tools/geographiclib-get-geoids.sh b/tools/geographiclib-get-geoids.sh
index e2f6365..13f506c 100644
--- a/tools/geographiclib-get-geoids.sh
+++ b/tools/geographiclib-get-geoids.sh
@@ -45,8 +45,6 @@ In addition you can specify
   good = same as best but substitute egm2008-2_5 for egm2008-1 to save
          on disk space
 
-If no name is specified then minimal is assumed.
-
 -p parentdir (default $DEFAULTDIR) specifies where the
 datasets should be stored.  The "Default $NAME path" listed when running
 
@@ -91,6 +89,10 @@ while getopts hp:fd c; do
     esac
 done
 shift `expr $OPTIND - 1`
+if test $# -eq 0; then
+    usage 1>&2;
+    exit 1
+fi
 
 test -d "$PARENTDIR"/$SUBDIR || mkdir -p "$PARENTDIR"/$SUBDIR 2> /dev/null
 if test ! -d "$PARENTDIR"/$SUBDIR; then
@@ -130,8 +132,6 @@ egm2008-2_5
 egm2008-1
 EOF
 
-test $# -eq 0 && set -- minimal
-
 while test $# -gt 0; do
     if grep "^$1\$" $TEMP/all > /dev/null; then
 	echo $1
diff --git a/tools/geographiclib-get-gravity.sh b/tools/geographiclib-get-gravity.sh
index 489bf95..d9534c3 100644
--- a/tools/geographiclib-get-gravity.sh
+++ b/tools/geographiclib-get-gravity.sh
@@ -36,8 +36,6 @@ In addition you can specify
   all = all of the supported gravity models
   minimal = egm96 wgs84
 
-If no name is specified then minimal is assumed.
-
 -p parentdir (default $DEFAULTDIR) specifies where the
 datasets should be stored.  The "Default $NAME path" listed when running
 
@@ -82,6 +80,10 @@ while getopts hp:fd c; do
     esac
 done
 shift `expr $OPTIND - 1`
+if test $# -eq 0; then
+    usage 1>&2;
+    exit 1
+fi
 
 test -d "$PARENTDIR"/$SUBDIR || mkdir -p "$PARENTDIR"/$SUBDIR 2> /dev/null
 if test ! -d "$PARENTDIR"/$SUBDIR; then
@@ -119,8 +121,6 @@ grs80
 wgs84
 EOF
 
-test $# -eq 0 && set -- minimal
-
 while test $# -gt 0; do
     if grep "^$1\$" $TEMP/all > /dev/null; then
 	echo $1
diff --git a/tools/geographiclib-get-magnetic.sh b/tools/geographiclib-get-magnetic.sh
index a34d846..75bbd01 100644
--- a/tools/geographiclib-get-magnetic.sh
+++ b/tools/geographiclib-get-magnetic.sh
@@ -34,8 +34,6 @@ In addition you can specify
   all = all of the supported magnetic models
   minimal = wmm2010 igrf11
 
-If no name is specified then minimal is assumed.
-
 -p parentdir (default $DEFAULTDIR) specifies where the
 datasets should be stored.  The "Default $NAME path" listed when running
 
@@ -79,6 +77,10 @@ while getopts hp:fd c; do
     esac
 done
 shift `expr $OPTIND - 1`
+if test $# -eq 0; then
+    usage 1>&2;
+    exit 1
+fi
 
 test -d "$PARENTDIR"/$SUBDIR || mkdir -p "$PARENTDIR"/$SUBDIR 2> /dev/null
 if test ! -d "$PARENTDIR"/$SUBDIR; then
@@ -114,8 +116,6 @@ emm2010
 igrf11
 EOF
 
-test $# -eq 0 && set -- minimal
-
 while test $# -gt 0; do
     if grep "^$1\$" $TEMP/all > /dev/null; then
 	echo $1

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/geographiclib.git



More information about the Pkg-grass-devel mailing list