use crate::render::Rect;
use super::Coord;
pub struct CoordCartesian {
xlim: Option<(f64, f64)>,
ylim: Option<(f64, f64)>,
reverse_x: bool,
reverse_y: bool,
expand: [bool; 4],
}
impl CoordCartesian {
pub fn new() -> Self {
CoordCartesian {
xlim: None,
ylim: None,
reverse_x: false,
reverse_y: false,
expand: [true; 4],
}
}
pub fn expand(mut self, top: bool, right: bool, bottom: bool, left: bool) -> Self {
self.expand = [top, right, bottom, left];
self
}
pub fn reverse(mut self, x: bool, y: bool) -> Self {
self.reverse_x = x;
self.reverse_y = y;
self
}
pub fn xlim(mut self, min: f64, max: f64) -> Self {
self.xlim = Some((min, max));
self
}
pub fn ylim(mut self, min: f64, max: f64) -> Self {
self.ylim = Some((min, max));
self
}
pub fn get_xlim(&self) -> Option<(f64, f64)> {
self.xlim
}
pub fn get_ylim(&self) -> Option<(f64, f64)> {
self.ylim
}
}
impl Default for CoordCartesian {
fn default() -> Self {
Self::new()
}
}
impl Coord for CoordCartesian {
fn transform(&self, point: (f64, f64), plot_area: &Rect) -> (f64, f64) {
let (nx, ny) = point;
let nx = if self.reverse_x { 1.0 - nx } else { nx };
let ny = if self.reverse_y { 1.0 - ny } else { ny };
let px = plot_area.x + nx * plot_area.width;
let py = plot_area.y + (1.0 - ny) * plot_area.height;
(px, py)
}
fn zoom_x(&self) -> Option<(f64, f64)> {
self.xlim
}
fn zoom_y(&self) -> Option<(f64, f64)> {
self.ylim
}
fn train_scales(&mut self, scales: &mut crate::scale::ScaleSet) {
let [top, right, bottom, left] = self.expand.map(|e| !e);
let x = if self.reverse_x {
(right, left)
} else {
(left, right)
};
let y = if self.reverse_y {
(top, bottom)
} else {
(bottom, top)
};
for (aes, (lo, hi)) in [(crate::aes::Aesthetic::X, x), (crate::aes::Aesthetic::Y, y)] {
if lo || hi {
if let Some(s) = scales.get_mut(&aes) {
s.clear_expand(lo, hi);
}
}
}
}
}