// -*- C++ -*- #ifndef RISAMPLEPATTERN_H #define RISAMPLEPATTERN_H /* Copyright 1996 * Tue May 13 09:29:22 1997 Brian Smits (bes@phoenix.cs.utah.edu) * * RiSamplePattern.H * * * * $Id: RiSamplePattern.H,v 1.3 1999/06/10 20:10:56 bes Exp $ * */ #ifndef RICOMMON_H #include #endif #ifndef RIRANDOM_H #include #endif #ifndef RIVECTOR2_H #include #endif /*************************************************************** CLASS RiSamplingStrategy Takes a RiRandom, and generates N samples points in [0,1)^D based on some strategy. DESCRIPTION Used to fill the data of an RiSamplePattern based on some sampling strategy such as uniform or jittered. This class should be able to handle any number of requested samples. This may mean that the sample pattern isn't perfect, for example if the strategy is jittered 2D and the caller asks for 10 samples, the first 9 might be jittered on a 3x3 grid and the last sample chosen uniformly. IMPLEMENTATION DETAIL This class must be stateless to the extent that it can be shared among multiple users with different sample pattern size needs. PATTERN Strategy ****************************************************************/ class RiSamplingStrategy { public: //// [in] numSamples Number of samples desired // [in] numDimensions The dimension of the sample spaces // [in] gen The random number generator to be used // [out] realNum Number actually created (<= numSamples) virtual int CreateSamples(RiReal *samples, int numSamples, int numDimensions, RiRandom &gen) const = 0; }; /*************************************************************** CLASS RiUniformSampling Create N sample points of dimension D uniform in [0,1)^D DESCRIPTION ****************************************************************/ class RiUniformSampling : public RiSamplingStrategy { public: //// [in] numSamples Number of samples desired // [in] numDimensions The dimension of the sample spaces // [in] gen The random number generator to be used // [out] realNum Number actually created (<= numSamples) int CreateSamples(RiReal *samples, int numSamples, int numDimensions, RiRandom &gen) const; }; /*************************************************************** CLASS Ri1DJitteredSampling Create N sample points of dimension 2 jittered on [0,1)^2 DESCRIPTION ****************************************************************/ class Ri1DJitteredSampling : public RiSamplingStrategy { public: //// [in] numSamples Number of samples desired // [in] numDimensions The dimension of the sample spaces // [in] gen The random number generator to be used // [out] realNum Number actually created (<= numSamples) int CreateSamples(RiReal *samples, int numSamples, int numDimensions, RiRandom &gen) const; }; /*************************************************************** CLASS Ri2DJitteredSampling Create N sample points of dimension 2 jittered on [0,1)^2 DESCRIPTION If an odd number of dimensions are requested, the LAST dimension is jittered as a 1Djittered sample. This method returns a perfect square number of samples ****************************************************************/ class Ri2DJitteredSampling : public RiSamplingStrategy { public: //// [in] numSamples Number of samples desired // [in] numDimensions The dimension of the sample spaces // [in] gen The random number generator to be used // [out] realNum Number actually created (<= numSamples) int CreateSamples(RiReal *samples, int numSamples, int numDimensions, RiRandom &gen) const; }; /*************************************************************** CLASS RiSamplePattern Generate a set of N samples from [0,1)^D DESCRIPTION LIMITATIONS Can't handle adaptive sampling ****************************************************************/ class RiSamplePattern { public: // GROUP: Constructors and assignment //// Default Constructor RiSamplePattern(); //// Constructor // [strategy] is NOT adopted, user is responsible for clean up AFTER done // [generator]is NOT adopted, user is responsible for clean up AFTER done RiSamplePattern(int numSamples, int dimension, RiSamplingStrategy *strategy, RiRandom *generator); ////Copy Constructor Not efficient RiSamplePattern(const RiSamplePattern &); //// Assignment Not efficient const RiSamplePattern &operator=(const RiSamplePattern &); //// Destructor ~RiSamplePattern(); // GROUP: Accessors //// Get the number of samples actually created by the method int GetNumSamples() const; //// Get the dimension of the sample points int GetNumDimensions() const; //// Get the raw data user shouldn't access beyond retval + Dim const RiReal *operator()(int sample) const; //// Get a specific sample and coordinate RiReal operator()(int sample, int dimension) const; //// Create a new sampling pattern (user must call permute if desired) void Resample(); //// Permute the samples in each (groupSize) dimensions. Permutes // the first column as well, so multiple sample patterns will be // permuted with respect to each other. The algorithm works even // when groupSize doesn't divide NumDimensions evenly. void Permute(int groupSize); //// void Permute(int groupSize, int seed); private: RiSamplingStrategy *strategy; RiRandom *generator; RiReal *samples; int numSamples; int numDimensions; // can't have the permutation depend on a possibly NonRandom RiRandom static RiRandom permuteGen; }; /*************************************************************** CLASS Ri1DSamplePatternIterator Cycle through each dimension of an RiSamplePattern DESCRIPTION Cycle through each dimmension of an RiSamplePattern, this allows one level of an algorithm to increment the sample counter, and another to cycle through all the dimensions of a particular sample. Currently it only seems useful to have the Iterator cycle through dimensions, but it is designed to cycle through samples as well. The creator of the Iterator can worry about hitting each sample no more than once if that is important. WARNINGS This is not a true iterator as it's interface consists of GetNext() which returns the next 1D point and advances, and NextSample() which shifts down to the next sample PATTERNS Iterator (modified for cycling behavior) ****************************************************************/ class Ri1DSamplePatternIterator { public: // GROUP: Constructors and assignment //// Default Constructor Ri1DSamplePatternIterator(const RiSamplePattern &samples); // GROUP: Members //// Done with this sample, move on to the next one void NextSample(); //// Get the next dimension of the current sample (and advance) RiReal GetNext(); private: int samplePos; int numSamples; int dimensionPos; int numDimensions; const RiSamplePattern &samples; }; /*************************************************************** CLASS Ri2DSamplePatternIterator Cycle through each dimension of an RiSamplePattern DESCRIPTION Cycle through each dimmension of an RiSamplePattern, this allows one level of an algorithm to increment the sample counter, and another to cycle through all pairs of dimensions of a particular sample. Currently it only seems useful to have the Iterator cycle through dimensions, but it is designed to cycle through samples as well. The creator of the Iterator can worry about hitting each sample no more than once if that is important. WARNINGS This is not a true iterator as it's interface consists of GetNext() which returns the next 2D point and advances, and NextSample() which shifts down to the next sample PATTERNS Iterator (modified for cycling behavior) ****************************************************************/ class Ri2DSamplePatternIterator { public: // GROUP: Constructors and assignment //// Default Constructor Ri2DSamplePatternIterator(const RiSamplePattern &samples); // GROUP: Members //// Done with this sample, move on to the next one void NextSample(); //// Get the next dimension of the current sample (and advance) RiVector2 GetNext(); private: int samplePos; int numSamples; int dimensionPos; int numDimensions; const RiSamplePattern &samples; }; #endif /* RISAMPLEPATTERN_H */