bs_trace/trace/
sampling.rs1use 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}