123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553 |
- /**
- * \file GeoCoords.hpp
- * \brief Header for GeographicLib::GeoCoords class
- *
- * Copyright (c) Charles Karney (2008-2020) <charles@karney.com> and licensed
- * under the MIT/X11 License. For more information, see
- * https://geographiclib.sourceforge.io/
- **********************************************************************/
- #if !defined(GEOGRAPHICLIB_GEOCOORDS_HPP)
- #define GEOGRAPHICLIB_GEOCOORDS_HPP 1
- #include <GeographicLib/UTMUPS.hpp>
- #include <GeographicLib/Constants.hpp>
- namespace GeographicLib {
- /**
- * \brief Conversion between geographic coordinates
- *
- * This class stores a geographic position which may be set via the
- * constructors or Reset via
- * - latitude and longitude
- * - UTM or UPS coordinates
- * - a string representation of these or an MGRS coordinate string
- *
- * The state consists of the latitude and longitude and the supplied UTM or
- * UPS coordinates (possibly derived from the MGRS coordinates). If latitude
- * and longitude were given then the UTM/UPS coordinates follows the standard
- * conventions.
- *
- * The mutable state consists of the UTM or UPS coordinates for a alternate
- * zone. A method SetAltZone is provided to set the alternate UPS/UTM zone.
- *
- * Methods are provided to return the geographic coordinates, the input UTM
- * or UPS coordinates (and associated meridian convergence and scale), or
- * alternate UTM or UPS coordinates (and their associated meridian
- * convergence and scale).
- *
- * Once the input string has been parsed, you can print the result out in any
- * of the formats, decimal degrees, degrees minutes seconds, MGRS, UTM/UPS.
- *
- * Example of use:
- * \include example-GeoCoords.cpp
- *
- * <a href="GeoConvert.1.html">GeoConvert</a> is a command-line utility
- * providing access to the functionality of GeoCoords.
- **********************************************************************/
- class GEOGRAPHICLIB_EXPORT GeoCoords {
- private:
- typedef Math::real real;
- real _lat, _long, _easting, _northing, _gamma, _k;
- bool _northp;
- int _zone; // See UTMUPS::zonespec
- mutable real _alt_easting, _alt_northing, _alt_gamma, _alt_k;
- mutable int _alt_zone;
- void CopyToAlt() const {
- _alt_easting = _easting;
- _alt_northing = _northing;
- _alt_gamma = _gamma;
- _alt_k = _k;
- _alt_zone = _zone;
- }
- static void UTMUPSString(int zone, bool northp,
- real easting, real northing,
- int prec, bool abbrev, std::string& utm);
- void FixHemisphere();
- public:
- /** \name Initializing the GeoCoords object
- **********************************************************************/
- ///@{
- /**
- * The default constructor sets the coordinate as undefined.
- **********************************************************************/
- GeoCoords()
- : _lat(Math::NaN())
- , _long(Math::NaN())
- , _easting(Math::NaN())
- , _northing(Math::NaN())
- , _gamma(Math::NaN())
- , _k(Math::NaN())
- , _northp(false)
- , _zone(UTMUPS::INVALID)
- { CopyToAlt(); }
- /**
- * Construct from a string.
- *
- * @param[in] s 1-element, 2-element, or 3-element string representation of
- * the position.
- * @param[in] centerp governs the interpretation of MGRS coordinates (see
- * below).
- * @param[in] longfirst governs the interpretation of geographic
- * coordinates (see below).
- * @exception GeographicErr if the \e s is malformed (see below).
- *
- * Parse as a string and interpret it as a geographic position. The input
- * string is broken into space (or comma) separated pieces and Basic
- * decision on which format is based on number of components
- * -# MGRS
- * -# "Lat Long" or "Long Lat"
- * -# "Zone Easting Northing" or "Easting Northing Zone"
- *
- * The following inputs are approximately the same (Ar Ramadi Bridge, Iraq)
- * - Latitude and Longitude
- * - 33.44 43.27
- * - N33d26.4' E43d16.2'
- * - 43d16'12"E 33d26'24"N
- * - 43:16:12E 33:26:24
- * - MGRS
- * - 38SLC30
- * - 38SLC391014
- * - 38SLC3918701405
- * - 37SHT9708
- * - UTM
- * - 38n 339188 3701405
- * - 897039 3708229 37n
- *
- * <b>Latitude and Longitude parsing</b>: Latitude precedes longitude,
- * unless a N, S, E, W hemisphere designator is used on one or both
- * coordinates. If \e longfirst = true (default is false), then
- * longitude precedes latitude in the absence of a hemisphere designator.
- * Thus (with \e longfirst = false)
- * - 40 -75
- * - N40 W75
- * - -75 N40
- * - 75W 40N
- * - E-75 -40S
- * .
- * are all the same position. The coordinates may be given in
- * decimal degrees, degrees and decimal minutes, degrees, minutes,
- * seconds, etc. Use d, ', and " to mark off the degrees,
- * minutes and seconds. Various alternative symbols for degrees, minutes,
- * and seconds are allowed. Alternatively, use : to separate these
- * components. A single addition or subtraction is allowed. (See
- * DMS::Decode for details.) Thus
- * - 40d30'30"
- * - 40d30'30
- * - 40°30'30
- * - 40d30.5'
- * - 40d30.5
- * - 40:30:30
- * - 40:30.5
- * - 40.508333333
- * - 40:30+0:0:30
- * - 40:31-0:0.5
- * .
- * all specify the same angle. The leading sign applies to the following
- * components so -1d30 is -(1+30/60) = −1.5. However, note
- * that -1:30-0:0:15 is parsed as (-1:30) + (-0:0:15) = −(1+30/60)
- * − (15/3600). Latitudes must be in the range [−90°,
- * 90°]. Internally longitudes are reduced to the range
- * [−180°, 180°].
- *
- * <b>UTM/UPS parsing</b>: For UTM zones (−80° ≤ Lat <
- * 84°), the zone designator is made up of a zone number (for 1 to 60)
- * and a hemisphere letter (n or s), e.g., 38n (38north can also be used).
- * The latitude band designer ([C--M] in the southern hemisphere and [N--X]
- * in the northern) should NOT be used. (This is part of the MGRS
- * coordinate.) The zone designator for the poles (where UPS is employed)
- * is a hemisphere letter by itself, i.e., n or s (north or south can also
- * be used).
- *
- * <b>MGRS parsing</b> interprets the grid references as square area at the
- * specified precision (1m, 10m, 100m, etc.). If \e centerp = true (the
- * default), the center of this square is then taken to be the precise
- * position; thus:
- * - 38SMB = 38n 450000 3650000
- * - 38SMB4484 = 38n 444500 3684500
- * - 38SMB44148470 = 38n 444145 3684705
- * .
- * Otherwise, the "south-west" corner of the square is used, i.e.,
- * - 38SMB = 38n 400000 3600000
- * - 38SMB4484 = 38n 444000 3684000
- * - 38SMB44148470 = 38n 444140 3684700
- **********************************************************************/
- explicit GeoCoords(const std::string& s,
- bool centerp = true, bool longfirst = false)
- { Reset(s, centerp, longfirst); }
- /**
- * Construct from geographic coordinates.
- *
- * @param[in] latitude (degrees).
- * @param[in] longitude (degrees).
- * @param[in] zone if specified, force the UTM/UPS representation to use a
- * specified zone using the rules given in UTMUPS::zonespec.
- * @exception GeographicErr if \e latitude is not in [−90°,
- * 90°].
- * @exception GeographicErr if \e zone cannot be used for this location.
- **********************************************************************/
- GeoCoords(real latitude, real longitude, int zone = UTMUPS::STANDARD) {
- Reset(latitude, longitude, zone);
- }
- /**
- * Construct from UTM/UPS coordinates.
- *
- * @param[in] zone UTM zone (zero means UPS).
- * @param[in] northp hemisphere (true means north, false means south).
- * @param[in] easting (meters).
- * @param[in] northing (meters).
- * @exception GeographicErr if \e zone, \e easting, or \e northing is
- * outside its allowed range.
- **********************************************************************/
- GeoCoords(int zone, bool northp, real easting, real northing) {
- Reset(zone, northp, easting, northing);
- }
- /**
- * Reset the location from a string. See
- * GeoCoords(const std::string& s, bool centerp, bool longfirst).
- *
- * @param[in] s 1-element, 2-element, or 3-element string representation of
- * the position.
- * @param[in] centerp governs the interpretation of MGRS coordinates.
- * @param[in] longfirst governs the interpretation of geographic
- * coordinates.
- * @exception GeographicErr if the \e s is malformed.
- **********************************************************************/
- void Reset(const std::string& s,
- bool centerp = true, bool longfirst = false);
- /**
- * Reset the location in terms of geographic coordinates. See
- * GeoCoords(real latitude, real longitude, int zone).
- *
- * @param[in] latitude (degrees).
- * @param[in] longitude (degrees).
- * @param[in] zone if specified, force the UTM/UPS representation to use a
- * specified zone using the rules given in UTMUPS::zonespec.
- * @exception GeographicErr if \e latitude is not in [−90°,
- * 90°].
- * @exception GeographicErr if \e zone cannot be used for this location.
- **********************************************************************/
- void Reset(real latitude, real longitude, int zone = UTMUPS::STANDARD) {
- UTMUPS::Forward(latitude, longitude,
- _zone, _northp, _easting, _northing, _gamma, _k,
- zone);
- _lat = latitude;
- _long = longitude;
- if (_long >= 180) _long -= 360;
- else if (_long < -180) _long += 360;
- CopyToAlt();
- }
- /**
- * Reset the location in terms of UPS/UPS coordinates. See
- * GeoCoords(int zone, bool northp, real easting, real northing).
- *
- * @param[in] zone UTM zone (zero means UPS).
- * @param[in] northp hemisphere (true means north, false means south).
- * @param[in] easting (meters).
- * @param[in] northing (meters).
- * @exception GeographicErr if \e zone, \e easting, or \e northing is
- * outside its allowed range.
- **********************************************************************/
- void Reset(int zone, bool northp, real easting, real northing) {
- UTMUPS::Reverse(zone, northp, easting, northing,
- _lat, _long, _gamma, _k);
- _zone = zone;
- _northp = northp;
- _easting = easting;
- _northing = northing;
- FixHemisphere();
- CopyToAlt();
- }
- ///@}
- /** \name Querying the GeoCoords object
- **********************************************************************/
- ///@{
- /**
- * @return latitude (degrees)
- **********************************************************************/
- Math::real Latitude() const { return _lat; }
- /**
- * @return longitude (degrees)
- **********************************************************************/
- Math::real Longitude() const { return _long; }
- /**
- * @return easting (meters)
- **********************************************************************/
- Math::real Easting() const { return _easting; }
- /**
- * @return northing (meters)
- **********************************************************************/
- Math::real Northing() const { return _northing; }
- /**
- * @return meridian convergence (degrees) for the UTM/UPS projection.
- **********************************************************************/
- Math::real Convergence() const { return _gamma; }
- /**
- * @return scale for the UTM/UPS projection.
- **********************************************************************/
- Math::real Scale() const { return _k; }
- /**
- * @return hemisphere (false means south, true means north).
- **********************************************************************/
- bool Northp() const { return _northp; }
- /**
- * @return hemisphere letter n or s.
- **********************************************************************/
- char Hemisphere() const { return _northp ? 'n' : 's'; }
- /**
- * @return the zone corresponding to the input (return 0 for UPS).
- **********************************************************************/
- int Zone() const { return _zone; }
- ///@}
- /** \name Setting and querying the alternate zone
- **********************************************************************/
- ///@{
- /**
- * Specify alternate zone number.
- *
- * @param[in] zone zone number for the alternate representation.
- * @exception GeographicErr if \e zone cannot be used for this location.
- *
- * See UTMUPS::zonespec for more information on the interpretation of \e
- * zone. Note that \e zone == UTMUPS::STANDARD (the default) use the
- * standard UPS or UTM zone, UTMUPS::MATCH does nothing retaining the
- * existing alternate representation. Before this is called the alternate
- * zone is the input zone.
- **********************************************************************/
- void SetAltZone(int zone = UTMUPS::STANDARD) const {
- if (zone == UTMUPS::MATCH)
- return;
- zone = UTMUPS::StandardZone(_lat, _long, zone);
- if (zone == _zone)
- CopyToAlt();
- else {
- bool northp;
- UTMUPS::Forward(_lat, _long,
- _alt_zone, northp,
- _alt_easting, _alt_northing, _alt_gamma, _alt_k,
- zone);
- }
- }
- /**
- * @return current alternate zone (return 0 for UPS).
- **********************************************************************/
- int AltZone() const { return _alt_zone; }
- /**
- * @return easting (meters) for alternate zone.
- **********************************************************************/
- Math::real AltEasting() const { return _alt_easting; }
- /**
- * @return northing (meters) for alternate zone.
- **********************************************************************/
- Math::real AltNorthing() const { return _alt_northing; }
- /**
- * @return meridian convergence (degrees) for alternate zone.
- **********************************************************************/
- Math::real AltConvergence() const { return _alt_gamma; }
- /**
- * @return scale for alternate zone.
- **********************************************************************/
- Math::real AltScale() const { return _alt_k; }
- ///@}
- /** \name String representations of the GeoCoords object
- **********************************************************************/
- ///@{
- /**
- * String representation with latitude and longitude as signed decimal
- * degrees.
- *
- * @param[in] prec precision (relative to about 1m).
- * @param[in] longfirst if true give longitude first (default = false)
- * @exception std::bad_alloc if memory for the string can't be allocated.
- * @return decimal latitude/longitude string representation.
- *
- * Precision specifies accuracy of representation as follows:
- * - prec = −5 (min), 1°
- * - prec = 0, 10<sup>−5</sup>° (about 1m)
- * - prec = 3, 10<sup>−8</sup>°
- * - prec = 9 (max), 10<sup>−14</sup>°
- **********************************************************************/
- std::string GeoRepresentation(int prec = 0, bool longfirst = false) const;
- /**
- * String representation with latitude and longitude as degrees, minutes,
- * seconds, and hemisphere.
- *
- * @param[in] prec precision (relative to about 1m)
- * @param[in] longfirst if true give longitude first (default = false)
- * @param[in] dmssep if non-null, use as the DMS separator character
- * (instead of d, ', " delimiters).
- * @exception std::bad_alloc if memory for the string can't be allocated.
- * @return DMS latitude/longitude string representation.
- *
- * Precision specifies accuracy of representation as follows:
- * - prec = −5 (min), 1°
- * - prec = −4, 0.1°
- * - prec = −3, 1'
- * - prec = −2, 0.1'
- * - prec = −1, 1"
- * - prec = 0, 0.1" (about 3m)
- * - prec = 1, 0.01"
- * - prec = 10 (max), 10<sup>−11</sup>"
- **********************************************************************/
- std::string DMSRepresentation(int prec = 0, bool longfirst = false,
- char dmssep = char(0))
- const;
- /**
- * MGRS string.
- *
- * @param[in] prec precision (relative to about 1m).
- * @exception std::bad_alloc if memory for the string can't be allocated.
- * @return MGRS string.
- *
- * This gives the coordinates of the enclosing grid square with size given
- * by the precision. Thus 38n 444180 3684790 converted to a MGRS
- * coordinate at precision −2 (100m) is 38SMB441847 and not
- * 38SMB442848. \e prec specifies the precision of the MGRS string as
- * follows:
- * - prec = −6 (min), only the grid zone is returned, e.g., 38S
- * - prec = −5, 100km, e.g., 38SMB
- * - prec = −4, 10km
- * - prec = −3, 1km
- * - prec = −2, 100m
- * - prec = −1, 10m
- * - prec = 0, 1m
- * - prec = 1, 0.1m
- * - prec = 6 (max), 1μm
- **********************************************************************/
- std::string MGRSRepresentation(int prec = 0) const;
- /**
- * UTM/UPS string.
- *
- * @param[in] prec precision (relative to about 1m)
- * @param[in] abbrev if true (the default) use abbreviated (n/s) notation
- * for hemisphere; otherwise spell out the hemisphere (north/south)
- * @exception std::bad_alloc if memory for the string can't be allocated.
- * @return UTM/UPS string representation: zone designator, easting, and
- * northing.
- *
- * Precision specifies accuracy of representation as follows:
- * - prec = −5 (min), 100km
- * - prec = −3, 1km
- * - prec = 0, 1m
- * - prec = 3, 1mm
- * - prec = 6, 1μm
- * - prec = 9 (max), 1nm
- **********************************************************************/
- std::string UTMUPSRepresentation(int prec = 0, bool abbrev = true) const;
- /**
- * UTM/UPS string with hemisphere override.
- *
- * @param[in] northp hemisphere override
- * @param[in] prec precision (relative to about 1m)
- * @param[in] abbrev if true (the default) use abbreviated (n/s) notation
- * for hemisphere; otherwise spell out the hemisphere (north/south)
- * @exception GeographicErr if the hemisphere override attempts to change
- * UPS N to UPS S or vice versa.
- * @exception std::bad_alloc if memory for the string can't be allocated.
- * @return UTM/UPS string representation: zone designator, easting, and
- * northing.
- **********************************************************************/
- std::string UTMUPSRepresentation(bool northp, int prec = 0,
- bool abbrev = true) const;
- /**
- * MGRS string for the alternate zone. See GeoCoords::MGRSRepresentation.
- *
- * @param[in] prec precision (relative to about 1m).
- * @exception std::bad_alloc if memory for the string can't be allocated.
- * @return MGRS string.
- **********************************************************************/
- std::string AltMGRSRepresentation(int prec = 0) const;
- /**
- * UTM/UPS string for the alternate zone. See
- * GeoCoords::UTMUPSRepresentation.
- *
- * @param[in] prec precision (relative to about 1m)
- * @param[in] abbrev if true (the default) use abbreviated (n/s) notation
- * for hemisphere; otherwise spell out the hemisphere (north/south)
- * @exception std::bad_alloc if memory for the string can't be allocated.
- * @return UTM/UPS string representation: zone designator, easting, and
- * northing.
- **********************************************************************/
- std::string AltUTMUPSRepresentation(int prec = 0, bool abbrev = true)
- const;
- /**
- * UTM/UPS string for the alternate zone, with hemisphere override.
- *
- * @param[in] northp hemisphere override
- * @param[in] prec precision (relative to about 1m)
- * @param[in] abbrev if true (the default) use abbreviated (n/s) notation
- * for hemisphere; otherwise spell out the hemisphere (north/south)
- * @exception GeographicErr if the hemisphere override attempts to change
- * UPS n to UPS s or vice verse.
- * @exception std::bad_alloc if memory for the string can't be allocated.
- * @return UTM/UPS string representation: zone designator, easting, and
- * northing.
- **********************************************************************/
- std::string AltUTMUPSRepresentation(bool northp, int prec = 0,
- bool abbrev = true) const;
- ///@}
- /** \name Inspector functions
- **********************************************************************/
- ///@{
- /**
- * @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
- *
- * (The WGS84 value is returned because the UTM and UPS projections are
- * based on this ellipsoid.)
- **********************************************************************/
- Math::real EquatorialRadius() const { return UTMUPS::EquatorialRadius(); }
- /**
- * @return \e f the flattening of the WGS84 ellipsoid.
- *
- * (The WGS84 value is returned because the UTM and UPS projections are
- * based on this ellipsoid.)
- **********************************************************************/
- Math::real Flattening() const { return UTMUPS::Flattening(); }
- /**
- * \deprecated An old name for EquatorialRadius().
- **********************************************************************/
- GEOGRAPHICLIB_DEPRECATED("Use EquatorialRadius()")
- Math::real MajorRadius() const { return EquatorialRadius(); }
- ///@}
- };
- } // namespace GeographicLib
- #endif // GEOGRAPHICLIB_GEOCOORDS_HPP
|