geographiclib 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/AUTHORS +12 -0
  3. data/LICENSE +24 -0
  4. data/ext/geographiclib/Accumulator.cpp +23 -0
  5. data/ext/geographiclib/AlbersEqualArea.cpp +445 -0
  6. data/ext/geographiclib/AzimuthalEquidistant.cpp +41 -0
  7. data/ext/geographiclib/CassiniSoldner.cpp +89 -0
  8. data/ext/geographiclib/CircularEngine.cpp +96 -0
  9. data/ext/geographiclib/DMS.cpp +381 -0
  10. data/ext/geographiclib/Ellipsoid.cpp +125 -0
  11. data/ext/geographiclib/EllipticFunction.cpp +512 -0
  12. data/ext/geographiclib/GARS.cpp +122 -0
  13. data/ext/geographiclib/GeoCoords.cpp +175 -0
  14. data/ext/geographiclib/Geocentric.cpp +172 -0
  15. data/ext/geographiclib/Geodesic.cpp +1908 -0
  16. data/ext/geographiclib/GeodesicExact.cpp +927 -0
  17. data/ext/geographiclib/GeodesicExactC4.cpp +7879 -0
  18. data/ext/geographiclib/GeodesicLine.cpp +321 -0
  19. data/ext/geographiclib/GeodesicLineExact.cpp +289 -0
  20. data/ext/geographiclib/GeographicLib/Accumulator.hpp +184 -0
  21. data/ext/geographiclib/GeographicLib/AlbersEqualArea.hpp +312 -0
  22. data/ext/geographiclib/GeographicLib/AzimuthalEquidistant.hpp +139 -0
  23. data/ext/geographiclib/GeographicLib/CassiniSoldner.hpp +204 -0
  24. data/ext/geographiclib/GeographicLib/CircularEngine.hpp +195 -0
  25. data/ext/geographiclib/GeographicLib/Config.h +12 -0
  26. data/ext/geographiclib/GeographicLib/Constants.hpp +387 -0
  27. data/ext/geographiclib/GeographicLib/DMS.hpp +370 -0
  28. data/ext/geographiclib/GeographicLib/Ellipsoid.hpp +534 -0
  29. data/ext/geographiclib/GeographicLib/EllipticFunction.hpp +692 -0
  30. data/ext/geographiclib/GeographicLib/GARS.hpp +143 -0
  31. data/ext/geographiclib/GeographicLib/GeoCoords.hpp +544 -0
  32. data/ext/geographiclib/GeographicLib/Geocentric.hpp +267 -0
  33. data/ext/geographiclib/GeographicLib/Geodesic.hpp +970 -0
  34. data/ext/geographiclib/GeographicLib/GeodesicExact.hpp +862 -0
  35. data/ext/geographiclib/GeographicLib/GeodesicLine.hpp +701 -0
  36. data/ext/geographiclib/GeographicLib/GeodesicLineExact.hpp +667 -0
  37. data/ext/geographiclib/GeographicLib/Geohash.hpp +180 -0
  38. data/ext/geographiclib/GeographicLib/Geoid.hpp +472 -0
  39. data/ext/geographiclib/GeographicLib/Georef.hpp +160 -0
  40. data/ext/geographiclib/GeographicLib/Gnomonic.hpp +206 -0
  41. data/ext/geographiclib/GeographicLib/GravityCircle.hpp +301 -0
  42. data/ext/geographiclib/GeographicLib/GravityModel.hpp +520 -0
  43. data/ext/geographiclib/GeographicLib/LambertConformalConic.hpp +313 -0
  44. data/ext/geographiclib/GeographicLib/LocalCartesian.hpp +236 -0
  45. data/ext/geographiclib/GeographicLib/MGRS.hpp +355 -0
  46. data/ext/geographiclib/GeographicLib/MagneticCircle.hpp +178 -0
  47. data/ext/geographiclib/GeographicLib/MagneticModel.hpp +347 -0
  48. data/ext/geographiclib/GeographicLib/Math.hpp +920 -0
  49. data/ext/geographiclib/GeographicLib/NormalGravity.hpp +350 -0
  50. data/ext/geographiclib/GeographicLib/OSGB.hpp +249 -0
  51. data/ext/geographiclib/GeographicLib/PolarStereographic.hpp +150 -0
  52. data/ext/geographiclib/GeographicLib/PolygonArea.hpp +288 -0
  53. data/ext/geographiclib/GeographicLib/Rhumb.hpp +589 -0
  54. data/ext/geographiclib/GeographicLib/SphericalEngine.hpp +376 -0
  55. data/ext/geographiclib/GeographicLib/SphericalHarmonic.hpp +354 -0
  56. data/ext/geographiclib/GeographicLib/SphericalHarmonic1.hpp +281 -0
  57. data/ext/geographiclib/GeographicLib/SphericalHarmonic2.hpp +315 -0
  58. data/ext/geographiclib/GeographicLib/TransverseMercator.hpp +196 -0
  59. data/ext/geographiclib/GeographicLib/TransverseMercatorExact.hpp +254 -0
  60. data/ext/geographiclib/GeographicLib/UTMUPS.hpp +421 -0
  61. data/ext/geographiclib/GeographicLib/Utility.hpp +612 -0
  62. data/ext/geographiclib/Geohash.cpp +102 -0
  63. data/ext/geographiclib/Geoid.cpp +509 -0
  64. data/ext/geographiclib/Georef.cpp +135 -0
  65. data/ext/geographiclib/Gnomonic.cpp +85 -0
  66. data/ext/geographiclib/GravityCircle.cpp +129 -0
  67. data/ext/geographiclib/GravityModel.cpp +360 -0
  68. data/ext/geographiclib/LambertConformalConic.cpp +456 -0
  69. data/ext/geographiclib/LocalCartesian.cpp +62 -0
  70. data/ext/geographiclib/MGRS.cpp +461 -0
  71. data/ext/geographiclib/MagneticCircle.cpp +52 -0
  72. data/ext/geographiclib/MagneticModel.cpp +269 -0
  73. data/ext/geographiclib/Math.cpp +63 -0
  74. data/ext/geographiclib/NormalGravity.cpp +262 -0
  75. data/ext/geographiclib/OSGB.cpp +167 -0
  76. data/ext/geographiclib/PolarStereographic.cpp +108 -0
  77. data/ext/geographiclib/PolygonArea.cpp +204 -0
  78. data/ext/geographiclib/Rhumb.cpp +383 -0
  79. data/ext/geographiclib/SphericalEngine.cpp +477 -0
  80. data/ext/geographiclib/TransverseMercator.cpp +603 -0
  81. data/ext/geographiclib/TransverseMercatorExact.cpp +464 -0
  82. data/ext/geographiclib/UTMUPS.cpp +296 -0
  83. data/ext/geographiclib/Utility.cpp +61 -0
  84. data/ext/geographiclib/extconf.rb +3 -0
  85. data/ext/geographiclib/geographiclib.cpp +62 -0
  86. data/lib/geographiclib.rb +20 -0
  87. metadata +140 -0
