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 6921 2010-12-31 14:34:50Z 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
00030
00031
00032 for (string::size_type pos0 = 0, pos1; pos0 != string::npos;) {
00033 pos1 = s.find_first_not_of(spaces, pos0);
00034 if (pos1 == string::npos)
00035 break;
00036 pos0 = s.find_first_of(spaces, pos1);
00037 sa.push_back(s.substr(pos1, pos0 == string::npos ? pos0 : pos0 - pos1));
00038 }
00039 if (sa.size() == 1) {
00040 int prec;
00041 MGRS::Reverse(sa[0], _zone, _northp, _easting, _northing, prec, centerp);
00042 UTMUPS::Reverse(_zone, _northp, _easting, _northing,
00043 _lat, _long, _gamma, _k);
00044 } else if (sa.size() == 2) {
00045 DMS::DecodeLatLon(sa[0], sa[1], _lat, _long);
00046 UTMUPS::Forward( _lat, _long,
00047 _zone, _northp, _easting, _northing, _gamma, _k);
00048 } else if (sa.size() == 3) {
00049 unsigned zoneind, coordind;
00050 if (sa[0].size() > 0 && isalpha(sa[0][sa[0].size() - 1])) {
00051 zoneind = 0;
00052 coordind = 1;
00053 } else if (sa[2].size() > 0 && isalpha(sa[2][sa[2].size() - 1])) {
00054 zoneind = 2;
00055 coordind = 0;
00056 } else
00057 throw GeographicErr("Neither " + sa[0] + " nor " + sa[2]
00058 + " of the form UTM/UPS Zone + Hemisphere"
00059 + " (ex: 38N, 09S, N)");
00060 UTMUPS::DecodeZone(sa[zoneind], _zone, _northp);
00061 for (unsigned i = 0; i < 2; ++i)
00062 (i ? _northing : _easting) = DMS::Decode(sa[coordind + i]);
00063 UTMUPS::Reverse(_zone, _northp, _easting, _northing,
00064 _lat, _long, _gamma, _k);
00065 FixHemisphere();
00066 } else
00067 throw GeographicErr("Coordinate requires 1, 2, or 3 elements");
00068 CopyToAlt();
00069 }
00070
00071
00072 string GeoCoords::GeoRepresentation(int prec) const {
00073 prec = max(0, min(9, prec) + 5);
00074 ostringstream os;
00075 os << fixed << setprecision(prec);
00076 if (_lat == _lat)
00077 os << _lat;
00078 else
00079 os << "nan";
00080 os << " ";
00081 if (_long == _long)
00082 os << _long;
00083 else
00084 os << "nan";
00085 return os.str();
00086 }
00087
00088 string GeoCoords::DMSRepresentation(int prec) const {
00089 prec = max(0, min(10, prec) + 5);
00090 return DMS::Encode(_lat, unsigned(prec), DMS::LATITUDE) +
00091 " " + DMS::Encode(_long, unsigned(prec), DMS::LONGITUDE);
00092 }
00093
00094 string GeoCoords::MGRSRepresentation(int prec) const {
00095
00096 prec = max(0, min(6, prec) + 5);
00097 string mgrs;
00098 MGRS::Forward(_zone, _northp, _easting, _northing, _lat, prec, mgrs);
00099 return mgrs;
00100 }
00101
00102 string GeoCoords::AltMGRSRepresentation(int prec) const {
00103
00104 prec = max(0, min(6, prec) + 5);
00105 string mgrs;
00106 MGRS::Forward(_alt_zone, _northp, _alt_easting, _alt_northing, _lat, prec,
00107 mgrs);
00108 return mgrs;
00109 }
00110
00111 void GeoCoords::UTMUPSString(int zone, real easting, real northing, int prec,
00112 std::string& utm) const {
00113 ostringstream os;
00114 prec = max(-5, min(9, prec));
00115 real scale = prec < 0 ? pow(real(10), -prec) : real(1);
00116 os << UTMUPS::EncodeZone(zone, _northp) << fixed << setfill('0');
00117 if (Math::isfinite(easting)) {
00118 os << " " << setprecision(max(0, prec)) << easting / scale;
00119 if (prec < 0 && abs(easting / scale) > real(0.5))
00120 os << setw(-prec) << 0;
00121 } else
00122 os << " nan";
00123 if (Math::isfinite(northing)) {
00124 os << " " << setprecision(max(0, prec)) << northing / scale;
00125 if (prec < 0 && abs(northing / scale) > real(0.5))
00126 os << setw(-prec) << 0;
00127 } else
00128 os << " nan";
00129 utm = os.str();
00130 }
00131
00132 string GeoCoords::UTMUPSRepresentation(int prec) const {
00133 string utm;
00134 UTMUPSString(_zone, _easting, _northing, prec, utm);
00135 return utm;
00136 }
00137
00138 string GeoCoords::AltUTMUPSRepresentation(int prec) const {
00139 string utm;
00140 UTMUPSString(_alt_zone, _alt_easting, _alt_northing, prec, utm);
00141 return utm;
00142 }
00143
00144 void GeoCoords::FixHemisphere() {
00145 if (_lat == 0 || (_northp && _lat >= 0) || (!_northp && _lat < 0) ||
00146 _lat != _lat)
00147
00148 return;
00149 if (_zone != UTMUPS::UPS) {
00150 _northing += (_northp ? 1 : -1) * UTMUPS::UTMShift();
00151 _northp = !_northp;
00152 } else
00153 throw GeographicErr("Hemisphere mixup");
00154 }
00155
00156 }