// Copyright (C) 2003 Davis E. King (davisking@users.sourceforge.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_VECTOr_H_ #define DLIB_VECTOr_H_ #include <cmath> #include "vector_abstract.h" #include "../algs.h" #include "../serialize.h" #include <functional> #include <iostream> #include "../matrix/matrix.h" namespace dlib { class point; template < typename T > class vector { /*! INITIAL VALUE - x_value == 0 - y_value == 0 - z_value == 0 CONVENTION - x_value == x() - y_value == y() - z_value == z() !*/ public: typedef T type; vector ( ) : x_value(0.0), y_value(0.0), z_value(0.0) {} // --------------------------------------- vector ( const T _x, const T _y, const T _z ) : x_value(_x), y_value(_y), z_value(_z) {} // --------------------------------------- vector ( const vector& v ) : x_value(v.x_value), y_value(v.y_value), z_value(v.z_value) {} // --------------------------------------- inline vector ( const point& p ); // --------------------------------------- template <typename EXP> vector ( const matrix_exp<EXP>& m) { // make sure requires clause is not broken DLIB_ASSERT((m.nr() == 1 || m.nc() == 1) && m.size() == 3, "\t vector(const matrix_exp& m)" << "\n\t the given matrix is of the wrong size" << "\n\t m.nr(): " << m.nr() << "\n\t m.nc(): " << m.nc() << "\n\t m.size(): " << m.size() << "\n\t this: " << this ); x_value = m(0); y_value = m(1); z_value = m(2); } template <long NR, long NC, typename MM> operator matrix<T,NR, NC, MM> () const { matrix<T,3,1> m; m(0) = x_value; m(1) = y_value; m(2) = z_value; return m; } // --------------------------------------- ~vector ( ){} // --------------------------------------- T length( ) const { return (T)std::sqrt((double)(x_value*x_value + y_value*y_value + z_value*z_value)); } // --------------------------------------- vector normalize ( ) const { T tmp = (T)std::sqrt((double)(x_value*x_value + y_value*y_value + z_value*z_value)); return vector ( x_value/tmp, y_value/tmp, z_value/tmp ); } // --------------------------------------- T& x ( ) { return x_value; } // --------------------------------------- T& y ( ) { return y_value; } // --------------------------------------- T& z ( ) { return z_value; } // --------------------------------------- const T& x ( ) const { return x_value; } // --------------------------------------- const T& y ( ) const { return y_value; } // --------------------------------------- const T& z ( ) const { return z_value; } // --------------------------------------- T dot ( const vector& rhs ) const { return x_value*rhs.x_value + y_value*rhs.y_value + z_value*rhs.z_value; } // --------------------------------------- vector cross ( const vector& rhs ) const { return vector ( y_value*rhs.z_value - z_value*rhs.y_value, z_value*rhs.x_value - x_value*rhs.z_value, x_value*rhs.y_value - y_value*rhs.x_value ); } // --------------------------------------- vector operator+ ( const vector& rhs ) const { return vector ( x_value+rhs.x_value, y_value+rhs.y_value, z_value+rhs.z_value ); } // --------------------------------------- vector operator- ( const vector& rhs ) const { return vector ( x_value-rhs.x_value, y_value-rhs.y_value, z_value-rhs.z_value ); } // --------------------------------------- vector& operator= ( const vector& rhs ) { x_value = rhs.x_value; y_value = rhs.y_value; z_value = rhs.z_value; return *this; } // --------------------------------------- vector operator/ ( const T rhs ) const { return vector ( x_value/rhs, y_value/rhs, z_value/rhs ); } // --------------------------------------- vector& operator += ( const vector& rhs ) { x_value += rhs.x_value; y_value += rhs.y_value; z_value += rhs.z_value; return *this; } // --------------------------------------- vector& operator -= ( const vector& rhs ) { x_value -= rhs.x_value; y_value -= rhs.y_value; z_value -= rhs.z_value; return *this; } // --------------------------------------- vector& operator *= ( const T rhs ) { x_value *= rhs; y_value *= rhs; z_value *= rhs; return *this; } // --------------------------------------- vector& operator /= ( const T rhs ) { x_value /= rhs; y_value /= rhs; z_value /= rhs; return *this; } // --------------------------------------- bool operator== ( const vector& rhs ) const { return (x_value == rhs.x_value && y_value == rhs.y_value && z_value == rhs.z_value ); } // --------------------------------------- bool operator!= ( const vector& rhs ) const { return !((*this) == rhs); } // --------------------------------------- void swap ( vector& item ) { exchange(x_value,item.x_value); exchange(y_value,item.y_value); exchange(z_value,item.z_value); } // --------------------------------------- private: T x_value; T y_value; T z_value; }; // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- template<typename T, typename U> inline vector<T> operator* ( const vector<T> & lhs, const U rhs ) { return vector<T> ( lhs.x()*rhs, lhs.y()*rhs, lhs.z()*rhs ); } // ---------------------------------------------------------------------------------------- template<typename T, typename U> inline vector<T> operator* ( const U lhs, const vector<T> & rhs ) { return rhs*lhs; } // ---------------------------------------------------------------------------------------- template<typename T> inline void swap ( vector<T> & a, vector<T> & b ) { a.swap(b); } // ---------------------------------------------------------------------------------------- template<typename T> inline void serialize ( const vector<T> & item, std::ostream& out ) { try { serialize(item.x(),out); serialize(item.y(),out); serialize(item.z(),out); } catch (serialization_error e) { throw serialization_error(e.info + "\n while serializing object of type vector"); } } template<typename T> inline void deserialize ( vector<T> & item, std::istream& in ) { try { deserialize(item.x(),in); deserialize(item.y(),in); deserialize(item.z(),in); } catch (serialization_error e) { item.x() = 0; item.y() = 0; item.z() = 0; throw serialization_error(e.info + "\n while deserializing object of type vector"); } } // ---------------------------------------------------------------------------------------- template<typename T> std::ostream& operator<< ( std::ostream& out, const vector<T>& item ) { out << "(" << item.x() << ", " << item.y() << ", " << item.z() << ")"; return out; } template<typename T> std::istream& operator>>( std::istream& in, vector<T>& item ) { // eat all the crap up to the '(' while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\r' || in.peek() == '\n') in.get(); // there should be a '(' if not then this is an error if (in.get() != '(') { in.setstate(in.rdstate() | std::ios::failbit); return in; } // eat all the crap up to the first number while (in.peek() == ' ' || in.peek() == '\t') in.get(); in >> item.x(); if (!in.good()) return in; // eat all the crap up to the next number while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == ',') in.get(); in >> item.y(); if (!in.good()) return in; // eat all the crap up to the next number while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == ',') in.get(); in >> item.z(); if (!in.good()) return in; // eat all the crap up to the ')' while (in.peek() == ' ' || in.peek() == '\t') in.get(); // there should be a ')' if not then this is an error if (in.get() != ')') in.setstate(in.rdstate() | std::ios::failbit); return in; } // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------- class point { /*! INITIAL VALUE The initial value of this object is defined by its constructor. CONVENTION - x_ == x() - y_ == y() !*/ public: point ( ) : x_(0), y_(0) {} point ( long x__, long y__ ) { x_ = x__; y_ = y__; } point ( const point& p ) { x_ = p.x_; y_ = p.y_; } template <typename T> point ( const vector<T>& v ) : x_(static_cast<long>(v.x()+0.5)), y_(static_cast<long>(v.y()+0.5)) {} long x ( ) const { return x_; } long y ( ) const { return y_; } long& x ( ) { return x_; } long& y ( ) { return y_; } const point operator+ ( const point& rhs ) const { return point(x()+rhs.x(), y()+rhs.y()); } const point operator- ( const point& rhs ) const { return point(x()-rhs.x(), y()-rhs.y()); } point& operator= ( const point& p ) { x_ = p.x_; y_ = p.y_; return *this; } point& operator+= ( const point& rhs ) { x_ += rhs.x_; y_ += rhs.y_; return *this; } point& operator-= ( const point& rhs ) { x_ -= rhs.x_; y_ -= rhs.y_; return *this; } bool operator== ( const point& p ) const { return p.x_ == x_ && p.y_ == y_; } bool operator!= ( const point& p ) const { return p.x_ != x_ || p.y_ != y_; } private: long x_; long y_; }; // ---------------------------------------------------------------------------------------- inline void serialize ( const point& item, std::ostream& out ) { try { serialize(item.x(),out); serialize(item.y(),out); } catch (serialization_error& e) { throw serialization_error(e.info + "\n while serializing an object of type point"); } } inline void deserialize ( point& item, std::istream& in ) { try { deserialize(item.x(),in); deserialize(item.y(),in); } catch (serialization_error& e) { throw serialization_error(e.info + "\n while deserializing an object of type point"); } } inline std::ostream& operator<< ( std::ostream& out, const point& item ) { out << "(" << item.x() << ", " << item.y() << ")"; return out; } inline std::istream& operator>>( std::istream& in, point& item ) { // eat all the crap up to the '(' while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\r' || in.peek() == '\n') in.get(); // there should be a '(' if not then this is an error if (in.get() != '(') { in.setstate(in.rdstate() | std::ios::failbit); return in; } // eat all the crap up to the first number while (in.peek() == ' ' || in.peek() == '\t') in.get(); bool is_negative = false; if (in.peek() == '-') { in.get(); is_negative = true; } // read in the number and store it in item.x() item.x() = 0; while (in.peek() >= '0' && in.peek() <= '9') { long temp = in.get()-'0'; item.x() = item.x()*10 + temp; } if (is_negative) item.x() *= -1; if (!in.good()) return in; // eat all the crap up to the next number while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == ',') in.get(); is_negative = false; if (in.peek() == '-') { in.get(); is_negative = true; } // read in the number and store it in item.y() item.y() = 0; while (in.peek() >= '0' && in.peek() <= '9') { long temp = in.get()-'0'; item.y() = item.y()*10 + temp; } if (is_negative) item.y() *= -1; if (!in.good()) return in; // eat all the crap up to the ')' while (in.peek() == ' ' || in.peek() == '\t') in.get(); // there should be a ')' if not then this is an error if (in.get() != ')') in.setstate(in.rdstate() | std::ios::failbit); return in; } // ---------------------------------------------------------------------------------------- template <typename T> vector<T>::vector ( const point& p ) : x_value(p.x()), y_value(p.y()), z_value(0) {} // ---------------------------------------------------------------------------------------- } namespace std { /*! Define std::less<vector<T> > so that you can use vectors in the associative containers. !*/ template<typename T> struct less<dlib::vector<T> > : public binary_function<dlib::vector<T> ,dlib::vector<T> ,bool> { inline bool operator() (const dlib::vector<T> & a, const dlib::vector<T> & 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<point> so that you can use points in the associative containers. !*/ template<> struct less<dlib::point> : public binary_function<dlib::point,dlib::point,bool> { inline bool operator() (const dlib::point& a, const dlib::point& 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_H_