00001 #pragma once 00002 /** 00003 * \file NETGeographicLib/SphericalHarmonic.h 00004 * \brief Header for NETGeographicLib::SphericalHarmonic class 00005 * 00006 * NETGeographicLib is copyright (c) Scott Heiman (2013) 00007 * GeographicLib is Copyright (c) Charles Karney (2010-2012) 00008 * <charles@karney.com> and licensed under the MIT/X11 License. 00009 * For more information, see 00010 * http://geographiclib.sourceforge.net/ 00011 **********************************************************************/ 00012 00013 namespace NETGeographicLib 00014 { 00015 ref class CircularEngine; 00016 ref class SphericalCoefficients; 00017 /** 00018 * \brief .NET wrapper for GeographicLib::SphericalHarmonic. 00019 * 00020 * This class allows .NET applications to access GeographicLib::SphericalHarmonic. 00021 * 00022 * This class evaluates the spherical harmonic sum \verbatim 00023 V(x, y, z) = sum(n = 0..N)[ q^(n+1) * sum(m = 0..n)[ 00024 (C[n,m] * cos(m*lambda) + S[n,m] * sin(m*lambda)) * 00025 P[n,m](cos(theta)) ] ] 00026 \endverbatim 00027 * where 00028 * - <i>p</i><sup>2</sup> = <i>x</i><sup>2</sup> + <i>y</i><sup>2</sup>, 00029 * - <i>r</i><sup>2</sup> = <i>p</i><sup>2</sup> + <i>z</i><sup>2</sup>, 00030 * - \e q = <i>a</i>/<i>r</i>, 00031 * - θ = atan2(\e p, \e z) = the spherical \e colatitude, 00032 * - λ = atan2(\e y, \e x) = the longitude. 00033 * - P<sub>\e nm</sub>(\e t) is the associated Legendre polynomial of degree 00034 * \e n and order \e m. 00035 * 00036 * Two normalizations are supported for P<sub>\e nm</sub> 00037 * - fully normalized denoted by SphericalHarmonic::FULL. 00038 * - Schmidt semi-normalized denoted by SphericalHarmonic::SCHMIDT. 00039 * 00040 * Clenshaw summation is used for the sums over both \e n and \e m. This 00041 * allows the computation to be carried out without the need for any 00042 * temporary arrays. See GeographicLib::SphericalEngine.cpp for more 00043 * information on the implementation. 00044 * 00045 * References: 00046 * - C. W. Clenshaw, A note on the summation of Chebyshev series, 00047 * %Math. Tables Aids Comput. 9(51), 118--120 (1955). 00048 * - R. E. Deakin, Derivatives of the earth's potentials, Geomatics 00049 * Research Australasia 68, 31--60, (June 1998). 00050 * - W. A. Heiskanen and H. Moritz, Physical Geodesy, (Freeman, San 00051 * Francisco, 1967). (See Sec. 1-14, for a definition of Pbar.) 00052 * - S. A. Holmes and W. E. Featherstone, A unified approach to the Clenshaw 00053 * summation and the recursive computation of very high degree and order 00054 * normalised associated Legendre functions, J. Geodesy 76(5), 00055 * 279--299 (2002). 00056 * - C. C. Tscherning and K. Poder, Some geodetic applications of Clenshaw 00057 * summation, Boll. Geod. Sci. Aff. 41(4), 349--375 (1982). 00058 * 00059 * C# Example: 00060 * \include example-SphericalHarmonic.cs 00061 * Managed C++ Example: 00062 * \include example-SphericalHarmonic.cpp 00063 * Visual Basic Example: 00064 * \include example-SphericalHarmonic.vb 00065 * 00066 * <B>INTERFACE DIFFERENCES:</B><BR> 00067 * This class replaces the GeographicLib::SphericalHarmonic::operator() with 00068 * HarmonicSum. 00069 * 00070 * Coefficients returns a SphericalCoefficients object. 00071 * 00072 * The Normalization parameter in the constructors is passed in as an 00073 * enumeration rather than an unsigned. 00074 **********************************************************************/ 00075 public ref class SphericalHarmonic 00076 { 00077 private: 00078 // a pointer to the unmanaged GeographicLib::SphericalHarmonic 00079 const GeographicLib::SphericalHarmonic* m_pSphericalHarmonic; 00080 // the finalizer frees the unmanaged memory when the object is destroyed. 00081 !SphericalHarmonic(); 00082 // local containers for the cosine and sine coefficients. The 00083 // GeographicLib::SphericalEngine::coeffs class uses a 00084 // std::vector::iterator to access these vectors. 00085 std::vector<double> *m_C, *m_S; 00086 public: 00087 /** 00088 * Supported normalizations for the associated Legendre polynomials. 00089 **********************************************************************/ 00090 enum class Normalization { 00091 /** 00092 * Fully normalized associated Legendre polynomials. 00093 * 00094 * These are defined by <i>P</i><sub><i>nm</i></sub><sup>full</sup>(\e z) 00095 * = (−1)<sup><i>m</i></sup> sqrt(\e k (2\e n + 1) (\e n − \e 00096 * m)! / (\e n + \e m)!) 00097 * <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z), where 00098 * <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z) is Ferrers 00099 * function (also known as the Legendre function on the cut or the 00100 * associated Legendre polynomial) http://dlmf.nist.gov/14.7.E10 and \e k 00101 * = 1 for \e m = 0 and \e k = 2 otherwise. 00102 * 00103 * The mean squared value of 00104 * <i>P</i><sub><i>nm</i></sub><sup>full</sup>(cosθ) 00105 * cos(<i>m</i>λ) and 00106 * <i>P</i><sub><i>nm</i></sub><sup>full</sup>(cosθ) 00107 * sin(<i>m</i>λ) over the sphere is 1. 00108 * 00109 * @hideinitializer 00110 **********************************************************************/ 00111 FULL = GeographicLib::SphericalEngine::FULL, 00112 /** 00113 * Schmidt semi-normalized associated Legendre polynomials. 00114 * 00115 * These are defined by <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(\e 00116 * z) = (−1)<sup><i>m</i></sup> sqrt(\e k (\e n − \e m)! / 00117 * (\e n + \e m)!) <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z), 00118 * where <b>P</b><sub><i>n</i></sub><sup><i>m</i></sup>(\e z) is Ferrers 00119 * function (also known as the Legendre function on the cut or the 00120 * associated Legendre polynomial) http://dlmf.nist.gov/14.7.E10 and \e k 00121 * = 1 for \e m = 0 and \e k = 2 otherwise. 00122 * 00123 * The mean squared value of 00124 * <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(cosθ) 00125 * cos(<i>m</i>λ) and 00126 * <i>P</i><sub><i>nm</i></sub><sup>schmidt</sup>(cosθ) 00127 * sin(<i>m</i>λ) over the sphere is 1/(2\e n + 1). 00128 * 00129 * @hideinitializer 00130 **********************************************************************/ 00131 SCHMIDT = GeographicLib::SphericalEngine::SCHMIDT, 00132 }; 00133 00134 /** 00135 * Constructor with a full set of coefficients specified. 00136 * 00137 * @param[in] C the coefficients \e C<sub>\e nm</sub>. 00138 * @param[in] S the coefficients \e S<sub>\e nm</sub>. 00139 * @param[in] N the maximum degree and order of the sum 00140 * @param[in] a the reference radius appearing in the definition of the 00141 * sum. 00142 * @param[in] norm the normalization for the associated Legendre 00143 * polynomials, either SphericalHarmonic::full (the default) or 00144 * SphericalHarmonic::schmidt. 00145 * @exception GeographicErr if \e N does not satisfy \e N ≥ −1. 00146 * @exception GeographicErr if \e C or \e S is not big enough to hold the 00147 * coefficients. 00148 * 00149 * The coefficients \e C<sub>\e nm</sub> and \e S<sub>\e nm</sub> are 00150 * stored in the one-dimensional vectors \e C and \e S which must contain 00151 * (\e N + 1)(\e N + 2)/2 and N (\e N + 1)/2 elements, respectively, stored 00152 * in "column-major" order. Thus for \e N = 3, the order would be: 00153 * <i>C</i><sub>00</sub>, 00154 * <i>C</i><sub>10</sub>, 00155 * <i>C</i><sub>20</sub>, 00156 * <i>C</i><sub>30</sub>, 00157 * <i>C</i><sub>11</sub>, 00158 * <i>C</i><sub>21</sub>, 00159 * <i>C</i><sub>31</sub>, 00160 * <i>C</i><sub>22</sub>, 00161 * <i>C</i><sub>32</sub>, 00162 * <i>C</i><sub>33</sub>. 00163 * In general the (\e n,\e m) element is at index \e m \e N − \e m 00164 * (\e m − 1)/2 + \e n. The layout of \e S is the same except that 00165 * the first column is omitted (since the \e m = 0 terms never contribute 00166 * to the sum) and the 0th element is <i>S</i><sub>11</sub> 00167 * 00168 * The class stores <i>pointers</i> to the first elements of \e C and \e S. 00169 * These arrays should not be altered or destroyed during the lifetime of a 00170 * SphericalHarmonic object. 00171 **********************************************************************/ 00172 SphericalHarmonic(array<double>^ C, 00173 array<double>^ S, 00174 int N, double a, Normalization norm ); 00175 00176 /** 00177 * Constructor with a subset of coefficients specified. 00178 * 00179 * @param[in] C the coefficients \e C<sub>\e nm</sub>. 00180 * @param[in] S the coefficients \e S<sub>\e nm</sub>. 00181 * @param[in] N the degree used to determine the layout of \e C and \e S. 00182 * @param[in] nmx the maximum degree used in the sum. The sum over \e n is 00183 * from 0 thru \e nmx. 00184 * @param[in] mmx the maximum order used in the sum. The sum over \e m is 00185 * from 0 thru min(\e n, \e mmx). 00186 * @param[in] a the reference radius appearing in the definition of the 00187 * sum. 00188 * @param[in] norm the normalization for the associated Legendre 00189 * polynomials, either SphericalHarmonic::FULL (the default) or 00190 * SphericalHarmonic::SCHMIDT. 00191 * @exception GeographicErr if \e N, \e nmx, and \e mmx do not satisfy 00192 * \e N ≥ \e nmx ≥ \e mmx ≥ −1. 00193 * @exception GeographicErr if \e C or \e S is not big enough to hold the 00194 * coefficients. 00195 * 00196 * The class stores <i>pointers</i> to the first elements of \e C and \e S. 00197 * These arrays should not be altered or destroyed during the lifetime of a 00198 * SphericalHarmonic object. 00199 **********************************************************************/ 00200 SphericalHarmonic(array<double>^ C, 00201 array<double>^ S, 00202 int N, int nmx, int mmx, 00203 double a, Normalization norm); 00204 00205 /** 00206 * The destructor calls the finalizer 00207 **********************************************************************/ 00208 ~SphericalHarmonic() { this->!SphericalHarmonic(); } 00209 00210 /** 00211 * Compute the spherical harmonic sum. 00212 * 00213 * @param[in] x cartesian coordinate. 00214 * @param[in] y cartesian coordinate. 00215 * @param[in] z cartesian coordinate. 00216 * @return \e V the spherical harmonic sum. 00217 * 00218 * This routine requires constant memory and thus never throws an 00219 * exception. 00220 **********************************************************************/ 00221 double HarmonicSum(double x, double y, double z); 00222 00223 /** 00224 * Compute a spherical harmonic sum and its gradient. 00225 * 00226 * @param[in] x cartesian coordinate. 00227 * @param[in] y cartesian coordinate. 00228 * @param[in] z cartesian coordinate. 00229 * @param[out] gradx \e x component of the gradient 00230 * @param[out] grady \e y component of the gradient 00231 * @param[out] gradz \e z component of the gradient 00232 * @return \e V the spherical harmonic sum. 00233 * 00234 * This is the same as the previous function, except that the components of 00235 * the gradients of the sum in the \e x, \e y, and \e z directions are 00236 * computed. This routine requires constant memory and thus never throws 00237 * an exception. 00238 **********************************************************************/ 00239 double HarmonicSum(double x, double y, double z, 00240 [System::Runtime::InteropServices::Out] double% gradx, 00241 [System::Runtime::InteropServices::Out] double% grady, 00242 [System::Runtime::InteropServices::Out] double% gradz); 00243 00244 /** 00245 * Create a CircularEngine to allow the efficient evaluation of several 00246 * points on a circle of latitude. 00247 * 00248 * @param[in] p the radius of the circle. 00249 * @param[in] z the height of the circle above the equatorial plane. 00250 * @param[in] gradp if true the returned object will be able to compute the 00251 * gradient of the sum. 00252 * @exception std::bad_alloc if the memory for the CircularEngine can't be 00253 * allocated. 00254 * @return the CircularEngine object. 00255 * 00256 * SphericalHarmonic::operator()() exchanges the order of the sums in the 00257 * definition, i.e., ∑<sub>n = 0..N</sub> ∑<sub>m = 0..n</sub> 00258 * becomes ∑<sub>m = 0..N</sub> ∑<sub>n = m..N</sub>. 00259 * SphericalHarmonic::Circle performs the inner sum over degree \e n (which 00260 * entails about <i>N</i><sup>2</sup> operations). Calling 00261 * CircularEngine::operator()() on the returned object performs the outer 00262 * sum over the order \e m (about \e N operations). 00263 **********************************************************************/ 00264 CircularEngine^ Circle(double p, double z, bool gradp); 00265 00266 /** 00267 * @return the zeroth SphericalCoefficients object. 00268 **********************************************************************/ 00269 SphericalCoefficients^ Coefficients(); 00270 }; 00271 } // namespace NETGeographicLib