#ifndef STIM_SPH_HARMONICS #define STIM_SPH_HARMONICS #include #include #include #include #include #define WIRE_SCALE 1.001 namespace stim{ template class spharmonics{ public: std::vector C; //list of SH coefficients protected: unsigned int mcN; //number of Monte-Carlo samples //calculate the value of the SH basis function (l, m) at (theta, phi) //here, theta = [0, PI], phi = [0, 2*PI] double SH(int l, int m, double theta, double phi){ std::complex result = boost::math::spherical_harmonic(l, m, phi, theta); return result.imag() + result.real(); // return boost::math::spherical_harmonic_i(l, m, phi, theta); } unsigned int coeff_1d(unsigned int l, int m){ return pow(l + 1, 2) - (l - m) - 1; } public: spharmonics() { mcN = 0; } spharmonics(size_t c) : spharmonics() { resize(c); } void push(double c){ C.push_back(c); } void resize(unsigned int n){ C.resize(n); } void setc(unsigned int l, int m, T value){ unsigned int c = coeff_1d(l, m); C[c] = value; } void setc(unsigned int c, T value){ C[c] = value; } unsigned int getSize() const{ return C.size(); } std::vector getC() const{ return C; } /// Initialize Monte-Carlo sampling of a function using N spherical harmonics coefficients /// @param N is the number of spherical harmonics coefficients used to represent the user function void mcBegin(unsigned int coefficients){ C.resize(coefficients, 0); mcN = 0; } void mcBegin(unsigned int l, int m){ unsigned int c = pow(l + 1, 2) - (l - m); mcBegin(c); } void mcSample(double theta, double phi, double val){ int l, m; double sh; l = m = 0; for(unsigned int i = 0; i < C.size(); i++){ sh = SH(l, m, theta, phi); C[i] += sh * val; m++; //increment m //if we're in a new tier, increment l and set m = -l if(m > l){ l++; m = -l; } } //end for all coefficients //increment the number of samples mcN++; } //end mcSample() void mcEnd(){ //divide all coefficients by the number of samples for(unsigned int i = 0; i < C.size(); i++) C[i] /= mcN; } /// Generates a PDF describing the probability distribution of points on a spherical surface /// @param sph_pts is a list of points in spherical coordinates (theta, phi) where theta = [0, 2pi] and phi = [0, pi] /// @param l is the maximum degree of the spherical harmonic function /// @param m is the maximum order void pdf(std::vector > sph_pts, unsigned int l, int m){ mcBegin( l, m ); //begin spherical harmonic sampling unsigned int nP = sph_pts.size(); for(unsigned int p = 0; p < nP; p++){ mcSample(sph_pts[p][1], sph_pts[p][2], 1.0); } mcEnd(); } std::string str(){ std::stringstream ss; int l, m; l = m = 0; for(unsigned int i = 0; i < C.size(); i++){ ss< l){ l++; m = -l; ss< l){ l++; m = -l; } } return fx; } /* //overload arithmetic operations spharmonics operator*(T rhs) const { spharmonics result(C.size()); //create a new spherical harmonics object for (size_t c = 0; c < C.size(); c++) //for each coefficient result.C[c] = C[c] * rhs; //calculate the factor and store the result in the new spharmonics object return result; } spharmonics operator+(spharmonics rhs) { size_t low = std::min(C.size(), rhs.C.size()); //store the number of coefficients in the lowest object size_t high = std::max(C.size(), rhs.C.size()); //store the number of coefficients in the result bool rhs_lowest = false; //true if rhs has the lowest number of coefficients if (rhs.C.size() < C.size()) rhs_lowest = true; //if rhs has a lower number of coefficients, set the flag spharmonics result(high); //create a new object size_t c; for (c = 0; c < low; c++) //perform the first batch of additions result.C[c] = C[c] + rhs.C[c]; //perform the addition for (c = low; c < high; c++) { if (rhs_lowest) result.C[c] = C[c]; else result.C[c] = rhs.C[c]; } return result; } spharmonics operator-(spharmonics rhs) { return (*this) + (rhs * (T)(-1)); } */ }; //end class sph_harmonics } #endif