Skip to content

Commit 42ad00e

Browse files
committed
Added humidity and density
Squashed commit of the following: commit d14ab7adb087d7fab2dfdf4210c791d85d0c280f Author: Andrew Bowers <[email protected]> Date: Wed Jun 2 22:05:49 2021 +1200 Update CHANGELOG.md Co-authored-by: Diego Barrios Romero <[email protected]> commit 81d28a6372e58c3491ad5319ecacfbcde81bb54a Author: Andrew Bowers <[email protected]> Date: Wed Jun 2 17:43:31 2021 +1200 Update CHANGELOG.md Added changelog entry commit 0ca6d1add001cd7095b0f5df6d77cd404262461c Author: Andrew Bowers <[email protected]> Date: Wed Jun 2 17:08:05 2021 +1200 Update src/humidity.rs Co-authored-by: Diego Barrios Romero <[email protected]> commit a71f9775a7a897379b65ea1d9307a640876de018 Author: Andrew Bowers <[email protected]> Date: Wed Jun 2 17:07:42 2021 +1200 Update src/humidity.rs Co-authored-by: Diego Barrios Romero <[email protected]> commit 6a22745d25e329626621c99d199a8de2fc6b264f Author: Andrew Bowers <[email protected]> Date: Mon Apr 27 22:08:57 2020 +1200 Created new Humidity and Density modules * Responded to Issue #19 - added humidity module * Created density module (required for one output from Humidity) * Updated ReadMe to include Density and Humidity * Added new modules into lib.rs * [TODO: updates to CHANGELOG, etc...] [TODO (Possibly): Add more native units (g/m3), (kg/L), (g/mL), (t/m3), (oz/cu in), (oz/US fl oz), (lb/cu yd)... ]
1 parent 934959e commit 42ad00e

File tree

5 files changed

+498
-7
lines changed

5 files changed

+498
-7
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
88

99
Added this Changelog.
1010

