00001 #pragma once 00002 /** 00003 * \file NETGeographicLib/Geoid.h 00004 * \brief Header for NETGeographicLib::Geoid class 00005 * 00006 * NETGeographicLib is copyright (c) Scott Heiman (2013) 00007 * GeographicLib is Copyright (c) Charles Karney (2010-2012) 00008 * <charles@karney.com> and licensed under the MIT/X11 License. 00009 * For more information, see 00010 * http://geographiclib.sourceforge.net/ 00011 **********************************************************************/ 00012 00013 namespace NETGeographicLib 00014 { 00015 /** 00016 * \brief .NET wrapper for GeographicLib::Geoid. 00017 * 00018 * This class allows .NET applications to access GeographicLib::Geoid. 00019 * 00020 * This class evaluated the height of one of the standard geoids, EGM84, 00021 * EGM96, or EGM2008 by bilinear or cubic interpolation into a rectangular 00022 * grid of data. These geoid models are documented in 00023 * - EGM84: 00024 * http://earth-info.nga.mil/GandG/wgs84/gravitymod/wgs84_180/wgs84_180.html 00025 * - EGM96: 00026 * http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm96/egm96.html 00027 * - EGM2008: 00028 * http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008 00029 * 00030 * The geoids are defined in terms of spherical harmonics. However in order 00031 * to provide a quick and flexible method of evaluating the geoid heights, 00032 * this class evaluates the height by interpolation into a grid of 00033 * precomputed values. 00034 * 00035 * See \ref geoid for details of how to install the data sets, the data 00036 * format, estimates of the interpolation errors, and how to use caching. 00037 * 00038 * In addition to returning the geoid height, the gradient of the geoid can 00039 * be calculated. The gradient is defined as the rate of change of the geoid 00040 * as a function of position on the ellipsoid. This uses the parameters for 00041 * the WGS84 ellipsoid. The gradient defined in terms of the interpolated 00042 * heights. As a result of the way that the geoid data is stored, the 00043 * calculation of gradients can result in large quantization errors. This is 00044 * particularly acute for fine grids, at high latitudes, and for the easterly 00045 * gradient. 00046 * 00047 * This class is typically \e not thread safe in that a single instantiation 00048 * cannot be safely used by multiple threads because of the way the object 00049 * reads the data set and because it maintains a single-cell cache. If 00050 * multiple threads need to calculate geoid heights they should all construct 00051 * thread-local instantiations. Alternatively, set the optional \e 00052 * threadsafe parameter to true in the constructor. This causes the 00053 * constructor to read all the data into memory and to turn off the 00054 * single-cell caching which results in a Geoid object which \e is thread 00055 * safe. 00056 * 00057 * C# Example: 00058 * \include example-Geoid.cs 00059 * Managed C++ Example: 00060 * \include example-Geoid.cpp 00061 * Visual Basic Example: 00062 * \include example-Geoid.vb 00063 * 00064 * <B>INTERFACE DIFFERENCES:</B><BR> 00065 * The () operator has been replaced with Height method. 00066 * 00067 * The following functions are implemented as properties: 00068 * Description, DateTime, GeoidFile, GeoidName, GeoidDirectory, 00069 * Interpolation, MaxError, RMSError, Offset, Scale, ThreadSafe, 00070 * Cache, CacheWest, CacheEast, CacheNorth, CacheSouth, MajorRadius, 00071 * and Flattening. 00072 **********************************************************************/ 00073 public ref class Geoid 00074 { 00075 private: 00076 // a pointer to the unmanaged GeographicLib::Geoid. 00077 const GeographicLib::Geoid* m_pGeoid; 00078 00079 // the finalizer frees hthe unmanaged memory when the object is destroyed. 00080 !Geoid(void); 00081 public: 00082 /** 00083 * Flags indicating conversions between heights above the geoid and heights 00084 * above the ellipsoid. 00085 **********************************************************************/ 00086 enum class ConvertFlag { 00087 /** 00088 * The multiplier for converting from heights above the geoid to heights 00089 * above the ellipsoid. 00090 **********************************************************************/ 00091 ELLIPSOIDTOGEOID = -1, 00092 /** 00093 * No conversion. 00094 **********************************************************************/ 00095 NONE = 0, 00096 /** 00097 * The multiplier for converting from heights above the ellipsoid to 00098 * heights above the geoid. 00099 **********************************************************************/ 00100 GEOIDTOELLIPSOID = 1, 00101 }; 00102 00103 /** \name Setting up the geoid 00104 **********************************************************************/ 00105 ///@{ 00106 /** 00107 * Construct a geoid. 00108 * 00109 * @param[in] name the name of the geoid. 00110 * @param[in] path (optional) directory for data file. 00111 * @param[in] cubic (optional) interpolation method; false means bilinear, 00112 * true (the default) means cubic. 00113 * @param[in] threadsafe (optional), if true, construct a thread safe 00114 * object. The default is false 00115 * @exception GeographicErr if the data file cannot be found, is 00116 * unreadable, or is corrupt. 00117 * @exception GeographicErr if \e threadsafe is true but the memory 00118 * necessary for caching the data can't be allocated. 00119 * 00120 * The data file is formed by appending ".pgm" to the name. If \e path is 00121 * specified (and is non-empty), then the file is loaded from directory, \e 00122 * path. Otherwise the path is given by DefaultGeoidPath(). If the \e 00123 * threadsafe parameter is true, the data set is read into memory, the data 00124 * file is closed, and single-cell caching is turned off; this results in a 00125 * Geoid object which \e is thread safe. 00126 **********************************************************************/ 00127 Geoid(System::String^ name, System::String^ path, 00128 bool cubic, bool threadsafe); 00129 /** 00130 * The destructor calls the finalizer. 00131 **********************************************************************/ 00132 ~Geoid() 00133 { this->!Geoid(); } 00134 00135 /** 00136 * Set up a cache. 00137 * 00138 * @param[in] south latitude (degrees) of the south edge of the cached area. 00139 * @param[in] west longitude (degrees) of the west edge of the cached area. 00140 * @param[in] north latitude (degrees) of the north edge of the cached area. 00141 * @param[in] east longitude (degrees) of the east edge of the cached area. 00142 * @exception GeographicErr if the memory necessary for caching the data 00143 * can't be allocated (in this case, you will have no cache and can try 00144 * again with a smaller area). 00145 * @exception GeographicErr if there's a problem reading the data. 00146 * @exception GeographicErr if this is called on a threadsafe Geoid. 00147 * 00148 * Cache the data for the specified "rectangular" area bounded by the 00149 * parallels \e south and \e north and the meridians \e west and \e east. 00150 * \e east is always interpreted as being east of \e west, if necessary by 00151 * adding 360° to its value. \e south and \e north should be in 00152 * the range [−90°, 90°]; \e west and \e east should 00153 * be in the range [−540°, 540°). 00154 **********************************************************************/ 00155 void CacheArea(double south, double west, double north, double east); 00156 00157 /** 00158 * Cache all the data. 00159 * 00160 * @exception GeographicErr if the memory necessary for caching the data 00161 * can't be allocated (in this case, you will have no cache and can try 00162 * again with a smaller area). 00163 * @exception GeographicErr if there's a problem reading the data. 00164 * @exception GeographicErr if this is called on a threadsafe Geoid. 00165 * 00166 * On most computers, this is fast for data sets with grid resolution of 5' 00167 * or coarser. For a 1' grid, the required RAM is 450MB; a 2.5' grid needs 00168 * 72MB; and a 5' grid needs 18MB. 00169 **********************************************************************/ 00170 void CacheAll(); 00171 00172 /** 00173 * Clear the cache. This never throws an error. (This does nothing with a 00174 * thread safe Geoid.) 00175 **********************************************************************/ 00176 void CacheClear(); 00177 00178 ///@} 00179 00180 /** \name Compute geoid heights 00181 **********************************************************************/ 00182 ///@{ 00183 /** 00184 * Compute the geoid height at a point 00185 * 00186 * @param[in] lat latitude of the point (degrees). 00187 * @param[in] lon longitude of the point (degrees). 00188 * @exception GeographicErr if there's a problem reading the data; this 00189 * never happens if (\e lat, \e lon) is within a successfully cached area. 00190 * @return geoid height (meters). 00191 * 00192 * The latitude should be in [−90°, 90°] and 00193 * longitude should be in [−540°, 540°). 00194 **********************************************************************/ 00195 double Height(double lat, double lon); 00196 00197 /** 00198 * Compute the geoid height and gradient at a point 00199 * 00200 * @param[in] lat latitude of the point (degrees). 00201 * @param[in] lon longitude of the point (degrees). 00202 * @param[out] gradn northerly gradient (dimensionless). 00203 * @param[out] grade easterly gradient (dimensionless). 00204 * @exception GeographicErr if there's a problem reading the data; this 00205 * never happens if (\e lat, \e lon) is within a successfully cached area. 00206 * @return geoid height (meters). 00207 * 00208 * The latitude should be in [−90°, 90°] and 00209 * longitude should be in [−540°, 540°). As a result 00210 * of the way that the geoid data is stored, the calculation of gradients 00211 * can result in large quantization errors. This is particularly acute for 00212 * fine grids, at high latitudes, and for the easterly gradient. If you 00213 * need to compute the direction of the acceleration due to gravity 00214 * accurately, you should use GravityModel::Gravity. 00215 **********************************************************************/ 00216 double Height(double lat, double lon, 00217 [System::Runtime::InteropServices::Out] double% gradn, 00218 [System::Runtime::InteropServices::Out] double% grade); 00219 00220 /** 00221 * Convert a height above the geoid to a height above the ellipsoid and 00222 * vice versa. 00223 * 00224 * @param[in] lat latitude of the point (degrees). 00225 * @param[in] lon longitude of the point (degrees). 00226 * @param[in] h height of the point (degrees). 00227 * @param[in] d a Geoid::convertflag specifying the direction of the 00228 * conversion; Geoid::GEOIDTOELLIPSOID means convert a height above the 00229 * geoid to a height above the ellipsoid; Geoid::ELLIPSOIDTOGEOID means 00230 * convert a height above the ellipsoid to a height above the geoid. 00231 * @exception GeographicErr if there's a problem reading the data; this 00232 * never happens if (\e lat, \e lon) is within a successfully cached area. 00233 * @return converted height (meters). 00234 **********************************************************************/ 00235 double ConvertHeight(double lat, double lon, double h, 00236 ConvertFlag d); 00237 00238 ///@} 00239 00240 /** \name Inspector functions 00241 **********************************************************************/ 00242 ///@{ 00243 /** 00244 * @return geoid description, if available, in the data file; if 00245 * absent, return "NONE". 00246 **********************************************************************/ 00247 property System::String^ Description { System::String^ get(); } 00248 00249 /** 00250 * @return date of the data file; if absent, return "UNKNOWN". 00251 **********************************************************************/ 00252 property System::String^ DateTime { System::String^ get(); } 00253 00254 /** 00255 * @return full file name used to load the geoid data. 00256 **********************************************************************/ 00257 property System::String^ GeoidFile { System::String^ get(); } 00258 00259 /** 00260 * @return "name" used to load the geoid data (from the first argument of 00261 * the constructor). 00262 **********************************************************************/ 00263 property System::String^ GeoidName { System::String^ get(); } 00264 00265 /** 00266 * @return directory used to load the geoid data. 00267 **********************************************************************/ 00268 property System::String^ GeoidDirectory { System::String^ get(); } 00269 00270 /** 00271 * @return interpolation method ("cubic" or "bilinear"). 00272 **********************************************************************/ 00273 property System::String^ Interpolation { System::String^ get(); } 00274 00275 /** 00276 * @return estimate of the maximum interpolation and quantization error 00277 * (meters). 00278 * 00279 * This relies on the value being stored in the data file. If the value is 00280 * absent, return −1. 00281 **********************************************************************/ 00282 property double MaxError { double get(); } 00283 00284 /** 00285 * @return estimate of the RMS interpolation and quantization error 00286 * (meters). 00287 * 00288 * This relies on the value being stored in the data file. If the value is 00289 * absent, return −1. 00290 **********************************************************************/ 00291 property double RMSError { double get(); } 00292 00293 /** 00294 * @return offset (meters). 00295 * 00296 * This in used in converting from the pixel values in the data file to 00297 * geoid heights. 00298 **********************************************************************/ 00299 property double Offset { double get(); } 00300 00301 /** 00302 * @return scale (meters). 00303 * 00304 * This in used in converting from the pixel values in the data file to 00305 * geoid heights. 00306 **********************************************************************/ 00307 property double Scale { double get(); } 00308 00309 /** 00310 * @return true if the object is constructed to be thread safe. 00311 **********************************************************************/ 00312 property bool ThreadSafe { bool get(); } 00313 00314 /** 00315 * @return true if a data cache is active. 00316 **********************************************************************/ 00317 property bool Cache { bool get(); } 00318 00319 /** 00320 * @return west edge of the cached area; the cache includes this edge. 00321 **********************************************************************/ 00322 property double CacheWest { double get(); } 00323 00324 /** 00325 * @return east edge of the cached area; the cache excludes this edge. 00326 **********************************************************************/ 00327 property double CacheEast { double get(); } 00328 00329 /** 00330 * @return north edge of the cached area; the cache includes this edge. 00331 **********************************************************************/ 00332 property double CacheNorth { double get(); } 00333 00334 /** 00335 * @return south edge of the cached area; the cache excludes this edge 00336 * unless it's the south pole. 00337 **********************************************************************/ 00338 property double CacheSouth { double get(); } 00339 00340 /** 00341 * @return \e a the equatorial radius of the WGS84 ellipsoid (meters). 00342 * 00343 * (The WGS84 value is returned because the supported geoid models are all 00344 * based on this ellipsoid.) 00345 **********************************************************************/ 00346 property double MajorRadius { double get(); } 00347 00348 /** 00349 * @return \e f the flattening of the WGS84 ellipsoid. 00350 * 00351 * (The WGS84 value is returned because the supported geoid models are all 00352 * based on this ellipsoid.) 00353 **********************************************************************/ 00354 property double Flattening { double get(); } 00355 ///@} 00356 00357 /** 00358 * @return the default path for geoid data files. 00359 * 00360 * This is the value of the environment variable 00361 * GEOGRAPHICLIB_GEOID_PATH, if set; otherwise, it is 00362 * $GEOGRAPHICLIB_DATA/geoids if the environment variable 00363 * GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default 00364 * (/usr/local/share/GeographicLib/geoids on non-Windows systems and 00365 * C:/ProgramData/GeographicLib/geoids on Windows systems). 00366 **********************************************************************/ 00367 static System::String^ DefaultGeoidPath(); 00368 00369 /** 00370 * @return the default name for the geoid. 00371 * 00372 * This is the value of the environment variable 00373 * GEOGRAPHICLIB_GEOID_NAME, if set, otherwise, it is "egm96-5". The 00374 * Geoid class does not use this function; it is just provided as a 00375 * convenience for a calling program when constructing a Geoid object. 00376 **********************************************************************/ 00377 static System::String^ DefaultGeoidName(); 00378 }; 00379 } // namespace NETGeographicLib