diff options
Diffstat (limited to 'source/blender/freestyle/intern/geometry/VecMat.h')
-rwxr-xr-x | source/blender/freestyle/intern/geometry/VecMat.h | 899 |
1 files changed, 899 insertions, 0 deletions
diff --git a/source/blender/freestyle/intern/geometry/VecMat.h b/source/blender/freestyle/intern/geometry/VecMat.h new file mode 100755 index 00000000000..9bbec3b1349 --- /dev/null +++ b/source/blender/freestyle/intern/geometry/VecMat.h @@ -0,0 +1,899 @@ +// +// Filename : VecMat.h +// Author(s) : Sylvain Paris +// Emmanuel Turquin +// Stephane Grabli +// Purpose : Vectors and Matrices definition and manipulation +// Date of creation : 12/06/2003 +// +/////////////////////////////////////////////////////////////////////////////// + + +// +// Copyright (C) : Please refer to the COPYRIGHT file distributed +// with this source distribution. +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef VECMAT_H +# define VECMAT_H + +# include <math.h> +# include <vector> +# include <iostream> + +namespace VecMat { + + namespace Internal { + + template <bool B> + struct is_false {}; + + template <> + struct is_false<false> { + static inline void ensure() {} + }; + + } // end of namespace Internal + + // + // Vector class + // - T: value type + // - N: dimension + // + ///////////////////////////////////////////////////////////////////////////// + + template <class T, unsigned N> + class Vec + { + public: + + typedef T value_type; + + // constructors + + inline Vec() { + for (unsigned i = 0; i < N; i++) + this->_coord[i] = 0; + } + + ~Vec() { + Internal::is_false<(N == 0)>::ensure(); + } + + template <class U> + explicit inline Vec(const U tab[N]) { + for (unsigned i = 0; i < N; i++) + this->_coord[i] = (T)tab[i]; + } + + template <class U> + explicit inline Vec(const std::vector<U>& tab) { + for (unsigned i = 0; i < N; i++) + this->_coord[i] = (T)tab[i]; + } + + template <class U> + explicit inline Vec(const Vec<U, N>& v) { + for (unsigned i = 0; i < N; i++) + this->_coord[i] = (T)v[i]; + } + + // accessors + + inline value_type operator[](const unsigned i) const { + return this->_coord[i]; + } + + inline value_type& operator[](const unsigned i) { + return this->_coord[i]; + } + + static inline unsigned dim() { + return N; + } + + // various useful methods + + inline value_type norm() const { + return (T)sqrt((float)squareNorm()); + } + + inline value_type squareNorm() const { + return (*this) * (*this); + } + + inline Vec<T, N>& normalize() { + value_type n = norm(); + for (unsigned i = 0; i < N; i++) + this->_coord[i] /= n; + return *this; + } + + inline Vec<T, N>& normalizeSafe() { + value_type n = norm(); + if (n) + for (unsigned i=0; i < N; i++) + this->_coord[i] /= n; + return *this; + } + + // classical operators + inline Vec<T, N> operator+(const Vec<T, N>& v) const{ + Vec<T, N> res(v); + res += *this; + return res; + } + + inline Vec<T, N> operator-(const Vec<T,N>& v) const{ + Vec<T, N> res(*this); + res -= v; + return res; + } + + inline Vec<T, N> operator*(const typename Vec<T,N>::value_type r) const{ + Vec<T, N> res(*this); + res *= r; + return res; + } + + inline Vec<T, N> operator/(const typename Vec<T,N>::value_type r) const{ + Vec<T, N> res(*this); + if (r) + res /= r; + return res; + } + + // dot product + inline value_type operator*(const Vec<T, N>& v) const{ + value_type sum = 0; + for (unsigned i = 0; i < N; i++) + sum += (*this)[i] * v[i]; + return sum; + } + + template <class U> + inline Vec<T, N>& operator=(const Vec<U, N>& v) { + if (this != &v) + for (unsigned i = 0; i < N; i++) + this->_coord[i] = (T)v[i]; + return *this; + } + + template <class U> + inline Vec<T, N>& operator+=(const Vec<U, N>& v) { + for (unsigned i = 0 ; i < N; i++) + this->_coord[i] += (T)v[i]; + return *this; + } + + template <class U> + inline Vec<T, N>& operator-=(const Vec<U, N>& v) { + for (unsigned i = 0 ; i < N; i++) + this->_coord[i] -= (T)v[i]; + return *this; + } + + template <class U> + inline Vec<T, N>& operator*=(const U r) { + for (unsigned i = 0 ; i < N; i++) + this->_coord[i] *= r; + return *this; + } + + template <class U> + inline Vec<T, N>& operator/=(const U r) { + if (r) + for (unsigned i = 0 ; i < N; i++) + this->_coord[i] /= r; + return *this; + } + + + inline bool operator==(const Vec<T, N>& v) const { + for(unsigned i = 0; i < N; i++) + if (this->_coord[i] != v[i]) + return false; + return true; + } + + inline bool operator!=(const Vec<T, N>& v) const { + for(unsigned i = 0; i < N; i++) + if (this->_coord[i] != v[i]) + return true; + return false; + } + + inline bool operator<(const Vec<T, N>& v) const { + for (unsigned i = 0; i<N; i++) { + if (this->_coord[i] < v[i]) + return true; + if (this->_coord[i] > v[i]) + return false; + if (this->_coord[i] == v[i]) + continue; + } + return false; + } + + inline bool operator>(const Vec<T, N>& v) const { + for (unsigned i=0; i<N; i++) { + if(this->_coord[i] > v[i]) + return true; + if(this->_coord[i] < v[i]) + return false; + if(this->_coord[i] == v[i]) + continue; + } + return false; + } + + protected: + + value_type _coord[N]; + enum { + _dim = N, + }; + }; + + + // + // Vec2 class (2D Vector) + // - T: value type + // + ///////////////////////////////////////////////////////////////////////////// + + template <class T> + class Vec2 : public Vec<T, 2> + { + public: + + typedef typename Vec<T, 2>::value_type value_type; + + inline Vec2() : Vec<T, 2>() {} + + template <class U> + explicit inline Vec2(const U tab[2]) : Vec<T, 2>(tab) {} + + template <class U> + explicit inline Vec2(const std::vector<U>& tab) : Vec<T, 2>(tab) {} + + template <class U> + inline Vec2(const Vec<U, 2>& v) : Vec<T, 2>(v) {} + + inline Vec2(const value_type x, + const value_type y = 0) : Vec<T, 2>() { + this->_coord[0] = (T)x; + this->_coord[1] = (T)y; + } + + inline value_type x() const { + return this->_coord[0]; + } + + inline value_type& x() { + return this->_coord[0]; + } + + inline value_type y() const { + return this->_coord[1]; + } + + inline value_type& y() { + return this->_coord[1]; + } + + inline void setX(const value_type v) { + this->_coord[0] = v; + } + + inline void setY(const value_type v) { + this->_coord[1] = v; + } + + // FIXME: hack swig -- no choice + inline Vec2<T> operator+(const Vec2<T>& v) const{ + Vec2<T> res(v); + res += *this; + return res; + } + + inline Vec2<T> operator-(const Vec2<T>& v) const{ + Vec2<T> res(*this); + res -= v; + return res; + } + + inline Vec2<T> operator*(const value_type r) const{ + Vec2<T> res(*this); + res *= r; + return res; + } + + inline Vec2<T> operator/(const value_type r) const{ + Vec2<T> res(*this); + if (r) + res /= r; + return res; + } + + // dot product + inline value_type operator*(const Vec2<T>& v) const{ + value_type sum = 0; + for (unsigned i = 0; i < 2; i++) + sum += (*this)[i] * v[i]; + return sum; + } + }; + + + // + // HVec3 class (3D Vector in homogeneous coordinates) + // - T: value type + // + ///////////////////////////////////////////////////////////////////////////// + + template <class T> + class HVec3 : public Vec<T, 4> + { + public: + + typedef typename Vec<T, 4>::value_type value_type; + + inline HVec3() : Vec<T, 4>() {} + + template <class U> + explicit inline HVec3(const U tab[4]) : Vec<T, 4>(tab) {} + + template <class U> + explicit inline HVec3(const std::vector<U>& tab) : Vec<T, 4>(tab) {} + + template<class U> + inline HVec3(const Vec<U, 4>& v) : Vec<T, 4>(v) {} + + inline HVec3(const value_type sx, + const value_type sy = 0, + const value_type sz = 0, + const value_type s = 1) { + this->_coord[0] = sx; + this->_coord[1] = sy; + this->_coord[2] = sz; + this->_coord[3] = s; + } + + template <class U> + inline HVec3(const Vec<U, 3>& sv, + const U s = 1) { + this->_coord[0] = (T)sv[0]; + this->_coord[1] = (T)sv[1]; + this->_coord[2] = (T)sv[2]; + this->_coord[3] = (T)s; + } + + inline value_type sx() const { + return this->_coord[0]; + } + + inline value_type& sx() { + return this->_coord[0]; + } + + inline value_type sy() const { + return this->_coord[1]; + } + + inline value_type& sy() { + return this->_coord[1]; + } + + inline value_type sz() const { + return this->_coord[2]; + } + + inline value_type& sz() { + return this->_coord[2]; + } + + inline value_type s() const { + return this->_coord[3]; + } + + inline value_type& s() { + return this->_coord[3]; + } + + // Acces to non-homogeneous coordinates in 3D + + inline value_type x() const { + return this->_coord[0] / this->_coord[3]; + } + + inline value_type y() const { + return this->_coord[1] / this->_coord[3]; + } + + inline value_type z() const { + return this->_coord[2] / this->_coord[3]; + } + }; + + + // + // Vec3 class (3D Vec) + // - T: value type + // + ///////////////////////////////////////////////////////////////////////////// + + template <class T> + class Vec3 : public Vec<T, 3> + { + public: + + typedef typename Vec<T, 3>::value_type value_type; + + inline Vec3() : Vec<T, 3>() {} + + template <class U> + explicit inline Vec3(const U tab[3]) : Vec<T, 3>(tab) {} + + template <class U> + explicit inline Vec3(const std::vector<U>& tab) : Vec<T, 3>(tab) {} + + template<class U> + inline Vec3(const Vec<U, 3>& v) : Vec<T, 3>(v) {} + + template<class U> + inline Vec3(const HVec3<U>& v) { + this->_coord[0] = (T)v.x(); + this->_coord[1] = (T)v.y(); + this->_coord[2] = (T)v.z(); + } + + inline Vec3(const value_type x, + const value_type y = 0, + const value_type z = 0) : Vec<T, 3>() { + this->_coord[0] = x; + this->_coord[1] = y; + this->_coord[2] = z; + } + + inline value_type x() const { + return this->_coord[0]; + } + + inline value_type& x() { + return this->_coord[0]; + } + + inline value_type y() const { + return this->_coord[1]; + } + + inline value_type& y() { + return this->_coord[1]; + } + + inline value_type z() const { + return this->_coord[2]; + } + + inline value_type& z() { + return this->_coord[2]; + } + + inline void setX(const value_type v) { + this->_coord[0] = v; + } + + inline void setY(const value_type v) { + this->_coord[1] = v; + } + + inline void setZ(const value_type v) { + this->_coord[2] = v; + } + + // classical operators + // FIXME: hack swig -- no choice + inline Vec3<T> operator+(const Vec3<T>& v) const{ + Vec3<T> res(v); + res += *this; + return res; + } + + inline Vec3<T> operator-(const Vec3<T>& v) const{ + Vec3<T> res(*this); + res -= v; + return res; + } + + inline Vec3<T> operator*(const value_type r) const{ + Vec3<T> res(*this); + res *= r; + return res; + } + + inline Vec3<T> operator/(const value_type r) const{ + Vec3<T> res(*this); + if (r) + res /= r; + return res; + } + + // dot product + inline value_type operator*(const Vec3<T>& v) const{ + value_type sum = 0; + for (unsigned i = 0; i < 3; i++) + sum += (*this)[i] * v[i]; + return sum; + } + + // cross product for 3D Vectors + // FIXME: hack swig -- no choice + inline Vec3<T> operator^(const Vec3<T>& v) const{ + Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1], + (*this)[2] * v[0] - (*this)[0] * v[2], + (*this)[0] * v[1] - (*this)[1] * v[0]); + return res; + } + + // cross product for 3D Vectors + template <typename U> + inline Vec3<T> operator^(const Vec<U, 3>& v) const{ + Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1], + (*this)[2] * v[0] - (*this)[0] * v[2], + (*this)[0] * v[1] - (*this)[1] * v[0]); + return res; + } + }; + + + // + // Matrix class + // - T: value type + // - M: rows + // - N: cols + // + ///////////////////////////////////////////////////////////////////////////// + + // Dirty, but icc under Windows needs this +# define _SIZE (M * N) + + template <class T, unsigned M, unsigned N> + class Matrix + { + public: + + typedef T value_type; + + inline Matrix() { + for (unsigned i = 0; i < _SIZE; i++) + this->_coord[i] = 0; + } + + ~Matrix() { + Internal::is_false<(M == 0)>::ensure(); + Internal::is_false<(N == 0)>::ensure(); + } + + template <class U> + explicit inline Matrix(const U tab[_SIZE]) { + for (unsigned i = 0; i < _SIZE; i++) + this->_coord[i] = tab[i]; + } + + template <class U> + explicit inline Matrix(const std::vector<U>& tab) { + for (unsigned i = 0; i < _SIZE; i++) + this->_coord[i] = tab[i]; + } + + template <class U> + inline Matrix(const Matrix<U, M, N>& m) { + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] = (T)m(i, j); + } + + inline value_type operator()(const unsigned i, const unsigned j) const { + return this->_coord[i * N + j]; + } + + inline value_type& operator()(const unsigned i, const unsigned j) { + return this->_coord[i * N + j]; + } + + static inline unsigned rows() { + return M; + } + + static inline unsigned cols() { + return N; + } + + inline Matrix<T, M, N>& transpose() const { + Matrix<T, N, M> res; + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + res(j,i) = this->_coord[i * N + j]; + return res; + } + + template <class U> + inline Matrix<T, M, N>& operator=(const Matrix<U, M, N>& m) { + if (this != &m) + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] = (T)m(i, j); + return *this; + } + + template <class U> + inline Matrix<T, M, N>& operator+=(const Matrix<U, M, N>& m) { + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] += (T)m(i, j); + return *this; + } + + template <class U> + inline Matrix<T, M, N>& operator-=(const Matrix<U, M, N>& m) { + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] -= (T)m(i, j); + return *this; + } + + template <class U> + inline Matrix<T, M, N>& operator*=(const U lambda) { + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] *= lambda; + return *this; + } + + template <class U> + inline Matrix<T, M, N>& operator/=(const U lambda) { + if (lambda) + for (unsigned i = 0; i < M; i++) + for (unsigned j = 0; j < N; j++) + this->_coord[i * N + j] /= lambda; + return *this; + } + + protected: + + value_type _coord[_SIZE]; + }; + + + // + // SquareMatrix class + // - T: value type + // - N: rows & cols + // + ///////////////////////////////////////////////////////////////////////////// + + // Dirty, but icc under Windows needs this +# define __SIZE (N * N) + + template <class T, unsigned N> + class SquareMatrix : public Matrix<T, N, N> + { + public: + + typedef T value_type; + + inline SquareMatrix() : Matrix<T, N, N>() {} + + template <class U> + explicit inline SquareMatrix(const U tab[__SIZE]) : Matrix<T, N, N>(tab) {} + + template <class U> + explicit inline SquareMatrix(const std::vector<U>& tab) : Matrix<T, N, N>(tab) {} + + template <class U> + inline SquareMatrix(const Matrix<U, N, N>& m) : Matrix<T, N, N>(m) {} + + static inline SquareMatrix<T, N> identity() { + SquareMatrix<T, N> res; + for (unsigned i = 0; i < N; i++) + res(i, i) = 1; + return res; + } + }; + + + // + // Vector external functions + // + ///////////////////////////////////////////////////////////////////////////// + + // template <class T, unsigned N> + // inline Vec<T, N> operator+(const Vec<T, N>& v1, + // const Vec<T, N>& v2) { + // Vec<T, N> res(v1); + // res += v2; + // return res; + // } + // + // template <class T, unsigned N> + // inline Vec<T, N> operator-(const Vec<T, N>& v1, + // const Vec<T, N>& v2) { + // Vec<T, N> res(v1); + // res -= v2; + // return res; + // } + // template <class T, unsigned N> + // inline Vec<T, N> operator*(const Vec<T, N>& v, + // const typename Vec<T, N>::value_type r) { + // Vec<T, N> res(v); + // res *= r; + // return res; + // } + + template <class T, unsigned N> + inline Vec<T, N> operator*(const typename Vec<T, N>::value_type r, + const Vec<T, N>& v) { + Vec<T, N> res(v); + res *= r; + return res; + } + // + // template <class T, unsigned N> + // inline Vec<T, N> operator/(const Vec<T, N>& v, + // const typename Vec<T, N>::value_type r) { + // Vec<T, N> res(v); + // if (r) + // res /= r; + // return res; + // } + // + // dot product + // template <class T, unsigned N> + // inline typename Vec<T, N>::value_type operator*(const Vec<T, N>& v1, + // const Vec<T, N>& v2) { + // typename Vec<T, N>::value_type sum = 0; + // for (unsigned i = 0; i < N; i++) + // sum += v1[i] * v2[i]; + // return sum; + // } + // + // // cross product for 3D Vectors + // template <typename T> + // inline Vec3<T> operator^(const Vec<T, 3>& v1, + // const Vec<T, 3>& v2) { + // Vec3<T> res(v1[1] * v2[2] - v1[2] * v2[1], + // v1[2] * v2[0] - v1[0] * v2[2], + // v1[0] * v2[1] - v1[1] * v2[0]); + // return res; + // } + + // stream operator + template <class T, unsigned N> + inline std::ostream& operator<<(std::ostream& s, + const Vec<T, N>& v) { + unsigned i; + s << "["; + for (i = 0; i < N - 1; i++) + s << v[i] << ", "; + s << v[i] << "]"; + return s; + } + + + // + // Matrix external functions + // + ///////////////////////////////////////////////////////////////////////////// + + template <class T, unsigned M, unsigned N> + inline Matrix<T, M, N> + operator+(const Matrix<T, M, N>& m1, + const Matrix<T, M, N>& m2) { + Matrix<T, M, N> res(m1); + res += m2; + return res; + } + + template <class T, unsigned M, unsigned N> + inline Matrix<T, M, N> + operator-(const Matrix<T, M, N>& m1, + const Matrix<T, M, N>& m2) { + Matrix<T, M, N> res(m1); + res -= m2; + return res; + } + + template <class T, unsigned M, unsigned N> + inline Matrix<T, M, N> + operator*(const Matrix<T, M, N>& m1, + const typename Matrix<T, M, N>::value_type lambda) { + Matrix<T, M, N> res(m1); + res *= lambda; + return res; + } + + template <class T, unsigned M, unsigned N> + inline Matrix<T, M, N> + operator*(const typename Matrix<T, M, N>::value_type lambda, + const Matrix<T, M, N>& m1) { + Matrix<T, M, N> res(m1); + res *= lambda; + return res; + } + + template <class T, unsigned M, unsigned N> + inline Matrix<T, M, N> + operator/(const Matrix<T, M, N>& m1, + const typename Matrix<T, M, N>::value_type lambda) { + Matrix<T, M, N> res(m1); + res /= lambda; + return res; + } + + template <class T, unsigned M, unsigned N, unsigned P> + inline Matrix<T, M, P> + operator*(const Matrix<T, M, N>& m1, + const Matrix<T, N, P>& m2) { + unsigned i, j, k; + Matrix<T, M, P> res; + typename Matrix<T, N, P>::value_type scale; + + for (j = 0; j < P; j++) { + for (k = 0; k < N; k++) { + scale = m2(k, j); + for (i = 0; i < N; i++) + res(i, j) += m1(i, k) * scale; + } + } + return res; + } + + template <class T, unsigned M, unsigned N> + inline Vec<T, M> + operator*(const Matrix<T, M, N>& m, + const Vec<T, N>& v) { + + Vec<T, M> res; + typename Matrix<T, M, N>::value_type scale; + + for (unsigned j = 0; j < M; j++) { + scale = v[j]; + for (unsigned i = 0; i < N; i++) + res[i] += m(i, j) * scale; + } + return res; + } + + // stream operator + template <class T, unsigned M, unsigned N> + inline std::ostream& operator<<(std::ostream& s, + const Matrix<T, M, N>& m) { + unsigned i, j; + for (i = 0; i < M; i++) { + s << "["; + for (j = 0; j < N - 1; j++) + s << m(i, j) << ", "; + s << m(i, j) << "]" << std::endl; + } + return s; + } + +} // end of namespace VecMat + +#endif // VECMAT_H |