@@ -0,0 +1,167 @@
1
+ /**
2
+ * \file OSGB.cpp
3
+ * \brief Implementation for GeographicLib::OSGB class
4
+ *
5
+ * Copyright (c) Charles Karney (2010-2014) <charles@karney.com> and licensed
6
+ * under the MIT/X11 License. For more information, see
7
+ * http://geographiclib.sourceforge.net/
8
+ **********************************************************************/
9
+
10
+ #include <GeographicLib/OSGB.hpp>
11
+ #include <GeographicLib/Utility.hpp>
12
+
13
+ namespace GeographicLib {
14
+
15
+ using namespace std;
16
+
17
+ const string OSGB::letters_ = "ABCDEFGHJKLMNOPQRSTUVWXYZ";
18
+ const string OSGB::digits_ = "0123456789";
19
+
20
+ const TransverseMercator& OSGB::OSGBTM() {
21
+ static const TransverseMercator osgbtm(MajorRadius(), Flattening(),
22
+ CentralScale());
23
+ return osgbtm;
24
+ }
25
+
26
+ Math::real OSGB::computenorthoffset() {
27
+ real x, y;
28
+ static const real northoffset =
29
+ ( OSGBTM().Forward(real(0), OriginLatitude(), real(0), x, y),
30
+ FalseNorthing() - y );
31
+ return northoffset;
32
+ }
33
+
34
+ void OSGB::GridReference(real x, real y, int prec, std::string& gridref) {
35
+ CheckCoords(x, y);
36
+ if (!(prec >= 0 && prec <= maxprec_))
37
+ throw GeographicErr("OSGB precision " + Utility::str(prec)
38
+ + " not in [0, "
39
+ + Utility::str(int(maxprec_)) + "]");
40
+ if (Math::isnan(x) || Math::isnan(y)) {
41
+ gridref = "INVALID";
42
+ return;
43
+ }
44
+ char grid[2 + 2 * maxprec_];
45
+ int
46
+ xh = int(floor(x / tile_)),
47
+ yh = int(floor(y / tile_));
48
+ real
49
+ xf = x - tile_ * xh,
50
+ yf = y - tile_ * yh;
51
+ xh += tileoffx_;
52
+ yh += tileoffy_;
53
+ int z = 0;
54
+ grid[z++] = letters_[(tilegrid_ - (yh / tilegrid_) - 1)
55
+ * tilegrid_ + (xh / tilegrid_)];
56
+ grid[z++] = letters_[(tilegrid_ - (yh % tilegrid_) - 1)
57
+ * tilegrid_ + (xh % tilegrid_)];
58
+ real mult = pow(real(base_), max(tilelevel_ - prec, 0));
59
+ int
60
+ ix = int(floor(xf / mult)),
61
+ iy = int(floor(yf / mult));
62
+ for (int c = min(prec, int(tilelevel_)); c--;) {
63
+ grid[z + c] = digits_[ ix % base_ ];
64
+ ix /= base_;
65
+ grid[z + c + prec] = digits_[ iy % base_ ];
66
+ iy /= base_;
67
+ }
68
+ if (prec > tilelevel_) {
69
+ xf -= floor(xf / mult);
70
+ yf -= floor(yf / mult);
71
+ mult = pow(real(base_), prec - tilelevel_);
72
+ ix = int(floor(xf * mult));
73
+ iy = int(floor(yf * mult));
74
+ for (int c = prec - tilelevel_; c--;) {
75
+ grid[z + c + tilelevel_] = digits_[ ix % base_ ];
76
+ ix /= base_;
77
+ grid[z + c + tilelevel_ + prec] = digits_[ iy % base_ ];
78
+ iy /= base_;
79
+ }
80
+ }
81
+ int mlen = z + 2 * prec;
82
+ gridref.resize(mlen);
83
+ copy(grid, grid + mlen, gridref.begin());
84
+ }
85
+
86
+ void OSGB::GridReference(const std::string& gridref,
87
+ real& x, real& y, int& prec,
88
+ bool centerp) {
89
+ int
90
+ len = int(gridref.size()),
91
+ p = 0;
92
+ if (len >= 2 &&
93
+ toupper(gridref[0]) == 'I' &&
94
+ toupper(gridref[1]) == 'N') {
95
+ x = y = Math::NaN();
96
+ prec = -2; // For compatibility with MGRS::Reverse.
97
+ return;
98
+ }
99
+ char grid[2 + 2 * maxprec_];
100
+ for (int i = 0; i < len; ++i) {
101
+ if (!isspace(gridref[i])) {
102
+ if (p >= 2 + 2 * maxprec_)
103
+ throw GeographicErr("OSGB string " + gridref + " too long");
104
+ grid[p++] = gridref[i];
105
+ }
106
+ }
107
+ len = p;
108
+ p = 0;
109
+ if (len < 2)
110
+ throw GeographicErr("OSGB string " + gridref + " too short");
111
+ if (len % 2)
112
+ throw GeographicErr("OSGB string " + gridref +
113
+ " has odd number of characters");
114
+ int
115
+ xh = 0,
116
+ yh = 0;
117
+ while (p < 2) {
118
+ int i = Utility::lookup(letters_, grid[p++]);
119
+ if (i < 0)
120
+ throw GeographicErr("Illegal prefix character " + gridref);
121
+ yh = yh * tilegrid_ + tilegrid_ - (i / tilegrid_) - 1;
122
+ xh = xh * tilegrid_ + (i % tilegrid_);
123
+ }
124
+ xh -= tileoffx_;
125
+ yh -= tileoffy_;
126
+
127
+ int prec1 = (len - p)/2;
128
+ real
129
+ unit = tile_,
130
+ x1 = unit * xh,
131
+ y1 = unit * yh;
132
+ for (int i = 0; i < prec1; ++i) {
133
+ unit /= base_;
134
+ int
135
+ ix = Utility::lookup(digits_, grid[p + i]),
136
+ iy = Utility::lookup(digits_, grid[p + i + prec1]);
137
+ if (ix < 0 || iy < 0)
138
+ throw GeographicErr("Encountered a non-digit in " + gridref);
139
+ x1 += unit * ix;
140
+ y1 += unit * iy;
141
+ }
142
+ if (centerp) {
143
+ x1 += unit/2;
144
+ y1 += unit/2;
145
+ }
146
+ x = x1;
147
+ y = y1;
148
+ prec = prec1;
149
+ }
150
+
151
+ void OSGB::CheckCoords(real x, real y) {
152
+ // Limits are all multiples of 100km and are all closed on the lower end
153
+ // and open on the upper end -- and this is reflected in the error
154
+ // messages. NaNs are let through.
155
+ if (x < minx_ || x >= maxx_)
156
+ throw GeographicErr("Easting " + Utility::str(int(floor(x/1000)))
157
+ + "km not in OSGB range ["
158
+ + Utility::str(minx_/1000) + "km, "
159
+ + Utility::str(maxx_/1000) + "km)");
160
+ if (y < miny_ || y >= maxy_)
161
+ throw GeographicErr("Northing " + Utility::str(int(floor(y/1000)))
162
+ + "km not in OSGB range ["
163
+ + Utility::str(miny_/1000) + "km, "
164
+ + Utility::str(maxy_/1000) + "km)");
165
+ }
166
+
167
+ } // namespace GeographicLib
@@ -0,0 +1,108 @@
1
+ /**
2
+ * \file PolarStereographic.cpp
3
+ * \brief Implementation for GeographicLib::PolarStereographic class
4
+ *
5
+ * Copyright (c) Charles Karney (2008-2015) <charles@karney.com> and licensed
6
+ * under the MIT/X11 License. For more information, see
7
+ * http://geographiclib.sourceforge.net/
8
+ **********************************************************************/
9
+
10
+ #include <GeographicLib/PolarStereographic.hpp>
11
+
12
+ namespace GeographicLib {
13
+
14
+ using namespace std;
15
+
16
+ PolarStereographic::PolarStereographic(real a, real f, real k0)
17
+ : _a(a)
18
+ , _f(f)
19
+ , _e2(_f * (2 - _f))
20
+ , _es((_f < 0 ? -1 : 1) * sqrt(abs(_e2)))
21
+ , _e2m(1 - _e2)
22
+ , _c( (1 - _f) * exp(Math::eatanhe(real(1), _es)) )
23
+ , _k0(k0)
24
+ {
25
+ if (!(Math::isfinite(_a) && _a > 0))
26
+ throw GeographicErr("Major radius is not positive");
27
+ if (!(Math::isfinite(_f) && _f < 1))
28
+ throw GeographicErr("Minor radius is not positive");
29
+ if (!(Math::isfinite(_k0) && _k0 > 0))
30
+ throw GeographicErr("Scale is not positive");
31
+ }
32
+
33
+ const PolarStereographic& PolarStereographic::UPS() {
34
+ static const PolarStereographic ups(Constants::WGS84_a(),
35
+ Constants::WGS84_f(),
36
+ Constants::UPS_k0());
37
+ return ups;
38
+ }
39
+
40
+ // This formulation converts to conformal coordinates by tau = tan(phi) and
41
+ // tau' = tan(phi') where phi' is the conformal latitude. The formulas are:
42
+ // tau = tan(phi)
43
+ // secphi = hypot(1, tau)
44
+ // sig = sinh(e * atanh(e * tau / secphi))
45
+ // taup = tan(phip) = tau * hypot(1, sig) - sig * hypot(1, tau)
46
+ // c = (1 - f) * exp(e * atanh(e))
47
+ //
48
+ // Forward:
49
+ // rho = (2*k0*a/c) / (hypot(1, taup) + taup) (taup >= 0)
50
+ // = (2*k0*a/c) * (hypot(1, taup) - taup) (taup < 0)
51
+ //
52
+ // Reverse:
53
+ // taup = ((2*k0*a/c) / rho - rho / (2*k0*a/c))/2
54
+ //
55
+ // Scale:
56
+ // k = (rho/a) * secphi * sqrt((1-e2) + e2 / secphi^2)
57
+ //
58
+ // In limit rho -> 0, tau -> inf, taup -> inf, secphi -> inf, secphip -> inf
59
+ // secphip = taup = exp(-e * atanh(e)) * tau = exp(-e * atanh(e)) * secphi
60
+
61
+ void PolarStereographic::Forward(bool northp, real lat, real lon,
62
+ real& x, real& y, real& gamma, real& k)
63
+ const {
64
+ lat = Math::LatFix(lat);
65
+ lat *= northp ? 1 : -1;
66
+ real
67
+ tau = Math::tand(lat),
68
+ secphi = Math::hypot(real(1), tau),
69
+ taup = Math::taupf(tau, _es),
70
+ rho = Math::hypot(real(1), taup) + abs(taup);
71
+ rho = taup >= 0 ? (lat != 90 ? 1/rho : 0) : rho;
72
+ rho *= 2 * _k0 * _a / _c;
73
+ k = lat != 90 ? (rho / _a) * secphi * sqrt(_e2m + _e2 / Math::sq(secphi)) :
74
+ _k0;
75
+ Math::sincosd(lon, x, y);
76
+ x *= rho;
77
+ y *= (northp ? -rho : rho);
78
+ gamma = Math::AngNormalize(northp ? lon : -lon);
79
+ }
80
+
81
+ void PolarStereographic::Reverse(bool northp, real x, real y,
82
+ real& lat, real& lon, real& gamma, real& k)
83
+ const {
84
+ real
85
+ rho = Math::hypot(x, y),
86
+ t = rho ? rho / (2 * _k0 * _a / _c) :
87
+ Math::sq(numeric_limits<real>::epsilon()),
88
+ taup = (1 / t - t) / 2,
89
+ tau = Math::tauf(taup, _es),
90
+ secphi = Math::hypot(real(1), tau);
91
+ k = rho ? (rho / _a) * secphi * sqrt(_e2m + _e2 / Math::sq(secphi)) : _k0;
92
+ lat = (northp ? 1 : -1) * Math::atand(tau);
93
+ lon = Math::atan2d(x, northp ? -y : y );
94
+ gamma = Math::AngNormalize(northp ? lon : -lon);
95
+ }
96
+
97
+ void PolarStereographic::SetScale(real lat, real k) {
98
+ if (!(Math::isfinite(k) && k > 0))
99
+ throw GeographicErr("Scale is not positive");
100
+ if (!(-90 < lat && lat <= 90))
101
+ throw GeographicErr("Latitude must be in (-90d, 90d]");
102
+ real x, y, gamma, kold;
103
+ _k0 = 1;
104
+ Forward(true, lat, 0, x, y, gamma, kold);
105
+ _k0 *= k/kold;
106
+ }
107
+
108
+ } // namespace GeographicLib
@@ -0,0 +1,204 @@
1
+ /**
2
+ * \file PolygonArea.cpp
3
+ * \brief Implementation for GeographicLib::PolygonAreaT class
4
+ *
5
+ * Copyright (c) Charles Karney (2010-2015) <charles@karney.com> and licensed
6
+ * under the MIT/X11 License. For more information, see
7
+ * http://geographiclib.sourceforge.net/
8
+ **********************************************************************/
9
+
10
+ #include <GeographicLib/PolygonArea.hpp>
11
+
12
+ namespace GeographicLib {
13
+
14
+ using namespace std;
15
+
16
+ template <class GeodType>
17
+ void PolygonAreaT<GeodType>::AddPoint(real lat, real lon) {
18
+ lat = Math::LatFix(lat);
19
+ lon = Math::AngNormalize(lon);
20
+ if (_num == 0) {
21
+ _lat0 = _lat1 = lat;
22
+ _lon0 = _lon1 = lon;
23
+ } else {
24
+ real s12, S12, t;
25
+ _earth.GenInverse(_lat1, _lon1, lat, lon, _mask, s12, t, t, t, t, t, S12);
26
+ _perimetersum += s12;
27
+ if (!_polyline) {
28
+ _areasum += S12;
29
+ _crossings += transit(_lon1, lon);
30
+ }
31
+ _lat1 = lat; _lon1 = lon;
32
+ }
33
+ ++_num;
34
+ }
35
+
36
+ template <class GeodType>
37
+ void PolygonAreaT<GeodType>::AddEdge(real azi, real s) {
38
+ if (_num) { // Do nothing if _num is zero
39
+ real lat, lon, S12, t;
40
+ _earth.GenDirect(_lat1, _lon1, azi, false, s, _mask,
41
+ lat, lon, t, t, t, t, t, S12);
42
+ _perimetersum += s;
43
+ if (!_polyline) {
44
+ _areasum += S12;
45
+ _crossings += transitdirect(_lon1, lon);
46
+ lon = Math::AngNormalize(lon);
47
+ }
48
+ _lat1 = lat; _lon1 = lon;
49
+ ++_num;
50
+ }
51
+ }
52
+
53
+ template <class GeodType>
54
+ unsigned PolygonAreaT<GeodType>::Compute(bool reverse, bool sign,
55
+ real& perimeter, real& area) const {
56
+ real s12, S12, t;
57
+ if (_num < 2) {
58
+ perimeter = 0;
59
+ if (!_polyline)
60
+ area = 0;
61
+ return _num;
62
+ }
63
+ if (_polyline) {
64
+ perimeter = _perimetersum();
65
+ return _num;
66
+ }
67
+ _earth.GenInverse(_lat1, _lon1, _lat0, _lon0, _mask,
68
+ s12, t, t, t, t, t, S12);
69
+ perimeter = _perimetersum(s12);
70
+ Accumulator<> tempsum(_areasum);
71
+ tempsum += S12;
72
+ int crossings = _crossings + transit(_lon1, _lon0);
73
+ if (crossings & 1)
74
+ tempsum += (tempsum < 0 ? 1 : -1) * _area0/2;
75
+ // area is with the clockwise sense. If !reverse convert to
76
+ // counter-clockwise convention.
77
+ if (!reverse)
78
+ tempsum *= -1;
79
+ // If sign put area in (-area0/2, area0/2], else put area in [0, area0)
80
+ if (sign) {
81
+ if (tempsum > _area0/2)
82
+ tempsum -= _area0;
83
+ else if (tempsum <= -_area0/2)
84
+ tempsum += _area0;
85
+ } else {
86
+ if (tempsum >= _area0)
87
+ tempsum -= _area0;
88
+ else if (tempsum < 0)
89
+ tempsum += _area0;
90
+ }
91
+ area = 0 + tempsum();
92
+ return _num;
93
+ }
94
+
95
+ template <class GeodType>
96
+ unsigned PolygonAreaT<GeodType>::TestPoint(real lat, real lon,
97
+ bool reverse, bool sign,
98
+ real& perimeter, real& area) const
99
+ {
100
+ if (_num == 0) {
101
+ perimeter = 0;
102
+ if (!_polyline)
103
+ area = 0;
104
+ return 1;
105
+ }
106
+ perimeter = _perimetersum();
107
+ real tempsum = _polyline ? 0 : _areasum();
108
+ int crossings = _crossings;
109
+ unsigned num = _num + 1;
110
+ for (int i = 0; i < (_polyline ? 1 : 2); ++i) {
111
+ real s12, S12, t;
112
+ _earth.GenInverse(i == 0 ? _lat1 : lat, i == 0 ? _lon1 : lon,
113
+ i != 0 ? _lat0 : lat, i != 0 ? _lon0 : lon,
114
+ _mask, s12, t, t, t, t, t, S12);
115
+ perimeter += s12;
116
+ if (!_polyline) {
117
+ tempsum += S12;
118
+ crossings += transit(i == 0 ? _lon1 : lon,
119
+ i != 0 ? _lon0 : lon);
120
+ }
121
+ }
122
+
123
+ if (_polyline)
124
+ return num;
125
+
126
+ if (crossings & 1)
127
+ tempsum += (tempsum < 0 ? 1 : -1) * _area0/2;
128
+ // area is with the clockwise sense. If !reverse convert to
129
+ // counter-clockwise convention.
130
+ if (!reverse)
131
+ tempsum *= -1;
132
+ // If sign put area in (-area0/2, area0/2], else put area in [0, area0)
133
+ if (sign) {
134
+ if (tempsum > _area0/2)
135
+ tempsum -= _area0;
136
+ else if (tempsum <= -_area0/2)
137
+ tempsum += _area0;
138
+ } else {
139
+ if (tempsum >= _area0)
140
+ tempsum -= _area0;
141
+ else if (tempsum < 0)
142
+ tempsum += _area0;
143
+ }
144
+ area = 0 + tempsum;
145
+ return num;
146
+ }
147
+
148
+ template <class GeodType>
149
+ unsigned PolygonAreaT<GeodType>::TestEdge(real azi, real s,
150
+ bool reverse, bool sign,
151
+ real& perimeter, real& area) const {
152
+ if (_num == 0) { // we don't have a starting point!
153
+ perimeter = Math::NaN();
154
+ if (!_polyline)
155
+ area = Math::NaN();
156
+ return 0;
157
+ }
158
+ unsigned num = _num + 1;
159
+ perimeter = _perimetersum() + s;
160
+ if (_polyline)
161
+ return num;
162
+
163
+ real tempsum = _areasum();
164
+ int crossings = _crossings;
165
+ {
166
+ real lat, lon, s12, S12, t;
167
+ _earth.GenDirect(_lat1, _lon1, azi, false, s, _mask,
168
+ lat, lon, t, t, t, t, t, S12);
169
+ tempsum += S12;
170
+ crossings += transitdirect(_lon1, lon);
171
+ lon = Math::AngNormalize(lon);
172
+ _earth.GenInverse(lat, lon, _lat0, _lon0, _mask, s12, t, t, t, t, t, S12);
173
+ perimeter += s12;
174
+ tempsum += S12;
175
+ crossings += transit(lon, _lon0);
176
+ }
177
+
178
+ if (crossings & 1)
179
+ tempsum += (tempsum < 0 ? 1 : -1) * _area0/2;
180
+ // area is with the clockwise sense. If !reverse convert to
181
+ // counter-clockwise convention.
182
+ if (!reverse)
183
+ tempsum *= -1;
184
+ // If sign put area in (-area0/2, area0/2], else put area in [0, area0)
185
+ if (sign) {
186
+ if (tempsum > _area0/2)
187
+ tempsum -= _area0;
188
+ else if (tempsum <= -_area0/2)
189
+ tempsum += _area0;
190
+ } else {
191
+ if (tempsum >= _area0)
192
+ tempsum -= _area0;
193
+ else if (tempsum < 0)
194
+ tempsum += _area0;
195
+ }
196
+ area = 0 + tempsum;
197
+ return num;
198
+ }
199
+
200
+ template class GEOGRAPHICLIB_EXPORT PolygonAreaT<Geodesic>;
201
+ template class GEOGRAPHICLIB_EXPORT PolygonAreaT<GeodesicExact>;
202
+ template class GEOGRAPHICLIB_EXPORT PolygonAreaT<Rhumb>;
203
+
204
+ } // namespace GeographicLib