use crate::scale::Scale;
use crate::theme::Theme;
use crate::visual::color::{ColorMap, ColorPalette, SingleColor};
use crate::visual::shape::PointShape;
#[derive(Debug, Clone)]
pub enum VisualMapper {
ContinuousColor { map: ColorMap },
DiscreteColor { palette: ColorPalette },
Shape {
custom_shapes: Option<Vec<PointShape>>,
},
Size {
range: (f64, f64),
},
}
impl VisualMapper {
pub fn new_color_default(scale_type: &Scale, theme: &Theme) -> Self {
match scale_type {
Scale::Discrete => VisualMapper::DiscreteColor {
palette: theme.palette,
},
_ => VisualMapper::ContinuousColor {
map: theme.color_map,
},
}
}
pub fn new_size_default(min: f64, max: f64) -> Self {
VisualMapper::Size { range: (min, max) }
}
pub fn new_shape_default() -> Self {
VisualMapper::Shape {
custom_shapes: None,
}
}
pub fn map_to_color(&self, norm: f64, logical_max: f64) -> SingleColor {
match self {
VisualMapper::ContinuousColor { map } => {
map.get_color(norm)
}
VisualMapper::DiscreteColor { palette } => {
let index = (norm * logical_max).round() as usize;
palette.get_color(index)
}
_ => SingleColor::default(),
}
}
pub fn map_to_shape(&self, norm: f64, logical_max: f64) -> PointShape {
match self {
VisualMapper::Shape { custom_shapes } => {
let shapes = custom_shapes
.as_deref()
.unwrap_or(PointShape::LEGEND_SHAPES);
if shapes.is_empty() {
return PointShape::Circle;
}
let index = (norm * logical_max).round() as usize;
shapes[index % shapes.len()]
}
_ => PointShape::Circle,
}
}
pub fn map_to_size(&self, norm: f64) -> f64 {
match self {
VisualMapper::Size { range } => range.0 + norm * (range.1 - range.0),
_ => 5.0,
}
}
}