11use crate :: style:: { HSLColor , RGBAColor , RGBColor } ;
22
3- use num_traits:: { Float , FromPrimitive , ToPrimitive } ;
4-
53/// Converts scalar values to colors.
64pub trait ColorMap < ColorType : crate :: prelude:: Color , FloatType = f32 >
75where
8- FloatType : Float ,
6+ FloatType : num_traits :: Float ,
97{
108 /// Takes a scalar value 0.0 <= h <= 1.0 and returns the corresponding color.
119 /// Typically color-scales are named according to which color-type they return.
@@ -47,6 +45,8 @@ impl<ColorType: crate::style::Color + Clone> DerivedColorMap<ColorType> {
4745 }
4846}
4947
48+ #[ macro_export]
49+ #[ doc( hidden) ]
5050macro_rules! calculate_new_color_value(
5151 ( $relative_difference: expr, $colors: expr, $index_upper: expr, $index_lower: expr, RGBColor ) => {
5252 RGBColor (
@@ -81,20 +81,34 @@ macro_rules! calculate_new_color_value(
8181 } ;
8282) ;
8383
84- fn calculate_relative_difference_index_lower_upper <
85- FloatType : Float + FromPrimitive + ToPrimitive ,
84+ // Helper function to calculate the lower and upper index nearest to a provided float value.
85+ //
86+ // Used to obtain colors from a colorscale given a value h between 0.0 and 1.0.
87+ // It also returns the relative difference which can then be used to calculate a linear interpolation between the two nearest colors.
88+ // ```
89+ // # use plotters::prelude::*;
90+ // let r = calculate_relative_difference_index_lower_upper(1.2, 1.0, 3.0, 4);
91+ // let (relative_difference, lower_index, upper_index) = r;
92+ //
93+ // assert_eq!(relative_difference, 0.7000000000000001);
94+ // assert_eq!(lower_index, 0);
95+ // assert_eq!(upper_index, 1);
96+ // ```
97+ #[ doc( hidden) ]
98+ pub fn calculate_relative_difference_index_lower_upper <
99+ FloatType : num_traits:: Float + num_traits:: FromPrimitive + num_traits:: ToPrimitive ,
86100> (
87101 h : FloatType ,
88102 min : FloatType ,
89103 max : FloatType ,
90- n_colors : usize ,
104+ n_steps : usize ,
91105) -> ( FloatType , usize , usize ) {
92106 // Ensure that we do have a value in bounds
93107 let h = num_traits:: clamp ( h, min, max) ;
94108 // Next calculate a normalized value between 0.0 and 1.0
95109 let t = ( h - min) / ( max - min) ;
96110 let approximate_index =
97- t * ( FloatType :: from_usize ( n_colors ) . unwrap ( ) - FloatType :: one ( ) ) . max ( FloatType :: zero ( ) ) ;
111+ t * ( FloatType :: from_usize ( n_steps ) . unwrap ( ) - FloatType :: one ( ) ) . max ( FloatType :: zero ( ) ) ;
98112 // Calculate which index are the two most nearest of the supplied value
99113 let index_lower = approximate_index. floor ( ) . to_usize ( ) . unwrap ( ) ;
100114 let index_upper = approximate_index. ceil ( ) . to_usize ( ) . unwrap ( ) ;
@@ -106,7 +120,7 @@ fn calculate_relative_difference_index_lower_upper<
106120macro_rules! implement_color_scale_for_derived_color_map{
107121 ( $( $color_type: ident) ,+) => {
108122 $(
109- impl <FloatType : Float + FromPrimitive + ToPrimitive > ColorMap <$color_type, FloatType > for DerivedColorMap <$color_type> {
123+ impl <FloatType : num_traits :: Float + num_traits :: FromPrimitive + num_traits :: ToPrimitive > ColorMap <$color_type, FloatType > for DerivedColorMap <$color_type> {
110124 fn get_color_normalized( & self , h: FloatType , min: FloatType , max: FloatType ) -> $color_type {
111125 let (
112126 relative_difference,
@@ -119,7 +133,7 @@ macro_rules! implement_color_scale_for_derived_color_map{
119133 self . colors. len( )
120134 ) ;
121135 // Interpolate the final color linearly
122- calculate_new_color_value!(
136+ $crate :: calculate_new_color_value!(
123137 relative_difference,
124138 self . colors,
125139 index_upper,
@@ -134,11 +148,30 @@ macro_rules! implement_color_scale_for_derived_color_map{
134148
135149implement_color_scale_for_derived_color_map ! { RGBAColor , RGBColor , HSLColor }
136150
151+ #[ macro_export]
152+ #[ doc( hidden) ]
153+ // Counts the number of arguments which are separated by spaces
154+ //
155+ // This macro is used internally to determine the size of an array to hold all new colors.
156+ // ```
157+ // # use plotters::count;
158+ // let counted = count!{Plotting is fun};
159+ // assert_eq!(counted, 3);
160+ //
161+ // let counted2 = count!{0_usize was my favourite 1_f64 last century};
162+ // assert_eq!(counted2, 7);
163+ //
164+ // let new_array = ["Hello"; count!(Plotting is fun)];
165+ // assert_eq!(new_array, ["Hello"; 3]);
166+ // ```
137167macro_rules! count {
138168 ( ) => ( 0usize ) ;
139- ( $x: tt $( $xs: tt) * ) => ( 1usize + count!( $( $xs) * ) ) ;
169+ ( $x: tt $( $xs: tt) * ) => ( 1usize + $crate :: count!( $( $xs) * ) ) ;
140170}
141171
172+ #[ macro_export]
173+ #[ doc( hidden) ]
174+ /// Converts a given color identifier and a sequence of colors to an array of them.
142175macro_rules! define_colors_from_list_of_values_or_directly{
143176 ( $color_type: ident, $( ( $( $color_value: expr) ,+) ) ,+) => {
144177 [ $( $color_type( $( $color_value) ,+) ) ,+]
@@ -148,9 +181,12 @@ macro_rules! define_colors_from_list_of_values_or_directly{
148181 } ;
149182}
150183
184+ #[ macro_export]
185+ #[ doc( hidden) ]
186+ /// Implements the [ColorMap] trait on a given color scale.
151187macro_rules! implement_linear_interpolation_color_map {
152188 ( $color_scale_name: ident, $color_type: ident) => {
153- impl <FloatType : std:: fmt:: Debug + Float + FromPrimitive + ToPrimitive >
189+ impl <FloatType : std:: fmt:: Debug + num_traits :: Float + num_traits :: FromPrimitive + num_traits :: ToPrimitive >
154190 ColorMap <$color_type, FloatType > for $color_scale_name
155191 {
156192 fn get_color_normalized(
@@ -170,7 +206,7 @@ macro_rules! implement_linear_interpolation_color_map {
170206 Self :: COLORS . len( )
171207 ) ;
172208 // Interpolate the final color linearly
173- calculate_new_color_value!(
209+ $crate :: calculate_new_color_value!(
174210 relative_difference,
175211 Self :: COLORS ,
176212 index_upper,
@@ -184,7 +220,7 @@ macro_rules! implement_linear_interpolation_color_map {
184220 #[ doc = "Get color value from `" ]
185221 #[ doc = stringify!( $color_scale_name) ]
186222 #[ doc = "` by supplying a parameter 0.0 <= h <= 1.0" ]
187- pub fn get_color<FloatType : std:: fmt:: Debug + Float + FromPrimitive + ToPrimitive >(
223+ pub fn get_color<FloatType : std:: fmt:: Debug + num_traits :: Float + num_traits :: FromPrimitive + num_traits :: ToPrimitive >(
188224 h: FloatType ,
189225 ) -> $color_type {
190226 let color_scale = $color_scale_name { } ;
@@ -195,7 +231,7 @@ macro_rules! implement_linear_interpolation_color_map {
195231 #[ doc = stringify!( $color_scale_name) ]
196232 #[ doc = "` by supplying lower and upper bounds min, max and a parameter h where min <= h <= max" ]
197233 pub fn get_color_normalized<
198- FloatType : std:: fmt:: Debug + Float + FromPrimitive + ToPrimitive ,
234+ FloatType : std:: fmt:: Debug + num_traits :: Float + num_traits :: FromPrimitive + num_traits :: ToPrimitive ,
199235 >(
200236 h: FloatType ,
201237 min: FloatType ,
@@ -208,34 +244,57 @@ macro_rules! implement_linear_interpolation_color_map {
208244 } ;
209245}
210246
247+ #[ doc( inline) ]
248+ pub use crate :: def_linear_colormap;
249+
211250#[ macro_export]
212- /// Macro to create a new colormap with evenly spaced colors at compile-time.
213- macro_rules! define_linear_interpolation_color_map{
251+ #[ doc( hidden) ]
252+ /// Create a new colormap with evenly spaced colors and interpolates between them automatically.
253+ ///
254+ /// This macro works by taking a identifier (name) for the colormap, the type of color to specify, a
255+ /// docstring and a list of colors and constructs an empty struct on which it implements the [ColorMap] trait.
256+ ///
257+ /// ```
258+ /// use plotters::prelude::*;
259+ /// def_linear_colormap! {
260+ /// BlackWhite,
261+ /// RGBColor,
262+ /// "Simple chromatic colormap from black to white.",
263+ /// ( 0, 0, 0),
264+ /// (255, 255, 255)
265+ /// }
266+ ///
267+ /// assert_eq!(BlackWhite::get_color(0.0), RGBColor(0,0,0));
268+ /// ```
269+ ///
270+ /// Hint: Some helper macros and functions have been deliberately hidden from end users.
271+ /// Look for them in the source code if you are interested.
272+ macro_rules! def_linear_colormap{
214273 ( $color_scale_name: ident, $color_type: ident, $doc: expr, $( ( $( $color_value: expr) ,+) ) ,* ) => {
215274 #[ doc = $doc]
216- pub struct $color_scale_name { }
275+ pub struct $color_scale_name;
217276
218277 impl $color_scale_name {
219278 // const COLORS: [$color_type; $number_colors] = [$($color_type($($color_value),+)),+];
220- // const COLORS: [$color_type; count!($(($($color_value:expr),+))*)] = [$($color_type($($color_value),+)),+];
221- const COLORS : [ $color_type; count!( $( ( $( $color_value: expr) ,+) ) * ) ] = define_colors_from_list_of_values_or_directly!{ $color_type, $( ( $( $color_value) ,+) ) ,* } ;
279+ // const COLORS: [$color_type; $crate:: count!($(($($color_value:expr),+))*)] = [$($color_type($($color_value),+)),+];
280+ const COLORS : [ $color_type; $crate :: count!( $( ( $( $color_value: expr) ,+) ) * ) ] = $crate :: define_colors_from_list_of_values_or_directly!{ $color_type, $( ( $( $color_value) ,+) ) ,* } ;
222281 }
223282
224- implement_linear_interpolation_color_map!{ $color_scale_name, $color_type}
283+ $crate :: implement_linear_interpolation_color_map!{ $color_scale_name, $color_type}
225284 } ;
226285 ( $color_scale_name: ident, $color_type: ident, $doc: expr, $( $color_complete: tt) ,+) => {
227286 #[ doc = $doc]
228- pub struct $color_scale_name { }
287+ pub struct $color_scale_name;
229288
230289 impl $color_scale_name {
231- const COLORS : [ $color_type; count!( $( $color_complete) * ) ] = define_colors_from_list_of_values_or_directly!{ $( $color_complete) ,+} ;
290+ const COLORS : [ $color_type; $crate :: count!( $( $color_complete) * ) ] = $crate :: define_colors_from_list_of_values_or_directly!{ $( $color_complete) ,+} ;
232291 }
233292
234- implement_linear_interpolation_color_map!{ $color_scale_name, $color_type}
293+ $crate :: implement_linear_interpolation_color_map!{ $color_scale_name, $color_type}
235294 }
236295}
237296
238- define_linear_interpolation_color_map ! {
297+ def_linear_colormap ! {
239298 ViridisRGBA ,
240299 RGBAColor ,
241300 "A colormap optimized for visually impaired people (RGBA format).
@@ -251,7 +310,7 @@ define_linear_interpolation_color_map! {
251310 ( 254 , 232 , 37 , 1.0 )
252311}
253312
254- define_linear_interpolation_color_map ! {
313+ def_linear_colormap ! {
255314 ViridisRGB ,
256315 RGBColor ,
257316 "A colormap optimized for visually impaired people (RGB Format).
@@ -267,23 +326,23 @@ define_linear_interpolation_color_map! {
267326 ( 254 , 232 , 37 )
268327}
269328
270- define_linear_interpolation_color_map ! {
329+ def_linear_colormap ! {
271330 BlackWhite ,
272331 RGBColor ,
273332 "Simple chromatic colormap from black to white." ,
274333 ( 0 , 0 , 0 ) ,
275334 ( 255 , 255 , 255 )
276335}
277336
278- define_linear_interpolation_color_map ! {
337+ def_linear_colormap ! {
279338 MandelbrotHSL ,
280339 HSLColor ,
281340 "Colormap created to replace the one used in the mandelbrot example." ,
282341 ( 0.0 , 1.0 , 0.5 ) ,
283342 ( 1.0 , 1.0 , 0.5 )
284343}
285344
286- define_linear_interpolation_color_map ! {
345+ def_linear_colormap ! {
287346 VulcanoHSL ,
288347 HSLColor ,
289348 "A vulcanic colormap that display red/orange and black colors" ,
@@ -292,7 +351,7 @@ define_linear_interpolation_color_map! {
292351}
293352
294353use super :: full_palette:: * ;
295- define_linear_interpolation_color_map ! {
354+ def_linear_colormap ! {
296355 Bone ,
297356 RGBColor ,
298357 "Dark colormap going from black over blue to white." ,
@@ -301,7 +360,7 @@ define_linear_interpolation_color_map! {
301360 WHITE
302361}
303362
304- define_linear_interpolation_color_map ! {
363+ def_linear_colormap ! {
305364 Copper ,
306365 RGBColor ,
307366 "Friendly black to brown colormap." ,
0 commit comments