17#if !defined(GEOGRAPHICLIB_DATA)
19# define GEOGRAPHICLIB_DATA "C:/ProgramData/GeographicLib"
21# define GEOGRAPHICLIB_DATA "/usr/local/share/GeographicLib"
25#if !defined(GEOGRAPHICLIB_GRAVITY_DEFAULT_NAME)
26# define GEOGRAPHICLIB_GRAVITY_DEFAULT_NAME "egm96"
31# pragma warning (disable: 4996)
38 GravityModel::GravityModel(
const std::string& name,
const std::string& path,
42 , _description(
"NONE")
44 , _amodel(
Math::NaN())
45 , _gGMmodel(
Math::NaN())
54 bool truncate = Nmax >= 0 || Mmax >= 0;
56 if (Nmax >= 0 && Mmax < 0) Mmax = Nmax;
57 if (Nmax < 0) Nmax = numeric_limits<int>::max();
58 if (Mmax < 0) Mmax = numeric_limits<int>::max();
62 string coeff = _filename +
".cof";
63 ifstream coeffstr(coeff.c_str(), ios::binary);
66 char id[idlength_ + 1];
67 coeffstr.read(
id, idlength_);
71 if (_id !=
string(
id))
74 if (truncate) { N = Nmax; M = Mmax; }
76 if (!(N >= 0 && M >= 0))
82 if (truncate) { N = Nmax; M = Mmax; }
86 _cCC.resize(1, real(0));
88 _cCC[0] += _zeta0 / _corrmult;
90 int pos = int(coeffstr.tellg());
91 coeffstr.seekg(0, ios::end);
92 if (pos != coeffstr.tellg())
100 real mult = _earth._gGM / _gGMmodel;
101 real amult =
Math::sq(_earth._a / _amodel);
105 _zonal.clear(); _zonal.push_back(1);
106 _dzonal0 = (_earth.
MassConstant() - _gGMmodel) / _gGMmodel;
107 for (
int n = 2; n <= nmx; n += 2) {
116 s = - mult * _earth.Jn(n) / sqrt(real(2 * n + 1)),
123 int nmx1 = int(_zonal.size()) - 1;
134 void GravityModel::ReadMetadata(
const string& name) {
135 const char* spaces =
" \t\n\v\f\r";
136 _filename = _dir +
"/" + name +
".egm";
137 ifstream metastr(_filename.c_str());
141 getline(metastr, line);
142 if (!(line.size() >= 6 && line.substr(0,5) ==
"EGMF-"))
143 throw GeographicErr(_filename +
" does not contain EGMF-n signature");
144 string::size_type n = line.find_first_of(spaces, 5);
145 if (n != string::npos)
147 string version(line, 5, n);
149 throw GeographicErr(
"Unknown version in " + _filename +
": " + version);
152 while (getline(metastr, line)) {
158 else if (key ==
"Description")
160 else if (key ==
"ReleaseDate")
162 else if (key ==
"ModelRadius")
163 _amodel = Utility::val<real>(val);
164 else if (key ==
"ModelMass")
165 _gGMmodel = Utility::val<real>(val);
166 else if (key ==
"AngularVelocity")
167 omega = Utility::val<real>(val);
168 else if (key ==
"ReferenceRadius")
169 a = Utility::val<real>(val);
170 else if (key ==
"ReferenceMass")
171 GM = Utility::val<real>(val);
172 else if (key ==
"Flattening")
173 f = Utility::fract<real>(val);
174 else if (key ==
"DynamicalFormFactor")
175 J2 = Utility::fract<real>(val);
176 else if (key ==
"HeightOffset")
177 _zeta0 = Utility::fract<real>(val);
178 else if (key ==
"CorrectionMultiplier")
179 _corrmult = Utility::fract<real>(val);
180 else if (key ==
"Normalization") {
181 if (val ==
"FULL" || val ==
"Full" || val ==
"full")
183 else if (val ==
"SCHMIDT" || val ==
"Schmidt" || val ==
"schmidt")
187 }
else if (key ==
"ByteOrder") {
188 if (val ==
"Big" || val ==
"big")
189 throw GeographicErr(
"Only little-endian ordering is supported");
190 else if (!(val ==
"Little" || val ==
"little"))
191 throw GeographicErr(
"Unknown byte ordering " + val);
192 }
else if (key ==
"ID")
197 if (!(isfinite(_amodel) && _amodel > 0))
198 throw GeographicErr(
"Model radius must be positive");
199 if (!(isfinite(_gGMmodel) && _gGMmodel > 0))
200 throw GeographicErr(
"Model mass constant must be positive");
201 if (!(isfinite(_corrmult) && _corrmult > 0))
202 throw GeographicErr(
"Correction multiplier must be positive");
203 if (!(isfinite(_zeta0)))
204 throw GeographicErr(
"Height offset must be finite");
205 if (
int(_id.size()) != idlength_)
206 throw GeographicErr(
"Invalid ID");
207 if (isfinite(f) && isfinite(J2))
208 throw GeographicErr(
"Cannot specify both f and J2");
209 _earth = NormalGravity(a, GM, omega,
210 isfinite(f) ? f : J2, isfinite(f));
215 bool gradp,
bool correct)
const {
222 real T, invR = correct ? 1 / hypot(hypot(X, Y), Z) : 1;
225 deltaX = deltaY = deltaZ = 0;
226 T = _disturbing(-1, X, Y, Z, deltaX, deltaY, deltaZ);
227 real f = _gGMmodel / _amodel;
232 invR = _gGMmodel * _dzonal0 * invR * invR * invR;
238 T = _disturbing(-1, X, Y, Z);
239 T = (
T / _amodel - (correct ? _dzonal0 : 0) * invR) * _gGMmodel;
244 real& GX, real& GY, real& GZ)
const {
246 Vres = _gravitational(X, Y, Z, GX, GY, GZ),
247 f = _gGMmodel / _amodel;
256 real& gX, real& gY, real& gZ)
const {
258 Wres =
V(X, Y, Z, gX, gY, gZ) + _earth.
Phi(X, Y, fX, fY);
265 real& Dg01, real& xi, real& eta)
const {
266 real X, Y, Z, M[Geocentric::dim2_];
267 _earth.
Earth().IntForward(lat, lon, h, X, Y, Z, M);
269 deltax, deltay, deltaz,
270 T = InternalT(X, Y, Z, deltax, deltay, deltaz,
true,
false),
271 clam = M[3], slam = -M[0],
275 cpsi = R != 0 ? P / R : M[7],
276 spsi = R != 0 ? Z / R : M[8];
278 real MC[Geocentric::dim2_];
279 Geocentric::Rotation(spsi, cpsi, slam, clam, MC);
280 Geocentric::Unrotate(MC, deltax, deltay, deltaz, deltax, deltay, deltaz);
282 Dg01 = - deltaz - 2 *
T / R;
283 real gammaX, gammaY, gammaZ;
284 _earth.
U(X, Y, Z, gammaX, gammaY, gammaZ);
285 real gamma = hypot( hypot(gammaX, gammaY), gammaZ);
293 _earth.
Earth().IntForward(lat, lon, 0, X, Y, Z, NULL);
297 T = InternalT(X, Y, Z, dummy, dummy, dummy,
false,
false),
298 invR = 1 / hypot(hypot(X, Y), Z),
299 correction = _corrmult * _correction(invR * X, invR * Y, invR * Z);
301 return T/gamma0 + correction;
305 real& gx, real& gy, real& gz)
const {
306 real X, Y, Z, M[Geocentric::dim2_];
307 _earth.
Earth().IntForward(lat, lon, h, X, Y, Z, M);
308 real Wres =
W(X, Y, Z, gx, gy, gz);
309 Geocentric::Unrotate(M, gx, gy, gz, gx, gy, gz);
313 real& deltax, real& deltay,
314 real& deltaz)
const {
315 real X, Y, Z, M[Geocentric::dim2_];
316 _earth.
Earth().IntForward(lat, lon, h, X, Y, Z, M);
317 real Tres = InternalT(X, Y, Z, deltax, deltay, deltaz,
true,
true);
318 Geocentric::Unrotate(M, deltax, deltay, deltaz, deltax, deltay, deltaz);
325 caps &= ~(CAP_GAMMA0 | CAP_C);
326 real X, Y, Z, M[Geocentric::dim2_];
327 _earth.
Earth().IntForward(lat, 0, h, X, Y, Z, M);
330 invR = 1 / hypot(X, Z),
334 if (caps & CAP_GAMMA) {
335 _earth.
U(X, Y, Z, fx, fy, fz);
336 gamma = hypot(fx, fz);
339 _earth.
Phi(X, Y, fx, fy);
341 _earth._a, _earth._f, lat, h, Z, X, M[7], M[8],
342 _amodel, _gGMmodel, _dzonal0, _corrmult,
345 _gravitational.
Circle(X, Z,
true) :
349 _disturbing.
Circle(-1, X, Z, (caps&CAP_DELTA) != 0) :
352 _correction.
Circle(invR * X, invR * Z,
false) :
358 char* gravitypath = getenv(
"GEOGRAPHICLIB_GRAVITY_PATH");
360 path = string(gravitypath);
363 char* datapath = getenv(
"GEOGRAPHICLIB_DATA");
365 path = string(datapath);
371 char* gravityname = getenv(
"GEOGRAPHICLIB_GRAVITY_NAME");
373 name = string(gravityname);
GeographicLib::Math::real real
Header for GeographicLib::GravityCircle class.
#define GEOGRAPHICLIB_DATA
#define GEOGRAPHICLIB_GRAVITY_DEFAULT_NAME
Header for GeographicLib::GravityModel class.
Header for GeographicLib::SphericalEngine class.
Header for GeographicLib::Utility class.
Spherical harmonic sums for a circle.
Exception handling for GeographicLib.
Gravity on a circle of latitude.
friend class GravityCircle
Math::real Disturbance(real lat, real lon, real h, real &deltax, real &deltay, real &deltaz) const
static std::string DefaultGravityPath()
void SphericalAnomaly(real lat, real lon, real h, real &Dg01, real &xi, real &eta) const
GravityCircle Circle(real lat, real h, unsigned caps=ALL) const
static std::string DefaultGravityName()
Math::real GeoidHeight(real lat, real lon) const
Math::real T(real X, real Y, real Z, real &deltaX, real &deltaY, real &deltaZ) const
Math::real Gravity(real lat, real lon, real h, real &gx, real &gy, real &gz) const
Math::real V(real X, real Y, real Z, real &GX, real &GY, real &GZ) const
Math::real W(real X, real Y, real Z, real &gX, real &gY, real &gZ) const
Mathematical functions needed by GeographicLib.
const Geocentric & Earth() const
Math::real Phi(real X, real Y, real &fX, real &fY) const
Math::real MassConstant() const
Math::real U(real X, real Y, real Z, real &gammaX, real &gammaY, real &gammaZ) const
Math::real SurfaceGravity(real lat) const
static void readcoeffs(std::istream &stream, int &N, int &M, std::vector< real > &C, std::vector< real > &S, bool truncate=false)
Spherical harmonic series with a correction to the coefficients.
CircularEngine Circle(real tau, real p, real z, bool gradp) const
Spherical harmonic series.
const SphericalEngine::coeff & Coefficients() const
CircularEngine Circle(real p, real z, bool gradp) const
static bool ParseLine(const std::string &line, std::string &key, std::string &value, char equals='\0', char comment='#')
Namespace for GeographicLib.