summaryrefslogtreecommitdiffstats
path: root/kscreensaver/kdesavers/vec3.h
diff options
context:
space:
mode:
Diffstat (limited to 'kscreensaver/kdesavers/vec3.h')
-rw-r--r--kscreensaver/kdesavers/vec3.h214
1 files changed, 214 insertions, 0 deletions
diff --git a/kscreensaver/kdesavers/vec3.h b/kscreensaver/kdesavers/vec3.h
new file mode 100644
index 00000000..62aeb8ed
--- /dev/null
+++ b/kscreensaver/kdesavers/vec3.h
@@ -0,0 +1,214 @@
+//============================================================================
+//
+// 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)
+{
+ 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)
+{
+ a *= b; /* valarray<T>::operator*=(const 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