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