GeographicLib: SphericalEngine.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

136

137#if defined(_MSC_VER)

138

139# pragma warning (disable: 4701)

140#endif

141

143

144 using namespace std;

145

146 vectorMath::real& SphericalEngine::sqrttable() {

147 static vector sqrttable(0);

148 return sqrttable;

149 }

150

151 template<bool gradp, SphericalEngine::normalization norm, int L>

153 real x, real y, real z, real a,

154 real& gradx, real& grady, real& gradz)

155 {

156 static_assert(L > 0, "L must be positive");

157 static_assert(norm == FULL || norm == SCHMIDT, "Unknown normalization");

158 int N = c[0].nmx(), M = c[0].mmx();

159

160 real

161 p = hypot(x, y),

162 cl = p != 0 ? x / p : 1,

163 sl = p != 0 ? y / p : 0,

164 r = hypot(z, p),

165 t = r != 0 ? z / r : 0,

166 u = r != 0 ? fmax(p / r, eps()) : 1,

167 q = a / r;

168 real

170 uq = u * q,

172 tu = t / u;

173

174 real vc = 0, vc2 = 0, vs = 0, vs2 = 0;

175

176

177 real vrc = 0, vrc2 = 0, vrs = 0, vrs2 = 0;

178 real vtc = 0, vtc2 = 0, vts = 0, vts2 = 0;

179 real vlc = 0, vlc2 = 0, vls = 0, vls2 = 0;

180 int k[L];

181 const vector& root( sqrttable() );

182 for (int m = M; m >= 0; --m) {

183

184 real

185 wc = 0, wc2 = 0, ws = 0, ws2 = 0,

186 wrc = 0, wrc2 = 0, wrs = 0, wrs2 = 0,

187 wtc = 0, wtc2 = 0, wts = 0, wts2 = 0;

188 for (int l = 0; l < L; ++l)

189 k[l] = c[l].index(N, m) + 1;

190 for (int n = N; n >= m; --n) {

191 real w, A, Ax, B, R;

192 switch (norm) {

194 w = root[2 * n + 1] / (root[n - m + 1] * root[n + m + 1]);

195 Ax = q * w * root[2 * n + 3];

196 A = t * Ax;

197 B = - q2 * root[2 * n + 5] /

198 (w * root[n - m + 2] * root[n + m + 2]);

199 break;

201 w = root[n - m + 1] * root[n + m + 1];

202 Ax = q * (2 * n + 1) / w;

203 A = t * Ax;

204 B = - q2 * w / (root[n - m + 2] * root[n + m + 2]);

205 break;

206 default: break;

207 }

208 R = c[0].Cv(--k[0]);

209 for (int l = 1; l < L; ++l)

210 R += c[l].Cv(--k[l], n, m, f[l]);

211 R *= scale();

212 w = A * wc + B * wc2 + R; wc2 = wc; wc = w;

213 if (gradp) {

214 w = A * wrc + B * wrc2 + (n + 1) * R; wrc2 = wrc; wrc = w;

215 w = A * wtc + B * wtc2 - u*Ax * wc2; wtc2 = wtc; wtc = w;

216 }

217 if (m) {

218 R = c[0].Sv(k[0]);

219 for (int l = 1; l < L; ++l)

220 R += c[l].Sv(k[l], n, m, f[l]);

221 R *= scale();

222 w = A * ws + B * ws2 + R; ws2 = ws; ws = w;

223 if (gradp) {

224 w = A * wrs + B * wrs2 + (n + 1) * R; wrs2 = wrs; wrs = w;

225 w = A * wts + B * wts2 - u*Ax * ws2; wts2 = wts; wts = w;

226 }

227 }

228 }

229

230

231 if (m) {

232 real v, A, B;

233 switch (norm) {

235 v = root[2] * root[2 * m + 3] / root[m + 1];

236 A = cl * v * uq;

237 B = - v * root[2 * m + 5] / (root[8] * root[m + 2]) * uq2;

238 break;

240 v = root[2] * root[2 * m + 1] / root[m + 1];

241 A = cl * v * uq;

242 B = - v * root[2 * m + 3] / (root[8] * root[m + 2]) * uq2;

243 break;

244 default: break;

245 }

246 v = A * vc + B * vc2 + wc ; vc2 = vc ; vc = v;

247 v = A * vs + B * vs2 + ws ; vs2 = vs ; vs = v;

248 if (gradp) {

249

250 wtc += m * tu * wc; wts += m * tu * ws;

251 v = A * vrc + B * vrc2 + wrc; vrc2 = vrc; vrc = v;

252 v = A * vrs + B * vrs2 + wrs; vrs2 = vrs; vrs = v;

253 v = A * vtc + B * vtc2 + wtc; vtc2 = vtc; vtc = v;

254 v = A * vts + B * vts2 + wts; vts2 = vts; vts = v;

255 v = A * vlc + B * vlc2 + m*ws; vlc2 = vlc; vlc = v;

256 v = A * vls + B * vls2 - m*wc; vls2 = vls; vls = v;

257 }

258 } else {

259 real A, B, qs;

260 switch (norm) {

262 A = root[3] * uq;

263 B = - root[15]/2 * uq2;

264 break;

266 A = uq;

267 B = - root[3]/2 * uq2;

268 break;

269 default: break;

270 }

271 qs = q / scale();

272 vc = qs * (wc + A * (cl * vc + sl * vs ) + B * vc2);

273 if (gradp) {

274 qs /= r;

275

276

277

278

279 vrc = - qs * (wrc + A * (cl * vrc + sl * vrs) + B * vrc2);

280 vtc = qs * (wtc + A * (cl * vtc + sl * vts) + B * vtc2);

281 vlc = qs / u * ( A * (cl * vlc + sl * vls) + B * vlc2);

282 }

283 }

284 }

285

286 if (gradp) {

287

288 gradx = cl * (u * vrc + t * vtc) - sl * vlc;

289 grady = sl * (u * vrc + t * vtc) + cl * vlc;

290 gradz = t * vrc - u * vtc ;

291 }

292 return vc;

293 }

