use crate::render::Rect;
use super::{AxisSpan, Coord};
#[derive(Default)]
pub struct CoordSf {
x_span: Option<AxisSpan>,
y_span: Option<AxisSpan>,
}
impl CoordSf {
pub fn new() -> Self {
Self::default()
}
fn ratio(&self) -> f64 {
match (&self.x_span, &self.y_span) {
(Some(x), Some(y)) if (x.max - x.min).abs() > f64::EPSILON => {
((y.max - y.min) / (x.max - x.min)).abs()
}
_ => 1.0,
}
}
}
impl Coord for CoordSf {
fn set_domains(&mut self, x: Option<AxisSpan>, y: Option<AxisSpan>) {
self.x_span = x;
self.y_span = y;
}
fn transform(&self, point: (f64, f64), plot_area: &Rect) -> (f64, f64) {
let data_aspect = self.ratio();
let pixel_aspect = plot_area.height / plot_area.width;
let (eff_w, eff_h, off_x, off_y) = if pixel_aspect > data_aspect {
let h = plot_area.width * data_aspect;
(plot_area.width, h, 0.0, (plot_area.height - h) / 2.0)
} else {
let w = plot_area.height / data_aspect;
(w, plot_area.height, (plot_area.width - w) / 2.0, 0.0)
};
let (nx, ny) = point;
let px = plot_area.x + off_x + nx * eff_w;
let py = plot_area.y + off_y + (1.0 - ny) * eff_h;
(px, py)
}
}