Skip to main content

string_art/
line_selector.rs

1use std::ops::Deref;
2
3use crate::{
4    verboser::Verboser, AsLab, Image
5};
6
7pub unsafe trait Builder<S> {
8    fn build_line_selector(
9        &self,
10        image: &Image<S>,
11        palette: &[impl AsLab<S>],
12        verboser: &mut impl Verboser,
13    ) -> Result<LineSelector, Error>;
14}
15
16#[derive(Clone, Copy)]
17pub struct LineItemSelector {
18    color_idx: usize,
19    count: usize,
20    cap: usize,
21}
22
23impl LineItemSelector {
24    pub fn new(color_idx: usize, count: usize, cap: usize) -> Self {
25        LineItemSelector {
26            color_idx,
27            count,
28            cap,
29        }
30    }
31
32    pub fn color_idx(&self) -> usize {
33        self.color_idx
34    }
35
36    pub fn cap(&self) -> usize {
37        self.cap
38    }
39}
40
41pub struct LineGroupSelector(Vec<LineItemSelector>);
42
43impl FromIterator<LineItemSelector> for LineGroupSelector {
44    fn from_iter<T: IntoIterator<Item = LineItemSelector>>(iter: T) -> Self {
45        LineGroupSelector(iter.into_iter().collect())
46    }
47}
48
49impl LineGroupSelector {
50    fn select_next(&mut self) -> Option<usize> {
51        let mut choice = None;
52        let mut best_ratio = 1.0;
53        for item in self.0.iter_mut() {
54            let ratio = item.count as f32 / item.cap as f32;
55            if ratio < best_ratio {
56                best_ratio = ratio;
57                choice = Some(item);
58            }
59        }
60
61        choice.map(|item| {
62            item.count += 1;
63            item.color_idx
64        })
65    }    
66}
67
68impl Deref for LineGroupSelector{
69    type Target = [LineItemSelector];
70
71    fn deref(&self) -> &Self::Target {
72        &self.0
73    }
74}
75
76pub struct LineSelector{
77    lines: Vec<LineGroupSelector>,
78    curr: usize,
79}
80
81impl LineSelector {
82    pub (crate) fn select_next(&mut self) -> Option<usize> {        
83        while let Some(last) = self.lines.get_mut(self.curr) {
84            if let Some(res) = last.select_next() {
85                return Some(res);
86            } else {
87                self.curr = if self.curr == 0{
88                    self.lines.len()
89                } else{
90                    unsafe { self.curr.unchecked_sub(1) }
91                }
92            }
93        }
94
95        None
96    }    
97}
98
99impl Deref for LineSelector {
100    type Target = [LineGroupSelector];
101
102    fn deref(&self) -> &Self::Target {
103        &self.lines
104    }
105}
106
107impl FromIterator<LineGroupSelector> for LineSelector {
108    fn from_iter<T: IntoIterator<Item = LineGroupSelector>>(iter: T) -> Self {
109        let lines: Vec<_> = iter.into_iter().collect();
110        LineSelector{
111            curr: lines.len().checked_sub(1).unwrap_or(lines.len()),
112            lines, 
113        
114        }
115    }
116}
117
118#[derive(Debug, thiserror::Error)]
119#[error("Invalid group index")]
120pub struct Error;