16 #if !defined(GEOGRAPHICLIB_DATA) 18 # define GEOGRAPHICLIB_DATA "C:/ProgramData/GeographicLib" 20 # define GEOGRAPHICLIB_DATA "/usr/local/share/GeographicLib" 24 #if !defined(GEOGRAPHICLIB_MAGNETIC_DEFAULT_NAME) 25 # define GEOGRAPHICLIB_MAGNETIC_DEFAULT_NAME "wmm2015" 30 # pragma warning (disable: 4996) 37 MagneticModel::MagneticModel(
const std::string& name,
const std::string& path,
41 , _description(
"NONE")
58 _G.resize(_Nmodels + 1 + _Nconstants);
59 _H.resize(_Nmodels + 1 + _Nconstants);
61 string coeff = _filename +
".cof";
62 ifstream coeffstr(coeff.c_str(), ios::binary);
65 char id[idlength_ + 1];
66 coeffstr.read(
id, idlength_);
70 if (_id !=
string(
id))
72 for (
int i = 0; i < _Nmodels + 1 + _Nconstants; ++i) {
75 if (!(M < 0 || _G[i][0] == 0))
79 int pos = int(coeffstr.tellg());
80 coeffstr.seekg(0, ios::end);
81 if (pos != coeffstr.tellg())
86 void MagneticModel::ReadMetadata(
const std::string& name) {
87 const char* spaces =
" \t\n\v\f\r";
88 _filename = _dir +
"/" + name +
".wmm";
89 ifstream metastr(_filename.c_str());
93 getline(metastr, line);
94 if (!(line.size() >= 6 && line.substr(0,5) ==
"WMMF-"))
95 throw GeographicErr(_filename +
" does not contain WMMF-n signature");
96 string::size_type n = line.find_first_of(spaces, 5);
97 if (n != string::npos)
99 string version = line.substr(5, n);
100 if (!(version ==
"1" || version ==
"2"))
101 throw GeographicErr(
"Unknown version in " + _filename +
": " + version);
103 while (getline(metastr, line)) {
109 else if (key ==
"Description")
111 else if (key ==
"ReleaseDate")
113 else if (key ==
"Radius")
114 _a = Utility::num<real>(val);
115 else if (key ==
"Type") {
116 if (!(val ==
"Linear" || val ==
"linear"))
118 }
else if (key ==
"Epoch")
119 _t0 = Utility::num<real>(val);
120 else if (key ==
"DeltaEpoch")
121 _dt0 = Utility::num<real>(val);
122 else if (key ==
"NumModels")
123 _Nmodels = Utility::num<int>(val);
124 else if (key ==
"NumConstants")
125 _Nconstants = Utility::num<int>(val);
126 else if (key ==
"MinTime")
127 _tmin = Utility::num<real>(val);
128 else if (key ==
"MaxTime")
129 _tmax = Utility::num<real>(val);
130 else if (key ==
"MinHeight")
131 _hmin = Utility::num<real>(val);
132 else if (key ==
"MaxHeight")
133 _hmax = Utility::num<real>(val);
134 else if (key ==
"Normalization") {
135 if (val ==
"FULL" || val ==
"Full" || val ==
"full")
137 else if (val ==
"SCHMIDT" || val ==
"Schmidt" || val ==
"schmidt")
141 }
else if (key ==
"ByteOrder") {
142 if (val ==
"Big" || val ==
"big")
143 throw GeographicErr(
"Only little-endian ordering is supported");
144 else if (!(val ==
"Little" || val ==
"little"))
146 }
else if (key ==
"ID")
159 if (
int(_id.size()) != idlength_)
163 if (!(_Nconstants == 0 || _Nconstants == 1))
173 void MagneticModel::Field(real t, real lat, real lon, real h,
bool diffp,
174 real& Bx, real& By, real& Bz,
175 real& Bxt, real& Byt, real& Bzt)
const {
177 int n = max(min(
int(floor(t / _dt0)), _Nmodels - 1), 0);
178 bool interpolate = n + 1 < _Nmodels;
181 real M[Geocentric::dim2_];
182 _earth.IntForward(lat, lon, h, X, Y, Z, M);
185 real BX0 = 0, BY0 = 0, BZ0 = 0, BX1 = 0, BY1 = 0, BZ1 = 0;
186 real BXc = 0, BYc = 0, BZc = 0;
187 _harm[n](X, Y, Z, BX0, BY0, BZ0);
188 _harm[n + 1](X, Y, Z, BX1, BY1, BZ1);
190 _harm[_Nmodels + 1](X, Y, Z, BXc, BYc, BZc);
193 BX1 = (BX1 - BX0) / _dt0;
194 BY1 = (BY1 - BY0) / _dt0;
195 BZ1 = (BZ1 - BZ0) / _dt0;
197 BX0 += t * BX1 + BXc;
198 BY0 += t * BY1 + BYc;
199 BZ0 += t * BZ1 + BZc;
201 Geocentric::Unrotate(M, BX1, BY1, BZ1, Bxt, Byt, Bzt);
206 Geocentric::Unrotate(M, BX0, BY0, BZ0, Bx, By, Bz);
214 int n = max(min(
int(floor(t1 / _dt0)), _Nmodels - 1), 0);
215 bool interpolate = n + 1 < _Nmodels;
217 real X, Y, Z, M[Geocentric::dim2_];
218 _earth.IntForward(lat, 0, h, X, Y, Z, M);
221 return (_Nconstants == 0 ?
223 M[7], M[8], t1, _dt0, interpolate,
224 _harm[n].Circle(X, Z,
true),
225 _harm[n + 1].Circle(X, Z,
true)) :
227 M[7], M[8], t1, _dt0, interpolate,
228 _harm[n].Circle(X, Z,
true),
229 _harm[n + 1].Circle(X, Z,
true),
230 _harm[_Nmodels + 1].Circle(X, Z,
true)));
234 real Bxt, real Byt, real Bzt,
235 real& H, real& F, real& D, real& I,
237 real& Dt, real& It) {
239 Ht = H ? (Bx * Bxt + By * Byt) / H :
Math::hypot(Bxt, Byt);
243 Ft = F ? (H * Ht + Bz * Bzt) / F :
Math::hypot(Ht, Bzt);
250 char* magneticpath = getenv(
"GEOGRAPHICLIB_MAGNETIC_PATH");
252 path = string(magneticpath);
255 char* datapath = getenv(
"GEOGRAPHICLIB_DATA");
257 path = string(datapath);
263 char* magneticname = getenv(
"GEOGRAPHICLIB_MAGNETIC_NAME");
265 name = string(magneticname);
Header for GeographicLib::Utility class.
static bool isfinite(T x)
Header for GeographicLib::MagneticCircle class.
Mathematical functions needed by GeographicLib.
#define GEOGRAPHICLIB_MAGNETIC_DEFAULT_NAME
Geomagnetic field on a circle of latitude.
MagneticCircle Circle(real t, real lat, real h) const
static void FieldComponents(real Bx, real By, real Bz, real &H, real &F, real &D, real &I)
static void readcoeffs(std::istream &stream, int &N, int &M, std::vector< real > &C, std::vector< real > &S)
static T atan2d(T y, T x)
#define GEOGRAPHICLIB_DATA
Namespace for GeographicLib.
Header for GeographicLib::MagneticModel class.
static std::string DefaultMagneticName()
Exception handling for GeographicLib.
static std::string DefaultMagneticPath()
Spherical harmonic series.
static bool ParseLine(const std::string &line, std::string &key, std::string &val)
Header for GeographicLib::SphericalEngine class.