Skip to content

Commit

Permalink
📝 rephrase major parts of the docs
Browse files Browse the repository at this point in the history
  • Loading branch information
tguichaoua committed Dec 18, 2023
1 parent 1367a78 commit 3b92b0b
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 110 deletions.
25 changes: 7 additions & 18 deletions src/angle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ use crate::float::Float;
use crate::macros::{forward_ref_binop, forward_ref_op_assign, forward_ref_unop};
use crate::AngleUnbounded;

/// Represents a point on the circle as an unit agnostic angle.
/// Represents a point on the circle as a unit-agnostic angle.
///
/// The parameter `F` is the floating-point type used to store the value.
///
/// # Behaviour
///
/// Two different values of the same point on the circle are the same [`Angle`] :
/// Two different values of the same point on the circle are the same [`Angle`].
///
/// ```
/// # use angulus::Angle;
Expand All @@ -22,26 +22,15 @@ use crate::AngleUnbounded;
/// assert_eq!(a, b);
/// ```
///
/// To preserve the difference use [`AngleUnbounded`].
///
/// # Why doesn't it implement [`PartialOrd`] ?
///
/// Because [`Angle`]s represents points on the circle (i.e. not a numerical value), they cannot be ordered.
///
/// # The main range
///
/// The main range for an angle is :
///
/// - `(-π, π]` radians
/// - `(-180, 180]` degrees
/// - `(-0.5, 0.5]` turns
/// - `(-200, 200]` gradians
/// Because [`Angle`]s represent points on the circle (i.e., not a numerical value), they cannot be ordered.
///
/// # The `NaN` angle
///
/// An angle can be `NaN` in the following cases :
/// An angle can be `NaN` in the following cases:
///
/// - create the angle from an non finite value
/// - Create an angle from a non-finite value;
/// ```
/// # use angulus::Angle;
/// let a = Angle::from_radians(f32::INFINITY);
Expand All @@ -50,7 +39,7 @@ use crate::AngleUnbounded;
/// let b = Angle::from_radians(f32::NAN);
/// assert!(b.is_nan());
/// ```
/// - doing some operations that result into non finite value
/// - Doing an operation that result into a non-finite value;
/// ```
/// # use angulus::Angle;
/// let a = Angle::DEG_90;
Expand Down Expand Up @@ -271,7 +260,7 @@ impl<F: Float> Angle<F> {
//-------------------------------------------------------------------

impl<F: Copy> Angle<F> {
/// Converts this angle into an unbounded angle in [the main range](Angle#the-main-range).
/// Converts this angle into an unbounded angle in [the main range](crate#the-main-range).
#[must_use = "this returns the result of the operation, without modifying the original"]
#[inline]
pub const fn to_unbounded(self) -> AngleUnbounded<F> {
Expand Down
65 changes: 16 additions & 49 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,11 @@
//! Unit agnostic angle.
//! This crate provides two types ([`Angle`] and [`AngleUnbounded`]) that both represent an angle value
//! with no specific unit (radian, degree, etc.).
//!
//! ## Overview
//! They can be used in place of `f32` and `f64` for angle manipulations.
//!
//! Using simple floating point numbers to store an angle value is error-prone : you may add two
//! angle with one in radians and the second in degrees or you may try to compute the cosine of
//! a value in degrees and get an unexpected result.
//! # [`Angle`] vs [`AngleUnbounded`]
//!
//! [`Angle`] and [`AngleUnbounded`] represent an angle value with no specific unit.
//!
//! ## [`Angle`] vs [`AngleUnbounded`]
//!
//! Both represent a point on the circle as a unit agnostic angle.
//!
//! But [`Angle`] consider two different values of the same point as the same angle :
//! [`Angle`] is a specific point of the circle.
//!
//! ```
//! # use angulus::Angle;
Expand All @@ -22,7 +15,7 @@
//! assert_eq!(a, b);
//! ```
//!
//! While [`AngleUnbounded`] consider those value as two different angle :
//! While [`AngleUnbounded`] preserves the "number of turns".
//!
//! ```
//! # use angulus::AngleUnbounded;
Expand All @@ -32,48 +25,22 @@
//! assert_ne!(a, b);
//! ```
//!
//! ## From value to angle
//!
//! To create an angle from a value, you can use the `from_*` methods with the unit of the value...
//! # The main range
//!
//! ```
//! # use angulus::Angle;
//! let deg = Angle::from_degrees(90.0);
//! let rad = Angle::from_radians(3.14);
//! let turns = Angle::from_turns(0.75);
//! let grad = Angle::from_gradians(50.0);
//! ```
//! The main range for an angle is :
//!
//! or you use the [`ToAngle`] trait directly on the value.
//! - `(-π, π]` radians
//! - `(-180, 180]` degrees
//! - `(-0.5, 0.5]` turns
//! - `(-200, 200]` gradians
//!
//! ```
//! # use angulus::ToAngle;
//! let deg = 90.0.deg();
//! let rad = 3.14.rad();
//! let turns = 0.75.turns();
//! let grad = 50.0.grad();
//! ```
//!
//! ## From angle to value
//!
//! To convert back an angle to a value you can use the `to_*` methods with the desired unit.
//!
//! ```
//! # use angulus::Angle32;
//! let a = Angle32::QUARTER;
//!
//! assert_eq!(a.to_radians(), std::f32::consts::FRAC_PI_2);
//! assert_eq!(a.to_degrees(), 90.0);
//! assert_eq!(a.to_turns(), 0.25);
//! assert_eq!(a.to_gradians(), 100.0);
//! ```
//! # Display
//!
//! ## Display
//! Since [`Angle`] and [`AngleUnbounded`] are unit-agnostic, they cannot implement the [`Display`][std::fmt::Display] trait.
//!
//! Since [`Angle`] and [`AngleUnbounded`] are unit agnostic they didn't implement the [`Display`][std::fmt::Display] trait.
//! But you can use one of the unit wrapper from [the units module][units] to specify a unit.
//! To display an angle with a specific unit, wrap it in one of the unit struct of [the `units` module][units].
//!
//! ## Crate features
//! # Crate features
//!
//! - `std`: by default angulus links to the standard library. Disable this feature to remove this dependency and be able to use angulus in `#![no_std]` crates.
//! - `libm`: use the [libm crate](https://docs.rs/libm/latest/libm/) for the math methods (sin, cos, tan) when `std` is disabled.
Expand Down
23 changes: 12 additions & 11 deletions src/rand.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
//! Generate random angles with the [rand crate](https://docs.rs/rand/latest/rand/).
//!
//! ## Provided implementations
//! # Provided implementations
//!
//! [`Angle`] and [`AngleUnbounded`] (and [their unit wrapped equivalent][crate::units]) can be generated
//! [`Angle`] and [`AngleUnbounded`] (and [their unit-wrapped equivalents][crate::units]) can be generated
//! with the [`Standard`] distribution, and so with [`rand::random`](https://docs.rs/rand/latest/rand/fn.random.html)
//! with the following ranges and distributions:
//!
//! - [`Angle`]: Uniformly distributed on the circle.
//! - [`AngleUnbounded`]: Uniformly distributed in the range `(-π, π]` radians.
//! - [`Angle`]: uniformly distributed on the circle.
//! - [`AngleUnbounded`]: uniformly distributed in [the main range](crate#the-main-range).
//!
//! **Note**: The unit wrappers have no influence on the generated value.
//!
//! ## Uniform ranges
//! # Uniform ranges
//!
//! Angle types can also be generated from a range using [`rand::Rng::gen_range`].
//! [`Angle`] and [`AngleUnbounded`] can also be generated from a range using [`rand::Rng::gen_range`]
//! with some specific behaviour.
//!
//! ### [`Angle`]
//! ## [`Angle`]
//!
//! Because [`Angle`] [did not implements `PartialOrd`](Angle#why-doesnt-it-implement-partialord-),
//! Because [`Angle`] [did not implement `PartialOrd`](Angle#why-doesnt-it-implement-partialord-),
//! the generated angle will belong to the part of the circle between the bounds in counterclockwise.
//! I.e. the order of the bounds will determine which part of the circle the generated angle belongs to.
//! I.e., the order of the bounds will determine which part of the circle the generated angle belongs to.
//!
//! ```
//! # use angulus::*;
Expand All @@ -38,9 +39,9 @@
//! assert!(a.cos() >= 0.0);
//! ```
//!
//! ### [`AngleUnbounded`]
//! ## [`AngleUnbounded`]
//!
//! Since [`AngleUnbounded`] implements [`PartialOrd`], the order matter and the range may be empty,
//! Since [`AngleUnbounded`] implements [`PartialOrd`], the order matters and the range may be empty,
//! resulting in panic.
//!
//! ```no_run
Expand Down
16 changes: 6 additions & 10 deletions src/serde.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
//! (De)Serialization with the [serde crate](https://docs.rs/serde/latest/serde/).
//!
//! ## Select in which unit to (de)serialize to/from
//!
//! For convenience, even though [`Angle`] and [`AngleUnbounded`] are unit agnostic, they (de)serialize to/from radians.
//! To explicitly (de)serialize to/from a specific unit, you can wrap the angle type into a unit wrapper from
//! [the units module][crate::units].
//!
//! [`Angle`] (and their wrapped equivalents) will serialize to a value in [the main range](Angle#the-main-range).
//! [`Angle`] and [`AngleUnbounded`] are (de)serialized to/from floating point numbers.
//! By default, they are converted into radians or read as a radian values.
//! To convert or read them with a different unit, use one of the wrappers from [the `units` module][crate::units].
//!
//! ```
//! # use angulus::{units::*, *};
//! # use float_eq::assert_float_eq;
//! # use ::serde::{Serialize, Deserialize};
//! #[derive(Serialize, Deserialize)]
//! struct Foo {
//! angle: Angle32,
//! raw: Angle32,
//! rad: Radians<Angle32>,
//! deg: Degrees<Angle32>,
//! tr: Turns<Angle32>,
Expand All @@ -23,7 +19,7 @@
//!
//! let json = serde_json::json!{
//! {
//! "angle": 0.5, // this field is read as 0.5 rad
//! "raw": 0.5, // this field is read as 0.5 rad
//! "rad": 1.0, // this field is read as 1 rad
//! "deg": 90.0, // this field is read as 90°
//! "tr": 0.5, // this field is read as 0.5 turns
Expand All @@ -33,7 +29,7 @@
//!
//! let foo: Foo = serde_json::from_value(json).unwrap();
//!
//! assert_float_eq!(foo.angle.to_radians(), 0.5, abs <= 0.000001);
//! assert_float_eq!(foo.raw.to_radians(), 0.5, abs <= 0.000001);
//! assert_float_eq!(foo.rad.0.to_radians(), 1.0, abs <= 0.000001);
//! assert_float_eq!(foo.deg.0.to_degrees(), 90.0, abs <= 0.000001);
//! assert_float_eq!(foo.tr.0.to_turns(), 0.5, abs <= 0.000001);
Expand Down
7 changes: 4 additions & 3 deletions src/unbounded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ use crate::float::Float;
use crate::macros::{forward_ref_binop, forward_ref_op_assign, forward_ref_unop};
use crate::Angle;

/// Represents a point on the circle as an unit agnostic angle.
/// Represents a point on the circle as a unit-agnostic angle.
///
/// The parameter `F` is the floating-point type used to store the value.
///
/// # Behaviour
/// Unlike [`Angle`], two different values of the same point on the circle are different
/// angles :
///
/// Unlike [`Angle`], two different values of the same point on the circle are
/// two different [`AngleUnbounded`].
///
/// ```
/// # use angulus::AngleUnbounded;
Expand Down
36 changes: 17 additions & 19 deletions src/units.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
//! This module provides wrappers to "colorize" an angle with a specific unit.
//! Wrappers to represent an angle with a specific unit.
//!
//! ## Display
//!
//! Because angles are unit agnostic they cannot implement the [`Display`] trait.
//!
//! But unit wrappers implement the [`Display`] trait.
//! The value is displayed by writing the angle value in the desired unit followed by the unit symbol.
//!
//! For [`Angle`], the displayed value is in [the main range](Angle#the-main-range).
//! Wrapping an [`Angle`] or an [`AngleUnbounded`] with these wrappers enables [`Display`] capability.
//!
//! ```
//! # use angulus::{Angle, ToAngle, units::{Degrees, Radians, Turns, Gradians}};
Expand All @@ -28,42 +21,47 @@ macro_rules! unit {
(
$Unit:ident, $doc:expr, $to_method:ident, $from_method:ident, $format:expr
) => {
/// Unit wrapper to "colorize" an angle in
/// Unit wrapper for the
#[doc = $doc]
/// unit.
///
/// See the [module level documentation][self] for more details.
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct $Unit<A>(pub A);

impl<F: Float> $Unit<Angle<F>> {
/// The value of the angle in
/// Returns the value of the angle in the
#[doc = $doc]
/// unit.
///
/// The value is in [the main range](Angle#the-main-range).
/// The value is in [the main range](crate#the-main-range).
#[inline]
pub fn to_value(self) -> F {
self.0.$to_method()
}

/// Create an new instance from a value in
/// Converts a value in
#[doc = $doc]
/// into an angle.
#[inline]
pub fn from_value(x: F) -> Self {
Self(Angle::$from_method(x))
}
}

impl<F: Float> $Unit<AngleUnbounded<F>> {
/// The value of the angle in
/// Returns the value of the angle in the
#[doc = $doc]
/// unit.
#[inline]
pub fn to_value(self) -> F {
self.0.$to_method()
}

/// Create an new instance from a value in
/// Converts a value in
#[doc = $doc]
/// into an angle.
#[inline]
pub fn from_value(x: F) -> Self {
Self(AngleUnbounded::$from_method(x))
Expand Down Expand Up @@ -93,7 +91,7 @@ macro_rules! unit {
};
}

unit!(Radians, "radians.", to_radians, from_radians, "{} rad");
unit!(Degrees, "degrees.", to_degrees, from_degrees, "{}°");
unit!(Turns, "turns.", to_turns, from_turns, "{} tr");
unit!(Gradians, "gradians.", to_gradians, from_gradians, "{}g");
unit!(Radians, "radian", to_radians, from_radians, "{} rad");
unit!(Degrees, "degree", to_degrees, from_degrees, "{}°");
unit!(Turns, "turn", to_turns, from_turns, "{} tr");
unit!(Gradians, "gradian", to_gradians, from_gradians, "{}g");

0 comments on commit 3b92b0b

Please sign in to comment.