From cc4c66ab50923ac75207cf0ac548986368f55757 Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Sat, 18 Jul 2020 12:50:20 +0200 Subject: [PATCH 1/2] Add support for solid angles mostly based on what we do for angles. --- src/si/mod.rs | 24 +++++++-- src/si/solid_angle.rs | 114 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 src/si/solid_angle.rs diff --git a/src/si/mod.rs b/src/si/mod.rs index cdc09b4d..053998ae 100644 --- a/src/si/mod.rs +++ b/src/si/mod.rs @@ -89,6 +89,7 @@ system! { pressure::Pressure, ratio::Ratio, specific_heat_capacity::SpecificHeatCapacity, + solid_angle::SolidAngle, temperature_interval::TemperatureInterval, thermal_conductivity::ThermalConductivity, thermodynamic_temperature::ThermodynamicTemperature, @@ -118,7 +119,7 @@ pub mod marker { use si::{Dimension, Quantity, Units}; use Kind; - /// AngleKind is a `Kind` for separating angular quantities from their identically dimensioned + /// `AngleKind` is a `Kind` for separating angular quantities from their identically dimensioned /// non-angular quantity counterparts. Conversions to and from `AngleKind` quantities are /// supported through implementations of the `From` trait. /// @@ -131,9 +132,22 @@ pub mod marker { /// ``` pub trait AngleKind: ::Kind {} - /// InformationKind is a `Kind` for separating information quantities from their identically - /// dimensioned non-information quantity counterparts. Conversions to and from - /// `InformationKind` quantities are supported through implementations of the `From` trait. + /// `SolidAngleKind` is a `Kind` for separating quantities of solid angles from other + /// identically dimensioned quantities. Conversions to and from `SolidAngleKind` quantities are + /// supported through implementations of the `From` trait. + /// + #[cfg_attr(feature = "f32", doc = " ```rust")] + #[cfg_attr(not(feature = "f32"), doc = " ```rust,ignore")] + /// # use uom::si::f32::*; + /// # use uom::si::solid_angle::steradian; + /// let a: SolidAngle = SolidAngle::new::(1.0); + /// let r: Ratio = a.into(); + /// ``` + pub trait SolidAngleKind: ::Kind {} + + /// `InformationKind` is a `Kind` for separating information quantities from their identically + /// dimensioned non-information quantity counterparts. Conversions to and from `InformationKind` + /// quantities are supported through implementations of the `From` trait. /// #[cfg_attr(feature = "f32", doc = " ```rust")] #[cfg_attr(not(feature = "f32"), doc = " ```rust,ignore")] @@ -299,6 +313,8 @@ pub mod marker { impl_from!(AngleKind, Kind); impl_from!(Kind, AngleKind); + impl_from!(SolidAngleKind, Kind); + impl_from!(Kind, SolidAngleKind); impl_from!(InformationKind, Kind); impl_from!(Kind, InformationKind); impl_from!(ConstituentConcentrationKind, Kind); diff --git a/src/si/solid_angle.rs b/src/si/solid_angle.rs new file mode 100644 index 00000000..8c72c7ae --- /dev/null +++ b/src/si/solid_angle.rs @@ -0,0 +1,114 @@ +//! Solid angle (dimensionless quantity). + +quantity! { + /// Solid angle (dimensionless quantity). + quantity: SolidAngle; "solid angle"; + /// Dimension of solid angle, 1 (dimensionless). + dimension: ISQ< + Z0, // length + Z0, // mass + Z0, // time + Z0, // electric current + Z0, // thermodynamic temperature + Z0, // amount of substance + Z0>; // luminous intensity + kind: dyn (::si::marker::SolidAngleKind); + units { + /// SI derived unit of solid angle is steradians. It is the solid angle subtended at the + /// center of a unit sphere by a unit area on its surface. + @steradian: 1.0_E0; "sr", "steradian", "steradians"; + @spat: 1.256_637_061_435_917_3_E1; "sp", "spat", "spats"; + @square_degree: 3.046_174_197_867_086_E-4; "°²", "square degree", "square degrees"; + @square_minute: 8.461_594_994_075_238_9_E-8; "′²", "square minute", "square minutes"; + @square_second: 2.350_443_053_909_788_6_E-11; "″²", "square second", "square seconds"; + } +} + +#[cfg(all(feature = "std", feature = "f32"))] +impl SolidAngle<::si::SI, f32> { + /// The solid angle subtended by a sphere at its center, i.e. with a value 4π as measured in + /// steradians. + pub const SPHERE: Self = Self { + dimension: std::marker::PhantomData, + units: std::marker::PhantomData, + value: 4. * std::f32::consts::PI, + }; +} + +#[cfg(all(feature = "std", feature = "f64"))] +impl SolidAngle<::si::SI, f64> { + /// The solid angle subtended by a sphere at its center, i.e. with a value 4π as measured in + /// steradians. + pub const SPHERE: Self = Self { + dimension: std::marker::PhantomData, + units: std::marker::PhantomData, + value: 4. * std::f64::consts::PI, + }; +} + +mod convert { + use super::*; + + impl ::lib::convert::From for SolidAngle + where + U: ::si::Units + ?Sized, + V: ::num::Num + ::Conversion, + { + fn from(t: V) -> Self { + SolidAngle { + dimension: ::lib::marker::PhantomData, + units: ::lib::marker::PhantomData, + value: t, + } + } + } + + storage_types! { + use super::*; + + impl ::lib::convert::From> for V + where + U: ::si::Units + ?Sized, + V: ::num::Num + ::Conversion, + { + fn from(t: SolidAngle) -> Self { + t.value + } + } + } +} + +#[cfg(test)] +mod tests { + storage_types! { + use ::lib::f64::consts::PI; + use num::{FromPrimitive, One}; + use si::solid_angle as sa; + use si::quantities::*; + use tests::Test; + + #[test] + fn from() { + let r1: SolidAngle = SolidAngle::::from(V::one()); + let r2: SolidAngle = V::one().into(); + let _: V = V::from(r1); + let _: V = r2.into(); + } + + #[test] + fn check_units() { + Test::assert_eq(&SolidAngle::new::(V::from_f64(4.0 * PI).unwrap()), + &SolidAngle::new::(V::one())); + Test::assert_approx_eq( + &SolidAngle::new::(V::from_f64(360.0 * 360.0 / PI).unwrap()), + &SolidAngle::new::(V::one())); + Test::assert_approx_eq( + &SolidAngle::new::(V::from_f64(60.0 * 60.0).unwrap()), + &SolidAngle::new::(V::one())); + Test::assert_approx_eq( + &SolidAngle::new::( + V::from_f64((60.0 * 60.0) * (60.0 * 60.0)).unwrap()), + &SolidAngle::new::(V::one())); + } + } +} From 91877634f724ff204311b81b7dd34c8d3e3402df Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Sat, 18 Jul 2020 12:55:53 +0200 Subject: [PATCH 2/2] Make angle helper constants available to no_std builds. --- src/si/angle.rs | 28 ++++++++++++++-------------- src/si/solid_angle.rs | 16 ++++++++-------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/si/angle.rs b/src/si/angle.rs index bdd5b41e..3a885103 100644 --- a/src/si/angle.rs +++ b/src/si/angle.rs @@ -29,37 +29,37 @@ quantity! { } } -#[cfg(all(feature = "std", feature = "f32"))] +#[cfg(feature = "f32")] impl Angle<::si::SI, f32> { /// A half turn, i.e. an angle with a value of π as measured in radians pub const HALF_TURN: Self = Self { - dimension: std::marker::PhantomData, - units: std::marker::PhantomData, - value: std::f32::consts::PI, + dimension: ::lib::marker::PhantomData, + units: ::lib::marker::PhantomData, + value: ::lib::f32::consts::PI, }; /// A full turn, i.e. an angle with a value of 2π as measured in radians pub const FULL_TURN: Self = Self { - dimension: std::marker::PhantomData, - units: std::marker::PhantomData, - value: 2. * std::f32::consts::PI, + dimension: ::lib::marker::PhantomData, + units: ::lib::marker::PhantomData, + value: 2. * ::lib::f32::consts::PI, }; } -#[cfg(all(feature = "std", feature = "f64"))] +#[cfg(feature = "f64")] impl Angle<::si::SI, f64> { /// A half turn, i.e. an angle with a value of π as measured in radians pub const HALF_TURN: Self = Self { - dimension: std::marker::PhantomData, - units: std::marker::PhantomData, - value: std::f64::consts::PI, + dimension: ::lib::marker::PhantomData, + units: ::lib::marker::PhantomData, + value: ::lib::f64::consts::PI, }; /// A full turn, i.e. an angle with a value of 2π as measured in radians pub const FULL_TURN: Self = Self { - dimension: std::marker::PhantomData, - units: std::marker::PhantomData, - value: 2. * std::f64::consts::PI, + dimension: ::lib::marker::PhantomData, + units: ::lib::marker::PhantomData, + value: 2. * ::lib::f64::consts::PI, }; } diff --git a/src/si/solid_angle.rs b/src/si/solid_angle.rs index 8c72c7ae..30a118dd 100644 --- a/src/si/solid_angle.rs +++ b/src/si/solid_angle.rs @@ -24,25 +24,25 @@ quantity! { } } -#[cfg(all(feature = "std", feature = "f32"))] +#[cfg(feature = "f32")] impl SolidAngle<::si::SI, f32> { /// The solid angle subtended by a sphere at its center, i.e. with a value 4π as measured in /// steradians. pub const SPHERE: Self = Self { - dimension: std::marker::PhantomData, - units: std::marker::PhantomData, - value: 4. * std::f32::consts::PI, + dimension: ::lib::marker::PhantomData, + units: ::lib::marker::PhantomData, + value: 4. * ::lib::f32::consts::PI, }; } -#[cfg(all(feature = "std", feature = "f64"))] +#[cfg(feature = "f64")] impl SolidAngle<::si::SI, f64> { /// The solid angle subtended by a sphere at its center, i.e. with a value 4π as measured in /// steradians. pub const SPHERE: Self = Self { - dimension: std::marker::PhantomData, - units: std::marker::PhantomData, - value: 4. * std::f64::consts::PI, + dimension: ::lib::marker::PhantomData, + units: ::lib::marker::PhantomData, + value: 4. * ::lib::f64::consts::PI, }; }