// Copyright (C) 2003 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #undef DLIB_VECTOR_ABSTRACT_ #ifdef DLIB_VECTOR_ABSTRACT_ #include "../serialize.h" #include <functional> #include <iostream> #include "../matrix/matrix_abstract.h" namespace dlib { template < typename T, long NR = 3 > class vector : public matrix<T,NR,1> { /*! REQUIREMENTS ON T T should be some object that provides an interface that is compatible with double, float, int, long and the like. REQUIREMENTS ON NR NR == 3 || NR == 2 INITIAL VALUE x() == 0 y() == 0 z() == 0 WHAT THIS OBJECT REPRESENTS This object represents a three dimensional vector. If NR == 2 then this object is limited to representing points on the XY plane where Z is set to 0. Also note that this object performs the appropriate integer and floating point conversions and promotions when vectors of mixed type are used together. For example: vector<int,3> vi; vector<double,2> vd; vd + vi == a vector<double,3> object type since that is what is needed to contain the result of vi+vd without any loss of information. !*/ public: typedef T type; vector ( ); /*! ensures - #*this has been properly initialized !*/ vector ( const T _x, const T _y, const T _z ); /*! requires - NR == 3 ensures - #x() == _x - #y() == _y - #z() == _z !*/ vector ( const T _x, const T _y ); /*! requires - NR == 2 ensures - #x() == _x - #y() == _y - #z() == 0 !*/ template <typename U, long NRv> vector ( const vector<U,NRv>& v ); /*! ensures - Initializes *this with the contents of v and does any rounding if necessary and also takes care of converting between 2 and 3 dimensional vectors. - if (U is a real valued type like float or double and T is an integral type like long) then - if (NR == 3) then - #x() == floor(v.x() + 0.5) - #y() == floor(v.y() + 0.5) - #z() == floor(v.z() + 0.5) - else // NR == 2 - #x() == floor(v.x() + 0.5) - #y() == floor(v.y() + 0.5) - #z() == 0 - else - if (NR == 3) then - #x() == v.x() - #y() == v.y() - #z() == v.z() - else // NR == 2 - #x() == v.x() - #y() == v.y() - #z() == 0 !*/ template <typename EXP> vector ( const matrix_exp<EXP>& m ); /*! requires - m.size() == NR - m.nr() == 1 || m.nc() == 1 (i.e. m must be a row or column matrix) ensures - Initializes *this with the contents of m and does any rounding if necessary and also takes care of converting between 2 and 3 dimensional vectors. - if (m contains real valued values like float or double and T is an integral type like long) then - #x() == floor(m(0) + 0.5) - #y() == floor(m(1) + 0.5) - if (NR == 3) then - #z() == floor(m(2) + 0.5) - else - #z() == 0 - else - #x() == m(0) - #y() == m(1) - if (NR == 3) then - #z() == m(2) - else - #z() == 0 !*/ ~vector ( ); /*! ensures - all resources associated with *this have been released !*/ double length( ) const; /*! ensures - returns the length of the vector !*/ double length_squared( ) const; /*! ensures - returns length()*length() !*/ T& x ( ); /*! ensures - returns a reference to the x component of the vector !*/ T& y ( ); /*! ensures - returns a reference to the y component of the vector !*/ T& z ( ); /*! requires - NR == 3 (this function actually doesn't exist when NR != 3) ensures - returns a reference to the z component of the vector !*/ const T& x ( ) const; /*! ensures - returns a const reference to the x component of the vector !*/ const T& y ( ) const; /*! ensures - returns a const reference to the y component of the vector !*/ const T& z ( ) const; /*! ensures - if (NR == 3) then - returns a const reference to the z component of the vector - else - return 0 (there isn't really a z in this case so we just return 0) !*/ T dot ( const vector& rhs ) const; /*! ensures - returns the result of the dot product between *this and rhs !*/ vector<T,3> cross ( const vector& rhs ) const; /*! ensures - returns the result of the cross product between *this and rhs !*/ vector<double,NR> normalize ( ) const; /*! ensures - returns a vector with length() == 1 and in the same direction as *this !*/ vector operator+ ( const vector& rhs ) const; /*! ensures - returns the result of adding *this to rhs !*/ vector operator- ( const vector& rhs ) const; /*! ensures - returns the result of subtracting rhs from *this !*/ vector operator- ( ) const; /*! ensures - returns -1*(*this) !*/ vector operator/ ( const T rhs ) const; /*! ensures - returns the result of dividing *this by rhs !*/ vector& operator= ( const vector& rhs ); /*! ensures - #x() == rhs.x() - #y() == rhs.y() - #z() == rhs.z() - returns #*this !*/ vector& operator += ( const vector& rhs ); /*! ensures - #*this == *this + rhs - returns #*this !*/ vector& operator -= ( const vector& rhs ); /*! ensures - #*this == *this - rhs - returns #*this !*/ vector& operator *= ( const T rhs ); /*! ensures - #*this == *this * rhs - returns #*this !*/ vector& operator /= ( const T rhs ); /*! ensures - #*this == *this / rhs - returns #*this !*/ template <typename U, long NR2> bool operator== ( const vector<U,NR2>& rhs ) const; /*! ensures - if (x() == rhs.x() && y() == rhs.y() && z() == rhs.z()) then - returns true - else - returns false !*/ template <typename U, long NR2> bool operator!= ( const vector<U,NR2>& rhs ) const; /*! ensures - returns !((*this) == rhs) !*/ void swap ( vector& item ); /*! ensures - swaps *this and item !*/ }; // ---------------------------------------------------------------------------------------- template<typename T, typename U, long NR> vector operator* ( const vector<T,NR> & lhs, const U rhs ); /*! ensures - returns the result of multiplying the scalar rhs by lhs !*/ template<typename T, typename U, long NR> vector operator* ( const U lhs, const vector<T,NR> & rhs ); /*! ensures - returns the result of multiplying the scalar lhs by rhs !*/ template<typename T, long NR> inline void swap ( vector<T,NR> & a, vector<T,NR> & b ) { a.swap(b); } /*! provides a global swap function !*/ template<typename T, long NR> void serialize ( const vector<T,NR>& item, std::ostream& out ); /*! provides serialization support !*/ template<typename T, long NR> void deserialize ( vector<T,NR>& item, std::istream& in ); /*! provides deserialization support !*/ template<typename T> std::ostream& operator<< ( std::ostream& out, const vector<T,3>& item ); /*! ensures - writes item to out in the form "(x, y, z)" !*/ template<typename T> std::istream& operator>>( std::istream& in, vector<T,3>& item ); /*! ensures - reads a vector from the input stream in and stores it in #item. The data in the input stream should be of the form (x, y, z) !*/ template<typename T> std::ostream& operator<< ( std::ostream& out, const vector<T,2>& item ); /*! ensures - writes item to out in the form "(x, y)" !*/ template<typename T> std::istream& operator>>( std::istream& in, vector<T,2>& item ); /*! ensures - reads a vector from the input stream in and stores it in #item. The data in the input stream should be of the form (x, y) !*/ // ---------------------------------------------------------------------------------------- /*!A point This is just a typedef of the vector object. !*/ typedef vector<long,2> point; /*!A dpoint This is just a typedef of the vector object. !*/ typedef vector<double,2> dpoint; // ---------------------------------------------------------------------------------------- } namespace std { /*! Define std::less<vector<T,3> > so that you can use vectors in the associative containers. !*/ template<typename T> struct less<dlib::vector<T,3> > : public binary_function<dlib::vector<T,3> ,dlib::vector<T,3> ,bool> { inline bool operator() (const dlib::vector<T,3> & a, const dlib::vector<T,3> & b) const { if (a.x() < b.x()) return true; else if (a.x() > b.x()) return false; else if (a.y() < b.y()) return true; else if (a.y() > b.y()) return false; else if (a.z() < b.z()) return true; else if (a.z() > b.z()) return false; else return false; } }; /*! Define std::less<vector<T,2> > so that you can use vector<T,2>s in the associative containers. !*/ template<typename T> struct less<dlib::vector<T,2> > : public binary_function<dlib::vector<T,2> ,dlib::vector<T,2> ,bool> { inline bool operator() (const dlib::vector<T,2> & a, const dlib::vector<T,2> & b) const { if (a.x() < b.x()) return true; else if (a.x() > b.x()) return false; else if (a.y() < b.y()) return true; else if (a.y() > b.y()) return false; else return false; } }; } #endif // DLIB_VECTOR_ABSTRACT_