legendre.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2006                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
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  * Contrary to their definition, the Associated Legendre Polynomials presented here are
00034  * only computed for positive m values.
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; //Double factorial here
00083                         for (unsigned i = 1; i <= m; ++i)
00084                         {
00085                                 p_m_m *= fact * sin_theta; //raising sin_theta to the power of m/2
00086                                 fact += 2.0;
00087                         }
00088 
00089                         if (m&1) //odd m
00090                         {
00091                                 // Condon-Shortley Phase term
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                         std::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); //OK
00123                 else
00124                 {
00125                         ScalarType p_m_m = legendre_P_m_m(m, sin_theta); //OK
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); //OK
00130 
00131                         if (l == m + 1) return p_m_mplusone;
00132 
00133                         unsigned n = m + 1;
00134 
00135                         while(n < l)
00136                         {
00137                                 std::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]; //dynamic table
00174         ScalarType _x; //table is conserved only across consistent x invocations
00175         ScalarType _sin_theta;
00176 
00177         void generate(ScalarType cos_theta, ScalarType sin_theta)
00178         {
00179                 //generate all 'l's with m = 0
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 }} //vcg::math namespace
00240 
00241 #endif


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:32:46