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