Move free trigonometric functions onto Angle trait
This commit is contained in:
parent
5b9eeb15a0
commit
612be7fecc
6 changed files with 72 additions and 66 deletions
40
src/angle.rs
40
src/angle.rs
|
@ -104,24 +104,22 @@ pub trait Angle where
|
|||
fn equiv(&self, other: &Self) -> bool {
|
||||
self.normalize() == other.normalize()
|
||||
}
|
||||
|
||||
fn sin(self) -> Self::Unitless;
|
||||
fn cos(self) -> Self::Unitless;
|
||||
fn tan(self) -> Self::Unitless;
|
||||
fn sin_cos(self) -> (Self::Unitless, Self::Unitless);
|
||||
|
||||
#[inline] fn cot(self) -> Self::Unitless { Self::tan(self).recip() }
|
||||
#[inline] fn sec(self) -> Self::Unitless { Self::cos(self).recip() }
|
||||
#[inline] fn csc(self) -> Self::Unitless { Self::sin(self).recip() }
|
||||
|
||||
fn asin(a: Self::Unitless) -> Self;
|
||||
fn acos(a: Self::Unitless) -> Self;
|
||||
fn atan(a: Self::Unitless) -> Self;
|
||||
fn atan2(a: Self::Unitless, b: Self::Unitless) -> Self;
|
||||
}
|
||||
|
||||
#[inline] pub fn bisect<A: Angle>(a: A, b: A) -> A { a.bisect(b) }
|
||||
|
||||
#[inline] pub fn sin<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { theta.into().s.sin() }
|
||||
#[inline] pub fn cos<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { theta.into().s.cos() }
|
||||
#[inline] pub fn tan<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { theta.into().s.tan() }
|
||||
#[inline] pub fn sin_cos<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> (S, S) { theta.into().s.sin_cos() }
|
||||
|
||||
#[inline] pub fn cot<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { tan(theta.into()).recip() }
|
||||
#[inline] pub fn sec<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { cos(theta.into()).recip() }
|
||||
#[inline] pub fn csc<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { sin(theta.into()).recip() }
|
||||
|
||||
#[inline] pub fn asin<S: BaseFloat, R: From<Rad<S>>>(s: S) -> R { rad(s.asin()).into() }
|
||||
#[inline] pub fn acos<S: BaseFloat, R: From<Rad<S>>>(s: S) -> R { rad(s.acos()).into() }
|
||||
#[inline] pub fn atan<S: BaseFloat, R: From<Rad<S>>>(s: S) -> R { rad(s.atan()).into() }
|
||||
#[inline] pub fn atan2<S: BaseFloat, R: From<Rad<S>>>(a: S, b: S) -> R { rad(a.atan2(b)).into() }
|
||||
|
||||
macro_rules! impl_angle {
|
||||
($Angle:ident, $fmt:expr, $full_turn:expr, $hi:expr) => {
|
||||
impl<S: BaseFloat> Angle for $Angle<S> {
|
||||
|
@ -148,6 +146,16 @@ macro_rules! impl_angle {
|
|||
#[inline] fn turn_div_3() -> $Angle<S> { let factor: S = cast(3).unwrap(); $Angle::full_turn() / factor }
|
||||
#[inline] fn turn_div_4() -> $Angle<S> { let factor: S = cast(4).unwrap(); $Angle::full_turn() / factor }
|
||||
#[inline] fn turn_div_6() -> $Angle<S> { let factor: S = cast(6).unwrap(); $Angle::full_turn() / factor }
|
||||
|
||||
#[inline] fn sin(self) -> S { let rad: Rad<S> = self.into(); rad.s.sin() }
|
||||
#[inline] fn cos(self) -> S { let rad: Rad<S> = self.into(); rad.s.cos() }
|
||||
#[inline] fn tan(self) -> S { let rad: Rad<S> = self.into(); rad.s.tan() }
|
||||
#[inline] fn sin_cos(self) -> (S, S) { let rad: Rad<S> = self.into(); rad.s.sin_cos() }
|
||||
|
||||
#[inline] fn asin(a: S) -> $Angle<S> { Rad::new(a.asin()).into() }
|
||||
#[inline] fn acos(a: S) -> $Angle<S> { Rad::new(a.acos()).into() }
|
||||
#[inline] fn atan(a: S) -> $Angle<S> { Rad::new(a.atan()).into() }
|
||||
#[inline] fn atan2(a: S, b: S) -> $Angle<S> { Rad::new(a.atan2(b)).into() }
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> Neg for $Angle<S> {
|
||||
|
|
|
@ -25,7 +25,7 @@ use rand::{Rand, Rng};
|
|||
use rust_num::{Zero, One};
|
||||
use rust_num::traits::cast;
|
||||
|
||||
use angle::{Rad, sin, cos, sin_cos};
|
||||
use angle::{Angle, Rad};
|
||||
use approx::ApproxEq;
|
||||
use array::Array;
|
||||
use num::BaseFloat;
|
||||
|
@ -71,11 +71,11 @@ impl<S: BaseFloat> Matrix2<S> {
|
|||
|
||||
#[inline]
|
||||
pub fn from_angle(theta: Rad<S>) -> Matrix2<S> {
|
||||
let cos_theta = cos(theta.clone());
|
||||
let sin_theta = sin(theta.clone());
|
||||
let cos_theta = Rad::cos(theta);
|
||||
let sin_theta = Rad::sin(theta);
|
||||
|
||||
Matrix2::new(cos_theta.clone(), sin_theta.clone(),
|
||||
-sin_theta.clone(), cos_theta.clone())
|
||||
Matrix2::new(cos_theta, sin_theta,
|
||||
-sin_theta, cos_theta)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,27 +118,27 @@ impl<S: BaseFloat> Matrix3<S> {
|
|||
/// Create a rotation matrix from a rotation around the `x` axis (pitch).
|
||||
pub fn from_angle_x(theta: Rad<S>) -> Matrix3<S> {
|
||||
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
|
||||
let (s, c) = sin_cos(theta);
|
||||
let (s, c) = Rad::sin_cos(theta);
|
||||
Matrix3::new(S::one(), S::zero(), S::zero(),
|
||||
S::zero(), c.clone(), s.clone(),
|
||||
S::zero(), -s.clone(), c.clone())
|
||||
S::zero(), c, s,
|
||||
S::zero(), -s, c)
|
||||
}
|
||||
|
||||
/// Create a rotation matrix from a rotation around the `y` axis (yaw).
|
||||
pub fn from_angle_y(theta: Rad<S>) -> Matrix3<S> {
|
||||
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
|
||||
let (s, c) = sin_cos(theta);
|
||||
Matrix3::new(c.clone(), S::zero(), -s.clone(),
|
||||
let (s, c) = Rad::sin_cos(theta);
|
||||
Matrix3::new(c, S::zero(), -s,
|
||||
S::zero(), S::one(), S::zero(),
|
||||
s.clone(), S::zero(), c.clone())
|
||||
s, S::zero(), c)
|
||||
}
|
||||
|
||||
/// Create a rotation matrix from a rotation around the `z` axis (roll).
|
||||
pub fn from_angle_z(theta: Rad<S>) -> Matrix3<S> {
|
||||
// http://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
|
||||
let (s, c) = sin_cos(theta);
|
||||
Matrix3::new( c.clone(), s.clone(), S::zero(),
|
||||
-s.clone(), c.clone(), S::zero(),
|
||||
let (s, c) = Rad::sin_cos(theta);
|
||||
Matrix3::new( c, s, S::zero(),
|
||||
-s, c, S::zero(),
|
||||
S::zero(), S::zero(), S::one())
|
||||
}
|
||||
|
||||
|
@ -151,18 +151,18 @@ impl<S: BaseFloat> Matrix3<S> {
|
|||
/// - `z`: the angular rotation around the `z` axis (roll).
|
||||
pub fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Matrix3<S> {
|
||||
// http://en.wikipedia.org/wiki/Rotation_matrix#General_rotations
|
||||
let (sx, cx) = sin_cos(x);
|
||||
let (sy, cy) = sin_cos(y);
|
||||
let (sz, cz) = sin_cos(z);
|
||||
let (sx, cx) = Rad::sin_cos(x);
|
||||
let (sy, cy) = Rad::sin_cos(y);
|
||||
let (sz, cz) = Rad::sin_cos(z);
|
||||
|
||||
Matrix3::new( cy * cz, cy * sz, -sy,
|
||||
-cx * sz + sx * sy * cz, cx * cz + sx * sy * sz, sx * cy,
|
||||
sx * sz + cx * sy * cz, -sx * cz + cx * sy * sz, cx * cy)
|
||||
Matrix3::new(cy * cz, cy * sz, -sy,
|
||||
-cx * sz + sx * sy * cz, cx * cz + sx * sy * sz, sx * cy,
|
||||
sx * sz + cx * sy * cz, -sx * cz + cx * sy * sz, cx * cy)
|
||||
}
|
||||
|
||||
/// Create a rotation matrix from an angle around an arbitrary axis.
|
||||
pub fn from_axis_angle(axis: Vector3<S>, angle: Rad<S>) -> Matrix3<S> {
|
||||
let (s, c) = sin_cos(angle);
|
||||
let (s, c) = Rad::sin_cos(angle);
|
||||
let _1subc = S::one() - c;
|
||||
|
||||
Matrix3::new(_1subc * axis.x * axis.x + c,
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
use rust_num::{Zero, One};
|
||||
use rust_num::traits::cast;
|
||||
|
||||
use angle::{Angle, Rad, tan, cot};
|
||||
use angle::{Angle, Rad};
|
||||
use matrix::Matrix4;
|
||||
use num::BaseFloat;
|
||||
|
||||
|
@ -76,7 +76,7 @@ impl<S: BaseFloat> PerspectiveFov<S> {
|
|||
pub fn to_perspective(&self) -> Perspective<S> {
|
||||
let two: S = cast(2).unwrap();
|
||||
let angle = self.fovy / two;
|
||||
let ymax = self.near * tan(angle);
|
||||
let ymax = self.near * Rad::tan(angle);
|
||||
let xmax = ymax * self.aspect;
|
||||
|
||||
Perspective {
|
||||
|
@ -100,7 +100,7 @@ impl<S: BaseFloat> From<PerspectiveFov<S>> for Matrix4<S> {
|
|||
assert!(persp.far > persp.near, "The far plane cannot be closer than the near plane, found: far: {:?}, near: {:?}", persp.far, persp.near);
|
||||
|
||||
let two: S = cast(2).unwrap();
|
||||
let f = cot(persp.fovy / two);
|
||||
let f = Rad::cot(persp.fovy / two);
|
||||
|
||||
let c0r0 = f / persp.aspect;
|
||||
let c0r1 = S::zero();
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::f64;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::ops::*;
|
||||
|
@ -22,7 +21,7 @@ use rand::{Rand, Rng};
|
|||
use rust_num::{Float, One, Zero};
|
||||
use rust_num::traits::cast;
|
||||
|
||||
use angle::{Angle, Rad, acos, sin, sin_cos, rad};
|
||||
use angle::{Angle, Rad};
|
||||
use approx::ApproxEq;
|
||||
use matrix::{Matrix3, Matrix4};
|
||||
use num::BaseFloat;
|
||||
|
@ -210,12 +209,12 @@ impl<S: BaseFloat> Quaternion<S> {
|
|||
dot
|
||||
};
|
||||
|
||||
let theta: Rad<S> = acos(robust_dot.clone());
|
||||
let theta = Rad::acos(robust_dot.clone());
|
||||
|
||||
let scale1 = sin(theta * (S::one() - amount));
|
||||
let scale2 = sin(theta * amount);
|
||||
let scale1 = Rad::sin(theta * (S::one() - amount));
|
||||
let scale2 = Rad::sin(theta * amount);
|
||||
|
||||
(self * scale1 + other * scale2) * sin(theta).recip()
|
||||
(self * scale1 + other * scale2) * Rad::sin(theta).recip()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,22 +237,21 @@ impl<S: BaseFloat> Quaternion<S> {
|
|||
|
||||
if test > sig * unit {
|
||||
(
|
||||
rad(S::zero()),
|
||||
rad(cast(f64::consts::FRAC_PI_2).unwrap()),
|
||||
rad(two * qx.atan2(qw)),
|
||||
Rad::zero(),
|
||||
Rad::turn_div_4(),
|
||||
Rad::atan2(qx, qw) * two,
|
||||
)
|
||||
} else if test < -sig * unit {
|
||||
let y: S = cast(f64::consts::FRAC_PI_2).unwrap();
|
||||
(
|
||||
rad(S::zero()),
|
||||
rad(-y),
|
||||
rad(two * qx.atan2(qw)),
|
||||
Rad::zero(),
|
||||
-Rad::turn_div_4(),
|
||||
Rad::atan2(qx, qw) * two,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
rad((two * (qy * qw - qx * qz)).atan2(one - two * (sqy + sqz))),
|
||||
rad((two * (qx * qy + qz * qw)).asin()),
|
||||
rad((two * (qx * qw - qy * qz)).atan2(one - two * (sqx + sqz))),
|
||||
Rad::atan2(two * (qy * qw - qx * qz), one - two * (sqy + sqz)),
|
||||
Rad::asin(two * (qx * qy + qz * qw)),
|
||||
Rad::atan2(two * (qx * qw - qy * qz), one - two * (sqx + sqz)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -362,16 +360,16 @@ impl<S: BaseFloat> Rotation<Point3<S>> for Quaternion<S> {
|
|||
impl<S: BaseFloat> Rotation3<S> for Quaternion<S> {
|
||||
#[inline]
|
||||
fn from_axis_angle(axis: Vector3<S>, angle: Rad<S>) -> Quaternion<S> {
|
||||
let (s, c) = sin_cos(angle * cast(0.5f64).unwrap());
|
||||
let (s, c) = Rad::sin_cos(angle * cast(0.5f64).unwrap());
|
||||
Quaternion::from_sv(c, axis * s)
|
||||
}
|
||||
|
||||
/// - [Maths - Conversion Euler to Quaternion]
|
||||
/// (http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm)
|
||||
fn from_euler(x: Rad<S>, y: Rad<S>, z: Rad<S>) -> Quaternion<S> {
|
||||
let (s1, c1) = sin_cos(x * cast(0.5f64).unwrap());
|
||||
let (s2, c2) = sin_cos(y * cast(0.5f64).unwrap());
|
||||
let (s3, c3) = sin_cos(z * cast(0.5f64).unwrap());
|
||||
let (s1, c1) = Rad::sin_cos(x * cast(0.5f64).unwrap());
|
||||
let (s2, c2) = Rad::sin_cos(y * cast(0.5f64).unwrap());
|
||||
let (s3, c3) = Rad::sin_cos(z * cast(0.5f64).unwrap());
|
||||
|
||||
Quaternion::new(c1 * c2 * c3 - s1 * s2 * s3,
|
||||
s1 * s2 * c3 + c1 * c2 * s3,
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use angle::{Rad, acos};
|
||||
use angle::{Angle, Rad};
|
||||
use approx::ApproxEq;
|
||||
use matrix::{Matrix, SquareMatrix};
|
||||
use matrix::{Matrix2, Matrix3};
|
||||
|
@ -186,7 +186,7 @@ impl<S: BaseFloat> Rotation<Point2<S>> for Basis2<S> {
|
|||
|
||||
#[inline]
|
||||
fn between_vectors(a: Vector2<S>, b: Vector2<S>) -> Basis2<S> {
|
||||
Rotation2::from_angle(acos(a.dot(b)) )
|
||||
Rotation2::from_angle(Rad::acos(a.dot(b)) )
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -95,7 +95,7 @@ use rand::{Rand, Rng};
|
|||
|
||||
use rust_num::{NumCast, Zero, One};
|
||||
|
||||
use angle::{Rad, atan2, acos};
|
||||
use angle::{Angle, Rad};
|
||||
use approx::ApproxEq;
|
||||
use array::Array;
|
||||
use num::{BaseNum, BaseFloat, PartialOrd};
|
||||
|
@ -441,21 +441,21 @@ pub trait EuclideanVector: Vector + Sized where
|
|||
impl<S: BaseFloat> EuclideanVector for Vector2<S> {
|
||||
#[inline]
|
||||
fn angle(self, other: Vector2<S>) -> Rad<S> {
|
||||
atan2(self.perp_dot(other), self.dot(other))
|
||||
Rad::atan2(self.perp_dot(other), self.dot(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> EuclideanVector for Vector3<S> {
|
||||
#[inline]
|
||||
fn angle(self, other: Vector3<S>) -> Rad<S> {
|
||||
atan2(self.cross(other).length(), self.dot(other))
|
||||
Rad::atan2(self.cross(other).length(), self.dot(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: BaseFloat> EuclideanVector for Vector4<S> {
|
||||
#[inline]
|
||||
fn angle(self, other: Vector4<S>) -> Rad<S> {
|
||||
acos(self.dot(other) / (self.length() * other.length()))
|
||||
Rad::acos(self.dot(other) / (self.length() * other.length()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue