1
1
use crate :: style:: { HSLColor , RGBAColor , RGBColor } ;
2
2
3
- use num_traits:: { Float , FromPrimitive , ToPrimitive } ;
4
-
5
3
/// Converts scalar values to colors.
6
4
pub trait ColorMap < ColorType : crate :: prelude:: Color , FloatType = f32 >
7
5
where
8
- FloatType : Float ,
6
+ FloatType : num_traits :: Float ,
9
7
{
10
8
/// Takes a scalar value 0.0 <= h <= 1.0 and returns the corresponding color.
11
9
/// Typically color-scales are named according to which color-type they return.
@@ -47,6 +45,8 @@ impl<ColorType: crate::style::Color + Clone> DerivedColorMap<ColorType> {
47
45
}
48
46
}
49
47
48
+ #[ macro_export]
49
+ #[ doc( hidden) ]
50
50
macro_rules! calculate_new_color_value(
51
51
( $relative_difference: expr, $colors: expr, $index_upper: expr, $index_lower: expr, RGBColor ) => {
52
52
RGBColor (
@@ -81,20 +81,34 @@ macro_rules! calculate_new_color_value(
81
81
} ;
82
82
) ;
83
83
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 ,
86
100
> (
87
101
h : FloatType ,
88
102
min : FloatType ,
89
103
max : FloatType ,
90
- n_colors : usize ,
104
+ n_steps : usize ,
91
105
) -> ( FloatType , usize , usize ) {
92
106
// Ensure that we do have a value in bounds
93
107
let h = num_traits:: clamp ( h, min, max) ;
94
108
// Next calculate a normalized value between 0.0 and 1.0
95
109
let t = ( h - min) / ( max - min) ;
96
110
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 ( ) ) ;
98
112
// Calculate which index are the two most nearest of the supplied value
99
113
let index_lower = approximate_index. floor ( ) . to_usize ( ) . unwrap ( ) ;
100
114
let index_upper = approximate_index. ceil ( ) . to_usize ( ) . unwrap ( ) ;
@@ -106,7 +120,7 @@ fn calculate_relative_difference_index_lower_upper<
106
120
macro_rules! implement_color_scale_for_derived_color_map{
107
121
( $( $color_type: ident) ,+) => {
108
122
$(
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> {
110
124
fn get_color_normalized( & self , h: FloatType , min: FloatType , max: FloatType ) -> $color_type {
111
125
let (
112
126
relative_difference,
@@ -119,7 +133,7 @@ macro_rules! implement_color_scale_for_derived_color_map{
119
133
self . colors. len( )
120
134
) ;
121
135
// Interpolate the final color linearly
122
- calculate_new_color_value!(
136
+ $crate :: calculate_new_color_value!(
123
137
relative_difference,
124
138
self . colors,
125
139
index_upper,
@@ -134,11 +148,30 @@ macro_rules! implement_color_scale_for_derived_color_map{
134
148
135
149
implement_color_scale_for_derived_color_map ! { RGBAColor , RGBColor , HSLColor }
136
150
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
+ // ```
137
167
macro_rules! count {
138
168
( ) => ( 0usize ) ;
139
- ( $x: tt $( $xs: tt) * ) => ( 1usize + count!( $( $xs) * ) ) ;
169
+ ( $x: tt $( $xs: tt) * ) => ( 1usize + $crate :: count!( $( $xs) * ) ) ;
140
170
}
141
171
172
+ #[ macro_export]
173
+ #[ doc( hidden) ]
174
+ /// Converts a given color identifier and a sequence of colors to an array of them.
142
175
macro_rules! define_colors_from_list_of_values_or_directly{
143
176
( $color_type: ident, $( ( $( $color_value: expr) ,+) ) ,+) => {
144
177
[ $( $color_type( $( $color_value) ,+) ) ,+]
@@ -148,9 +181,12 @@ macro_rules! define_colors_from_list_of_values_or_directly{
148
181
} ;
149
182
}
150
183
184
+ #[ macro_export]
185
+ #[ doc( hidden) ]
186
+ /// Implements the [ColorMap] trait on a given color scale.
151
187
macro_rules! implement_linear_interpolation_color_map {
152
188
( $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 >
154
190
ColorMap <$color_type, FloatType > for $color_scale_name
155
191
{
156
192
fn get_color_normalized(
@@ -170,7 +206,7 @@ macro_rules! implement_linear_interpolation_color_map {
170
206
Self :: COLORS . len( )
171
207
) ;
172
208
// Interpolate the final color linearly
173
- calculate_new_color_value!(
209
+ $crate :: calculate_new_color_value!(
174
210
relative_difference,
175
211
Self :: COLORS ,
176
212
index_upper,
@@ -184,7 +220,7 @@ macro_rules! implement_linear_interpolation_color_map {
184
220
#[ doc = "Get color value from `" ]
185
221
#[ doc = stringify!( $color_scale_name) ]
186
222
#[ 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 >(
188
224
h: FloatType ,
189
225
) -> $color_type {
190
226
let color_scale = $color_scale_name { } ;
@@ -195,7 +231,7 @@ macro_rules! implement_linear_interpolation_color_map {
195
231
#[ doc = stringify!( $color_scale_name) ]
196
232
#[ doc = "` by supplying lower and upper bounds min, max and a parameter h where min <= h <= max" ]
197
233
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 ,
199
235
>(
200
236
h: FloatType ,
201
237
min: FloatType ,
@@ -208,34 +244,57 @@ macro_rules! implement_linear_interpolation_color_map {
208
244
} ;
209
245
}
210
246
247
+ #[ doc( inline) ]
248
+ pub use crate :: def_linear_colormap;
249
+
211
250
#[ 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{
214
273
( $color_scale_name: ident, $color_type: ident, $doc: expr, $( ( $( $color_value: expr) ,+) ) ,* ) => {
215
274
#[ doc = $doc]
216
- pub struct $color_scale_name { }
275
+ pub struct $color_scale_name;
217
276
218
277
impl $color_scale_name {
219
278
// 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) ,+) ) ,* } ;
222
281
}
223
282
224
- implement_linear_interpolation_color_map!{ $color_scale_name, $color_type}
283
+ $crate :: implement_linear_interpolation_color_map!{ $color_scale_name, $color_type}
225
284
} ;
226
285
( $color_scale_name: ident, $color_type: ident, $doc: expr, $( $color_complete: tt) ,+) => {
227
286
#[ doc = $doc]
228
- pub struct $color_scale_name { }
287
+ pub struct $color_scale_name;
229
288
230
289
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) ,+} ;
232
291
}
233
292
234
- implement_linear_interpolation_color_map!{ $color_scale_name, $color_type}
293
+ $crate :: implement_linear_interpolation_color_map!{ $color_scale_name, $color_type}
235
294
}
236
295
}
237
296
238
- define_linear_interpolation_color_map ! {
297
+ def_linear_colormap ! {
239
298
ViridisRGBA ,
240
299
RGBAColor ,
241
300
"A colormap optimized for visually impaired people (RGBA format).
@@ -251,7 +310,7 @@ define_linear_interpolation_color_map! {
251
310
( 254 , 232 , 37 , 1.0 )
252
311
}
253
312
254
- define_linear_interpolation_color_map ! {
313
+ def_linear_colormap ! {
255
314
ViridisRGB ,
256
315
RGBColor ,
257
316
"A colormap optimized for visually impaired people (RGB Format).
@@ -267,23 +326,23 @@ define_linear_interpolation_color_map! {
267
326
( 254 , 232 , 37 )
268
327
}
269
328
270
- define_linear_interpolation_color_map ! {
329
+ def_linear_colormap ! {
271
330
BlackWhite ,
272
331
RGBColor ,
273
332
"Simple chromatic colormap from black to white." ,
274
333
( 0 , 0 , 0 ) ,
275
334
( 255 , 255 , 255 )
276
335
}
277
336
278
- define_linear_interpolation_color_map ! {
337
+ def_linear_colormap ! {
279
338
MandelbrotHSL ,
280
339
HSLColor ,
281
340
"Colormap created to replace the one used in the mandelbrot example." ,
282
341
( 0.0 , 1.0 , 0.5 ) ,
283
342
( 1.0 , 1.0 , 0.5 )
284
343
}
285
344
286
- define_linear_interpolation_color_map ! {
345
+ def_linear_colormap ! {
287
346
VulcanoHSL ,
288
347
HSLColor ,
289
348
"A vulcanic colormap that display red/orange and black colors" ,
@@ -292,7 +351,7 @@ define_linear_interpolation_color_map! {
292
351
}
293
352
294
353
use super :: full_palette:: * ;
295
- define_linear_interpolation_color_map ! {
354
+ def_linear_colormap ! {
296
355
Bone ,
297
356
RGBColor ,
298
357
"Dark colormap going from black over blue to white." ,
@@ -301,7 +360,7 @@ define_linear_interpolation_color_map! {
301
360
WHITE
302
361
}
303
362
304
- define_linear_interpolation_color_map ! {
363
+ def_linear_colormap ! {
305
364
Copper ,
306
365
RGBColor ,
307
366
"Friendly black to brown colormap." ,
0 commit comments