geographiclib 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* \file SphericalEngine.hpp
|
|
3
|
+
* \brief Header for GeographicLib::SphericalEngine class
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) Charles Karney (2011-2012) <charles@karney.com> and licensed
|
|
6
|
+
* under the MIT/X11 License. For more information, see
|
|
7
|
+
* http://geographiclib.sourceforge.net/
|
|
8
|
+
**********************************************************************/
|
|
9
|
+
|
|
10
|
+
#if !defined(GEOGRAPHICLIB_SPHERICALENGINE_HPP)
|
|
11
|
+
#define GEOGRAPHICLIB_SPHERICALENGINE_HPP 1
|
|
12
|
+
|
|
13
|
+
#include <vector>
|
|
14
|
+
#include <istream>
|
|
15
|
+
#include <GeographicLib/Constants.hpp>
|
|
16
|
+
|
|
17
|
+
#if defined(_MSC_VER)
|
|
18
|
+
// Squelch warnings about dll vs vector
|
|
19
|
+
# pragma warning (push)
|
|
20
|
+
# pragma warning (disable: 4251)
|
|
21
|
+
#endif
|
|
22
|
+
|
|
23
|
+
namespace GeographicLib {
|
|
24
|
+
|
|
25
|
+
class CircularEngine;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* \brief The evaluation engine for SphericalHarmonic
|
|
29
|
+
*
|
|
30
|
+
* This serves as the backend to SphericalHarmonic, SphericalHarmonic1, and
|
|
31
|
+
* SphericalHarmonic2. Typically end-users will not have to access this
|
|
32
|
+
* class directly.
|
|
33
|
+
*
|
|
34
|
+
* See SphericalEngine.cpp for more information on the implementation.
|
|
35
|
+
*
|
|
36
|
+
* Example of use:
|
|
37
|
+
* \include example-SphericalEngine.cpp
|
|
38
|
+
**********************************************************************/
|
|
39
|
+
|
|
40
|
+
class GEOGRAPHICLIB_EXPORT SphericalEngine {
|
|
41
|
+
private:
|
|
42
|
+
typedef Math::real real;
|
|
43
|
+
// A table of the square roots of integers
|
|
44
|
+
static std::vector<real> root_;
|
|
45
|
+
friend class CircularEngine; // CircularEngine needs access to root_, scale_
|
|
46
|
+
// An internal scaling of the coefficients to avoid overflow in
|
|
47
|
+
// intermediate calculations.
|
|
48
|
+
static real scale() {
|
|
49
|
+
using std::pow;
|
|
50
|
+
return pow(real(std::numeric_limits<real>::radix),
|
|
51
|
+
-3 * (std::numeric_limits<real>::max_exponent < (1<<14) ?
|
|
52
|
+
std::numeric_limits<real>::max_exponent : (1<<14)) / 5);
|
|
53
|
+
}
|
|
54
|
+
// Move latitudes near the pole off the axis by this amount.
|
|
55
|
+
static real eps() {
|
|
56
|
+
using std::sqrt;
|
|
57
|
+
return std::numeric_limits<real>::epsilon() *
|
|
58
|
+
sqrt(std::numeric_limits<real>::epsilon());
|
|
59
|
+
}
|
|
60
|
+
static const std::vector<real> Z_;
|
|
61
|
+
SphericalEngine(); // Disable constructor
|
|
62
|
+
public:
|
|
63
|
+
/**
|
|
64
|
+
* Supported normalizations for associated Legendre polynomials.
|
|
65
|
+
**********************************************************************/
|
|
66
|
+
enum normalization {
|
|
67
|
+
/**
|
|
68
|
+
* Fully normalized associated Legendre polynomials. See
|
|
69
|
+
* SphericalHarmonic::FULL for documentation.
|
|
70
|
+
*
|
|
71
|
+
* @hideinitializer
|
|
72
|
+
**********************************************************************/
|
|
73
|
+
FULL = 0,
|
|
74
|
+
/**
|
|
75
|
+
* Schmidt semi-normalized associated Legendre polynomials. See
|
|
76
|
+
* SphericalHarmonic::SCHMIDT for documentation.
|
|
77
|
+
*
|
|
78
|
+
* @hideinitializer
|
|
79
|
+
**********************************************************************/
|
|
80
|
+
SCHMIDT = 1,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* \brief Package up coefficients for SphericalEngine
|
|
85
|
+
*
|
|
86
|
+
* This packages up the \e C, \e S coefficients and information about how
|
|
87
|
+
* the coefficients are stored into a single structure. This allows a
|
|
88
|
+
* vector of type SphericalEngine::coeff to be passed to
|
|
89
|
+
* SphericalEngine::Value. This class also includes functions to aid
|
|
90
|
+
* indexing into \e C and \e S.
|
|
91
|
+
*
|
|
92
|
+
* The storage layout of the coefficients is documented in
|
|
93
|
+
* SphericalHarmonic and SphericalHarmonic::SphericalHarmonic.
|
|
94
|
+
**********************************************************************/
|
|
95
|
+
class GEOGRAPHICLIB_EXPORT coeff {
|
|
96
|
+
private:
|
|
97
|
+
int _Nx, _nmx, _mmx;
|
|
98
|
+
std::vector<real>::const_iterator _Cnm;
|
|
99
|
+
std::vector<real>::const_iterator _Snm;
|
|
100
|
+
public:
|
|
101
|
+
/**
|
|
102
|
+
* A default constructor
|
|
103
|
+
**********************************************************************/
|
|
104
|
+
coeff()
|
|
105
|
+
: _Nx(-1)
|
|
106
|
+
, _nmx(-1)
|
|
107
|
+
, _mmx(-1)
|
|
108
|
+
, _Cnm(Z_.begin())
|
|
109
|
+
, _Snm(Z_.begin()) {}
|
|
110
|
+
/**
|
|
111
|
+
* The general constructor.
|
|
112
|
+
*
|
|
113
|
+
* @param[in] C a vector of coefficients for the cosine terms.
|
|
114
|
+
* @param[in] S a vector of coefficients for the sine terms.
|
|
115
|
+
* @param[in] N the degree giving storage layout for \e C and \e S.
|
|
116
|
+
* @param[in] nmx the maximum degree to be used.
|
|
117
|
+
* @param[in] mmx the maximum order to be used.
|
|
118
|
+
* @exception GeographicErr if \e N, \e nmx, and \e mmx do not satisfy
|
|
119
|
+
* \e N ≥ \e nmx ≥ \e mmx ≥ −1.
|
|
120
|
+
* @exception GeographicErr if \e C or \e S is not big enough to hold the
|
|
121
|
+
* coefficients.
|
|
122
|
+
* @exception std::bad_alloc if the memory for the square root table
|
|
123
|
+
* can't be allocated.
|
|
124
|
+
**********************************************************************/
|
|
125
|
+
coeff(const std::vector<real>& C,
|
|
126
|
+
const std::vector<real>& S,
|
|
127
|
+
int N, int nmx, int mmx)
|
|
128
|
+
: _Nx(N)
|
|
129
|
+
, _nmx(nmx)
|
|
130
|
+
, _mmx(mmx)
|
|
131
|
+
, _Cnm(C.begin())
|
|
132
|
+
, _Snm(S.begin())
|
|
133
|
+
{
|
|
134
|
+
if (!(_Nx >= _nmx && _nmx >= _mmx && _mmx >= -1))
|
|
135
|
+
throw GeographicErr("Bad indices for coeff");
|
|
136
|
+
if (!(index(_nmx, _mmx) < int(C.size()) &&
|
|
137
|
+
index(_nmx, _mmx) < int(S.size()) + (_Nx + 1)))
|
|
138
|
+
throw GeographicErr("Arrays too small in coeff");
|
|
139
|
+
SphericalEngine::RootTable(_nmx);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The constructor for full coefficient vectors.
|
|
143
|
+
*
|
|
144
|
+
* @param[in] C a vector of coefficients for the cosine terms.
|
|
145
|
+
* @param[in] S a vector of coefficients for the sine terms.
|
|
146
|
+
* @param[in] N the maximum degree and order.
|
|
147
|
+
* @exception GeographicErr if \e N does not satisfy \e N ≥ −1.
|
|
148
|
+
* @exception GeographicErr if \e C or \e S is not big enough to hold the
|
|
149
|
+
* coefficients.
|
|
150
|
+
* @exception std::bad_alloc if the memory for the square root table
|
|
151
|
+
* can't be allocated.
|
|
152
|
+
**********************************************************************/
|
|
153
|
+
coeff(const std::vector<real>& C,
|
|
154
|
+
const std::vector<real>& S,
|
|
155
|
+
int N)
|
|
156
|
+
: _Nx(N)
|
|
157
|
+
, _nmx(N)
|
|
158
|
+
, _mmx(N)
|
|
159
|
+
, _Cnm(C.begin())
|
|
160
|
+
, _Snm(S.begin())
|
|
161
|
+
{
|
|
162
|
+
if (!(_Nx >= -1))
|
|
163
|
+
throw GeographicErr("Bad indices for coeff");
|
|
164
|
+
if (!(index(_nmx, _mmx) < int(C.size()) &&
|
|
165
|
+
index(_nmx, _mmx) < int(S.size()) + (_Nx + 1)))
|
|
166
|
+
throw GeographicErr("Arrays too small in coeff");
|
|
167
|
+
SphericalEngine::RootTable(_nmx);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* @return \e N the degree giving storage layout for \e C and \e S.
|
|
171
|
+
**********************************************************************/
|
|
172
|
+
inline int N() const { return _Nx; }
|
|
173
|
+
/**
|
|
174
|
+
* @return \e nmx the maximum degree to be used.
|
|
175
|
+
**********************************************************************/
|
|
176
|
+
inline int nmx() const { return _nmx; }
|
|
177
|
+
/**
|
|
178
|
+
* @return \e mmx the maximum order to be used.
|
|
179
|
+
**********************************************************************/
|
|
180
|
+
inline int mmx() const { return _mmx; }
|
|
181
|
+
/**
|
|
182
|
+
* The one-dimensional index into \e C and \e S.
|
|
183
|
+
*
|
|
184
|
+
* @param[in] n the degree.
|
|
185
|
+
* @param[in] m the order.
|
|
186
|
+
* @return the one-dimensional index.
|
|
187
|
+
**********************************************************************/
|
|
188
|
+
inline int index(int n, int m) const
|
|
189
|
+
{ return m * _Nx - m * (m - 1) / 2 + n; }
|
|
190
|
+
/**
|
|
191
|
+
* An element of \e C.
|
|
192
|
+
*
|
|
193
|
+
* @param[in] k the one-dimensional index.
|
|
194
|
+
* @return the value of the \e C coefficient.
|
|
195
|
+
**********************************************************************/
|
|
196
|
+
inline Math::real Cv(int k) const { return *(_Cnm + k); }
|
|
197
|
+
/**
|
|
198
|
+
* An element of \e S.
|
|
199
|
+
*
|
|
200
|
+
* @param[in] k the one-dimensional index.
|
|
201
|
+
* @return the value of the \e S coefficient.
|
|
202
|
+
**********************************************************************/
|
|
203
|
+
inline Math::real Sv(int k) const { return *(_Snm + (k - (_Nx + 1))); }
|
|
204
|
+
/**
|
|
205
|
+
* An element of \e C with checking.
|
|
206
|
+
*
|
|
207
|
+
* @param[in] k the one-dimensional index.
|
|
208
|
+
* @param[in] n the requested degree.
|
|
209
|
+
* @param[in] m the requested order.
|
|
210
|
+
* @param[in] f a multiplier.
|
|
211
|
+
* @return the value of the \e C coefficient multiplied by \e f in \e n
|
|
212
|
+
* and \e m are in range else 0.
|
|
213
|
+
**********************************************************************/
|
|
214
|
+
inline Math::real Cv(int k, int n, int m, real f) const
|
|
215
|
+
{ return m > _mmx || n > _nmx ? 0 : *(_Cnm + k) * f; }
|
|
216
|
+
/**
|
|
217
|
+
* An element of \e S with checking.
|
|
218
|
+
*
|
|
219
|
+
* @param[in] k the one-dimensional index.
|
|
220
|
+
* @param[in] n the requested degree.
|
|
221
|
+
* @param[in] m the requested order.
|
|
222
|
+
* @param[in] f a multiplier.
|
|
223
|
+
* @return the value of the \e S coefficient multiplied by \e f in \e n
|
|
224
|
+
* and \e m are in range else 0.
|
|
225
|
+
**********************************************************************/
|
|
226
|
+
inline Math::real Sv(int k, int n, int m, real f) const
|
|
227
|
+
{ return m > _mmx || n > _nmx ? 0 : *(_Snm + (k - (_Nx + 1))) * f; }
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* The size of the coefficient vector for the cosine terms.
|
|
231
|
+
*
|
|
232
|
+
* @param[in] N the maximum degree.
|
|
233
|
+
* @param[in] M the maximum order.
|
|
234
|
+
* @return the size of the vector of cosine terms as stored in column
|
|
235
|
+
* major order.
|
|
236
|
+
**********************************************************************/
|
|
237
|
+
static inline int Csize(int N, int M)
|
|
238
|
+
{ return (M + 1) * (2 * N - M + 2) / 2; }
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The size of the coefficient vector for the sine terms.
|
|
242
|
+
*
|
|
243
|
+
* @param[in] N the maximum degree.
|
|
244
|
+
* @param[in] M the maximum order.
|
|
245
|
+
* @return the size of the vector of cosine terms as stored in column
|
|
246
|
+
* major order.
|
|
247
|
+
**********************************************************************/
|
|
248
|
+
static inline int Ssize(int N, int M)
|
|
249
|
+
{ return Csize(N, M) - (N + 1); }
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Load coefficients from a binary stream.
|
|
253
|
+
*
|
|
254
|
+
* @param[in] stream the input stream.
|
|
255
|
+
* @param[out] N The maximum degree of the coefficients.
|
|
256
|
+
* @param[out] M The maximum order of the coefficients.
|
|
257
|
+
* @param[out] C The vector of cosine coefficients.
|
|
258
|
+
* @param[out] S The vector of sine coefficients.
|
|
259
|
+
* @exception GeographicErr if \e N and \e M do not satisfy \e N ≥
|
|
260
|
+
* \e M ≥ −1.
|
|
261
|
+
* @exception GeographicErr if there's an error reading the data.
|
|
262
|
+
* @exception std::bad_alloc if the memory for \e C or \e S can't be
|
|
263
|
+
* allocated.
|
|
264
|
+
*
|
|
265
|
+
* \e N and \e M are read as 4-byte ints. \e C and \e S are resized to
|
|
266
|
+
* accommodate all the coefficients (with the \e m = 0 coefficients for
|
|
267
|
+
* \e S excluded) and the data for these coefficients read as 8-byte
|
|
268
|
+
* doubles. The coefficients are stored in column major order. The
|
|
269
|
+
* bytes in the stream should use little-endian ordering. IEEE floating
|
|
270
|
+
* point is assumed for the coefficients.
|
|
271
|
+
**********************************************************************/
|
|
272
|
+
static void readcoeffs(std::istream& stream, int& N, int& M,
|
|
273
|
+
std::vector<real>& C, std::vector<real>& S);
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Evaluate a spherical harmonic sum and its gradient.
|
|
278
|
+
*
|
|
279
|
+
* @tparam gradp should the gradient be calculated.
|
|
280
|
+
* @tparam norm the normalization for the associated Legendre polynomials.
|
|
281
|
+
* @tparam L the number of terms in the coefficients.
|
|
282
|
+
* @param[in] c an array of coeff objects.
|
|
283
|
+
* @param[in] f array of coefficient multipliers. f[0] should be 1.
|
|
284
|
+
* @param[in] x the \e x component of the cartesian position.
|
|
285
|
+
* @param[in] y the \e y component of the cartesian position.
|
|
286
|
+
* @param[in] z the \e z component of the cartesian position.
|
|
287
|
+
* @param[in] a the normalizing radius.
|
|
288
|
+
* @param[out] gradx the \e x component of the gradient.
|
|
289
|
+
* @param[out] grady the \e y component of the gradient.
|
|
290
|
+
* @param[out] gradz the \e z component of the gradient.
|
|
291
|
+
* @result the spherical harmonic sum.
|
|
292
|
+
*
|
|
293
|
+
* See the SphericalHarmonic class for the definition of the sum. The
|
|
294
|
+
* coefficients used by this function are, for example, c[0].Cv + f[1] *
|
|
295
|
+
* c[1].Cv + ... + f[L−1] * c[L−1].Cv. (Note that f[0] is \e
|
|
296
|
+
* not used.) The upper limits on the sum are determined by c[0].nmx() and
|
|
297
|
+
* c[0].mmx(); these limits apply to \e all the components of the
|
|
298
|
+
* coefficients. The parameters \e gradp, \e norm, and \e L are template
|
|
299
|
+
* parameters, to allow more optimization to be done at compile time.
|
|
300
|
+
*
|
|
301
|
+
* Clenshaw summation is used which permits the evaluation of the sum
|
|
302
|
+
* without the need to allocate temporary arrays. Thus this function never
|
|
303
|
+
* throws an exception.
|
|
304
|
+
**********************************************************************/
|
|
305
|
+
template<bool gradp, normalization norm, int L>
|
|
306
|
+
static Math::real Value(const coeff c[], const real f[],
|
|
307
|
+
real x, real y, real z, real a,
|
|
308
|
+
real& gradx, real& grady, real& gradz);
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Create a CircularEngine object
|
|
312
|
+
*
|
|
313
|
+
* @tparam gradp should the gradient be calculated.
|
|
314
|
+
* @tparam norm the normalization for the associated Legendre polynomials.
|
|
315
|
+
* @tparam L the number of terms in the coefficients.
|
|
316
|
+
* @param[in] c an array of coeff objects.
|
|
317
|
+
* @param[in] f array of coefficient multipliers. f[0] should be 1.
|
|
318
|
+
* @param[in] p the radius of the circle = sqrt(<i>x</i><sup>2</sup> +
|
|
319
|
+
* <i>y</i><sup>2</sup>).
|
|
320
|
+
* @param[in] z the height of the circle.
|
|
321
|
+
* @param[in] a the normalizing radius.
|
|
322
|
+
* @exception std::bad_alloc if the memory for the CircularEngine can't be
|
|
323
|
+
* allocated.
|
|
324
|
+
* @result the CircularEngine object.
|
|
325
|
+
*
|
|
326
|
+
* If you need to evaluate the spherical harmonic sum for several points
|
|
327
|
+
* with constant \e f, \e p = sqrt(<i>x</i><sup>2</sup> +
|
|
328
|
+
* <i>y</i><sup>2</sup>), \e z, and \e a, it is more efficient to construct
|
|
329
|
+
* call SphericalEngine::Circle to give a CircularEngine object and then
|
|
330
|
+
* call CircularEngine::operator()() with arguments <i>x</i>/\e p and
|
|
331
|
+
* <i>y</i>/\e p.
|
|
332
|
+
**********************************************************************/
|
|
333
|
+
template<bool gradp, normalization norm, int L>
|
|
334
|
+
static CircularEngine Circle(const coeff c[], const real f[],
|
|
335
|
+
real p, real z, real a);
|
|
336
|
+
/**
|
|
337
|
+
* Check that the static table of square roots is big enough and enlarge it
|
|
338
|
+
* if necessary.
|
|
339
|
+
*
|
|
340
|
+
* @param[in] N the maximum degree to be used in SphericalEngine.
|
|
341
|
+
* @exception std::bad_alloc if the memory for the square root table can't
|
|
342
|
+
* be allocated.
|
|
343
|
+
*
|
|
344
|
+
* Typically, there's no need for an end-user to call this routine, because
|
|
345
|
+
* the constructors for SphericalEngine::coeff do so. However, since this
|
|
346
|
+
* updates a static table, there's a possible race condition in a
|
|
347
|
+
* multi-threaded environment. Because this routine does nothing if the
|
|
348
|
+
* table is already large enough, one way to avoid race conditions is to
|
|
349
|
+
* call this routine at program start up (when it's still single threaded),
|
|
350
|
+
* supplying the largest degree that your program will use. E.g., \code
|
|
351
|
+
GeographicLib::SphericalEngine::RootTable(2190);
|
|
352
|
+
\endcode
|
|
353
|
+
* suffices to accommodate extant magnetic and gravity models.
|
|
354
|
+
**********************************************************************/
|
|
355
|
+
static void RootTable(int N);
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Clear the static table of square roots and release the memory. Call
|
|
359
|
+
* this only when you are sure you no longer will be using SphericalEngine.
|
|
360
|
+
* Your program will crash if you call SphericalEngine after calling this
|
|
361
|
+
* routine. <b>It's safest not to call this routine at all.</b> (The space
|
|
362
|
+
* used by the table is modest.)
|
|
363
|
+
**********************************************************************/
|
|
364
|
+
static void ClearRootTable() {
|
|
365
|
+
std::vector<real> temp(0);
|
|
366
|
+
root_.swap(temp);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
} // namespace GeographicLib
|
|
371
|
+
|
|
372
|
+
#if defined(_MSC_VER)
|
|
373
|
+
# pragma warning (pop)
|
|
374
|
+
#endif
|
|
375
|
+
|
|
376
|
+
#endif // GEOGRAPHICLIB_SPHERICALENGINE_HPP
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* \file SphericalHarmonic.hpp
|
|
3
|
+
* \brief Header for GeographicLib::SphericalHarmonic class
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) Charles Karney (2011) <charles@karney.com> and licensed under
|
|
6
|
+
* the MIT/X11 License. For more information, see
|
|
7
|
+
* http://geographiclib.sourceforge.net/
|
|
8
|
+
**********************************************************************/
|
|
9
|
+
|
|
10
|
+
#if !defined(GEOGRAPHICLIB_SPHERICALHARMONIC_HPP)
|
|
11
|
+
#define GEOGRAPHICLIB_SPHERICALHARMONIC_HPP 1
|
|
12
|
+
|
|
13
|
+
#include <vector>
|
|
14
|
+
#include <GeographicLib/Constants.hpp>
|
|
15
|
+
#include <GeographicLib/SphericalEngine.hpp>
|
|
16
|
+
#include <GeographicLib/CircularEngine.hpp>
|
|
17
|
+
|
|
18
|
+
namespace GeographicLib {
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* \brief Spherical harmonic series
|
|
22
|
+
*
|
|
23
|
+
* This class evaluates the spherical harmonic sum \verbatim
|
|
24
|
+
V(x, y, z) = sum(n = 0..N)[ q^(n+1) * sum(m = 0..n)[
|
|
25
|
+
(C[n,m] * cos(m*lambda) + S[n,m] * sin(m*lambda)) *
|
|
26
|
+
P[n,m](cos(theta)) ] ]
|
|
27
|
+
\endverbatim
|
|
28
|
+
* where
|
|
29
|
+
* - <i>p</i><sup>2</sup> = <i>x</i><sup>2</sup> + <i>y</i><sup>2</sup>,
|
|
30
|
+
* - <i>r</i><sup>2</sup> = <i>p</i><sup>2</sup> + <i>z</i><sup>2</sup>,
|
|
31
|
+
* - \e q = <i>a</i>/<i>r</i>,
|
|
32
|
+
* - θ = atan2(\e p, \e z) = the spherical \e colatitude,
|
|
33
|
+
* - λ = atan2(\e y, \e x) = the longitude.
|
|
34
|
+
* - P<sub><i>nm</i></sub>(\e t) is the associated Legendre polynomial of
|
|
35
|
+
* degree \e n and order \e m.
|
|
36
|
+
*
|
|
37
|
+
* Two normalizations are supported for P<sub><i>nm</i></sub>
|
|
38
|
+
* - fully normalized denoted by SphericalHarmonic::FULL.
|
|
39
|
+
* - Schmidt semi-normalized denoted by SphericalHarmonic::SCHMIDT.
|
|
40
|
+
*
|
|
41
|
+
* Clenshaw summation is used for the sums over both \e n and \e m. This
|
|
42
|
+
* allows the computation to be carried out without the need for any
|
|
43
|
+
* temporary arrays. See SphericalEngine.cpp for more information on the
|
|
44
|
+
* implementation.
|
|
45
|
+
*
|
|
46
|
+
* References:
|
|
47
|
+
* - C. W. Clenshaw,
|
|
48
|
+
* <a href="https://dx.doi.org/10.1090/S0025-5718-1955-0071856-0">
|
|
49
|
+
* A note on the summation of Chebyshev series</a>,
|
|
50
|
+
* %Math. Tables Aids Comput. 9(51), 118--120 (1955).
|
|
51
|
+
* - R. E. Deakin, Derivatives of the earth's potentials, Geomatics
|
|
52
|
+
* Research Australasia 68, 31--60, (June 1998).
|
|
53
|
+
* - W. A. Heiskanen and H. Moritz, Physical Geodesy, (Freeman, San
|
|
54
|
+
* Francisco, 1967). (See Sec. 1-14, for a definition of Pbar.)
|
|
55
|
+
* - S. A. Holmes and W. E. Featherstone,
|
|
56
|
+
* <a href="https://dx.doi.org/10.1007/s00190-002-0216-2">
|
|
57
|
+
* A unified approach to the Clenshaw summation and the recursive
|
|
58
|
+
* computation of very high degree and order normalised associated Legendre
|
|
59
|
+
* functions</a>, J. Geodesy 76(5), 279--299 (2002).
|
|
60
|
+
* - C. C. Tscherning and K. Poder,
|
|
61
|
+
* <a href="http://cct.gfy.ku.dk/publ_cct/cct80.pdf">
|
|
62
|
+
* Some geodetic applications of Clenshaw summation</a>,
|
|
63
|
+
* Boll. Geod. Sci. Aff. 41(4), 349--375 (1982).
|
|
64
|
+
*
|
|
65
|
+
* Example of use:
|
|
66
|
+
* \include example-SphericalHarmonic.cpp
|
|
67
|
+
**********************************************************************/
|
|
68
|
+
|
|
69
|
+
class GEOGRAPHICLIB_EXPORT SphericalHarmonic {
|
|
70
|
+
public:
|
|
71
|
+
/**
|
|
72
|
+
* Supported normalizations for the associated Legendre polynomials.
|
|
73
|
+
**********************************************************************/
|
|
74
|
+
enum normalization {
|
|
75
|
+
/**
|
|
76
|
+
* Fully normalized associated Legendre polynomials.
|
|
77
|
+
*
|
|
78
|
+
* These are defined by
|
|
79
|
+
* <i>P</i><sub><i>nm</i></sub><sup>full</sup>(\e z)
|
|
80
|
+
* = (−1)<sup><i>m</i></sup>
|
|
81
|
+
* sqrt(\e k (2\e n + 1) (\e n − \e m)! / (\e n + \e m)!)
|
|
82
|
+
* <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z), where
|
|
83
|
+
* <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z) is Ferrers
|
|
84
|
+
* function (also known as the Legendre function on the cut or the
|
|
85
|
+
* associated Legendre polynomial) http://dlmf.nist.gov/14.7.E10 and \e k
|
|
86
|
+
* = 1 for \e m = 0 and \e k = 2 otherwise.
|
|
87
|
+
*
|
|
88
|
+
* The mean squared value of
|
|
89
|
+
* <i>P</i><sub><i>nm</i></sub><sup>full</sup>(cosθ)
|
|
90
|
+
* cos(<i>m</i>λ) and
|
|
91
|
+
* <i>P</i><sub><i>nm</i></sub><sup>full</sup>(cosθ)
|
|
92
|
+
* sin(<i>m</i>λ) over the sphere is 1.
|
|
93
|
+
*
|
|
94
|
+
* @hideinitializer
|
|
95
|
+
**********************************************************************/
|
|
96
|
+
FULL = SphericalEngine::FULL,
|
|
97
|
+
/**
|
|
98
|
+
* Schmidt semi-normalized associated Legendre polynomials.
|
|
99
|
+
*
|
|
100
|
+
* These are defined by
|
|
101
|
+
* <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(\e z)
|
|
102
|
+
* = (−1)<sup><i>m</i></sup>
|
|
103
|
+
* sqrt(\e k (\e n − \e m)! / (\e n + \e m)!)
|
|
104
|
+
* <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z), where
|
|
105
|
+
* <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z) is Ferrers
|
|
106
|
+
* function (also known as the Legendre function on the cut or the
|
|
107
|
+
* associated Legendre polynomial) http://dlmf.nist.gov/14.7.E10 and \e k
|
|
108
|
+
* = 1 for \e m = 0 and \e k = 2 otherwise.
|
|
109
|
+
*
|
|
110
|
+
* The mean squared value of
|
|
111
|
+
* <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(cosθ)
|
|
112
|
+
* cos(<i>m</i>λ) and
|
|
113
|
+
* <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(cosθ)
|
|
114
|
+
* sin(<i>m</i>λ) over the sphere is 1/(2\e n + 1).
|
|
115
|
+
*
|
|
116
|
+
* @hideinitializer
|
|
117
|
+
**********************************************************************/
|
|
118
|
+
SCHMIDT = SphericalEngine::SCHMIDT,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
private:
|
|
122
|
+
typedef Math::real real;
|
|
123
|
+
SphericalEngine::coeff _c[1];
|
|
124
|
+
real _a;
|
|
125
|
+
unsigned _norm;
|
|
126
|
+
|
|
127
|
+
public:
|
|
128
|
+
/**
|
|
129
|
+
* Constructor with a full set of coefficients specified.
|
|
130
|
+
*
|
|
131
|
+
* @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
|
|
132
|
+
* @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
|
|
133
|
+
* @param[in] N the maximum degree and order of the sum
|
|
134
|
+
* @param[in] a the reference radius appearing in the definition of the
|
|
135
|
+
* sum.
|
|
136
|
+
* @param[in] norm the normalization for the associated Legendre
|
|
137
|
+
* polynomials, either SphericalHarmonic::FULL (the default) or
|
|
138
|
+
* SphericalHarmonic::SCHMIDT.
|
|
139
|
+
* @exception GeographicErr if \e N does not satisfy \e N ≥ −1.
|
|
140
|
+
* @exception GeographicErr if \e C or \e S is not big enough to hold the
|
|
141
|
+
* coefficients.
|
|
142
|
+
*
|
|
143
|
+
* The coefficients <i>C</i><sub><i>nm</i></sub> and
|
|
144
|
+
* <i>S</i><sub><i>nm</i></sub> are stored in the one-dimensional vectors
|
|
145
|
+
* \e C and \e S which must contain (\e N + 1)(\e N + 2)/2 and \e N (\e N +
|
|
146
|
+
* 1)/2 elements, respectively, stored in "column-major" order. Thus for
|
|
147
|
+
* \e N = 3, the order would be:
|
|
148
|
+
* <i>C</i><sub>00</sub>,
|
|
149
|
+
* <i>C</i><sub>10</sub>,
|
|
150
|
+
* <i>C</i><sub>20</sub>,
|
|
151
|
+
* <i>C</i><sub>30</sub>,
|
|
152
|
+
* <i>C</i><sub>11</sub>,
|
|
153
|
+
* <i>C</i><sub>21</sub>,
|
|
154
|
+
* <i>C</i><sub>31</sub>,
|
|
155
|
+
* <i>C</i><sub>22</sub>,
|
|
156
|
+
* <i>C</i><sub>32</sub>,
|
|
157
|
+
* <i>C</i><sub>33</sub>.
|
|
158
|
+
* In general the (\e n,\e m) element is at index \e m \e N − \e m
|
|
159
|
+
* (\e m − 1)/2 + \e n. The layout of \e S is the same except that
|
|
160
|
+
* the first column is omitted (since the \e m = 0 terms never contribute
|
|
161
|
+
* to the sum) and the 0th element is <i>S</i><sub>11</sub>
|
|
162
|
+
*
|
|
163
|
+
* The class stores <i>pointers</i> to the first elements of \e C and \e S.
|
|
164
|
+
* These arrays should not be altered or destroyed during the lifetime of a
|
|
165
|
+
* SphericalHarmonic object.
|
|
166
|
+
**********************************************************************/
|
|
167
|
+
SphericalHarmonic(const std::vector<real>& C,
|
|
168
|
+
const std::vector<real>& S,
|
|
169
|
+
int N, real a, unsigned norm = FULL)
|
|
170
|
+
: _a(a)
|
|
171
|
+
, _norm(norm)
|
|
172
|
+
{ _c[0] = SphericalEngine::coeff(C, S, N); }
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Constructor with a subset of coefficients specified.
|
|
176
|
+
*
|
|
177
|
+
* @param[in] C the coefficients <i>C</i><sub><i>nm</i></sub>.
|
|
178
|
+
* @param[in] S the coefficients <i>S</i><sub><i>nm</i></sub>.
|
|
179
|
+
* @param[in] N the degree used to determine the layout of \e C and \e S.
|
|
180
|
+
* @param[in] nmx the maximum degree used in the sum. The sum over \e n is
|
|
181
|
+
* from 0 thru \e nmx.
|
|
182
|
+
* @param[in] mmx the maximum order used in the sum. The sum over \e m is
|
|
183
|
+
* from 0 thru min(\e n, \e mmx).
|
|
184
|
+
* @param[in] a the reference radius appearing in the definition of the
|
|
185
|
+
* sum.
|
|
186
|
+
* @param[in] norm the normalization for the associated Legendre
|
|
187
|
+
* polynomials, either SphericalHarmonic::FULL (the default) or
|
|
188
|
+
* SphericalHarmonic::SCHMIDT.
|
|
189
|
+
* @exception GeographicErr if \e N, \e nmx, and \e mmx do not satisfy
|
|
190
|
+
* \e N ≥ \e nmx ≥ \e mmx ≥ −1.
|
|
191
|
+
* @exception GeographicErr if \e C or \e S is not big enough to hold the
|
|
192
|
+
* coefficients.
|
|
193
|
+
*
|
|
194
|
+
* The class stores <i>pointers</i> to the first elements of \e C and \e S.
|
|
195
|
+
* These arrays should not be altered or destroyed during the lifetime of a
|
|
196
|
+
* SphericalHarmonic object.
|
|
197
|
+
**********************************************************************/
|
|
198
|
+
SphericalHarmonic(const std::vector<real>& C,
|
|
199
|
+
const std::vector<real>& S,
|
|
200
|
+
int N, int nmx, int mmx,
|
|
201
|
+
real a, unsigned norm = FULL)
|
|
202
|
+
: _a(a)
|
|
203
|
+
, _norm(norm)
|
|
204
|
+
{ _c[0] = SphericalEngine::coeff(C, S, N, nmx, mmx); }
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* A default constructor so that the object can be created when the
|
|
208
|
+
* constructor for another object is initialized. This default object can
|
|
209
|
+
* then be reset with the default copy assignment operator.
|
|
210
|
+
**********************************************************************/
|
|
211
|
+
SphericalHarmonic() {}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Compute the spherical harmonic sum.
|
|
215
|
+
*
|
|
216
|
+
* @param[in] x cartesian coordinate.
|
|
217
|
+
* @param[in] y cartesian coordinate.
|
|
218
|
+
* @param[in] z cartesian coordinate.
|
|
219
|
+
* @return \e V the spherical harmonic sum.
|
|
220
|
+
*
|
|
221
|
+
* This routine requires constant memory and thus never throws an
|
|
222
|
+
* exception.
|
|
223
|
+
**********************************************************************/
|
|
224
|
+
Math::real operator()(real x, real y, real z) const {
|
|
225
|
+
real f[] = {1};
|
|
226
|
+
real v = 0;
|
|
227
|
+
real dummy;
|
|
228
|
+
switch (_norm) {
|
|
229
|
+
case FULL:
|
|
230
|
+
v = SphericalEngine::Value<false, SphericalEngine::FULL, 1>
|
|
231
|
+
(_c, f, x, y, z, _a, dummy, dummy, dummy);
|
|
232
|
+
break;
|
|
233
|
+
case SCHMIDT:
|
|
234
|
+
v = SphericalEngine::Value<false, SphericalEngine::SCHMIDT, 1>
|
|
235
|
+
(_c, f, x, y, z, _a, dummy, dummy, dummy);
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
238
|
+
return v;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Compute a spherical harmonic sum and its gradient.
|
|
243
|
+
*
|
|
244
|
+
* @param[in] x cartesian coordinate.
|
|
245
|
+
* @param[in] y cartesian coordinate.
|
|
246
|
+
* @param[in] z cartesian coordinate.
|
|
247
|
+
* @param[out] gradx \e x component of the gradient
|
|
248
|
+
* @param[out] grady \e y component of the gradient
|
|
249
|
+
* @param[out] gradz \e z component of the gradient
|
|
250
|
+
* @return \e V the spherical harmonic sum.
|
|
251
|
+
*
|
|
252
|
+
* This is the same as the previous function, except that the components of
|
|
253
|
+
* the gradients of the sum in the \e x, \e y, and \e z directions are
|
|
254
|
+
* computed. This routine requires constant memory and thus never throws
|
|
255
|
+
* an exception.
|
|
256
|
+
**********************************************************************/
|
|
257
|
+
Math::real operator()(real x, real y, real z,
|
|
258
|
+
real& gradx, real& grady, real& gradz) const {
|
|
259
|
+
real f[] = {1};
|
|
260
|
+
real v = 0;
|
|
261
|
+
switch (_norm) {
|
|
262
|
+
case FULL:
|
|
263
|
+
v = SphericalEngine::Value<true, SphericalEngine::FULL, 1>
|
|
264
|
+
(_c, f, x, y, z, _a, gradx, grady, gradz);
|
|
265
|
+
break;
|
|
266
|
+
case SCHMIDT:
|
|
267
|
+
v = SphericalEngine::Value<true, SphericalEngine::SCHMIDT, 1>
|
|
268
|
+
(_c, f, x, y, z, _a, gradx, grady, gradz);
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
return v;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Create a CircularEngine to allow the efficient evaluation of several
|
|
276
|
+
* points on a circle of latitude.
|
|
277
|
+
*
|
|
278
|
+
* @param[in] p the radius of the circle.
|
|
279
|
+
* @param[in] z the height of the circle above the equatorial plane.
|
|
280
|
+
* @param[in] gradp if true the returned object will be able to compute the
|
|
281
|
+
* gradient of the sum.
|
|
282
|
+
* @exception std::bad_alloc if the memory for the CircularEngine can't be
|
|
283
|
+
* allocated.
|
|
284
|
+
* @return the CircularEngine object.
|
|
285
|
+
*
|
|
286
|
+
* SphericalHarmonic::operator()() exchanges the order of the sums in the
|
|
287
|
+
* definition, i.e., ∑<sub><i>n</i> = 0..<i>N</i></sub>
|
|
288
|
+
* ∑<sub><i>m</i> = 0..<i>n</i></sub> becomes ∑<sub><i>m</i> =
|
|
289
|
+
* 0..<i>N</i></sub> ∑<sub><i>n</i> = <i>m</i>..<i>N</i></sub>.
|
|
290
|
+
* SphericalHarmonic::Circle performs the inner sum over degree \e n (which
|
|
291
|
+
* entails about <i>N</i><sup>2</sup> operations). Calling
|
|
292
|
+
* CircularEngine::operator()() on the returned object performs the outer
|
|
293
|
+
* sum over the order \e m (about \e N operations).
|
|
294
|
+
*
|
|
295
|
+
* Here's an example of computing the spherical sum at a sequence of
|
|
296
|
+
* longitudes without using a CircularEngine object \code
|
|
297
|
+
SphericalHarmonic h(...); // Create the SphericalHarmonic object
|
|
298
|
+
double r = 2, lat = 33, lon0 = 44, dlon = 0.01;
|
|
299
|
+
double
|
|
300
|
+
phi = lat * Math::degree<double>(),
|
|
301
|
+
z = r * sin(phi), p = r * cos(phi);
|
|
302
|
+
for (int i = 0; i <= 100; ++i) {
|
|
303
|
+
real
|
|
304
|
+
lon = lon0 + i * dlon,
|
|
305
|
+
lam = lon * Math::degree<double>();
|
|
306
|
+
std::cout << lon << " " << h(p * cos(lam), p * sin(lam), z) << "\n";
|
|
307
|
+
}
|
|
308
|
+
\endcode
|
|
309
|
+
* Here is the same calculation done using a CircularEngine object. This
|
|
310
|
+
* will be about <i>N</i>/2 times faster. \code
|
|
311
|
+
SphericalHarmonic h(...); // Create the SphericalHarmonic object
|
|
312
|
+
double r = 2, lat = 33, lon0 = 44, dlon = 0.01;
|
|
313
|
+
double
|
|
314
|
+
phi = lat * Math::degree<double>(),
|
|
315
|
+
z = r * sin(phi), p = r * cos(phi);
|
|
316
|
+
CircularEngine c(h(p, z, false)); // Create the CircularEngine object
|
|
317
|
+
for (int i = 0; i <= 100; ++i) {
|
|
318
|
+
real
|
|
319
|
+
lon = lon0 + i * dlon;
|
|
320
|
+
std::cout << lon << " " << c(lon) << "\n";
|
|
321
|
+
}
|
|
322
|
+
\endcode
|
|
323
|
+
**********************************************************************/
|
|
324
|
+
CircularEngine Circle(real p, real z, bool gradp) const {
|
|
325
|
+
real f[] = {1};
|
|
326
|
+
switch (_norm) {
|
|
327
|
+
case FULL:
|
|
328
|
+
return gradp ?
|
|
329
|
+
SphericalEngine::Circle<true, SphericalEngine::FULL, 1>
|
|
330
|
+
(_c, f, p, z, _a) :
|
|
331
|
+
SphericalEngine::Circle<false, SphericalEngine::FULL, 1>
|
|
332
|
+
(_c, f, p, z, _a);
|
|
333
|
+
break;
|
|
334
|
+
case SCHMIDT:
|
|
335
|
+
default: // To avoid compiler warnings
|
|
336
|
+
return gradp ?
|
|
337
|
+
SphericalEngine::Circle<true, SphericalEngine::SCHMIDT, 1>
|
|
338
|
+
(_c, f, p, z, _a) :
|
|
339
|
+
SphericalEngine::Circle<false, SphericalEngine::SCHMIDT, 1>
|
|
340
|
+
(_c, f, p, z, _a);
|
|
341
|
+
break;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* @return the zeroth SphericalEngine::coeff object.
|
|
347
|
+
**********************************************************************/
|
|
348
|
+
const SphericalEngine::coeff& Coefficients() const
|
|
349
|
+
{ return _c[0]; }
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
} // namespace GeographicLib
|
|
353
|
+
|
|
354
|
+
#endif // GEOGRAPHICLIB_SPHERICALHARMONIC_HPP
|