#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct DataRange {
pub min_x: f64,
pub min_y: f64,
pub max_x: f64,
pub max_y: f64,
pub offset: Option<f64>,
pub scale: Option<f64>,
}
impl DataRange {
pub fn normalize(&self, v: f64) -> f64 {
(v - self.offset()) / self.scale()
}
pub fn denormalize(&self, v_scaled: f64) -> f64 {
v_scaled * self.scale() + self.offset()
}
fn offset(&self) -> f64 {
self.offset
.unwrap_or_else(|| f64::min(self.min_x, self.min_y))
}
fn scale(&self) -> f64 {
self.scale
.unwrap_or_else(|| f64::max(self.max_x, self.max_y) - self.offset())
}
}
impl Default for DataRange {
fn default() -> Self {
Self {
min_x: 0.0,
min_y: 0.0,
max_x: 1.0,
max_y: 1.0,
offset: None,
scale: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_data_range_default() {
let data_range = DataRange::default();
assert_eq!(data_range.min_x, 0.0);
assert_eq!(data_range.min_y, 0.0);
assert_eq!(data_range.max_x, 1.0);
assert_eq!(data_range.max_y, 1.0);
}
#[test]
fn test_data_range() {
let data_range = DataRange {
min_x: -10.0,
max_x: 100.0,
min_y: -20.0,
max_y: 50.0,
..Default::default()
};
assert_eq!(data_range.normalize(-20.0), 0.0);
assert_eq!(data_range.normalize(40.0), 0.5);
assert_eq!(data_range.normalize(100.0), 1.0);
assert_eq!(data_range.denormalize(0.0), -20.0);
assert_eq!(data_range.denormalize(0.5), 40.0);
assert_eq!(data_range.denormalize(1.0), 100.0);
}
}