Mathematical Vector (V2) (can do 2D and 3D)

#ifndef VECTEUR_HPP_INCLUDED #define VECTEUR_HPP_INCLUDED #include <cmath> #include <initializer_list> #include <string> #include <regex> #include <sstream> #include <cstdlib> #include <functional> class vecteur{ private: bool isTab(const std::string& str) const{ std::regex tabs("^(\\t)*$"); std::smatch matcher; return std::regex_match(str, matcher, tabs); } template <class T> std::string __stringstreamStringify(const T& arg) const{ std::stringstream ss; ss << arg; return ss.str(); } public: /***@@@CLASSattributes@@@***/ /*vecteur::PI*/ constexpr static double PI = 3.141592653589793; /*vecteur::angleUnit*/ /*vecteur::angleUnit::deg*/ enum class angleUnit{ deg = 1 << 0, rad = 1 << 1 }; /*vecteur::mode*/ /*vecteur::mode::origin*/ enum class mode{ origin = 1 << 0, xy = 1 << 1, yz = 1 << 2, xz = 1 << 3, xyz = 1 << 4, undefined = 1 << 5 }; /***@@@CLASSmethods@@@***/ /**Radian to Degree conversion */ double radian2degree(const double& x) const{ return x*( (double)(180 / vecteur::PI) ); } /**Degree to Radian conversion */ double degree2radian(const double& x) const{ return x*( (double)(vecteur::PI / 180) ); } /***@@@ATTRIBUTES@@@***/ double x, y, z; /***@@@CONSTRUCTORS@@@***/ /**Default constructor *@param a being the x-component (default: 0) *@param b being the y-component (default: 0) *@param c being the z-component (default: 0) */ vecteur(double a=0, double b=0, double c=0) : x(a),y(b),z(c){} /**Copy constructor *@param v being the vecteur to copy */ vecteur(const vecteur& v){ this->x = v.x; this->y = v.y; this->z = v.z; } /**Assignment operator : vecteur *@param v being the vecteur to copy *@return a reference to the current vecteur (allows chaining) */ vecteur& operator=(const vecteur& v){ this->x = v.x; this->y = v.y; this->z = v.z; return (*this); } /**Assignment operator : initiliazer list {} *@param init_list being the initializer list *@return a reference to the current vecteur (allows chaining) */ vecteur& operator=(const std::initializer_list<double>& init_list){ (*this) = vecteur(init_list); return (*this); } /**Initializer list {} constructor *@param init_list being the initializer list * *@behavior if init_list.length == 1, then it'll set the value for x ||| if init_list.length == 2, then it'll set the value for x and y ||| if init_list.length==3 then it will set the values for x, y and z ||| else {0, 0, 0} */ vecteur(const std::initializer_list<double>& init_list){ switch(init_list.size()){ case 1: this->x = *( init_list.begin() ); this->y=0; this->z=0; break; case 2: this->x = *( init_list.begin() ); this->y = *( init_list.begin()+1 ); this->z = 0; break; case 3: this->x = *( init_list.begin() ); this->y = *( init_list.begin()+1 ); this->z = *( init_list.begin()+2 ); break; default: (*this) = vecteur(0,0,0); break; } } /***@@@DESTRUCTORS@@@***/ /**Default destructor * */ ~vecteur() = default; /***@@@CALCULUSESoperators@@@***/ /**operator+ (binary) : Addition of vecteurs *@param other being the second operand of the addition (this being the first operand) *@return a vecteur being this+other */ vecteur operator+(const vecteur& other) const{ return vecteur(x+other.x, y+other.y, z+other.z); } /**operator- (binary) : Subtraction of vecteurs *@param other being the second operand of the subtraction (this being the first operand) *@return a vecteur being this-other */ vecteur operator-(const vecteur& other) const{ return vecteur(x-other.x, y-other.y, z-other.z); } /**operator* (binary) : Scaling *@param scale_factor being the scaling factor *@return a scaled vecteur being scale_factor*this */ vecteur operator*(const double& scale_factor) const{ return vecteur(x*scale_factor, y*scale_factor, z*scale_factor); } /**operator- (unary) : *@return the opposite of the current vecteur */ vecteur operator-() const{ return (*this) * -1; } /**operator+= : self addition *@param other being the other vecteur *@return a reference to the current vecteur (allows chaining) */ vecteur& operator+=(const vecteur& other){ (*this) = (*this) + other; return (*this); } /**operator-= : self subtraction *@param other being the other vecteur *@return a reference to the current vecteur (allows chaining) */ vecteur& operator-=(const vecteur& other){ (*this) = (*this) - other; return (*this); } /**operator*= : self scaling *@param scale_factor being the scaling factor *@return a reference to the current vecteur (allows chaining) */ vecteur& operator*=(const double& scale_factor){ (*this) = (*this) * scale_factor; return (*this); } /***@@@COMPARISONoperators@@@***/ /**operator== : Test if two vecteurs are equivalent *@param other being the other vecteur *@return TRUE if equivalent, FALSE otherwise */ bool operator==(const vecteur& other) const{ if(this == &other) return true; return x==other.x && y==other.y && z==other.z; } /**operator!= : Test if two vecteurs are not equivalent *@param other being the other vecteur *@return TRUE if not equivalent, FALSE otherwise */ bool operator!=(const vecteur& other) const{ return !( this->operator==(other) ); } /**operator< : Determines whether the vecteur is closer to the origin (0,0,0) than the other *@param other being the other vecteur *@return TRUE if this is closer than other, FALSE otherwise */ bool operator<(const vecteur& other) const{ return this->norm() < other.norm(); } /**operator<= : Determines whether the vecteur is closer to or at the same distance from the origin *@param other being the other vecteur *@return TRUE if closer or same distance, FALSE otherwise */ bool operator<=(const vecteur& other) const{ return (*this) < other || (*this) == other; } /**operator> : Determines whether the vecteur is further away from the origin *@param other being the other vecteur *@return TRUE if further away, FALSE otherwise */ bool operator>(const vecteur& other) const{ return this->norm() > other.norm(); } /**operator>= : Determines whether the vecteur is further away from or at the same distance from the origin *@param other being the other vecteur *@return TRUE if further away or same distance, FALSE otherwise */ bool operator>=(const vecteur& other) const{ return (*this) > other || (*this) == other; } /***@@@OPERATIONS@@@***/ /**Addition of vecteurs *@param other being the second operand of the addition *@return a vecteur being this+other */ vecteur plus(const vecteur& other) const{ return (*this) + other; } /**Subtraction of vecteurs *@param other being the second operand of the subtraction *@return a vecteur being this-other */ vecteur minus(const vecteur& other) const{ return (*this) - other; } /**Scaling *@param scale_factor being the scaling factor *@return a vecteur being this*scale_factor */ vecteur times(const double& scale_factor) const{ return (*this) * scale_factor; } /**Opposite of a vecteur *@return a vecteur being -1*scale_factor */ vecteur opposite() const{ return -(*this); } /**Self addition *@param other being the vecteur to add *@return a reference to the current vecteur (allows chaining) */ vecteur& add(const vecteur& other){ (*this) += other; return (*this); } /**Self subtraction *@param other being the vecteur to subtract *@return a reference to the current vecteur (allows chaining) */ vecteur& sub(const vecteur& other){ (*this) -= other; return (*this); } /**Self scaling *@param scale_factor being the scaling factor *@return a reference to the current vecteur (allows chaining) */ vecteur& scale(const double& scale_factor){ (*this) *= scale_factor; return (*this); } /**Equivalence test *@param other being the other vecteur *@return TRUE if equivalent, FALSE otherwise */ bool equals(const vecteur& other) const{ return (*this) == other; } /***@@@METHODS@@@***/ /**Calculation of the norm of the vecteur *@return the norm of the vecteur as a double */ double norm() const{ return std::abs( std::sqrt(x*x + y*y + z*z) ); } double norme() const{ return this->norm(); } /**Determines whether the vecteur is the origin or not *@return TRUE if origin, FALSE otherwise */ bool isOrigin() const{ return this->equals(vecteur(0,0,0)); } bool isZero() const{ return this->isOrigin(); } /**Determines whether the vecteur is 2D or not *@return TRUE if 2D, FALSE otherwise * *@behavior the origin is 2D */ bool is2D() const{ return isOrigin() || x==0 || y==0 || z==0; } /**Determines whether the vecteur is 3D or not *@return TRUE if 3D, FALSE otherwise * *@behavior the origin is 3D */ bool is3D() const{ return isOrigin() || !is2D(); } /**Calculation of the scalar product *@param other being the other vecteur *@return the scalar product between this and other as a double */ double scal_prod(const vecteur& other) const{ return x*other.x + y*other.y + z*other.z; } double prod_scal(const vecteur& other) const{ return this->scal_prod(other); } /**Determines whether two vecteurs are collinear or not *@param other being the other vecteur *@return TRUE if collinear, FALSE otherwise */ bool collinear(const vecteur& other) const{ if( (is2D() && other.is2D()) || (is3D() && other.is3D()) ){ double b1b1 = this->scal_prod((*this)); double b1b2 = this->scal_prod(other); double b2b2 = other.scal_prod(other); if(b1b1!=0 && b2b2!=0) if(b1b1*b2b2 == b1b2*b1b2) return true; } return false; } bool isCollinearTo(const vecteur& other) const{ return this->collinear(other); } /**Determines whether two vecteurs are orthogonal *@param other being the other vecteur *@return TRUE if orthogonal, FALSE otherwise */ bool orthogonal(const vecteur& other) const{ return prod_scal(other)==0.000; } bool isOrthogonalTo(const vecteur& other) const{ return this->isOrthogonalTo(other); } /**Calculation of the angle between two vecteur *@param other being the other vecteur *@param angleMode being the desired unit for the result (use the enum vecteur::angleUnit) (default: deg) *@return -404 if error, the angle as a double (unit corresponding to the angleUnit) */ double angleFrom(const vecteur& other, const vecteur::angleUnit& angleMode = vecteur::angleUnit::deg) const{ if(is2D() && other.is2D()){ double a = this->norm(); double b = other.norm(); double ps = this->scal_prod(other); double ab = a * b; double res = std::acos(ps/ab); /**WARNING: std::acos returns an angle as a radian, might need conversion**/ switch(angleMode){ case vecteur::angleUnit::deg : return vecteur::radian2degree(res); case vecteur::angleUnit::rad : return res; default: return -404; } } return -404.00; } /**Calculations of the vectorial product between two vecteurs *@param other being the other vecteur *@return the vectorial product as a vecteur */ vecteur vect_prod(const vecteur& other) const{ double a,b,c; /** a stands for the x-component b stands for the y-component c stands for the z-component **/ c = (x * other.y) - (y * other.x); a = (y * other.z) - (z * other.y); b = (z * other.x) - (x * other.z); return vecteur(a, b, c); } vecteur prod_vect(const vecteur& other) const{ return this->vect_prod(other); } /**Mode getter *@return the current mode of the vecteur * *@behavior origin > xyz > xy > xz > yz > undefined */ vecteur::mode getMode() const{ if(isOrigin()) return vecteur::mode::origin; if(is3D()) return vecteur::mode::xyz; if(is2D()){ if(z==0) return vecteur::mode::xy; if(y==0) return vecteur::mode::xz; if(x==0) return vecteur::mode::yz; } return vecteur::mode::undefined; } /**String representation of the vecteur's current mode *@return a string representing the vecteur's current mode */ std::string getModeString() const{ vecteur::mode vm = this->getMode(); switch(vm){ case vecteur::mode::origin : return "origin"; case vecteur::mode::xyz : return "xyz"; case vecteur::mode::xy : return "xy"; case vecteur::mode::xz : return "xz"; case vecteur::mode::yz : return "yz"; case vecteur::mode::undefined : return "undefined"; default: return "undefined"; } } /***@@@DEBUG@@@***/ /**Quik way of displaying info regarding a vecteur */ void debugDisplay() const{ std::cout << "<VECTEUR>" << '\n'; std::cout << '\t' << "x: " << x << '\n'; std::cout << '\t' << "y: " << y << '\n'; std::cout << '\t' << "z: " << z << '\n'; std::cout << "</VECTEUR>" << '\n'; } /**Display all the informations regarding a vecteur *@param tab being a string made of tabulation characters only (tabulation level for display) */ void disp(const std::string& tab = "") const{ std::cout << this->stringify(tab); } /**Creation of a string representation of the vecteur *@param tabu being a string made of tabulation characters only (tabulation level for display) *@return a string representation of the vecteur */ std::string stringify(const std::string& tabu = "") const{ std::string tab = isTab(tabu) ? tabu : ""; std::string ret = ""; ret += tab + "<VECTEUR>" + '\n'; ret += (x!=0) ? tab + '\t' + "x: " + __stringstreamStringify(x) + '\n' : ""; ret += (y!=0) ? tab + '\t' + "y: " + __stringstreamStringify(y) + '\n' : ""; ret += (z!=0) ? tab + '\t' + "z: " + __stringstreamStringify(z) + '\n' : ""; ret += tab + '\t' + "mode: " + getModeString() + '\n'; ret += tab + '\t' + "norm: " + __stringstreamStringify(this->norm()) + " unit(s)" + '\n'; ret += tab + "</VECTEUR>" + '\n' +'\n'; return ret; } /**hashCode to string (std::string) *@return a string representation of the vecteur's hashcode */ std::string hashCodeString() const{ return __stringstreamStringify(this->hashCode()); } /**hashCode calculation *@return the vecteur's hashcode as an integer */ int hashCode() const{ const int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; result = prime * result + z; result = prime * result + (int)getMode(); result = prime * result + (int)norm(); char* ender; result = prime * result + std::strtol(__stringstreamStringify(this).c_str(), &ender, 10); return result; } }; #endif // VECTEUR_HPP_INCLUDED
A class that allows handling 2D and 3D vectors (mathematical ones) in a fancy c++ code style.
Easy to use, many calculation methods including the vectorial product and the calculus of the angle between two vectors.

( https://en.wikipedia.org/wiki/Vector_(mathematics_and_physics)

EDITS:
#3 : Corrected typos, replaced PI with a better PI (lmao)
#4 : Few fixes + ready fo doxygen

Be the first to comment

You can use [html][/html], [css][/css], [php][/php] and more to embed the code. Urls are automatically hyperlinked. Line breaks and paragraphs are automatically generated.