00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <iostream>
00011 #include <sstream>
00012 #include <string>
00013 #include <sstream>
00014 #include <fstream>
00015 #include <cmath>
00016 #include <limits>
00017 #include <GeographicLib/Rhumb.hpp>
00018 #include <GeographicLib/DMS.hpp>
00019 #include <GeographicLib/Utility.hpp>
00020
00021 #if defined(_MSC_VER)
00022
00023
00024 # pragma warning (disable: 4127 4701)
00025 #endif
00026
00027 #include "RhumbSolve.usage"
00028
00029 using namespace GeographicLib;
00030 typedef Math::real real;
00031
00032 std::string LatLonString(real lat, real lon, int prec, bool dms, char dmssep) {
00033 return dms ?
00034 DMS::Encode(lat, prec + 5, DMS::LATITUDE, dmssep) + " " +
00035 DMS::Encode(lon, prec + 5, DMS::LONGITUDE, dmssep) :
00036 DMS::Encode(lat, prec + 5, DMS::NUMBER) + " " +
00037 DMS::Encode(lon, prec + 5, DMS::NUMBER);
00038 }
00039
00040 std::string AzimuthString(real azi, int prec, bool dms, char dmssep) {
00041 return dms ? DMS::Encode(azi, prec + 5, DMS::AZIMUTH, dmssep) :
00042 DMS::Encode(azi >= 180 ? azi - 360 : azi, prec + 5, DMS::NUMBER);
00043 }
00044
00045 int main(int argc, char* argv[]) {
00046 try {
00047 Utility::set_digits();
00048 bool linecalc = false, inverse = false, dms = false, exact = true;
00049 real
00050 a = Constants::WGS84_a(),
00051 f = Constants::WGS84_f();
00052 real lat1, lon1, azi12 = Math::NaN(), lat2, lon2, s12;
00053 int prec = 3;
00054 std::string istring, ifile, ofile, cdelim;
00055 char lsep = ';', dmssep = char(0);
00056
00057 for (int m = 1; m < argc; ++m) {
00058 std::string arg(argv[m]);
00059 if (arg == "-i") {
00060 inverse = true;
00061 linecalc = false;
00062 } else if (arg == "-l") {
00063 inverse = false;
00064 linecalc = true;
00065 if (m + 3 >= argc) return usage(1, true);
00066 try {
00067 DMS::DecodeLatLon(std::string(argv[m + 1]), std::string(argv[m + 2]),
00068 lat1, lon1);
00069 azi12 = DMS::DecodeAzimuth(std::string(argv[m + 3]));
00070 }
00071 catch (const std::exception& e) {
00072 std::cerr << "Error decoding arguments of -l: " << e.what() << "\n";
00073 return 1;
00074 }
00075 m += 3;
00076 } else if (arg == "-e") {
00077 if (m + 2 >= argc) return usage(1, true);
00078 try {
00079 a = Utility::num<real>(std::string(argv[m + 1]));
00080 f = Utility::fract<real>(std::string(argv[m + 2]));
00081 }
00082 catch (const std::exception& e) {
00083 std::cerr << "Error decoding arguments of -e: " << e.what() << "\n";
00084 return 1;
00085 }
00086 m += 2;
00087 }
00088 else if (arg == "-d") {
00089 dms = true;
00090 dmssep = '\0';
00091 } else if (arg == "-:") {
00092 dms = true;
00093 dmssep = ':';
00094 } else if (arg == "-p") {
00095 if (++m == argc) return usage(1, true);
00096 try {
00097 prec = Utility::num<int>(std::string(argv[m]));
00098 }
00099 catch (const std::exception&) {
00100 std::cerr << "Precision " << argv[m] << " is not a number\n";
00101 return 1;
00102 }
00103 } else if (arg == "-s")
00104 exact = false;
00105 else if (arg == "--input-string") {
00106 if (++m == argc) return usage(1, true);
00107 istring = argv[m];
00108 } else if (arg == "--input-file") {
00109 if (++m == argc) return usage(1, true);
00110 ifile = argv[m];
00111 } else if (arg == "--output-file") {
00112 if (++m == argc) return usage(1, true);
00113 ofile = argv[m];
00114 } else if (arg == "--line-separator") {
00115 if (++m == argc) return usage(1, true);
00116 if (std::string(argv[m]).size() != 1) {
00117 std::cerr << "Line separator must be a single character\n";
00118 return 1;
00119 }
00120 lsep = argv[m][0];
00121 } else if (arg == "--comment-delimiter") {
00122 if (++m == argc) return usage(1, true);
00123 cdelim = argv[m];
00124 } else if (arg == "--version") {
00125 std::cout
00126 << argv[0] << ": GeographicLib version "
00127 << GEOGRAPHICLIB_VERSION_STRING << "\n";
00128 return 0;
00129 } else
00130 return usage(!(arg == "-h" || arg == "--help"), arg != "--help");
00131 }
00132
00133 if (!ifile.empty() && !istring.empty()) {
00134 std::cerr << "Cannot specify --input-string and --input-file together\n";
00135 return 1;
00136 }
00137 if (ifile == "-") ifile.clear();
00138 std::ifstream infile;
00139 std::istringstream instring;
00140 if (!ifile.empty()) {
00141 infile.open(ifile.c_str());
00142 if (!infile.is_open()) {
00143 std::cerr << "Cannot open " << ifile << " for reading\n";
00144 return 1;
00145 }
00146 } else if (!istring.empty()) {
00147 std::string::size_type m = 0;
00148 while (true) {
00149 m = istring.find(lsep, m);
00150 if (m == std::string::npos)
00151 break;
00152 istring[m] = '\n';
00153 }
00154 instring.str(istring);
00155 }
00156 std::istream* input = !ifile.empty() ? &infile :
00157 (!istring.empty() ? &instring : &std::cin);
00158
00159 std::ofstream outfile;
00160 if (ofile == "-") ofile.clear();
00161 if (!ofile.empty()) {
00162 outfile.open(ofile.c_str());
00163 if (!outfile.is_open()) {
00164 std::cerr << "Cannot open " << ofile << " for writing\n";
00165 return 1;
00166 }
00167 }
00168 std::ostream* output = !ofile.empty() ? &outfile : &std::cout;
00169
00170 const Rhumb rh(a, f, exact);
00171
00172
00173 prec = std::min(10 + Math::extra_digits(), std::max(0, prec));
00174 int retval = 0;
00175 std::string s;
00176 if (linecalc) {
00177 const RhumbLine rhl(rh.Line(lat1, lon1, azi12));
00178 while (std::getline(*input, s)) {
00179 try {
00180 std::istringstream str(s);
00181 if (!(str >> s12))
00182 throw GeographicErr("Incomplete input: " + s);
00183 std::string strc;
00184 if (str >> strc)
00185 throw GeographicErr("Extraneous input: " + strc);
00186 rhl.Position(s12, lat2, lon2);
00187 *output << LatLonString(lat2, lon2, prec, dms, dmssep) << "\n";
00188 }
00189 catch (const std::exception& e) {
00190
00191 *output << "ERROR: " << e.what() << "\n";
00192 retval = 1;
00193 }
00194 }
00195 } else if (inverse) {
00196 while (std::getline(*input, s)) {
00197 try {
00198 std::istringstream str(s);
00199 std::string slat1, slon1, slat2, slon2;
00200 if (!(str >> slat1 >> slon1 >> slat2 >> slon2))
00201 throw GeographicErr("Incomplete input: " + s);
00202 std::string strc;
00203 if (str >> strc)
00204 throw GeographicErr("Extraneous input: " + strc);
00205 DMS::DecodeLatLon(slat1, slon1, lat1, lon1);
00206 DMS::DecodeLatLon(slat2, slon2, lat2, lon2);
00207 rh.Inverse(lat1, lon1, lat2, lon2, s12, azi12);
00208 *output << AzimuthString(azi12, prec, dms, dmssep) << " "
00209 << Utility::str(s12, prec) << "\n";
00210 }
00211 catch (const std::exception& e) {
00212
00213 *output << "ERROR: " << e.what() << "\n";
00214 retval = 1;
00215 }
00216 }
00217 } else {
00218 while (std::getline(*input, s)) {
00219 try {
00220 std::istringstream str(s);
00221 std::string slat1, slon1, sazi;
00222 if (!(str >> slat1 >> slon1 >> sazi >> s12))
00223 throw GeographicErr("Incomplete input: " + s);
00224 std::string strc;
00225 if (str >> strc)
00226 throw GeographicErr("Extraneous input: " + strc);
00227 DMS::DecodeLatLon(slat1, slon1, lat1, lon1);
00228 azi12 = DMS::DecodeAzimuth(sazi);
00229 rh.Direct(lat1, lon1, azi12, s12, lat2, lon2);
00230 *output << LatLonString(lat2, lon2, prec, dms, dmssep) << "\n";
00231 }
00232 catch (const std::exception& e) {
00233
00234 *output << "ERROR: " << e.what() << "\n";
00235 retval = 1;
00236 }
00237 }
00238 }
00239 return retval;
00240 }
00241 catch (const std::exception& e) {
00242 std::cerr << "Caught exception: " << e.what() << "\n";
00243 return 1;
00244 }
00245 catch (...) {
00246 std::cerr << "Caught unknown exception\n";
00247 return 1;
00248 }
00249 }