Commit 2e325f2918e2293cacf6fc9fe814af8c80f95c12

Authored by Pavel Govyadinov
1 parent 9bfae4d0

Fixed the pdf implementation in spharmonics classes, added the random.h class in…

… stim/math for access to randomized variables and to sample a solid sphere (or angle), the functions are static but an instance can be initialized if a specific seed is needed
Showing 2 changed files with 152 additions and 2 deletions   Show diff stats
stim/math/random.h 0 → 100644
  1 +#ifndef STIM_RANDOM
  2 +#define STIM_RANDOM
  3 +
  4 +#include <stdio.h>
  5 +#include <stdlib.h>
  6 +#include <time.h>
  7 +#include <stim/math/vec3.h>
  8 +#include <stim/math/constants.h>
  9 +
  10 +namespace stim{
  11 +
  12 +template<class T>
  13 +class Random{
  14 +protected:
  15 + void init(int seed = 0)
  16 + {
  17 + if(seed <= 0)
  18 + srand(time(NULL));
  19 + else if(seed > 0)
  20 + srand(time(seed));
  21 + else
  22 + std::cout << "Error: Unknown value: in STIM::RANDOM" << std::endl;
  23 + }
  24 +
  25 +public:
  26 + /// Default Constructor
  27 + Random(){
  28 + init(-1);
  29 + }
  30 +
  31 + /// Constructor from a seed.
  32 + /// A positive seed sets, 0 or negative yeilds the
  33 + Random(int seed){
  34 + init(seed);
  35 + }
  36 +
  37 + ///Returns a random number uniformly sampled between 0 and 1
  38 + static
  39 + T uniformRandom()
  40 + {
  41 + return ( (T)(rand()))/( (T)(RAND_MAX)); ///generates a random number between 0 and 1 using the uniform distribution.
  42 + }
  43 +
  44 + ///Returns a random number from a normal distribution between 0 to 1.
  45 + static
  46 + T normalRandom()
  47 + {
  48 + T u1 = uniformRandom();
  49 + T u2 = uniformRandom();
  50 + return cos(2.0*atan(1.0)*u2)*sqrt(-1.0*log(u1)); ///generate a random number using the normal distribution between 0 and 1.
  51 + }
  52 + ///Return a random vec3 each value between 0 and 1 from a uniform distribution.
  53 + static
  54 + stim::vec3<T> uniformRandVector()
  55 + {
  56 + stim::vec3<T> r(uniformRandom(), uniformRandom(), 1.0); ///generate a random vector using the uniform distribution between 0 and 1.
  57 + return r;
  58 + }
  59 + ///Return a random vec3, each value between 0 and 1 from a normal distribution.
  60 + static
  61 + stim::vec3<T> normalRandVector()
  62 + {
  63 + stim::vec3<float> r(normalRandom(), normalRandom(), 1.0); ///generate a random vector using the normal distribution between 0 and 1.
  64 + return r;
  65 + }
  66 +
  67 + ///place num_samples of samples on the surface of a sphere of radius r.
  68 + ///returns an std::vector of vec3's in cartisian coordinates.
  69 + static std::vector<stim::vec3 <T> >
  70 + sample_sphere(unsigned int num_samples, T radius = 1, T solidAngle = stim::TAU)
  71 + {
  72 + std::cout << "did this" << std::endl;
  73 + T PHI[2], Z[2], range; ///Range of angles in cylinderical coordinates
  74 + PHI[0] = solidAngle/2; ///project the solid angle into spherical coords
  75 + PHI[1] = asin(0); ///
  76 + Z[0] = cos(PHI[0]); ///project the z into spherical coordinates
  77 + Z[1] = cos(PHI[1]); ///
  78 + range = Z[0] - Z[1]; ///the range of all possible z values.
  79 +
  80 + T z, theta, phi; /// temporary individual
  81 +
  82 + std::vector<stim::vec3<T> > samples;
  83 +
  84 + //srand(100); ///set random seed
  85 +
  86 + for(int i = 0; i < num_samples; i++) ///for each sample
  87 + {
  88 + z = uniformRandom()*range + Z[1]; ///find a random z based on the solid angle
  89 + theta = uniformRandom() * stim::TAU; ///find theta
  90 + phi = acos(z); ///project into spherical coord phi
  91 + stim::vec3<T> sph(radius, theta, phi); ///assume spherical
  92 + stim::vec3<T> cart = sph.sph2cart(); ///conver to cartesisn
  93 + samples.push_back(cart); ///push into list
  94 + }
  95 +
  96 +///THIS IS DEBUGGING CODE, UNCOMMENT TO CHECK WHETHER THE SURFACE IS WELL SAMPLED!
  97 +/*
  98 + std::stringstream name;
  99 + for(int i = 0; i < num_samples; i++)
  100 + name << samples[i].str() << std::endl;
  101 +
  102 +
  103 + std::ofstream outFile;
  104 + outFile.open("Sampled Surface.txt");
  105 + outFile << name.str().c_str();
  106 +*/
  107 +
  108 + return samples; ///return full list.
  109 + }
  110 +};
  111 +
  112 +}
  113 +
  114 +#endif
