aboutsummaryrefslogtreecommitdiff
path: root/src/analysis.rs
blob: aabe4e5665089b6a51ff9fbb069c3ddc9ca896dc (plain)
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use crate::{LabelFormat,LabelU16};

use avl_tree::*;

#[derive(Debug)]
pub struct Data {
    pub label: u16,
    pub area: usize,
    pub perimeter: usize,
    pub neighboring: usize,
    pub non_neighboring: usize,
}

impl Data {
    const fn new(label: u16, area: usize, perimeter: usize, neighboring: usize, non_neighboring: usize) -> Self {
        Self {
            label,
            area,
            perimeter,
            neighboring,
            non_neighboring,
        }
    }
}

fn any(a: &[bool]) -> bool {
    for value in a.iter() {
        if *value {
            return true;
        }
    }
    false
}

impl LabelFormat<u16> {
    pub fn get_tree(&self) -> AVLTree<u16, Data> {
        let mut avt = avl_tree::AVLTree::<u16, Data>::new();
        for y in 0..self.height {
            for x in 0..self.width {
                let index = x + y * self.width;
                let key = self.buffer[index];
                if key.is_zero() {
                    continue;
                }
                let mut new_data = Data::new(
                    key,
                    0,
                    0,
                    0,
                    0);
                match avt.get(key) {
                    Some(data) => {
                        new_data.area = data.area;
                        new_data.perimeter = data.perimeter;
                        new_data.neighboring = data.neighboring;
                        new_data.non_neighboring = data.non_neighboring;
                    },
                    None => {
                    },
                }
                let neighbors: [Option<u16>;4] = [
                    self.get_up(x,y),
                    self.get_right(x,y),
                    self.get_down(x,y),
                    self.get_left(x,y),
                ];
                let perimeter_slice = neighbors.map(|x|
                    match x {
                        Some(y) => (y.is_zero()) || (y != new_data.label),
                        None => false,
                    });
                let add_perimeter = any(&perimeter_slice);
                let neighboring_slice = neighbors.map(|x|
                    match x {
                        Some(y) => (y != new_data.label) && (!y.is_zero()),
                        None => false,
                    });
                let add_neighboring = any(&neighboring_slice);
                let non_neighboring_slice = neighbors.map(|x|
                    match x {
                        Some(y) => y.is_zero(),
                        None => false,
                    });
                let add_non_neighboring = any(&non_neighboring_slice);
                // Always increase area
                new_data.area += 1;
                // Increase perimeter if there is a neighbor that is not the same cell
                if add_perimeter {
                    new_data.perimeter += 1;
                }
                if add_non_neighboring {
                    new_data.non_neighboring += 1;
                }
                if add_neighboring {
                    new_data.neighboring += 1;
                }
                avt.insert(key, new_data);
            }
        }
        avt
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn get_areas_test() {
        const DIM: usize = 6;
        let mut test_data = LabelFormat::<u16> {
            buffer: vec![0u16; DIM*DIM],
            width: DIM,
            height: DIM,
        };
        test_data.buffer[2+3*DIM] = 1;
        test_data.buffer[3+3*DIM] = 1;
        test_data.buffer[4+3*DIM] = 2;
        test_data.idilate();

        test_data.display();
        for (key,val) in test_data.get_tree().iter() {
            println!("{} -> {:?}",key,val)
        }
    }
}