ADD: new track message, Entity class and Position class
This commit is contained in:
21
libs/geographiclib/tools/.gitignore
vendored
Normal file
21
libs/geographiclib/tools/.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
.deps
|
||||
.libs
|
||||
Makefile.in
|
||||
Makefile
|
||||
TAGS
|
||||
CMakeFiles
|
||||
cmake_install.cmake
|
||||
geographiclib-get-geoids
|
||||
geographiclib-get-gravity
|
||||
geographiclib-get-magnetic
|
||||
*.log
|
||||
CartConvert
|
||||
ConicProj
|
||||
GeoConvert
|
||||
GeodSolve
|
||||
GeodesicProj
|
||||
GeoidEval
|
||||
Gravity
|
||||
MagneticField
|
||||
Planimeter
|
||||
TransverseMercatorProj
|
||||
79
libs/geographiclib/tools/CMakeLists.txt
Normal file
79
libs/geographiclib/tools/CMakeLists.txt
Normal file
@@ -0,0 +1,79 @@
|
||||
# Build the tools...
|
||||
|
||||
# Where to find the *.usage files for the --help option.
|
||||
if (RELEASE)
|
||||
set (MANDIR ${PROJECT_SOURCE_DIR}/man)
|
||||
else ()
|
||||
set (MANDIR ${PROJECT_BINARY_DIR}/man)
|
||||
endif ()
|
||||
include_directories (${MANDIR})
|
||||
|
||||
# Only needed if target_compile_definitions is not supported
|
||||
add_definitions (${PROJECT_DEFINITIONS})
|
||||
|
||||
# Loop over all the tools, specifying the source and library.
|
||||
add_custom_target (tools ALL)
|
||||
foreach (TOOL ${TOOLS})
|
||||
|
||||
add_executable (${TOOL} ${TOOL}.cpp)
|
||||
if (NOT RELEASE)
|
||||
add_dependencies (${TOOL} usage)
|
||||
endif ()
|
||||
add_dependencies (tools ${TOOL})
|
||||
|
||||
set_source_files_properties (${TOOL}.cpp PROPERTIES
|
||||
OBJECT_DEPENDS ${MANDIR}/${TOOL}.usage)
|
||||
|
||||
target_link_libraries (${TOOL} ${PROJECT_LIBRARIES} ${HIGHPREC_LIBRARIES})
|
||||
|
||||
endforeach ()
|
||||
|
||||
if (MSVC OR CMAKE_CONFIGURATION_TYPES)
|
||||
# Add _d suffix for your debug versions of the tools
|
||||
set_target_properties (${TOOLS} PROPERTIES
|
||||
DEBUG_POSTFIX "${CMAKE_DEBUG_POSTFIX}")
|
||||
endif ()
|
||||
|
||||
if (APPLE AND RELATIVE_LIBDIR)
|
||||
# Ensure that the package is relocatable
|
||||
set_target_properties (${TOOLS} PROPERTIES
|
||||
INSTALL_RPATH "@loader_path/${RELATIVE_LIBDIR}")
|
||||
endif ()
|
||||
|
||||
# Specify where the tools are installed, adding them to the export targets
|
||||
if (BINDIR)
|
||||
install (TARGETS ${TOOLS} EXPORT targets DESTINATION ${BINDIR})
|
||||
endif ()
|
||||
|
||||
if (MSVC AND PACKAGE_DEBUG_LIBS)
|
||||
# Possibly don't EXPORT the debug versions of the tools and then this
|
||||
# wouldn't be necessary. However, including the debug versions of the
|
||||
# tools in the installer package is innocuous.
|
||||
foreach (TOOL ${TOOLS})
|
||||
install (PROGRAMS
|
||||
"${PROJECT_BINARY_DIR}/bin/Debug/${TOOL}${CMAKE_DEBUG_POSTFIX}.exe"
|
||||
DESTINATION bin CONFIGURATIONS Release)
|
||||
endforeach ()
|
||||
endif ()
|
||||
|
||||
# Put all the tools into a folder in the IDE
|
||||
set_property (TARGET tools ${TOOLS} PROPERTY FOLDER tools)
|
||||
|
||||
# Create the scripts for downloading the data files on non-Windows
|
||||
# systems. This needs to substitute ${GEOGRAPHICLIB_DATA} as the
|
||||
# default data directory. These are installed under sbin, because it is
|
||||
# expected to be run with write access to /usr/local.
|
||||
if (NOT CMAKE_HOST_WIN32)
|
||||
foreach (SCRIPT ${SCRIPTS})
|
||||
configure_file (${SCRIPT}.sh scripts/${SCRIPT} @ONLY)
|
||||
add_custom_command (OUTPUT ${SCRIPT}
|
||||
COMMAND ${CMAKE_COMMAND} -E
|
||||
copy scripts/${SCRIPT} ${SCRIPT} && chmod +x ${SCRIPT}
|
||||
DEPENDS ${SCRIPT}.sh)
|
||||
if (SBINDIR)
|
||||
install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${SCRIPT}
|
||||
DESTINATION ${SBINDIR})
|
||||
endif ()
|
||||
endforeach ()
|
||||
add_custom_target (scripts ALL DEPENDS ${SCRIPTS})
|
||||
endif ()
|
||||
213
libs/geographiclib/tools/CartConvert.cpp
Normal file
213
libs/geographiclib/tools/CartConvert.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
* \file CartConvert.cpp
|
||||
* \brief Command line utility for geodetic to cartesian coordinate conversions
|
||||
*
|
||||
* Copyright (c) Charles Karney (2009-2017) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="CartConvert.1.html">man page</a> for usage information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <GeographicLib/Geocentric.hpp>
|
||||
#include <GeographicLib/LocalCartesian.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional expressions and potentially
|
||||
// uninitialized local variables
|
||||
# pragma warning (disable: 4127 4701)
|
||||
#endif
|
||||
|
||||
#include "CartConvert.usage"
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
using namespace GeographicLib;
|
||||
typedef Math::real real;
|
||||
Utility::set_digits();
|
||||
bool localcartesian = false, reverse = false, longfirst = false;
|
||||
real
|
||||
a = Constants::WGS84_a(),
|
||||
f = Constants::WGS84_f();
|
||||
int prec = 6;
|
||||
real lat0 = 0, lon0 = 0, h0 = 0;
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';';
|
||||
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-r")
|
||||
reverse = true;
|
||||
else if (arg == "-l") {
|
||||
localcartesian = true;
|
||||
if (m + 3 >= argc) return usage(1, true);
|
||||
try {
|
||||
DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
|
||||
lat0, lon0, longfirst);
|
||||
h0 = Utility::val<real>(std::string(argv[m + 3]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -l: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 3;
|
||||
} else if (arg == "-e") {
|
||||
if (m + 2 >= argc) return usage(1, true);
|
||||
try {
|
||||
a = Utility::val<real>(std::string(argv[m + 1]));
|
||||
f = Utility::fract<real>(std::string(argv[m + 2]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 2;
|
||||
} else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-p") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
prec = Utility::val<int>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
return 0;
|
||||
} else
|
||||
return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
|
||||
|
||||
const Geocentric ec(a, f);
|
||||
const LocalCartesian lc(lat0, lon0, h0, ec);
|
||||
|
||||
// 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));
|
||||
std::string s, eol, stra, strb, strc, strd;
|
||||
std::istringstream str;
|
||||
int retval = 0;
|
||||
while (std::getline(*input, s)) {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
str.clear(); str.str(s);
|
||||
// initial values to suppress warnings
|
||||
real lat, lon, h, x = 0, y = 0, z = 0;
|
||||
if (!(str >> stra >> strb >> strc))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
if (reverse) {
|
||||
x = Utility::val<real>(stra);
|
||||
y = Utility::val<real>(strb);
|
||||
z = Utility::val<real>(strc);
|
||||
} else {
|
||||
DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
|
||||
h = Utility::val<real>(strc);
|
||||
}
|
||||
if (str >> strd)
|
||||
throw GeographicErr("Extraneous input: " + strd);
|
||||
if (reverse) {
|
||||
if (localcartesian)
|
||||
lc.Reverse(x, y, z, lat, lon, h);
|
||||
else
|
||||
ec.Reverse(x, y, z, lat, lon, h);
|
||||
*output << Utility::str(longfirst ? lon : lat, prec + 5) << " "
|
||||
<< Utility::str(longfirst ? lat : lon, prec + 5) << " "
|
||||
<< Utility::str(h, prec) << eol;
|
||||
} else {
|
||||
if (localcartesian)
|
||||
lc.Forward(lat, lon, h, x, y, z);
|
||||
else
|
||||
ec.Forward(lat, lon, h, x, y, z);
|
||||
*output << Utility::str(x, prec) << " "
|
||||
<< Utility::str(y, prec) << " "
|
||||
<< Utility::str(z, prec) << eol;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
*output << "ERROR: " << e.what() << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
249
libs/geographiclib/tools/ConicProj.cpp
Normal file
249
libs/geographiclib/tools/ConicProj.cpp
Normal file
@@ -0,0 +1,249 @@
|
||||
/**
|
||||
* \file ConicProj.cpp
|
||||
* \brief Command line utility for conical projections
|
||||
*
|
||||
* Copyright (c) Charles Karney (2009-2017) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="ConicProj.1.html">man page</a> for usage information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <GeographicLib/LambertConformalConic.hpp>
|
||||
#include <GeographicLib/AlbersEqualArea.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional expressions and potentially
|
||||
// uninitialized local variables
|
||||
# pragma warning (disable: 4127 4701)
|
||||
#endif
|
||||
|
||||
#include "ConicProj.usage"
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
using namespace GeographicLib;
|
||||
typedef Math::real real;
|
||||
Utility::set_digits();
|
||||
bool lcc = false, albers = false, reverse = false, longfirst = false;
|
||||
real lat1 = 0, lat2 = 0, lon0 = 0, k1 = 1;
|
||||
real
|
||||
a = Constants::WGS84_a(),
|
||||
f = Constants::WGS84_f();
|
||||
int prec = 6;
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';';
|
||||
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-r")
|
||||
reverse = true;
|
||||
else if (arg == "-c" || arg == "-a") {
|
||||
lcc = arg == "-c";
|
||||
albers = arg == "-a";
|
||||
if (m + 2 >= argc) return usage(1, true);
|
||||
try {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
DMS::flag ind;
|
||||
(i ? lat2 : lat1) = DMS::Decode(std::string(argv[++m]), ind);
|
||||
if (ind == DMS::LONGITUDE)
|
||||
throw GeographicErr("Bad hemisphere");
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-l") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
DMS::flag ind;
|
||||
lon0 = DMS::Decode(std::string(argv[m]), ind);
|
||||
if (ind == DMS::LATITUDE)
|
||||
throw GeographicErr("Bad hemisphere");
|
||||
lon0 = Math::AngNormalize(lon0);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding argument of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-k") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
k1 = Utility::val<real>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding argument of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-e") {
|
||||
if (m + 2 >= argc) return usage(1, true);
|
||||
try {
|
||||
a = Utility::val<real>(std::string(argv[m + 1]));
|
||||
f = Utility::fract<real>(std::string(argv[m + 2]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 2;
|
||||
} else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-p") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
prec = Utility::val<int>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
return 0;
|
||||
} else
|
||||
return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
|
||||
|
||||
if (!(lcc || albers)) {
|
||||
std::cerr << "Must specify \"-c lat1 lat2\" or "
|
||||
<< "\"-a lat1 lat2\"\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const LambertConformalConic lproj =
|
||||
lcc ? LambertConformalConic(a, f, lat1, lat2, k1)
|
||||
: LambertConformalConic(1, 0, 0, 0, 1);
|
||||
const AlbersEqualArea aproj =
|
||||
albers ? AlbersEqualArea(a, f, lat1, lat2, k1)
|
||||
: AlbersEqualArea(1, 0, 0, 0, 1);
|
||||
|
||||
// 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));
|
||||
std::string s, eol, stra, strb, strc;
|
||||
std::istringstream str;
|
||||
int retval = 0;
|
||||
while (std::getline(*input, s)) {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
str.clear(); str.str(s);
|
||||
real lat, lon, x, y, gamma, k;
|
||||
if (!(str >> stra >> strb))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
if (reverse) {
|
||||
x = Utility::val<real>(stra);
|
||||
y = Utility::val<real>(strb);
|
||||
} else
|
||||
DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
|
||||
if (str >> strc)
|
||||
throw GeographicErr("Extraneous input: " + strc);
|
||||
if (reverse) {
|
||||
if (lcc)
|
||||
lproj.Reverse(lon0, x, y, lat, lon, gamma, k);
|
||||
else
|
||||
aproj.Reverse(lon0, x, y, lat, lon, gamma, k);
|
||||
*output << Utility::str(longfirst ? lon : lat, prec + 5) << " "
|
||||
<< Utility::str(longfirst ? lat : lon, prec + 5) << " "
|
||||
<< Utility::str(gamma, prec + 6) << " "
|
||||
<< Utility::str(k, prec + 6) << eol;
|
||||
} else {
|
||||
if (lcc)
|
||||
lproj.Forward(lon0, lat, lon, x, y, gamma, k);
|
||||
else
|
||||
aproj.Forward(lon0, lat, lon, x, y, gamma, k);
|
||||
*output << Utility::str(x, prec) << " "
|
||||
<< Utility::str(y, prec) << " "
|
||||
<< Utility::str(gamma, prec + 6) << " "
|
||||
<< Utility::str(k, prec + 6) << eol;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
*output << "ERROR: " << e.what() << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
245
libs/geographiclib/tools/GeoConvert.cpp
Normal file
245
libs/geographiclib/tools/GeoConvert.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
/**
|
||||
* \file GeoConvert.cpp
|
||||
* \brief Command line utility for geographic coordinate conversions
|
||||
*
|
||||
* Copyright (c) Charles Karney (2008-2017) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="GeoConvert.1.html">man page</a> for usage information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <GeographicLib/GeoCoords.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
#include <GeographicLib/MGRS.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional expressions
|
||||
# pragma warning (disable: 4127)
|
||||
#endif
|
||||
|
||||
#include "GeoConvert.usage"
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
using namespace GeographicLib;
|
||||
typedef Math::real real;
|
||||
Utility::set_digits();
|
||||
enum { GEOGRAPHIC, DMS, UTMUPS, MGRS, CONVERGENCE };
|
||||
int outputmode = GEOGRAPHIC;
|
||||
int prec = 0;
|
||||
int zone = UTMUPS::MATCH;
|
||||
bool centerp = true, longfirst = false;
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';', dmssep = char(0);
|
||||
bool sethemisphere = false, northp = false, abbrev = true, latch = false;
|
||||
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-g")
|
||||
outputmode = GEOGRAPHIC;
|
||||
else if (arg == "-d") {
|
||||
outputmode = DMS;
|
||||
dmssep = '\0';
|
||||
} else if (arg == "-:") {
|
||||
outputmode = DMS;
|
||||
dmssep = ':';
|
||||
} else if (arg == "-u")
|
||||
outputmode = UTMUPS;
|
||||
else if (arg == "-m")
|
||||
outputmode = MGRS;
|
||||
else if (arg == "-c")
|
||||
outputmode = CONVERGENCE;
|
||||
else if (arg == "-n")
|
||||
centerp = false;
|
||||
else if (arg == "-z") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
std::string zonestr(argv[m]);
|
||||
try {
|
||||
UTMUPS::DecodeZone(zonestr, zone, northp);
|
||||
sethemisphere = true;
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::istringstream str(zonestr);
|
||||
char c;
|
||||
if (!(str >> zone) || (str >> c)) {
|
||||
std::cerr << "Zone " << zonestr
|
||||
<< " is not a number or zone+hemisphere\n";
|
||||
return 1;
|
||||
}
|
||||
if (!(zone >= UTMUPS::MINZONE && zone <= UTMUPS::MAXZONE)) {
|
||||
std::cerr << "Zone " << zone << " not in [0, 60]\n";
|
||||
return 1;
|
||||
}
|
||||
sethemisphere = false;
|
||||
}
|
||||
latch = false;
|
||||
} else if (arg == "-s") {
|
||||
zone = UTMUPS::STANDARD;
|
||||
sethemisphere = false;
|
||||
latch = false;
|
||||
} else if (arg == "-S") {
|
||||
zone = UTMUPS::STANDARD;
|
||||
sethemisphere = false;
|
||||
latch = true;
|
||||
} else if (arg == "-t") {
|
||||
zone = UTMUPS::UTM;
|
||||
sethemisphere = false;
|
||||
latch = false;
|
||||
} else if (arg == "-T") {
|
||||
zone = UTMUPS::UTM;
|
||||
sethemisphere = false;
|
||||
latch = true;
|
||||
} else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-p") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
prec = Utility::val<int>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-l")
|
||||
abbrev = false;
|
||||
else if (arg == "-a")
|
||||
abbrev = true;
|
||||
else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
MGRS::Check();
|
||||
return 0;
|
||||
} else
|
||||
return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
|
||||
|
||||
GeoCoords p;
|
||||
std::string s, eol;
|
||||
std::string os;
|
||||
int retval = 0;
|
||||
|
||||
while (std::getline(*input, s)) {
|
||||
eol = "\n";
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
p.Reset(s, centerp, longfirst);
|
||||
p.SetAltZone(zone);
|
||||
switch (outputmode) {
|
||||
case GEOGRAPHIC:
|
||||
os = p.GeoRepresentation(prec, longfirst);
|
||||
break;
|
||||
case DMS:
|
||||
os = p.DMSRepresentation(prec, longfirst, dmssep);
|
||||
break;
|
||||
case UTMUPS:
|
||||
os = (sethemisphere
|
||||
? p.AltUTMUPSRepresentation(northp, prec, abbrev)
|
||||
: p.AltUTMUPSRepresentation(prec, abbrev));
|
||||
break;
|
||||
case MGRS:
|
||||
os = p.AltMGRSRepresentation(prec);
|
||||
break;
|
||||
case CONVERGENCE:
|
||||
{
|
||||
real
|
||||
gamma = p.AltConvergence(),
|
||||
k = p.AltScale();
|
||||
int prec1 = std::max(-5, std::min(Math::extra_digits() + 8, prec));
|
||||
os = Utility::str(gamma, prec1 + 5) + " "
|
||||
+ Utility::str(k, prec1 + 7);
|
||||
}
|
||||
}
|
||||
if (latch &&
|
||||
zone < UTMUPS::MINZONE && p.AltZone() >= UTMUPS::MINZONE) {
|
||||
zone = p.AltZone();
|
||||
northp = p.Northp();
|
||||
sethemisphere = true;
|
||||
latch = false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
// Write error message to cout so output lines match input lines
|
||||
os = std::string("ERROR: ") + e.what();
|
||||
retval = 1;
|
||||
}
|
||||
*output << os << eol;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
406
libs/geographiclib/tools/GeodSolve.cpp
Normal file
406
libs/geographiclib/tools/GeodSolve.cpp
Normal file
@@ -0,0 +1,406 @@
|
||||
/**
|
||||
* \file GeodSolve.cpp
|
||||
* \brief Command line utility for geodesic calculations
|
||||
*
|
||||
* Copyright (c) Charles Karney (2009-2019) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="GeodSolve.1.html">man page</a> for usage information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <GeographicLib/Geodesic.hpp>
|
||||
#include <GeographicLib/GeodesicLine.hpp>
|
||||
#include <GeographicLib/GeodesicExact.hpp>
|
||||
#include <GeographicLib/GeodesicLineExact.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional expressions and potentially
|
||||
// uninitialized local variables
|
||||
# pragma warning (disable: 4127 4701)
|
||||
#endif
|
||||
|
||||
#include "GeodSolve.usage"
|
||||
|
||||
typedef GeographicLib::Math::real real;
|
||||
|
||||
std::string LatLonString(real lat, real lon, int prec, bool dms, char dmssep,
|
||||
bool longfirst) {
|
||||
using namespace GeographicLib;
|
||||
std::string
|
||||
latstr = dms ? DMS::Encode(lat, prec + 5, DMS::LATITUDE, dmssep) :
|
||||
DMS::Encode(lat, prec + 5, DMS::NUMBER),
|
||||
lonstr = dms ? DMS::Encode(lon, prec + 5, DMS::LONGITUDE, dmssep) :
|
||||
DMS::Encode(lon, prec + 5, DMS::NUMBER);
|
||||
return
|
||||
(longfirst ? lonstr : latstr) + " " + (longfirst ? latstr : lonstr);
|
||||
}
|
||||
|
||||
std::string AzimuthString(real azi, int prec, bool dms, char dmssep) {
|
||||
using namespace GeographicLib;
|
||||
return dms ? DMS::Encode(azi, prec + 5, DMS::AZIMUTH, dmssep) :
|
||||
DMS::Encode(azi, prec + 5, DMS::NUMBER);
|
||||
}
|
||||
|
||||
std::string DistanceStrings(real s12, real a12,
|
||||
bool full, bool arcmode, int prec, bool dms) {
|
||||
using namespace GeographicLib;
|
||||
std::string s;
|
||||
if (full || !arcmode)
|
||||
s += Utility::str(s12, prec);
|
||||
if (full)
|
||||
s += " ";
|
||||
if (full || arcmode)
|
||||
s += DMS::Encode(a12, prec + 5, dms ? DMS::NONE : DMS::NUMBER);
|
||||
return s;
|
||||
}
|
||||
|
||||
real ReadDistance(const std::string& s, bool arcmode, bool fraction = false) {
|
||||
using namespace GeographicLib;
|
||||
return fraction ? Utility::fract<real>(s) :
|
||||
(arcmode ? DMS::DecodeAngle(s) : Utility::val<real>(s));
|
||||
}
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
using namespace GeographicLib;
|
||||
enum { NONE = 0, LINE, DIRECT, INVERSE };
|
||||
Utility::set_digits();
|
||||
bool inverse = false, arcmode = false,
|
||||
dms = false, full = false, exact = false, unroll = false,
|
||||
longfirst = false, azi2back = false, fraction = false,
|
||||
arcmodeline = false;
|
||||
real
|
||||
a = Constants::WGS84_a(),
|
||||
f = Constants::WGS84_f();
|
||||
real lat1, lon1, azi1, lat2, lon2, azi2, s12, m12, a12, M12, M21, S12,
|
||||
mult = 1;
|
||||
int linecalc = NONE, prec = 3;
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';', dmssep = char(0);
|
||||
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-i") {
|
||||
inverse = true;
|
||||
linecalc = NONE;
|
||||
} else if (arg == "-a")
|
||||
arcmode = !arcmode;
|
||||
else if (arg == "-F")
|
||||
fraction = true;
|
||||
else if (arg == "-L" || arg == "-l") { // -l is DEPRECATED
|
||||
inverse = false;
|
||||
linecalc = LINE;
|
||||
if (m + 3 >= argc) return usage(1, true);
|
||||
try {
|
||||
DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
|
||||
lat1, lon1, longfirst);
|
||||
azi1 = DMS::DecodeAzimuth(std::string(argv[m + 3]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -L: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 3;
|
||||
} else if (arg == "-D") {
|
||||
inverse = false;
|
||||
linecalc = DIRECT;
|
||||
if (m + 4 >= argc) return usage(1, true);
|
||||
try {
|
||||
DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
|
||||
lat1, lon1, longfirst);
|
||||
azi1 = DMS::DecodeAzimuth(std::string(argv[m + 3]));
|
||||
s12 = ReadDistance(std::string(argv[m + 4]), arcmode);
|
||||
arcmodeline = arcmode;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -D: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 4;
|
||||
} else if (arg == "-I") {
|
||||
inverse = false;
|
||||
linecalc = INVERSE;
|
||||
if (m + 4 >= argc) return usage(1, true);
|
||||
try {
|
||||
DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
|
||||
lat1, lon1, longfirst);
|
||||
DMS::DecodeLatLon(std::string(argv[m + 3]), std::string(argv[m + 4]),
|
||||
lat2, lon2, longfirst);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -I: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 4;
|
||||
} else if (arg == "-e") {
|
||||
if (m + 2 >= argc) return usage(1, true);
|
||||
try {
|
||||
a = Utility::val<real>(std::string(argv[m + 1]));
|
||||
f = Utility::fract<real>(std::string(argv[m + 2]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 2;
|
||||
} else if (arg == "-u")
|
||||
unroll = true;
|
||||
else if (arg == "-d") {
|
||||
dms = true;
|
||||
dmssep = '\0';
|
||||
} else if (arg == "-:") {
|
||||
dms = true;
|
||||
dmssep = ':';
|
||||
} else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-b")
|
||||
azi2back = true;
|
||||
else if (arg == "-f")
|
||||
full = true;
|
||||
else if (arg == "-p") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
prec = Utility::val<int>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-E")
|
||||
exact = true;
|
||||
else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
return 0;
|
||||
} else
|
||||
return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
|
||||
|
||||
// GeodesicExact mask values are the same as Geodesic
|
||||
unsigned outmask = Geodesic::LATITUDE | Geodesic::LONGITUDE |
|
||||
Geodesic::AZIMUTH; // basic output quantities
|
||||
outmask |= inverse ? Geodesic::DISTANCE : // distance-related flags
|
||||
(arcmode ? Geodesic::NONE : Geodesic::DISTANCE_IN);
|
||||
// longitude unrolling
|
||||
outmask |= unroll ? Geodesic::LONG_UNROLL : Geodesic::NONE;
|
||||
// full output -- don't use Geodesic::ALL since this includes DISTANCE_IN
|
||||
outmask |= full ? (Geodesic::DISTANCE | Geodesic::REDUCEDLENGTH |
|
||||
Geodesic::GEODESICSCALE | Geodesic::AREA) :
|
||||
Geodesic::NONE;
|
||||
|
||||
const Geodesic geods(a, f);
|
||||
const GeodesicExact geode(a, f);
|
||||
GeodesicLine ls;
|
||||
GeodesicLineExact le;
|
||||
if (linecalc) {
|
||||
if (linecalc == LINE) fraction = false;
|
||||
if (exact) {
|
||||
le = linecalc == DIRECT ?
|
||||
geode.GenDirectLine(lat1, lon1, azi1, arcmodeline, s12, outmask) :
|
||||
linecalc == INVERSE ?
|
||||
geode.InverseLine(lat1, lon1, lat2, lon2, outmask) :
|
||||
// linecalc == LINE
|
||||
geode.Line(lat1, lon1, azi1, outmask);
|
||||
mult = fraction ? le.GenDistance(arcmode) : 1;
|
||||
if (linecalc == INVERSE) azi1 = le.Azimuth();
|
||||
} else {
|
||||
ls = linecalc == DIRECT ?
|
||||
geods.GenDirectLine(lat1, lon1, azi1, arcmodeline, s12, outmask) :
|
||||
linecalc == INVERSE ?
|
||||
geods.InverseLine(lat1, lon1, lat2, lon2, outmask) :
|
||||
// linecalc == LINE
|
||||
geods.Line(lat1, lon1, azi1, outmask);
|
||||
mult = fraction ? ls.GenDistance(arcmode) : 1;
|
||||
if (linecalc == INVERSE) azi1 = ls.Azimuth();
|
||||
}
|
||||
}
|
||||
|
||||
// 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));
|
||||
std::string s, eol, slat1, slon1, slat2, slon2, sazi1, ss12, strc;
|
||||
std::istringstream str;
|
||||
int retval = 0;
|
||||
while (std::getline(*input, s)) {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
str.clear(); str.str(s);
|
||||
if (inverse) {
|
||||
if (!(str >> slat1 >> slon1 >> slat2 >> slon2))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
if (str >> strc)
|
||||
throw GeographicErr("Extraneous input: " + strc);
|
||||
DMS::DecodeLatLon(slat1, slon1, lat1, lon1, longfirst);
|
||||
DMS::DecodeLatLon(slat2, slon2, lat2, lon2, longfirst);
|
||||
a12 = exact ?
|
||||
geode.GenInverse(lat1, lon1, lat2, lon2, outmask,
|
||||
s12, azi1, azi2, m12, M12, M21, S12) :
|
||||
geods.GenInverse(lat1, lon1, lat2, lon2, outmask,
|
||||
s12, azi1, azi2, m12, M12, M21, S12);
|
||||
if (full) {
|
||||
if (unroll) {
|
||||
real e;
|
||||
lon2 = lon1 + Math::AngDiff(lon1, lon2, e);
|
||||
lon2 += e;
|
||||
} else {
|
||||
lon1 = Math::AngNormalize(lon1);
|
||||
lon2 = Math::AngNormalize(lon2);
|
||||
}
|
||||
*output << LatLonString(lat1, lon1, prec, dms, dmssep, longfirst)
|
||||
<< " ";
|
||||
}
|
||||
*output << AzimuthString(azi1, prec, dms, dmssep) << " ";
|
||||
if (full)
|
||||
*output << LatLonString(lat2, lon2, prec, dms, dmssep, longfirst)
|
||||
<< " ";
|
||||
if (azi2back) {
|
||||
using std::copysign;
|
||||
// map +/-0 -> -/+180; +/-180 -> -/+0
|
||||
// this depends on abs(azi2) <= 180
|
||||
azi2 = copysign(azi2 + copysign(real(Math::hd), -azi2), -azi2);
|
||||
}
|
||||
*output << AzimuthString(azi2, prec, dms, dmssep) << " "
|
||||
<< DistanceStrings(s12, a12, full, arcmode, prec, dms);
|
||||
if (full)
|
||||
*output << " " << Utility::str(m12, prec)
|
||||
<< " " << Utility::str(M12, prec+7)
|
||||
<< " " << Utility::str(M21, prec+7)
|
||||
<< " " << Utility::str(S12, std::max(prec-7, 0));
|
||||
*output << eol;
|
||||
} else {
|
||||
if (linecalc) {
|
||||
if (!(str >> ss12))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
if (str >> strc)
|
||||
throw GeographicErr("Extraneous input: " + strc);
|
||||
// In fraction mode input is read as a distance
|
||||
s12 = ReadDistance(ss12, !fraction && arcmode, fraction) * mult;
|
||||
a12 = exact ?
|
||||
le.GenPosition(arcmode, s12, outmask,
|
||||
lat2, lon2, azi2, s12, m12, M12, M21, S12) :
|
||||
ls.GenPosition(arcmode, s12, outmask,
|
||||
lat2, lon2, azi2, s12, m12, M12, M21, S12);
|
||||
} else {
|
||||
if (!(str >> slat1 >> slon1 >> sazi1 >> ss12))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
if (str >> strc)
|
||||
throw GeographicErr("Extraneous input: " + strc);
|
||||
DMS::DecodeLatLon(slat1, slon1, lat1, lon1, longfirst);
|
||||
azi1 = DMS::DecodeAzimuth(sazi1);
|
||||
s12 = ReadDistance(ss12, arcmode);
|
||||
a12 = exact ?
|
||||
geode.GenDirect(lat1, lon1, azi1, arcmode, s12, outmask,
|
||||
lat2, lon2, azi2, s12, m12, M12, M21, S12) :
|
||||
geods.GenDirect(lat1, lon1, azi1, arcmode, s12, outmask,
|
||||
lat2, lon2, azi2, s12, m12, M12, M21, S12);
|
||||
}
|
||||
if (full)
|
||||
*output
|
||||
<< LatLonString(lat1, unroll ? lon1 : Math::AngNormalize(lon1),
|
||||
prec, dms, dmssep, longfirst)
|
||||
<< " " << AzimuthString(azi1, prec, dms, dmssep) << " ";
|
||||
if (azi2back) {
|
||||
using std::copysign;
|
||||
// map +/-0 -> -/+180; +/-180 -> -/+0
|
||||
// this depends on abs(azi2) <= 180
|
||||
azi2 = copysign(azi2 + copysign(real(Math::hd), -azi2), -azi2);
|
||||
}
|
||||
*output << LatLonString(lat2, lon2, prec, dms, dmssep, longfirst)
|
||||
<< " " << AzimuthString(azi2, prec, dms, dmssep);
|
||||
if (full)
|
||||
*output << " "
|
||||
<< DistanceStrings(s12, a12, full, arcmode, prec, dms)
|
||||
<< " " << Utility::str(m12, prec)
|
||||
<< " " << Utility::str(M12, prec+7)
|
||||
<< " " << Utility::str(M21, prec+7)
|
||||
<< " " << Utility::str(S12, std::max(prec-7, 0));
|
||||
*output << 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;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
231
libs/geographiclib/tools/GeodesicProj.cpp
Normal file
231
libs/geographiclib/tools/GeodesicProj.cpp
Normal file
@@ -0,0 +1,231 @@
|
||||
/**
|
||||
* \file GeodesicProj.cpp
|
||||
* \brief Command line utility for geodesic projections
|
||||
*
|
||||
* Copyright (c) Charles Karney (2009-2017) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="GeodesicProj.1.html">man page</a> for usage information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <GeographicLib/Geodesic.hpp>
|
||||
#include <GeographicLib/AzimuthalEquidistant.hpp>
|
||||
#include <GeographicLib/CassiniSoldner.hpp>
|
||||
#include <GeographicLib/Gnomonic.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional expressions and potentially
|
||||
// uninitialized local variables
|
||||
# pragma warning (disable: 4127 4701)
|
||||
#endif
|
||||
|
||||
#include "GeodesicProj.usage"
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
using namespace GeographicLib;
|
||||
typedef Math::real real;
|
||||
Utility::set_digits();
|
||||
bool azimuthal = false, cassini = false, gnomonic = false, reverse = false,
|
||||
longfirst = false;
|
||||
real lat0 = 0, lon0 = 0;
|
||||
real
|
||||
a = Constants::WGS84_a(),
|
||||
f = Constants::WGS84_f();
|
||||
int prec = 6;
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';';
|
||||
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-r")
|
||||
reverse = true;
|
||||
else if (arg == "-c" || arg == "-z" || arg == "-g") {
|
||||
cassini = azimuthal = gnomonic = false;
|
||||
cassini = arg == "-c";
|
||||
azimuthal = arg == "-z";
|
||||
gnomonic = arg == "-g";
|
||||
if (m + 2 >= argc) return usage(1, true);
|
||||
try {
|
||||
DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
|
||||
lat0, lon0, longfirst);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 2;
|
||||
} else if (arg == "-e") {
|
||||
if (m + 2 >= argc) return usage(1, true);
|
||||
try {
|
||||
a = Utility::val<real>(std::string(argv[m + 1]));
|
||||
f = Utility::fract<real>(std::string(argv[m + 2]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 2;
|
||||
} else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-p") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
prec = Utility::val<int>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
return 0;
|
||||
} else
|
||||
return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
|
||||
|
||||
if (!(azimuthal || cassini || gnomonic)) {
|
||||
std::cerr << "Must specify \"-z lat0 lon0\" or "
|
||||
<< "\"-c lat0 lon0\" or \"-g lat0 lon0\"\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const Geodesic geod(a, f);
|
||||
const CassiniSoldner cs = cassini ?
|
||||
CassiniSoldner(lat0, lon0, geod) : CassiniSoldner(geod);
|
||||
const AzimuthalEquidistant az(geod);
|
||||
const Gnomonic gn(geod);
|
||||
|
||||
// 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));
|
||||
std::string s, eol, stra, strb, strc;
|
||||
std::istringstream str;
|
||||
int retval = 0;
|
||||
std::cout << std::fixed;
|
||||
while (std::getline(*input, s)) {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
str.clear(); str.str(s);
|
||||
real lat, lon, x, y, azi, rk;
|
||||
if (!(str >> stra >> strb))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
if (reverse) {
|
||||
x = Utility::val<real>(stra);
|
||||
y = Utility::val<real>(strb);
|
||||
} else
|
||||
DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
|
||||
if (str >> strc)
|
||||
throw GeographicErr("Extraneous input: " + strc);
|
||||
if (reverse) {
|
||||
if (cassini)
|
||||
cs.Reverse(x, y, lat, lon, azi, rk);
|
||||
else if (azimuthal)
|
||||
az.Reverse(lat0, lon0, x, y, lat, lon, azi, rk);
|
||||
else
|
||||
gn.Reverse(lat0, lon0, x, y, lat, lon, azi, rk);
|
||||
*output << Utility::str(longfirst ? lon : lat, prec + 5) << " "
|
||||
<< Utility::str(longfirst ? lat : lon, prec + 5) << " "
|
||||
<< Utility::str(azi, prec + 5) << " "
|
||||
<< Utility::str(rk, prec + 6) << eol;
|
||||
} else {
|
||||
if (cassini)
|
||||
cs.Forward(lat, lon, x, y, azi, rk);
|
||||
else if (azimuthal)
|
||||
az.Forward(lat0, lon0, lat, lon, x, y, azi, rk);
|
||||
else
|
||||
gn.Forward(lat0, lon0, lat, lon, x, y, azi, rk);
|
||||
*output << Utility::str(x, prec) << " "
|
||||
<< Utility::str(y, prec) << " "
|
||||
<< Utility::str(azi, prec + 5) << " "
|
||||
<< Utility::str(rk, prec + 6) << eol;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
*output << "ERROR: " << e.what() << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
279
libs/geographiclib/tools/GeoidEval.cpp
Normal file
279
libs/geographiclib/tools/GeoidEval.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
/**
|
||||
* \file GeoidEval.cpp
|
||||
* \brief Command line utility for evaluating geoid heights
|
||||
*
|
||||
* Copyright (c) Charles Karney (2009-2017) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="GeoidEval.1.html">man page</a> for usage information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <GeographicLib/Geoid.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
#include <GeographicLib/GeoCoords.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional expressions and potentially
|
||||
// uninitialized local variables
|
||||
# pragma warning (disable: 4127 4701)
|
||||
#endif
|
||||
|
||||
#include "GeoidEval.usage"
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
using namespace GeographicLib;
|
||||
typedef Math::real real;
|
||||
Utility::set_digits();
|
||||
bool cacheall = false, cachearea = false, verbose = false, cubic = true;
|
||||
real caches, cachew, cachen, cachee;
|
||||
std::string dir;
|
||||
std::string geoid = Geoid::DefaultGeoidName();
|
||||
Geoid::convertflag heightmult = Geoid::NONE;
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';';
|
||||
bool northp = false, longfirst = false;
|
||||
int zonenum = UTMUPS::INVALID;
|
||||
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-a") {
|
||||
cacheall = true;
|
||||
cachearea = false;
|
||||
}
|
||||
else if (arg == "-c") {
|
||||
if (m + 4 >= argc) return usage(1, true);
|
||||
cacheall = false;
|
||||
cachearea = true;
|
||||
try {
|
||||
DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
|
||||
caches, cachew, longfirst);
|
||||
DMS::DecodeLatLon(std::string(argv[m + 3]), std::string(argv[m + 4]),
|
||||
cachen, cachee, longfirst);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding argument of -c: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 4;
|
||||
} else if (arg == "--msltohae")
|
||||
heightmult = Geoid::GEOIDTOELLIPSOID;
|
||||
else if (arg == "--haetomsl")
|
||||
heightmult = Geoid::ELLIPSOIDTOGEOID;
|
||||
else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-z") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
std::string zone = argv[m];
|
||||
try {
|
||||
UTMUPS::DecodeZone(zone, zonenum, northp);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding zone: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
if (!(zonenum >= UTMUPS::MINZONE && zonenum <= UTMUPS::MAXZONE)) {
|
||||
std::cerr << "Illegal zone " << zone << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-n") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
geoid = argv[m];
|
||||
} else if (arg == "-d") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
dir = argv[m];
|
||||
} else if (arg == "-l")
|
||||
cubic = false;
|
||||
else if (arg == "-v")
|
||||
verbose = true;
|
||||
else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
return 0;
|
||||
} else {
|
||||
int retval = usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
if (arg == "-h")
|
||||
std::cout
|
||||
<< "\nDefault geoid path = \"" << Geoid::DefaultGeoidPath()
|
||||
<< "\"\nDefault geoid name = \"" << Geoid::DefaultGeoidName()
|
||||
<< "\"\n";
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
|
||||
|
||||
int retval = 0;
|
||||
try {
|
||||
const Geoid g(geoid, dir, cubic);
|
||||
try {
|
||||
if (cacheall)
|
||||
g.CacheAll();
|
||||
else if (cachearea)
|
||||
g.CacheArea(caches, cachew, cachen, cachee);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "ERROR: " << e.what() << "\nProceeding without a cache\n";
|
||||
}
|
||||
if (verbose) {
|
||||
std::cerr << "Geoid file: " << g.GeoidFile() << "\n"
|
||||
<< "Description: " << g.Description() << "\n"
|
||||
<< "Interpolation: " << g.Interpolation() << "\n"
|
||||
<< "Date & Time: " << g.DateTime() << "\n"
|
||||
<< "Offset (m): " << g.Offset() << "\n"
|
||||
<< "Scale (m): " << g.Scale() << "\n"
|
||||
<< "Max error (m): " << g.MaxError() << "\n"
|
||||
<< "RMS error (m): " << g.RMSError() << "\n";
|
||||
if (g.Cache())
|
||||
std::cerr
|
||||
<< "Caching:"
|
||||
<< "\n SW Corner: " << g.CacheSouth() << " " << g.CacheWest()
|
||||
<< "\n NE Corner: " << g.CacheNorth() << " " << g.CacheEast()
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
GeoCoords p;
|
||||
std::string s, eol, suff;
|
||||
const char* spaces = " \t\n\v\f\r,"; // Include comma as space
|
||||
while (std::getline(*input, s)) {
|
||||
try {
|
||||
eol = "\n";
|
||||
if (!cdelim.empty()) {
|
||||
std::string::size_type m = s.find(cdelim);
|
||||
if (m != std::string::npos) {
|
||||
eol = " " + s.substr(m) + "\n";
|
||||
std::string::size_type m1 =
|
||||
m > 0 ? s.find_last_not_of(spaces, m - 1) : std::string::npos;
|
||||
s = s.substr(0, m1 != std::string::npos ? m1 + 1 : m);
|
||||
}
|
||||
}
|
||||
real height = 0;
|
||||
if (zonenum != UTMUPS::INVALID) {
|
||||
// Expect "easting northing" if heightmult == 0, or
|
||||
// "easting northing height" if heightmult != 0.
|
||||
std::string::size_type pa = 0, pb = 0;
|
||||
real easting = 0, northing = 0;
|
||||
for (int i = 0; i < (heightmult ? 3 : 2); ++i) {
|
||||
if (pb == std::string::npos)
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
// Start of i'th token
|
||||
pa = s.find_first_not_of(spaces, pb);
|
||||
if (pa == std::string::npos)
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
// End of i'th token
|
||||
pb = s.find_first_of(spaces, pa);
|
||||
(i == 2 ? height : (i == 0 ? easting : northing)) =
|
||||
Utility::val<real>(s.substr(pa, (pb == std::string::npos ?
|
||||
pb : pb - pa)));
|
||||
}
|
||||
p.Reset(zonenum, northp, easting, northing);
|
||||
if (heightmult) {
|
||||
suff = pb == std::string::npos ? "" : s.substr(pb);
|
||||
s = s.substr(0, pa);
|
||||
}
|
||||
} else {
|
||||
if (heightmult) {
|
||||
// Treat last token as height
|
||||
// pb = last char of last token
|
||||
// pa = last char preceding white space
|
||||
// px = last char of 2nd last token
|
||||
std::string::size_type pb = s.find_last_not_of(spaces);
|
||||
std::string::size_type pa = s.find_last_of(spaces, pb);
|
||||
if (pa == std::string::npos || pb == std::string::npos)
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
height = Utility::val<real>(s.substr(pa + 1, pb - pa));
|
||||
s = s.substr(0, pa + 1);
|
||||
}
|
||||
p.Reset(s, true, longfirst);
|
||||
}
|
||||
if (heightmult) {
|
||||
real h = g(p.Latitude(), p.Longitude());
|
||||
*output << s
|
||||
<< Utility::str(height + real(heightmult) * h, 4)
|
||||
<< suff << eol;
|
||||
} else {
|
||||
real h = g(p.Latitude(), p.Longitude());
|
||||
*output << Utility::str(h, 4) << eol;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
*output << "ERROR: " << e.what() << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error reading " << geoid << ": " << e.what() << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
335
libs/geographiclib/tools/Gravity.cpp
Normal file
335
libs/geographiclib/tools/Gravity.cpp
Normal file
@@ -0,0 +1,335 @@
|
||||
/**
|
||||
* \file Gravity.cpp
|
||||
* \brief Command line utility for evaluating gravity fields
|
||||
*
|
||||
* Copyright (c) Charles Karney (2011-2022) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="Gravity.1.html">man page</a> for usage information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <GeographicLib/GravityModel.hpp>
|
||||
#include <GeographicLib/GravityCircle.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional and enum-float expressions
|
||||
// and potentially uninitialized local variables
|
||||
# pragma warning (disable: 4127 5055 4701)
|
||||
#endif
|
||||
|
||||
#include "Gravity.usage"
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
using namespace GeographicLib;
|
||||
typedef Math::real real;
|
||||
Utility::set_digits();
|
||||
bool verbose = false, longfirst = false;
|
||||
std::string dir;
|
||||
std::string model = GravityModel::DefaultGravityName();
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';';
|
||||
real lat = 0, h = 0;
|
||||
bool circle = false;
|
||||
int prec = -1, Nmax = -1, Mmax = -1;
|
||||
enum {
|
||||
GRAVITY = 0,
|
||||
DISTURBANCE = 1,
|
||||
ANOMALY = 2,
|
||||
UNDULATION = 3,
|
||||
};
|
||||
unsigned mode = GRAVITY;
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-n") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
model = argv[m];
|
||||
} else if (arg == "-d") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
dir = argv[m];
|
||||
} else if (arg == "-N") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
Nmax = Utility::val<int>(std::string(argv[m]));
|
||||
if (Nmax < 0) {
|
||||
std::cerr << "Maximum degree " << argv[m] << " is negative\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-M") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
Mmax = Utility::val<int>(std::string(argv[m]));
|
||||
if (Mmax < 0) {
|
||||
std::cerr << "Maximum order " << argv[m] << " is negative\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-G")
|
||||
mode = GRAVITY;
|
||||
else if (arg == "-D")
|
||||
mode = DISTURBANCE;
|
||||
else if (arg == "-A")
|
||||
mode = ANOMALY;
|
||||
else if (arg == "-H")
|
||||
mode = UNDULATION;
|
||||
else if (arg == "-c") {
|
||||
if (m + 2 >= argc) return usage(1, true);
|
||||
try {
|
||||
using std::fabs;
|
||||
DMS::flag ind;
|
||||
lat = DMS::Decode(std::string(argv[++m]), ind);
|
||||
if (ind == DMS::LONGITUDE)
|
||||
throw GeographicErr("Bad hemisphere letter on latitude");
|
||||
if (!(fabs(lat) <= Math::qd))
|
||||
throw GeographicErr("Latitude not in [-" + std::to_string(Math::qd)
|
||||
+ "d, " + std::to_string(Math::qd) + "d]");
|
||||
h = Utility::val<real>(std::string(argv[++m]));
|
||||
circle = true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding argument of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-p") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
prec = Utility::val<int>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-v")
|
||||
verbose = true;
|
||||
else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
return 0;
|
||||
} else {
|
||||
int retval = usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
if (arg == "-h")
|
||||
std::cout<< "\nDefault gravity path = \""
|
||||
<< GravityModel::DefaultGravityPath()
|
||||
<< "\"\nDefault gravity name = \""
|
||||
<< GravityModel::DefaultGravityName()
|
||||
<< "\"\n";
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
|
||||
|
||||
switch (mode) {
|
||||
case GRAVITY:
|
||||
prec = std::min(16 + Math::extra_digits(), prec < 0 ? 5 : prec);
|
||||
break;
|
||||
case DISTURBANCE:
|
||||
case ANOMALY:
|
||||
prec = std::min(14 + Math::extra_digits(), prec < 0 ? 3 : prec);
|
||||
break;
|
||||
case UNDULATION:
|
||||
default:
|
||||
prec = std::min(12 + Math::extra_digits(), prec < 0 ? 4 : prec);
|
||||
break;
|
||||
}
|
||||
int retval = 0;
|
||||
try {
|
||||
using std::isfinite;
|
||||
const GravityModel g(model, dir, Nmax, Mmax);
|
||||
if (circle) {
|
||||
if (!isfinite(h))
|
||||
throw GeographicErr("Bad height");
|
||||
else if (mode == UNDULATION && h != 0)
|
||||
throw GeographicErr("Height should be zero for geoid undulations");
|
||||
}
|
||||
if (verbose) {
|
||||
std::cerr << "Gravity file: " << g.GravityFile() << "\n"
|
||||
<< "Name: " << g.GravityModelName() << "\n"
|
||||
<< "Description: " << g.Description() << "\n"
|
||||
<< "Date & Time: " << g.DateTime() << "\n";
|
||||
}
|
||||
unsigned mask = (mode == GRAVITY ? GravityModel::GRAVITY :
|
||||
(mode == DISTURBANCE ? GravityModel::DISTURBANCE :
|
||||
(mode == ANOMALY ? GravityModel::SPHERICAL_ANOMALY :
|
||||
GravityModel::GEOID_HEIGHT))); // mode == UNDULATION
|
||||
const GravityCircle c(circle ? g.Circle(lat, h, mask) : GravityCircle());
|
||||
std::string s, eol, stra, strb;
|
||||
std::istringstream str;
|
||||
while (std::getline(*input, s)) {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
str.clear(); str.str(s);
|
||||
real lon;
|
||||
if (circle) {
|
||||
if (!(str >> strb))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
DMS::flag ind;
|
||||
lon = DMS::Decode(strb, ind);
|
||||
if (ind == DMS::LATITUDE)
|
||||
throw GeographicErr("Bad hemisphere letter on " + strb);
|
||||
} else {
|
||||
if (!(str >> stra >> strb))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
|
||||
h = 0;
|
||||
if (!(str >> h)) // h is optional
|
||||
str.clear();
|
||||
if (mode == UNDULATION && h != 0)
|
||||
throw GeographicErr("Height must be zero for geoid heights");
|
||||
}
|
||||
if (str >> stra)
|
||||
throw GeographicErr("Extra junk in input: " + s);
|
||||
switch (mode) {
|
||||
case GRAVITY:
|
||||
{
|
||||
real gx, gy, gz;
|
||||
if (circle) {
|
||||
c.Gravity(lon, gx, gy, gz);
|
||||
} else {
|
||||
g.Gravity(lat, lon, h, gx, gy, gz);
|
||||
}
|
||||
*output << Utility::str(gx, prec) << " "
|
||||
<< Utility::str(gy, prec) << " "
|
||||
<< Utility::str(gz, prec) << eol;
|
||||
}
|
||||
break;
|
||||
case DISTURBANCE:
|
||||
{
|
||||
real deltax, deltay, deltaz;
|
||||
if (circle) {
|
||||
c.Disturbance(lon, deltax, deltay, deltaz);
|
||||
} else {
|
||||
g.Disturbance(lat, lon, h, deltax, deltay, deltaz);
|
||||
}
|
||||
// Convert to mGals
|
||||
*output << Utility::str(deltax * 100000, prec) << " "
|
||||
<< Utility::str(deltay * 100000, prec) << " "
|
||||
<< Utility::str(deltaz * 100000, prec)
|
||||
<< eol;
|
||||
}
|
||||
break;
|
||||
case ANOMALY:
|
||||
{
|
||||
real Dg01, xi, eta;
|
||||
if (circle)
|
||||
c.SphericalAnomaly(lon, Dg01, xi, eta);
|
||||
else
|
||||
g.SphericalAnomaly(lat, lon, h, Dg01, xi, eta);
|
||||
Dg01 *= 100000; // Convert to mGals
|
||||
xi *= Math::ds; // Convert to arcsecs
|
||||
eta *= Math::ds;
|
||||
*output << Utility::str(Dg01, prec) << " "
|
||||
<< Utility::str(xi, prec) << " "
|
||||
<< Utility::str(eta, prec) << eol;
|
||||
}
|
||||
break;
|
||||
case UNDULATION:
|
||||
default:
|
||||
{
|
||||
real N = circle ? c.GeoidHeight(lon) : g.GeoidHeight(lat, lon);
|
||||
*output << Utility::str(N, prec) << eol;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
*output << "ERROR: " << e.what() << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error reading " << model << ": " << e.what() << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
367
libs/geographiclib/tools/MagneticField.cpp
Normal file
367
libs/geographiclib/tools/MagneticField.cpp
Normal file
@@ -0,0 +1,367 @@
|
||||
/**
|
||||
* \file MagneticField.cpp
|
||||
* \brief Command line utility for evaluating magnetic fields
|
||||
*
|
||||
* Copyright (c) Charles Karney (2011-2022) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="MagneticField.1.html">man page</a> for usage information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <GeographicLib/MagneticModel.hpp>
|
||||
#include <GeographicLib/MagneticCircle.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional and enum-float expressions
|
||||
# pragma warning (disable: 4127 5055)
|
||||
#endif
|
||||
|
||||
#include "MagneticField.usage"
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
using namespace GeographicLib;
|
||||
typedef Math::real real;
|
||||
Utility::set_digits();
|
||||
bool verbose = false, longfirst = false;
|
||||
std::string dir;
|
||||
std::string model = MagneticModel::DefaultMagneticName();
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';';
|
||||
real time = 0, lat = 0, h = 0;
|
||||
bool timeset = false, circle = false, rate = false;
|
||||
real hguard = 500000, tguard = 50;
|
||||
int prec = 1, Nmax = -1, Mmax = -1;
|
||||
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-n") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
model = argv[m];
|
||||
} else if (arg == "-d") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
dir = argv[m];
|
||||
} else if (arg == "-N") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
Nmax = Utility::val<int>(std::string(argv[m]));
|
||||
if (Nmax < 0) {
|
||||
std::cerr << "Maximum degree " << argv[m] << " is negative\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-M") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
Mmax = Utility::val<int>(std::string(argv[m]));
|
||||
if (Mmax < 0) {
|
||||
std::cerr << "Maximum order " << argv[m] << " is negative\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-t") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
time = Utility::fractionalyear<real>(std::string(argv[m]));
|
||||
timeset = true;
|
||||
circle = false;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding argument of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-c") {
|
||||
if (m + 3 >= argc) return usage(1, true);
|
||||
try {
|
||||
using std::fabs;
|
||||
time = Utility::fractionalyear<real>(std::string(argv[++m]));
|
||||
DMS::flag ind;
|
||||
lat = DMS::Decode(std::string(argv[++m]), ind);
|
||||
if (ind == DMS::LONGITUDE)
|
||||
throw GeographicErr("Bad hemisphere letter on latitude");
|
||||
if (!(fabs(lat) <= Math::qd))
|
||||
throw GeographicErr("Latitude not in [-" + std::to_string(Math::qd)
|
||||
+ "d, " + std::to_string(Math::qd) + "d]");
|
||||
h = Utility::val<real>(std::string(argv[++m]));
|
||||
timeset = false;
|
||||
circle = true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding argument of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-r")
|
||||
rate = !rate;
|
||||
else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-p") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
prec = Utility::val<int>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-T") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
tguard = Utility::val<real>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding argument of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-H") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
hguard = Utility::val<real>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding argument of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-v")
|
||||
verbose = true;
|
||||
else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
return 0;
|
||||
} else {
|
||||
int retval = usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
if (arg == "-h")
|
||||
std::cout<< "\nDefault magnetic path = \""
|
||||
<< MagneticModel::DefaultMagneticPath()
|
||||
<< "\"\nDefault magnetic name = \""
|
||||
<< MagneticModel::DefaultMagneticName()
|
||||
<< "\"\n";
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
|
||||
|
||||
using std::fmax;
|
||||
tguard = fmax(real(0), tguard);
|
||||
hguard = fmax(real(0), hguard);
|
||||
prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
|
||||
int retval = 0;
|
||||
try {
|
||||
using std::isfinite;
|
||||
const MagneticModel m(model, dir, Geocentric::WGS84(), Nmax, Mmax);
|
||||
if ((timeset || circle)
|
||||
&& (!isfinite(time) ||
|
||||
time < m.MinTime() - tguard ||
|
||||
time > m.MaxTime() + tguard))
|
||||
throw GeographicErr("Time " + Utility::str(time) +
|
||||
" too far outside allowed range [" +
|
||||
Utility::str(m.MinTime()) + "," +
|
||||
Utility::str(m.MaxTime()) + "]");
|
||||
if (circle
|
||||
&& (!isfinite(h) ||
|
||||
h < m.MinHeight() - hguard ||
|
||||
h > m.MaxHeight() + hguard))
|
||||
throw GeographicErr("Height " + Utility::str(h/1000) +
|
||||
"km too far outside allowed range [" +
|
||||
Utility::str(m.MinHeight()/1000) + "km," +
|
||||
Utility::str(m.MaxHeight()/1000) + "km]");
|
||||
if (verbose) {
|
||||
std::cerr << "Magnetic file: " << m.MagneticFile() << "\n"
|
||||
<< "Name: " << m.MagneticModelName() << "\n"
|
||||
<< "Description: " << m.Description() << "\n"
|
||||
<< "Date & Time: " << m.DateTime() << "\n"
|
||||
<< "Time range: ["
|
||||
<< m.MinTime() << ","
|
||||
<< m.MaxTime() << "]\n"
|
||||
<< "Height range: ["
|
||||
<< m.MinHeight()/1000 << "km,"
|
||||
<< m.MaxHeight()/1000 << "km]\n";
|
||||
}
|
||||
if ((timeset || circle) && (time < m.MinTime() || time > m.MaxTime()))
|
||||
std::cerr << "WARNING: Time " << time
|
||||
<< " outside allowed range ["
|
||||
<< m.MinTime() << "," << m.MaxTime() << "]\n";
|
||||
if (circle && (h < m.MinHeight() || h > m.MaxHeight()))
|
||||
std::cerr << "WARNING: Height " << h/1000
|
||||
<< "km outside allowed range ["
|
||||
<< m.MinHeight()/1000 << "km,"
|
||||
<< m.MaxHeight()/1000 << "km]\n";
|
||||
const MagneticCircle c(circle ? m.Circle(time, lat, h) :
|
||||
MagneticCircle());
|
||||
std::string s, eol, stra, strb;
|
||||
std::istringstream str;
|
||||
while (std::getline(*input, s)) {
|
||||
try {
|
||||
eol = "\n";
|
||||
if (!cdelim.empty()) {
|
||||
std::string::size_type n = s.find(cdelim);
|
||||
if (n != std::string::npos) {
|
||||
eol = " " + s.substr(n) + "\n";
|
||||
s = s.substr(0, n);
|
||||
}
|
||||
}
|
||||
str.clear(); str.str(s);
|
||||
if (!(timeset || circle)) {
|
||||
if (!(str >> stra))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
time = Utility::fractionalyear<real>(stra);
|
||||
if (time < m.MinTime() - tguard || time > m.MaxTime() + tguard)
|
||||
throw GeographicErr("Time " + Utility::str(time) +
|
||||
" too far outside allowed range [" +
|
||||
Utility::str(m.MinTime()) + "," +
|
||||
Utility::str(m.MaxTime()) +
|
||||
"]");
|
||||
if (time < m.MinTime() || time > m.MaxTime())
|
||||
std::cerr << "WARNING: Time " << time
|
||||
<< " outside allowed range ["
|
||||
<< m.MinTime() << "," << m.MaxTime() << "]\n";
|
||||
}
|
||||
real lon;
|
||||
if (circle) {
|
||||
if (!(str >> strb))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
DMS::flag ind;
|
||||
lon = DMS::Decode(strb, ind);
|
||||
if (ind == DMS::LATITUDE)
|
||||
throw GeographicErr("Bad hemisphere letter on " + strb);
|
||||
} else {
|
||||
if (!(str >> stra >> strb))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
|
||||
h = 0; // h is optional
|
||||
if (str >> h) {
|
||||
if (h < m.MinHeight() - hguard || h > m.MaxHeight() + hguard)
|
||||
throw GeographicErr("Height " + Utility::str(h/1000) +
|
||||
"km too far outside allowed range [" +
|
||||
Utility::str(m.MinHeight()/1000) + "km," +
|
||||
Utility::str(m.MaxHeight()/1000) + "km]");
|
||||
if (h < m.MinHeight() || h > m.MaxHeight())
|
||||
std::cerr << "WARNING: Height " << h/1000
|
||||
<< "km outside allowed range ["
|
||||
<< m.MinHeight()/1000 << "km,"
|
||||
<< m.MaxHeight()/1000 << "km]\n";
|
||||
}
|
||||
else
|
||||
str.clear();
|
||||
}
|
||||
if (str >> stra)
|
||||
throw GeographicErr("Extra junk in input: " + s);
|
||||
real bx, by, bz, bxt, byt, bzt;
|
||||
if (circle)
|
||||
c(lon, bx, by, bz, bxt, byt, bzt);
|
||||
else
|
||||
m(time, lat, lon, h, bx, by, bz, bxt, byt, bzt);
|
||||
real H, F, D, I, Ht, Ft, Dt, It;
|
||||
MagneticModel::FieldComponents(bx, by, bz, bxt, byt, bzt,
|
||||
H, F, D, I, Ht, Ft, Dt, It);
|
||||
|
||||
*output << DMS::Encode(D, prec + 1, DMS::NUMBER) << " "
|
||||
<< DMS::Encode(I, prec + 1, DMS::NUMBER) << " "
|
||||
<< Utility::str(H, prec) << " "
|
||||
<< Utility::str(by, prec) << " "
|
||||
<< Utility::str(bx, prec) << " "
|
||||
<< Utility::str(-bz, prec) << " "
|
||||
<< Utility::str(F, prec) << eol;
|
||||
if (rate)
|
||||
*output << DMS::Encode(Dt, prec + 1, DMS::NUMBER) << " "
|
||||
<< DMS::Encode(It, prec + 1, DMS::NUMBER) << " "
|
||||
<< Utility::str(Ht, prec) << " "
|
||||
<< Utility::str(byt, prec) << " "
|
||||
<< Utility::str(bxt, prec) << " "
|
||||
<< Utility::str(-bzt, prec) << " "
|
||||
<< Utility::str(Ft, prec) << eol;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
*output << "ERROR: " << e.what() << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error reading " << model << ": " << e.what() << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
163
libs/geographiclib/tools/Makefile.am
Normal file
163
libs/geographiclib/tools/Makefile.am
Normal file
@@ -0,0 +1,163 @@
|
||||
#
|
||||
# Makefile.am
|
||||
#
|
||||
# Copyright (C) 2009, Francesco P. Lovergine <frankie@debian.org>
|
||||
|
||||
AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include \
|
||||
-I$(top_builddir)/man -I$(top_srcdir)/man -Wall -Wextra
|
||||
|
||||
LDADD = $(top_builddir)/src/libGeographicLib.la
|
||||
DEPS = $(top_builddir)/src/libGeographicLib.la
|
||||
|
||||
bin_PROGRAMS = CartConvert \
|
||||
ConicProj \
|
||||
GeoConvert \
|
||||
GeodSolve \
|
||||
GeodesicProj \
|
||||
GeoidEval \
|
||||
Gravity \
|
||||
MagneticField \
|
||||
Planimeter \
|
||||
RhumbSolve \
|
||||
TransverseMercatorProj
|
||||
|
||||
CartConvert_SOURCES = CartConvert.cpp \
|
||||
../man/CartConvert.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/Geocentric.hpp \
|
||||
../include/GeographicLib/LocalCartesian.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
ConicProj_SOURCES = ConicProj.cpp \
|
||||
../man/ConicProj.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/AlbersEqualArea.hpp \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/LambertConformalConic.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
GeoConvert_SOURCES = GeoConvert.cpp \
|
||||
../man/GeoConvert.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/GeoCoords.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/UTMUPS.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
GeodSolve_SOURCES = GeodSolve.cpp \
|
||||
../man/GeodSolve.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/Geodesic.hpp \
|
||||
../include/GeographicLib/GeodesicExact.hpp \
|
||||
../include/GeographicLib/GeodesicLine.hpp \
|
||||
../include/GeographicLib/GeodesicLineExact.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
GeodesicProj_SOURCES = GeodesicProj.cpp \
|
||||
../man/GeodesicProj.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/AzimuthalEquidistant.hpp \
|
||||
../include/GeographicLib/CassiniSoldner.hpp \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/Geodesic.hpp \
|
||||
../include/GeographicLib/GeodesicLine.hpp \
|
||||
../include/GeographicLib/Gnomonic.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
GeoidEval_SOURCES = GeoidEval.cpp \
|
||||
../man/GeoidEval.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/GeoCoords.hpp \
|
||||
../include/GeographicLib/Geoid.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/UTMUPS.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
Gravity_SOURCES = Gravity.cpp \
|
||||
../man/Gravity.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/CircularEngine.hpp \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/Geocentric.hpp \
|
||||
../include/GeographicLib/GravityCircle.hpp \
|
||||
../include/GeographicLib/GravityModel.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/NormalGravity.hpp \
|
||||
../include/GeographicLib/SphericalEngine.hpp \
|
||||
../include/GeographicLib/SphericalHarmonic.hpp \
|
||||
../include/GeographicLib/SphericalHarmonic1.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
MagneticField_SOURCES = MagneticField.cpp \
|
||||
../man/MagneticField.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/CircularEngine.hpp \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/Geocentric.hpp \
|
||||
../include/GeographicLib/MagneticCircle.hpp \
|
||||
../include/GeographicLib/MagneticModel.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/SphericalEngine.hpp \
|
||||
../include/GeographicLib/SphericalHarmonic.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
Planimeter_SOURCES = Planimeter.cpp \
|
||||
../man/Planimeter.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/Accumulator.hpp \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/Ellipsoid.hpp \
|
||||
../include/GeographicLib/GeoCoords.hpp \
|
||||
../include/GeographicLib/Geodesic.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/PolygonArea.hpp \
|
||||
../include/GeographicLib/Rhumb.hpp \
|
||||
../include/GeographicLib/UTMUPS.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
RhumbSolve_SOURCES = RhumbSolve.cpp \
|
||||
../man/RhumbSolve.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/Ellipsoid.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
TransverseMercatorProj_SOURCES = TransverseMercatorProj.cpp \
|
||||
../man/TransverseMercatorProj.usage \
|
||||
../include/GeographicLib/Config.h \
|
||||
../include/GeographicLib/Constants.hpp \
|
||||
../include/GeographicLib/DMS.hpp \
|
||||
../include/GeographicLib/EllipticFunction.hpp \
|
||||
../include/GeographicLib/Math.hpp \
|
||||
../include/GeographicLib/TransverseMercator.hpp \
|
||||
../include/GeographicLib/TransverseMercatorExact.hpp \
|
||||
../include/GeographicLib/Utility.hpp
|
||||
|
||||
sbin_SCRIPTS = geographiclib-get-geoids \
|
||||
geographiclib-get-gravity \
|
||||
geographiclib-get-magnetic
|
||||
|
||||
geographiclib_data = $(datadir)/GeographicLib
|
||||
geographiclib-get-geoids: geographiclib-get-geoids.sh
|
||||
sed -e "s%@GEOGRAPHICLIB_DATA@%$(geographiclib_data)%" $< > $@
|
||||
chmod +x $@
|
||||
geographiclib-get-gravity: geographiclib-get-gravity.sh
|
||||
sed -e "s%@GEOGRAPHICLIB_DATA@%$(geographiclib_data)%" $< > $@
|
||||
chmod +x $@
|
||||
geographiclib-get-magnetic: geographiclib-get-magnetic.sh
|
||||
sed -e "s%@GEOGRAPHICLIB_DATA@%$(geographiclib_data)%" $< > $@
|
||||
chmod +x $@
|
||||
|
||||
CLEANFILES = $(sbin_SCRIPTS)
|
||||
EXTRA_DIST = CMakeLists.txt \
|
||||
geographiclib-get-geoids.sh geographiclib-get-gravity.sh \
|
||||
geographiclib-get-magnetic.sh
|
||||
248
libs/geographiclib/tools/Planimeter.cpp
Normal file
248
libs/geographiclib/tools/Planimeter.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
/**
|
||||
* \file Planimeter.cpp
|
||||
* \brief Command line utility for measuring the area of geodesic polygons
|
||||
*
|
||||
* Copyright (c) Charles Karney (2010-2022) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="Planimeter.1.html">man page</a> for usage information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <GeographicLib/PolygonArea.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
#include <GeographicLib/GeoCoords.hpp>
|
||||
#include <GeographicLib/Ellipsoid.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional expressions
|
||||
# pragma warning (disable: 4127)
|
||||
#endif
|
||||
|
||||
#include "Planimeter.usage"
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
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, longfirst = false,
|
||||
geoconvert_compat = false;
|
||||
int linetype = GEODESIC;
|
||||
int prec = 6;
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';';
|
||||
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-r")
|
||||
reverse = !reverse;
|
||||
else if (arg == "-s")
|
||||
sign = !sign;
|
||||
else if (arg == "-l")
|
||||
polyline = !polyline;
|
||||
else if (arg == "-e") {
|
||||
if (m + 2 >= argc) return usage(1, true);
|
||||
try {
|
||||
a = Utility::val<real>(std::string(argv[m + 1]));
|
||||
f = Utility::fract<real>(std::string(argv[m + 2]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 2;
|
||||
} else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-p") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
prec = Utility::val<int>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} 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 == "--geoconvert-input")
|
||||
geoconvert_compat = true;
|
||||
else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
return 0;
|
||||
} else
|
||||
return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
|
||||
|
||||
const Ellipsoid ellip(a, f);
|
||||
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),
|
||||
// 10^-11 sec (= 0.3 nm).
|
||||
prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
|
||||
std::string s, eol("\n");
|
||||
real perimeter, area;
|
||||
unsigned num;
|
||||
std::istringstream str;
|
||||
std::string slat, slon, junk;
|
||||
real lat = 0, lon = 0;
|
||||
while (std::getline(*input, s)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
bool endpoly = s.empty();
|
||||
if (!endpoly) {
|
||||
try {
|
||||
using std::isnan;
|
||||
if (geoconvert_compat) {
|
||||
p.Reset(s, true, longfirst);
|
||||
lat = p.Latitude(); lon = p.Longitude();
|
||||
} else {
|
||||
str.clear(); str.str(s);
|
||||
if (!(str >> slat >> slon))
|
||||
throw GeographicErr("incomplete input");
|
||||
if (str >> junk)
|
||||
throw GeographicErr("extra input");
|
||||
DMS::DecodeLatLon(slat, slon, lat, lon, longfirst);
|
||||
}
|
||||
if (isnan(lat) || isnan(lon))
|
||||
endpoly = true;
|
||||
}
|
||||
catch (const GeographicErr&) {
|
||||
endpoly = true;
|
||||
}
|
||||
}
|
||||
if (endpoly) {
|
||||
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) {
|
||||
*output << " " << Utility::str(area, std::max(0, prec - 5));
|
||||
}
|
||||
*output << eol;
|
||||
}
|
||||
linetype == EXACT ? polye.Clear() :
|
||||
linetype == RHUMB ? polyr.Clear() : poly.Clear();
|
||||
eol = "\n";
|
||||
} else {
|
||||
linetype == EXACT ? polye.AddPoint(lat, lon) :
|
||||
linetype == RHUMB ? polyr.AddPoint(lat, lon) :
|
||||
poly.AddPoint(linetype == AUTHALIC ? ellip.AuthalicLatitude(lat) :
|
||||
lat, lon);
|
||||
}
|
||||
}
|
||||
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);
|
||||
if (!polyline) {
|
||||
*output << " " << Utility::str(area, std::max(0, prec - 5));
|
||||
}
|
||||
*output << eol;
|
||||
}
|
||||
linetype == EXACT ? polye.Clear() :
|
||||
linetype == RHUMB ? polyr.Clear() : poly.Clear();
|
||||
eol = "\n";
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
244
libs/geographiclib/tools/RhumbSolve.cpp
Normal file
244
libs/geographiclib/tools/RhumbSolve.cpp
Normal file
@@ -0,0 +1,244 @@
|
||||
/**
|
||||
* \file RhumbSolve.cpp
|
||||
* \brief Command line utility for rhumb line calculations
|
||||
*
|
||||
* Copyright (c) Charles Karney (2014-2017) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="RhumbSolve.1.html">man page</a> for usage information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <GeographicLib/Rhumb.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional expressions and potentially
|
||||
// uninitialized local variables
|
||||
# pragma warning (disable: 4127 4701)
|
||||
#endif
|
||||
|
||||
#include "RhumbSolve.usage"
|
||||
|
||||
using namespace GeographicLib;
|
||||
typedef Math::real real;
|
||||
|
||||
std::string LatLonString(real lat, real lon, int prec, bool dms, char dmssep,
|
||||
bool longfirst) {
|
||||
using namespace GeographicLib;
|
||||
std::string
|
||||
latstr = dms ? DMS::Encode(lat, prec + 5, DMS::LATITUDE, dmssep) :
|
||||
DMS::Encode(lat, prec + 5, DMS::NUMBER),
|
||||
lonstr = dms ? DMS::Encode(lon, prec + 5, DMS::LONGITUDE, dmssep) :
|
||||
DMS::Encode(lon, prec + 5, DMS::NUMBER);
|
||||
return
|
||||
(longfirst ? lonstr : latstr) + " " + (longfirst ? latstr : lonstr);
|
||||
}
|
||||
|
||||
std::string AzimuthString(real azi, int prec, bool dms, char dmssep) {
|
||||
return dms ? DMS::Encode(azi, prec + 5, DMS::AZIMUTH, dmssep) :
|
||||
DMS::Encode(azi, prec + 5, DMS::NUMBER);
|
||||
}
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
Utility::set_digits();
|
||||
bool linecalc = false, inverse = false, dms = false, exact = true,
|
||||
longfirst = false;
|
||||
real
|
||||
a = Constants::WGS84_a(),
|
||||
f = Constants::WGS84_f();
|
||||
real lat1, lon1, azi12 = Math::NaN(), lat2, lon2, s12, S12;
|
||||
int prec = 3;
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';', dmssep = char(0);
|
||||
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-i") {
|
||||
inverse = true;
|
||||
linecalc = false;
|
||||
} else if (arg == "-L" || arg == "-l") { // -l is DEPRECATED
|
||||
inverse = false;
|
||||
linecalc = true;
|
||||
if (m + 3 >= argc) return usage(1, true);
|
||||
try {
|
||||
DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
|
||||
lat1, lon1, longfirst);
|
||||
azi12 = DMS::DecodeAzimuth(std::string(argv[m + 3]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -L: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 3;
|
||||
} else if (arg == "-e") {
|
||||
if (m + 2 >= argc) return usage(1, true);
|
||||
try {
|
||||
a = Utility::val<real>(std::string(argv[m + 1]));
|
||||
f = Utility::fract<real>(std::string(argv[m + 2]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 2;
|
||||
}
|
||||
else if (arg == "-d") {
|
||||
dms = true;
|
||||
dmssep = '\0';
|
||||
} else if (arg == "-:") {
|
||||
dms = true;
|
||||
dmssep = ':';
|
||||
} else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-p") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
prec = Utility::val<int>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-s")
|
||||
exact = false;
|
||||
else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
return 0;
|
||||
} else
|
||||
return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
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, Math::qd));
|
||||
// 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));
|
||||
std::string s, eol, slat1, slon1, slat2, slon2, sazi, ss12, strc;
|
||||
std::istringstream str;
|
||||
int retval = 0;
|
||||
while (std::getline(*input, s)) {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
str.clear(); str.str(s);
|
||||
if (linecalc) {
|
||||
if (!(str >> s12))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
if (str >> strc)
|
||||
throw GeographicErr("Extraneous input: " + strc);
|
||||
rhl.Position(s12, lat2, lon2, S12);
|
||||
*output << LatLonString(lat2, lon2, prec, dms, dmssep, longfirst)
|
||||
<< " " << Utility::str(S12, std::max(prec-7, 0)) << eol;
|
||||
} else if (inverse) {
|
||||
if (!(str >> slat1 >> slon1 >> slat2 >> slon2))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
if (str >> strc)
|
||||
throw GeographicErr("Extraneous input: " + strc);
|
||||
DMS::DecodeLatLon(slat1, slon1, lat1, lon1, longfirst);
|
||||
DMS::DecodeLatLon(slat2, slon2, lat2, lon2, longfirst);
|
||||
rh.Inverse(lat1, lon1, lat2, lon2, s12, azi12, S12);
|
||||
*output << AzimuthString(azi12, prec, dms, dmssep) << " "
|
||||
<< Utility::str(s12, prec) << " "
|
||||
<< Utility::str(S12, std::max(prec-7, 0)) << eol;
|
||||
} else { // direct
|
||||
if (!(str >> slat1 >> slon1 >> sazi >> s12))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
if (str >> strc)
|
||||
throw GeographicErr("Extraneous input: " + strc);
|
||||
DMS::DecodeLatLon(slat1, slon1, lat1, lon1, longfirst);
|
||||
azi12 = DMS::DecodeAzimuth(sazi);
|
||||
rh.Direct(lat1, lon1, azi12, s12, lat2, lon2, S12);
|
||||
*output << LatLonString(lat2, lon2, prec, dms, dmssep, longfirst)
|
||||
<< " " << 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;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
239
libs/geographiclib/tools/TransverseMercatorProj.cpp
Normal file
239
libs/geographiclib/tools/TransverseMercatorProj.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
* \file TransverseMercatorProj.cpp
|
||||
* \brief Command line utility for transverse Mercator projections
|
||||
*
|
||||
* Copyright (c) Charles Karney (2008-2017) <charles@karney.com> and licensed
|
||||
* under the MIT/X11 License. For more information, see
|
||||
* https://geographiclib.sourceforge.io/
|
||||
*
|
||||
* See the <a href="TransverseMercatorProj.1.html">man page</a> for usage
|
||||
* information.
|
||||
**********************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <GeographicLib/TransverseMercatorExact.hpp>
|
||||
#include <GeographicLib/TransverseMercator.hpp>
|
||||
#include <GeographicLib/DMS.hpp>
|
||||
#include <GeographicLib/Utility.hpp>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// Squelch warnings about constant conditional expressions and potentially
|
||||
// uninitialized local variables
|
||||
# pragma warning (disable: 4127 4701)
|
||||
#endif
|
||||
|
||||
#include "TransverseMercatorProj.usage"
|
||||
|
||||
int main(int argc, const char* const argv[]) {
|
||||
try {
|
||||
using namespace GeographicLib;
|
||||
typedef Math::real real;
|
||||
Utility::set_digits();
|
||||
bool exact = true, extended = false, series = false, reverse = false,
|
||||
longfirst = false;
|
||||
real
|
||||
a = Constants::WGS84_a(),
|
||||
f = Constants::WGS84_f(),
|
||||
k0 = Constants::UTM_k0(),
|
||||
lon0 = 0;
|
||||
int prec = 6;
|
||||
std::string istring, ifile, ofile, cdelim;
|
||||
char lsep = ';';
|
||||
|
||||
for (int m = 1; m < argc; ++m) {
|
||||
std::string arg(argv[m]);
|
||||
if (arg == "-r")
|
||||
reverse = true;
|
||||
else if (arg == "-t") {
|
||||
exact = true;
|
||||
extended = true;
|
||||
series = false;
|
||||
} else if (arg == "-s") {
|
||||
exact = false;
|
||||
extended = false;
|
||||
series = true;
|
||||
} else if (arg == "-l") {
|
||||
if (++m >= argc) return usage(1, true);
|
||||
try {
|
||||
DMS::flag ind;
|
||||
lon0 = DMS::Decode(std::string(argv[m]), ind);
|
||||
if (ind == DMS::LATITUDE)
|
||||
throw GeographicErr("Bad hemisphere");
|
||||
lon0 = Math::AngNormalize(lon0);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding argument of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-k") {
|
||||
if (++m >= argc) return usage(1, true);
|
||||
try {
|
||||
k0 = Utility::val<real>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding argument of " << arg << ": "
|
||||
<< e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "-e") {
|
||||
if (m + 2 >= argc) return usage(1, true);
|
||||
try {
|
||||
a = Utility::val<real>(std::string(argv[m + 1]));
|
||||
f = Utility::fract<real>(std::string(argv[m + 2]));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
m += 2;
|
||||
} else if (arg == "-w")
|
||||
longfirst = !longfirst;
|
||||
else if (arg == "-p") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
try {
|
||||
prec = Utility::val<int>(std::string(argv[m]));
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
std::cerr << "Precision " << argv[m] << " is not a number\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (arg == "--input-string") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
istring = argv[m];
|
||||
} else if (arg == "--input-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ifile = argv[m];
|
||||
} else if (arg == "--output-file") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
ofile = argv[m];
|
||||
} else if (arg == "--line-separator") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
if (std::string(argv[m]).size() != 1) {
|
||||
std::cerr << "Line separator must be a single character\n";
|
||||
return 1;
|
||||
}
|
||||
lsep = argv[m][0];
|
||||
} else if (arg == "--comment-delimiter") {
|
||||
if (++m == argc) return usage(1, true);
|
||||
cdelim = argv[m];
|
||||
} else if (arg == "--version") {
|
||||
std::cout << argv[0] << ": GeographicLib version "
|
||||
<< GEOGRAPHICLIB_VERSION_STRING << "\n";
|
||||
return 0;
|
||||
} else
|
||||
return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
|
||||
}
|
||||
|
||||
if (!ifile.empty() && !istring.empty()) {
|
||||
std::cerr << "Cannot specify --input-string and --input-file together\n";
|
||||
return 1;
|
||||
}
|
||||
if (ifile == "-") ifile.clear();
|
||||
std::ifstream infile;
|
||||
std::istringstream instring;
|
||||
if (!ifile.empty()) {
|
||||
infile.open(ifile.c_str());
|
||||
if (!infile.is_open()) {
|
||||
std::cerr << "Cannot open " << ifile << " for reading\n";
|
||||
return 1;
|
||||
}
|
||||
} else if (!istring.empty()) {
|
||||
std::string::size_type m = 0;
|
||||
while (true) {
|
||||
m = istring.find(lsep, m);
|
||||
if (m == std::string::npos)
|
||||
break;
|
||||
istring[m] = '\n';
|
||||
}
|
||||
instring.str(istring);
|
||||
}
|
||||
std::istream* input = !ifile.empty() ? &infile :
|
||||
(!istring.empty() ? &instring : &std::cin);
|
||||
|
||||
std::ofstream outfile;
|
||||
if (ofile == "-") ofile.clear();
|
||||
if (!ofile.empty()) {
|
||||
outfile.open(ofile.c_str());
|
||||
if (!outfile.is_open()) {
|
||||
std::cerr << "Cannot open " << ofile << " for writing\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
|
||||
|
||||
const TransverseMercator& TMS =
|
||||
series ? TransverseMercator(a, f, k0) : TransverseMercator(1, 0, 1);
|
||||
|
||||
const TransverseMercatorExact& TME =
|
||||
exact ? TransverseMercatorExact(a, f, k0, extended)
|
||||
: TransverseMercatorExact(1, real(0.1), 1, false);
|
||||
|
||||
// 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));
|
||||
std::string s, eol, stra, strb, strc;
|
||||
std::istringstream str;
|
||||
int retval = 0;
|
||||
std::cout << std::fixed;
|
||||
while (std::getline(*input, s)) {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
str.clear(); str.str(s);
|
||||
real lat, lon, x, y;
|
||||
if (!(str >> stra >> strb))
|
||||
throw GeographicErr("Incomplete input: " + s);
|
||||
if (reverse) {
|
||||
x = Utility::val<real>(stra);
|
||||
y = Utility::val<real>(strb);
|
||||
} else
|
||||
DMS::DecodeLatLon(stra, strb, lat, lon, longfirst);
|
||||
if (str >> strc)
|
||||
throw GeographicErr("Extraneous input: " + strc);
|
||||
real gamma, k;
|
||||
if (reverse) {
|
||||
if (series)
|
||||
TMS.Reverse(lon0, x, y, lat, lon, gamma, k);
|
||||
else
|
||||
TME.Reverse(lon0, x, y, lat, lon, gamma, k);
|
||||
*output << Utility::str(longfirst ? lon : lat, prec + 5) << " "
|
||||
<< Utility::str(longfirst ? lat : lon, prec + 5) << " "
|
||||
<< Utility::str(gamma, prec + 6) << " "
|
||||
<< Utility::str(k, prec + 6) << eol;
|
||||
} else {
|
||||
if (series)
|
||||
TMS.Forward(lon0, lat, lon, x, y, gamma, k);
|
||||
else
|
||||
TME.Forward(lon0, lat, lon, x, y, gamma, k);
|
||||
*output << Utility::str(x, prec) << " "
|
||||
<< Utility::str(y, prec) << " "
|
||||
<< Utility::str(gamma, prec + 6) << " "
|
||||
<< Utility::str(k, prec + 6) << eol;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
*output << "ERROR: " << e.what() << "\n";
|
||||
retval = 1;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
std::cerr << "Caught exception: " << e.what() << "\n";
|
||||
return 1;
|
||||
}
|
||||
catch (...) {
|
||||
std::cerr << "Caught unknown exception\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
211
libs/geographiclib/tools/geographiclib-get-geoids.sh
Normal file
211
libs/geographiclib/tools/geographiclib-get-geoids.sh
Normal file
@@ -0,0 +1,211 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Download geoid datasets for use by GeographicLib::Geoid. This is
|
||||
# modeled on a similar script geographiclib-datasets-download by
|
||||
# Francesco P. Lovergine <frankie@debian.org>
|
||||
#
|
||||
# Copyright (c) Charles Karney (2011-2022) <charles@karney.com> and
|
||||
# licensed under the MIT/X11 License. For more information, see
|
||||
# https://geographiclib.sourceforge.io/
|
||||
|
||||
DEFAULTDIR="@GEOGRAPHICLIB_DATA@"
|
||||
SUBDIR=geoids
|
||||
NAME=geoid
|
||||
MODEL=geoid
|
||||
CLASS=Geoid
|
||||
TOOL=GeoidEval
|
||||
EXT=pgm
|
||||
usage() {
|
||||
cat <<EOF
|
||||
usage: $0 [-p parentdir] [-f] [-d] [-h] $MODEL...
|
||||
|
||||
This program downloads and installs the datasets used by the
|
||||
GeographicLib::$CLASS class and the $TOOL tool to compute geoid
|
||||
heights. These datasets are NGA earth gravity models evaluated on a
|
||||
rectangular grid in latitude and longitude. $MODEL is one of more of the
|
||||
names from this table:
|
||||
|
||||
size (MB)
|
||||
name geoid grid tar.bz2 disk
|
||||
egm84-30 EGM84 30' 0.5 0.6
|
||||
egm84-15 EGM84 15' 1.5 2.1
|
||||
egm96-15 EGM96 15' 1.5 2.1
|
||||
egm96-5 EGM96 5' 11 19
|
||||
egm2008-5 EGM2008 5' 11 19
|
||||
egm2008-2_5 EGM2008 2.5' 35 75
|
||||
egm2008-1 EGM2008 1' 170 470
|
||||
|
||||
The size columns give the download and installed sizes of the datasets.
|
||||
In addition you can specify
|
||||
|
||||
all = all of the supported geoids
|
||||
minimal = emg96-5
|
||||
best = egm84-15 egm96-5 egm2008-1 (the highest resolution for each
|
||||
earth gravity model)
|
||||
good = same as best but substitute egm2008-2_5 for egm2008-1 to save
|
||||
on disk space
|
||||
|
||||
-p parentdir (default $DEFAULTDIR) specifies where the
|
||||
datasets should be stored. The "Default $NAME path" listed when running
|
||||
|
||||
$TOOL -h
|
||||
|
||||
should be parentdir/$SUBDIR. This script must be run by a user with
|
||||
write access to this directory.
|
||||
|
||||
Normally only datasets which are not already in parentdir are
|
||||
downloaded. You can force the download and reinstallation with -f.
|
||||
The -f flag also let you download new models (not yet in the set
|
||||
defined by "all").
|
||||
|
||||
If -d is provided, the temporary directory which holds the downloads,
|
||||
\$TMPDIR/$NAME-XXXXXXXX or ${TMPDIR:-/tmp}/$NAME-XXXXXXXX,
|
||||
will be saved. -h prints this help.
|
||||
|
||||
For more information on the $NAME datasets, visit
|
||||
|
||||
https://geographiclib.sourceforge.io/C++/doc/$NAME.html
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
PARENTDIR="$DEFAULTDIR"
|
||||
DEBUG=
|
||||
FORCE=
|
||||
while getopts hp:fd c; do
|
||||
case $c in
|
||||
h )
|
||||
usage;
|
||||
exit 0
|
||||
;;
|
||||
p ) PARENTDIR="$OPTARG"
|
||||
;;
|
||||
f ) FORCE=y
|
||||
;;
|
||||
d ) DEBUG=y
|
||||
;;
|
||||
* )
|
||||
usage 1>&2;
|
||||
exit 1
|
||||
;;
|
||||
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
|
||||
echo Cannot create directory $PARENTDIR/$SUBDIR 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMP=
|
||||
if test -z "$DEBUG"; then
|
||||
trap 'trap "" 0; test "$TEMP" && rm -rf "$TEMP"; exit 1' 1 2 3 9 15
|
||||
trap 'test "$TEMP" && rm -rf "$TEMP"' 0
|
||||
fi
|
||||
TEMP=`mktemp -d -q -t $NAME-XXXXXXXX`
|
||||
|
||||
if test -z "$TEMP" -o ! -d "$TEMP"; then
|
||||
echo Cannot create temporary directory 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WRITETEST="$PARENTDIR"/$SUBDIR/write-test-`basename $TEMP`
|
||||
if touch "$WRITETEST" 2> /dev/null; then
|
||||
rm -f "$WRITETEST"
|
||||
else
|
||||
echo Cannot write in directory $PARENTDIR/$SUBDIR 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
cat > $TEMP/all <<EOF
|
||||
egm84-30
|
||||
egm84-15
|
||||
egm96-15
|
||||
egm96-5
|
||||
egm2008-5
|
||||
egm2008-2_5
|
||||
egm2008-1
|
||||
EOF
|
||||
|
||||
while test $# -gt 0; do
|
||||
if grep "^$1\$" $TEMP/all > /dev/null; then
|
||||
echo $1
|
||||
else
|
||||
case "$1" in
|
||||
all )
|
||||
cat $TEMP/all
|
||||
;;
|
||||
minimal )
|
||||
echo egm96-5
|
||||
;;
|
||||
best ) # highest resolution models
|
||||
cat <<EOF
|
||||
egm2008-1
|
||||
egm96-5
|
||||
egm84-15
|
||||
EOF
|
||||
;;
|
||||
good ) # like best but with egm2008-1 -> egm2008-2_5
|
||||
cat <<EOF
|
||||
egm2008-2_5
|
||||
egm96-5
|
||||
egm84-15
|
||||
EOF
|
||||
;;
|
||||
* )
|
||||
if test -n "$FORCE"; then
|
||||
echo $1
|
||||
else
|
||||
echo Unknown $MODEL $1 1>&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done > $TEMP/list
|
||||
|
||||
sort -u $TEMP/list > $TEMP/todo
|
||||
|
||||
while read file; do
|
||||
if test -z "$FORCE" -a -s $PARENTDIR/$SUBDIR/$file.$EXT; then
|
||||
echo $PARENTDIR/$SUBDIR/$file.$EXT already installed, skipping $file...
|
||||
echo $file >> $TEMP/skip
|
||||
continue
|
||||
fi
|
||||
echo download $file.tar.bz2 ...
|
||||
echo $file >> $TEMP/download
|
||||
URL="https://downloads.sourceforge.net/project/geographiclib/$SUBDIR-distrib/$file.tar.bz2?use_mirror=autoselect"
|
||||
ARCHIVE=$TEMP/$file.tar.bz2
|
||||
wget -O$ARCHIVE $URL
|
||||
echo unpack $file.tar.bz2 ...
|
||||
tar vxojf $ARCHIVE -C $PARENTDIR
|
||||
echo $MODEL $file installed.
|
||||
done < $TEMP/todo
|
||||
|
||||
if test "$DEBUG"; then
|
||||
echo Saving temporary directory $TEMP
|
||||
fi
|
||||
echo
|
||||
if test -s $TEMP/download; then
|
||||
n=`wc -l < $TEMP/download`
|
||||
s=; test $n -gt 1 && s=s
|
||||
cat <<EOF
|
||||
Installed $NAME dataset$s `tr '\n' ' ' < $TEMP/download`in $PARENTDIR/$SUBDIR.
|
||||
EOF
|
||||
fi
|
||||
if test -s $TEMP/skip; then
|
||||
n=`wc -l < $TEMP/skip`
|
||||
s=; test $n -gt 1 && s=s
|
||||
cat <<EOF
|
||||
Skipped $NAME dataset$s `tr '\n' ' ' < $TEMP/skip | sed 's/ $//'`.
|
||||
EOF
|
||||
fi
|
||||
echo
|
||||
186
libs/geographiclib/tools/geographiclib-get-gravity.sh
Normal file
186
libs/geographiclib/tools/geographiclib-get-gravity.sh
Normal file
@@ -0,0 +1,186 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Download gravity models for use by GeographicLib::GravityModel.
|
||||
#
|
||||
# Copyright (c) Charles Karney (2011-2022) <charles@karney.com> and
|
||||
# licensed under the MIT/X11 License. For more information, see
|
||||
# https://geographiclib.sourceforge.io/
|
||||
|
||||
DEFAULTDIR="@GEOGRAPHICLIB_DATA@"
|
||||
SUBDIR=gravity
|
||||
NAME=gravity
|
||||
MODEL=gravitymodel
|
||||
CLASS=GravityModel
|
||||
TOOL=Gravity
|
||||
EXT=egm.cof
|
||||
usage() {
|
||||
cat <<EOF
|
||||
usage: $0 [-p parentdir] [-f] [-d] [-h] $MODEL...
|
||||
|
||||
This program downloads and installs the datasets used by the
|
||||
GeographicLib::$CLASS class and the $TOOL tool to compute
|
||||
gravity fields. $MODEL is one of more of the names from this
|
||||
table:
|
||||
|
||||
size (kB)
|
||||
name degree tar.bz2 disk
|
||||
egm84 18 27 26
|
||||
egm96 360 2100 2100
|
||||
egm2008 2190 76000 75000
|
||||
wgs84 20 1 1
|
||||
grs80 20 1 1
|
||||
|
||||
The size columns give the download and installed sizes of the datasets.
|
||||
In addition you can specify
|
||||
|
||||
all = all of the supported gravity models
|
||||
minimal = egm96 wgs84
|
||||
|
||||
-p parentdir (default $DEFAULTDIR) specifies where the
|
||||
datasets should be stored. The "Default $NAME path" listed when running
|
||||
|
||||
$TOOL -h
|
||||
|
||||
should be parentdir/$SUBDIR. This script must be run by a user with
|
||||
write access to this directory.
|
||||
|
||||
Normally only datasets which are not already in parentdir are
|
||||
downloaded. You can force the download and reinstallation with -f.
|
||||
The -f flag also let you download new models (not yet in the set
|
||||
defined by "all").
|
||||
|
||||
If -d is provided, the temporary directory which holds the downloads,
|
||||
\$TMPDIR/$NAME-XXXXXXXX or ${TMPDIR:-/tmp}/$NAME-XXXXXXXX,
|
||||
will be saved. -h prints this help.
|
||||
|
||||
For more information on the $NAME datasets, visit
|
||||
|
||||
https://geographiclib.sourceforge.io/C++/doc/$NAME.html
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
PARENTDIR="$DEFAULTDIR"
|
||||
DEBUG=
|
||||
FORCE=
|
||||
while getopts hp:fd c; do
|
||||
case $c in
|
||||
h )
|
||||
usage;
|
||||
exit 0
|
||||
;;
|
||||
p ) PARENTDIR="$OPTARG"
|
||||
;;
|
||||
f ) FORCE=y
|
||||
;;
|
||||
d ) DEBUG=y
|
||||
;;
|
||||
* )
|
||||
usage 1>&2;
|
||||
exit 1
|
||||
;;
|
||||
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
|
||||
echo Cannot create directory $PARENTDIR/$SUBDIR 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMP=
|
||||
if test -z "$DEBUG"; then
|
||||
trap 'trap "" 0; test "$TEMP" && rm -rf "$TEMP"; exit 1' 1 2 3 9 15
|
||||
trap 'test "$TEMP" && rm -rf "$TEMP"' 0
|
||||
fi
|
||||
TEMP=`mktemp -d -q -t $NAME-XXXXXXXX`
|
||||
|
||||
if test -z "$TEMP" -o ! -d "$TEMP"; then
|
||||
echo Cannot create temporary directory 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WRITETEST="$PARENTDIR"/$SUBDIR/write-test-`basename $TEMP`
|
||||
if touch "$WRITETEST" 2> /dev/null; then
|
||||
rm -f "$WRITETEST"
|
||||
else
|
||||
echo Cannot write in directory $PARENTDIR/$SUBDIR 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
cat > $TEMP/all <<EOF
|
||||
egm84
|
||||
egm96
|
||||
egm2008
|
||||
grs80
|
||||
wgs84
|
||||
EOF
|
||||
|
||||
while test $# -gt 0; do
|
||||
if grep "^$1\$" $TEMP/all > /dev/null; then
|
||||
echo $1
|
||||
else
|
||||
case "$1" in
|
||||
all )
|
||||
cat $TEMP/all
|
||||
;;
|
||||
minimal )
|
||||
echo egm96; echo wgs84
|
||||
;;
|
||||
* )
|
||||
if test -n "$FORCE"; then
|
||||
echo $1
|
||||
else
|
||||
echo Unknown $MODEL $1 1>&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done > $TEMP/list
|
||||
|
||||
sort -u $TEMP/list > $TEMP/todo
|
||||
|
||||
while read file; do
|
||||
if test -z "$FORCE" -a -s $PARENTDIR/$SUBDIR/$file.$EXT; then
|
||||
echo $PARENTDIR/$SUBDIR/$file.$EXT already installed, skipping $file...
|
||||
echo $file >> $TEMP/skip
|
||||
continue
|
||||
fi
|
||||
echo download $file.tar.bz2 ...
|
||||
echo $file >> $TEMP/download
|
||||
URL="https://downloads.sourceforge.net/project/geographiclib/$SUBDIR-distrib/$file.tar.bz2?use_mirror=autoselect"
|
||||
ARCHIVE=$TEMP/$file.tar.bz2
|
||||
wget -O$ARCHIVE $URL
|
||||
echo unpack $file.tar.bz2 ...
|
||||
tar vxojf $ARCHIVE -C $PARENTDIR
|
||||
echo $MODEL $file installed.
|
||||
done < $TEMP/todo
|
||||
|
||||
if test "$DEBUG"; then
|
||||
echo Saving temporary directory $TEMP
|
||||
fi
|
||||
echo
|
||||
if test -s $TEMP/download; then
|
||||
n=`wc -l < $TEMP/download`
|
||||
s=; test $n -gt 1 && s=s
|
||||
cat <<EOF
|
||||
Installed $NAME dataset$s `tr '\n' ' ' < $TEMP/download`in $PARENTDIR/$SUBDIR.
|
||||
EOF
|
||||
fi
|
||||
if test -s $TEMP/skip; then
|
||||
n=`wc -l < $TEMP/skip`
|
||||
s=; test $n -gt 1 && s=s
|
||||
cat <<EOF
|
||||
Skipped $NAME dataset$s `tr '\n' ' ' < $TEMP/skip | sed 's/ $//'`.
|
||||
EOF
|
||||
fi
|
||||
echo
|
||||
195
libs/geographiclib/tools/geographiclib-get-magnetic.sh
Normal file
195
libs/geographiclib/tools/geographiclib-get-magnetic.sh
Normal file
@@ -0,0 +1,195 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Download magnetic models for use by GeographicLib::MagneticModel.
|
||||
#
|
||||
# Copyright (c) Charles Karney (2011-2022) <charles@karney.com> and
|
||||
# licensed under the MIT/X11 License. For more information, see
|
||||
# https://geographiclib.sourceforge.io/
|
||||
|
||||
DEFAULTDIR="@GEOGRAPHICLIB_DATA@"
|
||||
SUBDIR=magnetic
|
||||
NAME=magnetic
|
||||
MODEL=magneticmodel
|
||||
CLASS=MagneticModel
|
||||
TOOL=MagneticField
|
||||
EXT=wmm.cof
|
||||
usage() {
|
||||
cat <<EOF
|
||||
usage: $0 [-p parentdir] [-f] [-d] [-h] $MODEL...
|
||||
|
||||
This program downloads and installs the datasets used by the
|
||||
GeographicLib::$CLASS class and the $TOOL tool to compute
|
||||
magnetic fields. $MODEL is one of more of the names from this
|
||||
table:
|
||||
|
||||
size (kB)
|
||||
name degree years tar.bz2 disk
|
||||
wmm2010 12 2010-2015 2 3
|
||||
wmm2015 12 2015-2020 2 3 *deprecated*
|
||||
wmm2015v2 12 2015-2020 2 3
|
||||
wmm2020 12 2020-2025 2 3
|
||||
igrf11 13 1900-2015 7 25
|
||||
igrf12 13 1900-2020 7 26
|
||||
igrf13 13 1900-2025 7 28
|
||||
emm2010 739 2010-2015 3700 4400
|
||||
emm2015 729 2000-2020 660 4300
|
||||
emm2017 790 2000-2022 1740 5050
|
||||
|
||||
The size columns give the download and installed sizes of the datasets.
|
||||
In addition you can specify
|
||||
|
||||
all = all of the supported magnetic models
|
||||
minimal = wmm2020 igrf13
|
||||
|
||||
-p parentdir (default $DEFAULTDIR) specifies where the
|
||||
datasets should be stored. The "Default $NAME path" listed when running
|
||||
|
||||
$TOOL -h
|
||||
|
||||
should be parentdir/$SUBDIR. This script must be run by a user with
|
||||
write access to this directory.
|
||||
|
||||
Normally only datasets which are not already in parentdir are
|
||||
downloaded. You can force the download and reinstallation with -f.
|
||||
The -f flag also let you download new models (not yet in the set
|
||||
defined by "all").
|
||||
|
||||
If -d is provided, the temporary directory which holds the downloads,
|
||||
\$TMPDIR/$NAME-XXXXXXXX or ${TMPDIR:-/tmp}/$NAME-XXXXXXXX,
|
||||
will be saved. -h prints this help.
|
||||
|
||||
For more information on the magnetic models, visit
|
||||
|
||||
https://geographiclib.sourceforge.io/C++/doc/$NAME.html
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
PARENTDIR="$DEFAULTDIR"
|
||||
FORCE=
|
||||
while getopts hp:fd c; do
|
||||
case $c in
|
||||
h )
|
||||
usage;
|
||||
exit 0
|
||||
;;
|
||||
p ) PARENTDIR="$OPTARG"
|
||||
;;
|
||||
f ) FORCE=y
|
||||
;;
|
||||
d ) DEBUG=y
|
||||
;;
|
||||
* )
|
||||
usage 1>&2;
|
||||
exit 1
|
||||
;;
|
||||
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
|
||||
echo Cannot create directory $PARENTDIR/$SUBDIR 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TEMP=
|
||||
if test -z "$DEBUG"; then
|
||||
trap 'trap "" 0; test "$TEMP" && rm -rf "$TEMP"; exit 1' 1 2 3 9 15
|
||||
trap 'test "$TEMP" && rm -rf "$TEMP"' 0
|
||||
fi
|
||||
TEMP=`mktemp -d -q -t $NAME-XXXXXXXX`
|
||||
|
||||
if test -z "$TEMP" -o ! -d "$TEMP"; then
|
||||
echo Cannot create temporary directory 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WRITETEST="$PARENTDIR"/$SUBDIR/write-test-`basename $TEMP`
|
||||
if touch "$WRITETEST" 2> /dev/null; then
|
||||
rm -f "$WRITETEST"
|
||||
else
|
||||
echo Cannot write in directory $PARENTDIR/$SUBDIR 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
cat > $TEMP/all <<EOF
|
||||
wmm2010
|
||||
wmm2015
|
||||
wmm2015v2
|
||||
wmm2020
|
||||
emm2010
|
||||
emm2015
|
||||
emm2017
|
||||
igrf11
|
||||
igrf12
|
||||
igrf13
|
||||
EOF
|
||||
|
||||
while test $# -gt 0; do
|
||||
if grep "^$1\$" $TEMP/all > /dev/null; then
|
||||
echo $1
|
||||
else
|
||||
case "$1" in
|
||||
all )
|
||||
cat $TEMP/all
|
||||
;;
|
||||
minimal )
|
||||
echo wmm2020; echo igrf13
|
||||
;;
|
||||
* )
|
||||
if test -n "$FORCE"; then
|
||||
echo $1
|
||||
else
|
||||
echo Unknown $MODEL $1 1>&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done > $TEMP/list
|
||||
|
||||
sort -u $TEMP/list > $TEMP/todo
|
||||
|
||||
while read file; do
|
||||
if test -z "$FORCE" -a -s $PARENTDIR/$SUBDIR/$file.$EXT; then
|
||||
echo $PARENTDIR/$SUBDIR/$file.$EXT already installed, skipping $file...
|
||||
echo $file >> $TEMP/skip
|
||||
continue
|
||||
fi
|
||||
echo download $file.tar.bz2 ...
|
||||
echo $file >> $TEMP/download
|
||||
URL="https://downloads.sourceforge.net/project/geographiclib/$SUBDIR-distrib/$file.tar.bz2?use_mirror=autoselect"
|
||||
ARCHIVE=$TEMP/$file.tar.bz2
|
||||
wget -O$ARCHIVE $URL
|
||||
echo unpack $file.tar.bz2 ...
|
||||
tar vxojf $ARCHIVE -C $PARENTDIR
|
||||
echo $MODEL $file installed.
|
||||
done < $TEMP/todo
|
||||
|
||||
if test "$DEBUG"; then
|
||||
echo Saving temporary directory $TEMP
|
||||
fi
|
||||
echo
|
||||
if test -s $TEMP/download; then
|
||||
n=`wc -l < $TEMP/download`
|
||||
s=; test $n -gt 1 && s=s
|
||||
cat <<EOF
|
||||
Installed $NAME dataset$s `tr '\n' ' ' < $TEMP/download`in $PARENTDIR/$SUBDIR.
|
||||
EOF
|
||||
fi
|
||||
if test -s $TEMP/skip; then
|
||||
n=`wc -l < $TEMP/skip`
|
||||
s=; test $n -gt 1 && s=s
|
||||
cat <<EOF
|
||||
Skipped $NAME dataset$s `tr '\n' ' ' < $TEMP/skip | sed 's/ $//'`.
|
||||
EOF
|
||||
fi
|
||||
echo
|
||||
Reference in New Issue
Block a user