00001 /** 00002 * \file UTMUPS.hpp 00003 * \brief Header for GeographicLib::UTMUPS class 00004 * 00005 * Copyright (c) Charles Karney (2008) <charles@karney.com> 00006 * and licensed under the LGPL. 00007 **********************************************************************/ 00008 00009 00010 #if !defined(UTMUPS_HPP) 00011 #define UTMUPS_HPP "$Id: UTMUPS.hpp 6535 2009-02-10 22:37:07Z ckarney $" 00012 00013 #include <string> 00014 #include <sstream> 00015 00016 namespace GeographicLib { 00017 00018 /** 00019 * \brief Convert between Geographic coordinates and UTM/UPS 00020 * 00021 * UTM and UPS are defined 00022 * - <a href="http://earth-info.nga.mil/GandG/publications/tm8358.2/TM8358_2.pdf"> 00023 * The Universal Grids: Universal Transverse Mercator (UTM) and Universal 00024 * Polar Stereographic (UPS)</a>, Defense Mapping Agency, Technical Manual 00025 * TM8358.2 (1989). 00026 * . 00027 * Section 2-3 defines UTM and section 3-2.4 defines UPS. This document also 00028 * includes approximate algorithms for the computation of the underlying 00029 * transverse Mercator and polar stereographic projections. Here we 00030 * substitute much more accurate algorithms given by 00031 * GeographicLib:TransverseMercator and GeographicLib:PolarStereographic. 00032 * 00033 * In this implementation, the conversions are closed, i.e., output from 00034 * Forward is legal input for Reverse and vice versa. The error is about 5nm 00035 * in each direction. However, the conversion from legal UTM/UPS coordinates 00036 * to geographic coordinates and back might throw an error if the initial 00037 * point is within 5nm of the edge of the allowed range for the UTM/UPS 00038 * coordinates. 00039 * 00040 * The simplest way to guarantee the closed property is to define allowed 00041 * ranges for the eastings and northings for UTM and UPS coordinates. The 00042 * UTM boundaries are the same for all zones. (The only place the 00043 * exceptional nature of the zone boundaries is evident is when converting to 00044 * UTM/UPS coordinates requesting the standard zone.) The MGRS lettering 00045 * scheme imposes natural limits on UTM/UPS coordinates which may be 00046 * converted into MGRS coordinates. For the conversion to/from geographic 00047 * coordinates these ranges have been extended by 100km in order to provide a 00048 * generous overlap between UTM and UPS and between UTM zones. 00049 * 00050 * The <a href="http://www.nga.mil">NGA</a> software package 00051 * <a href="http://earth-info.nga.mil/GandG/geotrans/index.html">geotrans</a> 00052 * also provides conversions to and from UTM and UPS. Version 2.4.2 (and 00053 * earlier) suffers from some drawbacks: 00054 * - Inconsistent rules are used to determine the whether a particular UTM or 00055 * UPS coordinate is legal. A more systematic approach is taken here. 00056 * - The underlying projections are not very accurately implemented. 00057 **********************************************************************/ 00058 class UTMUPS { 00059 private: 00060 static const double falseeasting[4]; 00061 static const double falsenorthing[4]; 00062 static const double mineasting[4]; 00063 static const double maxeasting[4]; 00064 static const double minnorthing[4]; 00065 static const double maxnorthing[4]; 00066 static double CentralMeridian(int zone) throw() { return 6 * zone - 183.0; } 00067 template<typename T> static std::string str(T x) { 00068 std::ostringstream s; s << x; return s.str(); 00069 } 00070 static void CheckLatLon(double lat, double lon); 00071 // Throw an error if easting or northing are outside standard ranges. If 00072 // throwp = false, return bool instead. 00073 static bool CheckCoords(bool utmp, bool northp, double x, double y, 00074 bool throwp = true); 00075 public: 00076 00077 /** 00078 * Return the standard zone for latitude \e lat (degrees) and longitude \e 00079 * lon (degrees). Return 0 if in the standard regions for UPS otherwise 00080 * return the UTM zone. This includes the Norway and Svalbard exceptions. 00081 * The tests on latitudes and longitudes are all closed on the lower end 00082 * open on the upper. Thus for UTM zone 38, latitude is in [-80, 84) and 00083 * longitude is in [42, 48). This is exact. 00084 **********************************************************************/ 00085 static int StandardZone(double lat, double lon) throw(); 00086 00087 /** 00088 * Convert geographic coordinates to UTM or UPS coordinate. Given latitude 00089 * \e lat (degrees), and longitude \e lon (degrees), return \e zone (zero 00090 * indicates UPS), hemisphere \e northp (false means south, true means 00091 * north), easting \e x (meters), and northing \e y (meters). The prefered 00092 * zone for the result can be specified with \e setzone (negative means 00093 * result of UTMUPS::StandardZone, zero means UPS, positive means a 00094 * particular UTM zone), Throw error if the resulting easting or northing 00095 * is outside the allowed range (see Reverse). This also returns meridian 00096 * convergence \e gamma (degrees) and scale \e k. The accuracy of the 00097 * conversion is about 5nm. 00098 * 00099 * To extent the standard UTM zones into the UPS regions use \e setzone = 00100 * UTMUPS::StandardZone(max(-80.0, min(80.0, \e lat))). 00101 **********************************************************************/ 00102 static void Forward(double lat, double lon, 00103 int& zone, bool& northp, double& x, double& y, 00104 double& gamma, double& k, 00105 int setzone = -1); 00106 00107 /** 00108 * Convert UTM or UPS coordinate to geographic coordinates . Given zone \e 00109 * zone (\e zone == 0 indicates UPS), hemisphere \e northp (false means 00110 * south, true means north), easting \e x (meters), and northing \e y 00111 * (meters), return latitude \e lat (degrees) and longitude \e lon 00112 * (degrees). Throw error if easting or northing is outside the allowed 00113 * range (see below). This also returns meridian convergence \e gamma 00114 * (degrees) and scale \e k. The accuracy of the conversion is about 5nm. 00115 * 00116 * UTM eastings are allowed to be in the range [0km, 1000km], northings are 00117 * allowed to be in in [0km, 9600km] for the northern hemisphere and in 00118 * [900km, 10000km] for the southern hemisphere. (However UTM northings 00119 * can be continued across the equator. So the actual limits on the 00120 * northings are [-9100km, 9600km] for the "northern" hemisphere and 00121 * [900km, 19600km] for the "southern" hemisphere.) 00122 * 00123 * UPS eastings and northings are allowed to be in the range [1200km, 00124 * 2800km] in the northern hemisphere and in [700km, 3100km] in the 00125 * southern hemisphere. 00126 * 00127 * These ranges are 100km larger than allowed for the conversions to MGRS. 00128 * (100km is the maximum extra padding consistent with eastings remaining 00129 * non-negative.) This allows generous overlaps between zones and UTM and 00130 * UPS. No checks are performed beyond these (e.g., to limit the distance 00131 * outside the standard zone boundaries). 00132 **********************************************************************/ 00133 static void Reverse(int zone, bool northp, double x, double y, 00134 double& lat, double& lon, double& gamma, double& k); 00135 00136 /** 00137 * Forward without returning convergence and scale. 00138 **********************************************************************/ 00139 static void Forward(double lat, double lon, 00140 int& zone, bool& northp, double& x, double& y, 00141 int setzone = -1) { 00142 double gamma, k; 00143 Forward(lat, lon, zone, northp, x, y, gamma, k, setzone); 00144 } 00145 00146 /** 00147 * Reverse without returning convergence and scale. 00148 **********************************************************************/ 00149 static void Reverse(int zone, bool northp, double x, double y, 00150 double& lat, double& lon) { 00151 double gamma, k; 00152 Reverse(zone, northp, x, y, lat, lon, gamma, k); 00153 } 00154 }; 00155 00156 } // namespace GeographicLib 00157 #endif