// 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 #include #include "../matrix/matrix_abstract.h" namespace dlib { template < typename T, long NR = 3 > class vector : public matrix { /*! 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 vi; vector vd; vd + vi == a vector 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 vector ( const vector& 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 vector ( const matrix_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 cross ( const vector& rhs ) const; /*! ensures - returns the result of the cross product between *this and rhs !*/ vector 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 bool operator== ( const vector& rhs ) const; /*! ensures - if (x() == rhs.x() && y() == rhs.y() && z() == rhs.z()) then - returns true - else - returns false !*/ template bool operator!= ( const vector& rhs ) const; /*! ensures - returns !((*this) == rhs) !*/ void swap ( vector& item ); /*! ensures - swaps *this and item !*/ }; // ---------------------------------------------------------------------------------------- template vector operator* ( const vector & lhs, const U rhs ); /*! ensures - returns the result of multiplying the scalar rhs by lhs !*/ template vector operator* ( const U lhs, const vector & rhs ); /*! ensures - returns the result of multiplying the scalar lhs by rhs !*/ template inline void swap ( vector & a, vector & b ) { a.swap(b); } /*! provides a global swap function !*/ template void serialize ( const vector& item, std::ostream& out ); /*! provides serialization support !*/ template void deserialize ( vector& item, std::istream& in ); /*! provides deserialization support !*/ template std::ostream& operator<< ( std::ostream& out, const vector& item ); /*! ensures - writes item to out in the form "(x, y, z)" !*/ template std::istream& operator>>( std::istream& in, vector& 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 std::ostream& operator<< ( std::ostream& out, const vector& item ); /*! ensures - writes item to out in the form "(x, y)" !*/ template std::istream& operator>>( std::istream& in, vector& 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 point; /*!A dpoint This is just a typedef of the vector object. !*/ typedef vector dpoint; // ---------------------------------------------------------------------------------------- bool is_convex_quadrilateral ( const std::array& pts ); /*! ensures - If you walk the points in pts in order pts[0], pts[1], pts[2], pts[3], pts[0] does it draw a convex quadrilateral? This routine returns true if yes and false if not. !*/ // ---------------------------------------------------------------------------------------- template < typename array_of_dpoints > double polygon_area ( const array_of_dpoints& pts ); /*! requires - array_of_dpoints is something with an interface compatible with std::vector or std::array. ensures - If you walk the points pts in order to make a closed polygon, what is its area? This function returns that area. It uses the shoelace formula to compute the result and so works for general non-self-intersecting polygons. !*/ // ---------------------------------------------------------------------------------------- } namespace std { /*! Define std::less > so that you can use vectors in the associative containers. !*/ template struct less > : public binary_function ,dlib::vector ,bool> { inline bool operator() (const dlib::vector & a, const dlib::vector & 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 > so that you can use vectors in the associative containers. !*/ template struct less > : public binary_function ,dlib::vector ,bool> { inline bool operator() (const dlib::vector & a, const dlib::vector & 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_