random.h 3.36 KB
#ifndef STIM_RANDOM
#define STIM_RANDOM

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stim/math/vec3.h>
#include <stim/math/constants.h>

namespace stim{

template<class T>
class Random{
protected:
	void init() {
		srand(time(NULL));
	}

	void init(unsigned int seed){
		srand(seed);
	}

public:
	/// Default Constructor
	Random(){
		init();
	}

	/// Constructor from a seed.
	/// A positive seed sets, 0 or negative yeilds the 
	Random(unsigned int seed){
		init(seed);
	}

	///Returns a random number uniformly sampled between 0 and 1
	static
	T uniformRandom()
	{
	     return (  (T)(rand()))/(  (T)(RAND_MAX));  ///generates a random number between 0 and 1 using the uniform distribution.
	}

	///Returns a random number from a normal distribution between 0 to 1.
	static
	T normalRandom()
	{
		T u1 = uniformRandom();
		T u2 = uniformRandom();
		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.
	}
	///Return a random vec3 each value between 0 and 1 from a uniform distribution.
	static
	stim::vec3<T> uniformRandVector()
	{
		stim::vec3<T> r(uniformRandom(), uniformRandom(), 1.0);                                                  ///generate a random vector using the uniform distribution between 0 and 1.
		return r;
	}
	///Return a random vec3, each value between 0 and 1 from a normal distribution.
	static
	stim::vec3<T> normalRandVector()
	{
		stim::vec3<float> r(normalRandom(), normalRandom(), 1.0);                                                    ///generate a random vector using the normal distribution between      0 and 1.
		return r;
	}

	///place num_samples of samples on the surface of a sphere of radius r.
	///returns an std::vector of vec3's in cartisian coordinates.
	static std::vector<stim::vec3 <T> >
	sample_sphere(unsigned int num_samples, T radius = 1, T solidAngle = stim::TAU)
	{
		std::cout << "did this" << std::endl;
		T PHI[2], Z[2], range;      ///Range of angles in cylinderical coordinates
		PHI[0] = solidAngle/2;          ///project the solid angle into spherical coords
		PHI[1] = asin(0);               ///
		Z[0] = cos(PHI[0]);             ///project the z into spherical coordinates
		Z[1] = cos(PHI[1]);             ///
		range = Z[0] - Z[1];            ///the range of all possible z values.

		T z, theta, phi;            /// temporary individual

		std::vector<stim::vec3<T> > samples;

		//srand(100);                     ///set random seed

		for(int i = 0; i < num_samples; i++)		///for each sample
		{
			z = uniformRandom()*range + Z[1];	///find a random z based on the solid angle
			theta = uniformRandom() * stim::TAU;	///find theta
			phi = acos(z);				///project into spherical coord phi
			stim::vec3<T> sph(radius, theta, phi);	///assume spherical
			stim::vec3<T> cart = sph.sph2cart();	///conver to cartesisn
			samples.push_back(cart);		///push into list
		}

///THIS IS DEBUGGING CODE, UNCOMMENT TO CHECK WHETHER THE SURFACE IS WELL SAMPLED!
/*
		std::stringstream name;
	      	for(int i = 0; i < num_samples; i++)
			name << samples[i].str() << std::endl;
		
	    
	      	std::ofstream outFile;
	      	outFile.open("Sampled Surface.txt");
	      	outFile << name.str().c_str();                                                              
*/

		return samples;					///return full list.
	}
};

}

#endif