NETGeographicLib  1.38
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Pages
DMS.h
Go to the documentation of this file.
1 /**
2  * \file NETGeographicLib/DMS.h
3  * \brief Header for NETGeographicLib::DMS class
4  *
5  * NETGeographicLib is copyright (c) Scott Heiman (2013)
6  * GeographicLib is Copyright (c) Charles Karney (2010-2012)
7  * <charles@karney.com> and licensed under the MIT/X11 License.
8  * For more information, see
9  * http://geographiclib.sourceforge.net/
10  **********************************************************************/
11 #pragma once
12 
13 namespace NETGeographicLib
14 {
15  /**
16  * \brief .NET wrapper for GeographicLib::DMS.
17  *
18  * Parse a string representing degree, minutes, and seconds and return the
19  * angle in degrees and format an angle in degrees as degree, minutes, and
20  * seconds. In addition, handle NANs and infinities on input and output.
21  *
22  * C# Example:
23  * \include example-DMS.cs
24  * Managed C++ Example:
25  * \include example-DMS.cpp
26  * Visual Basic Example:
27  * \include example-DMS.vb
28  **********************************************************************/
29 public ref class DMS
30 {
31 public:
32  /**
33  * Indicator for presence of hemisphere indicator (N/S/E/W) on latitudes
34  * and longitudes.
35  **********************************************************************/
36  enum class Flag {
37  /**
38  * No indicator present.
39  * @hideinitializer
40  **********************************************************************/
41  NONE = 0,
42  /**
43  * Latitude indicator (N/S) present.
44  * @hideinitializer
45  **********************************************************************/
46  LATITUDE = 1,
47  /**
48  * Longitude indicator (E/W) present.
49  * @hideinitializer
50  **********************************************************************/
51  LONGITUDE = 2,
52  /**
53  * Used in Encode to indicate output of an azimuth in [000, 360) with no
54  * letter indicator.
55  * @hideinitializer
56  **********************************************************************/
57  AZIMUTH = 3,
58  /**
59  * Used in Encode to indicate output of a plain number.
60  * @hideinitializer
61  **********************************************************************/
62  NUMBER = 4,
63  };
64 
65  /**
66  * Indicator for trailing units on an angle.
67  **********************************************************************/
68  enum class Component {
69  /**
70  * Trailing unit is degrees.
71  * @hideinitializer
72  **********************************************************************/
73  DEGREE = 0,
74  /**
75  * Trailing unit is arc minutes.
76  * @hideinitializer
77  **********************************************************************/
78  MINUTE = 1,
79  /**
80  * Trailing unit is arc seconds.
81  * @hideinitializer
82  **********************************************************************/
83  SECOND = 2,
84  };
85 
86  /**
87  * Convert a string in DMS to an angle.
88  *
89  * @param[in] dms string input.
90  * @param[out] ind a DMS::flag value signaling the presence of a
91  * hemisphere indicator.
92  * @exception GeographicErr if \e dms is malformed (see below).
93  * @return angle (degrees).
94  *
95  * Degrees, minutes, and seconds are indicated by the characters d, '
96  * (single quote), &quot; (double quote), and these components may only be
97  * given in this order. Any (but not all) components may be omitted and
98  * other symbols (e.g., the &deg; symbol for degrees and the unicode
99  * prime and double prime symbols for minutes and seconds) may be
100  * substituted. The last component indicator may be omitted and is assumed
101  * to be the next smallest unit (thus 33d10 is interpreted as 33d10'). The
102  * final component may be a decimal fraction but the non-final components
103  * must be integers. Instead of using d, ', and &quot; to indicate
104  * degrees, minutes, and seconds, : (colon) may be used to <i>separate</i>
105  * these components (numbers must appear before and after each colon); thus
106  * 50d30'10.3&quot; may be written as 50:30:10.3, 5.5' may be written
107  * 0:5.5, and so on. The integer parts of the minutes and seconds
108  * components must be less than 60. A single leading sign is permitted. A
109  * hemisphere designator (N, E, W, S) may be added to the beginning or end
110  * of the string. The result is multiplied by the implied sign of the
111  * hemisphere designator (negative for S and W). In addition \e ind is set
112  * to DMS::LATITUDE if N or S is present, to DMS::LONGITUDE if E or W is
113  * present, and to DMS::NONE otherwise. Throws an error on a malformed
114  * string. No check is performed on the range of the result. Examples of
115  * legal and illegal strings are
116  * - <i>LEGAL</i> (all the entries on each line are equivalent)
117  * - -20.51125, 20d30'40.5&quot;S, -20&deg;30'40.5, -20d30.675,
118  * N-20d30'40.5&quot;, -20:30:40.5
119  * - 4d0'9, 4d9&quot;, 4d9'', 4:0:9, 004:00:09, 4.0025, 4.0025d, 4d0.15,
120  * 04:.15
121  * - <i>ILLEGAL</i> (the exception thrown explains the problem)
122  * - 4d5&quot;4', 4::5, 4:5:, :4:5, 4d4.5'4&quot;, -N20.5, 1.8e2d, 4:60,
123  * 4d-5'
124  *
125  * <b>NOTE:</b> At present, all the string handling in the C++
126  * implementation %GeographicLib is with 8-bit characters. The support for
127  * unicode symbols for degrees, minutes, and seconds is therefore via the
128  * <a href="http://en.wikipedia.org/wiki/UTF-8">UTF-8</a> encoding. (The
129  * JavaScript implementation of this class uses unicode natively, of
130  * course.)
131  *
132  * Here is the list of Unicode symbols supported for degrees, minutes,
133  * seconds:
134  * - degrees:
135  * - d, D lower and upper case letters
136  * - U+00b0 degree symbol (&deg;)
137  * - U+00ba masculine ordinal indicator
138  * - U+2070 superscript zero
139  * - U+02da ring above
140  * - minutes:
141  * - ' apostrophe
142  * - U+2032 prime (&prime;)
143  * - U+00b4 acute accent
144  * - U+2019 right single quote (&rsquo;)
145  * - seconds:
146  * - &quot; quotation mark
147  * - U+2033 double prime (&Prime;)
148  * - U+201d right double quote (&rdquo;)
149  * - '&nbsp;' any two consecutive symbols for minutes
150  * .
151  * The codes with a leading zero byte, e.g., U+00b0, are accepted in their
152  * UTF-8 coded form 0xc2 0xb0 and as a single byte 0xb0.
153  **********************************************************************/
154  static double Decode(System::String^ dms,
155  [System::Runtime::InteropServices::Out] Flag% ind);
156 
157  /**
158  * Convert DMS to an angle.
159  *
160  * @param[in] d degrees.
161  * @param[in] m arc minutes.
162  * @param[in] s arc seconds.
163  * @return angle (degrees)
164  *
165  * This does not propagate the sign on \e d to the other components, so
166  * -3d20' would need to be represented as - DMS::Decode(3.0, 20.0) or
167  * DMS::Decode(-3.0, -20.0).
168  **********************************************************************/
169  static double Decode(double d, double m, double s )
170  { return d + (m + s/double(60))/double(60); }
171 
172  /// \cond SKIP
173  /**
174  * <b>DEPRECATED</b> (use Utility::num, instead).
175  * Convert a string to a double number.
176  *
177  * @param[in] str string input.
178  * @exception GeographicErr if \e str is malformed.
179  * @return decoded number.
180  **********************************************************************/
181  static double Decode(System::String^ str);
182  /// \endcond
183 
184  /**
185  * Convert a pair of strings to latitude and longitude.
186  *
187  * @param[in] dmsa first string.
188  * @param[in] dmsb second string.
189  * @param[out] lat latitude.
190  * @param[out] lon longitude reduced to the range [&minus;180&deg;,
191  * 180&deg;).
192  * @param[in] swaplatlong if true assume longitude is given before latitude
193  * in the absence of hemisphere designators (default false).
194  * @exception GeographicErr if \e dmsa or \e dmsb is malformed.
195  * @exception GeographicErr if \e dmsa and \e dmsb are both interpreted as
196  * latitudes.
197  * @exception GeographicErr if \e dmsa and \e dmsb are both interpreted as
198  * longitudes.
199  * @exception GeographicErr if decoded latitude is not in [&minus;90&deg;,
200  * 90&deg;].
201  * @exception GeographicErr if decoded longitude is not in
202  * [&minus;540&deg;, 540&deg;).
203  *
204  * By default, the \e lat (resp., \e lon) is assigned to the results of
205  * decoding \e dmsa (resp., \e dmsb). However this is overridden if either
206  * \e dmsa or \e dmsb contain a latitude or longitude hemisphere designator
207  * (N, S, E, W). If an exception is thrown, \e lat and \e lon are
208  * unchanged.
209  **********************************************************************/
210  static void DecodeLatLon(System::String^ dmsa, System::String^ dmsb,
211  [System::Runtime::InteropServices::Out] double% lat,
212  [System::Runtime::InteropServices::Out] double% lon,
213  bool swaplatlong );
214 
215  /**
216  * Convert a string to an angle in degrees.
217  *
218  * @param[in] angstr input string.
219  * @exception GeographicErr if \e angstr is malformed.
220  * @exception GeographicErr if \e angstr includes a hemisphere designator.
221  * @return angle (degrees)
222  *
223  * No hemisphere designator is allowed and no check is done on the range of
224  * the result.
225  **********************************************************************/
226  static double DecodeAngle(System::String^ angstr);
227 
228  /**
229  * Convert a string to an azimuth in degrees.
230  *
231  * @param[in] azistr input string.
232  * @exception GeographicErr if \e azistr is malformed.
233  * @exception GeographicErr if \e azistr includes a N/S designator.
234  * @exception GeographicErr if decoded azimuth is not in
235  * [&minus;540&deg;, 540&deg;).
236  * @return azimuth (degrees) reduced to the range [&minus;180&deg;,
237  * 180&deg;).
238  *
239  * A hemisphere designator E/W can be used; the result is multiplied by
240  * &minus;1 if W is present.
241  **********************************************************************/
242  static double DecodeAzimuth(System::String^ azistr);
243 
244  /**
245  * Convert angle (in degrees) into a DMS string (using d, ', and &quot;).
246  *
247  * @param[in] angle input angle (degrees)
248  * @param[in] trailing DMS::component value indicating the trailing units
249  * on the string and this is given as a decimal number if necessary.
250  * @param[in] prec the number of digits after the decimal point for the
251  * trailing component.
252  * @param[in] ind DMS::flag value indicated additional formatting.
253  * @param[in] dmssep if non-null, use as the DMS separator character
254  * (instead of d, ', &quot; delimiters).
255  * @exception GeographicErr if memory for the string can't be allocated.
256  * @return formatted string
257  *
258  * The interpretation of \e ind is as follows:
259  * - ind == DMS::NONE, signed result no leading zeros on degrees except in
260  * the units place, e.g., -8d03'.
261  * - ind == DMS::LATITUDE, trailing N or S hemisphere designator, no sign,
262  * pad degrees to 2 digits, e.g., 08d03'S.
263  * - ind == DMS::LONGITUDE, trailing E or W hemisphere designator, no
264  * sign, pad degrees to 3 digits, e.g., 008d03'W.
265  * - ind == DMS::AZIMUTH, convert to the range [0, 360&deg;), no
266  * sign, pad degrees to 3 digits, , e.g., 351d57'.
267  * .
268  * The integer parts of the minutes and seconds components are always given
269  * with 2 digits.
270  **********************************************************************/
271  static System::String^ Encode(double angle, Component trailing, unsigned prec,
272  Flag ind, char dmssep );
273 
274  /**
275  * Convert angle into a DMS string (using d, ', and &quot;) selecting the
276  * trailing component based on the precision.
277  *
278  * @param[in] angle input angle (degrees)
279  * @param[in] prec the precision relative to 1 degree.
280  * @param[in] ind DMS::flag value indicated additional formatting.
281  * @param[in] dmssep if non-null, use as the DMS separator character
282  * (instead of d, ', &quot; delimiters).
283  * @exception std::bad_alloc if memory for the string can't be allocated.
284  * @return formatted string
285  *
286  * \e prec indicates the precision relative to 1 degree, e.g., \e prec = 3
287  * gives a result accurate to 0.1' and \e prec = 4 gives a result accurate
288  * to 1&quot;. \e ind is interpreted as in DMS::Encode with the additional
289  * facility that DMS::NUMBER represents \e angle as a number in fixed
290  * format with precision \e prec.
291  **********************************************************************/
292  static System::String^ Encode(double angle, unsigned prec, Flag ind,
293  char dmssep );
294 
295  /**
296  * Split angle into degrees and minutes
297  *
298  * @param[in] ang angle (degrees)
299  * @param[out] d degrees (an integer returned as a double)
300  * @param[out] m arc minutes.
301  **********************************************************************/
302  static void Encode(double ang,
303  [System::Runtime::InteropServices::Out] double% d,
304  [System::Runtime::InteropServices::Out] double% m)
305  {
306  d = int(ang); m = 60 * (ang - d);
307  }
308 
309  /**
310  * Split angle into degrees and minutes and seconds.
311  *
312  * @param[in] ang angle (degrees)
313  * @param[out] d degrees (an integer returned as a double)
314  * @param[out] m arc minutes (an integer returned as a double)
315  * @param[out] s arc seconds.
316  **********************************************************************/
317  static void Encode(double ang,
318  [System::Runtime::InteropServices::Out] double% d,
319  [System::Runtime::InteropServices::Out] double% m,
320  [System::Runtime::InteropServices::Out] double% s)
321  {
322  d = int(ang); ang = 60 * (ang - d);
323  m = int(ang); s = 60 * (ang - m);
324  }
325 };
326 } // namespace NETGeographicLib
static void DecodeLatLon(System::String^ dmsa, System::String^ dmsb, [System::Runtime::InteropServices::Out] double% lat, [System::Runtime::InteropServices::Out] double% lon, bool swaplatlong)
static double Decode(System::String^ dms, [System::Runtime::InteropServices::Out] Flag% ind)
static double DecodeAngle(System::String^ angstr)
static System::String^ Encode(double angle, Component trailing, unsigned prec, Flag ind, char dmssep)
static double Decode(double d, double m, double s)
Definition: DMS.h:169
.NET wrapper for GeographicLib::DMS.
Definition: DMS.h:29
static void Encode(double ang, [System::Runtime::InteropServices::Out] double% d, [System::Runtime::InteropServices::Out] double% m, [System::Runtime::InteropServices::Out] double% s)
Definition: DMS.h:317
static void Encode(double ang, [System::Runtime::InteropServices::Out] double% d, [System::Runtime::InteropServices::Out] double% m)
Definition: DMS.h:302
static double DecodeAzimuth(System::String^ azistr)