Skip to main content

ggplot_rs/scale/
grey.rs

1use crate::aes::Aesthetic;
2use crate::data::Value;
3
4use super::Scale;
5
6/// Greyscale discrete color scale.
7/// Maps discrete levels to evenly-spaced grey values between `start` and `end`.
8/// Default range is 0.2 (dark grey) to 0.8 (light grey), where 0.0 = black and 1.0 = white.
9#[derive(Clone)]
10pub struct ScaleColorGrey {
11    aesthetic: Aesthetic,
12    name: String,
13    start: f64,
14    end: f64,
15    levels: Vec<String>,
16}
17
18impl ScaleColorGrey {
19    pub fn new(aesthetic: Aesthetic) -> Self {
20        ScaleColorGrey {
21            aesthetic,
22            name: String::new(),
23            start: 0.2,
24            end: 0.8,
25            levels: Vec::new(),
26        }
27    }
28
29    /// Set the grey range. `start` and `end` are values in [0, 1]
30    /// where 0.0 = black and 1.0 = white.
31    pub fn with_range(mut self, start: f64, end: f64) -> Self {
32        self.start = start;
33        self.end = end;
34        self
35    }
36
37    fn grey_for_index(&self, idx: usize) -> u8 {
38        let n = self.levels.len().max(1);
39        let t = if n == 1 {
40            (self.start + self.end) / 2.0
41        } else {
42            self.start + (self.end - self.start) * (idx as f64 / (n - 1) as f64)
43        };
44        (t.clamp(0.0, 1.0) * 255.0) as u8
45    }
46}
47
48impl Scale for ScaleColorGrey {
49    fn aesthetic(&self) -> Aesthetic {
50        self.aesthetic.clone()
51    }
52
53    fn train(&mut self, values: &[Value]) {
54        for v in values {
55            let key = v.to_group_key();
56            if !self.levels.contains(&key) {
57                self.levels.push(key);
58            }
59        }
60    }
61
62    fn map(&self, value: &Value) -> f64 {
63        let key = value.to_group_key();
64        self.levels
65            .iter()
66            .position(|l| l == &key)
67            .map(|i| i as f64)
68            .unwrap_or(0.0)
69    }
70
71    fn breaks(&self) -> Vec<(f64, String)> {
72        self.levels
73            .iter()
74            .enumerate()
75            .map(|(i, label)| (i as f64, label.clone()))
76            .collect()
77    }
78
79    fn name(&self) -> &str {
80        &self.name
81    }
82
83    fn set_name(&mut self, name: &str) {
84        self.name = name.to_string();
85    }
86
87    fn is_discrete(&self) -> bool {
88        true
89    }
90
91    fn map_to_color(&self, value: &Value) -> Option<(u8, u8, u8)> {
92        let key = value.to_group_key();
93        let idx = self.levels.iter().position(|l| l == &key).unwrap_or(0);
94        let g = self.grey_for_index(idx);
95        Some((g, g, g))
96    }
97
98    fn clone_box(&self) -> Box<dyn Scale> {
99        Box::new(self.clone())
100    }
101
102    fn reset_training(&mut self) {
103        self.levels.clear();
104    }
105}