GeographicLib
1.21
|
00001 /** 00002 * \file GeoCoords.cpp 00003 * \brief Implementation for GeographicLib::GeoCoords class 00004 * 00005 * Copyright (c) Charles Karney (2008-2011) <charles@karney.com> and licensed 00006 * under the MIT/X11 License. For more information, see 00007 * http://geographiclib.sourceforge.net/ 00008 **********************************************************************/ 00009 00010 #include <GeographicLib/GeoCoords.hpp> 00011 #include <vector> 00012 #include <sstream> 00013 #include <iomanip> 00014 #include <GeographicLib/MGRS.hpp> 00015 #include <GeographicLib/DMS.hpp> 00016 00017 #define GEOGRAPHICLIB_GEOCOORDS_CPP \ 00018 "$Id: 084d4ec9163dc9d8989b54b12a04bf0f44a8c23f $" 00019 00020 RCSID_DECL(GEOGRAPHICLIB_GEOCOORDS_CPP) 00021 RCSID_DECL(GEOGRAPHICLIB_GEOCOORDS_HPP) 00022 00023 namespace GeographicLib { 00024 00025 using namespace std; 00026 00027 void GeoCoords::Reset(const std::string& s, bool centerp, bool swaplatlong) { 00028 vector<string> sa; 00029 const char* spaces = " \t\n\v\f\r,"; // Include comma as a space 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, swaplatlong); 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 (i ? _northing : _easting) = DMS::Decode(sa[coordind + i]); 00061 UTMUPS::Reverse(_zone, _northp, _easting, _northing, 00062 _lat, _long, _gamma, _k); 00063 FixHemisphere(); 00064 } else 00065 throw GeographicErr("Coordinate requires 1, 2, or 3 elements"); 00066 CopyToAlt(); 00067 } 00068 00069 00070 string GeoCoords::GeoRepresentation(int prec, bool swaplatlong) const { 00071 prec = max(0, min(9, prec) + 5); 00072 ostringstream os; 00073 os << fixed << setprecision(prec); 00074 real a = swaplatlong ? _long : _lat; 00075 real b = swaplatlong ? _lat : _long; 00076 if (!Math::isnan(a)) 00077 os << a; 00078 else 00079 os << "nan"; 00080 os << " "; 00081 if (!Math::isnan(b)) 00082 os << b; 00083 else 00084 os << "nan"; 00085 return os.str(); 00086 } 00087 00088 string GeoCoords::DMSRepresentation(int prec, bool swaplatlong, 00089 char dmssep) const { 00090 prec = max(0, min(10, prec) + 5); 00091 return DMS::Encode(swaplatlong ? _long : _lat, unsigned(prec), 00092 swaplatlong ? DMS::LONGITUDE : DMS::LATITUDE, dmssep) + 00093 " " + DMS::Encode(swaplatlong ? _lat : _long, unsigned(prec), 00094 swaplatlong ? DMS::LATITUDE : DMS::LONGITUDE, dmssep); 00095 } 00096 00097 string GeoCoords::DMSRepresentation(int prec, bool swaplatlong) const 00098 { return DMSRepresentation(prec, swaplatlong, char(0)); } 00099 00100 string GeoCoords::MGRSRepresentation(int prec) const { 00101 // Max precision is um 00102 prec = max(0, min(6, prec) + 5); 00103 string mgrs; 00104 MGRS::Forward(_zone, _northp, _easting, _northing, _lat, prec, mgrs); 00105 return mgrs; 00106 } 00107 00108 string GeoCoords::AltMGRSRepresentation(int prec) const { 00109 // Max precision is um 00110 prec = max(0, min(6, prec) + 5); 00111 string mgrs; 00112 MGRS::Forward(_alt_zone, _northp, _alt_easting, _alt_northing, _lat, prec, 00113 mgrs); 00114 return mgrs; 00115 } 00116 00117 void GeoCoords::UTMUPSString(int zone, real easting, real northing, int prec, 00118 std::string& utm) const { 00119 ostringstream os; 00120 prec = max(-5, min(9, prec)); 00121 real scale = prec < 0 ? pow(real(10), -prec) : real(1); 00122 os << UTMUPS::EncodeZone(zone, _northp) << fixed << setfill('0'); 00123 if (Math::isfinite(easting)) { 00124 os << " " << setprecision(max(0, prec)) << easting / scale; 00125 if (prec < 0 && abs(easting / scale) > real(0.5)) 00126 os << setw(-prec) << 0; 00127 } else 00128 os << " nan"; 00129 if (Math::isfinite(northing)) { 00130 os << " " << setprecision(max(0, prec)) << northing / scale; 00131 if (prec < 0 && abs(northing / scale) > real(0.5)) 00132 os << setw(-prec) << 0; 00133 } else 00134 os << " nan"; 00135 utm = os.str(); 00136 } 00137 00138 string GeoCoords::UTMUPSRepresentation(int prec) const { 00139 string utm; 00140 UTMUPSString(_zone, _easting, _northing, prec, utm); 00141 return utm; 00142 } 00143 00144 string GeoCoords::AltUTMUPSRepresentation(int prec) const { 00145 string utm; 00146 UTMUPSString(_alt_zone, _alt_easting, _alt_northing, prec, utm); 00147 return utm; 00148 } 00149 00150 void GeoCoords::FixHemisphere() { 00151 if (_lat == 0 || (_northp && _lat >= 0) || (!_northp && _lat < 0) || 00152 Math::isnan(_lat)) 00153 // Allow either hemisphere for equator 00154 return; 00155 if (_zone != UTMUPS::UPS) { 00156 _northing += (_northp ? 1 : -1) * UTMUPS::UTMShift(); 00157 _northp = !_northp; 00158 } else 00159 throw GeographicErr("Hemisphere mixup"); 00160 } 00161 00162 } // namespace GeographicLib