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
#[derive(Clone)]
pub struct RGBAColour {
r: u8,
g: u8,
b: u8,
a: u8,
}
impl RGBAColour {
pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
Self { r, g, b, a }
}
pub fn to_vec(&self) -> Vec<u8> {
vec![self.r, self.g, self.b, self.a]
}
}
pub struct ColourGradient {
colours: Vec<RGBAColour>,
min: f32,
max: f32,
}
impl ColourGradient {
pub fn new() -> Self {
Self {
colours: vec![],
min: 0.0,
max: 1.0,
}
}
pub fn get_colour(&self, value: f32) -> RGBAColour {
assert!(self.colours.len() > 1);
if value >= self.max {
return self.colours.last().unwrap().clone();
}
let mut ratio = value / self.max;
let width = 1.0 / (self.colours.len() as f32 - 1.0);
let mut i = 0;
while ratio > width {
ratio -= width;
i += 1;
}
ratio *= (self.colours.len() - 1) as f32;
assert!(0.0 <= ratio);
assert!(ratio <= 1.0);
assert!(i < self.colours.len());
let first = self.colours[i].clone();
let second = self.colours[i + 1].clone();
RGBAColour {
r: self.interpolate(first.r, second.r, ratio),
g: self.interpolate(first.g, second.g, ratio),
b: self.interpolate(first.b, second.b, ratio),
a: 255,
}
}
pub fn add_colour(&mut self, colour: RGBAColour) {
self.colours.push(colour);
}
fn interpolate(&self, start: u8, finish: u8, ratio: f32) -> u8 {
((f32::from(finish) - f32::from(start)) * ratio + f32::from(start)).round() as u8
}
pub fn set_max(&mut self, max: f32) {
self.max = max
}
pub fn set_min(&mut self, min: f32) {
self.min = min
}
}