cgmath/src/angle.rs

334 lines
11 KiB
Rust
Raw Normal View History

2014-05-26 17:10:04 +00:00
// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
2015-03-14 02:49:46 +00:00
// refer to the Cargo.toml file at the top-level directory of this distribution.
2013-09-04 02:20:53 +00:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Angle units for type-safe, self-documenting code.
2013-10-19 14:00:44 +00:00
use std::fmt;
use std::f64;
2015-01-03 21:29:26 +00:00
use std::ops::*;
2013-09-04 02:20:53 +00:00
2015-03-15 02:53:57 +00:00
use rand::{Rand, Rng};
use rand::distributions::range::SampleRange;
2015-04-05 01:32:12 +00:00
use rust_num::{Float, One, Zero, one, zero};
2015-04-25 03:28:31 +00:00
use rust_num::traits::cast;
2015-04-05 01:19:11 +00:00
2014-01-09 00:26:50 +00:00
use approx::ApproxEq;
2015-04-05 01:19:11 +00:00
use num::BaseFloat;
2014-01-09 00:26:50 +00:00
2014-05-25 10:00:52 +00:00
/// An angle, in radians
2015-02-08 18:25:42 +00:00
#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, RustcEncodable, RustcDecodable)]
pub struct Rad<S> { pub s: S }
2014-05-25 10:00:52 +00:00
/// An angle, in degrees
2015-02-08 18:25:42 +00:00
#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, RustcEncodable, RustcDecodable)]
pub struct Deg<S> { pub s: S }
2013-09-04 02:20:53 +00:00
2014-05-25 10:00:52 +00:00
/// Create a new angle, in radians
2014-05-26 17:10:04 +00:00
#[inline] pub fn rad<S: BaseFloat>(s: S) -> Rad<S> { Rad { s: s } }
2014-05-25 10:00:52 +00:00
/// Create a new angle, in degrees
2014-05-26 17:10:04 +00:00
#[inline] pub fn deg<S: BaseFloat>(s: S) -> Deg<S> { Deg { s: s } }
2013-09-04 02:20:53 +00:00
2015-05-06 08:10:26 +00:00
impl<S> From<Rad<S>> for Deg<S> where S: BaseFloat {
2015-04-05 01:32:12 +00:00
#[inline]
2015-05-06 08:10:26 +00:00
fn from(r: Rad<S>) -> Deg<S> {
deg(r.s * cast(180.0 / f64::consts::PI).unwrap())
2015-04-05 01:32:12 +00:00
}
}
2013-09-04 02:20:53 +00:00
2015-05-06 08:10:26 +00:00
impl<S> From<Deg<S>> for Rad<S> where S: BaseFloat {
2015-04-05 01:32:12 +00:00
#[inline]
2015-05-06 08:10:26 +00:00
fn from(d: Deg<S>) -> Rad<S> {
rad(d.s * cast(f64::consts::PI / 180.0).unwrap())
2015-04-05 01:32:12 +00:00
}
}
2013-09-04 02:20:53 +00:00
/// Private utility functions for converting to/from scalars
trait ScalarConv<S> {
fn from(s: S) -> Self;
fn s<'a>(&'a self) -> &'a S;
fn mut_s<'a>(&'a mut self) -> &'a mut S;
}
2014-05-26 17:10:04 +00:00
impl<S: BaseFloat> ScalarConv<S> for Rad<S> {
#[inline] fn from(s: S) -> Rad<S> { rad(s) }
#[inline] fn s<'a>(&'a self) -> &'a S { &self.s }
#[inline] fn mut_s<'a>(&'a mut self) -> &'a mut S { &mut self.s }
}
2014-05-26 17:10:04 +00:00
impl<S: BaseFloat> ScalarConv<S> for Deg<S> {
#[inline] fn from(s: S) -> Deg<S> { deg(s) }
#[inline] fn s<'a>(&'a self) -> &'a S { &self.s }
#[inline] fn mut_s<'a>(&'a mut self) -> &'a mut S { &mut self.s }
}
2014-05-25 10:00:52 +00:00
/// Operations on angles.
2013-09-04 02:20:53 +00:00
pub trait Angle
<
2014-05-26 17:10:04 +00:00
S: BaseFloat
2013-09-04 02:20:53 +00:00
>
: Clone + Zero
+ PartialEq + PartialOrd
2013-09-04 02:20:53 +00:00
+ ApproxEq<S>
2015-01-05 01:56:01 +00:00
+ Neg<Output=Self>
2015-05-06 08:10:26 +00:00
+ Into<Rad<S>>
+ Into<Deg<S>>
+ ScalarConv<S>
2015-01-23 23:01:24 +00:00
+ fmt::Debug
2013-09-04 02:20:53 +00:00
{
2014-05-25 10:00:52 +00:00
/// Create a new angle from any other valid angle.
2013-09-04 02:20:53 +00:00
fn from<A: Angle<S>>(theta: A) -> Self;
2014-05-25 10:00:52 +00:00
/// Negate this angle, in-place.
2014-12-21 17:28:59 +00:00
#[inline] fn neg_self(&mut self) { *self = -(*self).clone() }
2013-09-04 02:20:53 +00:00
2014-05-25 10:00:52 +00:00
/// Add this angle with another, returning the new angle.
#[inline] fn add_a(&self, other: Self) -> Self { ScalarConv::from(*self.s() + *other.s()) }
2014-05-25 10:00:52 +00:00
/// Subtract another angle from this one, returning the new angle.
#[inline] fn sub_a(&self, other: Self) -> Self { ScalarConv::from(*self.s() - *other.s()) }
2014-05-25 10:00:52 +00:00
/// Divide this angle by another, returning the ratio.
2013-09-04 02:20:53 +00:00
#[inline] fn div_a(&self, other: Self) -> S { *self.s() / *other.s() }
2014-05-25 10:00:52 +00:00
/// Take the remainder of this angle with another.
2013-09-04 02:20:53 +00:00
#[inline] fn rem_a(&self, other: Self) -> S { *self.s() % *other.s() }
2014-05-25 10:00:52 +00:00
/// Multiply this angle by a scalar, returning the new angle.
#[inline] fn mul_s(&self, s: S) -> Self { ScalarConv::from(*self.s() * s) }
2014-05-25 10:00:52 +00:00
/// Divide this angle by a scalar, returing the new angle.
#[inline] fn div_s(&self, s: S) -> Self { ScalarConv::from(*self.s() / s) }
2014-05-25 10:00:52 +00:00
/// Take the remainder of this angle by a scalar, returning the new angle.
#[inline] fn rem_s(&self, s: S) -> Self { ScalarConv::from(*self.s() % s) }
2013-09-04 02:20:53 +00:00
2014-05-25 10:00:52 +00:00
/// Add this angle with another, in-place.
2013-09-04 02:20:53 +00:00
#[inline] fn add_self_a(&mut self, other: Self) { *self.mut_s() = *self.s() + *other.s() }
2014-05-25 10:00:52 +00:00
/// Subtract another angle from this one, in-place.
2013-09-04 02:20:53 +00:00
#[inline] fn sub_self_a(&mut self, other: Self) { *self.mut_s() = *self.s() - *other.s() }
2014-05-25 10:00:52 +00:00
/// Multiply this angle by a scalar, in-place.
2013-09-04 02:20:53 +00:00
#[inline] fn mul_self_s(&mut self, s: S) { *self.mut_s() = *self.s() * s }
2014-05-25 10:00:52 +00:00
/// Divide this angle by a scalar, in-place.
2013-09-04 02:20:53 +00:00
#[inline] fn div_self_s(&mut self, s: S) { *self.mut_s() = *self.s() / s }
2014-05-25 10:00:52 +00:00
/// Take the remainder of this angle by a scalar, in-place.
2013-09-04 02:20:53 +00:00
#[inline] fn rem_self_s(&mut self, s: S) { *self.mut_s() = *self.s() % s }
/// Return the angle, normalized to the range `[0, full_turn)`.
#[inline]
fn normalize(&self) -> Self {
let mut a = self.clone();
a.normalize_self();
a
}
/// Normalize the angle to the range `[0, full_turn)`.
#[inline]
fn normalize_self(&mut self) {
let full_turn: Self = Angle::full_turn();
self.rem_self_s(full_turn.s().clone());
if *self < zero() { self.add_self_a(full_turn) };
}
/// Return the angle rotated by half a turn
#[inline]
fn opposite(&self) -> Self {
self.add_a(Angle::turn_div_2()).normalize()
}
2013-09-17 06:40:29 +00:00
/// Returns the interior bisector of the two angles
#[inline]
fn bisect(&self, other: Self) -> Self {
2014-06-26 04:26:15 +00:00
self.add_a(self.sub_a(other).mul_s(cast(0.5f64).unwrap())).normalize()
2013-09-17 06:40:29 +00:00
}
fn full_turn() -> Self;
2015-01-09 23:16:39 +00:00
#[inline] fn turn_div_2() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(2i8).unwrap()) }
#[inline] fn turn_div_3() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(3i8).unwrap()) }
#[inline] fn turn_div_4() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(4i8).unwrap()) }
#[inline] fn turn_div_6() -> Self { let full_turn: Self = Angle::full_turn(); full_turn.div_s(cast(6i8).unwrap()) }
2015-01-23 23:01:24 +00:00
#[inline] fn equiv(&self, other: &Self) -> bool { self.normalize() == other.normalize() }
}
2014-05-26 17:10:04 +00:00
#[inline] pub fn bisect<S: BaseFloat, A: Angle<S>>(a: A, b: A) -> A { a.bisect(b) }
2013-09-17 06:40:29 +00:00
2014-05-26 17:10:04 +00:00
impl<S: BaseFloat>
2014-01-09 00:26:50 +00:00
Rad<S> {
#[inline] pub fn zero() -> Rad<S> { zero() }
#[inline] pub fn full_turn() -> Rad<S> { Angle::full_turn() }
#[inline] pub fn turn_div_2() -> Rad<S> { Angle::turn_div_2() }
#[inline] pub fn turn_div_3() -> Rad<S> { Angle::turn_div_3() }
#[inline] pub fn turn_div_4() -> Rad<S> { Angle::turn_div_4() }
#[inline] pub fn turn_div_6() -> Rad<S> { Angle::turn_div_6() }
}
2014-05-26 17:10:04 +00:00
impl<S: BaseFloat>
2014-01-09 00:26:50 +00:00
Deg<S> {
#[inline] pub fn zero() -> Deg<S> { zero() }
#[inline] pub fn full_turn() -> Deg<S> { Angle::full_turn() }
#[inline] pub fn turn_div_2() -> Deg<S> { Angle::turn_div_2() }
#[inline] pub fn turn_div_3() -> Deg<S> { Angle::turn_div_3() }
#[inline] pub fn turn_div_4() -> Deg<S> { Angle::turn_div_4() }
#[inline] pub fn turn_div_6() -> Deg<S> { Angle::turn_div_6() }
2013-09-04 02:20:53 +00:00
}
impl<R: Into<Rad<S>>, S: BaseFloat> Add<R> for Rad<S> {
2015-01-05 01:56:01 +00:00
type Output = Rad<S>;
2015-01-05 01:56:01 +00:00
#[inline]
fn add(self, other: R) -> Rad<S> { rad(self.s + other.into().s) }
2015-01-05 01:56:01 +00:00
}
impl<R: Into<Rad<S>>, S: BaseFloat> Add<R> for Deg<S> {
2015-01-05 01:56:01 +00:00
type Output = Deg<S>;
#[inline]
fn add(self, other: R) -> Deg<S> { deg(self.s + other.into().s) }
2015-01-05 01:56:01 +00:00
}
impl<R: Into<Rad<S>>, S: BaseFloat> Sub<R> for Rad<S> {
2015-01-05 01:56:01 +00:00
type Output = Rad<S>;
#[inline]
fn sub(self, other: R) -> Rad<S> { rad(self.s - other.into().s) }
2015-01-05 01:56:01 +00:00
}
impl<R: Into<Rad<S>>, S: BaseFloat> Sub<R> for Deg<S> {
2015-01-05 01:56:01 +00:00
type Output = Deg<S>;
#[inline]
fn sub(self, other: R) -> Deg<S> { deg(self.s - other.into().s) }
2015-01-05 01:56:01 +00:00
}
impl<S: BaseFloat> Neg for Rad<S> {
type Output = Rad<S>;
#[inline]
fn neg(self) -> Rad<S> { rad(-self.s) }
}
impl<S: BaseFloat> Neg for Deg<S> {
type Output = Deg<S>;
#[inline]
fn neg(self) -> Deg<S> { deg(-self.s) }
}
2015-01-05 01:56:01 +00:00
impl<S: BaseFloat> Zero for Rad<S> {
#[inline]
fn zero() -> Rad<S> { rad(zero()) }
#[inline]
fn is_zero(&self) -> bool { *self == zero() }
}
impl<S: BaseFloat> Zero for Deg<S> {
#[inline]
fn zero() -> Deg<S> { deg(zero()) }
#[inline]
fn is_zero(&self) -> bool { *self == zero() }
}
impl<R: Into<Rad<S>>, S: BaseFloat> Mul<R> for Rad<S> {
2015-01-05 01:56:01 +00:00
type Output = Rad<S>;
2015-01-05 01:56:01 +00:00
#[inline]
fn mul(self, other: R) -> Rad<S> { rad(self.s * other.into().s) }
2015-01-05 01:56:01 +00:00
}
impl<R: Into<Rad<S>>, S: BaseFloat> Mul<R> for Deg<S> {
2015-01-05 01:56:01 +00:00
type Output = Deg<S>;
#[inline]
fn mul(self, other: R) -> Deg<S> { deg(self.s * other.into().s) }
2015-01-05 01:56:01 +00:00
}
2015-01-05 01:56:01 +00:00
impl<S: BaseFloat> One for Rad<S> {
#[inline]
fn one() -> Rad<S> { rad(one()) }
}
impl<S: BaseFloat> One for Deg<S> {
#[inline]
fn one() -> Deg<S> { deg(one()) }
}
const PI_2: f64 = f64::consts::PI * 2f64;
2014-05-26 17:10:04 +00:00
impl<S: BaseFloat>
2014-01-09 00:26:50 +00:00
Angle<S> for Rad<S> {
2015-05-06 08:10:26 +00:00
#[inline] fn from<A: Angle<S>>(theta: A) -> Rad<S> { theta.into() }
#[inline] fn full_turn() -> Rad<S> { rad(cast(PI_2).unwrap()) }
2013-09-04 02:20:53 +00:00
}
2014-05-26 17:10:04 +00:00
impl<S: BaseFloat>
2014-01-09 00:26:50 +00:00
Angle<S> for Deg<S> {
2015-05-06 08:10:26 +00:00
#[inline] fn from<A: Angle<S>>(theta: A) -> Deg<S> { theta.into() }
2015-01-09 23:16:39 +00:00
#[inline] fn full_turn() -> Deg<S> { deg(cast(360i32).unwrap()) }
2013-09-04 02:20:53 +00:00
}
#[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() }
2013-09-04 02:20:53 +00:00
2015-01-23 23:01:24 +00:00
impl<S: BaseFloat + fmt::Debug>
fmt::Debug for Rad<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2015-01-09 22:06:45 +00:00
write!(f, "{:?} rad", self.s)
}
}
2015-01-23 23:01:24 +00:00
impl<S: BaseFloat + fmt::Debug>
fmt::Debug for Deg<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2015-01-09 22:06:45 +00:00
write!(f, "{:?}°", self.s)
}
}
2013-09-04 02:20:53 +00:00
2014-05-26 17:10:04 +00:00
impl<S: BaseFloat>
2014-01-09 00:26:50 +00:00
ApproxEq<S> for Rad<S> {
2013-09-04 02:20:53 +00:00
#[inline]
2014-01-09 00:26:50 +00:00
fn approx_eq_eps(&self, other: &Rad<S>, epsilon: &S) -> bool {
self.s.approx_eq_eps(&other.s, epsilon)
2013-09-04 02:20:53 +00:00
}
}
2014-05-26 17:10:04 +00:00
impl<S: BaseFloat>
2014-01-09 00:26:50 +00:00
ApproxEq<S> for Deg<S> {
2013-09-04 02:20:53 +00:00
#[inline]
2014-01-09 00:26:50 +00:00
fn approx_eq_eps(&self, other: &Deg<S>, epsilon: &S) -> bool {
self.s.approx_eq_eps(&other.s, epsilon)
2013-09-04 02:20:53 +00:00
}
}
2015-03-15 02:53:57 +00:00
impl<S: BaseFloat + PartialOrd + SampleRange + Rand> Rand for Rad<S> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Rad<S> {
let angle: S = rng.gen_range(cast(-f64::consts::PI).unwrap(), cast(f64::consts::PI).unwrap());
rad(angle)
}
}
impl<S: BaseFloat + PartialOrd + SampleRange + Rand> Rand for Deg<S> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Deg<S> {
let angle: S = rng.gen_range(cast(-180f64).unwrap(), cast(180f64).unwrap());
deg(angle)
}
}