|
| 1 | +use crate::style::{HSLColor,RGBAColor,RGBColor}; |
| 2 | + |
| 3 | +use num_traits::{Float,ToPrimitive,FromPrimitive}; |
| 4 | + |
1 | 5 | pub trait ColorScale<ColorType: crate::prelude::Color, FloatType=f32>
|
2 | 6 | where
|
3 | 7 | FloatType: Float,
|
|
8 | 12 |
|
9 | 13 | fn get_color_normalized(&self, h: FloatType, min: FloatType, max: FloatType) -> ColorType;
|
10 | 14 | }
|
| 15 | + |
| 16 | + |
| 17 | +macro_rules! count { |
| 18 | + () => (0usize); |
| 19 | + ($x:tt $($xs:tt)* ) => (1usize + count!($($xs)*)); |
| 20 | +} |
| 21 | + |
| 22 | + |
| 23 | +macro_rules! define_colors_from_list_of_values_or_directly{ |
| 24 | + ($color_type:tt, $(($($color_value:expr),+)),+) => { |
| 25 | + [$($color_type($($color_value),+)),+] |
| 26 | + }; |
| 27 | + ($($color_complete:tt),+) => { |
| 28 | + [$($color_complete),+] |
| 29 | + }; |
| 30 | +} |
| 31 | + |
| 32 | + |
| 33 | +macro_rules! implement_linear_interpolation_color_map{ |
| 34 | + ($color_scale_name:ident, $color_type:tt) => { |
| 35 | + impl<FloatType: std::fmt::Debug + Float + FromPrimitive + ToPrimitive> ColorScale<$color_type, FloatType> for $color_scale_name { |
| 36 | + fn get_color_normalized(&self, h: FloatType, min: FloatType, max: FloatType) -> $color_type { |
| 37 | + // Ensure that we do have a value in bounds |
| 38 | + let h = h.max(min).min(max); |
| 39 | + // Make sure that we really have a minimal value which is smaller than the maximal value |
| 40 | + assert_eq!(min<max, true); |
| 41 | + // Next calculate a normalized value between 0.0 and 1.0 |
| 42 | + let t = (h - min)/(max-min); |
| 43 | + let approximate_index = t * (FloatType::from_usize(Self::COLORS.len()).unwrap() - FloatType::one()).max(FloatType::zero()); |
| 44 | + // Calculate which index are the two most nearest of the supplied value |
| 45 | + let index_lower = approximate_index.floor().to_usize().unwrap(); |
| 46 | + let index_upper = approximate_index.ceil().to_usize().unwrap(); |
| 47 | + // Calculate the relative difference, ie. is the actual value more towards the color of index_upper or index_lower? |
| 48 | + let relative_difference = approximate_index.ceil() - approximate_index; |
| 49 | + // Interpolate the final color linearly |
| 50 | + calculate_new_color_value!(relative_difference, Self::COLORS, index_upper, index_lower, $color_type) |
| 51 | + } |
| 52 | + } |
| 53 | + |
| 54 | + impl $color_scale_name { |
| 55 | + pub fn get_color<FloatType: std::fmt::Debug + Float + FromPrimitive + ToPrimitive>(h: FloatType) -> $color_type { |
| 56 | + let color_scale = $color_scale_name {}; |
| 57 | + color_scale.get_color(h) |
| 58 | + } |
| 59 | + |
| 60 | + pub fn get_color_normalized<FloatType: std::fmt::Debug + Float + FromPrimitive + ToPrimitive>(h: FloatType, min: FloatType, max: FloatType) -> $color_type { |
| 61 | + let color_scale = $color_scale_name {}; |
| 62 | + color_scale.get_color_normalized(h, min, max) |
| 63 | + } |
| 64 | + } |
| 65 | + } |
| 66 | +} |
| 67 | + |
| 68 | + |
| 69 | +#[macro_export] |
| 70 | +macro_rules! define_linear_interpolation_color_map{ |
| 71 | + ($color_scale_name:ident, $color_type:tt, $(($($color_value:expr),+)),*) => { |
| 72 | + pub struct $color_scale_name {} |
| 73 | + |
| 74 | + impl $color_scale_name { |
| 75 | + // const COLORS: [$color_type; $number_colors] = [$($color_type($($color_value),+)),+]; |
| 76 | + // const COLORS: [$color_type; count!($(($($color_value:expr),+))*)] = [$($color_type($($color_value),+)),+]; |
| 77 | + const COLORS: [$color_type; count!($(($($color_value:expr),+))*)] = define_colors_from_list_of_values_or_directly!{$color_type, $(($($color_value),+)),*}; |
| 78 | + } |
| 79 | + |
| 80 | + implement_linear_interpolation_color_map!{$color_scale_name, $color_type} |
| 81 | + }; |
| 82 | + ($color_scale_name:ident, $color_type:tt, $($color_complete:tt),+) => { |
| 83 | + pub struct $color_scale_name {} |
| 84 | + |
| 85 | + impl $color_scale_name { |
| 86 | + const COLORS: [$color_type; count!($($color_complete)*)] = define_colors_from_list_of_values_or_directly!{$($color_complete),+}; |
| 87 | + } |
| 88 | + |
| 89 | + implement_linear_interpolation_color_map!{$color_scale_name, $color_type} |
| 90 | + } |
| 91 | +} |
0 commit comments