00001 #pragma once 00002 /** 00003 * \file NETGeographicLib/PolygonArea.h 00004 * \brief Header for NETGeographicLib::PolygonArea 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 ref class Geodesic; 00016 /** 00017 * \brief .NET wrapper for GeographicLib::PolygonArea and PolygonAreaExact. 00018 * 00019 * This class allows .NET applications to access GeographicLib::PolygonArea. 00020 * 00021 * This computes the area of a geodesic polygon using the method given 00022 * Section 6 of 00023 * - C. F. F. Karney, 00024 * <a href="http://dx.doi.org/10.1007/s00190-012-0578-z"> 00025 * Algorithms for geodesics</a>, 00026 * J. Geodesy <b>87</b>, 43--55 (2013); 00027 * DOI: <a href="http://dx.doi.org/10.1007/s00190-012-0578-z"> 00028 * 10.1007/s00190-012-0578-z</a>; 00029 * addenda: <a href="http://geographiclib.sf.net/geod-addenda.html"> 00030 * geod-addenda.html</a>. 00031 * 00032 * This class lets you add vertices one at a time to the polygon. The area 00033 * and perimeter are accumulated in two times the standard floating point 00034 * precision to guard against the loss of accuracy with many-sided polygons. 00035 * At any point you can ask for the perimeter and area so far. There's an 00036 * option to treat the points as defining a polyline instead of a polygon; in 00037 * that case, only the perimeter is computed. 00038 * 00039 * C# Example: 00040 * \include example-PolygonArea.cs 00041 * Managed C++ Example: 00042 * \include example-PolygonArea.cpp 00043 * Visual Basic Example: 00044 * \include example-PolygonArea.vb 00045 * 00046 * <B>INTERFACE DIFFERENCES:</B><BR> 00047 * The MajorRadius and Flattening functions are implemented as properties. 00048 **********************************************************************/ 00049 public ref class PolygonArea 00050 { 00051 private: 00052 // a pointer to the unmanaged GeographicLib::PolygonArea 00053 GeographicLib::PolygonArea* m_pPolygonArea; 00054 00055 // the finalize frees the unmanaged memory when the object is destroyed. 00056 !PolygonArea(void); 00057 public: 00058 00059 /** 00060 * Constructor for PolygonArea. 00061 * 00062 * @param[in] earth the Geodesic object to use for geodesic calculations. 00063 * @param[in] polyline if true that treat the points as defining a polyline 00064 * instead of a polygon. 00065 **********************************************************************/ 00066 PolygonArea(Geodesic^ earth, bool polyline ); 00067 00068 /** 00069 * Constructor for PolygonArea that assumes a WGS84 ellipsoid. 00070 * 00071 * @param[in] polyline if true that treat the points as defining a polyline 00072 * instead of a polygon. 00073 **********************************************************************/ 00074 PolygonArea(const bool polyline ); 00075 00076 /** 00077 * The destructor calls the finalizer. 00078 **********************************************************************/ 00079 ~PolygonArea() 00080 { this->!PolygonArea(); } 00081 00082 /** 00083 * Clear PolygonArea, allowing a new polygon to be started. 00084 **********************************************************************/ 00085 void Clear(); 00086 00087 /** 00088 * Add a point to the polygon or polyline. 00089 * 00090 * @param[in] lat the latitude of the point (degrees). 00091 * @param[in] lon the longitude of the point (degrees). 00092 * 00093 * \e lat should be in the range [−90°, 90°] and \e 00094 * lon should be in the range [−540°, 540°). 00095 **********************************************************************/ 00096 void AddPoint(double lat, double lon); 00097 00098 /** 00099 * Add an edge to the polygon or polyline. 00100 * 00101 * @param[in] azi azimuth at current point (degrees). 00102 * @param[in] s distance from current point to next point (meters). 00103 * 00104 * \e azi should be in the range [−540°, 540°). This does 00105 * nothing if no points have been added yet. Use PolygonArea::CurrentPoint 00106 * to determine the position of the new vertex. 00107 **********************************************************************/ 00108 void AddEdge(double azi, double s); 00109 00110 /** 00111 * Return the results so far. 00112 * 00113 * @param[in] reverse if true then clockwise (instead of counter-clockwise) 00114 * traversal counts as a positive area. 00115 * @param[in] sign if true then return a signed result for the area if 00116 * the polygon is traversed in the "wrong" direction instead of returning 00117 * the area for the rest of the earth. 00118 * @param[out] perimeter the perimeter of the polygon or length of the 00119 * polyline (meters). 00120 * @param[out] area the area of the polygon (meters<sup>2</sup>); only set 00121 * if \e polyline is false in the constructor. 00122 * @return the number of points. 00123 **********************************************************************/ 00124 unsigned Compute(bool reverse, bool sign, 00125 [System::Runtime::InteropServices::Out] double% perimeter, 00126 [System::Runtime::InteropServices::Out] double% area); 00127 00128 /** 00129 * Return the results assuming a tentative final test point is added; 00130 * however, the data for the test point is not saved. This lets you report 00131 * a running result for the perimeter and area as the user moves the mouse 00132 * cursor. Ordinary floating point arithmetic is used to accumulate the 00133 * data for the test point; thus the area and perimeter returned are less 00134 * accurate than if PolygonArea::AddPoint and PolygonArea::Compute are 00135 * used. 00136 * 00137 * @param[in] lat the latitude of the test point (degrees). 00138 * @param[in] lon the longitude of the test point (degrees). 00139 * @param[in] reverse if true then clockwise (instead of counter-clockwise) 00140 * traversal counts as a positive area. 00141 * @param[in] sign if true then return a signed result for the area if 00142 * the polygon is traversed in the "wrong" direction instead of returning 00143 * the area for the rest of the earth. 00144 * @param[out] perimeter the approximate perimeter of the polygon or length 00145 * of the polyline (meters). 00146 * @param[out] area the approximate area of the polygon 00147 * (meters<sup>2</sup>); only set if polyline is false in the 00148 * constructor. 00149 * @return the number of points. 00150 * 00151 * \e lat should be in the range [−90°, 90°] and \e 00152 * lon should be in the range [−540°, 540°). 00153 **********************************************************************/ 00154 unsigned TestPoint(double lat, double lon, bool reverse, bool sign, 00155 [System::Runtime::InteropServices::Out] double% perimeter, 00156 [System::Runtime::InteropServices::Out] double% area); 00157 00158 /** 00159 * Return the results assuming a tentative final test point is added via an 00160 * azimuth and distance; however, the data for the test point is not saved. 00161 * This lets you report a running result for the perimeter and area as the 00162 * user moves the mouse cursor. Ordinary floating point arithmetic is used 00163 * to accumulate the data for the test point; thus the area and perimeter 00164 * returned are less accurate than if PolygonArea::AddEdge and 00165 * PolygonArea::Compute are used. 00166 * 00167 * @param[in] azi azimuth at current point (degrees). 00168 * @param[in] s distance from current point to final test point (meters). 00169 * @param[in] reverse if true then clockwise (instead of counter-clockwise) 00170 * traversal counts as a positive area. 00171 * @param[in] sign if true then return a signed result for the area if 00172 * the polygon is traversed in the "wrong" direction instead of returning 00173 * the area for the rest of the earth. 00174 * @param[out] perimeter the approximate perimeter of the polygon or length 00175 * of the polyline (meters). 00176 * @param[out] area the approximate area of the polygon 00177 * (meters<sup>2</sup>); only set if polyline is false in the 00178 * constructor. 00179 * @return the number of points. 00180 * 00181 * \e azi should be in the range [−540°, 540°). 00182 **********************************************************************/ 00183 unsigned TestEdge(double azi, double s, bool reverse, bool sign, 00184 [System::Runtime::InteropServices::Out] double% perimeter, 00185 [System::Runtime::InteropServices::Out] double% area); 00186 00187 /** \name Inspector functions 00188 **********************************************************************/ 00189 ///@{ 00190 /** 00191 * @return \e a the equatorial radius of the ellipsoid (meters). This is 00192 * the value inherited from the Geodesic object used in the constructor. 00193 **********************************************************************/ 00194 property double MajorRadius { double get(); } 00195 00196 /** 00197 * @return \e f the flattening of the ellipsoid. This is the value 00198 * inherited from the Geodesic object used in the constructor. 00199 **********************************************************************/ 00200 property double Flattening { double get(); } 00201 00202 /** 00203 * Report the previous vertex added to the polygon or polyline. 00204 * 00205 * @param[out] lat the latitude of the point (degrees). 00206 * @param[out] lon the longitude of the point (degrees). 00207 * 00208 * If no points have been added, then NaNs are returned. Otherwise, \e lon 00209 * will be in the range [−180°, 180°). 00210 **********************************************************************/ 00211 void CurrentPoint([System::Runtime::InteropServices::Out] double% lat, 00212 [System::Runtime::InteropServices::Out] double% lon); 00213 ///@} 00214 }; 00215 00216 //************************************************************************* 00217 // PolygonAreaExact 00218 //************************************************************************* 00219 ref class GeodesicExact; 00220 00221 public ref class PolygonAreaExact 00222 { 00223 private: 00224 // a pointer to the unmanaged GeographicLib::PolygonArea 00225 GeographicLib::PolygonAreaExact* m_pPolygonArea; 00226 00227 // the finalize frees the unmanaged memory when the object is destroyed. 00228 !PolygonAreaExact(void); 00229 public: 00230 00231 /** 00232 * Constructor for PolygonArea. 00233 * 00234 * @param[in] earth the Geodesic object to use for geodesic calculations. 00235 * @param[in] polyline if true that treat the points as defining a polyline 00236 * instead of a polygon. 00237 **********************************************************************/ 00238 PolygonAreaExact(GeodesicExact^ earth, bool polyline ); 00239 00240 /** 00241 * Constructor for PolygonArea that assumes a WGS84 ellipsoid. 00242 * 00243 * @param[in] polyline if true that treat the points as defining a polyline 00244 * instead of a polygon. 00245 **********************************************************************/ 00246 PolygonAreaExact(const bool polyline ); 00247 00248 /** 00249 * The destructor calls the finalizer. 00250 **********************************************************************/ 00251 ~PolygonAreaExact() 00252 { this->!PolygonAreaExact(); } 00253 00254 /** 00255 * Clear PolygonArea, allowing a new polygon to be started. 00256 **********************************************************************/ 00257 void Clear(); 00258 00259 /** 00260 * Add a point to the polygon or polyline. 00261 * 00262 * @param[in] lat the latitude of the point (degrees). 00263 * @param[in] lon the longitude of the point (degrees). 00264 * 00265 * \e lat should be in the range [−90°, 90°] and \e 00266 * lon should be in the range [−540°, 540°). 00267 **********************************************************************/ 00268 void AddPoint(double lat, double lon); 00269 00270 /** 00271 * Add an edge to the polygon or polyline. 00272 * 00273 * @param[in] azi azimuth at current point (degrees). 00274 * @param[in] s distance from current point to next point (meters). 00275 * 00276 * \e azi should be in the range [−540°, 540°). This does 00277 * nothing if no points have been added yet. Use PolygonArea::CurrentPoint 00278 * to determine the position of the new vertex. 00279 **********************************************************************/ 00280 void AddEdge(double azi, double s); 00281 00282 /** 00283 * Return the results so far. 00284 * 00285 * @param[in] reverse if true then clockwise (instead of counter-clockwise) 00286 * traversal counts as a positive area. 00287 * @param[in] sign if true then return a signed result for the area if 00288 * the polygon is traversed in the "wrong" direction instead of returning 00289 * the area for the rest of the earth. 00290 * @param[out] perimeter the perimeter of the polygon or length of the 00291 * polyline (meters). 00292 * @param[out] area the area of the polygon (meters<sup>2</sup>); only set 00293 * if \e polyline is false in the constructor. 00294 * @return the number of points. 00295 **********************************************************************/ 00296 unsigned Compute(bool reverse, bool sign, 00297 [System::Runtime::InteropServices::Out] double% perimeter, 00298 [System::Runtime::InteropServices::Out] double% area); 00299 00300 /** 00301 * Return the results assuming a tentative final test point is added; 00302 * however, the data for the test point is not saved. This lets you report 00303 * a running result for the perimeter and area as the user moves the mouse 00304 * cursor. Ordinary floating point arithmetic is used to accumulate the 00305 * data for the test point; thus the area and perimeter returned are less 00306 * accurate than if PolygonArea::AddPoint and PolygonArea::Compute are 00307 * used. 00308 * 00309 * @param[in] lat the latitude of the test point (degrees). 00310 * @param[in] lon the longitude of the test point (degrees). 00311 * @param[in] reverse if true then clockwise (instead of counter-clockwise) 00312 * traversal counts as a positive area. 00313 * @param[in] sign if true then return a signed result for the area if 00314 * the polygon is traversed in the "wrong" direction instead of returning 00315 * the area for the rest of the earth. 00316 * @param[out] perimeter the approximate perimeter of the polygon or length 00317 * of the polyline (meters). 00318 * @param[out] area the approximate area of the polygon 00319 * (meters<sup>2</sup>); only set if polyline is false in the 00320 * constructor. 00321 * @return the number of points. 00322 * 00323 * \e lat should be in the range [−90°, 90°] and \e 00324 * lon should be in the range [−540°, 540°). 00325 **********************************************************************/ 00326 unsigned TestPoint(double lat, double lon, bool reverse, bool sign, 00327 [System::Runtime::InteropServices::Out] double% perimeter, 00328 [System::Runtime::InteropServices::Out] double% area); 00329 00330 /** 00331 * Return the results assuming a tentative final test point is added via an 00332 * azimuth and distance; however, the data for the test point is not saved. 00333 * This lets you report a running result for the perimeter and area as the 00334 * user moves the mouse cursor. Ordinary floating point arithmetic is used 00335 * to accumulate the data for the test point; thus the area and perimeter 00336 * returned are less accurate than if PolygonArea::AddEdge and 00337 * PolygonArea::Compute are used. 00338 * 00339 * @param[in] azi azimuth at current point (degrees). 00340 * @param[in] s distance from current point to final test point (meters). 00341 * @param[in] reverse if true then clockwise (instead of counter-clockwise) 00342 * traversal counts as a positive area. 00343 * @param[in] sign if true then return a signed result for the area if 00344 * the polygon is traversed in the "wrong" direction instead of returning 00345 * the area for the rest of the earth. 00346 * @param[out] perimeter the approximate perimeter of the polygon or length 00347 * of the polyline (meters). 00348 * @param[out] area the approximate area of the polygon 00349 * (meters<sup>2</sup>); only set if polyline is false in the 00350 * constructor. 00351 * @return the number of points. 00352 * 00353 * \e azi should be in the range [−540°, 540°). 00354 **********************************************************************/ 00355 unsigned TestEdge(double azi, double s, bool reverse, bool sign, 00356 [System::Runtime::InteropServices::Out] double% perimeter, 00357 [System::Runtime::InteropServices::Out] double% area); 00358 00359 /** \name Inspector functions 00360 **********************************************************************/ 00361 ///@{ 00362 /** 00363 * @return \e a the equatorial radius of the ellipsoid (meters). This is 00364 * the value inherited from the Geodesic object used in the constructor. 00365 **********************************************************************/ 00366 property double MajorRadius { double get(); } 00367 00368 /** 00369 * @return \e f the flattening of the ellipsoid. This is the value 00370 * inherited from the Geodesic object used in the constructor. 00371 **********************************************************************/ 00372 property double Flattening { double get(); } 00373 00374 /** 00375 * Report the previous vertex added to the polygon or polyline. 00376 * 00377 * @param[out] lat the latitude of the point (degrees). 00378 * @param[out] lon the longitude of the point (degrees). 00379 * 00380 * If no points have been added, then NaNs are returned. Otherwise, \e lon 00381 * will be in the range [−180°, 180°). 00382 **********************************************************************/ 00383 void CurrentPoint([System::Runtime::InteropServices::Out] double% lat, 00384 [System::Runtime::InteropServices::Out] double% lon); 00385 ///@} 00386 }; 00387 } // namespace NETGeographicLib