Move the dot method onto EuclideanVector
The Vector and EuclideanVector traits roughly line up with the concept of vector spaces and inner spaces respectively. It makes more sense to group `dot` with the other methods that depend on it.
This commit is contained in:
parent
84c2c0ff8a
commit
2cd6f402df
3 changed files with 37 additions and 15 deletions
|
@ -22,7 +22,7 @@ use matrix::{Matrix2, Matrix3};
|
||||||
use num::BaseFloat;
|
use num::BaseFloat;
|
||||||
use point::{Point, Point2, Point3};
|
use point::{Point, Point2, Point3};
|
||||||
use quaternion::Quaternion;
|
use quaternion::Quaternion;
|
||||||
use vector::{Vector, Vector2, Vector3};
|
use vector::{EuclideanVector, Vector2, Vector3};
|
||||||
|
|
||||||
/// A trait for a generic rotation. A rotation is a transformation that
|
/// A trait for a generic rotation. A rotation is a transformation that
|
||||||
/// creates a circular motion, and preserves at least one point in the space.
|
/// creates a circular motion, and preserves at least one point in the space.
|
||||||
|
|
|
@ -62,7 +62,8 @@
|
||||||
//! and [cross products](http://en.wikipedia.org/wiki/Cross_product).
|
//! and [cross products](http://en.wikipedia.org/wiki/Cross_product).
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use cgmath::{Vector, Vector2, Vector3, Vector4, dot};
|
//! use cgmath::{Vector, EuclideanVector};
|
||||||
|
//! use cgmath::{Vector2, Vector3, Vector4};
|
||||||
//!
|
//!
|
||||||
//! // All vectors implement the dot product as a method:
|
//! // All vectors implement the dot product as a method:
|
||||||
//! let a: Vector2<f64> = Vector2::new(3.0, 6.0);
|
//! let a: Vector2<f64> = Vector2::new(3.0, 6.0);
|
||||||
|
@ -70,7 +71,7 @@
|
||||||
//! assert_eq!(a.dot(b), 0.0);
|
//! assert_eq!(a.dot(b), 0.0);
|
||||||
//!
|
//!
|
||||||
//! // But there is also a top-level function:
|
//! // But there is also a top-level function:
|
||||||
//! assert_eq!(a.dot(b), dot(a, b));
|
//! assert_eq!(a.dot(b), cgmath::dot(a, b));
|
||||||
//!
|
//!
|
||||||
//! // Cross products are defined for 3-dimensional vectors:
|
//! // Cross products are defined for 3-dimensional vectors:
|
||||||
//! let e: Vector3<f64> = Vector3::unit_x();
|
//! let e: Vector3<f64> = Vector3::unit_x();
|
||||||
|
@ -121,14 +122,8 @@ pub trait Vector: Copy + Clone where
|
||||||
/// The additive identity vector. Adding this vector with another has no effect.
|
/// The additive identity vector. Adding this vector with another has no effect.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn zero() -> Self { Self::from_value(Self::Scalar::zero()) }
|
fn zero() -> Self { Self::from_value(Self::Scalar::zero()) }
|
||||||
|
|
||||||
/// Vector dot product
|
|
||||||
fn dot(self, other: Self) -> Self::Scalar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dot product of two vectors.
|
|
||||||
#[inline] pub fn dot<V: Vector>(a: V, b: V) -> V::Scalar { V::dot(a, b) }
|
|
||||||
|
|
||||||
/// A 2-dimensional vector.
|
/// A 2-dimensional vector.
|
||||||
///
|
///
|
||||||
/// This type is marked as `#[repr(C, packed)]`.
|
/// This type is marked as `#[repr(C, packed)]`.
|
||||||
|
@ -207,9 +202,10 @@ macro_rules! impl_vector {
|
||||||
impl<S: BaseNum> Vector for $VectorN<S> {
|
impl<S: BaseNum> Vector for $VectorN<S> {
|
||||||
type Scalar = S;
|
type Scalar = S;
|
||||||
|
|
||||||
#[inline] fn from_value(scalar: S) -> $VectorN<S> { $VectorN { $($field: scalar),+ } }
|
#[inline]
|
||||||
|
fn from_value(scalar: S) -> $VectorN<S> {
|
||||||
#[inline] fn dot(self, other: $VectorN<S>) -> S { $VectorN::mul_element_wise(self, other).sum() }
|
$VectorN { $($field: scalar),+ }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: Neg<Output = S>> Neg for $VectorN<S> {
|
impl<S: Neg<Output = S>> Neg for $VectorN<S> {
|
||||||
|
@ -468,6 +464,9 @@ pub trait EuclideanVector: Vector + Sized where
|
||||||
<Self as Vector>::Scalar: BaseFloat,
|
<Self as Vector>::Scalar: BaseFloat,
|
||||||
Self: ApproxEq<Epsilon = <Self as Vector>::Scalar>,
|
Self: ApproxEq<Epsilon = <Self as Vector>::Scalar>,
|
||||||
{
|
{
|
||||||
|
/// Vector dot (or inner) product.
|
||||||
|
fn dot(self, other: Self) -> Self::Scalar;
|
||||||
|
|
||||||
/// Returns `true` if the vector is perpendicular (at right angles) to the
|
/// Returns `true` if the vector is perpendicular (at right angles) to the
|
||||||
/// other vector.
|
/// other vector.
|
||||||
fn is_perpendicular(self, other: Self) -> bool {
|
fn is_perpendicular(self, other: Self) -> bool {
|
||||||
|
@ -519,7 +518,20 @@ pub trait EuclideanVector: Vector + Sized where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dot product of two vectors.
|
||||||
|
#[inline]
|
||||||
|
pub fn dot<V: EuclideanVector>(a: V, b: V) -> V::Scalar where
|
||||||
|
V::Scalar: BaseFloat,
|
||||||
|
{
|
||||||
|
V::dot(a, b)
|
||||||
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> EuclideanVector for Vector2<S> {
|
impl<S: BaseFloat> EuclideanVector for Vector2<S> {
|
||||||
|
#[inline]
|
||||||
|
fn dot(self, other: Vector2<S>) -> S {
|
||||||
|
Vector2::mul_element_wise(self, other).sum()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn angle(self, other: Vector2<S>) -> Rad<S> {
|
fn angle(self, other: Vector2<S>) -> Rad<S> {
|
||||||
Rad::atan2(Self::perp_dot(self, other), Self::dot(self, other))
|
Rad::atan2(Self::perp_dot(self, other), Self::dot(self, other))
|
||||||
|
@ -527,6 +539,11 @@ impl<S: BaseFloat> EuclideanVector for Vector2<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> EuclideanVector for Vector3<S> {
|
impl<S: BaseFloat> EuclideanVector for Vector3<S> {
|
||||||
|
#[inline]
|
||||||
|
fn dot(self, other: Vector3<S>) -> S {
|
||||||
|
Vector3::mul_element_wise(self, other).sum()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn angle(self, other: Vector3<S>) -> Rad<S> {
|
fn angle(self, other: Vector3<S>) -> Rad<S> {
|
||||||
Rad::atan2(self.cross(other).magnitude(), Self::dot(self, other))
|
Rad::atan2(self.cross(other).magnitude(), Self::dot(self, other))
|
||||||
|
@ -534,6 +551,11 @@ impl<S: BaseFloat> EuclideanVector for Vector3<S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat> EuclideanVector for Vector4<S> {
|
impl<S: BaseFloat> EuclideanVector for Vector4<S> {
|
||||||
|
#[inline]
|
||||||
|
fn dot(self, other: Vector4<S>) -> S {
|
||||||
|
Vector4::mul_element_wise(self, other).sum()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn angle(self, other: Vector4<S>) -> Rad<S> {
|
fn angle(self, other: Vector4<S>) -> Rad<S> {
|
||||||
Rad::acos(Self::dot(self, other) / (self.magnitude() * other.magnitude()))
|
Rad::acos(Self::dot(self, other) / (self.magnitude() * other.magnitude()))
|
||||||
|
|
|
@ -122,9 +122,9 @@ fn test_rem() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dot() {
|
fn test_dot() {
|
||||||
assert_eq!(Vector2::new(1isize, 2isize).dot(Vector2::new(3isize, 4isize)), 11isize);
|
assert_eq!(Vector2::new(1.0, 2.0).dot(Vector2::new(3.0, 4.0)), 11.0);
|
||||||
assert_eq!(Vector3::new(1isize, 2isize, 3isize).dot(Vector3::new(4isize, 5isize, 6isize)), 32isize);
|
assert_eq!(Vector3::new(1.0, 2.0, 3.0).dot(Vector3::new(4.0, 5.0, 6.0)), 32.0);
|
||||||
assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).dot(Vector4::new(5isize, 6isize, 7isize, 8isize)), 70isize);
|
assert_eq!(Vector4::new(1.0, 2.0, 3.0, 4.0).dot(Vector4::new(5.0, 6.0, 7.0, 8.0)), 70.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue