bs_trace/trace/
sampling.rs

1use itertools::Itertools;
2use rand::{Rng, RngCore};
3
4pub trait SamplingStrategy: Send + Sync {
5    fn get_sample_positions(
6        &self,
7        rng: &mut Box<dyn RngCore>,
8        x: usize,
9        y: usize,
10    ) -> Vec<(f64, f64)>;
11}
12
13pub struct SingleSampling<const W: usize, const H: usize>;
14pub struct SubdivisionSampling<const W: usize, const H: usize, const NUM_SUBDIVS: usize>;
15pub struct RandomSampling<const W: usize, const H: usize, const NUM_SAMPLES: usize> {}
16
17impl<const W: usize, const H: usize> SingleSampling<W, H> {
18    pub const fn new() -> Self {
19        SingleSampling {}
20    }
21}
22
23impl<const W: usize, const H: usize> SamplingStrategy for SingleSampling<W, H> {
24    fn get_sample_positions(
25        &self,
26        rng: &mut Box<dyn RngCore>,
27        x: usize,
28        y: usize,
29    ) -> Vec<(f64, f64)> {
30        vec![(x as f64 / W as f64, y as f64 / H as f64)]
31    }
32}
33
34impl<const W: usize, const H: usize, const NUM_SUBDIVS: usize>
35    SubdivisionSampling<W, H, NUM_SUBDIVS>
36{
37    pub const fn new() -> Self {
38        SubdivisionSampling {}
39    }
40}
41
42impl<const W: usize, const H: usize, const NUM_SUBDIVS: usize> SamplingStrategy
43    for SubdivisionSampling<W, H, NUM_SUBDIVS>
44{
45    fn get_sample_positions(
46        &self,
47        rng: &mut Box<dyn RngCore>,
48        x: usize,
49        y: usize,
50    ) -> Vec<(f64, f64)> {
51        (0..NUM_SUBDIVS)
52            .cartesian_product(0..NUM_SUBDIVS)
53            .map(|(x_adj, y_adj)| {
54                (
55                    (x_adj as f64 + 0.5) / NUM_SUBDIVS as f64,
56                    (y_adj as f64 + 0.5) / NUM_SUBDIVS as f64,
57                )
58            })
59            .map(|(x_adj, y_adj)| ((x_adj + x as f64) / W as f64, (y_adj + y as f64) / H as f64))
60            .collect()
61    }
62}
63
64impl<const W: usize, const H: usize, const NUM_SAMPLES: usize> RandomSampling<W, H, NUM_SAMPLES> {
65    pub const fn new() -> Self {
66        RandomSampling {}
67    }
68}
69
70impl<const W: usize, const H: usize, const NUM_SAMPLES: usize> SamplingStrategy
71    for RandomSampling<W, H, NUM_SAMPLES>
72{
73    fn get_sample_positions(
74        &self,
75        rng: &mut Box<dyn RngCore>,
76        x: usize,
77        y: usize,
78    ) -> Vec<(f64, f64)> {
79        (0..NUM_SAMPLES)
80            .map(|_| {
81                let x_adj: f64 = rng.gen_range(0.0..1.0);
82                let y_adj: f64 = rng.gen_range(0.0..1.0);
83                let x = x as f64 + x_adj;
84                let y = y as f64 + y_adj;
85                (x / W as f64, y / H as f64)
86            })
87            .collect()
88    }
89}