geographiclib 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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