GeographicLib  1.38
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GeoCoords.hpp
Go to the documentation of this file.
1 /**
2  * \file GeoCoords.hpp
3  * \brief Header for GeographicLib::GeoCoords class
4  *
5  * Copyright (c) Charles Karney (2008-2011) <charles@karney.com> and licensed
6  * under the MIT/X11 License. For more information, see
7  * http://geographiclib.sourceforge.net/
8  **********************************************************************/
9 
10 #if !defined(GEOGRAPHICLIB_GEOCOORDS_HPP)
11 #define GEOGRAPHICLIB_GEOCOORDS_HPP 1
12 
13 #include <GeographicLib/UTMUPS.hpp>
15 
16 namespace GeographicLib {
17 
18  /**
19  * \brief Conversion between geographic coordinates
20  *
21  * This class stores a geographic position which may be set via the
22  * constructors or Reset via
23  * - latitude and longitude
24  * - UTM or UPS coordinates
25  * - a string representation of these or an MGRS coordinate string
26  *
27  * The state consists of the latitude and longitude and the supplied UTM or
28  * UPS coordinates (possibly derived from the MGRS coordinates). If latitude
29  * and longitude were given then the UTM/UPS coordinates follows the standard
30  * conventions.
31  *
32  * The mutable state consists of the UTM or UPS coordinates for a alternate
33  * zone. A method SetAltZone is provided to set the alternate UPS/UTM zone.
34  *
35  * Methods are provided to return the geographic coordinates, the input UTM
36  * or UPS coordinates (and associated meridian convergence and scale), or
37  * alternate UTM or UPS coordinates (and their associated meridian
38  * convergence and scale).
39  *
40  * Once the input string has been parsed, you can print the result out in any
41  * of the formats, decimal degrees, degrees minutes seconds, MGRS, UTM/UPS.
42  *
43  * Example of use:
44  * \include example-GeoCoords.cpp
45  *
46  * <a href="GeoConvert.1.html">GeoConvert</a> is a command-line utility
47  * providing access to the functionality of GeoCoords.
48  **********************************************************************/
50  private:
51  typedef Math::real real;
52  real _lat, _long, _easting, _northing, _gamma, _k;
53  bool _northp;
54  int _zone; // See UTMUPS::zonespec
55  mutable real _alt_easting, _alt_northing, _alt_gamma, _alt_k;
56  mutable int _alt_zone;
57 
58  void CopyToAlt() const {
59  _alt_easting = _easting;
60  _alt_northing = _northing;
61  _alt_gamma = _gamma;
62  _alt_k = _k;
63  _alt_zone = _zone;
64  }
65  static void UTMUPSString(int zone, bool northp, real easting, real northing,
66  int prec, bool abbrev, std::string& utm);
67  void FixHemisphere();
68  public:
69 
70  /** \name Initializing the GeoCoords object
71  **********************************************************************/
72  ///@{
73  /**
74  * The default constructor is equivalent to \e latitude = 90&deg;,
75  * \e longitude = 0&deg;.
76  **********************************************************************/
78  // This is the N pole
79  : _lat(90)
80  , _long(0)
81  , _easting(2000000)
82  , _northing(2000000)
83  , _gamma(0)
84  , _k(Constants::UPS_k0())
85  , _northp(true)
86  , _zone(0)
87  { CopyToAlt(); }
88 
89  /**
90  * Construct from a string.
91  *
92  * @param[in] s 1-element, 2-element, or 3-element string representation of
93  * the position.
94  * @param[in] centerp governs the interpretation of MGRS coordinates (see
95  * below).
96  * @param[in] swaplatlong governs the interpretation of geographic
97  * coordinates (see below).
98  * @exception GeographicErr if the \e s is malformed (see below).
99  *
100  * Parse as a string and interpret it as a geographic position. The input
101  * string is broken into space (or comma) separated pieces and Basic
102  * decision on which format is based on number of components
103  * -# MGRS
104  * -# "Lat Long" or "Long Lat"
105  * -# "Zone Easting Northing" or "Easting Northing Zone"
106  *
107  * The following inputs are approximately the same (Ar Ramadi Bridge, Iraq)
108  * - Latitude and Longitude
109  * - 33.44 43.27
110  * - N33d26.4' E43d16.2'
111  * - 43d16'12&quot;E 33d26'24&quot;N
112  * - 43:16:12E 33:26:24
113  * - MGRS
114  * - 38SLC30
115  * - 38SLC391014
116  * - 38SLC3918701405
117  * - 37SHT9708
118  * - UTM
119  * - 38n 339188 3701405
120  * - 897039 3708229 37n
121  *
122  * <b>Latitude and Longitude parsing</b>: Latitude precedes longitude,
123  * unless a N, S, E, W hemisphere designator is used on one or both
124  * coordinates. If \e swaplatlong = true (default is false), then
125  * longitude precedes latitude in the absence of a hemisphere designator.
126  * Thus (with \e swaplatlong = false)
127  * - 40 -75
128  * - N40 W75
129  * - -75 N40
130  * - 75W 40N
131  * - E-75 -40S
132  * .
133  * are all the same position. The coordinates may be given in
134  * decimal degrees, degrees and decimal minutes, degrees, minutes,
135  * seconds, etc. Use d, ', and &quot; to mark off the degrees,
136  * minutes and seconds. Various alternative symbols for degrees, minutes,
137  * and seconds are allowed. Alternatively, use : to separate these
138  * components. (See DMS::Decode for details.) Thus
139  * - 40d30'30&quot;
140  * - 40d30'30
141  * - 40&deg;30'30
142  * - 40d30.5'
143  * - 40d30.5
144  * - 40:30:30
145  * - 40:30.5
146  * - 40.508333333
147  * .
148  * all specify the same angle. The leading sign applies to all components
149  * so -1d30 is -(1+30/60) = -1.5. Latitudes must be in the range
150  * [&minus;90&deg;, 90&deg;] and longitudes in the range
151  * [&minus;540&deg;, 540&deg;). Internally longitudes are reduced
152  * to the range [&minus;180&deg;, 180&deg;).
153  *
154  * <b>UTM/UPS parsing</b>: For UTM zones (&minus;80&deg; &le; Lat <
155  * 84&deg;), the zone designator is made up of a zone number (for 1 to 60)
156  * and a hemisphere letter (n or s), e.g., 38n (38north can also be used).
157  * The latitude band designer ([C--M] in the southern hemisphere and [N--X]
158  * in the northern) should NOT be used. (This is part of the MGRS
159  * coordinate.) The zone designator for the poles (where UPS is employed)
160  * is a hemisphere letter by itself, i.e., n or s (north or south can also
161  * be used).
162  *
163  * <b>MGRS parsing</b> interprets the grid references as square area at the
164  * specified precision (1m, 10m, 100m, etc.). If \e centerp = true (the
165  * default), the center of this square is then taken to be the precise
166  * position; thus:
167  * - 38SMB = 38n 450000 3650000
168  * - 38SMB4484 = 38n 444500 3684500
169  * - 38SMB44148470 = 38n 444145 3684705
170  * .
171  * Otherwise, the "south-west" corner of the square is used, i.e.,
172  * - 38SMB = 38n 400000 3600000
173  * - 38SMB4484 = 38n 444000 3684000
174  * - 38SMB44148470 = 38n 444140 3684700
175  **********************************************************************/
176  explicit GeoCoords(const std::string& s,
177  bool centerp = true, bool swaplatlong = false)
178  { Reset(s, centerp, swaplatlong); }
179 
180  /**
181  * Construct from geographic coordinates.
182  *
183  * @param[in] latitude (degrees).
184  * @param[in] longitude (degrees).
185  * @param[in] zone if specified, force the UTM/UPS representation to use a
186  * specified zone using the rules given in UTMUPS::zonespec.
187  * @exception GeographicErr if \e latitude is not in [&minus;90&deg;,
188  * 90&deg;].
189  * @exception GeographicErr if \e longitude is not in [&minus;540&deg;,
190  * 540&deg;).
191  * @exception GeographicErr if \e zone cannot be used for this location.
192  **********************************************************************/
193  GeoCoords(real latitude, real longitude, int zone = UTMUPS::STANDARD) {
194  Reset(latitude, longitude, zone);
195  }
196 
197  /**
198  * Construct from UTM/UPS coordinates.
199  *
200  * @param[in] zone UTM zone (zero means UPS).
201  * @param[in] northp hemisphere (true means north, false means south).
202  * @param[in] easting (meters).
203  * @param[in] northing (meters).
204  * @exception GeographicErr if \e zone, \e easting, or \e northing is
205  * outside its allowed range.
206  **********************************************************************/
207  GeoCoords(int zone, bool northp, real easting, real northing) {
208  Reset(zone, northp, easting, northing);
209  }
210 
211  /**
212  * Reset the location from a string. See
213  * GeoCoords(const std::string& s, bool centerp, bool swaplatlong).
214  *
215  * @param[in] s 1-element, 2-element, or 3-element string representation of
216  * the position.
217  * @param[in] centerp governs the interpretation of MGRS coordinates.
218  * @param[in] swaplatlong governs the interpretation of geographic
219  * coordinates.
220  * @exception GeographicErr if the \e s is malformed.
221  **********************************************************************/
222  void Reset(const std::string& s,
223  bool centerp = true, bool swaplatlong = false);
224 
225  /**
226  * Reset the location in terms of geographic coordinates. See
227  * GeoCoords(real latitude, real longitude, int zone).
228  *
229  * @param[in] latitude (degrees).
230  * @param[in] longitude (degrees).
231  * @param[in] zone if specified, force the UTM/UPS representation to use a
232  * specified zone using the rules given in UTMUPS::zonespec.
233  * @exception GeographicErr if \e latitude is not in [&minus;90&deg;,
234  * 90&deg;].
235  * @exception GeographicErr if \e longitude is not in [&minus;540&deg;,
236  * 540&deg;).
237  * @exception GeographicErr if \e zone cannot be used for this location.
238  **********************************************************************/
239  void Reset(real latitude, real longitude, int zone = UTMUPS::STANDARD) {
240  UTMUPS::Forward(latitude, longitude,
241  _zone, _northp, _easting, _northing, _gamma, _k,
242  zone);
243  _lat = latitude;
244  _long = longitude;
245  if (_long >= 180) _long -= 360;
246  else if (_long < -180) _long += 360;
247  CopyToAlt();
248  }
249 
250  /**
251  * Reset the location in terms of UPS/UPS coordinates. See
252  * GeoCoords(int zone, bool northp, real easting, real northing).
253  *
254  * @param[in] zone UTM zone (zero means UPS).
255  * @param[in] northp hemisphere (true means north, false means south).
256  * @param[in] easting (meters).
257  * @param[in] northing (meters).
258  * @exception GeographicErr if \e zone, \e easting, or \e northing is
259  * outside its allowed range.
260  **********************************************************************/
261  void Reset(int zone, bool northp, real easting, real northing) {
262  UTMUPS::Reverse(zone, northp, easting, northing,
263  _lat, _long, _gamma, _k);
264  _zone = zone;
265  _northp = northp;
266  _easting = easting;
267  _northing = northing;
268  FixHemisphere();
269  CopyToAlt();
270  }
271  ///@}
272 
273  /** \name Querying the GeoCoords object
274  **********************************************************************/
275  ///@{
276  /**
277  * @return latitude (degrees)
278  **********************************************************************/
279  Math::real Latitude() const { return _lat; }
280 
281  /**
282  * @return longitude (degrees)
283  **********************************************************************/
284  Math::real Longitude() const { return _long; }
285 
286  /**
287  * @return easting (meters)
288  **********************************************************************/
289  Math::real Easting() const { return _easting; }
290 
291  /**
292  * @return northing (meters)
293  **********************************************************************/
294  Math::real Northing() const { return _northing; }
295 
296  /**
297  * @return meridian convergence (degrees) for the UTM/UPS projection.
298  **********************************************************************/
299  Math::real Convergence() const { return _gamma; }
300 
301  /**
302  * @return scale for the UTM/UPS projection.
303  **********************************************************************/
304  Math::real Scale() const { return _k; }
305 
306  /**
307  * @return hemisphere (false means south, true means north).
308  **********************************************************************/
309  bool Northp() const { return _northp; }
310 
311  /**
312  * @return hemisphere letter n or s.
313  **********************************************************************/
314  char Hemisphere() const { return _northp ? 'n' : 's'; }
315 
316  /**
317  * @return the zone corresponding to the input (return 0 for UPS).
318  **********************************************************************/
319  int Zone() const { return _zone; }
320 
321  ///@}
322 
323  /** \name Setting and querying the alternate zone
324  **********************************************************************/
325  ///@{
326  /**
327  * Specify alternate zone number.
328  *
329  * @param[in] zone zone number for the alternate representation.
330  * @exception GeographicErr if \e zone cannot be used for this location.
331  *
332  * See UTMUPS::zonespec for more information on the interpretation of \e
333  * zone. Note that \e zone == UTMUPS::STANDARD (the default) use the
334  * standard UPS or UTM zone, UTMUPS::MATCH does nothing retaining the
335  * existing alternate representation. Before this is called the alternate
336  * zone is the input zone.
337  **********************************************************************/
338  void SetAltZone(int zone = UTMUPS::STANDARD) const {
339  if (zone == UTMUPS::MATCH)
340  return;
341  zone = UTMUPS::StandardZone(_lat, _long, zone);
342  if (zone == _zone)
343  CopyToAlt();
344  else {
345  bool northp;
346  UTMUPS::Forward(_lat, _long,
347  _alt_zone, northp,
348  _alt_easting, _alt_northing, _alt_gamma, _alt_k,
349  zone);
350  }
351  }
352 
353  /**
354  * @return current alternate zone (return 0 for UPS).
355  **********************************************************************/
356  int AltZone() const { return _alt_zone; }
357 
358  /**
359  * @return easting (meters) for alternate zone.
360  **********************************************************************/
361  Math::real AltEasting() const { return _alt_easting; }
362 
363  /**
364  * @return northing (meters) for alternate zone.
365  **********************************************************************/
366  Math::real AltNorthing() const { return _alt_northing; }
367 
368  /**
369  * @return meridian convergence (degrees) for alternate zone.
370  **********************************************************************/
371  Math::real AltConvergence() const { return _alt_gamma; }
372 
373  /**
374  * @return scale for alternate zone.
375  **********************************************************************/
376  Math::real AltScale() const { return _alt_k; }
377  ///@}
378 
379  /** \name String representations of the GeoCoords object
380  **********************************************************************/
381  ///@{
382  /**
383  * String representation with latitude and longitude as signed decimal
384  * degrees.
385  *
386  * @param[in] prec precision (relative to about 1m).
387  * @param[in] swaplatlong if true give longitude first (default = false)
388  * @exception std::bad_alloc if memory for the string can't be allocated.
389  * @return decimal latitude/longitude string representation.
390  *
391  * Precision specifies accuracy of representation as follows:
392  * - prec = &minus;5 (min), 1&deg;
393  * - prec = 0, 10<sup>&minus;5</sup>&deg; (about 1m)
394  * - prec = 3, 10<sup>&minus;8</sup>&deg;
395  * - prec = 9 (max), 10<sup>&minus;14</sup>&deg;
396  **********************************************************************/
397  std::string GeoRepresentation(int prec = 0, bool swaplatlong = false) const;
398 
399  /**
400  * String representation with latitude and longitude as degrees, minutes,
401  * seconds, and hemisphere.
402  *
403  * @param[in] prec precision (relative to about 1m)
404  * @param[in] swaplatlong if true give longitude first (default = false)
405  * @param[in] dmssep if non-null, use as the DMS separator character
406  * (instead of d, ', &quot; delimiters).
407  * @exception std::bad_alloc if memory for the string can't be allocated.
408  * @return DMS latitude/longitude string representation.
409  *
410  * Precision specifies accuracy of representation as follows:
411  * - prec = &minus;5 (min), 1&deg;
412  * - prec = &minus;4, 0.1&deg;
413  * - prec = &minus;3, 1'
414  * - prec = &minus;2, 0.1'
415  * - prec = &minus;1, 1&quot;
416  * - prec = 0, 0.1&quot; (about 3m)
417  * - prec = 1, 0.01&quot;
418  * - prec = 10 (max), 10<sup>&minus;11</sup>&quot;
419  **********************************************************************/
420  std::string DMSRepresentation(int prec = 0, bool swaplatlong = false,
421  char dmssep = char(0))
422  const;
423 
424  /**
425  * MGRS string.
426  *
427  * @param[in] prec precision (relative to about 1m).
428  * @exception std::bad_alloc if memory for the string can't be allocated.
429  * @return MGRS string.
430  *
431  * This gives the coordinates of the enclosing grid square with size given
432  * by the precision. Thus 38n 444180 3684790 converted to a MGRS
433  * coordinate at precision &minus;2 (100m) is 38SMB441847 and not
434  * 38SMB442848. \e prec specifies the precision of the MGRS string as
435  * follows:
436  * - prec = &minus;5 (min), 100km
437  * - prec = &minus;4, 10km
438  * - prec = &minus;3, 1km
439  * - prec = &minus;2, 100m
440  * - prec = &minus;1, 10m
441  * - prec = 0, 1m
442  * - prec = 1, 0.1m
443  * - prec = 6 (max), 1&mu;m
444  **********************************************************************/
445  std::string MGRSRepresentation(int prec = 0) const;
446 
447  /**
448  * UTM/UPS string.
449  *
450  * @param[in] prec precision (relative to about 1m)
451  * @param[in] abbrev if true (the default) use abbreviated (n/s) notation
452  * for hemisphere; otherwise spell out the hemisphere (north/south)
453  * @exception std::bad_alloc if memory for the string can't be allocated.
454  * @return UTM/UPS string representation: zone designator, easting, and
455  * northing.
456  *
457  * Precision specifies accuracy of representation as follows:
458  * - prec = &minus;5 (min), 100km
459  * - prec = &minus;3, 1km
460  * - prec = 0, 1m
461  * - prec = 3, 1mm
462  * - prec = 6, 1&mu;m
463  * - prec = 9 (max), 1nm
464  **********************************************************************/
465  std::string UTMUPSRepresentation(int prec = 0, bool abbrev = true) const;
466 
467  /**
468  * UTM/UPS string with hemisphere override.
469  *
470  * @param[in] northp hemisphere override
471  * @param[in] prec precision (relative to about 1m)
472  * @param[in] abbrev if true (the default) use abbreviated (n/s) notation
473  * for hemisphere; otherwise spell out the hemisphere (north/south)
474  * @exception GeographicErr if the hemisphere override attempts to change
475  * UPS N to UPS S or vice versa.
476  * @exception std::bad_alloc if memory for the string can't be allocated.
477  * @return UTM/UPS string representation: zone designator, easting, and
478  * northing.
479  **********************************************************************/
480  std::string UTMUPSRepresentation(bool northp, int prec = 0,
481  bool abbrev = true) const;
482 
483  /**
484  * MGRS string for the alternate zone. See GeoCoords::MGRSRepresentation.
485  *
486  * @param[in] prec precision (relative to about 1m).
487  * @exception std::bad_alloc if memory for the string can't be allocated.
488  * @return MGRS string.
489  **********************************************************************/
490  std::string AltMGRSRepresentation(int prec = 0) const;
491 
492  /**
493  * UTM/UPS string for the alternate zone. See
494  * GeoCoords::UTMUPSRepresentation.
495  *
496  * @param[in] prec precision (relative to about 1m)
497  * @param[in] abbrev if true (the default) use abbreviated (n/s) notation
498  * for hemisphere; otherwise spell out the hemisphere (north/south)
499  * @exception std::bad_alloc if memory for the string can't be allocated.
500  * @return UTM/UPS string representation: zone designator, easting, and
501  * northing.
502  **********************************************************************/
503  std::string AltUTMUPSRepresentation(int prec = 0, bool abbrev = true) const;
504 
505  /**
506  * UTM/UPS string for the alternate zone, with hemisphere override.
507  *
508  * @param[in] northp hemisphere override
509  * @param[in] prec precision (relative to about 1m)
510  * @param[in] abbrev if true (the default) use abbreviated (n/s) notation
511  * for hemisphere; otherwise spell out the hemisphere (north/south)
512  * @exception GeographicErr if the hemisphere override attempts to change
513  * UPS n to UPS s or vice verse.
514  * @exception std::bad_alloc if memory for the string can't be allocated.
515  * @return UTM/UPS string representation: zone designator, easting, and
516  * northing.
517  **********************************************************************/
518  std::string AltUTMUPSRepresentation(bool northp, int prec = 0,
519  bool abbrev = true) const;
520  ///@}
521 
522  /** \name Inspector functions
523  **********************************************************************/
524  ///@{
525  /**
526  * @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
527  *
528  * (The WGS84 value is returned because the UTM and UPS projections are
529  * based on this ellipsoid.)
530  **********************************************************************/
532 
533  /**
534  * @return \e f the flattening of the WGS84 ellipsoid.
535  *
536  * (The WGS84 value is returned because the UTM and UPS projections are
537  * based on this ellipsoid.)
538  **********************************************************************/
540  ///@}
541 
542  /// \cond SKIP
543  /**
544  * <b>DEPRECATED</b>
545  * @return \e r the inverse flattening of the ellipsoid.
546  **********************************************************************/
547  Math::real InverseFlattening() const
548  { return UTMUPS::InverseFlattening(); }
549  /// \endcond
550  };
551 
552 } // namespace GeographicLib
553 
554 #endif // GEOGRAPHICLIB_GEOCOORDS_HPP
Math::real Latitude() const
Definition: GeoCoords.hpp:279
#define GEOGRAPHICLIB_EXPORT
Definition: Constants.hpp:70
GeoCoords(int zone, bool northp, real easting, real northing)
Definition: GeoCoords.hpp:207
static Math::real Flattening()
Definition: UTMUPS.hpp:416
GeographicLib::Math::real real
Definition: GeodSolve.cpp:40
Math::real AltNorthing() const
Definition: GeoCoords.hpp:366
Header for GeographicLib::UTMUPS class.
Math::real MajorRadius() const
Definition: GeoCoords.hpp:531
GeoCoords(real latitude, real longitude, int zone=UTMUPS::STANDARD)
Definition: GeoCoords.hpp:193
Conversion between geographic coordinates.
Definition: GeoCoords.hpp:49
Math::real Northing() const
Definition: GeoCoords.hpp:294
GeoCoords(const std::string &s, bool centerp=true, bool swaplatlong=false)
Definition: GeoCoords.hpp:176
static Math::real MajorRadius()
Definition: UTMUPS.hpp:407
Math::real AltEasting() const
Definition: GeoCoords.hpp:361
void Reset(real latitude, real longitude, int zone=UTMUPS::STANDARD)
Definition: GeoCoords.hpp:239
static void Forward(real lat, real lon, int &zone, bool &northp, real &x, real &y, real &gamma, real &k, int setzone=STANDARD, bool mgrslimits=false)
Definition: UTMUPS.cpp:67
Math::real Convergence() const
Definition: GeoCoords.hpp:299
Math::real Scale() const
Definition: GeoCoords.hpp:304
Namespace for GeographicLib.
Definition: Accumulator.cpp:12
Constants needed by GeographicLib
Definition: Constants.hpp:95
Math::real AltConvergence() const
Definition: GeoCoords.hpp:371
static void Reverse(int zone, bool northp, real x, real y, real &lat, real &lon, real &gamma, real &k, bool mgrslimits=false)
Definition: UTMUPS.cpp:118
Header for GeographicLib::Constants class.
Math::real AltScale() const
Definition: GeoCoords.hpp:376
void Reset(int zone, bool northp, real easting, real northing)
Definition: GeoCoords.hpp:261
char Hemisphere() const
Definition: GeoCoords.hpp:314
Math::real Easting() const
Definition: GeoCoords.hpp:289
void SetAltZone(int zone=UTMUPS::STANDARD) const
Definition: GeoCoords.hpp:338
Math::real Flattening() const
Definition: GeoCoords.hpp:539
static int StandardZone(real lat, real lon, int setzone=STANDARD)
Definition: UTMUPS.cpp:42
Math::real Longitude() const
Definition: GeoCoords.hpp:284