... ...
stim/math/spharmonics.h
... ... @@ -5,6 +5,7 @@
5 5 #include <stim/math/vector.h>
6 6 #include <boost/math/special_functions/spherical_harmonic.hpp>
7 7 #include <stim/math/constants.h>
  8 +#include <stim/math/random.h>
8 9 #include <vector>
9 10  
10 11 #define WIRE_SCALE 1.001
... ... @@ -26,7 +27,6 @@ protected:
26 27 double SH(int l, int m, double theta, double phi){
27 28 std::complex<T> result = boost::math::spherical_harmonic(l, m, phi, theta);
28 29 return result.imag() + result.real();
29   -// return boost::math::spherical_harmonic_i(l, m, phi, theta);
30 30 }
31 31  
32 32 unsigned int coeff_1d(unsigned int l, int m){
... ... @@ -117,10 +117,10 @@ public:
117 117 }
118 118  
119 119 /// Generates a PDF describing the probability distribution of points on a spherical surface
120   -
121 120 /// @param sph_pts is a list of points in spherical coordinates (theta, phi) where theta = [0, 2pi] and phi = [0, pi]
122 121 /// @param l is the maximum degree of the spherical harmonic function
123 122 /// @param m is the maximum order
  123 +
124 124 void pdf(std::vector<stim::vec<double> > sph_pts, unsigned int l, int m){
125 125  
126 126 mcBegin( l, m ); //begin spherical harmonic sampling
... ... @@ -134,6 +134,42 @@ public:
134 134 mcEnd();
135 135 }
136 136  
  137 + /// Generates a PDF describing the probability distribution of points on a spherical surface
  138 + /// @param sph_pts is a list of points in cartesian coordinates
  139 + /// @param l is the maximum degree of the spherical harmonic function
  140 + /// @param m is the maximum order
  141 + /// @param c is the centroid of the points in sph_pts. DEFAULT 0,0,0
  142 + /// @param n is the number of points of the surface of the sphere used to create the PDF. DEFAULT 1000
  143 + void pdf(std::vector<stim::vec3<double> > sph_pts, unsigned int l, int m, stim::vec3<double> c = stim::vec3<double>(0,0,0), unsigned int n = 1000)
  144 + {
  145 + std::vector<double> weights; ///the weight at each point on the surface of the sphere.
  146 +// weights.resize(n);
  147 + unsigned int nP = sph_pts.size();
  148 + std::vector<stim::vec3<double> > sphere = stim::Random<double>::sample_sphere(n, 1.0, stim::TAU);
  149 + for(int i = 0; i < n; i++)
  150 + {
  151 + double val = 0;
  152 + for(int j = 0; j < nP; j++)
  153 + {
  154 + stim::vec3<double> temp = sph_pts[j] - c;
  155 + if(temp.dot(sphere[i]) > 0)
  156 + val += pow(temp.dot(sphere[i]),4);
  157 + }
  158 + weights.push_back(val);
  159 + }
  160 +
  161 +
  162 + mcBegin(l, m); //begin spherical harmonic sampling
  163 +
  164 + for(unsigned int i = 0; i < n; i++)
  165 + {
  166 + stim::vec3<double> sph = sphere[i].cart2sph();
  167 + mcSample(sph[1], sph[2], weights[i]);
  168 + }
  169 +
  170 + mcEnd();
  171 + }
  172 +
137 173 std::string str(){
138 174  
139 175 std::stringstream ss;
... ...