00001 /** 00002 * \file OSGB.hpp 00003 * \brief Header for GeographicLib::OSGB class 00004 * 00005 * Copyright (c) Charles Karney (2010-2013) <charles@karney.com> and licensed 00006 * under the MIT/X11 License. For more information, see 00007 * http://geographiclib.sourceforge.net/ 00008 **********************************************************************/ 00009 00010 #if !defined(GEOGRAPHICLIB_OSGB_HPP) 00011 #define GEOGRAPHICLIB_OSGB_HPP 1 00012 00013 #include <GeographicLib/Constants.hpp> 00014 #include <GeographicLib/TransverseMercator.hpp> 00015 00016 #if defined(_MSC_VER) 00017 // Squelch warnings about dll vs string 00018 # pragma warning (push) 00019 # pragma warning (disable: 4251) 00020 #endif 00021 00022 namespace GeographicLib { 00023 00024 /** 00025 * \brief Ordnance Survey grid system for Great Britain 00026 * 00027 * The class implements the coordinate system used by the Ordnance Survey for 00028 * maps of Great Britain and conversions to the grid reference system. 00029 * 00030 * See 00031 * - <a href="http://www.ordnancesurvey.co.uk/docs/support/guide-coordinate-systems-great-britain.pdf"> 00032 * A guide to coordinate systems in Great Britain</a> 00033 * - <a href="http://www.ordnancesurvey.co.uk/docs/support/national-grid.pdf"> 00034 * Guide to the National Grid</a> 00035 * 00036 * \b WARNING: the latitudes and longitudes for the Ordnance Survey grid 00037 * system do not use the WGS84 datum. Do not use the values returned by this 00038 * class in the UTMUPS, MGRS, or Geoid classes without first converting the 00039 * datum (and vice versa). 00040 * 00041 * Example of use: 00042 * \include example-OSGB.cpp 00043 **********************************************************************/ 00044 class GEOGRAPHICLIB_EXPORT OSGB { 00045 private: 00046 typedef Math::real real; 00047 static const std::string letters_; 00048 static const std::string digits_; 00049 static const TransverseMercator& OSGBTM(); 00050 static real northoffset_; 00051 static bool init_; 00052 enum { 00053 base_ = 10, 00054 tile_ = 100000, 00055 tilelevel_ = 5, 00056 tilegrid_ = 5, 00057 tileoffx_ = 2 * tilegrid_, 00058 tileoffy_ = 1 * tilegrid_, 00059 minx_ = - tileoffx_ * tile_, 00060 miny_ = - tileoffy_ * tile_, 00061 maxx_ = (tilegrid_*tilegrid_ - tileoffx_) * tile_, 00062 maxy_ = (tilegrid_*tilegrid_ - tileoffy_) * tile_, 00063 // Maximum precision is um 00064 maxprec_ = 5 + 6, 00065 }; 00066 static real computenorthoffset(); 00067 static void CheckCoords(real x, real y); 00068 OSGB(); // Disable constructor 00069 public: 00070 00071 /** 00072 * Forward projection, from geographic to OSGB coordinates. 00073 * 00074 * @param[in] lat latitude of point (degrees). 00075 * @param[in] lon longitude of point (degrees). 00076 * @param[out] x easting of point (meters). 00077 * @param[out] y northing of point (meters). 00078 * @param[out] gamma meridian convergence at point (degrees). 00079 * @param[out] k scale of projection at point. 00080 * 00081 * \e lat should be in the range [−90°, 90°]; \e lon 00082 * should be in the range [−540°, 540°). 00083 **********************************************************************/ 00084 static void Forward(real lat, real lon, 00085 real& x, real& y, real& gamma, real& k) { 00086 OSGBTM().Forward(OriginLongitude(), lat, lon, x, y, gamma, k); 00087 x += FalseEasting(); 00088 y += computenorthoffset(); 00089 } 00090 00091 /** 00092 * Reverse projection, from OSGB coordinates to geographic. 00093 * 00094 * @param[in] x easting of point (meters). 00095 * @param[in] y northing of point (meters). 00096 * @param[out] lat latitude of point (degrees). 00097 * @param[out] lon longitude of point (degrees). 00098 * @param[out] gamma meridian convergence at point (degrees). 00099 * @param[out] k scale of projection at point. 00100 * 00101 * The value of \e lon returned is in the range [−180°, 00102 * 180°). 00103 **********************************************************************/ 00104 00105 static void Reverse(real x, real y, 00106 real& lat, real& lon, real& gamma, real& k) { 00107 x -= FalseEasting(); 00108 y -= computenorthoffset(); 00109 OSGBTM().Reverse(OriginLongitude(), x, y, lat, lon, gamma, k); 00110 } 00111 00112 /** 00113 * OSGB::Forward without returning the convergence and scale. 00114 **********************************************************************/ 00115 static void Forward(real lat, real lon, real& x, real& y) { 00116 real gamma, k; 00117 Forward(lat, lon, x, y, gamma, k); 00118 } 00119 00120 /** 00121 * OSGB::Reverse without returning the convergence and scale. 00122 **********************************************************************/ 00123 static void Reverse(real x, real y, real& lat, real& lon) { 00124 real gamma, k; 00125 Reverse(x, y, lat, lon, gamma, k); 00126 } 00127 00128 /** 00129 * Convert OSGB coordinates to a grid reference. 00130 * 00131 * @param[in] x easting of point (meters). 00132 * @param[in] y northing of point (meters). 00133 * @param[in] prec precision relative to 100 km. 00134 * @param[out] gridref National Grid reference. 00135 * @exception GeographicErr if \e prec, \e x, or \e y is outside its 00136 * allowed range. 00137 * @exception std::bad_alloc if the memory for \e gridref can't be 00138 * allocatied. 00139 * 00140 * \e prec specifies the precision of the grid reference string as follows: 00141 * - prec = 0 (min), 100km 00142 * - prec = 1, 10km 00143 * - prec = 2, 1km 00144 * - prec = 3, 100m 00145 * - prec = 4, 10m 00146 * - prec = 5, 1m 00147 * - prec = 6, 0.1m 00148 * - prec = 11 (max), 1μm 00149 * 00150 * The easting must be in the range [−1000 km, 1500 km) and the 00151 * northing must be in the range [−500 km, 2000 km). These bounds 00152 * are consistent with rules for the letter designations for the grid 00153 * system. 00154 **********************************************************************/ 00155 static void GridReference(real x, real y, int prec, std::string& gridref); 00156 00157 /** 00158 * Convert OSGB coordinates to a grid reference. 00159 * 00160 * @param[in] gridref National Grid reference. 00161 * @param[out] x easting of point (meters). 00162 * @param[out] y northing of point (meters). 00163 * @param[out] prec precision relative to 100 km. 00164 * @param[in] centerp if true (default), return center of the grid square, 00165 * else return SW (lower left) corner. 00166 * @exception GeographicErr if \e gridref is illegal. 00167 * 00168 * The grid reference must be of the form: two letters (not including I) 00169 * followed by an even number of digits (up to 22). 00170 **********************************************************************/ 00171 static void GridReference(const std::string& gridref, 00172 real& x, real& y, int& prec, 00173 bool centerp = true); 00174 00175 /** \name Inspector functions 00176 **********************************************************************/ 00177 ///@{ 00178 /** 00179 * @return \e a the equatorial radius of the Airy 1830 ellipsoid (meters). 00180 * 00181 * This is 20923713 ft converted to meters using the rule 1 ft = 00182 * 10<sup>9.48401603−10</sup> m. (The Airy 1830 value is returned 00183 * because the OSGB projection is based on this ellipsoid.) 00184 **********************************************************************/ 00185 static Math::real MajorRadius() { 00186 // result is about 6377563.3960320664406 m 00187 using std::pow; 00188 return pow(real(10), real(48401603 - 100000000) / 100000000) 00189 * 20923713; 00190 } 00191 00192 /** 00193 * @return \e f the inverse flattening of the Airy 1830 ellipsoid. 00194 * 00195 * For the Airy 1830 ellipsoid, \e a = 20923713 ft and \e b = 20853810 ft; 00196 * thus the flattening = (20923713 − 20853810)/20923713 = 00197 * 7767/2324857 = 1/299.32496459... (The Airy 1830 value is returned 00198 * because the OSGB projection is based on this ellipsoid.) 00199 **********************************************************************/ 00200 static Math::real Flattening() 00201 { return real(20923713 - 20853810) / 20923713; } 00202 00203 /// \cond SKIP 00204 /** 00205 * <b>DEPRECATED</b> 00206 * @return \e r the inverse flattening of the Airy 1830 ellipsoid. 00207 **********************************************************************/ 00208 static Math::real InverseFlattening() { return 1/Flattening(); } 00209 /// \endcond 00210 00211 /** 00212 * @return \e k0 central scale for the OSGB projection (0.9996012717...). 00213 * 00214 * C. J. Mugnier, Grids & Datums, PE&RS, Oct. 2003, states that 00215 * this is defined as 10<sup>9.9998268−10</sup>. 00216 **********************************************************************/ 00217 static Math::real CentralScale() { 00218 using std::pow; 00219 return pow(real(10), real(9998268 - 10000000) / 10000000); 00220 } 00221 00222 /** 00223 * @return latitude of the origin for the OSGB projection (49 degrees). 00224 **********************************************************************/ 00225 static Math::real OriginLatitude() { return real(49); } 00226 00227 /** 00228 * @return longitude of the origin for the OSGB projection (−2 00229 * degrees). 00230 **********************************************************************/ 00231 static Math::real OriginLongitude() { return real(-2); } 00232 00233 /** 00234 * @return false northing the OSGB projection (−100000 meters). 00235 **********************************************************************/ 00236 static Math::real FalseNorthing() { return real(-100000); } 00237 00238 /** 00239 * @return false easting the OSGB projection (400000 meters). 00240 **********************************************************************/ 00241 static Math::real FalseEasting() { return real(400000); } 00242 ///@} 00243 00244 }; 00245 00246 } // namespace GeographicLib 00247 00248 #if defined(_MSC_VER) 00249 # pragma warning (pop) 00250 #endif 00251 00252 #endif // GEOGRAPHICLIB_OSGB_HPP