477 lines
12 KiB
C++
477 lines
12 KiB
C++
// 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
|
|
!*/
|
|
|
|
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;
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
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_
|
|
|