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