dynamic_poisson_sampling/
lib.rs1
2use rand;
7
8#[doc(hidden)]
9fn distance<const N: usize>(lhs: &[f64; N], rhs: &[f64; N]) -> f64{
10 lhs.iter()
11 .zip(rhs.iter())
12 .map(|(&l, &r)| {
13 let diff = l - r;
14 diff * diff
15 })
16 .sum::<f64>().sqrt()
17}
18
19pub fn get_points<const N: usize, T>(k: u32, first_pos: [f64; N], rng: &mut impl rand::Rng, density_func:T)
44-> Vec<[f64; N]>
45where
46 T: Fn(&[f64; N]) -> Option<f64>
47{
48 struct Point<const N: usize>{
49 pos: [f64; N],
50 min_rad: f64,
51 }
52
53 let mut points: Vec<Point<N>> = Vec::new();
54
55 let mut active_list: Vec<usize> = Vec::new();
57
58
59
60
61
62 let r_rad = density_func(&first_pos);
64 if r_rad.is_none() { return vec![]; }
65 let r_rad = r_rad.unwrap();
66
67 points.push(Point{
68 pos: first_pos,
69 min_rad: r_rad,
70 });
71 active_list.push(0);
72
73
74
75 loop {
76 let r_ind = rng.gen_range(0..active_list.len());
77 let curr_ind = active_list[r_ind];
78 let (curr_pos, curr_rad) = (points[curr_ind].pos, points[curr_ind].min_rad);
79
80 'k_l: for _ in 0..k {
82 let r_distance = rng.gen_range(curr_rad .. 3.*curr_rad);
83
84
85 let mut deltas: [f64; N] = [0.0; N];
86
87 for delta in &mut deltas {
89 *delta = rng.gen_range(-1.0..=1.0);
90 }
91
92 let norm = (deltas.iter().map(|&x| x.powi(2)).sum::<f64>()).sqrt();
94 let mut r_pos: [f64; N] = [0.0; N];
95 for i in 0..N{
96 r_pos[i] = curr_pos[i]+(deltas[i]/norm)*r_distance;
97 }
98
99
100 let r_rad = density_func(&r_pos);
101 if r_rad.is_none() { continue 'k_l; }
102 let r_rad = r_rad.unwrap();
103
104 for point in points.iter() {
105 let distance = distance(&point.pos, &r_pos);
106 if distance < point.min_rad+r_rad {
107 continue 'k_l;
108 }
109 }
110
111 points.push(Point{
112 pos: r_pos,
113 min_rad: r_rad,
114 });
115
116 active_list.push(points.len()-1);
117 }
118
119 active_list.remove(r_ind);
120
121 if active_list.is_empty() {
122 break;
123 }
124 }
125
126 points.iter().map(|p| p.pos).collect()
127}