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