GeoCoords.hpp

Go to the documentation of this file.
00001 /**
00002  * \file GeoCoords.hpp
00003  * \brief Header for GeographicLib::GeoCoords class
00004  *
00005  * Copyright (c) Charles Karney (2008, 2009, 2010) <charles@karney.com>
00006  * and licensed under the LGPL.  For more information, see
00007  * http://geographiclib.sourceforge.net/
00008  **********************************************************************/
00009 
00010 #ifndef GEOGRAPHICLIB_GEOCOORDS_HPP
00011 #define GEOGRAPHICLIB_GEOCOORDS_HPP "$Id: GeoCoords.hpp 6785 2010-01-05 22:15:42Z karney $"
00012 
00013 #include "GeographicLib/UTMUPS.hpp"
00014 #include "GeographicLib/Constants.hpp"
00015 
00016 namespace GeographicLib {
00017 
00018   /**
00019    * \brief Conversion between geographic coordinates
00020    *
00021    * This class stores a geographic position which may be set via the
00022    * constructors or Reset via
00023    * - latitude and longitude
00024    * - UTM or UPS coordinates
00025    * - a string represention of these or an MGRS coordinate string
00026    *
00027    * The state consists of the latitude and longitude and the supplied UTM or
00028    * UPS coordinates (possibly derived from the MGRS coordinates).  If latitude
00029    * and longitude were given then the UTM/UPS coordinates follows the standard
00030    * conventions.
00031    *
00032    * The mutable state consists of the UTM or UPS coordinates for a alternate
00033    * zone.  A method SetAltZone is provided to set the alternate UPS/UTM zone.
00034    *
00035    * Methods are provided to return the geographic coordinates, the input UTM
00036    * or UPS coordinates (and associated meridian convergence and scale), or
00037    * alternate UTM or UPS coordinates (and their associated meridian
00038    * convergence and scale).
00039    *
00040    * Once the input string has been parsed, you can print the result out in any
00041    * of the formats, decimal degrees, degrees minutes seconds, MGRS, UTM/UPS.
00042    **********************************************************************/
00043   class GeoCoords {
00044   private:
00045     typedef Math::real real;
00046     real _lat, _long, _easting, _northing, _gamma, _k;
00047     bool _northp;
00048     int _zone;                  // See UTMUPS::zonespec
00049     mutable real _alt_easting, _alt_northing, _alt_gamma, _alt_k;
00050     mutable int _alt_zone;
00051 
00052     void CopyToAlt() const throw() {
00053       _alt_easting = _easting;
00054       _alt_northing = _northing;
00055       _alt_gamma = _gamma;
00056       _alt_k = _k;
00057       _alt_zone = _zone;
00058     }
00059     void UTMUPSString(int zone, real easting, real northing,
00060                       int prec, std::string& utm) const;
00061     void FixHemisphere();
00062   public:
00063 
00064     /**
00065      * The default contructor is equivalent to \e latitude = 90<sup>o</sup>, \e
00066      * longitude = 0<sup>o</sup>.
00067      **********************************************************************/
00068     GeoCoords() throw()
00069       // This is the N pole
00070       : _lat(90)
00071       , _long(0)
00072       , _easting(2000000)
00073       , _northing(2000000)
00074       , _northp(true)
00075       , _zone(0)
00076     { CopyToAlt(); }
00077 
00078     /**
00079      * Parse as a string and interpret it as a geographic position.  The input
00080      * string is broken into space (or comma) separated pieces and Basic
00081      * decision on which format is based on number of components
00082      * -# MGRS
00083      * -# "Lat Long" or "Long Lat"
00084      * -# "Zone Easting Northing" or "Easting Northing Zone"
00085      *
00086      * The following inputs are approximately the same (Ar Ramadi Bridge, Iraq)
00087      * - Latitude and Longitude
00088      *   -  33.44      43.27
00089      *   -  N33d26.4'  E43d16.2'
00090      *   -  43d16'12"E 33d26'24"N
00091      * - MGRS
00092      *   -  38SLC301
00093      *   -  38SLC391014
00094      *   -  38SLC3918701405
00095      *   -  37SHT9708
00096      * - UTM
00097      *   -  38N 339188 3701405
00098      *   -  897039 3708229 37N
00099      *
00100      * Latitude and Longitude parsing.  Latitude precedes longitude, unless a
00101      * N, S, E, W hemisphere designator is used on one or both coordinates.
00102      * Thus
00103      * - 40 -75
00104      * - N40 W75
00105      * - -75 N40
00106      * - 75W 40N
00107      * - E-75 -40S
00108      * .
00109      * are all the same position.  The coodinates may be given in decimal
00110      * degrees, degrees and decimal minutes, degrees, minutes, seconds, etc.
00111      * Use d, ', and " to make off the degrees, minutes and seconds.  Thus
00112      * - 40d30'30"
00113      * - 40d30'30
00114      * - 40d30.5'
00115      * - 40d30.5
00116      * - 40.508333333
00117      * .
00118      * all specify the same angle.  The leading sign applies to all components
00119      * so -1d30 is -(1+30/60) = -1.5.  Latitudes must be in the range [-90, 90]
00120      * and longitudes in the range [-180, 360].  Internally longitudes are
00121      * reduced to the range [-180, 180).
00122      *
00123      * UTM/UPS parsing.  For UTM zones (-80 <= Lat <= 84), the zone designator
00124      * is made up of a zone number (for 1 to 60) and a hemisphere letter (N or
00125      * S), e.g., 38N.  The latitude zone designer ([C&ndash;M] in the southern
00126      * hemisphere and [N&ndash;X] in the northern) should NOT be used.  (This
00127      * is part of the MGRS coordinate.)  The zone designator for the poles
00128      * (where UPS is employed) is a hemisphere letter by itself, i.e., N or S.
00129      *
00130      * MGRS parsing interprets the grid references as square area at the
00131      * specified precision (1m, 10m, 100m, etc.).  If \e centerp = true (the
00132      * default), the center of this square is then taken to be the precise
00133      * position; thus:
00134      * - 38SMB           = 38N 450000 3650000
00135      * - 38SMB4484       = 38N 444500 3684500
00136      * - 38SMB44148470   = 38N 444145 3684705
00137      * .
00138      * Otherwise, the "south-west" corner of the square is used, i.e.,
00139      * - 38SMB           = 38N 400000 3600000
00140      * - 38SMB4484       = 38N 444000 3684000
00141      * - 38SMB44148470   = 38N 444140 3684700
00142      **********************************************************************/
00143     explicit GeoCoords(const std::string& s, bool centerp = true)
00144     { Reset(s, centerp); }
00145 
00146     /**
00147      * Specify the location in terms of \e latitude (degrees) and \e longitude
00148      * (degrees).  Use \e zone to force the UTM/UPS representation to use a
00149      * specified zone using the rules given in UTMUPS::zonespec.
00150      **********************************************************************/
00151     GeoCoords(real latitude, real longitude, int zone = UTMUPS::STANDARD) {
00152       Reset(latitude, longitude, zone);
00153     }
00154 
00155     /**
00156      * Specify the location in terms of UPS/UPS \e zone (zero means UPS),
00157      * hemisphere \e northp (false means south, true means north), \e easting
00158      * (meters) and \e northing (meters).
00159      **********************************************************************/
00160     GeoCoords(int zone, bool northp, real easting, real northing) {
00161       Reset(zone, northp, easting, northing);
00162     }
00163 
00164     /**
00165      * Reset the location as a 1-element, 2-element, or 3-element string.  See
00166      * GeoCoords(const string& s, bool centerp).
00167      **********************************************************************/
00168     void Reset(const std::string& s, bool centerp = true);
00169 
00170     /**
00171      * Reset the location in terms of \e latitude and \e longitude.  See
00172      * GeoCoords(real latitude, real longitude, int zone).
00173      **********************************************************************/
00174     void Reset(real latitude, real longitude, int zone = UTMUPS::STANDARD) {
00175       UTMUPS::Forward(latitude, longitude,
00176                       _zone, _northp, _easting, _northing, _gamma, _k,
00177                       zone);
00178       _lat = latitude;
00179       _long = longitude;
00180       if (_long >= 180)
00181         _long -= 360;
00182       CopyToAlt();
00183     }
00184 
00185     /**
00186      * Reset the location in terms of UPS/UPS \e zone, hemisphere \e northp, \e
00187      * easting, and \e northing.  See GeoCoords(int zone, bool northp,
00188      * real easting, real northing).
00189      **********************************************************************/
00190     void Reset(int zone, bool northp, real easting, real northing) {
00191       UTMUPS::Reverse(zone, northp, easting, northing,
00192                       _lat, _long, _gamma, _k);
00193       _zone = zone;
00194       _northp = northp;
00195       _easting = easting;
00196       _northing = northing;
00197       FixHemisphere();
00198       CopyToAlt();
00199     }
00200 
00201     /**
00202      * Return latitude (degrees)
00203      **********************************************************************/
00204     Math::real Latitude() const throw() { return _lat; }
00205 
00206     /**
00207      * Return longitude (degrees)
00208      **********************************************************************/
00209     Math::real Longitude() const throw() { return _long; }
00210 
00211     /**
00212      * Return easting (meters)
00213      **********************************************************************/
00214     Math::real Easting() const throw() { return _easting; }
00215 
00216     /**
00217      * Return northing (meters)
00218      **********************************************************************/
00219     Math::real Northing() const throw() { return _northing; }
00220 
00221     /**
00222      * Return meridian convergence (degrees) for the UTM/UPS projection.
00223      **********************************************************************/
00224     Math::real Convergence() const throw() { return _gamma; }
00225 
00226     /**
00227      * Return scale for the UTM/UPS projection.
00228      **********************************************************************/
00229     Math::real Scale() const throw() { return _k; }
00230 
00231     /**
00232      * Return hemisphere (false means south, true means north).
00233      **********************************************************************/
00234     bool Northp() const throw() { return _northp; }
00235 
00236     /**
00237      * Return hemisphere letter N or S.
00238      **********************************************************************/
00239     char Hemisphere() const throw() { return _northp ? 'N' : 'S'; }
00240 
00241     /**
00242      * Return the zone corresponding to the input (return 0 for UPS).
00243      **********************************************************************/
00244     int Zone() const throw() { return _zone; }
00245 
00246     /**
00247      * Use zone number, \e zone, for the alternate representation.  See
00248      * UTMUPS::zonespec for more information on the interpretation of \e zone.
00249      * Note that \e zone == UTMUPS::STANDARD (the default) use the standard UPS
00250      * or UTM zone, UTMUPS::MATCH does nothing retaining the existing alternate
00251      * representation.  Before this is called the alternate zone is the input
00252      * zone.
00253      **********************************************************************/
00254     void SetAltZone(int zone = UTMUPS::STANDARD) const {
00255       if (zone == UTMUPS::MATCH)
00256         return;
00257       zone = UTMUPS::StandardZone(_lat, _long, zone);
00258       if (zone == _zone)
00259         CopyToAlt();
00260       else {
00261         bool northp;
00262         UTMUPS::Forward(_lat, _long,
00263                         _alt_zone, northp,
00264                         _alt_easting, _alt_northing, _alt_gamma, _alt_k,
00265                         zone);
00266       }
00267     }
00268 
00269     /**
00270      * Returns the current alternate zone (return 0 for UPS).
00271      **********************************************************************/
00272     int AltZone() const throw() { return _alt_zone; }
00273 
00274     /**
00275      * Return easting (meters) for alternate zone.
00276      **********************************************************************/
00277     Math::real AltEasting() const throw() { return _alt_easting; }
00278 
00279     /**
00280      * Return northing (meters) for alternate zone.
00281      **********************************************************************/
00282     Math::real AltNorthing() const throw() { return _alt_northing; }
00283 
00284     /**
00285      * Return meridian convergence (degrees) for altermate zone.
00286      **********************************************************************/
00287     Math::real AltConvergence() const throw() { return _alt_gamma; }
00288 
00289     /**
00290      * Return scale for altermate zone.
00291      **********************************************************************/
00292     Math::real AltScale() const throw() { return _alt_k; }
00293 
00294     /**
00295      * Return string with latitude and longitude as signed decimal degrees.
00296      * Precision \e prec specifies accuracy of representation as follows:
00297      * - prec = -5 (min), 1d
00298      * - prec = 0, 10<sup>-5</sup>d (about 1m)
00299      * - prec = 3, 10<sup>-8</sup>d
00300      * - prec = 9 (max), 10<sup>-14</sup>d
00301      **********************************************************************/
00302     std::string GeoRepresentation(int prec = 0) const;
00303 
00304     /**
00305      * Return string with latitude and longitude as degrees, minutes, seconds,
00306      * and hemisphere.  Precision \e prec specifies accuracy of representation
00307      * as follows:
00308      * - prec = -5 (min), 1d
00309      * - prec = -4, 0.1d
00310      * - prec = -3, 1'
00311      * - prec = -2, 0.1'
00312      * - prec = -1, 1"
00313      * - prec = 0, 0.1" (about 3m)
00314      * - prec = 1, 0.01"
00315      * - prec = 10 (max), 10<sup>-11</sup>"
00316      **********************************************************************/
00317     std::string DMSRepresentation(int prec = 0) const;
00318 
00319     /**
00320      * Return MGRS string.  This gives the coordinates of the enclosing grid
00321      * square with size given by the precision \e prec.  Thus 38N 444180
00322      * 3684790 converted to a MGRS coordinate at precision -2 (100m) is
00323      * 38SMB441847 and not 38SMB442848.  Precision \e prec specifies the
00324      * precision of the MSGRS string as follows:
00325      * - prec = -5 (min), 100km
00326      * - prec = -4, 10km
00327      * - prec = -3, 1km
00328      * - prec = -2, 100m
00329      * - prec = -1, 10m
00330      * - prec = 0, 1m
00331      * - prec = 1, 0.1m
00332      * - prec = 6 (max), 1um
00333      **********************************************************************/
00334     std::string MGRSRepresentation(int prec = 0) const;
00335 
00336     /**
00337      * Return string consisting of UTM/UPS zone designator, easting, and
00338      * northing,  Precision \e prec specifies accuracy of representation
00339      * as follows:
00340      * - prec = -5 (min), 100km
00341      * - prec = -3, 1km
00342      * - prec = 0, 1m
00343      * - prec = 3, 1mm
00344      * - prec = 6, 1um
00345      * - prec = 9 (max), 1nm
00346      **********************************************************************/
00347     std::string UTMUPSRepresentation(int prec = 0) const;
00348 
00349     /**
00350      * Return MGRS string using alternative zone.  See MGRSRepresentation for
00351      * the interpretation of \e prec.
00352      **********************************************************************/
00353     std::string AltMGRSRepresentation(int prec = 0) const;
00354 
00355     /**
00356      * Return string consisting of alternate UTM/UPS zone designator, easting,
00357      * and northing.  See UTMUPSRepresentation for the interpretation of \e
00358      * prec.
00359      **********************************************************************/
00360     std::string AltUTMUPSRepresentation(int prec = 0) const;
00361 
00362     /**
00363      * The major radius of the ellipsoid (meters).  This is the value for the
00364      * WGS84 ellipsoid because the UTM and UPS projections are based on this
00365      * ellipsoid.
00366      **********************************************************************/
00367     Math::real MajorRadius() const throw() { return UTMUPS::MajorRadius(); }
00368 
00369     /**
00370      * The inverse flattening of the ellipsoid.  This is the value for the
00371      * WGS84 ellipsoid because the UTM and UPS projections are based on this
00372      * ellipsoid.
00373      **********************************************************************/
00374     Math::real InverseFlattening() const throw()
00375     { return UTMUPS::InverseFlattening(); }
00376   };
00377 
00378 } // namespace GeographicLib
00379 #endif  // GEOGRAPHICLIB_GEOCOORDS_HPP

Generated on 21 May 2010 for GeographicLib by  doxygen 1.6.1