Commit aec7c847 authored by Davis King's avatar Davis King

Cleaned up the vector and point classes. Now there is only one class, the vector,

class and it is capable of representing everything the old vector and point
class could.

--HG--
extra : convert_revision : svn%3Afdd8eb12-d10e-0410-9acb-85c331704f74/trunk%402727
parent 3fc0a290
......@@ -70,17 +70,6 @@ namespace dlib
{
}
template <typename T>
rectangle (
const vector<T>& v
) :
l(static_cast<long>(v.x()+0.5)),
t(static_cast<long>(v.y()+0.5)),
r(static_cast<long>(v.x()+0.5)),
b(static_cast<long>(v.y()+0.5))
{
}
rectangle (
const point& p1,
const point& p2
......@@ -89,15 +78,6 @@ namespace dlib
*this = rectangle(p1) + rectangle(p2);
}
template <typename T>
rectangle (
const vector<T>& v1,
const vector<T>& v2
)
{
*this = rectangle(v1) + rectangle(v2);
}
rectangle (
) :
l(0),
......@@ -228,6 +208,14 @@ namespace dlib
return (rect + *this == *this);
}
rectangle& operator+= (
const point& p
)
{
*this = *this + rectangle(p);
return *this;
}
rectangle& operator+= (
const rectangle& rect
)
......
......@@ -90,18 +90,6 @@ namespace dlib
- #bottom() == p.y()
!*/
template <typename T>
rectangle (
const vector<T>& v
);
/*!
ensures
- #left() == static_cast<long>(floor(v.x()+0.5))
- #top() == static_cast<long>(floor(v.y()+0.5))
- #right() == static_cast<long>(floor(v.x()+0.5))
- #bottom() == static_cast<long>(floor(v.y()+0.5))
!*/
rectangle (
const point& p1,
const point& p2
......@@ -111,16 +99,6 @@ namespace dlib
- #*this == rectangle(p1) + rectangle(p2)
!*/
template <typename T>
rectangle (
const vector<T>& v1,
const vector<T>& v2
);
/*!
ensures
- #*this == rectangle(v1) + rectangle(v2)
!*/
long left (
) const;
/*!
......
......@@ -13,12 +13,17 @@
namespace dlib
{
class point;
template <
typename T
typename T,
long NR = 3
>
class vector
class vector;
// ----------------------------------------------------------------------------------------
template <typename T>
class vector<T,3>
{
/*!
INITIAL VALUE
......@@ -38,11 +43,12 @@ namespace dlib
typedef T type;
vector (
) :
x_value(0.0),
y_value(0.0),
z_value(0.0)
{}
)
{
x() = 0;
y() = 0;
z() = 0;
}
// ---------------------------------------
......@@ -50,35 +56,506 @@ namespace dlib
const T _x,
const T _y,
const T _z
) :
x_value(_x),
y_value(_y),
z_value(_z)
{}
)
{
x() = _x;
y() = _y;
z() = _z;
}
// ---------------------------------------
vector (
const vector& item
)
{
x() = item.x();
y() = item.y();
z() = item.z();
}
// ---------------------------------------
template <typename U>
vector (
const vector<U,2>& item
)
{
// Do this so that we get the appropriate rounding depending on the relative
// type of T and U.
vector<T,2> temp(item);
x() = temp.x();
y() = temp.y();
z() = 0;
}
// ---------------------------------------
vector (
const vector<T,2>& item
)
{
x() = item.x();
y() = item.y();
z() = 0;
}
// ---------------------------------------
template <typename U>
vector (
const vector<U,3>& item
)
{
(*this) = item;
}
// ---------------------------------------
template <typename EXP>
vector ( const matrix_exp<EXP>& m)
{
(*this) = m;
}
// ---------------------------------------
template <typename EXP>
const typename enable_if_c<std::numeric_limits<T>::is_integer == true &&
std::numeric_limits<typename EXP::type>::is_integer == false, vector>::type&
operator = (
const matrix_exp<EXP>& m
)
{
// you can only assign vectors with 3 elements to a dlib::vector<T,3> object
COMPILE_TIME_ASSERT(EXP::NR*EXP::NC == 3 || EXP::NR*EXP::NC == 0);
// 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() = std::floor(m(0)+0.5);
y() = std::floor(m(1)+0.5);
z() = std::floor(m(2)+0.5);
return *this;
}
template <typename EXP>
const typename disable_if_c<std::numeric_limits<T>::is_integer == true &&
std::numeric_limits<typename EXP::type>::is_integer == false, vector>::type&
operator = (
const matrix_exp<EXP>& m
)
{
// you can only assign vectors with 3 elements to a dlib::vector<T,3> object
COMPILE_TIME_ASSERT(EXP::NR*EXP::NC == 3 || EXP::NR*EXP::NC == 0);
// 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() = m(0);
y() = m(1);
z() = m(2);
return *this;
}
// ---------------------------------------
template <typename U>
const typename enable_if_c<std::numeric_limits<T>::is_integer == true && std::numeric_limits<U>::is_integer == false, vector>::type&
operator = (
const vector<U,3>& item
)
{
x() = static_cast<T>(std::floor(item.x() + 0.5));
y() = static_cast<T>(std::floor(item.y() + 0.5));
z() = static_cast<T>(std::floor(item.z() + 0.5));
return *this;
}
template <typename U>
const typename disable_if_c<std::numeric_limits<T>::is_integer == true && std::numeric_limits<U>::is_integer == false, vector>::type&
operator = (
const vector<U,3>& item
)
{
x() = static_cast<T>(item.x());
y() = static_cast<T>(item.y());
z() = static_cast<T>(item.z());
return *this;
}
// ---------------------------------------
vector& operator= (
const vector& item
)
{
x() = item.x();
y() = item.y();
z() = item.z();
return *this;
}
// ---------------------------------------
T length(
) const
{
return (T)std::sqrt((double)(x()*x() + y()*y() + z()*z()));
}
// ---------------------------------------
vector normalize (
) const
{
T tmp = (T)std::sqrt((double)(x()*x() + y()*y() + z()*z()));
return vector ( x()/tmp,
y()/tmp,
z()/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()*rhs.x() + y()*rhs.y() + z()*rhs.z();
}
// ---------------------------------------
vector cross (
const vector& rhs
) const
{
return vector (
y()*rhs.z() - z()*rhs.y(),
z()*rhs.x() - x()*rhs.z(),
x()*rhs.y() - y()*rhs.x()
);
}
// ---------------------------------------
vector& operator += (
const vector& rhs
)
{
x() += rhs.x();
y() += rhs.y();
z() += rhs.z();
return *this;
}
// ---------------------------------------
vector& operator -= (
const vector& rhs
)
{
x() -= rhs.x();
y() -= rhs.y();
z() -= rhs.z();
return *this;
}
// ---------------------------------------
vector& operator /= (
const T& rhs
)
{
x() /= rhs;
y() /= rhs;
z() /= rhs;
return *this;
}
// ---------------------------------------
vector& operator *= (
const T& rhs
)
{
x() *= rhs;
y() *= rhs;
z() *= rhs;
return *this;
}
// ---------------------------------------
vector operator + (
const vector& rhs
) const
{
return vector(x()+rhs.x(), y()+rhs.y(), z()+rhs.z());
}
// ---------------------------------------
vector operator - (
const vector& rhs
) const
{
return vector(x()-rhs.x(), y()-rhs.y(), z()-rhs.z());
}
// ---------------------------------------
vector operator / (
const T& val
) const
{
return vector(x()/val, y()/val, z()/val);
}
// ---------------------------------------
template <typename U, long NR2>
bool operator== (
const vector<U,NR2>& rhs
) const
{
return x()==rhs.x() && y()==rhs.y() && z()==rhs.z();
}
// ---------------------------------------
template <typename U, long NR2>
bool operator!= (
const vector<U,NR2>& rhs
) const
{
return !(*this == rhs);
}
// ---------------------------------------
template <long NRm, long NC, typename MM, typename l>
operator matrix<T,NRm, NC, MM,l> (
) const
{
matrix<T,NRm, NC, MM,l> m(3,1);
m(0) = x();
m(1) = y();
m(2) = z();
return m;
}
// ---------------------------------------
void swap (
vector& item
)
{
dlib::exchange(x_value, item.x_value);
dlib::exchange(y_value, item.y_value);
dlib::exchange(z_value, item.z_value);
}
// ---------------------------------------
private:
T x_value;
T y_value;
T z_value;
};
// ----------------------------------------------------------------------------------------
template <typename T>
class vector<T,2>
{
/*!
INITIAL VALUE
- x_value == 0
- y_value == 0
CONVENTION
- x_value == x()
- y_value == y()
- z() == 0
!*/
public:
typedef T type;
vector (
const vector& v
) :
x_value(v.x_value),
y_value(v.y_value),
z_value(v.z_value)
{}
)
{
x() = 0;
y() = 0;
}
// ---------------------------------------
inline vector (
const point& p
);
vector (
const T _x,
const T _y
)
{
x() = _x;
y() = _y;
}
// ---------------------------------------
template <typename U>
vector (
const vector<U,3>& item
)
{
// Do this so that we get the appropriate rounding depending on the relative
// type of T and U.
vector<T,3> temp(item);
x() = temp.x();
y() = temp.y();
}
// ---------------------------------------
vector (
const vector& item
)
{
x() = item.x();
y() = item.y();
}
// ---------------------------------------
vector (
const vector<T,3>& item
)
{
x() = item.x();
y() = item.y();
}
// ---------------------------------------
template <typename U>
vector (
const vector<U,2>& item
)
{
(*this) = item;
}
// ---------------------------------------
template <typename EXP>
vector ( const matrix_exp<EXP>& m)
{
(*this) = m;
}
// ---------------------------------------
template <typename EXP>
const typename enable_if_c<std::numeric_limits<T>::is_integer == true &&
std::numeric_limits<typename EXP::type>::is_integer == false, vector>::type&
operator = (
const matrix_exp<EXP>& m
)
{
// you can only assign vectors with 2 elements to a dlib::vector<T,2> object
COMPILE_TIME_ASSERT(EXP::NR*EXP::NC == 2 || EXP::NR*EXP::NC == 0);
// make sure requires clause is not broken
DLIB_ASSERT((m.nr() == 1 || m.nc() == 1) && (m.size() == 2),
"\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() = std::floor(m(0)+0.5);
y() = std::floor(m(1)+0.5);
return *this;
}
template <typename EXP>
vector ( const matrix_exp<EXP>& m)
const typename disable_if_c<std::numeric_limits<T>::is_integer == true &&
std::numeric_limits<typename EXP::type>::is_integer == false, vector>::type&
operator = (
const matrix_exp<EXP>& m
)
{
// you can only assign vectors with 2 elements to a dlib::vector<T,2> object
COMPILE_TIME_ASSERT(EXP::NR*EXP::NC == 2 || EXP::NR*EXP::NC == 0);
// make sure requires clause is not broken
DLIB_ASSERT((m.nr() == 1 || m.nc() == 1) && m.size() == 3,
DLIB_ASSERT((m.nr() == 1 || m.nc() == 1) && (m.size() == 2),
"\t vector(const matrix_exp& m)"
<< "\n\t the given matrix is of the wrong size"
<< "\n\t m.nr(): " << m.nr()
......@@ -86,32 +563,53 @@ namespace dlib
<< "\n\t m.size(): " << m.size()
<< "\n\t this: " << this
);
x_value = m(0);
y_value = m(1);
z_value = m(2);
x() = m(0);
y() = m(1);
return *this;
}
template <long NR, long NC, typename MM>
operator matrix<T,NR, NC, MM> () const
// ---------------------------------------
template <typename U>
const typename enable_if_c<std::numeric_limits<T>::is_integer == true && std::numeric_limits<U>::is_integer == false, vector>::type&
operator = (
const vector<U,2>& item
)
{
matrix<T,3,1> m;
m(0) = x_value;
m(1) = y_value;
m(2) = z_value;
return m;
x() = static_cast<T>(std::floor(item.x() + 0.5));
y() = static_cast<T>(std::floor(item.y() + 0.5));
return *this;
}
template <typename U>
const typename disable_if_c<std::numeric_limits<T>::is_integer == true && std::numeric_limits<U>::is_integer == false, vector>::type&
operator = (
const vector<U,2>& item
)
{
x() = static_cast<T>(item.x());
y() = static_cast<T>(item.y());
return *this;
}
// ---------------------------------------
~vector (
){}
vector& operator= (
const vector& item
)
{
x() = item.x();
y() = item.y();
return *this;
}
// ---------------------------------------
T length(
) const
{
return (T)std::sqrt((double)(x_value*x_value + y_value*y_value + z_value*z_value));
return (T)std::sqrt((double)(x()*x() + y()*y()));
}
// ---------------------------------------
......@@ -119,11 +617,10 @@ namespace dlib
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 tmp = (T)std::sqrt((double)(x()*x() + y()*y()));
return vector ( x()/tmp,
y()/tmp
);
}
// ---------------------------------------
......@@ -131,7 +628,7 @@ namespace dlib
T& x (
)
{
return x_value;
return x_value;
}
// ---------------------------------------
......@@ -139,15 +636,7 @@ namespace dlib
T& y (
)
{
return y_value;
}
// ---------------------------------------
T& z (
)
{
return z_value;
return y_value;
}
// ---------------------------------------
......@@ -155,7 +644,7 @@ namespace dlib
const T& x (
) const
{
return x_value;
return x_value;
}
// ---------------------------------------
......@@ -163,15 +652,15 @@ namespace dlib
const T& y (
) const
{
return y_value;
return y_value;
}
// ---------------------------------------
const T& z (
const T z (
) const
{
return z_value;
{
return 0;
}
// ---------------------------------------
......@@ -180,130 +669,107 @@ namespace dlib
const vector& rhs
) const
{
return x_value*rhs.x_value + y_value*rhs.y_value + z_value*rhs.z_value;
return x()*rhs.x() + y()*rhs.y();
}
// ---------------------------------------
vector cross (
vector& operator += (
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
);
x() += rhs.x();
y() += rhs.y();
return *this;
}
// ---------------------------------------
vector operator+ (
vector& operator -= (
const vector& rhs
) const
)
{
return vector (
x_value+rhs.x_value,
y_value+rhs.y_value,
z_value+rhs.z_value
);
x() -= rhs.x();
y() -= rhs.y();
return *this;
}
// ---------------------------------------
vector operator- (
const vector& rhs
) const
vector& operator /= (
const T& rhs
)
{
return vector (
x_value-rhs.x_value,
y_value-rhs.y_value,
z_value-rhs.z_value
);
x() /= rhs;
y() /= rhs;
return *this;
}
// ---------------------------------------
vector& operator= (
const vector& rhs
vector& operator *= (
const T& rhs
)
{
x_value = rhs.x_value;
y_value = rhs.y_value;
z_value = rhs.z_value;
x() *= rhs;
y() *= rhs;
return *this;
}
// ---------------------------------------
vector operator/ (
const T rhs
vector operator + (
const vector& rhs
) const
{
return vector (
x_value/rhs,
y_value/rhs,
z_value/rhs
);
return vector(x()+rhs.x(), y()+rhs.y());
}
// ---------------------------------------
vector& operator += (
vector operator - (
const vector& rhs
)
) const
{
x_value += rhs.x_value;
y_value += rhs.y_value;
z_value += rhs.z_value;
return *this;
return vector(x()-rhs.x(), y()-rhs.y());
}
// ---------------------------------------
vector& operator -= (
const vector& rhs
)
vector operator / (
const T& val
) const
{
x_value -= rhs.x_value;
y_value -= rhs.y_value;
z_value -= rhs.z_value;
return *this;
return vector(x()/val, y()/val);
}
// ---------------------------------------
vector& operator *= (
const T rhs
)
template <typename U, long NR2>
bool operator== (
const vector<U,NR2>& rhs
) const
{
x_value *= rhs;
y_value *= rhs;
z_value *= rhs;
return *this;
return x()==rhs.x() && y()==rhs.y() && z()==rhs.z();
}
// ---------------------------------------
vector& operator /= (
const T rhs
)
bool operator== (
const vector& rhs
) const
{
x_value /= rhs;
y_value /= rhs;
z_value /= rhs;
return *this;
return x()==rhs.x() && y()==rhs.y();
}
// ---------------------------------------
bool operator== (
const vector& rhs
template <typename U, long NR2>
bool operator!= (
const vector<U,NR2>& rhs
) const
{
return (x_value == rhs.x_value &&
y_value == rhs.y_value &&
z_value == rhs.z_value );
return !(*this == rhs);
}
// ---------------------------------------
......@@ -312,7 +778,19 @@ namespace dlib
const vector& rhs
) const
{
return !((*this) == rhs);
return !(*this == rhs);
}
// ---------------------------------------
template <long NRm, long NC, typename MM, typename l>
operator matrix<T,NRm, NC, MM,l> (
) const
{
matrix<T,NRm, NC, MM,l> m(2,1);
m(0) = x();
m(1) = y();
return m;
}
// ---------------------------------------
......@@ -321,58 +799,89 @@ namespace dlib
vector& item
)
{
exchange(x_value,item.x_value);
exchange(y_value,item.y_value);
exchange(z_value,item.z_value);
dlib::exchange(x_value, item.x_value);
dlib::exchange(y_value, item.y_value);
}
// ---------------------------------------
private:
T x_value;
T y_value;
T z_value;
vector<T,3> cross (
const vector<T,3>& rhs
) const
{
return vector<T,3> (
y()*rhs.z(),
- x()*rhs.z(),
x()*rhs.y() - y()*rhs.x()
);
}
// ---------------------------------------
private:
T x_value;
T y_value;
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template<typename T, typename U>
inline vector<T> operator* (
const vector<T> & lhs,
const U rhs
template <typename T, typename U>
inline const vector<T,2> operator* (
const vector<T,2>& v,
const U& s
)
{
return vector<T,2>(v.x()*s, v.y()*s);
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline const vector<T,2> operator* (
const U& s,
const vector<T,2>& v
)
{
return vector<T,2>(v.x()*s, v.y()*s);
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline const vector<T,3> operator* (
const vector<T,3>& v,
const U& s
)
{
return vector<T> (
lhs.x()*rhs,
lhs.y()*rhs,
lhs.z()*rhs
);
return vector<T,3>(v.x()*s, v.y()*s, v.z()*s);
}
// ----------------------------------------------------------------------------------------
template<typename T, typename U>
inline vector<T> operator* (
const U lhs,
const vector<T> & rhs
) { return rhs*lhs; }
template <typename T, typename U>
inline const vector<T,3> operator* (
const U& s,
const vector<T,3>& v
)
{
return vector<T,3>(v.x()*s, v.y()*s, v.z()*s);
}
// ----------------------------------------------------------------------------------------
template<typename T>
template<typename T, long NR>
inline void swap (
vector<T> & a,
vector<T> & b
vector<T,NR> & a,
vector<T,NR> & b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
template<typename T>
inline void serialize (
const vector<T> & item,
const vector<T,3>& item,
std::ostream& out
)
{
......@@ -382,7 +891,7 @@ namespace dlib
serialize(item.y(),out);
serialize(item.z(),out);
}
catch (serialization_error e)
catch (serialization_error& e)
{
throw serialization_error(e.info + "\n while serializing object of type vector");
}
......@@ -390,7 +899,7 @@ namespace dlib
template<typename T>
inline void deserialize (
vector<T> & item,
vector<T,3>& item,
std::istream& in
)
{
......@@ -400,7 +909,7 @@ namespace dlib
deserialize(item.y(),in);
deserialize(item.z(),in);
}
catch (serialization_error e)
catch (serialization_error& e)
{
item.x() = 0;
item.y() = 0;
......@@ -409,12 +918,50 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
template<typename T>
inline void serialize (
const vector<T,2>& 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 object of type vector");
}
}
template<typename T>
inline void deserialize (
vector<T,2>& item,
std::istream& in
)
{
try
{
deserialize(item.x(),in);
deserialize(item.y(),in);
}
catch (serialization_error& e)
{
item.x() = 0;
item.y() = 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
const vector<T,3>& item
)
{
out << "(" << item.x() << ", " << item.y() << ", " << item.z() << ")";
......@@ -424,7 +971,7 @@ namespace dlib
template<typename T>
std::istream& operator>>(
std::istream& in,
vector<T>& item
vector<T,3>& item
)
{
......@@ -474,164 +1021,25 @@ namespace dlib
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
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<< (
template<typename T>
std::ostream& operator<< (
std::ostream& out,
const point& item
)
const vector<T,2>& item
)
{
out << "(" << item.x() << ", " << item.y() << ")";
return out;
}
inline std::istream& operator>>(
template<typename T>
std::istream& operator>>(
std::istream& in,
point& item
)
vector<T,2>& item
)
{
// eat all the crap up to the '('
while (in.peek() == ' ' || in.peek() == '\t' || in.peek() == '\r' || in.peek() == '\n')
in.get();
......@@ -646,23 +1054,7 @@ namespace dlib
// 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;
in >> item.x();
if (!in.good())
return in;
......@@ -670,24 +1062,7 @@ namespace dlib
// 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;
in >> item.y();
if (!in.good())
return in;
......@@ -704,14 +1079,7 @@ namespace dlib
// ----------------------------------------------------------------------------------------
template <typename T>
vector<T>::vector (
const point& p
) :
x_value(p.x()),
y_value(p.y()),
z_value(0)
{}
typedef vector<long,2> point;
// ----------------------------------------------------------------------------------------
......@@ -720,12 +1088,12 @@ namespace dlib
namespace std
{
/*!
Define std::less<vector<T> > so that you can use vectors in the associative containers.
Define std::less<vector<T,3> > 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>
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> & a, const dlib::vector<T> & b) const
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;
......@@ -738,12 +1106,12 @@ namespace std
};
/*!
Define std::less<point> so that you can use points in the associative containers.
Define std::less<vector<T,2> > so that you can use vector<T,2>s in the associative containers.
!*/
template<>
struct less<dlib::point> : public binary_function<dlib::point,dlib::point,bool>
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::point& a, const dlib::point& b) const
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;
......
......@@ -10,17 +10,19 @@
namespace dlib
{
class point;
template <
typename T
typename T,
long NR = 3
>
class vector
{
/*!
REQUIREMENTS ON T
T should be some object that provides an interface that is
compatible with double, float and the like.
compatible with double, float, int, long and the like.
REQUIREMENTS ON NR
NR == 3 || NR == 2
INITIAL VALUE
x() == 0
......@@ -28,11 +30,10 @@ namespace dlib
z() == 0
WHAT THIS OBJECT REPRESENTS
This object represents a three dimensional vector.
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.
THREAD SAFETY
Note that the vector object is not allowed to be reference counted.
This is to ensure a minimum amount of thread safety.
!*/
public:
......@@ -52,33 +53,53 @@ namespace dlib
const T _z
);
/*!
requires
- NR == 3
ensures
- #*this properly initialized
- #x() == _x
- #y() == _y
- #z() == _z
!*/
vector (
const point& p
const T _x,
const T _y
);
/*!
requires
- NR == 2
ensures
- #*this properly initialized
- #x() == p.x()
- #y() == p.y()
- #z() == 0
- #x() == _x
- #y() == _y
- #z() == 0
!*/
template <typename U, long NRv>
vector (
const vector& v
const vector<U,NRv>& v
);
/*!
ensures
- #*this properly initialized
- #x() == v.x()
- #y() == v.y()
- #z() == v.z()
- 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>
......@@ -87,27 +108,40 @@ namespace dlib
);
/*!
requires
- m.size() == 3
- m.size() == NR
- m.nr() == 1 || m.nc() == 1 (i.e. m must be a row or column matrix)
ensures
- #x() == m(0)
- #y() == m(1)
- #z() == m(2)
- 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
!*/
template <long NR, long NC, typename MM>
operator matrix<T,NR, NC, MM> (
operator matrix<T> (
) const;
/*!
ensures
- provides automatic conversions from a vector object to a column
matrix
- returns a matrix object m such that:
- m.nr() == 3
- m.nr() == NR
- m.nc() == 1
- m(0) == x()
- m(1) == y()
- m(2) == z()
- if (NR == 3) then
- m(2) == z()
!*/
~vector (
......@@ -142,6 +176,8 @@ namespace dlib
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
!*/
......@@ -164,7 +200,11 @@ namespace dlib
) const;
/*!
ensures
- returns a const reference to the z component of the vector
- 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 (
......@@ -175,7 +215,7 @@ namespace dlib
- returns the result of the dot product between *this and rhs
!*/
vector cross (
vector<T,3> cross (
const vector& rhs
) const;
/*!
......@@ -261,8 +301,9 @@ namespace dlib
- returns #*this
!*/
template <typename U, long NR2>
bool operator== (
const vector& rhs
const vector<U,NR2>& rhs
) const;
/*!
ensures
......@@ -272,8 +313,9 @@ namespace dlib
- returns false
!*/
template <typename U, long NR2>
bool operator!= (
const vector& rhs
const vector<U,NR2>& rhs
) const;
/*!
ensures
......@@ -290,47 +332,27 @@ namespace dlib
};
template<typename T, typename U>
vector<T> operator* (
const vector<T> & lhs,
const U rhs
);
/*!
ensures
- returns the result of multiplying the scalar rhs by lhs
!*/
template<typename T, typename U>
vector<T> operator* (
const U lhs,
const vector<T> & rhs
);
/*!
ensures
- returns the result of multiplying the scalar lhs by rhs
!*/
template<typename T>
template<typename T, long NR>
inline void swap (
vector<T> & a,
vector<T> & b
vector<T,NR> & a,
vector<T,NR> & b
) { a.swap(b); }
/*!
provides a global swap function
!*/
template<typename T>
template<typename T, long NR>
void serialize (
const vector<T> & item,
const vector<T,NR>& item,
std::ostream& out
);
/*!
provides serialization support
!*/
template<typename T>
template<typename T, long NR>
void deserialize (
vector<T> & item,
vector<T,NR>& item,
std::istream& in
);
/*!
......@@ -340,7 +362,7 @@ namespace dlib
template<typename T>
std::ostream& operator<< (
std::ostream& out,
const vector<T>& item
const vector<T,3>& item
);
/*!
ensures
......@@ -350,7 +372,7 @@ namespace dlib
template<typename T>
std::istream& operator>>(
std::istream& in,
vector<T>& item
vector<T,3>& item
);
/*!
ensures
......@@ -358,190 +380,35 @@ namespace dlib
The data in the input stream should be of the form (x, y, z)
!*/
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
class point
{
/*!
INITIAL VALUE
The initial value of this object is defined by its constructor.
WHAT THIS OBJECT REPRESENTS
This object represents a point inside a Cartesian coordinate system.
!*/
public:
point (
);
/*!
ensures
- #x() == 0
- #y() == 0
!*/
point (
long x_
long y_
);
/*!
ensures
- #x() == x_
- #y() == y_
!*/
point (
const point& p
);
/*!
ensures
- #x() == p.x()
- #y() == p.y()
!*/
template <typename T>
point (
const vector<T>& v
);
/*!
ensures
- #x() == floor(v.x()+0.5)
- #y() == floor(v.y()+0.5)
!*/
long x (
) const;
/*!
ensures
- returns the x coordinate of this point
!*/
long y (
) const;
/*!
ensures
- returns the y coordinate of this point
!*/
long& x (
);
/*!
ensures
- returns a non-const reference to the x coordinate of
this point
!*/
long& y (
);
/*!
ensures
- returns a non-const reference to the y coordinate of
this point
!*/
const point operator+ (
const point& rhs
) const;
/*!
ensures
- returns point(x()+rhs.x(), y()+rhs.y())
!*/
const point operator- (
const point& rhs
) const;
/*!
ensures
- returns point(x()-rhs.x(), y()-rhs.y())
!*/
point& operator= (
const point& p
);
/*!
ensures
- #x() == p.x()
- #y() == p.y()
- returns #*this
!*/
point& operator+= (
const point& rhs
);
/*!
ensures
- #*this = *this + rhs
- returns #*this
!*/
point& operator-= (
const point& rhs
);
/*!
ensures
- #*this = *this - rhs
- returns #*this
!*/
bool operator== (
const point& p
) const;
/*!
ensures
- if (x() == p.x() && y() == p.y()) then
- returns true
- else
- returns false
!*/
bool operator!= (
const point& p
) const;
/*!
ensures
- returns !(*this == p)
!*/
};
// ----------------------------------------------------------------------------------------
void serialize (
const point& item,
std::ostream& out
);
/*!
provides serialization support
!*/
void deserialize (
point& item,
std::istream& in
);
/*!
provides deserialization support
!*/
template<typename T>
std::ostream& operator<< (
std::ostream& out,
const point& item
const vector<T,2>& item
);
/*!
ensures
- writes item to out in the form "(x, y)"
!*/
template<typename T>
std::istream& operator>>(
std::istream& in,
point& item
vector<T,2>& item
);
/*!
ensures
- reads a point from the input stream in and stores it in #item.
- 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;
// ----------------------------------------------------------------------------------------
}
......@@ -549,12 +416,12 @@ namespace dlib
namespace std
{
/*!
Define std::less<vector<T> > so that you can use vectors in the associative containers.
Define std::less<vector<T,3> > 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>
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> & a, const dlib::vector<T> & b) const
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;
......@@ -567,12 +434,12 @@ namespace std
};
/*!
Define std::less<point> so that you can use points in the associative containers.
Define std::less<vector<T,2> > so that you can use vector<T,2>s in the associative containers.
!*/
template<>
struct less<dlib::point> : public binary_function<dlib::point,dlib::point,bool>
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::point& a, const dlib::point& b) const
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;
......
......@@ -129,6 +129,65 @@ namespace
DLIB_CASSERT(v1.y() == 6,"");
DLIB_CASSERT(v1.z() == 7,"");
{
dlib::vector<double,2> vd2;
dlib::vector<double,3> vd3;
dlib::vector<long,2> vl2;
dlib::vector<long,3> vl3;
vd2.x() = 2.3;
vd2.y() = 4.7;
vd3.z() = 9;
vd3 = vd2;
vl2 = vd3;
vl3 = vd3;
DLIB_CASSERT(vd2.z() == 0,"");
DLIB_CASSERT(vd3.z() == 0,"");
DLIB_CASSERT(vl2.z() == 0,"");
DLIB_CASSERT(vl3.z() == 0,"");
DLIB_CASSERT(vl2.x() == 2,"");
DLIB_CASSERT(vl3.x() == 2,"");
DLIB_CASSERT(vl2.y() == 5,"");
DLIB_CASSERT(vl3.y() == 5,"");
DLIB_CASSERT(abs(vd2.cross(vd3).dot(vd2)) < 1e-7,"");
DLIB_CASSERT(abs(vd3.cross(vd2).dot(vd2)) < 1e-7,"");
DLIB_CASSERT(abs(vd2.cross(vd3).dot(vd3)) < 1e-7,"");
DLIB_CASSERT(abs(vd3.cross(vd2).dot(vd3)) < 1e-7,"");
DLIB_CASSERT(abs(vl2.cross(vl3).dot(vl2)) == 0,"");
DLIB_CASSERT(abs(vl3.cross(vl2).dot(vl2)) == 0,"");
DLIB_CASSERT(abs(vl2.cross(vl3).dot(vl3)) == 0,"");
DLIB_CASSERT(abs(vl3.cross(vl2).dot(vl3)) == 0,"");
DLIB_CASSERT((vd2-vd3).length() < 1e-7,"");
DLIB_CASSERT(vl2 == vl3,"");
vl2.x() = 0;
vl2.y() = 0;
vl3 = vl2;
vl2.x() = 4;
vl3.y() = 3;
DLIB_CASSERT(vl2.cross(vl3).length() == 12,"");
DLIB_CASSERT(vl3.cross(vl2).length() == 12,"");
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment