00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00213 os = std::string("ERROR: ") + e.what();
00214 retval = 1;
00215 }
00216 std::cout << os << "\n";
00217 }
00218 return retval;
00219 }