294

295 template<bool gradp, SphericalEngine::normalization norm, int L>

297 real p, real z, real a) {

298

299 static_assert(L > 0, "L must be positive");

300 static_assert(norm == FULL || norm == SCHMIDT, "Unknown normalization");

301 int N = c[0].nmx(), M = c[0].mmx();

302

303 real

304 r = hypot(z, p),

305 t = r != 0 ? z / r : 0,

306 u = r != 0 ? fmax(p / r, eps()) : 1,

307 q = a / r;

308 real

310 tu = t / u;

312 int k[L];

313 const vector& root( sqrttable() );

314 for (int m = M; m >= 0; --m) {

315

316 real

317 wc = 0, wc2 = 0, ws = 0, ws2 = 0,

318 wrc = 0, wrc2 = 0, wrs = 0, wrs2 = 0,

319 wtc = 0, wtc2 = 0, wts = 0, wts2 = 0;

320 for (int l = 0; l < L; ++l)

321 k[l] = c[l].index(N, m) + 1;

322 for (int n = N; n >= m; --n) {

323 real w, A, Ax, B, R;

324 switch (norm) {

326 w = root[2 * n + 1] / (root[n - m + 1] * root[n + m + 1]);

327 Ax = q * w * root[2 * n + 3];

328 A = t * Ax;

329 B = - q2 * root[2 * n + 5] /

330 (w * root[n - m + 2] * root[n + m + 2]);

331 break;

333 w = root[n - m + 1] * root[n + m + 1];

334 Ax = q * (2 * n + 1) / w;

335 A = t * Ax;

336 B = - q2 * w / (root[n - m + 2] * root[n + m + 2]);

337 break;

338 default: break;

339 }

340 R = c[0].Cv(--k[0]);

341 for (int l = 1; l < L; ++l)

342 R += c[l].Cv(--k[l], n, m, f[l]);

343 R *= scale();

344 w = A * wc + B * wc2 + R; wc2 = wc; wc = w;

345 if (gradp) {

346 w = A * wrc + B * wrc2 + (n + 1) * R; wrc2 = wrc; wrc = w;

347 w = A * wtc + B * wtc2 - u*Ax * wc2; wtc2 = wtc; wtc = w;

348 }

349 if (m) {

350 R = c[0].Sv(k[0]);

351 for (int l = 1; l < L; ++l)

352 R += c[l].Sv(k[l], n, m, f[l]);

353 R *= scale();

354 w = A * ws + B * ws2 + R; ws2 = ws; ws = w;

355 if (gradp) {

356 w = A * wrs + B * wrs2 + (n + 1) * R; wrs2 = wrs; wrs = w;

357 w = A * wts + B * wts2 - u*Ax * ws2; wts2 = wts; wts = w;

358 }

359 }

360 }

361 if (!gradp)

362 circ.SetCoeff(m, wc, ws);

363 else {

364

365 wtc += m * tu * wc; wts += m * tu * ws;

366 circ.SetCoeff(m, wc, ws, wrc, wrs, wtc, wts);

367 }

368 }

369

370 return circ;

371 }

372

374

375 vector& root( sqrttable() );

376 int L = max(2 * N + 5, 15) + 1, oldL = int(root.size());

377 if (oldL >= L)

378 return;

379 root.resize(L);

380 for (int l = oldL; l < L; ++l)

381 root[l] = sqrt(real(l));

382 }

383

385 vector& C,

386 vector& S,

