1use crate::{Quantity, Unit};
43use qtty_derive::Unit;
44
45pub use crate::dimension::Area;
47
48pub trait AreaUnit: Unit<Dim = Area> {}
50impl<T: Unit<Dim = Area>> AreaUnit for T {}
51
52#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
58#[unit(symbol = "m²", dimension = Area, ratio = 1.0)]
59pub struct SquareMeter;
60pub type SquareMeters = Quantity<SquareMeter>;
62
63#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
65#[unit(symbol = "km²", dimension = Area, ratio = 1e6)]
66pub struct SquareKilometer;
67pub type SquareKilometers = Quantity<SquareKilometer>;
69
70#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
72#[unit(symbol = "cm²", dimension = Area, ratio = 1e-4)]
73pub struct SquareCentimeter;
74pub type SquareCentimeters = Quantity<SquareCentimeter>;
76
77#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
79#[unit(symbol = "mm²", dimension = Area, ratio = 1e-6)]
80pub struct SquareMillimeter;
81pub type SquareMillimeters = Quantity<SquareMillimeter>;
83
84#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
90#[unit(symbol = "ha", dimension = Area, ratio = 1e4)]
91pub struct Hectare;
92pub type Hectares = Quantity<Hectare>;
94
95#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
97#[unit(symbol = "a", dimension = Area, ratio = 100.0)]
98pub struct Are;
99pub type Ares = Quantity<Are>;
101
102#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
108#[unit(symbol = "in²", dimension = Area, ratio = 6.4516e-4)]
109pub struct SquareInch;
110pub type SquareInches = Quantity<SquareInch>;
112
113#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
115#[unit(symbol = "ft²", dimension = Area, ratio = 0.09290304)]
116pub struct SquareFoot;
117pub type SquareFeet = Quantity<SquareFoot>;
119
120#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
122#[unit(symbol = "yd²", dimension = Area, ratio = 0.83612736)]
123pub struct SquareYard;
124pub type SquareYards = Quantity<SquareYard>;
126
127#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
129#[unit(symbol = "mi²", dimension = Area, ratio = 2_589_988.110_336)]
130pub struct SquareMile;
131pub type SquareMiles = Quantity<SquareMile>;
133
134#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Unit)]
136#[unit(symbol = "ac", dimension = Area, ratio = 4_046.856_422_4)]
137pub struct Acre;
138pub type Acres = Quantity<Acre>;
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144 use approx::assert_abs_diff_eq;
145
146 #[test]
147 fn sqm_to_sqkm() {
148 let a = SquareMeters::new(1_000_000.0);
149 let b: SquareKilometers = a.to();
150 assert_abs_diff_eq!(b.value(), 1.0, epsilon = 1e-12);
151 }
152
153 #[test]
154 fn hectare_to_sqm() {
155 let a = Hectares::new(1.0);
156 let b: SquareMeters = a.to();
157 assert_abs_diff_eq!(b.value(), 10_000.0, epsilon = 1e-9);
158 }
159
160 #[test]
161 fn acre_to_hectare() {
162 let a = Acres::new(1.0);
163 let b: Hectares = a.to();
164 assert_abs_diff_eq!(b.value(), 0.404_685_642_24, epsilon = 1e-9);
165 }
166
167 #[test]
168 fn sqft_to_sqm() {
169 let a = SquareFeet::new(1.0);
170 let b: SquareMeters = a.to();
171 assert_abs_diff_eq!(b.value(), 0.092_903_04, epsilon = 1e-9);
172 }
173
174 #[test]
175 fn length_product_to_area() {
176 use crate::length::{Meter, Meters};
177 use crate::Prod;
178
179 let side = Meters::new(5.0);
180 let area_prod: Quantity<Prod<Meter, Meter>> = side * side;
181 let area: SquareMeters = area_prod.to();
182 assert_abs_diff_eq!(area.value(), 25.0, epsilon = 1e-12);
183 }
184
185 #[test]
186 fn sqmile_to_sqkm() {
187 let a = SquareMiles::new(1.0);
188 let b: SquareKilometers = a.to();
189 assert_abs_diff_eq!(b.value(), 2.589_988_110_336, epsilon = 1e-6);
190 }
191
192 #[test]
193 fn sqcm_to_sqm() {
194 let a = SquareCentimeters::new(10_000.0);
195 let b: SquareMeters = a.to();
196 assert_abs_diff_eq!(b.value(), 1.0, epsilon = 1e-12);
197 }
198
199 #[test]
200 fn sqmm_to_sqcm() {
201 let a = SquareMillimeters::new(100.0);
202 let b: SquareCentimeters = a.to();
203 assert_abs_diff_eq!(b.value(), 1.0, epsilon = 1e-12);
204 }
205
206 #[test]
207 fn are_to_sqm() {
208 let a = Ares::new(1.0);
209 let b: SquareMeters = a.to();
210 assert_abs_diff_eq!(b.value(), 100.0, epsilon = 1e-12);
211 }
212
213 #[test]
214 fn sqinch_to_sqcm() {
215 let a = SquareInches::new(1.0);
216 let b: SquareCentimeters = a.to();
217 assert_abs_diff_eq!(b.value(), 6.4516, epsilon = 1e-9);
219 }
220
221 #[test]
222 fn sqyard_to_sqm() {
223 let a = SquareYards::new(1.0);
224 let b: SquareMeters = a.to();
225 assert_abs_diff_eq!(b.value(), 0.836_127_36, epsilon = 1e-9);
226 }
227
228 #[test]
229 fn roundtrip_sqcm_sqm() {
230 let original = SquareCentimeters::new(250.0);
231 let converted = original.to::<SquareMeter>();
232 let back = converted.to::<SquareCentimeter>();
233 assert_abs_diff_eq!(back.value(), original.value(), epsilon = 1e-10);
234 }
235
236 #[test]
237 fn symbols_are_correct() {
238 assert_eq!(SquareMeter::SYMBOL, "m²");
239 assert_eq!(Hectare::SYMBOL, "ha");
240 assert_eq!(Acre::SYMBOL, "ac");
241 assert_eq!(SquareInch::SYMBOL, "in²");
242 }
243}