vorolib/
distribute.rs

1use dims::{X, Y};
2use img::Img;
3use norms::Dist;
4use norms::Norm;
5use point::Point2D;
6use pointset::UPoints;
7use rand::{Rng, StdRng};
8use std::collections::HashSet;
9
10/// Distribute points randomly.
11pub fn generate_random_points(img: &Img, avg_patch_size: usize, rng: &mut StdRng) -> UPoints {
12    debug_assert!(avg_patch_size > 0);
13    let (width, height, count) = (img.width(), img.height(), img.pixel_cnt() / avg_patch_size);
14    let mut points = HashSet::<Point2D>::with_capacity(count);
15    while points.len() < count {
16        let point = Point2D::from_raw(
17            rng.gen_range(0, width.value),
18            rng.gen_range(0, height.value),
19        );
20        if !points.contains(&point) {
21            points.insert(point);
22        } else {
23        }
24    }
25    UPoints::new(img.width(), img.height(), points.into_iter().collect())
26}
27
28/// Distribute points predictably.
29pub fn generate_fixed_points(width: X, height: Y, count: usize) -> UPoints {
30    debug_assert!(
31        width.euclidean_norm() * height.euclidean_norm() > Dist::fnew(9.0 * (count as f64))
32    );
33    let mut points = HashSet::<Point2D>::with_capacity(count);
34    let count_per_dim = (count as f64).sqrt().ceil() as usize;
35    for xi in 0..count_per_dim {
36        let x = width.as_index() * (2 * xi + 1) / (2 * count_per_dim);
37        for yi in 0..count_per_dim {
38            let y = height.as_index() * (2 * yi + 1) / (2 * count_per_dim);
39            points.insert(Point2D::from_raw(x as usize, y as usize));
40        }
41    }
42    UPoints::new(width, height, points.into_iter().collect())
43}
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48    use std::iter::FromIterator;
49
50    #[test]
51    fn test_equidistant() {
52        let points = generate_fixed_points(X::new(15), Y::new(15), 9);
53        assert_eq!(X::new(2), points.first_by_x().x());
54        let lookup: HashSet<Point2D> = HashSet::from_iter(points.into_iter());
55        assert!(lookup.contains(&Point2D::from_raw(2, 2)));
56        assert!(lookup.contains(&Point2D::from_raw(2, 7)));
57        assert!(lookup.contains(&Point2D::from_raw(2, 12)));
58        assert!(lookup.contains(&Point2D::from_raw(7, 2)));
59        assert!(lookup.contains(&Point2D::from_raw(7, 7)));
60        assert!(lookup.contains(&Point2D::from_raw(7, 12)));
61        assert!(lookup.contains(&Point2D::from_raw(12, 2)));
62        assert!(lookup.contains(&Point2D::from_raw(12, 7)));
63        assert!(lookup.contains(&Point2D::from_raw(12, 12)));
64    }
65}
66pub fn default_seed() -> [u8; 32] {
67    [
68        154, 209, 215, 146, 162, 81, 13, 78, 243, 132, 107, 232, 61, 157, 71, 142, 202, 167, 65,
69        141, 113, 250, 202, 52, 46, 221, 141, 139, 22, 29, 183, 135,
70    ]
71}