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