00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __VCGLIB_LEGENDRE_H
00025 #define __VCGLIB_LEGENDRE_H
00026
00027 #include <vcg/math/base.h>
00028
00029 namespace vcg {
00030 namespace math {
00031
00032
00033
00034
00035
00036
00037 template <typename ScalarType>
00038 class Legendre {
00039
00040 protected :
00041
00045 static inline ScalarType legendre_next(unsigned l, ScalarType P_lm1, ScalarType P_lm2, ScalarType x)
00046 {
00047 return ((2 * l + 1) * x * P_lm1 - l * P_lm2) / (l + 1);
00048 }
00049
00054 static inline double legendre_next(unsigned l, unsigned m, ScalarType P_lm1, ScalarType P_lm2, ScalarType x)
00055 {
00056 return ((2 * l + 1) * x * P_lm1 - (l + m) * P_lm2) / (l + 1 - m);
00057 }
00058
00062 static inline double legendre_P_m_mplusone(unsigned m, ScalarType p_m_m, ScalarType x)
00063 {
00064 return x * (2.0 * m + 1.0) * p_m_m;
00065 }
00066
00076 static inline double legendre_P_m_m(unsigned m, ScalarType sin_theta)
00077 {
00078 ScalarType p_m_m = 1.0;
00079
00080 if (m > 0)
00081 {
00082 ScalarType fact = 1.0;
00083 for (unsigned i = 1; i <= m; ++i)
00084 {
00085 p_m_m *= fact * sin_theta;
00086 fact += 2.0;
00087 }
00088
00089 if (m&1)
00090 {
00091
00092 p_m_m *= -1;
00093 }
00094 }
00095
00096 return p_m_m;
00097 }
00098
00099 static inline double legendre_P_l(unsigned l, ScalarType x)
00100 {
00101 ScalarType p0 = 1;
00102 ScalarType p1 = x;
00103
00104 if (l == 0) return p0;
00105
00106 for (unsigned n = 1; n < l; ++n)
00107 {
00108 Swap(p0, p1);
00109 p1 = legendre_next(n, p0, p1, x);
00110 }
00111
00112 return p1;
00113 }
00114
00119 static inline double legendre_P_l_m(unsigned l, unsigned m, ScalarType cos_theta, ScalarType sin_theta)
00120 {
00121 if(m > l) return 0;
00122 if(m == 0) return legendre_P_l(l, cos_theta);
00123 else
00124 {
00125 ScalarType p_m_m = legendre_P_m_m(m, sin_theta);
00126
00127 if (l == m) return p_m_m;
00128
00129 ScalarType p_m_mplusone = legendre_P_m_mplusone(m, p_m_m, cos_theta);
00130
00131 if (l == m + 1) return p_m_mplusone;
00132
00133 unsigned n = m + 1;
00134
00135 while(n < l)
00136 {
00137 Swap(p_m_m, p_m_mplusone);
00138 p_m_mplusone = legendre_next(n, m, p_m_m, p_m_mplusone, cos_theta);
00139 ++n;
00140 }
00141
00142 return p_m_mplusone;
00143 }
00144 }
00145
00146 public :
00147
00148 static double Polynomial(unsigned l, ScalarType x)
00149 {
00150 assert (x <= 1 && x >= -1);
00151 return legendre_P_l(l, x);
00152 }
00153
00154 static double AssociatedPolynomial(unsigned l, unsigned m, ScalarType x)
00155 {
00156 assert (m <= l && x <= 1 && x >= -1);
00157 return legendre_P_l_m(l, m, x, Sqrt(1.0 - x * x) );
00158 }
00159
00160 static double AssociatedPolynomial(unsigned l, unsigned m, ScalarType cos_theta, ScalarType sin_theta)
00161 {
00162 assert (m <= l && cos_theta <= 1 && cos_theta >= -1 && sin_theta <= 1 && sin_theta >= -1);
00163 return legendre_P_l_m(l, m, cos_theta, Abs(sin_theta));
00164 }
00165 };
00166
00167
00168 template <typename ScalarType, int MAX_L>
00169 class DynamicLegendre : public Legendre<ScalarType>
00170 {
00171
00172 private:
00173 ScalarType matrix[MAX_L][MAX_L];
00174 ScalarType _x;
00175 ScalarType _sin_theta;
00176
00177 void generate(ScalarType cos_theta, ScalarType sin_theta)
00178 {
00179
00180
00181 matrix[0][0] = 1;
00182 matrix[0][1] = cos_theta;
00183
00184 for (unsigned l = 2; l < MAX_L; ++l)
00185 {
00186 matrix[0][l] = legendre_next(l-1, matrix[0][l-1], matrix[0][l-2], cos_theta);
00187 }
00188
00189 for(unsigned l = 1; l < MAX_L; ++l)
00190 {
00191 for (unsigned m = 1; m <= l; ++m)
00192 {
00193 if (l == m) matrix[m][m] = legendre_P_m_m(m, sin_theta);
00194 else if (l == m + 1) matrix[m][l] = legendre_P_m_mplusone(m, matrix[m][m], cos_theta);
00195 else{
00196 matrix[m][l] = legendre_next(l-1, m, matrix[m][l-1], matrix[m][l-2], cos_theta);
00197 }
00198 }
00199 }
00200
00201 _x = cos_theta;
00202 }
00203
00204 public :
00205
00206 DynamicLegendre() : _x(2), _sin_theta(2) {}
00207
00208 double AssociatedPolynomial(unsigned l, unsigned m, ScalarType x)
00209 {
00210 assert (m <= l && x <= 1 && x >= -1);
00211 if (x != _x){
00212 _sin_theta = Sqrt(1.0 - x * x);
00213 generate(x, _sin_theta);
00214 }
00215 return matrix[m][l];
00216 }
00217
00218 double AssociatedPolynomial(unsigned l, unsigned m, ScalarType cos_theta, ScalarType sin_theta)
00219 {
00220 assert (m <= l && cos_theta <= 1 && cos_theta >= -1 && sin_theta <= 1 && sin_theta >= -1);
00221 if (cos_theta != _x){
00222 _sin_theta = sin_theta;
00223 generate(cos_theta, _sin_theta);
00224 }
00225 return matrix[m][l];
00226 }
00227
00228 double Polynomial(unsigned l, ScalarType x)
00229 {
00230 assert (x <= 1 && x >= -1);
00231 if (x != _x){
00232 _sin_theta = Sqrt(1.0 - x * x);
00233 generate(x, _sin_theta);
00234 }
00235 return matrix[0][l];
00236 }
00237 };
00238
00239 }}
00240
00241 #endif