// 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_