#ifndef VEC_H #define VEC_H #include #include #include // Defines a thin wrapper around fixed size C-style arrays, using template parameters, // which is useful for dealing with vectors of different dimensions. // For example, float[3] is equivalent to Vec<3,float>. // Entries in the vector are accessed with the overloaded [] operator, so // for example if x is a Vec<3,float>, then the middle entry is x[1]. // For convenience, there are a number of typedefs for abbreviation: // Vec<3,float> -> Vec3f // Vec<2,int> -> Vec2i // and so on. // Arithmetic operators are appropriately overloaded, and functions are defined // for additional operations (such as dot-products, norms, cross-products, etc.) namespace CCD { template struct Vec { T v[N]; Vec(void) {} explicit Vec(T value_for_all) { for(unsigned int i=0; i explicit Vec(const S *source) { for(unsigned int i=0; i explicit Vec(const Vec& source) { for(unsigned int i=0; i(T v0, T v1) { assert(N==2); v[0]=v0; v[1]=v1; } Vec(T v0, T v1, T v2) { assert(N==3); v[0]=v0; v[1]=v1; v[2]=v2; } Vec(T v0, T v1, T v2, T v3) { assert(N==4); v[0]=v0; v[1]=v1; v[2]=v2; v[3]=v3; } Vec(T v0, T v1, T v2, T v3, T v4) { assert(N==5); v[0]=v0; v[1]=v1; v[2]=v2; v[3]=v3; v[4]=v4; } Vec(T v0, T v1, T v2, T v3, T v4, T v5) { assert(N==6); v[0]=v0; v[1]=v1; v[2]=v2; v[3]=v3; v[4]=v4; v[5]=v5; } T &operator[](int index) { assert(0<=index && (unsigned int)index operator+=(const Vec &w) { for(unsigned int i=0; i operator+(const Vec &w) const { Vec sum(*this); sum+=w; return sum; } Vec operator-=(const Vec &w) { for(unsigned int i=0; i operator-(void) const // unary minus { Vec negative; for(unsigned int i=0; i operator-(const Vec &w) const // (binary) subtraction { Vec diff(*this); diff-=w; return diff; } Vec operator*=(T a) { for(unsigned int i=0; i operator*(T a) const { Vec w(*this); w*=a; return w; } Vec operator*=(const Vec &w) { for(unsigned int i=0; i operator*(const Vec &w) const { Vec componentwise_product; for(unsigned int i=0; i operator/=(T a) { for(unsigned int i=0; i operator/(T a) const { Vec w(*this); w/=a; return w; } }; typedef Vec<2,double> Vec2d; typedef Vec<2,float> Vec2f; typedef Vec<2,int> Vec2i; typedef Vec<2,unsigned int> Vec2ui; typedef Vec<2,short> Vec2s; typedef Vec<2,unsigned short> Vec2us; typedef Vec<2,char> Vec2c; typedef Vec<2,unsigned char> Vec2uc; typedef Vec<2,size_t> Vec2st; typedef Vec<3,double> Vec3d; typedef Vec<3,float> Vec3f; typedef Vec<3,int> Vec3i; typedef Vec<3,unsigned int> Vec3ui; typedef Vec<3,short> Vec3s; typedef Vec<3,unsigned short> Vec3us; typedef Vec<3,char> Vec3c; typedef Vec<3,unsigned char> Vec3uc; typedef Vec<3,size_t> Vec3st; typedef Vec<4,double> Vec4d; typedef Vec<4,float> Vec4f; typedef Vec<4,int> Vec4i; typedef Vec<4,unsigned int> Vec4ui; typedef Vec<4,short> Vec4s; typedef Vec<4,unsigned short> Vec4us; typedef Vec<4,char> Vec4c; typedef Vec<4,unsigned char> Vec4uc; typedef Vec<4,size_t> Vec4st; typedef Vec<6,double> Vec6d; typedef Vec<6,float> Vec6f; typedef Vec<6,unsigned int> Vec6ui; typedef Vec<6,int> Vec6i; typedef Vec<6,short> Vec6s; typedef Vec<6,unsigned short> Vec6us; typedef Vec<6,char> Vec6c; typedef Vec<6,unsigned char> Vec6uc; template T mag2(const Vec &a) { T l=a.v[0] * a.v[0]; for(unsigned int i=1; i T mag(const Vec &a) { return (T)sqrt(mag2(a)); } template inline T dist2(const Vec &a, const Vec &b) { T d=sqr(a.v[0]-b.v[0]); for(unsigned int i=1; i inline T dist(const Vec &a, const Vec &b) { return std::sqrt(dist2(a,b)); } template inline void normalize(Vec &a) { a/=mag(a); } template inline Vec normalized(const Vec &a) { return a/mag(a); } template inline T infnorm(const Vec &a) { T d=std::fabs(a.v[0]); for(unsigned int i=1; i void zero(Vec &a) { for(unsigned int i=0; i std::ostream &operator<<(std::ostream &out, const Vec &v) { out< std::istream &operator>>(std::istream &in, Vec &v) { in>>v.v[0]; for(unsigned int i=1; i>v.v[i]; return in; } template inline bool operator==(const Vec &a, const Vec &b) { bool t = (a.v[0] == b.v[0]); unsigned int i=1; while(i inline bool operator!=(const Vec &a, const Vec &b) { bool t = (a.v[0] != b.v[0]); unsigned int i=1; while(i inline Vec operator*(T a, const Vec &v) { Vec w(v); w*=a; return w; } template inline T min(const Vec &a) { T m=a.v[0]; for(unsigned int i=1; i inline Vec min_union(const Vec &a, const Vec &b) { Vec m; for(unsigned int i=0; i inline Vec max_union(const Vec &a, const Vec &b) { Vec m; for(unsigned int i=0; i b.v[i]) ? m.v[i]=a.v[i] : m.v[i]=b.v[i]; return m; } template inline T max(const Vec &a) { T m=a.v[0]; for(unsigned int i=1; im) m=a.v[i]; return m; } template inline T dot(const Vec &a, const Vec &b) { T d=a.v[0]*b.v[0]; for(unsigned int i=1; i inline Vec<2,T> rotate(const Vec<2,T>& a, const T& angle) { T c = cos(angle); T s = sin(angle); return Vec<2,T>(c*a[0] - s*a[1],s*a[0] + c*a[1]); // counter-clockwise rotation } // Rotate the point (x,y,z) around the vector (u,v,w) template inline Vec<3,T> rotate( const Vec<3,T>& x, const T& angle, const Vec<3,T>& u ) { T ux = u[0]*x[0]; T uy = u[0]*x[1]; T uz = u[0]*x[2]; T vx = u[1]*x[0]; T vy = u[1]*x[1]; T vz = u[1]*x[2]; T wx = u[2]*x[0]; T wy = u[2]*x[1]; T wz = u[2]*x[2]; T sa = (T) sin(angle); T ca = (T) cos(angle); return Vec<3,T> ( u[0] * (ux+vy+wz) + (x[0]*(u[1]*u[1]+u[2]*u[2])-u[0]*(vy+wz))*ca+(-wy+vz)*sa, u[1] * (ux+vy+wz) + (x[1]*(u[0]*u[0]+u[2]*u[2])-u[1]*(ux+wz))*ca+(wx-uz)*sa, u[2] * (ux+vy+wz) + (x[2]*(u[0]*u[0]+u[1]*u[1])-u[2]*(ux+vy))*ca+(-vx+uy)*sa ); } template inline Vec<2,T> perp(const Vec<2,T> &a) { return Vec<2,T>(-a.v[1], a.v[0]); } // counter-clockwise rotation by 90 degrees template inline T cross(const Vec<2,T> &a, const Vec<2,T> &b) { return a.v[0]*b.v[1]-a.v[1]*b.v[0]; } template inline Vec<3,T> cross(const Vec<3,T> &a, const Vec<3,T> &b) { return Vec<3,T>(a.v[1]*b.v[2]-a.v[2]*b.v[1], a.v[2]*b.v[0]-a.v[0]*b.v[2], a.v[0]*b.v[1]-a.v[1]*b.v[0]); } template inline T triple(const Vec<3,T> &a, const Vec<3,T> &b, const Vec<3,T> &c) { return a.v[0]*(b.v[1]*c.v[2]-b.v[2]*c.v[1]) +a.v[1]*(b.v[2]*c.v[0]-b.v[0]*c.v[2]) +a.v[2]*(b.v[0]*c.v[1]-b.v[1]*c.v[0]); } template inline unsigned int hash(const Vec &a) { unsigned int h=a.v[0]; for(unsigned int i=1; i inline void assign(const Vec &a, T &a0, T &a1) { assert(N==2); a0=a.v[0]; a1=a.v[1]; } template inline void assign(const Vec &a, T &a0, T &a1, T &a2) { assert(N==3); a0=a.v[0]; a1=a.v[1]; a2=a.v[2]; } template inline void assign(const Vec &a, T &a0, T &a1, T &a2, T &a3) { assert(N==4); a0=a.v[0]; a1=a.v[1]; a2=a.v[2]; a3=a.v[3]; } template inline void assign(const Vec &a, T &a0, T &a1, T &a2, T &a3, T &a4, T &a5) { assert(N==6); a0=a.v[0]; a1=a.v[1]; a2=a.v[2]; a3=a.v[3]; a4=a.v[4]; a5=a.v[5]; } template inline Vec round(const Vec &a) { Vec rounded; for(unsigned int i=0; i inline Vec floor(const Vec &a) { Vec rounded; for(unsigned int i=0; i inline Vec ceil(const Vec &a) { Vec rounded; for(unsigned int i=0; i inline Vec fabs(const Vec &a) { Vec result; for(unsigned int i=0; i inline void minmax(const Vec &x0, const Vec &x1, Vec &xmin, Vec &xmax) { for(unsigned int i=0; i inline void minmax(const Vec &x0, const Vec &x1, const Vec &x2, Vec &xmin, Vec &xmax) { for(unsigned int i=0; i inline void minmax(const Vec &x0, const Vec &x1, const Vec &x2, const Vec &x3, Vec &xmin, Vec &xmax) { for(unsigned int i=0; i inline void minmax(const Vec &x0, const Vec &x1, const Vec &x2, const Vec &x3, const Vec &x4, Vec &xmin, Vec &xmax) { for(unsigned int i=0; i inline void minmax(const Vec &x0, const Vec &x1, const Vec &x2, const Vec &x3, const Vec &x4, const Vec &x5, Vec &xmin, Vec &xmax) { for(unsigned int i=0; i inline void update_minmax(const Vec &x, Vec &xmin, Vec &xmax) { for(unsigned int i=0; i