387 bool truncate) {

388 if (truncate) {

389 if (!((N >= M && M >= 0) || (N == -1 && M == -1)))

390

391 throw GeographicErr("Bad requested degree and order " +

393 }

394 int nm[2];

395 Utility::readarray<int, int, false>(stream, nm, 2);

396 int N0 = nm[0], M0 = nm[1];

397 if (!((N0 >= M0 && M0 >= 0) || (N0 == -1 && M0 == -1)))

398

401 N = truncate ? min(N, N0) : N0;

402 M = truncate ? min(M, M0) : M0;

407 if (N == N0) {

408 Utility::readarray<double, real, false>(stream, C);

409 if (skip) stream.seekg(streamoff(skip), ios::cur);

410 Utility::readarray<double, real, false>(stream, S);

411 if (skip) stream.seekg(streamoff(skip), ios::cur);

412 } else {

413 for (int m = 0, k = 0; m <= M; ++m) {

414 Utility::readarray<double, real, false>(stream, &C[k], N + 1 - m);

415 stream.seekg((N0 - N) * sizeof(double), ios::cur);

416 k += N + 1 - m;

417 }

418 if (skip) stream.seekg(streamoff(skip), ios::cur);

419 for (int m = 1, k = 0; m <= M; ++m) {

420 Utility::readarray<double, real, false>(stream, &S[k], N + 1 - m);

421 stream.seekg((N0 - N) * sizeof(double), ios::cur);

422 k += N + 1 - m;

423 }

424 if (skip) stream.seekg(streamoff(skip), ios::cur);

425 }

426 return;

427 }

428

429

431 SphericalEngine::Value<true, SphericalEngine::FULL, 1>

432 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

434 SphericalEngine::Value<false, SphericalEngine::FULL, 1>

435 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

437 SphericalEngine::Value<true, SphericalEngine::SCHMIDT, 1>

438 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

440 SphericalEngine::Value<false, SphericalEngine::SCHMIDT, 1>

441 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

442

444 SphericalEngine::Value<true, SphericalEngine::FULL, 2>

445 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

447 SphericalEngine::Value<false, SphericalEngine::FULL, 2>

448 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

450 SphericalEngine::Value<true, SphericalEngine::SCHMIDT, 2>

451 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

453 SphericalEngine::Value<false, SphericalEngine::SCHMIDT, 2>

454 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

455

457 SphericalEngine::Value<true, SphericalEngine::FULL, 3>

458 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

460 SphericalEngine::Value<false, SphericalEngine::FULL, 3>

461 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

463 SphericalEngine::Value<true, SphericalEngine::SCHMIDT, 3>

464 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

466 SphericalEngine::Value<false, SphericalEngine::SCHMIDT, 3>

467 (const coeff[], const real[], real, real, real, real, real&, real&, real&);

468

470 SphericalEngine::Circle<true, SphericalEngine::FULL, 1>

471 (const coeff[], const real[], real, real, real);

473 SphericalEngine::Circle<false, SphericalEngine::FULL, 1>

474 (const coeff[], const real[], real, real, real);

476 SphericalEngine::Circle<true, SphericalEngine::SCHMIDT, 1>

477 (const coeff[], const real[], real, real, real);

479 SphericalEngine::Circle<false, SphericalEngine::SCHMIDT, 1>

480 (const coeff[], const real[], real, real, real);

481

483 SphericalEngine::Circle<true, SphericalEngine::FULL, 2>

484 (const coeff[], const real[], real, real, real);

486 SphericalEngine::Circle<false, SphericalEngine::FULL, 2>

487 (const coeff[], const real[], real, real, real);

489 SphericalEngine::Circle<true, SphericalEngine::SCHMIDT, 2>

490 (const coeff[], const real[], real, real, real);

492 SphericalEngine::Circle<false, SphericalEngine::SCHMIDT, 2>

493 (const coeff[], const real[], real, real, real);

494

496 SphericalEngine::Circle<true, SphericalEngine::FULL, 3>

497 (const coeff[], const real[], real, real, real);

499 SphericalEngine::Circle<false, SphericalEngine::FULL, 3>

500 (const coeff[], const real[], real, real, real);

502 SphericalEngine::Circle<true, SphericalEngine::SCHMIDT, 3>

503 (const coeff[], const real[], real, real, real);

505 SphericalEngine::Circle<false, SphericalEngine::SCHMIDT, 3>

506 (const coeff[], const real[], real, real, real);

507

508

509}

Header for GeographicLib::CircularEngine class.

#define GEOGRAPHICLIB_EXPORT

Header for GeographicLib::SphericalEngine class.

Header for GeographicLib::Utility class.

Spherical harmonic sums for a circle.

Exception handling for GeographicLib.

Package up coefficients for SphericalEngine.

Math::real Sv(int k) const

static int Csize(int N, int M)

static int Ssize(int N, int M)

static void readcoeffs(std::istream &stream, int &N, int &M, std::vector< real > &C, std::vector< real > &S, bool truncate=false)

Definition SphericalEngine.cpp:384

Math::real Cv(int k) const

static Math::real Value(const coeff c[], const real f[], real x, real y, real z, real a, real &gradx, real &grady, real &gradz)

Definition SphericalEngine.cpp:152

static void RootTable(int N)

Definition SphericalEngine.cpp:373

static CircularEngine Circle(const coeff c[], const real f[], real p, real z, real a)

Definition SphericalEngine.cpp:296

static std::string str(T x, int p=-1)

Namespace for GeographicLib.