Skip to content

Commit

Permalink
Merge pull request #619 from gabsi26/implement_angle_type
Browse files Browse the repository at this point in the history
Create and use `Angle` type
  • Loading branch information
hannobraun authored May 23, 2022
2 parents 4780571 + 010a265 commit 5eb3946
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 9 deletions.
2 changes: 1 addition & 1 deletion crates/fj-operations/src/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ impl ToShape for fj::Transform {
fn transform(transform: &fj::Transform) -> Transform {
let axis = Vector::from(transform.axis).normalize();
Transform::translation(transform.offset)
* Transform::rotation(axis * transform.angle)
* Transform::rotation(axis * transform.angle.rad())
}
101 changes: 101 additions & 0 deletions crates/fj/src/angle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use std::f64::consts::PI;

/// An angle
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serialization", derive(Serialize, Deserialize))]
pub struct Angle {
// The value of the angle in radians
rad: f64,
}

impl Angle {
/// Create a new angle specified in radians
pub fn from_rad(rad: f64) -> Self {
Self {
rad: Self::wrap(rad),
}
}
/// Create a new angle specified in degrees
pub fn from_deg(deg: f64) -> Self {
Self::from_rad(deg.to_radians())
}
/// Retrieve value of angle as radians
pub fn rad(&self) -> f64 {
self.rad
}
/// Retrieve value of angle as degrees
pub fn deg(&self) -> f64 {
self.rad.to_degrees()
}

// ensures that the angle is always 0 <= a < 2*pi
fn wrap(rad: f64) -> f64 {
let modulo = rad % (2. * PI);
if modulo < 0. {
modulo * -1.
} else {
modulo
}
}

// ensures that the angle is always 0 <= a < 2*pi
fn wrap_assign(&mut self) {
self.rad = Self::wrap(self.rad);
}
}

impl std::ops::Add for Angle {
type Output = Angle;
fn add(self, rhs: Self) -> Self::Output {
Self::from_rad(self.rad + rhs.rad)
}
}

impl std::ops::AddAssign for Angle {
fn add_assign(&mut self, rhs: Self) {
self.rad += rhs.rad;
self.wrap_assign()
}
}

impl std::ops::Sub for Angle {
type Output = Angle;
fn sub(self, rhs: Self) -> Self::Output {
Self::from_rad(self.rad - rhs.rad)
}
}

impl std::ops::SubAssign for Angle {
fn sub_assign(&mut self, rhs: Self) {
self.rad -= rhs.rad;
self.wrap_assign()
}
}

impl std::ops::Mul for Angle {
type Output = Angle;
fn mul(self, rhs: Self) -> Self::Output {
Self::from_rad(self.rad * rhs.rad)
}
}

impl std::ops::MulAssign for Angle {
fn mul_assign(&mut self, rhs: Self) {
self.rad *= rhs.rad;
self.wrap_assign()
}
}

impl std::ops::Div for Angle {
type Output = Angle;
fn div(self, rhs: Self) -> Self::Output {
Self::from_rad(self.rad / rhs.rad)
}
}

impl std::ops::DivAssign for Angle {
fn div_assign(&mut self, rhs: Self) {
self.rad /= rhs.rad;
self.wrap_assign()
}
}
3 changes: 2 additions & 1 deletion crates/fj/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@

pub mod syntax;

mod angle;
mod shape_2d;
mod shape_3d;

pub use self::{shape_2d::*, shape_3d::*};
pub use self::{angle::*, shape_2d::*, shape_3d::*};

/// A shape
#[derive(Clone, Debug)]
Expand Down
4 changes: 2 additions & 2 deletions crates/fj/src/shape_3d.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Shape, Shape2d};
use crate::{Angle, Shape, Shape2d};

/// A 3-dimensional shape
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -72,7 +72,7 @@ pub struct Transform {
pub axis: [f64; 3],

/// The angle of the rotation
pub angle: f64,
pub angle: Angle,

/// The offset of the translation
pub offset: [f64; 3],
Expand Down
6 changes: 3 additions & 3 deletions crates/fj/src/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub trait Transform {
///
/// Create a rotation that rotates `shape` by `angle` around an axis defined
/// by `axis`.
fn rotate(&self, axis: [f64; 3], angle: f64) -> crate::Transform;
fn rotate(&self, axis: [f64; 3], angle: crate::Angle) -> crate::Transform;

/// Create a translation
///
Expand All @@ -111,7 +111,7 @@ impl<T> Transform for T
where
T: Clone + Into<crate::Shape3d>,
{
fn rotate(&self, axis: [f64; 3], angle: f64) -> crate::Transform {
fn rotate(&self, axis: [f64; 3], angle: crate::Angle) -> crate::Transform {
let shape = self.clone().into();
crate::Transform {
shape,
Expand All @@ -126,7 +126,7 @@ where
crate::Transform {
shape,
axis: [1., 0., 0.],
angle: 0.,
angle: crate::Angle::from_rad(0.),
offset,
}
}
Expand Down
5 changes: 3 additions & 2 deletions models/star/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use fj::Angle;
use std::{collections::HashMap, f64::consts::PI};

#[no_mangle]
Expand Down Expand Up @@ -31,7 +32,7 @@ pub extern "C" fn model(args: &HashMap<String, String>) -> fj::Shape {
// gives us the angle and radius for each vertex.
let num_vertices = num_points * 2;
let vertex_iter = (0..num_vertices).map(|i| {
let angle = 2. * PI / num_vertices as f64 * i as f64;
let angle = Angle::from_rad(2. * PI / num_vertices as f64 * i as f64);
let radius = if i % 2 == 0 { r1 } else { r2 };
(angle, radius)
});
Expand All @@ -41,7 +42,7 @@ pub extern "C" fn model(args: &HashMap<String, String>) -> fj::Shape {
let mut outer = Vec::new();
let mut inner = Vec::new();
for (angle, radius) in vertex_iter {
let (sin, cos) = angle.sin_cos();
let (sin, cos) = angle.rad().sin_cos();

let x = cos * radius;
let y = sin * radius;
Expand Down

0 comments on commit 5eb3946

Please sign in to comment.