GeographicLib  1.21
GeodesicProj.cpp
Go to the documentation of this file.
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 }