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 | 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; | ... | ... |