00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "GeographicLib/GeoCoords.hpp"
00011 #include "GeographicLib/MGRS.hpp"
00012 #include "GeographicLib/DMS.hpp"
00013 #include <vector>
00014 #include <sstream>
00015 #include <iomanip>
00016
00017 #define GEOGRAPHICLIB_GEOCOORDS_CPP "$Id: GeoCoords.cpp 6785 2010-01-05 22:15:42Z karney $"
00018
00019 RCSID_DECL(GEOGRAPHICLIB_GEOCOORDS_CPP)
00020 RCSID_DECL(GEOGRAPHICLIB_GEOCOORDS_HPP)
00021
00022 namespace GeographicLib {
00023
00024 using namespace std;
00025
00026 void GeoCoords::Reset(const std::string& s, bool centerp) {
00027 vector<string> sa;
00028 const char* spaces = " \t\n\v\f\r,";
00029 const char* digits = "0123456789.";
00030 for (string::size_type pos0 = 0, pos1; pos0 != string::npos;) {
00031 pos1 = s.find_first_not_of(spaces, pos0);
00032 if (pos1 == string::npos)
00033 break;
00034 pos0 = s.find_first_of(spaces, pos1);
00035 sa.push_back(s.substr(pos1, pos0 == string::npos ? pos0 : pos0 - pos1));
00036 }
00037 if (sa.size() == 1) {
00038 int prec;
00039 MGRS::Reverse(sa[0], _zone, _northp, _easting, _northing, prec, centerp);
00040 UTMUPS::Reverse(_zone, _northp, _easting, _northing,
00041 _lat, _long, _gamma, _k);
00042 } else if (sa.size() == 2) {
00043 DMS::DecodeLatLon(sa[0], sa[1], _lat, _long);
00044 UTMUPS::Forward( _lat, _long,
00045 _zone, _northp, _easting, _northing, _gamma, _k);
00046 } else if (sa.size() == 3) {
00047 unsigned zoneind, coordind;
00048 if (sa[0].size() > 0 && isalpha(sa[0][sa[0].size() - 1])) {
00049 zoneind = 0;
00050 coordind = 1;
00051 } else if (sa[2].size() > 0 && isalpha(sa[2][sa[2].size() - 1])) {
00052 zoneind = 2;
00053 coordind = 0;
00054 } else
00055 throw GeographicErr("Neither " + sa[0] + " nor " + sa[2]
00056 + " of the form UTM/UPS Zone + Hemisphere"
00057 + " (ex: 38N, 09S, N)");
00058 UTMUPS::DecodeZone(sa[zoneind], _zone, _northp);
00059 for (unsigned i = 0; i < 2; ++i) {
00060 istringstream str(sa[coordind + i]);
00061 real x;
00062 if (!(str >> x))
00063 throw GeographicErr("Bad number " + sa[coordind + i]
00064 + " for UTM/UPS "
00065 + (i == 0 ? "easting " : "northing "));
00066
00067
00068
00069
00070
00071
00072
00073 int pos = min(int(str.tellg()),
00074 int(sa[coordind + i].find_last_of(digits)) + 1);
00075 if (pos != int(sa[coordind + i].size()))
00076 throw GeographicErr("Extra text "
00077 + sa[coordind + i].substr(pos) + " in UTM/UPS "
00078 + (i == 0 ? "easting " : "northing ")
00079 + sa[coordind + i]);
00080 (i ? _northing : _easting) = x;
00081 }
00082 UTMUPS::Reverse(_zone, _northp, _easting, _northing,
00083 _lat, _long, _gamma, _k);
00084 FixHemisphere();
00085 } else
00086 throw GeographicErr("Coordinate requires 1, 2, or 3 elements");
00087 CopyToAlt();
00088 }
00089
00090
00091 string GeoCoords::GeoRepresentation(int prec) const {
00092 prec = max(0, min(9, prec) + 5);
00093 ostringstream os;
00094 os << fixed << setprecision(prec) << _lat << " " << _long;
00095 return os.str();
00096 }
00097
00098 string GeoCoords::DMSRepresentation(int prec) const {
00099 prec = max(0, min(10, prec) + 5);
00100 return DMS::Encode(_lat, unsigned(prec), DMS::LATITUDE) +
00101 " " + DMS::Encode(_long, unsigned(prec), DMS::LONGITUDE);
00102 }
00103
00104 string GeoCoords::MGRSRepresentation(int prec) const {
00105
00106 prec = max(0, min(6, prec) + 5);
00107 string mgrs;
00108 MGRS::Forward(_zone, _northp, _easting, _northing, _lat, prec, mgrs);
00109 return mgrs;
00110 }
00111
00112 string GeoCoords::AltMGRSRepresentation(int prec) const {
00113
00114 prec = max(0, min(6, prec) + 5);
00115 string mgrs;
00116 MGRS::Forward(_alt_zone, _northp, _alt_easting, _alt_northing, _lat, prec,
00117 mgrs);
00118 return mgrs;
00119 }
00120
00121 void GeoCoords::UTMUPSString(int zone, real easting, real northing, int prec,
00122 std::string& utm) const {
00123 ostringstream os;
00124 prec = max(-5, min(9, prec));
00125 real scale = prec < 0 ? pow(real(10), -prec) : real(1);
00126 os << UTMUPS::EncodeZone(zone, _northp) << fixed << setfill('0');
00127 os << " " << setprecision(max(0, prec)) << easting / scale;
00128 if (prec < 0 && abs(easting / scale) > real(0.5))
00129 os << setw(-prec) << 0;
00130 os << " " << setprecision(max(0, prec)) << northing / scale;
00131 if (prec < 0 && abs(northing / scale) > real(0.5))
00132 os << setw(-prec) << 0;
00133 utm = os.str();
00134 }
00135
00136 string GeoCoords::UTMUPSRepresentation(int prec) const {
00137 string utm;
00138 UTMUPSString(_zone, _easting, _northing, prec, utm);
00139 return utm;
00140 }
00141
00142 string GeoCoords::AltUTMUPSRepresentation(int prec) const {
00143 string utm;
00144 UTMUPSString(_alt_zone, _alt_easting, _alt_northing, prec, utm);
00145 return utm;
00146 }
00147
00148 void GeoCoords::FixHemisphere() {
00149 if (_lat == 0 || (_northp && _lat >= 0) || (!_northp && _lat < 0))
00150
00151 return;
00152 if (_zone != UTMUPS::UPS) {
00153 _northing += (_northp ? 1 : -1) * UTMUPS::UTMShift();
00154 _northp = !_northp;
00155 } else
00156 throw GeographicErr("Hemisphere mixup");
00157 }
00158
00159 }