11+
### Added
12+
13+
- Humidity and density in [#27](https://github.com/rust-embedded-community/rust-measurements/pull/27)
14+
1115
### Changed
1216

1317
- Merged in [#36](https://github.com/rust-embedded-community/rust-measurements/pull/36) to adjust bounds on `Measurements::pick_appropriate_units()`, which changes the return value for cases when the value is 1.0.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@ Conversions to and from different units are simple, and operator overrides allow
2424
- Area
2525
- Current
2626
- Data (bytes, etc)
27+
- Density
2728
- Energy
2829
- Force
2930
- Frequency
3031
- Length
32+
- Humidity
3133
- Mass
3234
- Power
3335
- Pressure

src/density.rs

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
//! Types and constants for handling density.
2+
3+
use super::measurement::*;
4+
use mass::Mass;
5+
use volume::Volume;
6+
7+
// Constants, metric
8+
/// Number of pound per cubic foot in 1 kilograms per cubic meter
9+
pub const LBCF_KGCM_FACTOR: f64 = 0.062427973725314;
10+
11+
/// The `Density` struct can be used to deal with Densities in a common way, to enable mass,
12+
/// volume and density calculations and unit conversions.
13+
///
14+
/// # Example1 - calculating volume from units of mass and density
15+
///
16+
/// ```
17+
/// extern crate measurements;
18+
/// use measurements::{Density, Mass, Volume};
19+
///
20+
/// fn main() {
21+
/// // Q: A 12 stone man hops into a brimming full bath, completely emersing himself.
22+
/// // How many gallons of water spill on the floor?
23+
/// // (Assume The human body is roughly about as dense as water - 1 gm/cm³)
24+
/// //
25+
/// let body_density: Density = Mass::from_grams(1.0) / Volume:: from_cubic_centimetres(1.0);
26+
/// let mans_weight = Mass::from_stones(12.0);
27+
/// let water_volume = mans_weight / body_density;
28+
/// println!("{} gallons of water spilled on the floor", water_volume.as_gallons());
29+
///}
30+
/// ```
31+
/// # Example2 - converting to ad-hoc units of density
32+
///
33+
/// ```
34+
/// extern crate measurements;
35+
/// use measurements::{Density, Mass, Volume};
36+
///
37+
/// fn main() {
38+
/// // Q: what is 3 grams per litre in units of ounces per quart?
39+
/// //
40+
/// let density: Density = Mass::from_grams(3.0) / Volume:: from_litres(1.0);
41+
/// let ounces = (density * Volume::from_quarts(1.0)).as_ounces();
42+
/// println!("Answer is {} ounces per quart", ounces);
43+
///}
44+
/// ```
45+
46+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
47+
#[derive(Copy, Clone, Debug)]
48+
pub struct Density {
49+
kilograms_per_cubic_meter: f64,
50+
}
51+
52+
impl Density {
53+
/// Create a new Density from a floating point value in kilograms per cubic meter
54+
pub fn from_kilograms_per_cubic_meter(kilograms_per_cubic_meter: f64) -> Density {
55+
Density {
56+
kilograms_per_cubic_meter: kilograms_per_cubic_meter,
57+
}
58+
}
59+
60+
/// Create a new Density from a floating point value in pounds per cubic feet
61+
pub fn from_pounds_per_cubic_feet(pounds_per_cubic_foot: f64) -> Density {
62+
Density::from_kilograms_per_cubic_meter(pounds_per_cubic_foot / LBCF_KGCM_FACTOR)
63+
}
64+
65+
/// Convert this Density to a value in kilograms per cubic meter
66+
pub fn as_kilograms_per_cubic_meter(&self) -> f64 {
67+
self.kilograms_per_cubic_meter
68+
}
69+
70+
/// Convert this Density to a value in pounds per cubic feet
71+
pub fn as_pounds_per_cubic_feet(&self) -> f64 {
72+
self.kilograms_per_cubic_meter * LBCF_KGCM_FACTOR
73+
}
74+
}
75+
76+
// mass / volume = density
77+
impl ::std::ops::Div<Volume> for Mass {
78+
type Output = Density;
79+
80+
fn div(self, other: Volume) -> Density {
81+
Density::from_base_units(self.as_base_units() / other.as_cubic_meters())
82+
}
83+
}
84+
85+
// mass / density = volume
86+
impl ::std::ops::Div<Density> for Mass {
87+
type Output = Volume;
88+
89+
fn div(self, other: Density) -> Volume {
90+
Volume::from_cubic_meters(self.as_base_units() / other.as_base_units())
91+
}
92+
}
93+
94+
// volume * density = mass
95+
impl ::std::ops::Mul<Density> for Volume {
96+
type Output = Mass;
97+
98+
fn mul(self, other: Density) -> Mass {
99+
Mass::from_base_units(self.as_cubic_meters() * other.as_base_units())
100+
}
101+
}
102+
103+
// density * volume = mass
104+
impl ::std::ops::Mul<Volume> for Density {
105+
type Output = Mass;
106+
107+
fn mul(self, other: Volume) -> Mass {
108+
Mass::from_base_units(self.as_base_units() * other.as_cubic_meters())
109+
}
110+
}
111+
112+
impl Measurement for Density {
113+
fn as_base_units(&self) -> f64 {
114+
self.kilograms_per_cubic_meter
115+
}
116+
117+
fn from_base_units(units: f64) -> Self {
118+
Self::from_kilograms_per_cubic_meter(units)
119+
}
120+
121+
fn get_base_units_name(&self) -> &'static str {
122+
"kg/m\u{00B3}"
123+
}
124+
}
125+
126+
implement_measurement! { Density }
127+
128+
#[cfg(test)]
129+
mod test {
130+
131+
use super::*;
132+
use test_utils::assert_almost_eq;
133+
134+
// Metric
135+
#[test]
136+
fn mass_over_volume() {
137+
let v1 = Volume::from_cubic_meters(10.0);
138+
let m1 = Mass::from_kilograms(5.0);
139+
let i1 = m1 / v1;
140+
let r1 = i1.as_kilograms_per_cubic_meter();
141+
assert_almost_eq(r1, 0.5);
142+
}
143+
#[test]
144+
fn mass_over_density() {
145+
let m1 = Mass::from_kilograms(5.0);
146+
let d1 = Density::from_kilograms_per_cubic_meter(10.0);
147+
let i1 = m1 / d1;
148+
let r1 = i1.as_cubic_meters();
149+
assert_almost_eq(r1, 0.5);
150+
}
151+
#[test]
152+
fn volume_times_density() {
153+
let v1 = Volume::from_cubic_meters(5.0);
154+
let d1 = Density::from_kilograms_per_cubic_meter(10.0);
155+
let i1 = v1 * d1;
156+
let r1 = i1.as_kilograms();
157+
assert_almost_eq(r1, 50.0);
158+
}
159+
#[test]
160+
fn density_times_volume() {
161+
let v1 = Volume::from_cubic_meters(5.0);
162+
let d1 = Density::from_kilograms_per_cubic_meter(10.0);
163+
let i1 = v1 * d1;
164+
let r1 = i1.as_kilograms();
165+
assert_almost_eq(r1, 50.0);
166+
}
167+
#[test]
168+
fn cvt_pcf_to_kgcm() {
169+
let a = Density::from_kilograms_per_cubic_meter(1.0);
170+
let b = Density::from_pounds_per_cubic_feet(0.062428);
171+
assert_almost_eq(
172+
a.as_kilograms_per_cubic_meter(),
173+
b.as_kilograms_per_cubic_meter(),
174+
);
175+
assert_almost_eq(a.as_pounds_per_cubic_feet(), b.as_pounds_per_cubic_feet());
176+
}
177+
178+
// Traits
179+
#[test]
180+
fn add() {
181+
let a = Density::from_kilograms_per_cubic_meter(2.0);
182+
let b = Density::from_kilograms_per_cubic_meter(4.0);
183+
let c = a + b;
184+
let d = b + a;
185+
assert_almost_eq(c.as_kilograms_per_cubic_meter(), 6.0);
186+
assert_eq!(c, d);
187+
}
188+
189+
#[test]
190+
fn sub() {
191+
let a = Density::from_kilograms_per_cubic_meter(2.0);
192+
let b = Density::from_kilograms_per_cubic_meter(4.0);
193+
let c = a - b;
194+
assert_almost_eq(c.as_kilograms_per_cubic_meter(), -2.0);
195+
}
196+
197+
#[test]
198+
fn mul() {
199+
let a = Density::from_kilograms_per_cubic_meter(3.0);
200+
let b = a * 2.0;
201+
let c = 2.0 * a;
202+
assert_almost_eq(b.as_kilograms_per_cubic_meter(), 6.0);
203+
assert_eq!(b, c);
204+
}
205+
206+
#[test]
207+
fn div() {
208+
let a = Density::from_kilograms_per_cubic_meter(2.0);
209+
let b = Density::from_kilograms_per_cubic_meter(4.0);
210+
let c = a / b;
211+
let d = a / 2.0;
212+
assert_almost_eq(c, 0.5);
213+
assert_almost_eq(d.as_kilograms_per_cubic_meter(), 1.0);
214+
}
215+
216+
#[test]
217+
fn eq() {
218+
let a = Density::from_kilograms_per_cubic_meter(2.0);
219+
let b = Density::from_kilograms_per_cubic_meter(2.0);
220+
assert_eq!(a == b, true);
221+
}
222+
223+
#[test]
224+
fn neq() {
225+
let a = Density::from_kilograms_per_cubic_meter(2.0);
226+
let b = Density::from_kilograms_per_cubic_meter(4.0);
227+
assert_eq!(a == b, false);
228+
}
229+
230+
#[test]
231+
fn cmp() {
232+
let a = Density::from_kilograms_per_cubic_meter(2.0);
233+
let b = Density::from_kilograms_per_cubic_meter(4.0);
234+
assert_eq!(a < b, true);
235+
assert_eq!(a <= b, true);
236+
assert_eq!(a > b, false);
237+
assert_eq!(a >= b, false);
238+
}
239+
}

0 commit comments

Comments
 (0)