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)
}
}
}
|