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) <charles@karney.com> and licensed under
00006  * the LGPL.  For more information, see http://geographiclib.sourceforge.net/
00007  **********************************************************************/
00008 
00009 #if !defined(GEOGRAPHICLIB_OSGB_HPP)
00010 #define GEOGRAPHICLIB_OSGB_HPP "$Id: OSGB.hpp 6911 2010-12-09 23:13:55Z karney $"
00011 
00012 #include "GeographicLib/Constants.hpp"
00013 #include "GeographicLib/TransverseMercator.hpp"
00014 #include <string>
00015 #include <sstream>
00016 
00017 namespace GeographicLib {
00018 
00019   /**
00020    * \brief Ordnance Survey grid system for Great Britain
00021    *
00022    * The class implements the coordinate system used by the Ordnance Survey for
00023    * maps of Great Britain and conversions to the grid reference system.
00024    *
00025    * See
00026    * - <a href="http://www.ordnancesurvey.co.uk/oswebsite/gps/docs/A_Guide_to_Coordinate_Systems_in_Great_Britain.pdf">
00027    * A guide to coordinate systems in Great Britain</a>
00028    * - <a href="http://www.ordnancesurvey.co.uk/oswebsite/gps/information/coordinatesystemsinfo/guidetonationalgrid/page1.html">
00029    * Guide to National Grid</a>
00030    *
00031    * \b WARNING: the latitudes and longitudes for the Ordnance Survey grid
00032    * system do not use the WGS84 datum.  Do not use the values returned by this
00033    * class in the UTMUPS, MGRS, or Geoid classes without first converting the
00034    * datum (and vice versa).
00035    **********************************************************************/
00036   class OSGB {
00037   private:
00038     typedef Math::real real;
00039     static const std::string letters;
00040     static const std::string digits;
00041     static const TransverseMercator OSGBTM;
00042     static const real northoffset;
00043     enum {
00044       base = 10,
00045       tile = 100000,
00046       tilelevel = 5,
00047       tilegrid = 5,
00048       tileoffx = 2 * tilegrid,
00049       tileoffy = 1 * tilegrid,
00050       minx = - tileoffx * tile,
00051       miny = - tileoffy * tile,
00052       maxx = (tilegrid*tilegrid - tileoffx) * tile,
00053       maxy = (tilegrid*tilegrid - tileoffy) * tile,
00054       // Maximum precision is um
00055       maxprec = 5 + 6,
00056     };
00057     static real computenorthoffset() throw();
00058     static void CheckCoords(real x, real y);
00059     static int lookup(const std::string& s, char c) throw() {
00060       std::string::size_type r = s.find(toupper(c));
00061       return r == std::string::npos ? -1 : int(r);
00062     }
00063     template<typename T> static std::string str(T x) {
00064       std::ostringstream s; s << x; return s.str();
00065     }
00066     OSGB();                     // Disable constructor
00067 
00068   public:
00069 
00070     /**
00071      * Forward projection, from geographic to OSGB coordinates.
00072      *
00073      * @param[in] lat latitude of point (degrees).
00074      * @param[in] lon longitude of point (degrees).
00075      * @param[out] x easting of point (meters).
00076      * @param[out] y northing of point (meters).
00077      * @param[out] gamma meridian convergence at point (degrees).
00078      * @param[out] k scale of projection at point.
00079      *
00080      * \e lat should be in the range [-90, 90]; \e lon and \e lon0 should be in
00081      * the range [-180, 360].
00082      **********************************************************************/
00083     static void Forward(real lat, real lon,
00084                         real& x, real& y, real& gamma, real& k) throw() {
00085       OSGBTM.Forward(OriginLongitude(), lat, lon, x, y, gamma, k);
00086       x += FalseEasting();
00087       y += northoffset;
00088     }
00089 
00090     /**
00091      * Reverse projection, from OSGB coordinates to geographic.
00092      *
00093      * @param[in] x easting of point (meters).
00094      * @param[in] y northing of point (meters).
00095      * @param[out] lat latitude of point (degrees).
00096      * @param[out] lon longitude of point (degrees).
00097      * @param[out] gamma meridian convergence at point (degrees).
00098      * @param[out] k scale of projection at point.
00099      *
00100      * The value of \e lon returned is in the range [-180, 180).
00101      **********************************************************************/
00102 
00103     static void Reverse(real x, real y,
00104                         real& lat, real& lon, real& gamma, real& k) throw() {
00105       x -= FalseEasting();
00106       y -= northoffset;
00107       OSGBTM.Reverse(OriginLongitude(), x, y, lat, lon, gamma, k);
00108     }
00109 
00110     /**
00111      * OSGB::Forward without returning the convergence and scale.
00112      **********************************************************************/
00113     static void Forward(real lat, real lon, real& x, real& y) throw() {
00114       real gamma, k;
00115       Forward(lat, lon, x, y, gamma, k);
00116     }
00117 
00118     /**
00119      * OSGB::Reverse without returning the convergence and scale.
00120      **********************************************************************/
00121     static void Reverse(real x, real y, real& lat, real& lon) throw() {
00122       real gamma, k;
00123       Reverse(x, y, lat, lon, gamma, k);
00124     }
00125 
00126     /**
00127      * Convert OSGB coordinates to a grid reference.
00128      *
00129      * @param[in] x easting of point (meters).
00130      * @param[in] y northing of point (meters).
00131      * @param[in] prec precision relative to 100 km.
00132      * @param[out] gridref National Grid reference.
00133      *
00134      * \e prec specifies the precision of the grid reference string as follows:
00135      * - prec = 0 (min), 100km
00136      * - prec = 1, 10km
00137      * - prec = 2, 1km
00138      * - prec = 3, 100m
00139      * - prec = 4, 10m
00140      * - prec = 5, 1m
00141      * - prec = 6, 0.1m
00142      * - prec = 11 (max), 1um
00143      *
00144      * The easting must be in the range [-1000 km, 1500 km) and the northing
00145      * must be in the range [-500 km, 2000 km).  An exception is thrown if
00146      * either the easting and northing is outside these bounds.  These bounds
00147      * are consistent with rules for the letter designations for the grid
00148      * system.
00149      **********************************************************************/
00150     static void GridReference(real x, real y, int prec, std::string& gridref);
00151 
00152     /**
00153      * Convert OSGB coordinates to a grid reference.
00154      *
00155      * @param[in] gridref National Grid reference.
00156      * @param[out] x easting of point (meters).
00157      * @param[out] y northing of point (meters).
00158      * @param[out] prec precision relative to 100 km.
00159      * @param[in] centerp if true (default), return center of the grid square,
00160      *   else return SW (lower left) corner.
00161      *
00162      * The grid reference must be of the form: two letters (not including I)
00163      * followed by an even number of digits (up to 22).
00164      **********************************************************************/
00165     static void GridReference(const std::string& gridref,
00166                               real& x, real& y, int& prec,
00167                               bool centerp = true);
00168 
00169     /** \name Inspector functions
00170      **********************************************************************/
00171     ///@{
00172     /**
00173      * @return \e a the equatorial radius of the Airy 1830 ellipsoid (meters).
00174      *
00175      * This is 20923713 ft converted to meters using the rule 1 ft =
00176      * 10^(9.48401603-10) m.  (The Airy 1830 value is returned because the OSGB
00177      * projection is based on this ellipsoid.)
00178      **********************************************************************/
00179     static Math::real MajorRadius() throw()
00180     { return real(6377563.396032066440602120008397385037L); }
00181 
00182     /**
00183      * @return \e r the inverse flattening of the Airy 1830 ellipsoid.
00184      *
00185      * For the Airy 1830 ellipsoid, \e a = 20923713 ft and \e b = 20853810 ft;
00186      * thus the inverse flattening = 20923713/(20923713 - 20853810) =
00187      * 2324857/7767 = 299.32496459...  (The Airy 1830 value is returned because
00188      * the OSGB projection is based on this ellipsoid.)
00189      **********************************************************************/
00190     static Math::real InverseFlattening() throw()
00191     { return real(2324857)/real(7767); }
00192 
00193     /**
00194      * @return \e k0 central scale for the OSGB projection (0.9996012717).
00195      **********************************************************************/
00196     static Math::real CentralScale() throw()
00197     { return real(0.9996012717L); }
00198 
00199     /**
00200      * @return latitude of the origin for the OSGB projection (49 degrees).
00201      **********************************************************************/
00202     static Math::real OriginLatitude() throw() { return real(49); }
00203 
00204     /**
00205      * @return longitude of the origin for the OSGB projection (-2 degrees).
00206      **********************************************************************/
00207     static Math::real OriginLongitude() throw() { return real(-2); }
00208 
00209     /**
00210      * @return false northing the OSGB projection (-100000 meters).
00211      **********************************************************************/
00212     static Math::real FalseNorthing() throw() { return real(-100000); }
00213 
00214     /**
00215      * @return false easting the OSGB projection (400000 meters).
00216      **********************************************************************/
00217     static Math::real FalseEasting() throw() { return real(400000); }
00218     ///@}
00219 
00220   };
00221 
00222 } // namespace GeographicLib
00223 #endif