Skip to main content

qtty_core/units/
area.rs

1//! Area units.
2//!
3//! The canonical scaling unit for this dimension is the **square metre** (`SquareMeter::RATIO == 1.0`).
4//! All other area units are expressed as exact ratios to square metres.
5//!
6//! This module provides:
7//!
8//! - **Metric squares**: square millimetre, square centimetre, square metre, square kilometre.
9//! - **Land measurement**: hectare, are.
10//! - **Imperial/US**: square inch, square foot, square yard, square mile, acre.
11//!
12//! Area units can also arise *automatically* from multiplying two length quantities:
13//!
14//! ```rust
15//! use qtty_core::length::{Meter, Meters};
16//! use qtty_core::area::{SquareMeters, SquareMeter};
17//! use qtty_core::Prod;
18//!
19//! let side = Meters::new(5.0);
20//! let area_prod = side * side;                     // Quantity<Prod<Meter, Meter>>
21//! let area: SquareMeters = area_prod.to();          // Convert to named area unit
22//! assert!((area.value() - 25.0).abs() < 1e-12);
23//! ```
24
25use crate::{Quantity, Unit};
26use qtty_derive::Unit;
27
28/// Re-export the area dimension from the dimension module.
29pub use crate::dimension::Area;
30
31/// Marker trait for any [`Unit`] whose dimension is [`Area`].
32pub trait AreaUnit: Unit<Dim = Area> {}
33impl<T: Unit<Dim = Area>> AreaUnit for T {}
34
35// ─────────────────────────────────────────────────────────────────────────────
36// SI / metric area units
37// ─────────────────────────────────────────────────────────────────────────────
38
39/// Square metre (SI derived unit of area).
40#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
41#[unit(symbol = "m²", dimension = Area, ratio = 1.0)]
42pub struct SquareMeter;
43/// A quantity measured in square metres.
44pub type SquareMeters = Quantity<SquareMeter>;
45
46/// Square kilometre (`1e6 m²`).
47#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
48#[unit(symbol = "km²", dimension = Area, ratio = 1e6)]
49pub struct SquareKilometer;
50/// A quantity measured in square kilometres.
51pub type SquareKilometers = Quantity<SquareKilometer>;
52
53/// Square centimetre (`1e-4 m²`).
54#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
55#[unit(symbol = "cm²", dimension = Area, ratio = 1e-4)]
56pub struct SquareCentimeter;
57/// A quantity measured in square centimetres.
58pub type SquareCentimeters = Quantity<SquareCentimeter>;
59
60/// Square millimetre (`1e-6 m²`).
61#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
62#[unit(symbol = "mm²", dimension = Area, ratio = 1e-6)]
63pub struct SquareMillimeter;
64/// A quantity measured in square millimetres.
65pub type SquareMillimeters = Quantity<SquareMillimeter>;
66
67// ─────────────────────────────────────────────────────────────────────────────
68// Land measurement
69// ─────────────────────────────────────────────────────────────────────────────
70
71/// Hectare (`10 000 m²`).
72#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
73#[unit(symbol = "ha", dimension = Area, ratio = 1e4)]
74pub struct Hectare;
75/// A quantity measured in hectares.
76pub type Hectares = Quantity<Hectare>;
77
78/// Are (`100 m²`).
79#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
80#[unit(symbol = "a", dimension = Area, ratio = 100.0)]
81pub struct Are;
82/// A quantity measured in ares.
83pub type Ares = Quantity<Are>;
84
85// ─────────────────────────────────────────────────────────────────────────────
86// Imperial / US customary area units
87// ─────────────────────────────────────────────────────────────────────────────
88
89/// Square inch (`6.4516e-4 m²`, exact: `0.0254² m²`).
90#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
91#[unit(symbol = "in²", dimension = Area, ratio = 6.4516e-4)]
92pub struct SquareInch;
93/// A quantity measured in square inches.
94pub type SquareInches = Quantity<SquareInch>;
95
96/// Square foot (`0.09290304 m²`, exact: `0.3048² m²`).
97#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
98#[unit(symbol = "ft²", dimension = Area, ratio = 0.09290304)]
99pub struct SquareFoot;
100/// A quantity measured in square feet.
101pub type SquareFeet = Quantity<SquareFoot>;
102
103/// Square yard (`0.83612736 m²`, exact: `0.9144² m²`).
104#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
105#[unit(symbol = "yd²", dimension = Area, ratio = 0.83612736)]
106pub struct SquareYard;
107/// A quantity measured in square yards.
108pub type SquareYards = Quantity<SquareYard>;
109
110/// Square mile (`2_589_988.110336 m²`, exact: `1609.344² m²`).
111#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
112#[unit(symbol = "mi²", dimension = Area, ratio = 2_589_988.110_336)]
113pub struct SquareMile;
114/// A quantity measured in square miles.
115pub type SquareMiles = Quantity<SquareMile>;
116
117/// Acre (exactly `4046.8564224 m²`).
118#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
119#[unit(symbol = "ac", dimension = Area, ratio = 4_046.856_422_4)]
120pub struct Acre;
121/// A quantity measured in acres.
122pub type Acres = Quantity<Acre>;
123
124#[cfg(test)]
125mod tests {
126    use super::*;
127    use approx::assert_abs_diff_eq;
128
129    #[test]
130    fn sqm_to_sqkm() {
131        let a = SquareMeters::new(1_000_000.0);
132        let b: SquareKilometers = a.to();
133        assert_abs_diff_eq!(b.value(), 1.0, epsilon = 1e-12);
134    }
135
136    #[test]
137    fn hectare_to_sqm() {
138        let a = Hectares::new(1.0);
139        let b: SquareMeters = a.to();
140        assert_abs_diff_eq!(b.value(), 10_000.0, epsilon = 1e-9);
141    }
142
143    #[test]
144    fn acre_to_hectare() {
145        let a = Acres::new(1.0);
146        let b: Hectares = a.to();
147        assert_abs_diff_eq!(b.value(), 0.404_685_642_24, epsilon = 1e-9);
148    }
149
150    #[test]
151    fn sqft_to_sqm() {
152        let a = SquareFeet::new(1.0);
153        let b: SquareMeters = a.to();
154        assert_abs_diff_eq!(b.value(), 0.092_903_04, epsilon = 1e-9);
155    }
156
157    #[test]
158    fn length_product_to_area() {
159        use crate::length::{Meter, Meters};
160        use crate::Prod;
161
162        let side = Meters::new(5.0);
163        let area_prod: Quantity<Prod<Meter, Meter>> = side * side;
164        let area: SquareMeters = area_prod.to();
165        assert_abs_diff_eq!(area.value(), 25.0, epsilon = 1e-12);
166    }
167
168    #[test]
169    fn sqmile_to_sqkm() {
170        let a = SquareMiles::new(1.0);
171        let b: SquareKilometers = a.to();
172        assert_abs_diff_eq!(b.value(), 2.589_988_110_336, epsilon = 1e-6);
173    }
174}