Commit 2e325f2918e2293cacf6fc9fe814af8c80f95c12
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
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,6 +5,7 @@ | ||
5 | #include <stim/math/vector.h> | 5 | #include <stim/math/vector.h> |
6 | #include <boost/math/special_functions/spherical_harmonic.hpp> | 6 | #include <boost/math/special_functions/spherical_harmonic.hpp> |
7 | #include <stim/math/constants.h> | 7 | #include <stim/math/constants.h> |
8 | +#include <stim/math/random.h> | ||
8 | #include <vector> | 9 | #include <vector> |
9 | 10 | ||
10 | #define WIRE_SCALE 1.001 | 11 | #define WIRE_SCALE 1.001 |
@@ -26,7 +27,6 @@ protected: | @@ -26,7 +27,6 @@ protected: | ||
26 | double SH(int l, int m, double theta, double phi){ | 27 | double SH(int l, int m, double theta, double phi){ |
27 | std::complex<T> result = boost::math::spherical_harmonic(l, m, phi, theta); | 28 | std::complex<T> result = boost::math::spherical_harmonic(l, m, phi, theta); |
28 | return result.imag() + result.real(); | 29 | return result.imag() + result.real(); |
29 | -// return boost::math::spherical_harmonic_i(l, m, phi, theta); | ||
30 | } | 30 | } |
31 | 31 | ||
32 | unsigned int coeff_1d(unsigned int l, int m){ | 32 | unsigned int coeff_1d(unsigned int l, int m){ |
@@ -117,10 +117,10 @@ public: | @@ -117,10 +117,10 @@ public: | ||
117 | } | 117 | } |
118 | 118 | ||
119 | /// Generates a PDF describing the probability distribution of points on a spherical surface | 119 | /// Generates a PDF describing the probability distribution of points on a spherical surface |
120 | - | ||
121 | /// @param sph_pts is a list of points in spherical coordinates (theta, phi) where theta = [0, 2pi] and phi = [0, pi] | 120 | /// @param sph_pts is a list of points in spherical coordinates (theta, phi) where theta = [0, 2pi] and phi = [0, pi] |
122 | /// @param l is the maximum degree of the spherical harmonic function | 121 | /// @param l is the maximum degree of the spherical harmonic function |
123 | /// @param m is the maximum order | 122 | /// @param m is the maximum order |
123 | + | ||
124 | void pdf(std::vector<stim::vec<double> > sph_pts, unsigned int l, int m){ | 124 | void pdf(std::vector<stim::vec<double> > sph_pts, unsigned int l, int m){ |
125 | 125 | ||
126 | mcBegin( l, m ); //begin spherical harmonic sampling | 126 | mcBegin( l, m ); //begin spherical harmonic sampling |
@@ -134,6 +134,42 @@ public: | @@ -134,6 +134,42 @@ public: | ||
134 | mcEnd(); | 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 | std::string str(){ | 173 | std::string str(){ |
138 | 174 | ||
139 | std::stringstream ss; | 175 | std::stringstream ss; |