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