sphericalHarmonics.h 4.82 KB
Newer Older
1 2 3 4 5 6 7
/*
 * spericalHarmonics.h
 *
 *  Created on: Oct 2, 2013
 *      Author: sauvage
 */

8 9
#ifndef __SPHERICALHARMONICS_H__
#define __SPHERICALHARMONICS_H__
10

11 12 13
#include <cassert>
#include <cmath>
#include <iostream>
14 15 16 17 18

#include <Eigen/Core>
#include <Eigen/Dense>
#include <Eigen/Cholesky>

19 20
namespace CGoGN
{
21

22 23 24 25 26 27
namespace Utils
{

template <typename Tscalar, typename Tcoef>
class SphericalHarmonics
{
28 29 30 31 32 33
private :
	static const int max_resolution = 10 ;                   // max possible resolution for any object of that class
	static int resolution ;                                  // actual resolution level
	static int nb_coefs ;                                    // number of coefs = (resolution + 1) * (resolution + 1)
	static unsigned long cpt_instances;                      // number of instances of the class
	static Tscalar K_tab [(max_resolution+1)*(max_resolution+1)];   // table containing constants K
34 35 36 37

//	static Tscalar F_tab [(max_resolution+1)*(max_resolution+1)];   // table for computing the functions : P or Y or y

	static Tscalar F_tab [32][(max_resolution+1)*(max_resolution+1)];
38 39 40 41 42 43 44 45 46 47 48

	Tcoef* coefs;                                            // table of coefficients

public :
	// construction, destruction and initialization
	SphericalHarmonics();
	SphericalHarmonics(SphericalHarmonics const &);
	~SphericalHarmonics();

	static void set_level(int res_level);
	static void set_nb_coefs (int nb_coefs);
49 50
	static int get_resolution () { return resolution; }
	static int get_nb_coefs () { return nb_coefs; }
51 52 53

	// evaluation

54 55 56
	static void set_eval_direction (Tscalar theta, Tscalar phi, unsigned int threadId = 0) ;       // fix the direction in which the SH has to be evaluated
	static void set_eval_direction (Tscalar x, Tscalar y, Tscalar z, unsigned int threadId = 0) ;  // fix the direction in which the SH has to be evaluated
	Tcoef evaluate (unsigned int threadId = 0) const;				  						    // evaluates at a fixed direction
57

58 59
	Tcoef evaluate_at (Tscalar theta, Tscalar phi, unsigned int threadId = 0) const;               // eval spherical coordinates
	Tcoef evaluate_at (Tscalar x, Tscalar y, Tscalar z, unsigned int threadId = 0) const;          // eval cartesian coordinates
60 61

	// I/O
62 63
	const Tcoef& get_coef (int l, int m) const {assert ((l>=0 && l <=resolution) || !" maybe you forgot to call set_level()"); assert (m >= (-l) && m <= l); return get_coef(index(l,m));}
	Tcoef& get_coef (int l, int m) {assert ((l>=0 && l <=resolution) || !" maybe you forgot to call set_level()"); assert (m >= (-l) && m <= l); return get_coef(index(l,m));}
64 65 66
	template <typename TS,typename TC> friend std::ostream & operator<< (std::ostream & os, const SphericalHarmonics<TS,TC> & sh);

	// operators
67 68 69 70 71 72 73 74 75 76 77
	void operator= (const SphericalHarmonics<Tscalar,Tcoef>&);
	void operator+= (const SphericalHarmonics<Tscalar,Tcoef>&);
	SphericalHarmonics<Tscalar,Tcoef> operator+ (const SphericalHarmonics<Tscalar,Tcoef>&) const;
	void operator-= (const SphericalHarmonics<Tscalar,Tcoef> &);
	SphericalHarmonics<Tscalar,Tcoef> operator- (const SphericalHarmonics<Tscalar,Tcoef>&) const;
	void operator*= (Tscalar);
	SphericalHarmonics<Tscalar,Tcoef> operator* (Tscalar) const;
	void operator/= (Tscalar);
	SphericalHarmonics<Tscalar,Tcoef> operator/ (Tscalar) const;

	std::string CGoGNnameOfType() const { return "SphericalHarmonics"; }
78 79 80 81 82

//	static void copy_K_tab (Tscalar tab[]) ; // obsolete, was used for shaders

	// fitting
	template <typename Tdirection, typename Tchannel>
83
	void fit_to_data(int n, Tdirection* t_theta, Tdirection* t_phi, Tchannel* t_R, Tchannel* t_G, Tchannel* t_B, double lambda, unsigned int threadId = 0);
84
	template <typename Tdirection, typename Tchannel>
85
	void fit_to_data(int n, Tdirection* t_x, Tdirection* t_y, Tdirection* t_z, Tchannel* t_R, Tchannel* t_G, Tchannel* t_B, double lambda, unsigned int threadId = 0);
86

87
private :
88
	static inline int index (int l, int m) { return l*(l+1)+m; }
89 90 91

	// evaluation :
	static void init_K_tab (); // compute the normalization constants K_l^m and store them into K_tab
92 93
	static void compute_P_tab (Tscalar t, unsigned int threadId); // Compute Legendre Polynomials at parameter t and store them in F_tab (only for m>=0)
	static void compute_y_tab (Tscalar phi, unsigned int threadId); // Compute the real basis functions y_l^m at (theta, phi) and store them in F_tab (compute_P_tab must have been called before)
94

95 96
	const Tcoef& get_coef (int i) const {assert ((i>=0 && i<nb_coefs ) || !" maybe you forgot to call set_level()"); return coefs[i];}
	Tcoef& get_coef (int i) {assert ((i>=0 && i<nb_coefs ) || !" maybe you forgot to call set_level()"); return coefs[i];}
97 98 99 100 101 102

	// fitting
	template <typename Tchannel>
	void fit_to_data(int n, Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic>& mM, Tchannel* t_R, Tchannel* t_G, Tchannel* t_B, double lambda);
};

103 104 105
} // namespace Utils

} // namespace CGoGN
106

107
#include "Utils/sphericalHarmonics.hpp"
108

109
#endif /* __SPHERICALHARMONICS_H__ */