sb-rust-library 0.1.7

Basic library providing common functionality I reuse in many of my projects
Documentation
use std::ops::Range;

use crate::math::{Point, Bounds, Vector};

pub struct PlotFrame {
  pt_lim: Bounds<f64>,
  px_lim: Bounds<i64>,
  px_pt_ratio: Vector,
}

impl PlotFrame {

  pub fn new(canvas_bounds: Bounds<i64>, plotting_range: Bounds<f64>) -> PlotFrame {
    let pt_lim = plotting_range;
    let px_lim = canvas_bounds;
    let px_pt_ratio = (1.0, 1.0).into(); // recomputed right below
    let mut frame = PlotFrame { pt_lim, px_lim, px_pt_ratio };
    frame.recalculate_scaling();
    frame
  }

  fn recalculate_scaling(&mut self) {
    self.px_pt_ratio.x = ((self.px_lim.x.end - self.px_lim.x.start) as f64) / (self.pt_lim.x.end - self.pt_lim.x.start);
    self.px_pt_ratio.y = ((self.px_lim.y.end - self.px_lim.y.start) as f64) / (self.pt_lim.y.end - self.pt_lim.y.start);
  }

  /// Returns a signed because it can be negative which panics for unsigned return type.
  fn x_pt_to_px(&self, x: f64) -> i64 {
    ((x - self.pt_lim.x.start) * self.px_pt_ratio.x).round() as i64 + self.px_lim.x.start
  }

  /// Returns a signed because it can be negative which panics for unsigned return type.
  fn y_pt_to_px(&self, y: f64) -> i64 {
    ((y - self.pt_lim.y.start) * self.px_pt_ratio.y).round() as i64 + self.px_lim.y.start
  }

  /// Converts a logical, real, cartesian point to its corresponding pixel in the plot image.
  /// Returns a signed pair because it can be negative which panics for unsigned return type.
  pub fn pt_to_px<T: Into<Point>>(&self, pt: T) -> (i64, i64) {
    let p = pt.into();
    (self.x_pt_to_px(p.x), self.y_pt_to_px(p.y)).into()
  }

  /// Converts a logical, real, cartesian point to its real-valued pixel location in the plot image.
  pub fn pt_to_px_pt<T: Into<Point>>(&self, pt: T) -> Point {
    let p = pt.into();
    (
      (p.x - self.pt_lim.x.start) * self.px_pt_ratio.x + (self.px_lim.x.start as f64),
      (p.y - self.pt_lim.y.start) * self.px_pt_ratio.y + (self.px_lim.y.start as f64)
    ).into()
  }

  pub fn set_drawing_bounds<R: Into<Range<i64>>>(&mut self, x_bounds: R, y_bounds: R) {
    self.px_lim.x = x_bounds.into();
    self.px_lim.y = y_bounds.into();
    self.recalculate_scaling();
  }

  pub fn set_plotting_range<R: Into<Range<f64>>>(&mut self, x_range: R, y_range: R) {
    self.pt_lim.x = x_range.into();
    self.pt_lim.y = y_range.into();
    self.recalculate_scaling();
  }

}