GeoConvert.cpp

Go to the documentation of this file.
00001 /**
00002  * \file GeoConvert.cpp
00003  * \brief Command line utility for geographic coordinate conversions
00004  *
00005  * Copyright (c) Charles Karney (2008, 2009, 2010) <charles@karney.com>
00006  * and licensed under the LGPL.  For more information, see
00007  * http://geographiclib.sourceforge.net/
00008  *
00009  * Compile with -I../include and link with GeoCoords.o MGRS.o UTMUPS.o DMS.o
00010  * TransverseMercator.o PolarStereographic.o
00011  *
00012  * See \ref geoconvert for usage information.
00013  **********************************************************************/
00014 
00015 #include "GeographicLib/GeoCoords.hpp"
00016 #include "GeographicLib/DMS.hpp"
00017 #include <iostream>
00018 #include <sstream>
00019 #include <iomanip>
00020 
00021 int usage(int retval) {
00022   ( retval ? std::cerr : std::cout ) <<
00023 "Usage: GeoConvert [-g|-d|-u|-m|-c] [-p prec] [-z zone] [-s] [-t] [-n] [-h]\n\
00024 $Id: GeoConvert.cpp 6827 2010-05-20 19:56:18Z karney $\n\
00025 \n\
00026 Convert geographic coordinates to\n\
00027 \n\
00028     -g latitude and longitude (decimal degrees), default output\n\
00029     -d latitude and longitude (degrees mins secs)\n\
00030     -u UTM or UPS\n\
00031     -m MGRS\n\
00032     -c meridian convergence and scale\n\
00033 \n\
00034 The WGS84 model of the earth is used.  Geographic coordinates are given on\n\
00035 standard input as:\n\
00036 \n\
00037 Latitude and longitude (decimal degrees or degrees minutes seconds).  d,\n\
00038 ', and \" are used to denote degrees, minutes, and seconds, with the least\n\
00039 significant designator optional.  Latitude is given first unless a\n\
00040 hemisphere is specified, e.g., the following are all equivalent\n\
00041 \n\
00042     33.3 44.4\n\
00043     E44.4 N33.3\n\
00044     33d18'N 44d24'E\n\
00045     44d24 33d18N\n\
00046 \n\
00047 UTM or UPS given as zone+hemisphere easting northing or easting northing\n\
00048 zone+hemisphere.  The zone is absent for a UPS specification.  E.g.,\n\
00049 \n\
00050     38N 444140.54 3684706.36\n\
00051     444140.54 3684706.36 38N\n\
00052     S 2173854.98 2985980.58\n\
00053     2173854.98 2985980.58 S\n\
00054 \n\
00055 MRGS is used to specify the center of a grid square, e.g.,\n\
00056 \n\
00057     38SMB4484\n\
00058     38SMB44140847064\n\
00059 \n\
00060 -p prec (default 0) sets the precision relative to 1m.  This gives the\n\
00061 number of digits after the decimal point for UTM/UPS.  The number of digits\n\
00062 per coordinate for MGRS is 5 + prec.  For decimal degrees, the number of\n\
00063 digits after the decimal point is 5 + prec.  For DMS (degree, minute,\n\
00064 seconds) output, the number of digits after the decimal point in the\n\
00065 seconds components is 1 + prec; if this is negative then use minutes (prec\n\
00066 = -2 or -3) or degrees (prec <= -4) as the least significant component.\n\
00067 Print convergence, resp. scale, with 5 + prec, resp. 7 + prec, digits after\n\
00068 the decimal point.  The minimum value of prec is -5 and the maximum is 9\n\
00069 for UTM/UPS, 9 for decimal degrees, 10 for DMS, 6 for MGRS, and 8 for\n\
00070 convergence and scale.\n\
00071 \n\
00072 MGRS coordinates are given by truncating (instead of rounding) the\n\
00073 coordinates to the requested precision.  For example is prec = -3, the\n\
00074 result is the 1km square enclosing the position, for example,\n\
00075 \n\
00076     echo 38N 444800 3684700 | GeoConvert -m -p -3   ==> 38SMB4484\n\
00077 \n\
00078 If the -n option is given, then, on input, an MSGS coordinate refers to\n\
00079 the south-west corner of the MGRS square instead of the center.  Thus:\n\
00080 \n\
00081     echo 38SMB4484 | GeoConvert -u         ==> 38N 444500 3684500\n\
00082     echo 38SMB4484 | GeoConvert -u -n      ==> 38N 444000 3684000\n\
00083 \n\
00084 Convergence is the bearing of grid north given as degrees clockwise from\n\
00085 true north.\n\
00086 \n\
00087 UTM/UPS and MGRS are given in zone of the input if applicable, otherwise in\n\
00088 the standard zone.\n\
00089 \n\
00090 -z zone sets the zone for output.  Use either a positive number for a UTM\n\
00091 zone or zone = 0 to specify UPS.  Alternatively use a zone+hemisphere\n\
00092 designation (and the hemisphere is ignored).\n\
00093 \n\
00094 -s uses the standard UPS and UTM zone boundaries.\n\
00095 \n\
00096 -t is similar to -s but forces UPS regions to the closest UTM zone.\n\
00097 \n\
00098 For example, the point\n\
00099 \n\
00100     79.9S 6.1E\n\
00101 \n\
00102 corresponds to possible MGRS coordinates\n\
00103 \n\
00104     32CMS4324728161 (standard UTM zone = 32)\n\
00105     31CEM6066227959 (neighboring UTM zone = 31)\n\
00106       BBZ1945517770 (neighboring UPS zone)\n\
00107 \n\
00108 then\n\
00109     echo 79.9S 6.1E      | GeoConvert -p -3 -m       ==> 32CMS4328\n\
00110     echo 31CEM6066227959 | GeoConvert -p -3 -m       ==> 31CEM6027\n\
00111     echo 31CEM6066227959 | GeoConvert -p -3 -m -s    ==> 32CMS4328\n\
00112     echo 31CEM6066227959 | GeoConvert -p -3 -m -z 0  ==>   BBZ1917\n\
00113 \n\
00114 -h prints this help.\n";
00115   return retval;
00116 }
00117 
00118 int main(int argc, char* argv[]) {
00119   using namespace GeographicLib;
00120   typedef Math::real real;
00121   enum { GEOGRAPHIC, DMS, UTMUPS, MGRS, CONVERGENCE };
00122   int outputmode = GEOGRAPHIC;
00123   int prec = 0;
00124   int zone = UTMUPS::MATCH;
00125   bool centerp = true;
00126 
00127   for (int m = 1; m < argc; ++m) {
00128     std::string arg(argv[m]);
00129     if (arg == "-g")
00130       outputmode = GEOGRAPHIC;
00131     else if (arg == "-d")
00132       outputmode = DMS;
00133     else if (arg == "-u")
00134       outputmode = UTMUPS;
00135     else if (arg == "-m")
00136       outputmode = MGRS;
00137     else if (arg == "-c")
00138       outputmode = CONVERGENCE;
00139     else if (arg == "-n")
00140       centerp = false;
00141     else if (arg == "-p") {
00142       if (++m == argc) return usage(1);
00143       std::istringstream str(argv[m]);
00144       char c;
00145       if (!(str >> prec) || (str >> c)) {
00146           std::cerr << "Precision " << argv[m] << " is not a number\n";
00147           return 1;
00148       }
00149     } else if (arg == "-z") {
00150       if (++m == argc) return usage(1);
00151       std::string zonestr(argv[m]);
00152       try {
00153         bool northp;
00154         UTMUPS::DecodeZone(zonestr, zone, northp);
00155       }
00156       catch (const std::exception&) {
00157         std::istringstream str(zonestr);
00158         char c;
00159         if (!(str >> zone) || (str >> c)) {
00160           std::cerr << "Zone " << zonestr
00161                     << " is not a number or zone+hemisphere\n";
00162           return 1;
00163         }
00164         if (!(zone >= UTMUPS::MINZONE && zone <= UTMUPS::MAXZONE)) {
00165           std::cerr << "Zone " << zone << " not in [0, 60]\n";
00166           return 1;
00167         }
00168       }
00169     } else if (arg == "-s")
00170       zone = UTMUPS::STANDARD;
00171     else if (arg == "-t")
00172       zone = UTMUPS::UTM;
00173     else
00174       return usage(arg != "-h");
00175   }
00176 
00177   GeoCoords p;
00178   std::string s;
00179   std::string os;
00180   int retval = 0;
00181 
00182   while (std::getline(std::cin, s)) {
00183     try {
00184       p.Reset(s, centerp);
00185       p.SetAltZone(zone);
00186       switch (outputmode) {
00187       case GEOGRAPHIC:
00188         os = p.GeoRepresentation(prec);
00189         break;
00190       case DMS:
00191         os = p.DMSRepresentation(prec);
00192         break;
00193       case UTMUPS:
00194         os = p.AltUTMUPSRepresentation(prec);
00195         break;
00196       case MGRS:
00197         os = p.AltMGRSRepresentation(prec);
00198         break;
00199       case CONVERGENCE:
00200         {
00201           real
00202             gamma = p.AltConvergence(),
00203             k = p.AltScale();
00204           os =
00205             DMS::Encode(gamma, std::max(-5, std::min(8, prec)) + 5, DMS::NUMBER)
00206             + " " +
00207             DMS::Encode(k, std::max(-5, std::min(8, prec)) + 7, DMS::NUMBER);
00208         }
00209       }
00210     }
00211     catch (const std::exception& e) {
00212       // Write error message cout so output lines match input lines
00213       os = std::string("ERROR: ") + e.what();
00214       retval = 1;
00215     }
00216     std::cout << os << "\n";
00217   }
00218   return retval;
00219 }

Generated on 21 May 2010 for GeographicLib by  doxygen 1.6.1