NETGeographicLib  1.43
PolygonArea.h
Go to the documentation of this file.
1 #pragma once
2 /**
3  * \file NETGeographicLib/PolygonArea.h
4  * \brief Header for NETGeographicLib::PolygonArea 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  ref class Geodesic;
16  /**
17  * \brief .NET wrapper for GeographicLib::PolygonArea and PolygonAreaExact.
18  *
19  * This class allows .NET applications to access GeographicLib::PolygonArea.
20  *
21  * This computes the area of a geodesic polygon using the method given
22  * Section 6 of
23  * - C. F. F. Karney,
24  * <a href="https://dx.doi.org/10.1007/s00190-012-0578-z">
25  * Algorithms for geodesics</a>,
26  * J. Geodesy <b>87</b>, 43--55 (2013);
27  * DOI: <a href="https://dx.doi.org/10.1007/s00190-012-0578-z">
28  * 10.1007/s00190-012-0578-z</a>;
29  * addenda: <a href="http://geographiclib.sf.net/geod-addenda.html">
30  * geod-addenda.html</a>.
31  *
32  * This class lets you add vertices one at a time to the polygon. The area
33  * and perimeter are accumulated in two times the standard floating point
34  * precision to guard against the loss of accuracy with many-sided polygons.
35  * At any point you can ask for the perimeter and area so far. There's an
36  * option to treat the points as defining a polyline instead of a polygon; in
37  * that case, only the perimeter is computed.
38  *
39  * C# Example:
40  * \include example-PolygonArea.cs
41  * Managed C++ Example:
42  * \include example-PolygonArea.cpp
43  * Visual Basic Example:
44  * \include example-PolygonArea.vb
45  *
46  * <B>INTERFACE DIFFERENCES:</B><BR>
47  * The MajorRadius and Flattening functions are implemented as properties.
48  **********************************************************************/
49  public ref class PolygonArea
50  {
51  private:
52  // a pointer to the unmanaged GeographicLib::PolygonArea
53  GeographicLib::PolygonArea* m_pPolygonArea;
54 
55  // the finalize frees the unmanaged memory when the object is destroyed.
56  !PolygonArea(void);
57  public:
58 
59  /**
60  * Constructor for PolygonArea.
61  *
62  * @param[in] earth the Geodesic object to use for geodesic calculations.
63  * @param[in] polyline if true that treat the points as defining a polyline
64  * instead of a polygon.
65  **********************************************************************/
66  PolygonArea(Geodesic^ earth, bool polyline );
67 
68  /**
69  * Constructor for PolygonArea that assumes a WGS84 ellipsoid.
70  *
71  * @param[in] polyline if true that treat the points as defining a polyline
72  * instead of a polygon.
73  **********************************************************************/
74  PolygonArea(const bool polyline );
75 
76  /**
77  * The destructor calls the finalizer.
78  **********************************************************************/
80  { this->!PolygonArea(); }
81 
82  /**
83  * Clear PolygonArea, allowing a new polygon to be started.
84  **********************************************************************/
85  void Clear();
86 
87  /**
88  * Add a point to the polygon or polyline.
89  *
90  * @param[in] lat the latitude of the point (degrees).
91  * @param[in] lon the longitude of the point (degrees).
92  *
93  * \e lat should be in the range [&minus;90&deg;, 90&deg;] and \e
94  * lon should be in the range [&minus;540&deg;, 540&deg;).
95  **********************************************************************/
96  void AddPoint(double lat, double lon);
97 
98  /**
99  * Add an edge to the polygon or polyline.
100  *
101  * @param[in] azi azimuth at current point (degrees).
102  * @param[in] s distance from current point to next point (meters).
103  *
104  * \e azi should be in the range [&minus;540&deg;, 540&deg;). This does
105  * nothing if no points have been added yet. Use PolygonArea::CurrentPoint
106  * to determine the position of the new vertex.
107  **********************************************************************/
108  void AddEdge(double azi, double s);
109 
110  /**
111  * Return the results so far.
112  *
113  * @param[in] reverse if true then clockwise (instead of counter-clockwise)
114  * traversal counts as a positive area.
115  * @param[in] sign if true then return a signed result for the area if
116  * the polygon is traversed in the "wrong" direction instead of returning
117  * the area for the rest of the earth.
118  * @param[out] perimeter the perimeter of the polygon or length of the
119  * polyline (meters).
120  * @param[out] area the area of the polygon (meters<sup>2</sup>); only set
121  * if \e polyline is false in the constructor.
122  * @return the number of points.
123  **********************************************************************/
124  unsigned Compute(bool reverse, bool sign,
125  [System::Runtime::InteropServices::Out] double% perimeter,
126  [System::Runtime::InteropServices::Out] double% area);
127 
128  /**
129  * Return the results assuming a tentative final test point is added;
130  * however, the data for the test point is not saved. This lets you report
131  * a running result for the perimeter and area as the user moves the mouse
132  * cursor. Ordinary floating point arithmetic is used to accumulate the
133  * data for the test point; thus the area and perimeter returned are less
134  * accurate than if PolygonArea::AddPoint and PolygonArea::Compute are
135  * used.
136  *
137  * @param[in] lat the latitude of the test point (degrees).
138  * @param[in] lon the longitude of the test point (degrees).
139  * @param[in] reverse if true then clockwise (instead of counter-clockwise)
140  * traversal counts as a positive area.
141  * @param[in] sign if true then return a signed result for the area if
142  * the polygon is traversed in the "wrong" direction instead of returning
143  * the area for the rest of the earth.
144  * @param[out] perimeter the approximate perimeter of the polygon or length
145  * of the polyline (meters).
146  * @param[out] area the approximate area of the polygon
147  * (meters<sup>2</sup>); only set if polyline is false in the
148  * constructor.
149  * @return the number of points.
150  *
151  * \e lat should be in the range [&minus;90&deg;, 90&deg;] and \e
152  * lon should be in the range [&minus;540&deg;, 540&deg;).
153  **********************************************************************/
154  unsigned TestPoint(double lat, double lon, bool reverse, bool sign,
155  [System::Runtime::InteropServices::Out] double% perimeter,
156  [System::Runtime::InteropServices::Out] double% area);
157 
158  /**
159  * Return the results assuming a tentative final test point is added via an
160  * azimuth and distance; however, the data for the test point is not saved.
161  * This lets you report a running result for the perimeter and area as the
162  * user moves the mouse cursor. Ordinary floating point arithmetic is used
163  * to accumulate the data for the test point; thus the area and perimeter
164  * returned are less accurate than if PolygonArea::AddEdge and
165  * PolygonArea::Compute are used.
166  *
167  * @param[in] azi azimuth at current point (degrees).
168  * @param[in] s distance from current point to final test point (meters).
169  * @param[in] reverse if true then clockwise (instead of counter-clockwise)
170  * traversal counts as a positive area.
171  * @param[in] sign if true then return a signed result for the area if
172  * the polygon is traversed in the "wrong" direction instead of returning
173  * the area for the rest of the earth.
174  * @param[out] perimeter the approximate perimeter of the polygon or length
175  * of the polyline (meters).
176  * @param[out] area the approximate area of the polygon
177  * (meters<sup>2</sup>); only set if polyline is false in the
178  * constructor.
179  * @return the number of points.
180  *
181  * \e azi should be in the range [&minus;540&deg;, 540&deg;).
182  **********************************************************************/
183  unsigned TestEdge(double azi, double s, bool reverse, bool sign,
184  [System::Runtime::InteropServices::Out] double% perimeter,
185  [System::Runtime::InteropServices::Out] double% area);
186 
187  /** \name Inspector functions
188  **********************************************************************/
189  ///@{
190  /**
191  * @return \e a the equatorial radius of the ellipsoid (meters). This is
192  * the value inherited from the Geodesic object used in the constructor.
193  **********************************************************************/
194  property double MajorRadius { double get(); }
195 
196  /**
197  * @return \e f the flattening of the ellipsoid. This is the value
198  * inherited from the Geodesic object used in the constructor.
199  **********************************************************************/
200  property double Flattening { double get(); }
201 
202  /**
203  * Report the previous vertex added to the polygon or polyline.
204  *
205  * @param[out] lat the latitude of the point (degrees).
206  * @param[out] lon the longitude of the point (degrees).
207  *
208  * If no points have been added, then NaNs are returned. Otherwise, \e lon
209  * will be in the range [&minus;180&deg;, 180&deg;).
210  **********************************************************************/
211  void CurrentPoint([System::Runtime::InteropServices::Out] double% lat,
212  [System::Runtime::InteropServices::Out] double% lon);
213  ///@}
214  };
215 
216  //*************************************************************************
217  // PolygonAreaExact
218  //*************************************************************************
219  ref class GeodesicExact;
220 
221  public ref class PolygonAreaExact
222  {
223  private:
224  // a pointer to the unmanaged GeographicLib::PolygonArea
225  GeographicLib::PolygonAreaExact* m_pPolygonArea;
226 
227  // the finalize frees the unmanaged memory when the object is destroyed.
228  !PolygonAreaExact(void);
229  public:
230 
231  /**
232  * Constructor for PolygonArea.
233  *
234  * @param[in] earth the Geodesic object to use for geodesic calculations.
235  * @param[in] polyline if true that treat the points as defining a polyline
236  * instead of a polygon.
237  **********************************************************************/
238  PolygonAreaExact(GeodesicExact^ earth, bool polyline );
239 
240  /**
241  * Constructor for PolygonArea that assumes a WGS84 ellipsoid.
242  *
243  * @param[in] polyline if true that treat the points as defining a polyline
244  * instead of a polygon.
245  **********************************************************************/
246  PolygonAreaExact(const bool polyline );
247 
248  /**
249  * The destructor calls the finalizer.
250  **********************************************************************/
252  { this->!PolygonAreaExact(); }
253 
254  /**
255  * Clear PolygonArea, allowing a new polygon to be started.
256  **********************************************************************/
257  void Clear();
258 
259  /**
260  * Add a point to the polygon or polyline.
261  *
262  * @param[in] lat the latitude of the point (degrees).
263  * @param[in] lon the longitude of the point (degrees).
264  *
265  * \e lat should be in the range [&minus;90&deg;, 90&deg;] and \e
266  * lon should be in the range [&minus;540&deg;, 540&deg;).
267  **********************************************************************/
268  void AddPoint(double lat, double lon);
269 
270  /**
271  * Add an edge to the polygon or polyline.
272  *
273  * @param[in] azi azimuth at current point (degrees).
274  * @param[in] s distance from current point to next point (meters).
275  *
276  * \e azi should be in the range [&minus;540&deg;, 540&deg;). This does
277  * nothing if no points have been added yet. Use PolygonArea::CurrentPoint
278  * to determine the position of the new vertex.
279  **********************************************************************/
280  void AddEdge(double azi, double s);
281 
282  /**
283  * Return the results so far.
284  *
285  * @param[in] reverse if true then clockwise (instead of counter-clockwise)
286  * traversal counts as a positive area.
287  * @param[in] sign if true then return a signed result for the area if
288  * the polygon is traversed in the "wrong" direction instead of returning
289  * the area for the rest of the earth.
290  * @param[out] perimeter the perimeter of the polygon or length of the
291  * polyline (meters).
292  * @param[out] area the area of the polygon (meters<sup>2</sup>); only set
293  * if \e polyline is false in the constructor.
294  * @return the number of points.
295  **********************************************************************/
296  unsigned Compute(bool reverse, bool sign,
297  [System::Runtime::InteropServices::Out] double% perimeter,
298  [System::Runtime::InteropServices::Out] double% area);
299 
300  /**
301  * Return the results assuming a tentative final test point is added;
302  * however, the data for the test point is not saved. This lets you report
303  * a running result for the perimeter and area as the user moves the mouse
304  * cursor. Ordinary floating point arithmetic is used to accumulate the
305  * data for the test point; thus the area and perimeter returned are less
306  * accurate than if PolygonArea::AddPoint and PolygonArea::Compute are
307  * used.
308  *
309  * @param[in] lat the latitude of the test point (degrees).
310  * @param[in] lon the longitude of the test point (degrees).
311  * @param[in] reverse if true then clockwise (instead of counter-clockwise)
312  * traversal counts as a positive area.
313  * @param[in] sign if true then return a signed result for the area if
314  * the polygon is traversed in the "wrong" direction instead of returning
315  * the area for the rest of the earth.
316  * @param[out] perimeter the approximate perimeter of the polygon or length
317  * of the polyline (meters).
318  * @param[out] area the approximate area of the polygon
319  * (meters<sup>2</sup>); only set if polyline is false in the
320  * constructor.
321  * @return the number of points.
322  *
323  * \e lat should be in the range [&minus;90&deg;, 90&deg;] and \e
324  * lon should be in the range [&minus;540&deg;, 540&deg;).
325  **********************************************************************/
326  unsigned TestPoint(double lat, double lon, bool reverse, bool sign,
327  [System::Runtime::InteropServices::Out] double% perimeter,
328  [System::Runtime::InteropServices::Out] double% area);
329 
330  /**
331  * Return the results assuming a tentative final test point is added via an
332  * azimuth and distance; however, the data for the test point is not saved.
333  * This lets you report a running result for the perimeter and area as the
334  * user moves the mouse cursor. Ordinary floating point arithmetic is used
335  * to accumulate the data for the test point; thus the area and perimeter
336  * returned are less accurate than if PolygonArea::AddEdge and
337  * PolygonArea::Compute are used.
338  *
339  * @param[in] azi azimuth at current point (degrees).
340  * @param[in] s distance from current point to final test point (meters).
341  * @param[in] reverse if true then clockwise (instead of counter-clockwise)
342  * traversal counts as a positive area.
343  * @param[in] sign if true then return a signed result for the area if
344  * the polygon is traversed in the "wrong" direction instead of returning
345  * the area for the rest of the earth.
346  * @param[out] perimeter the approximate perimeter of the polygon or length
347  * of the polyline (meters).
348  * @param[out] area the approximate area of the polygon
349  * (meters<sup>2</sup>); only set if polyline is false in the
350  * constructor.
351  * @return the number of points.
352  *
353  * \e azi should be in the range [&minus;540&deg;, 540&deg;).
354  **********************************************************************/
355  unsigned TestEdge(double azi, double s, bool reverse, bool sign,
356  [System::Runtime::InteropServices::Out] double% perimeter,
357  [System::Runtime::InteropServices::Out] double% area);
358 
359  /** \name Inspector functions
360  **********************************************************************/
361  ///@{
362  /**
363  * @return \e a the equatorial radius of the ellipsoid (meters). This is
364  * the value inherited from the Geodesic object used in the constructor.
365  **********************************************************************/
366  property double MajorRadius { double get(); }
367 
368  /**
369  * @return \e f the flattening of the ellipsoid. This is the value
370  * inherited from the Geodesic object used in the constructor.
371  **********************************************************************/
372  property double Flattening { double get(); }
373 
374  /**
375  * Report the previous vertex added to the polygon or polyline.
376  *
377  * @param[out] lat the latitude of the point (degrees).
378  * @param[out] lon the longitude of the point (degrees).
379  *
380  * If no points have been added, then NaNs are returned. Otherwise, \e lon
381  * will be in the range [&minus;180&deg;, 180&deg;).
382  **********************************************************************/
383  void CurrentPoint([System::Runtime::InteropServices::Out] double% lat,
384  [System::Runtime::InteropServices::Out] double% lon);
385  ///@}
386  };
387 
388  //*************************************************************************
389  // PolygonAreaRhumb
390  //*************************************************************************
391  ref class Rhumb;
392 
393  public ref class PolygonAreaRhumb
394  {
395  private:
396  // a pointer to the unmanaged GeographicLib::PolygonArea
397  GeographicLib::PolygonAreaRhumb* m_pPolygonArea;
398 
399  // the finalize frees the unmanaged memory when the object is destroyed.
400  !PolygonAreaRhumb(void);
401  public:
402 
403  /**
404  * Constructor for PolygonArea.
405  *
406  * @param[in] earth the Geodesic object to use for geodesic calculations.
407  * @param[in] polyline if true that treat the points as defining a polyline
408  * instead of a polygon.
409  **********************************************************************/
410  PolygonAreaRhumb(Rhumb^ earth, bool polyline );
411 
412  /**
413  * Constructor for PolygonArea that assumes a WGS84 ellipsoid.
414  *
415  * @param[in] polyline if true that treat the points as defining a polyline
416  * instead of a polygon.
417  **********************************************************************/
418  PolygonAreaRhumb(const bool polyline );
419 
420  /**
421  * The destructor calls the finalizer.
422  **********************************************************************/
424  { this->!PolygonAreaRhumb(); }
425 
426  /**
427  * Clear PolygonArea, allowing a new polygon to be started.
428  **********************************************************************/
429  void Clear();
430 
431  /**
432  * Add a point to the polygon or polyline.
433  *
434  * @param[in] lat the latitude of the point (degrees).
435  * @param[in] lon the longitude of the point (degrees).
436  *
437  * \e lat should be in the range [&minus;90&deg;, 90&deg;] and \e
438  * lon should be in the range [&minus;540&deg;, 540&deg;).
439  **********************************************************************/
440  void AddPoint(double lat, double lon);
441 
442  /**
443  * Add an edge to the polygon or polyline.
444  *
445  * @param[in] azi azimuth at current point (degrees).
446  * @param[in] s distance from current point to next point (meters).
447  *
448  * \e azi should be in the range [&minus;540&deg;, 540&deg;). This does
449  * nothing if no points have been added yet. Use PolygonArea::CurrentPoint
450  * to determine the position of the new vertex.
451  **********************************************************************/
452  void AddEdge(double azi, double s);
453 
454  /**
455  * Return the results so far.
456  *
457  * @param[in] reverse if true then clockwise (instead of counter-clockwise)
458  * traversal counts as a positive area.
459  * @param[in] sign if true then return a signed result for the area if
460  * the polygon is traversed in the "wrong" direction instead of returning
461  * the area for the rest of the earth.
462  * @param[out] perimeter the perimeter of the polygon or length of the
463  * polyline (meters).
464  * @param[out] area the area of the polygon (meters<sup>2</sup>); only set
465  * if \e polyline is false in the constructor.
466  * @return the number of points.
467  **********************************************************************/
468  unsigned Compute(bool reverse, bool sign,
469  [System::Runtime::InteropServices::Out] double% perimeter,
470  [System::Runtime::InteropServices::Out] double% area);
471 
472  /**
473  * Return the results assuming a tentative final test point is added;
474  * however, the data for the test point is not saved. This lets you report
475  * a running result for the perimeter and area as the user moves the mouse
476  * cursor. Ordinary floating point arithmetic is used to accumulate the
477  * data for the test point; thus the area and perimeter returned are less
478  * accurate than if PolygonArea::AddPoint and PolygonArea::Compute are
479  * used.
480  *
481  * @param[in] lat the latitude of the test point (degrees).
482  * @param[in] lon the longitude of the test point (degrees).
483  * @param[in] reverse if true then clockwise (instead of counter-clockwise)
484  * traversal counts as a positive area.
485  * @param[in] sign if true then return a signed result for the area if
486  * the polygon is traversed in the "wrong" direction instead of returning
487  * the area for the rest of the earth.
488  * @param[out] perimeter the approximate perimeter of the polygon or length
489  * of the polyline (meters).
490  * @param[out] area the approximate area of the polygon
491  * (meters<sup>2</sup>); only set if polyline is false in the
492  * constructor.
493  * @return the number of points.
494  *
495  * \e lat should be in the range [&minus;90&deg;, 90&deg;] and \e
496  * lon should be in the range [&minus;540&deg;, 540&deg;).
497  **********************************************************************/
498  unsigned TestPoint(double lat, double lon, bool reverse, bool sign,
499  [System::Runtime::InteropServices::Out] double% perimeter,
500  [System::Runtime::InteropServices::Out] double% area);
501 
502  /**
503  * Return the results assuming a tentative final test point is added via an
504  * azimuth and distance; however, the data for the test point is not saved.
505  * This lets you report a running result for the perimeter and area as the
506  * user moves the mouse cursor. Ordinary floating point arithmetic is used
507  * to accumulate the data for the test point; thus the area and perimeter
508  * returned are less accurate than if PolygonArea::AddEdge and
509  * PolygonArea::Compute are used.
510  *
511  * @param[in] azi azimuth at current point (degrees).
512  * @param[in] s distance from current point to final test point (meters).
513  * @param[in] reverse if true then clockwise (instead of counter-clockwise)
514  * traversal counts as a positive area.
515  * @param[in] sign if true then return a signed result for the area if
516  * the polygon is traversed in the "wrong" direction instead of returning
517  * the area for the rest of the earth.
518  * @param[out] perimeter the approximate perimeter of the polygon or length
519  * of the polyline (meters).
520  * @param[out] area the approximate area of the polygon
521  * (meters<sup>2</sup>); only set if polyline is false in the
522  * constructor.
523  * @return the number of points.
524  *
525  * \e azi should be in the range [&minus;540&deg;, 540&deg;).
526  **********************************************************************/
527  unsigned TestEdge(double azi, double s, bool reverse, bool sign,
528  [System::Runtime::InteropServices::Out] double% perimeter,
529  [System::Runtime::InteropServices::Out] double% area);
530 
531  /** \name Inspector functions
532  **********************************************************************/
533  ///@{
534  /**
535  * @return \e a the equatorial radius of the ellipsoid (meters). This is
536  * the value inherited from the Geodesic object used in the constructor.
537  **********************************************************************/
538  property double MajorRadius { double get(); }
539 
540  /**
541  * @return \e f the flattening of the ellipsoid. This is the value
542  * inherited from the Geodesic object used in the constructor.
543  **********************************************************************/
544  property double Flattening { double get(); }
545 
546  /**
547  * Report the previous vertex added to the polygon or polyline.
548  *
549  * @param[out] lat the latitude of the point (degrees).
550  * @param[out] lon the longitude of the point (degrees).
551  *
552  * If no points have been added, then NaNs are returned. Otherwise, \e lon
553  * will be in the range [&minus;180&deg;, 180&deg;).
554  **********************************************************************/
555  void CurrentPoint([System::Runtime::InteropServices::Out] double% lat,
556  [System::Runtime::InteropServices::Out] double% lon);
557  ///@}
558  };
559 } // namespace NETGeographicLib
unsigned TestEdge(double azi, double s, bool reverse, bool sign, [System::Runtime::InteropServices::Out] double% perimeter, [System::Runtime::InteropServices::Out] double% area)
void AddPoint(double lat, double lon)
unsigned Compute(bool reverse, bool sign, [System::Runtime::InteropServices::Out] double% perimeter, [System::Runtime::InteropServices::Out] double% area)
void AddEdge(double azi, double s)
.NET wrapper for GeographicLib::PolygonArea and PolygonAreaExact.
Definition: PolygonArea.h:49
unsigned TestPoint(double lat, double lon, bool reverse, bool sign, [System::Runtime::InteropServices::Out] double% perimeter, [System::Runtime::InteropServices::Out] double% area)
.NET wrapper for GeographicLib::Geodesic.
Definition: Geodesic.h:170
PolygonArea(Geodesic^ earth, bool polyline)
.NET wrapper for GeographicLib::Rhumb.
Definition: Rhumb.h:65
.NET wrapper for GeographicLib::GeodesicExact.
Definition: GeodesicExact.h:86
void CurrentPoint([System::Runtime::InteropServices::Out] double% lat, [System::Runtime::InteropServices::Out] double% lon)