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
00014 namespace GeographicLib {
00015
00016 using namespace std;
00017
00018 void GeoCoords::Reset(const std::string& s, bool centerp, bool swaplatlong) {
00019 vector<string> sa;
00020 const char* spaces = " \t\n\v\f\r,";
00021 for (string::size_type pos0 = 0, pos1; pos0 != string::npos;) {
00022 pos1 = s.find_first_not_of(spaces, pos0);
00023 if (pos1 == string::npos)
00024 break;
00025 pos0 = s.find_first_of(spaces, pos1);
00026 sa.push_back(s.substr(pos1, pos0 == string::npos ? pos0 : pos0 - pos1));
00027 }
00028 if (sa.size() == 1) {
00029 int prec;
00030 MGRS::Reverse(sa[0], _zone, _northp, _easting, _northing, prec, centerp);
00031 UTMUPS::Reverse(_zone, _northp, _easting, _northing,
00032 _lat, _long, _gamma, _k);
00033 } else if (sa.size() == 2) {
00034 DMS::DecodeLatLon(sa[0], sa[1], _lat, _long, swaplatlong);
00035 UTMUPS::Forward( _lat, _long,
00036 _zone, _northp, _easting, _northing, _gamma, _k);
00037 } else if (sa.size() == 3) {
00038 unsigned zoneind, coordind;
00039 if (sa[0].size() > 0 && isalpha(sa[0][sa[0].size() - 1])) {
00040 zoneind = 0;
00041 coordind = 1;
00042 } else if (sa[2].size() > 0 && isalpha(sa[2][sa[2].size() - 1])) {
00043 zoneind = 2;
00044 coordind = 0;
00045 } else
00046 throw GeographicErr("Neither " + sa[0] + " nor " + sa[2]
00047 + " of the form UTM/UPS Zone + Hemisphere"
00048 + " (ex: 38n, 09s, n)");
00049 UTMUPS::DecodeZone(sa[zoneind], _zone, _northp);
00050 for (unsigned i = 0; i < 2; ++i)
00051 (i ? _northing : _easting) = DMS::Decode(sa[coordind + i]);
00052 UTMUPS::Reverse(_zone, _northp, _easting, _northing,
00053 _lat, _long, _gamma, _k);
00054 FixHemisphere();
00055 } else
00056 throw GeographicErr("Coordinate requires 1, 2, or 3 elements");
00057 CopyToAlt();
00058 }
00059
00060 string GeoCoords::GeoRepresentation(int prec, bool swaplatlong) const {
00061 prec = max(0, min(9 + Math::extra_digits(), prec) + 5);
00062 ostringstream os;
00063 os << fixed << setprecision(prec);
00064 real a = swaplatlong ? _long : _lat;
00065 real b = swaplatlong ? _lat : _long;
00066 if (!Math::isnan(a))
00067 os << a;
00068 else
00069 os << "nan";
00070 os << " ";
00071 if (!Math::isnan(b))
00072 os << b;
00073 else
00074 os << "nan";
00075 return os.str();
00076 }
00077
00078 string GeoCoords::DMSRepresentation(int prec, bool swaplatlong,
00079 char dmssep) const {
00080 prec = max(0, min(10 + Math::extra_digits(), prec) + 5);
00081 return DMS::Encode(swaplatlong ? _long : _lat, unsigned(prec),
00082 swaplatlong ? DMS::LONGITUDE : DMS::LATITUDE, dmssep) +
00083 " " + DMS::Encode(swaplatlong ? _lat : _long, unsigned(prec),
00084 swaplatlong ? DMS::LATITUDE : DMS::LONGITUDE, dmssep);
00085 }
00086
00087 string GeoCoords::MGRSRepresentation(int prec) const {
00088
00089 prec = max(-1, min(6, prec) + 5);
00090 string mgrs;
00091 MGRS::Forward(_zone, _northp, _easting, _northing, _lat, prec, mgrs);
00092 return mgrs;
00093 }
00094
00095 string GeoCoords::AltMGRSRepresentation(int prec) const {
00096
00097 prec = max(-1, min(6, prec) + 5);
00098 string mgrs;
00099 MGRS::Forward(_alt_zone, _northp, _alt_easting, _alt_northing, _lat, prec,
00100 mgrs);
00101 return mgrs;
00102 }
00103
00104 void GeoCoords::UTMUPSString(int zone, bool northp,
00105 real easting, real northing, int prec,
00106 bool abbrev, std::string& utm) {
00107 ostringstream os;
00108 prec = max(-5, min(9 + Math::extra_digits(), prec));
00109 real scale = prec < 0 ? pow(real(10), -prec) : real(1);
00110 os << UTMUPS::EncodeZone(zone, northp, abbrev) << fixed << setfill('0');
00111 if (Math::isfinite(easting)) {
00112 os << " " << setprecision(max(0, prec)) << easting / scale;
00113 if (prec < 0 && abs(easting / scale) > real(0.5))
00114 os << setw(-prec) << 0;
00115 } else
00116 os << " nan";
00117 if (Math::isfinite(northing)) {
00118 os << " " << setprecision(max(0, prec)) << northing / scale;
00119 if (prec < 0 && abs(northing / scale) > real(0.5))
00120 os << setw(-prec) << 0;
00121 } else
00122 os << " nan";
00123 utm = os.str();
00124 }
00125
00126 string GeoCoords::UTMUPSRepresentation(int prec, bool abbrev) const {
00127 string utm;
00128 UTMUPSString(_zone, _northp, _easting, _northing, prec, abbrev, utm);
00129 return utm;
00130 }
00131
00132 string GeoCoords::UTMUPSRepresentation(bool northp, int prec, bool abbrev)
00133 const {
00134 real e, n;
00135 int z;
00136 UTMUPS::Transfer(_zone, _northp, _easting, _northing,
00137 _zone, northp, e, n, z);
00138 string utm;
00139 UTMUPSString(_zone, northp, e, n, prec, abbrev, utm);
00140 return utm;
00141 }
00142
00143 string GeoCoords::AltUTMUPSRepresentation(int prec, bool abbrev) const {
00144 string utm;
00145 UTMUPSString(_alt_zone, _northp, _alt_easting, _alt_northing, prec,
00146 abbrev, utm);
00147 return utm;
00148 }
00149
00150 string GeoCoords::AltUTMUPSRepresentation(bool northp, int prec, bool abbrev)
00151 const {
00152 real e, n;
00153 int z;
00154 UTMUPS::Transfer(_alt_zone, _northp, _alt_easting, _alt_northing,
00155 _alt_zone, northp, e, n, z);
00156 string utm;
00157 UTMUPSString(_alt_zone, northp, e, n, prec, abbrev, utm);
00158 return utm;
00159 }
00160
00161 void GeoCoords::FixHemisphere() {
00162 if (_lat == 0 || (_northp && _lat >= 0) || (!_northp && _lat < 0) ||
00163 Math::isnan(_lat))
00164
00165 return;
00166 if (_zone != UTMUPS::UPS) {
00167 _northing += (_northp ? 1 : -1) * UTMUPS::UTMShift();
00168 _northp = !_northp;
00169 } else
00170 throw GeographicErr("Hemisphere mixup");
00171 }
00172
00173 }