GeographicLib
1.21
|
00001 /** 00002 * \file GeoConvert.cpp 00003 * \brief Command line utility for geographic coordinate conversions 00004 * 00005 * Copyright (c) Charles Karney (2008-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 GeoConvert \ 00011 * GeoConvert.cpp \ 00012 * ../src/DMS.cpp \ 00013 * ../src/GeoCoords.cpp \ 00014 * ../src/MGRS.cpp \ 00015 * ../src/PolarStereographic.cpp \ 00016 * ../src/TransverseMercator.cpp \ 00017 * ../src/UTMUPS.cpp 00018 * 00019 * See the <a href="GeoConvert.1.html">man page</a> for usage 00020 * information. 00021 **********************************************************************/ 00022 00023 #include <iostream> 00024 #include <sstream> 00025 #include <string> 00026 #include <sstream> 00027 #include <fstream> 00028 #include <GeographicLib/GeoCoords.hpp> 00029 #include <GeographicLib/DMS.hpp> 00030 #include <GeographicLib/Utility.hpp> 00031 00032 #include "GeoConvert.usage" 00033 00034 int main(int argc, char* argv[]) { 00035 try { 00036 using namespace GeographicLib; 00037 typedef Math::real real; 00038 enum { GEOGRAPHIC, DMS, UTMUPS, MGRS, CONVERGENCE }; 00039 int outputmode = GEOGRAPHIC; 00040 int prec = 0; 00041 int zone = UTMUPS::MATCH; 00042 bool centerp = true, swaplatlong = false; 00043 std::string istring, ifile, ofile, cdelim; 00044 char lsep = ';', dmssep = char(0); 00045 00046 for (int m = 1; m < argc; ++m) { 00047 std::string arg(argv[m]); 00048 if (arg == "-g") 00049 outputmode = GEOGRAPHIC; 00050 else if (arg == "-d") { 00051 outputmode = DMS; 00052 dmssep = '\0'; 00053 } else if (arg == "-:") { 00054 outputmode = DMS; 00055 dmssep = ':'; 00056 } else if (arg == "-u") 00057 outputmode = UTMUPS; 00058 else if (arg == "-m") 00059 outputmode = MGRS; 00060 else if (arg == "-c") 00061 outputmode = CONVERGENCE; 00062 else if (arg == "-n") 00063 centerp = false; 00064 else if (arg == "-w") 00065 swaplatlong = true; 00066 else if (arg == "-p") { 00067 if (++m == argc) return usage(1, true); 00068 try { 00069 prec = Utility::num<int>(std::string(argv[m])); 00070 } 00071 catch (const std::exception&) { 00072 std::cerr << "Precision " << argv[m] << " is not a number\n"; 00073 return 1; 00074 } 00075 } else if (arg == "-z") { 00076 if (++m == argc) return usage(1, true); 00077 std::string zonestr(argv[m]); 00078 try { 00079 bool northp; 00080 UTMUPS::DecodeZone(zonestr, zone, northp); 00081 } 00082 catch (const std::exception&) { 00083 std::istringstream str(zonestr); 00084 char c; 00085 if (!(str >> zone) || (str >> c)) { 00086 std::cerr << "Zone " << zonestr 00087 << " is not a number or zone+hemisphere\n"; 00088 return 1; 00089 } 00090 if (!(zone >= UTMUPS::MINZONE && zone <= UTMUPS::MAXZONE)) { 00091 std::cerr << "Zone " << zone << " not in [0, 60]\n"; 00092 return 1; 00093 } 00094 } 00095 } else if (arg == "-s") 00096 zone = UTMUPS::STANDARD; 00097 else if (arg == "-t") 00098 zone = UTMUPS::UTM; 00099 else if (arg == "--input-string") { 00100 if (++m == argc) return usage(1, true); 00101 istring = argv[m]; 00102 } else if (arg == "--input-file") { 00103 if (++m == argc) return usage(1, true); 00104 ifile = argv[m]; 00105 } else if (arg == "--output-file") { 00106 if (++m == argc) return usage(1, true); 00107 ofile = argv[m]; 00108 } else if (arg == "--line-separator") { 00109 if (++m == argc) return usage(1, true); 00110 if (std::string(argv[m]).size() != 1) { 00111 std::cerr << "Line separator must be a single character\n"; 00112 return 1; 00113 } 00114 lsep = argv[m][0]; 00115 } else if (arg == "--comment-delimiter") { 00116 if (++m == argc) return usage(1, true); 00117 cdelim = argv[m]; 00118 } else if (arg == "--version") { 00119 std::cout 00120 << argv[0] 00121 << ": $Id: e39b9974b58d123fd979b1c3c086ae3ccccba72d $\n" 00122 << "GeographicLib version " << GEOGRAPHICLIB_VERSION_STRING << "\n"; 00123 return 0; 00124 } else 00125 return usage(!(arg == "-h" || arg == "--help"), arg != "--help"); 00126 } 00127 00128 if (!ifile.empty() && !istring.empty()) { 00129 std::cerr << "Cannot specify --input-string and --input-file together\n"; 00130 return 1; 00131 } 00132 if (ifile == "-") ifile.clear(); 00133 std::ifstream infile; 00134 std::istringstream instring; 00135 if (!ifile.empty()) { 00136 infile.open(ifile.c_str()); 00137 if (!infile.is_open()) { 00138 std::cerr << "Cannot open " << ifile << " for reading\n"; 00139 return 1; 00140 } 00141 } else if (!istring.empty()) { 00142 std::string::size_type m = 0; 00143 while (true) { 00144 m = istring.find(lsep, m); 00145 if (m == std::string::npos) 00146 break; 00147 istring[m] = '\n'; 00148 } 00149 instring.str(istring); 00150 } 00151 std::istream* input = !ifile.empty() ? &infile : 00152 (!istring.empty() ? &instring : &std::cin); 00153 00154 std::ofstream outfile; 00155 if (ofile == "-") ofile.clear(); 00156 if (!ofile.empty()) { 00157 outfile.open(ofile.c_str()); 00158 if (!outfile.is_open()) { 00159 std::cerr << "Cannot open " << ofile << " for writing\n"; 00160 return 1; 00161 } 00162 } 00163 std::ostream* output = !ofile.empty() ? &outfile : &std::cout; 00164 00165 GeoCoords p; 00166 std::string s; 00167 std::string os; 00168 int retval = 0; 00169 00170 while (std::getline(*input, s)) { 00171 std::string eol("\n"); 00172 try { 00173 if (!cdelim.empty()) { 00174 std::string::size_type m = s.find(cdelim); 00175 if (m != std::string::npos) { 00176 eol = " " + s.substr(m) + "\n"; 00177 s = s.substr(0, m); 00178 } 00179 } 00180 p.Reset(s, centerp, swaplatlong); 00181 p.SetAltZone(zone); 00182 switch (outputmode) { 00183 case GEOGRAPHIC: 00184 os = p.GeoRepresentation(prec, swaplatlong); 00185 break; 00186 case DMS: 00187 os = p.DMSRepresentation(prec, swaplatlong, dmssep); 00188 break; 00189 case UTMUPS: 00190 os = p.AltUTMUPSRepresentation(prec); 00191 break; 00192 case MGRS: 00193 os = p.AltMGRSRepresentation(prec); 00194 break; 00195 case CONVERGENCE: 00196 { 00197 real 00198 gamma = p.AltConvergence(), 00199 k = p.AltScale(); 00200 os = 00201 Utility::str<real>(gamma, std::max(-5,std::min(8,prec))+5) 00202 + " " + 00203 Utility::str<real>(k, std::max(-5,std::min(8,prec))+7); 00204 } 00205 } 00206 } 00207 catch (const std::exception& e) { 00208 // Write error message to cout so output lines match input lines 00209 os = std::string("ERROR: ") + e.what(); 00210 retval = 1; 00211 } 00212 *output << os << eol; 00213 } 00214 return retval; 00215 } 00216 catch (const std::exception& e) { 00217 std::cerr << "Caught exception: " << e.what() << "\n"; 00218 return 1; 00219 } 00220 catch (...) { 00221 std::cerr << "Caught unknown exception\n"; 00222 return 1; 00223 } 00224 }