summaryrefslogtreecommitdiff
path: root/src/geom
diff options
context:
space:
mode:
Diffstat (limited to 'src/geom')
-rw-r--r--src/geom/angle.rs172
-rw-r--r--src/geom/length.rs50
-rw-r--r--src/geom/mod.rs2
3 files changed, 199 insertions, 25 deletions
diff --git a/src/geom/angle.rs b/src/geom/angle.rs
new file mode 100644
index 00000000..47541cb8
--- /dev/null
+++ b/src/geom/angle.rs
@@ -0,0 +1,172 @@
+use std::f64::consts::PI;
+
+use super::*;
+
+/// An angle.
+#[derive(Default, Copy, Clone, PartialEq, PartialOrd)]
+pub struct Angle {
+ /// The angle in raw units.
+ raw: f64,
+}
+
+impl Angle {
+ /// The zero angle.
+ pub const ZERO: Self = Self { raw: 0.0 };
+
+ /// Create an angle from a number of radians.
+ pub fn rad(rad: f64) -> Self {
+ Self::with_unit(rad, AngularUnit::Rad)
+ }
+
+ /// Create an angle from a number of degrees.
+ pub fn deg(deg: f64) -> Self {
+ Self::with_unit(deg, AngularUnit::Deg)
+ }
+
+ /// Create an angle from a number of raw units.
+ pub fn raw(raw: f64) -> Self {
+ Self { raw }
+ }
+
+ /// Convert this to a number of radians.
+ pub fn to_rad(self) -> f64 {
+ self.to_unit(AngularUnit::Rad)
+ }
+
+ /// Convert this to a number of degrees.
+ pub fn to_deg(self) -> f64 {
+ self.to_unit(AngularUnit::Deg)
+ }
+
+ /// Get the value of this angle in raw units.
+ pub fn to_raw(self) -> f64 {
+ self.raw
+ }
+
+ /// Create an angle from a value in a unit.
+ pub fn with_unit(val: f64, unit: AngularUnit) -> Self {
+ Self { raw: val * unit.raw_scale() }
+ }
+
+ /// Get the value of this length in unit.
+ pub fn to_unit(self, unit: AngularUnit) -> f64 {
+ self.raw / unit.raw_scale()
+ }
+}
+
+impl Display for Angle {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ write!(f, "{}{}", self.to_deg(), AngularUnit::Deg)
+ }
+}
+
+impl Debug for Angle {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ Display::fmt(self, f)
+ }
+}
+
+impl Neg for Angle {
+ type Output = Self;
+
+ fn neg(self) -> Self {
+ Self { raw: -self.raw }
+ }
+}
+
+impl Add for Angle {
+ type Output = Self;
+
+ fn add(self, other: Self) -> Self {
+ Self { raw: self.raw + other.raw }
+ }
+}
+
+sub_impl!(Angle - Angle -> Angle);
+
+impl Mul<f64> for Angle {
+ type Output = Self;
+
+ fn mul(self, other: f64) -> Self {
+ Self { raw: self.raw * other }
+ }
+}
+
+impl Mul<Angle> for f64 {
+ type Output = Angle;
+
+ fn mul(self, other: Angle) -> Angle {
+ other * self
+ }
+}
+
+impl Div<f64> for Angle {
+ type Output = Self;
+
+ fn div(self, other: f64) -> Self {
+ Self { raw: self.raw / other }
+ }
+}
+
+impl Div for Angle {
+ type Output = f64;
+
+ fn div(self, other: Self) -> f64 {
+ self.raw / other.raw
+ }
+}
+
+assign_impl!(Angle += Angle);
+assign_impl!(Angle -= Angle);
+assign_impl!(Angle *= f64);
+assign_impl!(Angle /= f64);
+
+impl Sum for Angle {
+ fn sum<I: Iterator<Item = Angle>>(iter: I) -> Self {
+ iter.fold(Angle::ZERO, Add::add)
+ }
+}
+/// Different units of angular measurement.
+#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+pub enum AngularUnit {
+ /// Radians.
+ Rad,
+ /// Degrees.
+ Deg,
+}
+
+impl AngularUnit {
+ /// How many raw units correspond to a value of `1.0` in this unit.
+ fn raw_scale(self) -> f64 {
+ match self {
+ Self::Rad => 1.0,
+ Self::Deg => PI / 180.0,
+ }
+ }
+}
+
+impl Display for AngularUnit {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ f.pad(match self {
+ Self::Rad => "rad",
+ Self::Deg => "deg",
+ })
+ }
+}
+
+impl Debug for AngularUnit {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ Display::fmt(self, f)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_angle_unit_conversion() {
+ assert!((Angle::rad(2.0 * PI).to_deg() - 360.0) < 1e-4);
+ assert!((Angle::deg(45.0).to_rad() - 0.7854) < 1e-4);
+ }
+}
diff --git a/src/geom/length.rs b/src/geom/length.rs
index 23650e89..3e6c8601 100644
--- a/src/geom/length.rs
+++ b/src/geom/length.rs
@@ -13,22 +13,22 @@ impl Length {
/// Create a length from a number of points.
pub fn pt(pt: f64) -> Self {
- Self::with_unit(pt, Unit::Pt)
+ Self::with_unit(pt, LengthUnit::Pt)
}
/// Create a length from a number of millimeters.
pub fn mm(mm: f64) -> Self {
- Self::with_unit(mm, Unit::Mm)
+ Self::with_unit(mm, LengthUnit::Mm)
}
/// Create a length from a number of centimeters.
pub fn cm(cm: f64) -> Self {
- Self::with_unit(cm, Unit::Cm)
+ Self::with_unit(cm, LengthUnit::Cm)
}
/// Create a length from a number of inches.
pub fn inches(inches: f64) -> Self {
- Self::with_unit(inches, Unit::In)
+ Self::with_unit(inches, LengthUnit::In)
}
/// Create a length from a number of raw units.
@@ -38,22 +38,22 @@ impl Length {
/// Convert this to a number of points.
pub fn to_pt(self) -> f64 {
- self.to_unit(Unit::Pt)
+ self.to_unit(LengthUnit::Pt)
}
/// Convert this to a number of millimeters.
pub fn to_mm(self) -> f64 {
- self.to_unit(Unit::Mm)
+ self.to_unit(LengthUnit::Mm)
}
/// Convert this to a number of centimeters.
pub fn to_cm(self) -> f64 {
- self.to_unit(Unit::Cm)
+ self.to_unit(LengthUnit::Cm)
}
/// Convert this to a number of inches.
pub fn to_inches(self) -> f64 {
- self.to_unit(Unit::In)
+ self.to_unit(LengthUnit::In)
}
/// Get the value of this length in raw units.
@@ -62,12 +62,12 @@ impl Length {
}
/// Create a length from a value in a unit.
- pub fn with_unit(val: f64, unit: Unit) -> Self {
+ pub fn with_unit(val: f64, unit: LengthUnit) -> Self {
Self { raw: val * unit.raw_scale() }
}
/// Get the value of this length in unit.
- pub fn to_unit(self, unit: Unit) -> f64 {
+ pub fn to_unit(self, unit: LengthUnit) -> f64 {
self.raw / unit.raw_scale()
}
@@ -86,9 +86,9 @@ impl Display for Length {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
// Format small lengths as points and large ones as centimeters.
let (val, unit) = if self.to_pt().abs() < 25.0 {
- (self.to_pt(), Unit::Pt)
+ (self.to_pt(), LengthUnit::Pt)
} else {
- (self.to_cm(), Unit::Cm)
+ (self.to_cm(), LengthUnit::Cm)
};
write!(f, "{}{}", (val * 100.0).round() / 100.0, unit)
}
@@ -161,9 +161,9 @@ impl Sum for Length {
}
}
-/// Different units of measurement.
+/// Different units of length measurement.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
-pub enum Unit {
+pub enum LengthUnit {
/// Points.
Pt,
/// Millimeters.
@@ -174,30 +174,30 @@ pub enum Unit {
In,
}
-impl Unit {
+impl LengthUnit {
/// How many raw units correspond to a value of `1.0` in this unit.
fn raw_scale(self) -> f64 {
match self {
- Unit::Pt => 1.0,
- Unit::Mm => 2.83465,
- Unit::Cm => 28.3465,
- Unit::In => 72.0,
+ LengthUnit::Pt => 1.0,
+ LengthUnit::Mm => 2.83465,
+ LengthUnit::Cm => 28.3465,
+ LengthUnit::In => 72.0,
}
}
}
-impl Display for Unit {
+impl Display for LengthUnit {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.pad(match self {
- Unit::Mm => "mm",
- Unit::Pt => "pt",
- Unit::Cm => "cm",
- Unit::In => "in",
+ LengthUnit::Mm => "mm",
+ LengthUnit::Pt => "pt",
+ LengthUnit::Cm => "cm",
+ LengthUnit::In => "in",
})
}
}
-impl Debug for Unit {
+impl Debug for LengthUnit {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
Display::fmt(self, f)
}
diff --git a/src/geom/mod.rs b/src/geom/mod.rs
index 69bb0898..e601cb1f 100644
--- a/src/geom/mod.rs
+++ b/src/geom/mod.rs
@@ -3,6 +3,7 @@
#[macro_use]
mod macros;
mod align;
+mod angle;
mod dir;
mod gen;
mod length;
@@ -14,6 +15,7 @@ mod size;
mod spec;
pub use align::*;
+pub use angle::*;
pub use dir::*;
pub use gen::*;
pub use length::*;