GeographicLib
2.7
Toggle main menu visibility
Loading...
Searching...
No Matches
OSGB.cpp
Go to the documentation of this file.
1
/**
2
* \file OSGB.cpp
3
* \brief Implementation for GeographicLib::OSGB class
4
*
5
* Copyright (c) Charles Karney (2010-2020) <karney@alum.mit.edu> and licensed
6
* under the MIT/X11 License. For more information, see
7
* https://geographiclib.sourceforge.io/
8
**********************************************************************/
9
10
#include <
GeographicLib/OSGB.hpp
>
11
#include <
GeographicLib/Utility.hpp
>
12
13
namespace
GeographicLib
{
14
15
using namespace
std;
16
17
const
char
*
const
OSGB::letters_ =
"ABCDEFGHJKLMNOPQRSTUVWXYZ"
;
18
const
char
*
const
OSGB::digits_ =
"0123456789"
;
19
20
const
TransverseMercator
& OSGB::OSGBTM() {
21
static
const
TransverseMercator osgbtm(
EquatorialRadius
(),
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
(isnan(x) || 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
// Need extra real because, since C++11, pow(float, int) returns double
59
real mult =
real
(pow(
real
(base_), max(tilelevel_ - prec, 0)));
60
int
61
ix = int(floor(xf / mult)),
62
iy = int(floor(yf / mult));
63
for
(
int
c = min(prec,
int
(tilelevel_)); c--;) {
64
grid[z + c] = digits_[ ix % base_ ];
65
ix /= base_;
66
grid[z + c + prec] = digits_[ iy % base_ ];
67
iy /= base_;
68
}
69
if
(prec > tilelevel_) {
70
xf -= floor(xf / mult);
71
yf -= floor(yf / mult);
72
mult =
real
(pow(
real
(base_), prec - tilelevel_));
73
ix = int(floor(xf * mult));
74
iy = int(floor(yf * mult));
75
for
(
int
c = prec - tilelevel_; c--;) {
76
grid[z + c + tilelevel_] = digits_[ ix % base_ ];
77
ix /= base_;
78
grid[z + c + tilelevel_ + prec] = digits_[ iy % base_ ];
79
iy /= base_;
80
}
81
}
82
int
mlen = z + 2 * prec;
83
gridref.resize(mlen);
84
copy(grid, grid + mlen, gridref.begin());
85
}
86
87
void
OSGB::GridReference
(
const
std::string& gridref,
88
real& x, real& y,
int
& prec,
89
bool
centerp) {
90
int
91
len = int(gridref.size()),
92
p = 0;
93
if
(len >= 2 &&
94
toupper(gridref[0]) ==
'I'
&&
95
toupper(gridref[1]) ==
'N'
) {
96
x = y =
Math::NaN
();
97
prec = -2;
// For compatibility with MGRS::Reverse.
98
return
;
99
}
100
char
grid[2 + 2 * maxprec_];
101
for
(
int
i = 0; i < len; ++i) {
102
if
(!isspace(gridref[i])) {
103
if
(p >= 2 + 2 * maxprec_)
104
throw
GeographicErr
(
"OSGB string "
+ gridref +
" too long"
);
105
grid[p++] = gridref[i];
106
}
107
}
108
len = p;
109
p = 0;
110
if
(len < 2)
111
throw
GeographicErr
(
"OSGB string "
+ gridref +
" too short"
);
112
if
(len % 2)
113
throw
GeographicErr
(
"OSGB string "
+ gridref +
114
" has odd number of characters"
);
115
int
116
xh = 0,
117
yh = 0;
118
while
(p < 2) {
119
int
i =
Utility::lookup
(letters_, grid[p++]);
120
if
(i < 0)
121
throw
GeographicErr
(
"Illegal prefix character "
+ gridref);
122
yh = yh * tilegrid_ + tilegrid_ - (i / tilegrid_) - 1;
123
xh = xh * tilegrid_ + (i % tilegrid_);
124
}
125
xh -= tileoffx_;
126
yh -= tileoffy_;
127
128
int
prec1 = (len - p)/2;
129
real
130
unit = tile_,
131
x1 = unit * xh,
132
y1 = unit * yh;
133
for
(
int
i = 0; i < prec1; ++i) {
134
unit /= base_;
135
int
136
ix =
Utility::lookup
(digits_, grid[p + i]),
137
iy =
Utility::lookup
(digits_, grid[p + i + prec1]);
138
if
(ix < 0 || iy < 0)
139
throw
GeographicErr
(
"Encountered a non-digit in "
+ gridref);
140
x1 += unit * ix;
141
y1 += unit * iy;
142
}
143
if
(centerp) {
144
x1 += unit/2;
145
y1 += unit/2;
146
}
147
x = x1;
148
y = y1;
149
prec = prec1;
150
}
151
152
void
OSGB::CheckCoords(
real
x,
real
y) {
153
// Limits are all multiples of 100km and are all closed on the lower end
154
// and open on the upper end -- and this is reflected in the error
155
// messages. NaNs are let through.
156
if
(x < minx_ || x >= maxx_)
157
throw
GeographicErr
(
"Easting "
+
Utility::str
(
int
(floor(x/1000)))
158
+
"km not in OSGB range ["
159
+
Utility::str
(minx_/1000) +
"km, "
160
+
Utility::str
(maxx_/1000) +
"km)"
);
161
if
(y < miny_ || y >= maxy_)
162
throw
GeographicErr
(
"Northing "
+
Utility::str
(
int
(floor(y/1000)))
163
+
"km not in OSGB range ["
164
+
Utility::str
(miny_/1000) +
"km, "
165
+
Utility::str
(maxy_/1000) +
"km)"
);
166
}
167
168
}
// namespace GeographicLib
real
GeographicLib::Math::real real
Definition
Geod3Solve.cpp:25
OSGB.hpp
Header for GeographicLib::OSGB class.
Utility.hpp
Header for GeographicLib::Utility class.
GeographicLib::GeographicErr
Exception handling for GeographicLib.
Definition
Constants.hpp:344
GeographicLib::Math::NaN
static T NaN()
Definition
Math.cpp:301
GeographicLib::Math::real
double real
Definition
Math.hpp:115
GeographicLib::OSGB::GridReference
static void GridReference(real x, real y, int prec, std::string &gridref)
Definition
OSGB.cpp:34
GeographicLib::OSGB::CentralScale
static Math::real CentralScale()
Definition
OSGB.hpp:206
GeographicLib::OSGB::EquatorialRadius
static Math::real EquatorialRadius()
Definition
OSGB.hpp:182
GeographicLib::OSGB::FalseNorthing
static Math::real FalseNorthing()
Definition
OSGB.hpp:225
GeographicLib::OSGB::Flattening
static Math::real Flattening()
Definition
OSGB.hpp:197
GeographicLib::OSGB::OriginLatitude
static Math::real OriginLatitude()
Definition
OSGB.hpp:214
GeographicLib::TransverseMercator
Transverse Mercator projection.
Definition
TransverseMercator.hpp:94
GeographicLib::Utility::lookup
static int lookup(const std::string &s, char c)
Definition
Utility.cpp:160
GeographicLib::Utility::str
static std::string str(T x, int p=-1)
Definition
Utility.hpp:161
GeographicLib
Namespace for GeographicLib.
Definition
Accumulator.cpp:12
src
OSGB.cpp
Generated by
1.17.0