You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
219 lines
6.8 KiB
219 lines
6.8 KiB
//============================================================================
|
|
//
|
|
// 3-dim real vector class
|
|
// $Id$
|
|
// Copyright (C) 2004 Georg Drenkhahn
|
|
//
|
|
// This file is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU General Public License version 2 as published by the
|
|
// Free Software Foundation.
|
|
//
|
|
//============================================================================
|
|
|
|
#ifndef VEC3_H
|
|
#define VEC3_H
|
|
|
|
#include <valarray>
|
|
|
|
/** @brief 3-dimensional real vector
|
|
*
|
|
* Implements regular 3 dimensional (space) vectors including the common inner
|
|
* scalar product (2 norm) and the cross product. @a T may be any integer or
|
|
* float data type which is an acceptable template argument of std::valarray. */
|
|
template<typename T>
|
|
class vec3 : public std::valarray<T>
|
|
{
|
|
public:
|
|
/** Default constructor */
|
|
vec3();
|
|
/** Constructor with initial element values */
|
|
vec3(const T&, const T&, const T&);
|
|
/** Copy constructor */
|
|
vec3(const std::valarray<T>&);
|
|
/** Copy constructor */
|
|
vec3(const std::slice_array<T>&);
|
|
|
|
/** Normalize the vector to have a norm of 1. @return Normalized vector if
|
|
* length is non-zero and otherwise the zero vector. */
|
|
vec3& normalize();
|
|
|
|
/** Rotate the vector (*this) in positive mathematical direction around the
|
|
* direction given by @a r. The norm of @a r specifies the rotation angle in
|
|
* radians.
|
|
* @param r Rotation vector.
|
|
* @return Rotated vector. */
|
|
vec3& rotate(const vec3& r);
|
|
|
|
/*--- static funcions ---*/
|
|
|
|
/** @param a first vector
|
|
* @param b second vector
|
|
* @return Cosine of the angle between @a a and @a b. If norm(@a a)==0 or
|
|
* norm(@a b)==0 the global variable errno is set to EDOM and NAN (or
|
|
* std::numeric_limits<T>::quiet_NaN()) is returned. */
|
|
static T cos_angle(const vec3& a, const vec3& b);
|
|
|
|
/** @brief Returns the angle between vectors @c a and @a b but with respect
|
|
* to a preferred rotation direction @a c.
|
|
*
|
|
* @param a First vector for angle. Must be | @a a |>0 otherwises NAN is
|
|
* returned.
|
|
* @param b Second vector for angle. Must be | @a b |>0 otherwises NAN is
|
|
* returned.
|
|
* @param c Indicates the rotation direction. @a c can be any vector which is
|
|
* not part of the plane spanned by @a a and @a b. If | @a c | = 0 the
|
|
* smalest possible angle angle is returned.
|
|
* @return Angle in radians between 0 and 2*Pi or NAN if | @a a |=0 or | @a b
|
|
* |=0.
|
|
*
|
|
* For @a a not parallel to @a b and @a a not antiparallel to @a b the 2
|
|
* vectors @a a,@a b span a unique plane in the 3-dimensional space. Let @b
|
|
* n<sub>1</sub> and @b n<sub>2</sub> be the two possible normal vectors for
|
|
* this plane with |@b n<sub>i</sub> |=1, i={1,2} and @b n<sub>1</sub> = -@b
|
|
* n<sub>2</sub> .
|
|
*
|
|
* Let further @a a and @a b enclose an angle alpha in [0,Pi], then there is
|
|
* one i in {1,2} so that (alpha*@b n<sub>i</sub> x @a a) * @a b = 0. This
|
|
* means @a a rotated by the rotation vector alpha*@b n<sub>i</sub> is
|
|
* parallel to @a b. One could also rotate @a a by (2*Pi-alpha)*(-@b
|
|
* n<sub>i</sub>) to acomplish the same transformation with
|
|
* ((2*Pi-alpha)*(-@b n<sub>i</sub>) x @a a) * @a b = 0
|
|
*
|
|
* The vector @a c defines the direction of the normal vector to take as
|
|
* reference. If @a c * @b n<sub>i</sub> > 0 alpha is returned and otherwise
|
|
* 2*Pi-alpha. If @a a parallel to @a b or @a a parallel to @a b the choice
|
|
* of @a c does not matter. */
|
|
static T angle(const vec3& a, const vec3& b, const vec3& c);
|
|
|
|
/*--- static inline funcions ---*/
|
|
|
|
/** Norm of argument vector.
|
|
* @param a vector.
|
|
* @return | @a a | */
|
|
static T norm(const vec3& a);
|
|
|
|
/** Angle between @a a and @a b.
|
|
* @param a fist vector. Must be | @a a | > 0 otherwises NAN is returned.
|
|
* @param b second vector. Must be | @a b | > 0 otherwises NAN is returned.
|
|
* @return Angle in radians between 0 and Pi or NAN if | @a a | = 0 or | @a b
|
|
* | = 0. */
|
|
static T angle(const vec3& a, const vec3& b);
|
|
|
|
/** Cross product of @a a and @a b.
|
|
* @param a fist vector.
|
|
* @param b second vector.
|
|
* @return Cross product of argument vectors @a a x @a b. */
|
|
static vec3 crossprod(const vec3& a, const vec3& b);
|
|
|
|
/** Normalized version of argument vector.
|
|
* @param a vector.
|
|
* @return @a a / | @a a | for | @a a | > 0 and otherwise the zero vector
|
|
* (=@a a). In the latter case the global variable errno is set to EDOM. */
|
|
static vec3 normalized(vec3 a);
|
|
};
|
|
|
|
/*--- inline member functions ---*/
|
|
|
|
template<typename T>
|
|
inline vec3<T>::vec3()
|
|
: std::valarray<T>(3)
|
|
{}
|
|
|
|
template<typename T>
|
|
inline vec3<T>::vec3(const T& a, const T& b, const T& c)
|
|
: std::valarray<T>(3)
|
|
{
|
|
(*this)[0] = a;
|
|
(*this)[1] = b;
|
|
(*this)[2] = c;
|
|
}
|
|
|
|
template<typename T>
|
|
inline vec3<T>::vec3(const std::valarray<T>& a)
|
|
: std::valarray<T>(a)
|
|
{
|
|
}
|
|
|
|
template<typename T>
|
|
inline vec3<T>::vec3(const std::slice_array<T>& a)
|
|
: std::valarray<T>(a)
|
|
{
|
|
}
|
|
|
|
/*--- inline non-member operators ---*/
|
|
|
|
/** @param a first vector summand
|
|
* @param b second vector summand
|
|
* @return Sum vector of vectors @a a and @a b. */
|
|
template<typename T>
|
|
inline vec3<T> operator+(vec3<T> a, const vec3<T>& b)
|
|
{
|
|
std::valarray<T> &a_ = a;
|
|
const std::valarray<T> &b_ = b;
|
|
a_ += b_; /* valarray<T>::operator+=(const valarray<T>&) */
|
|
return a;
|
|
}
|
|
|
|
/** @param a first vector multiplicant
|
|
* @param b second vector multiplicant
|
|
* @return Scalar product of vectors @a a and @a b. */
|
|
template<typename T>
|
|
inline T operator*(vec3<T> a, const vec3<T>& b)
|
|
{
|
|
std::valarray<T> &a_ = a;
|
|
const std::valarray<T> &b_ = b;
|
|
a_ *= b_; /* valarray<T>::operator*=(const valarray<T>&) */
|
|
return a.sum();
|
|
}
|
|
|
|
/** @param a scalar multiplicant
|
|
* @param b vector operand
|
|
* @return Product vector of scalar @a a and vector @a b. */
|
|
template<typename T>
|
|
inline vec3<T> operator*(const T& a, vec3<T> b)
|
|
{
|
|
b *= a; /* valarray<T>::operator*=(const T&) */
|
|
return b;
|
|
}
|
|
|
|
/** @param a vector operand
|
|
* @param b scalar multiplicant
|
|
* @return Product vector of scalar @a b and vector @a a. */
|
|
template<typename T>
|
|
inline vec3<T> operator*(vec3<T> a, const T& b)
|
|
{
|
|
return b*a; /* vec3<T>::operator*(const T&, vec3<T>) */
|
|
}
|
|
|
|
/*--- static inline funcions ---*/
|
|
|
|
template<typename T>
|
|
inline T vec3<T>::norm(const vec3<T>& a)
|
|
{
|
|
return sqrt(a*a);
|
|
}
|
|
|
|
template<typename T>
|
|
inline T vec3<T>::angle(const vec3<T>& a, const vec3<T>& b)
|
|
{
|
|
// returns NAN if cos_angle() returns NAN (TODO: test this case)
|
|
return acos(cos_angle(a,b));
|
|
}
|
|
|
|
template<typename T>
|
|
inline vec3<T> vec3<T>::crossprod(const vec3<T>& a, const vec3<T>& b)
|
|
{
|
|
return vec3<T>(
|
|
a[1]*b[2] - a[2]*b[1],
|
|
a[2]*b[0] - a[0]*b[2],
|
|
a[0]*b[1] - a[1]*b[0]);
|
|
}
|
|
|
|
template<typename T>
|
|
inline vec3<T> vec3<T>::normalized(vec3<T> a)
|
|
{
|
|
return a.normalize();
|
|
}
|
|
|
|
#endif
|