use crate::{Quantity, Unit};
use qtty_derive::Unit;
pub use crate::dimension::Area;
pub trait AreaUnit: Unit<Dim = Area> {}
impl<T: Unit<Dim = Area>> AreaUnit for T {}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "m²", dimension = Area, ratio = 1.0)]
pub struct SquareMeter;
pub type SquareMeters = Quantity<SquareMeter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "km²", dimension = Area, ratio = 1e6)]
pub struct SquareKilometer;
pub type SquareKilometers = Quantity<SquareKilometer>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "cm²", dimension = Area, ratio = 1e-4)]
pub struct SquareCentimeter;
pub type SquareCentimeters = Quantity<SquareCentimeter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "mm²", dimension = Area, ratio = 1e-6)]
pub struct SquareMillimeter;
pub type SquareMillimeters = Quantity<SquareMillimeter>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "ha", dimension = Area, ratio = 1e4)]
pub struct Hectare;
pub type Hectares = Quantity<Hectare>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "a", dimension = Area, ratio = 100.0)]
pub struct Are;
pub type Ares = Quantity<Are>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "in²", dimension = Area, ratio = 6.4516e-4)]
pub struct SquareInch;
pub type SquareInches = Quantity<SquareInch>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "ft²", dimension = Area, ratio = 0.09290304)]
pub struct SquareFoot;
pub type SquareFeet = Quantity<SquareFoot>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "yd²", dimension = Area, ratio = 0.83612736)]
pub struct SquareYard;
pub type SquareYards = Quantity<SquareYard>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "mi²", dimension = Area, ratio = 2_589_988.110_336)]
pub struct SquareMile;
pub type SquareMiles = Quantity<SquareMile>;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
#[unit(symbol = "ac", dimension = Area, ratio = 4_046.856_422_4)]
pub struct Acre;
pub type Acres = Quantity<Acre>;
#[cfg(test)]
mod tests {
use super::*;
use approx::assert_abs_diff_eq;
#[test]
fn sqm_to_sqkm() {
let a = SquareMeters::new(1_000_000.0);
let b: SquareKilometers = a.to();
assert_abs_diff_eq!(b.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn hectare_to_sqm() {
let a = Hectares::new(1.0);
let b: SquareMeters = a.to();
assert_abs_diff_eq!(b.value(), 10_000.0, epsilon = 1e-9);
}
#[test]
fn acre_to_hectare() {
let a = Acres::new(1.0);
let b: Hectares = a.to();
assert_abs_diff_eq!(b.value(), 0.404_685_642_24, epsilon = 1e-9);
}
#[test]
fn sqft_to_sqm() {
let a = SquareFeet::new(1.0);
let b: SquareMeters = a.to();
assert_abs_diff_eq!(b.value(), 0.092_903_04, epsilon = 1e-9);
}
#[test]
fn length_product_to_area() {
use crate::length::{Meter, Meters};
use crate::Prod;
let side = Meters::new(5.0);
let area_prod: Quantity<Prod<Meter, Meter>> = side * side;
let area: SquareMeters = area_prod.to();
assert_abs_diff_eq!(area.value(), 25.0, epsilon = 1e-12);
}
#[test]
fn sqmile_to_sqkm() {
let a = SquareMiles::new(1.0);
let b: SquareKilometers = a.to();
assert_abs_diff_eq!(b.value(), 2.589_988_110_336, epsilon = 1e-6);
}
#[test]
fn sqcm_to_sqm() {
let a = SquareCentimeters::new(10_000.0);
let b: SquareMeters = a.to();
assert_abs_diff_eq!(b.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn sqmm_to_sqcm() {
let a = SquareMillimeters::new(100.0);
let b: SquareCentimeters = a.to();
assert_abs_diff_eq!(b.value(), 1.0, epsilon = 1e-12);
}
#[test]
fn are_to_sqm() {
let a = Ares::new(1.0);
let b: SquareMeters = a.to();
assert_abs_diff_eq!(b.value(), 100.0, epsilon = 1e-12);
}
#[test]
fn sqinch_to_sqcm() {
let a = SquareInches::new(1.0);
let b: SquareCentimeters = a.to();
assert_abs_diff_eq!(b.value(), 6.4516, epsilon = 1e-9);
}
#[test]
fn sqyard_to_sqm() {
let a = SquareYards::new(1.0);
let b: SquareMeters = a.to();
assert_abs_diff_eq!(b.value(), 0.836_127_36, epsilon = 1e-9);
}
#[test]
fn roundtrip_sqcm_sqm() {
let original = SquareCentimeters::new(250.0);
let converted = original.to::<SquareMeter>();
let back = converted.to::<SquareCentimeter>();
assert_abs_diff_eq!(back.value(), original.value(), epsilon = 1e-10);
}
#[test]
fn symbols_are_correct() {
assert_eq!(SquareMeter::SYMBOL, "m²");
assert_eq!(Hectare::SYMBOL, "ha");
assert_eq!(Acre::SYMBOL, "ac");
assert_eq!(SquareInch::SYMBOL, "in²");
}
}