1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
use crate::vol::{BaseVol, FilledVox, ReadVol, SizedVol};
use vek::*;

pub struct Scaled<V> {
    pub inner: V,
    pub scale: Vec3<f32>,
}

impl<V: BaseVol> BaseVol for Scaled<V> {
    type Error = V::Error;
    type Vox = V::Vox;
}

impl<V: ReadVol> ReadVol for Scaled<V>
where
    V::Vox: FilledVox,
{
    #[inline(always)]
    fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Error> {
        // let ideal_pos = pos.map2(self.scale, |e, scale| (e as f32 + 0.5) / scale);
        // let pos = ideal_pos.map(|e| e.trunc() as i32);
        let min_pos = pos.map2(self.scale, |e, scale| ((e as f32) / scale).floor() as i32);
        let max_pos = pos.map2(self.scale, |e, scale| {
            ((e as f32 + 1.0) / scale).ceil() as i32
        });
        let pos = pos.map2(self.scale, |e, scale| {
            (((e as f32 + 0.5) / scale) - 0.5).round() as i32
        });

        // let ideal_search_size = Vec3::<f32>::one() / self.scale;
        let range_iter = |i: usize| {
            std::iter::successors(Some(0), |p| Some(if *p < 0 { -*p } else { -(*p + 1) }))
                .take_while(move |p| {
                    (min_pos[i]..max_pos[i])
                    /* ((ideal_pos[i] - ideal_search_size[i] / 2.0).ceil() as i32
                        ..(ideal_pos[i] + ideal_search_size[i] / 2.0).ceil() as i32) */
                        .contains(&(pos[i] + *p))
                })
        };
        range_iter(0)
            .flat_map(|i| {
                range_iter(1).map(move |j| range_iter(2).map(move |k| Vec3::new(i, j, k)))
            })
            .flatten()
            .map(|offs| self.inner.get(pos + offs))
            .find(|vox| vox.as_ref().map_or(false, |v| v.is_filled()))
            .unwrap_or_else(|| self.inner.get(pos))
    }
}

impl<V: SizedVol> SizedVol for Scaled<V> {
    #[inline(always)]
    fn lower_bound(&self) -> Vec3<i32> {
        self.inner
            .lower_bound()
            .map2(self.scale, |e, scale| (e as f32 * scale).floor() as i32)
    }

    #[inline(always)]
    fn upper_bound(&self) -> Vec3<i32> {
        self.inner
            .upper_bound()
            .map2(self.scale, |e, scale| (e as f32 * scale).ceil() as i32)
    }
}