NETGeographicLib  1.43
Geoid.h
Go to the documentation of this file.
1 #pragma once
2 /**
3  * \file NETGeographicLib/Geoid.h
4  * \brief Header for NETGeographicLib::Geoid class
5  *
6  * NETGeographicLib is copyright (c) Scott Heiman (2013)
7  * GeographicLib is Copyright (c) Charles Karney (2010-2012)
8  * <charles@karney.com> and licensed under the MIT/X11 License.
9  * For more information, see
10  * http://geographiclib.sourceforge.net/
11  **********************************************************************/
12 
13 namespace NETGeographicLib
14 {
15  /**
16  * \brief .NET wrapper for GeographicLib::Geoid.
17  *
18  * This class allows .NET applications to access GeographicLib::Geoid.
19  *
20  * This class evaluated the height of one of the standard geoids, EGM84,
21  * EGM96, or EGM2008 by bilinear or cubic interpolation into a rectangular
22  * grid of data. These geoid models are documented in
23  * - EGM84:
24  * http://earth-info.nga.mil/GandG/wgs84/gravitymod/wgs84_180/wgs84_180.html
25  * - EGM96:
26  * http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/egm96.html
27  * - EGM2008:
28  * http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008
29  *
30  * The geoids are defined in terms of spherical harmonics. However in order
31  * to provide a quick and flexible method of evaluating the geoid heights,
32  * this class evaluates the height by interpolation into a grid of
33  * precomputed values.
34  *
35  * The geoid height, \e N, can be used to convert a height above the
36  * ellipsoid, \e h, to the corresponding height above the geoid (roughly the
37  * height above mean sea level), \e H, using the relations
38  *
39  * &nbsp;&nbsp;&nbsp;\e h = \e N + \e H;
40  * &nbsp;&nbsp;\e H = &minus;\e N + \e h.
41  *
42  * See \ref geoid for details of how to install the data sets, the data
43  * format, estimates of the interpolation errors, and how to use caching.
44  *
45  * In addition to returning the geoid height, the gradient of the geoid can
46  * be calculated. The gradient is defined as the rate of change of the geoid
47  * as a function of position on the ellipsoid. This uses the parameters for
48  * the WGS84 ellipsoid. The gradient defined in terms of the interpolated
49  * heights. As a result of the way that the geoid data is stored, the
50  * calculation of gradients can result in large quantization errors. This is
51  * particularly acute for fine grids, at high latitudes, and for the easterly
52  * gradient.
53  *
54  * This class is typically \e not thread safe in that a single instantiation
55  * cannot be safely used by multiple threads because of the way the object
56  * reads the data set and because it maintains a single-cell cache. If
57  * multiple threads need to calculate geoid heights they should all construct
58  * thread-local instantiations. Alternatively, set the optional \e
59  * threadsafe parameter to true in the constructor. This causes the
60  * constructor to read all the data into memory and to turn off the
61  * single-cell caching which results in a Geoid object which \e is thread
62  * safe.
63  *
64  * C# Example:
65  * \include example-Geoid.cs
66  * Managed C++ Example:
67  * \include example-Geoid.cpp
68  * Visual Basic Example:
69  * \include example-Geoid.vb
70  *
71  * <B>INTERFACE DIFFERENCES:</B><BR>
72  * The () operator has been replaced with Height method.
73  *
74  * The following functions are implemented as properties:
75  * Description, DateTime, GeoidFile, GeoidName, GeoidDirectory,
76  * Interpolation, MaxError, RMSError, Offset, Scale, ThreadSafe,
77  * Cache, CacheWest, CacheEast, CacheNorth, CacheSouth, MajorRadius,
78  * and Flattening.
79  **********************************************************************/
80  public ref class Geoid
81  {
82  private:
83  // a pointer to the unmanaged GeographicLib::Geoid.
84  const GeographicLib::Geoid* m_pGeoid;
85 
86  // the finalizer frees hthe unmanaged memory when the object is destroyed.
87  !Geoid(void);
88  public:
89  /**
90  * Flags indicating conversions between heights above the geoid and heights
91  * above the ellipsoid.
92  **********************************************************************/
93  enum class ConvertFlag {
94  /**
95  * The multiplier for converting from heights above the geoid to heights
96  * above the ellipsoid.
97  **********************************************************************/
98  ELLIPSOIDTOGEOID = -1,
99  /**
100  * No conversion.
101  **********************************************************************/
102  NONE = 0,
103  /**
104  * The multiplier for converting from heights above the ellipsoid to
105  * heights above the geoid.
106  **********************************************************************/
107  GEOIDTOELLIPSOID = 1,
108  };
109 
110  /** \name Setting up the geoid
111  **********************************************************************/
112  ///@{
113  /**
114  * Construct a geoid.
115  *
116  * @param[in] name the name of the geoid.
117  * @param[in] path (optional) directory for data file.
118  * @param[in] cubic (optional) interpolation method; false means bilinear,
119  * true (the default) means cubic.
120  * @param[in] threadsafe (optional), if true, construct a thread safe
121  * object. The default is false
122  * @exception GeographicErr if the data file cannot be found, is
123  * unreadable, or is corrupt.
124  * @exception GeographicErr if \e threadsafe is true but the memory
125  * necessary for caching the data can't be allocated.
126  *
127  * The data file is formed by appending ".pgm" to the name. If \e path is
128  * specified (and is non-empty), then the file is loaded from directory, \e
129  * path. Otherwise the path is given by DefaultGeoidPath(). If the \e
130  * threadsafe parameter is true, the data set is read into memory, the data
131  * file is closed, and single-cell caching is turned off; this results in a
132  * Geoid object which \e is thread safe.
133  **********************************************************************/
134  Geoid(System::String^ name, System::String^ path,
135  bool cubic, bool threadsafe);
136  /**
137  * The destructor calls the finalizer.
138  **********************************************************************/
140  { this->!Geoid(); }
141 
142  /**
143  * Set up a cache.
144  *
145  * @param[in] south latitude (degrees) of the south edge of the cached area.
146  * @param[in] west longitude (degrees) of the west edge of the cached area.
147  * @param[in] north latitude (degrees) of the north edge of the cached area.
148  * @param[in] east longitude (degrees) of the east edge of the cached area.
149  * @exception GeographicErr if the memory necessary for caching the data
150  * can't be allocated (in this case, you will have no cache and can try
151  * again with a smaller area).
152  * @exception GeographicErr if there's a problem reading the data.
153  * @exception GeographicErr if this is called on a threadsafe Geoid.
154  *
155  * Cache the data for the specified "rectangular" area bounded by the
156  * parallels \e south and \e north and the meridians \e west and \e east.
157  * \e east is always interpreted as being east of \e west, if necessary by
158  * adding 360&deg; to its value. \e south and \e north should be in
159  * the range [&minus;90&deg;, 90&deg;]; \e west and \e east should
160  * be in the range [&minus;540&deg;, 540&deg;).
161  **********************************************************************/
162  void CacheArea(double south, double west, double north, double east);
163 
164  /**
165  * Cache all the data.
166  *
167  * @exception GeographicErr if the memory necessary for caching the data
168  * can't be allocated (in this case, you will have no cache and can try
169  * again with a smaller area).
170  * @exception GeographicErr if there's a problem reading the data.
171  * @exception GeographicErr if this is called on a threadsafe Geoid.
172  *
173  * On most computers, this is fast for data sets with grid resolution of 5'
174  * or coarser. For a 1' grid, the required RAM is 450MB; a 2.5' grid needs
175  * 72MB; and a 5' grid needs 18MB.
176  **********************************************************************/
177  void CacheAll();
178 
179  /**
180  * Clear the cache. This never throws an error. (This does nothing with a
181  * thread safe Geoid.)
182  **********************************************************************/
183  void CacheClear();
184 
185  ///@}
186 
187  /** \name Compute geoid heights
188  **********************************************************************/
189  ///@{
190  /**
191  * Compute the geoid height at a point
192  *
193  * @param[in] lat latitude of the point (degrees).
194  * @param[in] lon longitude of the point (degrees).
195  * @exception GeographicErr if there's a problem reading the data; this
196  * never happens if (\e lat, \e lon) is within a successfully cached area.
197  * @return geoid height (meters).
198  *
199  * The latitude should be in [&minus;90&deg;, 90&deg;] and
200  * longitude should be in [&minus;540&deg;, 540&deg;).
201  **********************************************************************/
202  double Height(double lat, double lon);
203 
204  /**
205  * Compute the geoid height and gradient at a point
206  *
207  * @param[in] lat latitude of the point (degrees).
208  * @param[in] lon longitude of the point (degrees).
209  * @param[out] gradn northerly gradient (dimensionless).
210  * @param[out] grade easterly gradient (dimensionless).
211  * @exception GeographicErr if there's a problem reading the data; this
212  * never happens if (\e lat, \e lon) is within a successfully cached area.
213  * @return geoid height (meters).
214  *
215  * The latitude should be in [&minus;90&deg;, 90&deg;] and
216  * longitude should be in [&minus;540&deg;, 540&deg;). As a result
217  * of the way that the geoid data is stored, the calculation of gradients
218  * can result in large quantization errors. This is particularly acute for
219  * fine grids, at high latitudes, and for the easterly gradient. If you
220  * need to compute the direction of the acceleration due to gravity
221  * accurately, you should use GravityModel::Gravity.
222  **********************************************************************/
223  double Height(double lat, double lon,
224  [System::Runtime::InteropServices::Out] double% gradn,
225  [System::Runtime::InteropServices::Out] double% grade);
226 
227  /**
228  * Convert a height above the geoid to a height above the ellipsoid and
229  * vice versa.
230  *
231  * @param[in] lat latitude of the point (degrees).
232  * @param[in] lon longitude of the point (degrees).
233  * @param[in] h height of the point (degrees).
234  * @param[in] d a Geoid::convertflag specifying the direction of the
235  * conversion; Geoid::GEOIDTOELLIPSOID means convert a height above the
236  * geoid to a height above the ellipsoid; Geoid::ELLIPSOIDTOGEOID means
237  * convert a height above the ellipsoid to a height above the geoid.
238  * @exception GeographicErr if there's a problem reading the data; this
239  * never happens if (\e lat, \e lon) is within a successfully cached area.
240  * @return converted height (meters).
241  **********************************************************************/
242  double ConvertHeight(double lat, double lon, double h,
243  ConvertFlag d);
244 
245  ///@}
246 
247  /** \name Inspector functions
248  **********************************************************************/
249  ///@{
250  /**
251  * @return geoid description, if available, in the data file; if
252  * absent, return "NONE".
253  **********************************************************************/
254  property System::String^ Description { System::String^ get(); }
255 
256  /**
257  * @return date of the data file; if absent, return "UNKNOWN".
258  **********************************************************************/
259  property System::String^ DateTime { System::String^ get(); }
260 
261  /**
262  * @return full file name used to load the geoid data.
263  **********************************************************************/
264  property System::String^ GeoidFile { System::String^ get(); }
265 
266  /**
267  * @return "name" used to load the geoid data (from the first argument of
268  * the constructor).
269  **********************************************************************/
270  property System::String^ GeoidName { System::String^ get(); }
271 
272  /**
273  * @return directory used to load the geoid data.
274  **********************************************************************/
275  property System::String^ GeoidDirectory { System::String^ get(); }
276 
277  /**
278  * @return interpolation method ("cubic" or "bilinear").
279  **********************************************************************/
280  property System::String^ Interpolation { System::String^ get(); }
281 
282  /**
283  * @return estimate of the maximum interpolation and quantization error
284  * (meters).
285  *
286  * This relies on the value being stored in the data file. If the value is
287  * absent, return &minus;1.
288  **********************************************************************/
289  property double MaxError { double get(); }
290 
291  /**
292  * @return estimate of the RMS interpolation and quantization error
293  * (meters).
294  *
295  * This relies on the value being stored in the data file. If the value is
296  * absent, return &minus;1.
297  **********************************************************************/
298  property double RMSError { double get(); }
299 
300  /**
301  * @return offset (meters).
302  *
303  * This in used in converting from the pixel values in the data file to
304  * geoid heights.
305  **********************************************************************/
306  property double Offset { double get(); }
307 
308  /**
309  * @return scale (meters).
310  *
311  * This in used in converting from the pixel values in the data file to
312  * geoid heights.
313  **********************************************************************/
314  property double Scale { double get(); }
315 
316  /**
317  * @return true if the object is constructed to be thread safe.
318  **********************************************************************/
319  property bool ThreadSafe { bool get(); }
320 
321  /**
322  * @return true if a data cache is active.
323  **********************************************************************/
324  property bool Cache { bool get(); }
325 
326  /**
327  * @return west edge of the cached area; the cache includes this edge.
328  **********************************************************************/
329  property double CacheWest { double get(); }
330 
331  /**
332  * @return east edge of the cached area; the cache excludes this edge.
333  **********************************************************************/
334  property double CacheEast { double get(); }
335 
336  /**
337  * @return north edge of the cached area; the cache includes this edge.
338  **********************************************************************/
339  property double CacheNorth { double get(); }
340 
341  /**
342  * @return south edge of the cached area; the cache excludes this edge
343  * unless it's the south pole.
344  **********************************************************************/
345  property double CacheSouth { double get(); }
346 
347  /**
348  * @return \e a the equatorial radius of the WGS84 ellipsoid (meters).
349  *
350  * (The WGS84 value is returned because the supported geoid models are all
351  * based on this ellipsoid.)
352  **********************************************************************/
353  property double MajorRadius { double get(); }
354 
355  /**
356  * @return \e f the flattening of the WGS84 ellipsoid.
357  *
358  * (The WGS84 value is returned because the supported geoid models are all
359  * based on this ellipsoid.)
360  **********************************************************************/
361  property double Flattening { double get(); }
362  ///@}
363 
364  /**
365  * @return the default path for geoid data files.
366  *
367  * This is the value of the environment variable
368  * GEOGRAPHICLIB_GEOID_PATH, if set; otherwise, it is
369  * $GEOGRAPHICLIB_DATA/geoids if the environment variable
370  * GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default
371  * (/usr/local/share/GeographicLib/geoids on non-Windows systems and
372  * C:/ProgramData/GeographicLib/geoids on Windows systems).
373  **********************************************************************/
374  static System::String^ DefaultGeoidPath();
375 
376  /**
377  * @return the default name for the geoid.
378  *
379  * This is the value of the environment variable
380  * GEOGRAPHICLIB_GEOID_NAME, if set, otherwise, it is "egm96-5". The
381  * Geoid class does not use this function; it is just provided as a
382  * convenience for a calling program when constructing a Geoid object.
383  **********************************************************************/
384  static System::String^ DefaultGeoidName();
385  };
386 } // namespace NETGeographicLib
System::String^ GeoidDirectory
Definition: Geoid.h:275
void CacheArea(double south, double west, double north, double east)
System::String^ DateTime
Definition: Geoid.h:259
System::String^ GeoidName
Definition: Geoid.h:270
Geoid(System::String^ name, System::String^ path, bool cubic, bool threadsafe)
static System::String^ DefaultGeoidPath()
System::String^ Interpolation
Definition: Geoid.h:280
static System::String^ DefaultGeoidName()
double ConvertHeight(double lat, double lon, double h, ConvertFlag d)
System::String^ GeoidFile
Definition: Geoid.h:264
System::String^ Description
Definition: Geoid.h:254
double Height(double lat, double lon)
.NET wrapper for GeographicLib::Geoid.
Definition: Geoid.h:80