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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
pub mod alpha;
pub mod color;
pub mod continuous;
pub mod datetime;
pub mod discrete;
pub mod format;
pub mod gradient;
pub mod gradient_n;
pub mod grey;
pub mod linetype;
pub mod linetype_manual;
pub mod manual;
pub mod modified;
pub mod palettes;
pub mod scale_set;
pub mod sec_axis;
pub mod shape;
pub mod shape_manual;
pub mod size;
pub mod steps;
pub mod transform;
pub mod util;
pub use scale_set::ScaleSet;
use crate::aes::Aesthetic;
use crate::data::Value;
use crate::render::backend::{Linetype, PointShape};
/// Trait for scales that map data values to visual properties.
pub trait Scale: Send + Sync {
/// Which aesthetic this scale is for.
fn aesthetic(&self) -> Aesthetic;
/// Incorporate data values to determine domain.
fn train(&mut self, values: &[Value]);
/// Map a data value to a [0, 1] normalized position (position scales)
/// or to a concrete visual value index (color/size scales).
fn map(&self, value: &Value) -> f64;
/// Generate break positions and labels for axis/legend.
fn breaks(&self) -> Vec<(f64, String)>;
/// Human-readable name (axis title).
fn name(&self) -> &str;
/// Set the scale name.
fn set_name(&mut self, name: &str);
/// Apply transformation to raw data (e.g., log10).
fn transform(&self, value: &Value) -> Value {
value.clone()
}
/// Whether this is a discrete scale.
fn is_discrete(&self) -> bool {
false
}
/// Map a data value to an RGB color. Default returns None.
fn map_to_color(&self, _value: &Value) -> Option<(u8, u8, u8)> {
None
}
/// Map a data value to a point shape. Default returns None.
fn map_to_shape(&self, _value: &Value) -> Option<PointShape> {
None
}
/// Map a data value to a linetype. Default returns None.
fn map_to_linetype(&self, _value: &Value) -> Option<Linetype> {
None
}
/// Map a data value to a point size (radius in pixels). Default returns None.
fn map_to_size(&self, _value: &Value) -> Option<f64> {
None
}
/// Map a data value to an alpha (opacity) value. Default returns None.
fn map_to_alpha(&self, _value: &Value) -> Option<f64> {
None
}
/// Get the secondary axis specification, if any.
fn sec_axis(&self) -> Option<&sec_axis::SecAxis> {
None
}
/// Adopt a plot-level default [`Locale`](crate::locale::Locale) for the
/// default break labels (number marks, month names, date formats), unless
/// the scale already has its own. Called by the plot builder when
/// [`GGPlot::locale`](crate::GGPlot::locale) is set. Default: ignored
/// (scales without numeric/date labels).
fn set_default_locale(&mut self, _locale: &crate::locale::Locale) {}
/// The locale this scale's default labels are rendered with, if any.
fn locale(&self) -> Option<&crate::locale::Locale> {
None
}
/// Override the trained domain limits (used by coord_cartesian zoom).
fn set_limits(&mut self, _min: f64, _max: f64) {
// Default no-op. Continuous scales override this.
}
/// Return OOB filter limits if this scale was created with explicit limits
/// (e.g., via xlim/ylim). Data outside these limits should be removed before stats.
fn filter_limits(&self) -> Option<(f64, f64)> {
None
}
/// Return the trained data domain (min, max) for continuous scales.
/// Used by the colorbar legend to pass data-space values to map_to_color().
fn domain(&self) -> Option<(f64, f64)> {
None
}
/// The data values at the panel edges (normalized 0 and 1) for a trained
/// continuous position scale — the limits after expansion, in the scale's
/// transformed space. `None` for discrete / untrained / non-position scales.
fn expanded_domain(&self) -> Option<(f64, f64)> {
None
}
/// Whether this axis is drawn on the opposite side (x → top, y → right).
fn axis_position_opposite(&self) -> bool {
false
}
/// Clone this scale into a boxed trait object.
fn clone_box(&self) -> Box<dyn Scale>;
/// Reset training state so the scale can be retrained on new data.
fn reset_training(&mut self) {}
}