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.
- checksums.yaml +7 -0
- data/AUTHORS +12 -0
- data/LICENSE +24 -0
- data/ext/geographiclib/Accumulator.cpp +23 -0
- data/ext/geographiclib/AlbersEqualArea.cpp +445 -0
- data/ext/geographiclib/AzimuthalEquidistant.cpp +41 -0
- data/ext/geographiclib/CassiniSoldner.cpp +89 -0
- data/ext/geographiclib/CircularEngine.cpp +96 -0
- data/ext/geographiclib/DMS.cpp +381 -0
- data/ext/geographiclib/Ellipsoid.cpp +125 -0
- data/ext/geographiclib/EllipticFunction.cpp +512 -0
- data/ext/geographiclib/GARS.cpp +122 -0
- data/ext/geographiclib/GeoCoords.cpp +175 -0
- data/ext/geographiclib/Geocentric.cpp +172 -0
- data/ext/geographiclib/Geodesic.cpp +1908 -0
- data/ext/geographiclib/GeodesicExact.cpp +927 -0
- data/ext/geographiclib/GeodesicExactC4.cpp +7879 -0
- data/ext/geographiclib/GeodesicLine.cpp +321 -0
- data/ext/geographiclib/GeodesicLineExact.cpp +289 -0
- data/ext/geographiclib/GeographicLib/Accumulator.hpp +184 -0
- data/ext/geographiclib/GeographicLib/AlbersEqualArea.hpp +312 -0
- data/ext/geographiclib/GeographicLib/AzimuthalEquidistant.hpp +139 -0
- data/ext/geographiclib/GeographicLib/CassiniSoldner.hpp +204 -0
- data/ext/geographiclib/GeographicLib/CircularEngine.hpp +195 -0
- data/ext/geographiclib/GeographicLib/Config.h +12 -0
- data/ext/geographiclib/GeographicLib/Constants.hpp +387 -0
- data/ext/geographiclib/GeographicLib/DMS.hpp +370 -0
- data/ext/geographiclib/GeographicLib/Ellipsoid.hpp +534 -0
- data/ext/geographiclib/GeographicLib/EllipticFunction.hpp +692 -0
- data/ext/geographiclib/GeographicLib/GARS.hpp +143 -0
- data/ext/geographiclib/GeographicLib/GeoCoords.hpp +544 -0
- data/ext/geographiclib/GeographicLib/Geocentric.hpp +267 -0
- data/ext/geographiclib/GeographicLib/Geodesic.hpp +970 -0
- data/ext/geographiclib/GeographicLib/GeodesicExact.hpp +862 -0
- data/ext/geographiclib/GeographicLib/GeodesicLine.hpp +701 -0
- data/ext/geographiclib/GeographicLib/GeodesicLineExact.hpp +667 -0
- data/ext/geographiclib/GeographicLib/Geohash.hpp +180 -0
- data/ext/geographiclib/GeographicLib/Geoid.hpp +472 -0
- data/ext/geographiclib/GeographicLib/Georef.hpp +160 -0
- data/ext/geographiclib/GeographicLib/Gnomonic.hpp +206 -0
- data/ext/geographiclib/GeographicLib/GravityCircle.hpp +301 -0
- data/ext/geographiclib/GeographicLib/GravityModel.hpp +520 -0
- data/ext/geographiclib/GeographicLib/LambertConformalConic.hpp +313 -0
- data/ext/geographiclib/GeographicLib/LocalCartesian.hpp +236 -0
- data/ext/geographiclib/GeographicLib/MGRS.hpp +355 -0
- data/ext/geographiclib/GeographicLib/MagneticCircle.hpp +178 -0
- data/ext/geographiclib/GeographicLib/MagneticModel.hpp +347 -0
- data/ext/geographiclib/GeographicLib/Math.hpp +920 -0
- data/ext/geographiclib/GeographicLib/NormalGravity.hpp +350 -0
- data/ext/geographiclib/GeographicLib/OSGB.hpp +249 -0
- data/ext/geographiclib/GeographicLib/PolarStereographic.hpp +150 -0
- data/ext/geographiclib/GeographicLib/PolygonArea.hpp +288 -0
- data/ext/geographiclib/GeographicLib/Rhumb.hpp +589 -0
- data/ext/geographiclib/GeographicLib/SphericalEngine.hpp +376 -0
- data/ext/geographiclib/GeographicLib/SphericalHarmonic.hpp +354 -0
- data/ext/geographiclib/GeographicLib/SphericalHarmonic1.hpp +281 -0
- data/ext/geographiclib/GeographicLib/SphericalHarmonic2.hpp +315 -0
- data/ext/geographiclib/GeographicLib/TransverseMercator.hpp +196 -0
- data/ext/geographiclib/GeographicLib/TransverseMercatorExact.hpp +254 -0
- data/ext/geographiclib/GeographicLib/UTMUPS.hpp +421 -0
- data/ext/geographiclib/GeographicLib/Utility.hpp +612 -0
- data/ext/geographiclib/Geohash.cpp +102 -0
- data/ext/geographiclib/Geoid.cpp +509 -0
- data/ext/geographiclib/Georef.cpp +135 -0
- data/ext/geographiclib/Gnomonic.cpp +85 -0
- data/ext/geographiclib/GravityCircle.cpp +129 -0
- data/ext/geographiclib/GravityModel.cpp +360 -0
- data/ext/geographiclib/LambertConformalConic.cpp +456 -0
- data/ext/geographiclib/LocalCartesian.cpp +62 -0
- data/ext/geographiclib/MGRS.cpp +461 -0
- data/ext/geographiclib/MagneticCircle.cpp +52 -0
- data/ext/geographiclib/MagneticModel.cpp +269 -0
- data/ext/geographiclib/Math.cpp +63 -0
- data/ext/geographiclib/NormalGravity.cpp +262 -0
- data/ext/geographiclib/OSGB.cpp +167 -0
- data/ext/geographiclib/PolarStereographic.cpp +108 -0
- data/ext/geographiclib/PolygonArea.cpp +204 -0
- data/ext/geographiclib/Rhumb.cpp +383 -0
- data/ext/geographiclib/SphericalEngine.cpp +477 -0
- data/ext/geographiclib/TransverseMercator.cpp +603 -0
- data/ext/geographiclib/TransverseMercatorExact.cpp +464 -0
- data/ext/geographiclib/UTMUPS.cpp +296 -0
- data/ext/geographiclib/Utility.cpp +61 -0
- data/ext/geographiclib/extconf.rb +3 -0
- data/ext/geographiclib/geographiclib.cpp +62 -0
- data/lib/geographiclib.rb +20 -0
- 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
|