## 7.6 Maximized Minimal Distance Sampler

The -sequence sampler is more effective than the stratified sampler, thanks to being stratified over all elementary intervals. However, it still sometimes generates sample points that are close together. An alternative is to use a different pair of generator matrices that not only generate -sequences but that are also specially designed to maximize the distance between samples; this approach is implemented by the MaxMinDistSampler. (See the “Further Reading” section for more details about the origin of these generator matrices.)

<<MaxMinDistSampler Declarations>>=
class MaxMinDistSampler : public PixelSampler { public: <<MaxMinDistSampler Public Methods>>
void StartPixel(const Point2i &); std::unique_ptr<Sampler> Clone(int seed); int RoundCount(int count) const { return RoundUpPow2(count); } MaxMinDistSampler(int64_t samplesPerPixel, int nSampledDimensions) : PixelSampler(RoundUpPow2(samplesPerPixel), nSampledDimensions) { CPixel = CMaxMinDist[Log2Int(samplesPerPixel)]; }
private: <<MaxMinDistSampler Private Data>>
const uint32_t *CPixel;
};

There are 17 of these specialized matrices, one for each power-of-two number of samples up to samples; a pointer to the appropriate one is stored in CPixel in the constructor.

<<MaxMinDistSampler Public Methods>>=
MaxMinDistSampler(int64_t samplesPerPixel, int nSampledDimensions) : PixelSampler(RoundUpPow2(samplesPerPixel), nSampledDimensions) { CPixel = CMaxMinDist[Log2Int(samplesPerPixel)]; }

<<MaxMinDistSampler Private Data>>=
const uint32_t *CPixel;

Figure 7.32 shows a few of these matrices.   Figure 7.33 shows the points that one of the matrices generates. Note that the same sampling pattern is used in each of the pixels shown there; when the matrices were found, distance between sample points was evaluated using toroidal topology—as if the unit square was rolled into a torus—to allow for high-quality sample tiling.

<<Low Discrepancy Declarations>>+=
extern uint32_t CMaxMinDist;

The MaxMinDistSampler uses the generator matrix to compute the pixel samples. The first 2D sample dimension’s value is set by uniformly stepping in the first dimension and the second comes from the generator matrix.

<<MaxMinDistSampler Method Definitions>>=
void MaxMinDistSampler::StartPixel(const Point2i &p) { Float invSPP = (Float)1 / samplesPerPixel; for (int i = 0; i < samplesPerPixel; ++i) samples2D[i] = Point2f(i * invSPP, SampleGeneratorMatrix(CPixel, i)); Shuffle(&samples2D, samplesPerPixel, 1, rng); <<Generate remaining samples for MaxMinDistSampler>>
for (size_t i = 0; i < samples1D.size(); ++i) VanDerCorput(1, samplesPerPixel, &samples1D[i], rng); for (size_t i = 1; i < samples2D.size(); ++i) Sobol2D(1, samplesPerPixel, &samples2D[i], rng); for (size_t i = 0; i < samples1DArraySizes.size(); ++i) { int count = samples1DArraySizes[i]; VanDerCorput(count, samplesPerPixel, &sampleArray1D[i], rng); } for (size_t i = 0; i < samples2DArraySizes.size(); ++i) { int count = samples2DArraySizes[i]; Sobol2D(count, samplesPerPixel, &sampleArray2D[i], rng); }
PixelSampler::StartPixel(p); }

The remaining dimensions are sampled using the first two Sobol matrices, like the ZeroTwoSequenceSampler. We have found slightly better results with this approach (versus using the CMaxMinDist matrices) for samples in non-image dimensions of the sample vector. Therefore, the corresponding fragment <<Generate remaining samples for MaxMinDistSampler>> isn’t included here.