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