geographiclib 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|