GeographicLib
1.21
|
00001 /** 00002 * \file TransverseMercatorProj.cpp 00003 * \brief Command line utility for transverse Mercator projections 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 TransverseMercatorProj \ 00011 * TransverseMercatorProj.cpp \ 00012 * ../src/DMS.cpp \ 00013 * ../src/EllipticFunction.cpp \ 00014 * ../src/TransverseMercator.cpp \ 00015 * ../src/TransverseMercatorExact.cpp 00016 * 00017 * See the <a href="TransverseMercatorProj.1.html">man page</a> for usage 00018 * information. 00019 **********************************************************************/ 00020 00021 #include <iostream> 00022 #include <sstream> 00023 #include <string> 00024 #include <sstream> 00025 #include <fstream> 00026 #include <GeographicLib/EllipticFunction.hpp> 00027 #include <GeographicLib/TransverseMercatorExact.hpp> 00028 #include <GeographicLib/TransverseMercator.hpp> 00029 #include <GeographicLib/DMS.hpp> 00030 #include <GeographicLib/Utility.hpp> 00031 00032 #include "TransverseMercatorProj.usage" 00033 00034 int main(int argc, char* argv[]) { 00035 try { 00036 using namespace GeographicLib; 00037 typedef Math::real real; 00038 bool exact = true, extended = false, series = false, reverse = false; 00039 real 00040 a = Constants::WGS84_a<real>(), 00041 f = Constants::WGS84_f<real>(), 00042 k0 = Constants::UTM_k0<real>(), 00043 lon0 = 0; 00044 std::string istring, ifile, ofile, cdelim; 00045 char lsep = ';'; 00046 00047 for (int m = 1; m < argc; ++m) { 00048 std::string arg(argv[m]); 00049 if (arg == "-r") 00050 reverse = true; 00051 else if (arg == "-t") { 00052 exact = true; 00053 extended = true; 00054 series = false; 00055 } else if (arg == "-s") { 00056 exact = false; 00057 extended = false; 00058 series = true; 00059 } else if (arg == "-l") { 00060 if (++m >= argc) return usage(1, true); 00061 try { 00062 DMS::flag ind; 00063 lon0 = DMS::Decode(std::string(argv[m]), ind); 00064 if (ind == DMS::LATITUDE) 00065 throw GeographicErr("Bad hemisphere"); 00066 if (!(lon0 >= -180 && lon0 <= 360)) 00067 throw GeographicErr("Bad longitude"); 00068 if (lon0 >= 180) lon0 -= 360; 00069 } 00070 catch (const std::exception& e) { 00071 std::cerr << "Error decoding argument of " << arg << ": " 00072 << e.what() << "\n"; 00073 return 1; 00074 } 00075 } else if (arg == "-k") { 00076 if (++m >= argc) return usage(1, true); 00077 try { 00078 k0 = Utility::num<real>(std::string(argv[m])); 00079 } 00080 catch (const std::exception& e) { 00081 std::cerr << "Error decoding argument of " << arg << ": " 00082 << e.what() << "\n"; 00083 return 1; 00084 } 00085 } else if (arg == "-e") { 00086 if (m + 2 >= argc) return usage(1, true); 00087 try { 00088 a = Utility::num<real>(std::string(argv[m + 1])); 00089 f = Utility::fract<real>(std::string(argv[m + 2])); 00090 } 00091 catch (const std::exception& e) { 00092 std::cerr << "Error decoding arguments of -e: " << e.what() << "\n"; 00093 return 1; 00094 } 00095 m += 2; 00096 } else if (arg == "--input-string") { 00097 if (++m == argc) return usage(1, true); 00098 istring = argv[m]; 00099 } else if (arg == "--input-file") { 00100 if (++m == argc) return usage(1, true); 00101 ifile = argv[m]; 00102 } else if (arg == "--output-file") { 00103 if (++m == argc) return usage(1, true); 00104 ofile = argv[m]; 00105 } else if (arg == "--line-separator") { 00106 if (++m == argc) return usage(1, true); 00107 if (std::string(argv[m]).size() != 1) { 00108 std::cerr << "Line separator must be a single character\n"; 00109 return 1; 00110 } 00111 lsep = argv[m][0]; 00112 } else if (arg == "--comment-delimiter") { 00113 if (++m == argc) return usage(1, true); 00114 cdelim = argv[m]; 00115 } else if (arg == "--version") { 00116 std::cout 00117 << argv[0] 00118 << ": $Id: dd2a53288a82171129091d16bec6d1457568eb4d $\n" 00119 << "GeographicLib version " << GEOGRAPHICLIB_VERSION_STRING << "\n"; 00120 return 0; 00121 } else 00122 return usage(!(arg == "-h" || arg == "--help"), arg != "--help"); 00123 } 00124 00125 if (!ifile.empty() && !istring.empty()) { 00126 std::cerr << "Cannot specify --input-string and --input-file together\n"; 00127 return 1; 00128 } 00129 if (ifile == "-") ifile.clear(); 00130 std::ifstream infile; 00131 std::istringstream instring; 00132 if (!ifile.empty()) { 00133 infile.open(ifile.c_str()); 00134 if (!infile.is_open()) { 00135 std::cerr << "Cannot open " << ifile << " for reading\n"; 00136 return 1; 00137 } 00138 } else if (!istring.empty()) { 00139 std::string::size_type m = 0; 00140 while (true) { 00141 m = istring.find(lsep, m); 00142 if (m == std::string::npos) 00143 break; 00144 istring[m] = '\n'; 00145 } 00146 instring.str(istring); 00147 } 00148 std::istream* input = !ifile.empty() ? &infile : 00149 (!istring.empty() ? &instring : &std::cin); 00150 00151 std::ofstream outfile; 00152 if (ofile == "-") ofile.clear(); 00153 if (!ofile.empty()) { 00154 outfile.open(ofile.c_str()); 00155 if (!outfile.is_open()) { 00156 std::cerr << "Cannot open " << ofile << " for writing\n"; 00157 return 1; 00158 } 00159 } 00160 std::ostream* output = !ofile.empty() ? &outfile : &std::cout; 00161 00162 const TransverseMercator& TMS = 00163 series ? TransverseMercator(a, f, k0) : TransverseMercator(1, 0, 1); 00164 00165 const TransverseMercatorExact& TME = 00166 exact ? TransverseMercatorExact(a, f, k0, extended) 00167 : TransverseMercatorExact(1, real(0.1), 1, false); 00168 00169 std::string s; 00170 int retval = 0; 00171 std::cout << std::fixed; 00172 while (std::getline(*input, s)) { 00173 try { 00174 std::string eol("\n"); 00175 if (!cdelim.empty()) { 00176 std::string::size_type m = s.find(cdelim); 00177 if (m != std::string::npos) { 00178 eol = " " + s.substr(m) + "\n"; 00179 s = s.substr(0, m); 00180 } 00181 } 00182 std::istringstream str(s); 00183 real lat, lon, x, y; 00184 std::string stra, strb; 00185 if (!(str >> stra >> strb)) 00186 throw GeographicErr("Incomplete input: " + s); 00187 if (reverse) { 00188 x = Utility::num<real>(stra); 00189 y = Utility::num<real>(strb); 00190 } else 00191 DMS::DecodeLatLon(stra, strb, lat, lon); 00192 std::string strc; 00193 if (str >> strc) 00194 throw GeographicErr("Extraneous input: " + strc); 00195 real gamma, k; 00196 if (reverse) { 00197 if (series) 00198 TMS.Reverse(lon0, x, y, lat, lon, gamma, k); 00199 else 00200 TME.Reverse(lon0, x, y, lat, lon, gamma, k); 00201 *output << Utility::str<real>(lat, 15) << " " 00202 << Utility::str<real>(lon, 15) << " " 00203 << Utility::str<real>(gamma, 16) << " " 00204 << Utility::str<real>(k, 16) << eol; 00205 } else { 00206 if (series) 00207 TMS.Forward(lon0, lat, lon, x, y, gamma, k); 00208 else 00209 TME.Forward(lon0, lat, lon, x, y, gamma, k); 00210 *output << Utility::str<real>(x, 10) << " " 00211 << Utility::str<real>(y, 10) << " " 00212 << Utility::str<real>(gamma, 16) << " " 00213 << Utility::str<real>(k, 16) << eol; 00214 } 00215 } 00216 catch (const std::exception& e) { 00217 *output << "ERROR: " << e.what() << "\n"; 00218 retval = 1; 00219 } 00220 } 00221 return retval; 00222 } 00223 catch (const std::exception& e) { 00224 std::cerr << "Caught exception: " << e.what() << "\n"; 00225 return 1; 00226 } 00227 catch (...) { 00228 std::cerr << "Caught unknown exception\n"; 00229 return 1; 00230 } 00231 }