#pragma once #define _USE_MATH_DEFINES #include #include #include #include #include namespace cgv { namespace math { template class vec; /** A vector with zero based index.*/ template class fvec { protected: //elements of vector T v[N]; public: //@name type definitions //@{ /// typedef T value_type; /// typedef T& reference; /// typedef const T& const_reference; /// typedef std::size_t size_type; /// typedef std::ptrdiff_t difference_type; /// typedef T* pointer; /// typedef const T* const_pointer; /// typedef T* iterator; /// typedef const T* const_iterator; /// typedef std::reverse_iterator reverse_iterator; /// typedef std::reverse_iterator const_reverse_iterator; //@} //@name iterator generation //@{ /// iterator begin() { return v; } /// iterator end() { return v+N; } /// const_iterator begin() const { return v; } /// const_iterator end() const { return v+N; } /// reverse_iterator rbegin() { return reverse_iterator(end()); } /// reverse_iterator rend() { return reverse_iterator(begin()); } /// const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } /// reverse iterator pointing to the end of reverse iteration const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } //@} //@name construction and assignment //@{ ///creates a vector not initialized fvec() {} ///creates a vector initialized to constant value a fvec(const T &a) { std::fill(v, v+N, a); } /// construct and init first two coordinates to the given values fvec(const T &x, const T &y) { set(x,y); } /// construct and init first three coordinates to the given values fvec(const T &x, const T &y, const T &z) { set(x,y,z); } /// construct and init first four coordinates to the given values fvec(const T &x, const T &y, const T &z,const T &w) { set(x,y,z,w); } ///creates a column vector initialized to array a fvec(const T *a) { std::copy(a, a+N, v); } ///creates a column vector initialized to array of a different type template fvec(const S *a) { for (unsigned i=0; i fvec(const fvec& fv) { for (unsigned i=0; i lift() const { fvec h_v; (fvec&)h_v=*this; h_v(N) = 1; return h_v; } /// conversion to vector type vec to_vec() const; //@} //@name access to components //@{ ///first element T& x() { return v[0]; } ///first element of const vector const T& x() const { return v[0]; } ///second element T& y() { return v[1]; } ///second element of const vector const T& y() const { return v[1]; } ///third element T& z() { return v[2]; } ///third element of const vector const T& z() const { return v[2]; } ///fourth element T& w() { return v[3]; } ///fourth element of const vector const T& w() const { return v[3]; } ///access i'th element T& operator()(const int i) { return v[i]; } ///access i'th element of const vector const T & operator()(const int i) const { return v[i]; } ///return number of elements static unsigned size() { return N; } ///cast into array. This allows calls like glVertexv(p) instead of glVertex(p.x(),p.y(),....) operator T*() { return v; } ///cast into const array operator const T*() const { return v; } //@} //@name operators //@{ ///in place addition of a scalar s fvec& operator += (const T& s) { for (unsigned i=0;i& operator -= (const T& s) { for (unsigned i=0;i& operator *= (const T& s) { for (unsigned i=0;i& operator /= (const T& s) { for (unsigned i=0;i fvec& operator += (const fvec& _v) { for (unsigned i=0; i fvec& operator -= (const fvec& _v) { for (unsigned i=0; i fvec& operator *= (const fvec& _v) { for (unsigned i=0; i fvec& operator /= (const fvec& _v) { for (unsigned i=0; i fvec operator + (const fvec& v) const { fvec r = *this; r += v; return r; } ///componentwise addition of scalar fvec operator + (const T& s) const { fvec r = *this; r += s; return r; } ///componentwise subtraction of scalar fvec operator - (const T& s) const { fvec r = *this; r -= s; return r; } ///vector subtraction template fvec operator - (const fvec& v) const { fvec r = *this; r -= v; return r; } ///componentwise vector multiplication template fvec operator * (const fvec& v) const { fvec r = *this; r *= v; return r; } ///componentwise vector division template fvec operator / (const fvec& v) const { fvec r = *this; r /= v; return r; } ///negates the vector fvec operator-(void) const { fvec r; for (unsigned i=0; i operator * (const T& s) const { fvec r = *this; r *= s; return r; } ///divides vector by scalar s fvec operator / (const T& s) const { fvec r = *this; r /= s; return r; } ///test for equality template bool operator == (const fvec& v) const { for (unsigned i=0;i bool operator != (const fvec& v) const { for (unsigned i=0;i::is_signed) { for(unsigned i = 0; i < N;i++) v[i]=(T)std::abs((double)v[i]); } } ///ceil componentwise void ceil() { for(unsigned i = 0; i < N;i++) v[i]=(T)::ceil((double)v[i]); } ///floor componentwise void floor() { for(unsigned i = 0; i < N;i++) v[i]=(T)::floor((double)v[i]); } ///round componentwise void round() { for(unsigned i = 0; i < N;i++) v[i]=(T)::floor((double)v[i]+0.5); } ///square length of vector T sqr_length() const { T l=0; for(unsigned i = 0; i!=N;i++) l+= operator()(i)*operator()(i); return l; } /// normalize the vector using the L2-Norm and return the length double normalize() { T l = length(); T inv_l = (T)1.0/l; for(unsigned i = 0; i fvec normalize(const fvec& v) { fvec w(v); w.normalize(); return w; } ///output of a vector template std::ostream& operator<<(std::ostream& out, const fvec& v) { for (unsigned i=0;i std::istream& operator>>(std::istream& in, fvec& v) { for (unsigned i=0;i> v(i); return in; } ///returns the product of a scalar s and vector v template fvec operator * (const T& s, const fvec& v) { fvec r = v; r *= s; return r; } ///returns the dot product of vector v and w template inline T dot(const fvec& v, const fvec& w) { T r = 0; for (unsigned i=0;i inline T length(const fvec& v) { return sqrt(dot(v,v)); } ///returns the squared length of vector v template inline T sqr_length(const fvec& v) { return dot(v,v); } ///returns the cross product of vector v and w template < typename T, cgv::type::uint32_type N> inline fvec cross(const fvec& v, const fvec& w) { fvec r(3); r(0)= v(1)*w(2) - v(2)*w(1); r(1)= v(2)*w(0) - v(0)*w(2); r(2)= v(0)*w(1) - v(1)*w(0); return r; } ///returns the cross product of vector v and w template < typename T, cgv::type::uint32_type N> inline fvec hom(const fvec& v) { fvec h; for (unsigned i = 0; i T min_value(const fvec &v) { return *(std::min_element(&v(0),&v(N-1)+1)); } ///returns the index of the smallest value template < typename T, cgv::type::uint32_type N> unsigned min_index(const fvec &v) { return (unsigned) (std::min_element(&v(0),&v(N-1)+1)-&v(0)); } ///return the index of the largest entry template < typename T, cgv::type::uint32_type N> unsigned max_index(const fvec &v) { return (unsigned) (std::max_element(&v(0),&v(N-1)+1)-&v(0)); } ///return the value of the largest entry template < typename T, cgv::type::uint32_type N> T max_value(const fvec &v) { return *(std::max_element(&v(0),&v(N-1)+1)); } } } #include "vec.h" namespace cgv { namespace math { /// conversion to vector type template vec fvec::to_vec() const { vec r; r.set_extern_data(N,const_cast(v)); return r; } } } /* #include #include namespace cgv { namespace type { namespace info { template struct type_name > { static const char* get_name() { static std::string name; if (name.empty()) { name = "fvec<"; name += type_name::get_name(); name += ','; name += cgv::utils::to_string(N); name += '>'; } return name.c_str(); } }; } } } */