// // This source code is property of the Computer Graphics and Visualization // chair of the TU Dresden. Do not distribute in modified or unmodified form! // Copyright (C) 2015 CGV TU Dresden - All Rights Reserved // /************************************************************************* Template class for vectors. This template class defines small vectors of a defined dimension with an arbitrary data type. Basic operations such as addition of vectors and multiplication of a vector and a scalar are supported via operator overloading. Also more advanced functions such as normalization and iterating through the elements are implemented. At the end of this file the data types "point2d", "point3d" and "point4d" are specified as a tinyvec of doubles with the according dimension. *************************************************************************/ #pragma once #include #include #pragma warning( disable : 4996 ) template class tiny_vec { T _data[N]; public: 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; tiny_vec(); template tiny_vec(InputIterator first,InputIterator last) { std::copy(first,last,begin()); } tiny_vec(size_t n, const T* marray); ~tiny_vec(); tiny_vec(const T&x,const T&y); tiny_vec(const T&x,const T&y, const T&z); tiny_vec(const T&x, const T&y, const T&z,const T& w); int size() const; operator T*(); operator const T*() const; void set(const T& x); void set(const T& x, const T& y); void set(const T& x, const T& y,const T& z); void set(const T& x, const T& y,const T& z, const T& w); tiny_vec& operator=(const T &s); tiny_vec& operator=(int s); tiny_vec& operator=(const tiny_vec & v); void fill(const T& s); void zeros(size_t m); void zeros(); void ones(); void ones(size_t m); iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; reverse_iterator rbegin(); reverse_iterator rend(); const_reverse_iterator rbegin() const; const_reverse_iterator rend() const; bool operator==(const tiny_vec& v) const; bool operator!=(const tiny_vec& v) const; tiny_vec operator-() const; tiny_vec& operator+=(const T& s); tiny_vec& operator+=(int s); tiny_vec operator+(const T& s) const; tiny_vec operator+(int s) const; tiny_vec& operator-=(const T& s); tiny_vec& operator-=(int s); tiny_vec operator-(const T& s) const; tiny_vec operator-(int s) const; tiny_vec& operator*=(const T& s); tiny_vec& operator*=(int s); tiny_vec operator*(const T& s) const; tiny_vec operator*(int s) const; tiny_vec& operator/=(const T& s); tiny_vec& operator/=(int s); tiny_vec operator/(const T& s) const; tiny_vec operator/(int s) const; tiny_vec& operator+=(const tiny_vec& v); tiny_vec operator+(const tiny_vec& v) const; tiny_vec& operator-=(const tiny_vec& v); tiny_vec operator-(const tiny_vec& v) const; tiny_vec& operator*=(const tiny_vec& v); tiny_vec operator*(const tiny_vec& v) const; tiny_vec& operator/=(const tiny_vec& v); tiny_vec operator/(const tiny_vec& v) const; T& operator()(size_t i); T operator()(size_t i) const; T& x() {return _data[0];}; T& y() {return _data[1];}; T& z() {return _data[2];}; T x() const {return _data[0];}; T y() const {return _data[1];}; T z() const {return _data[2];}; void sort(); void random_shuffle(); T& min_elem(); size_t min_index(); T& max_elem(); size_t max_index(); T& median_elem(); size_t median_index(); T sqr_length(); T length(); void normalize(); }; template tiny_vec::tiny_vec(){} template tiny_vec::tiny_vec(size_t n, const T* marray) { std::copy(marray,marray+_size,begin()); } template tiny_vec::~tiny_vec(){} template tiny_vec::tiny_vec(const T&x,const T&y) { _data[0]=x; _data[1]=y; } template tiny_vec::tiny_vec(const T&x,const T&y, const T&z) { _data[0]=x; _data[1]=y; _data[2]=z; } template tiny_vec::tiny_vec(const T&x, const T&y, const T&z,const T& w) { _data[0]=x; _data[1]=y; _data[2]=z; _data[3]=w; } template void tiny_vec::set(const T& x) { _data[0]=x; } template void tiny_vec::set(const T& x, const T& y) { _data[0]=x; _data[1]=y; } template void tiny_vec::set(const T& x, const T& y,const T& z) { _data[0]=x; _data[1]=y; _data[2]=z; } template void tiny_vec::set(const T& x, const T& y,const T& z, const T& w) { _data[0]=x; _data[1]=y; _data[2]=z; _data[3]=w; } template int tiny_vec::size() const { return N; } template tiny_vec::operator T*() { return _data; } template tiny_vec::operator const T*() const { return _data; } template tiny_vec& tiny_vec::operator=(const T &s) { for(int i=0;i < N;i++) _data[i]=s; return *this; } template tiny_vec& tiny_vec::operator=(int s) { for(int i=0;i tiny_vec& tiny_vec::operator=(const tiny_vec & v) { if(&v== this) return *this; std::copy(v.begin(),v.end(),begin()); return *this; } template void tiny_vec::fill(const T& s) { std::fill(begin(),end(),s); } template void tiny_vec::zeros(size_t m) { T zero; zero=0; std::fill(begin(), end(), zero); } template void tiny_vec::zeros() { T zero; zero=0; std::fill(begin(), end(), zero); } template void tiny_vec::ones() { T one; one = 1; std::fill(begin(), end(), one); } template void tiny_vec::ones(size_t m) { resize(m); T one; one = 1; std::fill(begin(), end(), one); } template typename tiny_vec::iterator tiny_vec::begin() { return _data; } template typename tiny_vec::const_iterator tiny_vec::begin() const { return _data; } template typename tiny_vec::iterator tiny_vec::end() { return _data + N; } template typename tiny_vec::const_iterator tiny_vec::end() const { return _data +N; } template typename tiny_vec::reverse_iterator tiny_vec::rbegin() { return reverse_iterator(end()); } template typename tiny_vec::reverse_iterator tiny_vec::rend() { return reverse_iterator(begin()); } template typename tiny_vec::const_reverse_iterator tiny_vec::rbegin() const { return const_reverse_iterator(end()); } template typename tiny_vec::const_reverse_iterator tiny_vec:: rend() const { return const_reverse_iterator(begin()); } template bool tiny_vec::operator==(const tiny_vec& v) const { return std::equal(begin(),end(),v.begin()); } template bool tiny_vec::operator!=(const tiny_vec& v) const { return !(*this == v); } template tiny_vec tiny_vec::operator-() const { return (T)-1* *this; } template tiny_vec& tiny_vec::operator+=(const T& s) { #ifdef _HAS_CPP0X std::for_each(begin(),end(),[&s](T& elem){elem+=s;}); #else for(int i=0;i tiny_vec& tiny_vec::operator+=(int s) { #ifdef _HAS_CPP0X std::for_each(begin(),end(),[&s](T& elem){elem+=(T)s;}); #else for(int i=0;i tiny_vec tiny_vec::operator+(const T& s) const { tiny_vec r = *this; r += s; return r; } template tiny_vec tiny_vec::operator+(int s) const { tiny_vec r = *this; r += s; return r; } template tiny_vec& tiny_vec::operator-=(const T& s) { #ifdef _HAS_CPP0X std::for_each(begin(),end(),[&s](T& elem){elem-=s;}); #else for(int i=0; i < N;i++) _data[i]-=s; #endif return *this; } template tiny_vec& tiny_vec::operator-=(int s) { #ifdef _HAS_CPP0X std::for_each(begin(),end(),[&s](T& elem){elem-=(T)s;}); #else for(int i=0;i tiny_vec tiny_vec::operator-(const T& s) const { tiny_vec r = *this; r -= s; return r; } template tiny_vec tiny_vec::operator-(int s) const { tiny_vec r = *this; r -= (T)s; return r; } template tiny_vec& tiny_vec::operator*=(const T& s) { #ifdef _HAS_CPP0X std::for_each(begin(),end(),[&s](T& elem){elem *= s;}); #else for(int i=0;i < N;i++) _data[i]*=s; #endif return *this; } template tiny_vec& tiny_vec::operator*=(int s) { #ifdef _HAS_CPP0X std::for_each(begin(),end(),[&s](T& elem){elem *= (T)s;}); #else for(int i=0; i tiny_vec tiny_vec::operator*(const T& s) const { tiny_vec r = *this; r *= s; return r; } template tiny_vec tiny_vec::operator*(int s) const { tiny_vec r = *this; r *= (T)s; return r; } template tiny_vec& tiny_vec::operator/=(const T& s) { #ifdef _HAS_CPP0X std::for_each(begin(),end(),[&s](T& elem){elem/=s;}); #else for(int i=0; i tiny_vec& tiny_vec::operator/=(int s) { #ifdef _HAS_CPP0X std::for_each(begin(),end(),[&s](T& elem){elem/=(T)s;}); #else for(int i=0;i tiny_vec tiny_vec::operator/(const T& s) const { tiny_vec r = *this; r /= s; return r; } template tiny_vec tiny_vec::operator/(int s) const { tiny_vec r = *this; r /= (T)s; return r; } template tiny_vec& tiny_vec::operator+=(const tiny_vec& v) { #ifdef _HAS_CPP0X const_iterator vit=v.begin(); std::for_each(begin(),end(),[&vit](T& elem){elem+=*vit++;}); #else for(int i=0; i tiny_vec tiny_vec::operator+(const tiny_vec& v) const { tiny_vec r = *this; r += v; return r; } template tiny_vec& tiny_vec::operator-=(const tiny_vec& v) { #ifdef _HAS_CPP0X const_iterator vit=v.begin(); std::for_each(begin(),end(),[&vit](T& elem){elem-=*vit++;}); #else for(int i =0; i < N; i++) _data[i]-= v[i]; #endif return *this; } template tiny_vec tiny_vec::operator-(const tiny_vec& v) const { tiny_vec r = *this; r -= v; return r; } template tiny_vec& tiny_vec::operator*=(const tiny_vec& v) { #ifdef _HAS_CPP0X auto vit=v.begin(); std::for_each(begin(),end(),[&vit](T& elem){elem*=*vit++;}); #else for(int i=0; i < N; i++) _data[i]*= v[i]; #endif return *this; } template tiny_vec tiny_vec::operator*(const tiny_vec& v) const { tiny_vec r = *this; r *= v; return r; } template tiny_vec& tiny_vec::operator/=(const tiny_vec& v) { #ifdef _HAS_CPP0X auto vit=v.begin(); std::for_each(begin(),end(),[&vit](T& elem){elem/=*vit++;}); #else for(int i = 0; i < N; i++) _data[i] /= v[i]; #endif return *this; } template tiny_vec tiny_vec::operator/(const tiny_vec& v) const { tiny_vec r = *this; r /= v; return r; } template T& tiny_vec::operator()(size_t i) { assert(i >= 0 && i < N); return _data[i]; } template T tiny_vec::operator()(size_t i) const { assert(i >= 0 && i < N); return _data[i]; } template void tiny_vec::sort() { std::sort(begin(),end()); } template void tiny_vec::random_shuffle() { std::random_shuffle(begin(),end()); } template T& tiny_vec::min_elem() { return *std::min_element(begin(),end()); } template size_t tiny_vec::min_index() { return std::distance(begin(),std::min_element(begin(),end())); } template T& tiny_vec::max_elem() { return *std::max_element(begin(),end()); } template size_t tiny_vec::max_index() { return std::distance(begin(),std::max_element(begin(),end())); } template T& tiny_vec::median_elem() { iterator it= begin() + _size/2; std::nth_element(begin(),it,end()); return *it; } template size_t tiny_vec::median_index() { return begin() +_size/2; } template T tiny_vec::sqr_length() { iterator it= begin(); T l = 0; while(it != end()) l += (*it)*(*it++); return l; } template T tiny_vec::length() { T l = sqr_length(); return sqrt(l); } template tiny_vec operator+(const T& s, const tiny_vec& v) { return v+s; } template tiny_vec operator+(int s, const tiny_vec& v) { return v+(T)s; } template tiny_vec operator-(const T& s, const tiny_vec& v) { return -v+s; } template tiny_vec operator-(int s, const tiny_vec& v) { return -v+(T)s; } template tiny_vec operator*(const T& s, const tiny_vec& v) { return v*s; } template tiny_vec operator*(int s, const tiny_vec& v) { return v*(T)s; } template tiny_vec operator/(const T& s, const tiny_vec& v) { return v*(T)(1.0/s); } template tiny_vec operator/(int s, const tiny_vec& v) { return v*(T)(1.0/s); } template T dot(const tiny_vec& v1, const tiny_vec& v2) { return std::inner_product(v1.begin(),v1.end(),v2.begin(),(T)0); } template tiny_vec cross(const tiny_vec& b, const tiny_vec& c) { tiny_vec a; a[0] = b(1)*c(2) - b(2)*c(1); a[1] = b(2)*c(0) - b(0)*c(2); a[2] = b(0)*c(1) - b(1)*c(0); return a; } template tiny_vec homog(const tiny_vec& v) { tiny_vec vh; std::copy(v.begin(),v.end(),vh.begin()); vh(v.size()) = (T)1; return vh; } template tiny_vec unhomog(const tiny_vec& v) { tiny_vec vh; T w = *(v.end()-1); #ifdef _HAS_CPP0X auto vit=v.begin(); std::for_each(vh.begin(),vh.end(),[&](T& elem){elem=*vit++/w;}); #else for(int i = 0; i < N-1; i++) vh[i] = v[i]/w; #endif return vh; } template std::ostream& operator<<(std::ostream& out, const tiny_vec& v) { #ifdef _HAS_CPP0X auto it = v.begin(); if(it != v.end()) out << *it ++; std::for_each(it, v.end(),[&out](const T& elem){ out << " " << elem;}); #else if(v.size() > 0) out << v[0]; for(int i = 1; i < v.size(); i++) out <<" " < std::istream& operator>>(std::istream& in, tiny_vec& v) { #ifdef _HAS_CPP0X std::for_each(v.begin(), v.end(),[&in](T& elem){ in >> elem;}); #else for(int i = 0; i < v.size(); i++) in >> v[i]; #endif return in; } template void tiny_vec::normalize() { T l = length(); if(l != 0) operator/=(l); } typedef tiny_vec point2d; typedef tiny_vec point3d; typedef tiny_vec point4d;