GeographicLib
1.21
|
00001 /** 00002 * \file CartConvert.cpp 00003 * \brief Command line utility for geodetic to cartesian coordinate conversions 00004 * 00005 * Copyright (c) Charles Karney (2009-2012) <charles@karney.com> and licensed 00006 * under the MIT/X11 License. For more information, see 00007 * http://geographiclib.sourceforge.net/ 00008 * 00009 * Compile and link with 00010 * g++ -g -O3 -I../include -I../man -o CartConvert \ 00011 * CartConvert.cpp \ 00012 * ../src/DMS.cpp \ 00013 * ../src/Geocentric.cpp \ 00014 * ../src/LocalCartesian.cpp 00015 * 00016 * See the <a href="CartConvert.1.html">man page</a> for usage 00017 * information. 00018 **********************************************************************/ 00019 00020 #include <iostream> 00021 #include <sstream> 00022 #include <string> 00023 #include <sstream> 00024 #include <fstream> 00025 #include <GeographicLib/Geocentric.hpp> 00026 #include <GeographicLib/LocalCartesian.hpp> 00027 #include <GeographicLib/DMS.hpp> 00028 #include <GeographicLib/Utility.hpp> 00029 00030 #include "CartConvert.usage" 00031 00032 int main(int argc, char* argv[]) { 00033 try { 00034 using namespace GeographicLib; 00035 typedef Math::real real; 00036 bool localcartesian = false, reverse = false; 00037 real 00038 a = Constants::WGS84_a<real>(), 00039 f = Constants::WGS84_f<real>(); 00040 real lat0 = 0, lon0 = 0, h0 = 0; 00041 std::string istring, ifile, ofile, cdelim; 00042 char lsep = ';'; 00043 00044 for (int m = 1; m < argc; ++m) { 00045 std::string arg(argv[m]); 00046 if (arg == "-r") 00047 reverse = true; 00048 else if (arg == "-l") { 00049 localcartesian = true; 00050 if (m + 3 >= argc) return usage(1, true); 00051 try { 00052 DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]), 00053 lat0, lon0); 00054 h0 = Utility::num<real>(std::string(argv[m + 3])); 00055 } 00056 catch (const std::exception& e) { 00057 std::cerr << "Error decoding arguments of -l: " << e.what() << "\n"; 00058 return 1; 00059 } 00060 m += 3; 00061 } else if (arg == "-e") { 00062 if (m + 2 >= argc) return usage(1, true); 00063 try { 00064 a = Utility::num<real>(std::string(argv[m + 1])); 00065 f = Utility::fract<real>(std::string(argv[m + 2])); 00066 } 00067 catch (const std::exception& e) { 00068 std::cerr << "Error decoding arguments of -e: " << e.what() << "\n"; 00069 return 1; 00070 } 00071 m += 2; 00072 } else if (arg == "--input-string") { 00073 if (++m == argc) return usage(1, true); 00074 istring = argv[m]; 00075 } else if (arg == "--input-file") { 00076 if (++m == argc) return usage(1, true); 00077 ifile = argv[m]; 00078 } else if (arg == "--output-file") { 00079 if (++m == argc) return usage(1, true); 00080 ofile = argv[m]; 00081 } else if (arg == "--line-separator") { 00082 if (++m == argc) return usage(1, true); 00083 if (std::string(argv[m]).size() != 1) { 00084 std::cerr << "Line separator must be a single character\n"; 00085 return 1; 00086 } 00087 lsep = argv[m][0]; 00088 } else if (arg == "--comment-delimiter") { 00089 if (++m == argc) return usage(1, true); 00090 cdelim = argv[m]; 00091 } else if (arg == "--version") { 00092 std::cout 00093 << argv[0] 00094 << ": $Id: b9e53a72ea7d026978678f3ab9d726a2d8485079 $\n" 00095 << "GeographicLib version " << GEOGRAPHICLIB_VERSION_STRING << "\n"; 00096 return 0; 00097 } else 00098 return usage(!(arg == "-h" || arg == "--help"), arg != "--help"); 00099 } 00100 00101 if (!ifile.empty() && !istring.empty()) { 00102 std::cerr << "Cannot specify --input-string and --input-file together\n"; 00103 return 1; 00104 } 00105 if (ifile == "-") ifile.clear(); 00106 std::ifstream infile; 00107 std::istringstream instring; 00108 if (!ifile.empty()) { 00109 infile.open(ifile.c_str()); 00110 if (!infile.is_open()) { 00111 std::cerr << "Cannot open " << ifile << " for reading\n"; 00112 return 1; 00113 } 00114 } else if (!istring.empty()) { 00115 std::string::size_type m = 0; 00116 while (true) { 00117 m = istring.find(lsep, m); 00118 if (m == std::string::npos) 00119 break; 00120 istring[m] = '\n'; 00121 } 00122 instring.str(istring); 00123 } 00124 std::istream* input = !ifile.empty() ? &infile : 00125 (!istring.empty() ? &instring : &std::cin); 00126 00127 std::ofstream outfile; 00128 if (ofile == "-") ofile.clear(); 00129 if (!ofile.empty()) { 00130 outfile.open(ofile.c_str()); 00131 if (!outfile.is_open()) { 00132 std::cerr << "Cannot open " << ofile << " for writing\n"; 00133 return 1; 00134 } 00135 } 00136 std::ostream* output = !ofile.empty() ? &outfile : &std::cout; 00137 00138 const Geocentric ec(a, f); 00139 const LocalCartesian lc(lat0, lon0, h0, ec); 00140 00141 std::string s; 00142 int retval = 0; 00143 while (std::getline(*input, s)) { 00144 try { 00145 std::string eol("\n"); 00146 if (!cdelim.empty()) { 00147 std::string::size_type m = s.find(cdelim); 00148 if (m != std::string::npos) { 00149 eol = " " + s.substr(m) + "\n"; 00150 s = s.substr(0, m); 00151 } 00152 } 00153 std::istringstream str(s); 00154 real lat, lon, h, x, y, z; 00155 std::string stra, strb, strc; 00156 if (!(str >> stra >> strb >> strc)) 00157 throw GeographicErr("Incomplete input: " + s); 00158 if (reverse) { 00159 x = Utility::num<real>(stra); 00160 y = Utility::num<real>(strb); 00161 z = Utility::num<real>(strc); 00162 } else { 00163 DMS::DecodeLatLon(stra, strb, lat, lon); 00164 h = Utility::num<real>(strc); 00165 } 00166 std::string strd; 00167 if (str >> strd) 00168 throw GeographicErr("Extraneous input: " + strd); 00169 if (reverse) { 00170 if (localcartesian) 00171 lc.Reverse(x, y, z, lat, lon, h); 00172 else 00173 ec.Reverse(x, y, z, lat, lon, h); 00174 *output << Utility::str<real>(lat, 15) << " " 00175 << Utility::str<real>(lon, 15) << " " 00176 << Utility::str<real>(h, 12) << eol; 00177 } else { 00178 if (localcartesian) 00179 lc.Forward(lat, lon, h, x, y, z); 00180 else 00181 ec.Forward(lat, lon, h, x, y, z); 00182 *output << Utility::str<real>(x, 10) << " " 00183 << Utility::str<real>(y, 10) << " " 00184 << Utility::str<real>(z, 10) << eol; 00185 } 00186 } 00187 catch (const std::exception& e) { 00188 *output << "ERROR: " << e.what() << "\n"; 00189 retval = 1; 00190 } 00191 } 00192 return retval; 00193 } 00194 catch (const std::exception& e) { 00195 std::cerr << "Caught exception: " << e.what() << "\n"; 00196 return 1; 00197 } 00198 catch (...) { 00199 std::cerr << "Caught unknown exception\n"; 00200 return 1; 00201 } 00202 }