AshanGimhana's picture
Upload folder using huggingface_hub
9375c9a verified
// Copyright (C) 2003 Davis E. King ([email protected])
// 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"
#include <limits>
#include <array>
#if defined(_MSC_VER) && _MSC_VER < 1400
#pragma warning(push)
// Despite my efforts to disabuse visual studio of its usual nonsense I can't find a
// way to make this warning go away without just disabling it. This is the warning:
// dlib\geometry\vector.h(129) : warning C4805: '==' : unsafe mix of type 'std::numeric_limits<_Ty>::is_integer' and type 'bool' in operation
//
#pragma warning(disable:4805)
#endif
namespace dlib
{
template <
typename T,
long NR = 3
>
class vector;
// ----------------------------------------------------------------------------------------
template <typename T, typename U, typename enabled = void>
struct vect_promote;
template <typename T, typename U, bool res = (sizeof(T) <= sizeof(U))>
struct largest_type
{
typedef T type;
};
template <typename T, typename U>
struct largest_type<T,U,true>
{
typedef U type;
};
template <typename T, typename U>
struct vect_promote<T,U, typename enable_if_c<std::numeric_limits<T>::is_integer == std::numeric_limits<U>::is_integer>::type>
{
// If both T and U are both either integral or non-integral then just
// use the biggest one
typedef typename largest_type<T,U>::type type;
};
template <typename T, typename U>
struct vect_promote<T,U, typename enable_if_c<std::numeric_limits<T>::is_integer != std::numeric_limits<U>::is_integer>::type>
{
typedef double type;
};
// ----------------------------------------------------------------------------------------
// This insanity here is to work around a bug in visual studio 8. These two rebind
// structures are actually declared at a few points in this file because just having the
// one declaration here isn't enough for visual studio. It takes the three spread around
// to avoid all its bugs.
template <typename T, long N>
struct vc_rebind
{
typedef vector<T,N> type;
};
template <typename T, typename U, long N>
struct vc_rebind_promote
{
typedef vector<typename vect_promote<T,U>::type,N> type;
};
// ----------------------------------------------------------------------------------------
template <typename T, typename U, typename enabled = void>
struct vector_assign_helper
{
template <long NR>
static void assign (
vector<T,2>& dest,
const vector<U,NR>& src
)
{
dest.x() = static_cast<T>(src.x());
dest.y() = static_cast<T>(src.y());
}
template <long NR>
static void assign (
vector<T,3>& dest,
const vector<U,NR>& src
)
{
dest.x() = static_cast<T>(src.x());
dest.y() = static_cast<T>(src.y());
dest.z() = static_cast<T>(src.z());
}
template <typename EXP>
static void assign (
vector<T,2>& dest,
const matrix_exp<EXP>& m
)
{
T x = static_cast<T>(m(0));
T y = static_cast<T>(m(1));
dest.x() = x;
dest.y() = y;
}
template <typename EXP>
static void assign (
vector<T,3>& dest,
const matrix_exp<EXP>& m
)
{
T x = static_cast<T>(m(0));
T y = static_cast<T>(m(1));
T z = static_cast<T>(m(2));
dest.x() = x;
dest.y() = y;
dest.z() = z;
}
};
// This is an overload for the case where you are converting from a floating point
// type to an integral type. These overloads make sure values are rounded to
// the nearest integral value.
template <typename T, typename U>
struct vector_assign_helper<T,U, typename enable_if_c<std::numeric_limits<T>::is_integer == true &&
std::numeric_limits<U>::is_integer == false>::type>
{
template <long NR>
static void assign (
vector<T,2>& dest,
const vector<U,NR>& src
)
{
dest.x() = static_cast<T>(std::floor(src.x() + 0.5));
dest.y() = static_cast<T>(std::floor(src.y() + 0.5));
}
template <long NR>
static void assign (
vector<T,3>& dest,
const vector<U,NR>& src
)
{
dest.x() = static_cast<T>(std::floor(src.x() + 0.5));
dest.y() = static_cast<T>(std::floor(src.y() + 0.5));
dest.z() = static_cast<T>(std::floor(src.z() + 0.5));
}
template <typename EXP>
static void assign (
vector<T,3>& dest,
const matrix_exp<EXP>& m
)
{
dest.x() = static_cast<T>(std::floor(m(0) + 0.5));
dest.y() = static_cast<T>(std::floor(m(1) + 0.5));
dest.z() = static_cast<T>(std::floor(m(2) + 0.5));
}
template <typename EXP>
static void assign (
vector<T,2>& dest,
const matrix_exp<EXP>& m
)
{
dest.x() = static_cast<T>(std::floor(m(0) + 0.5));
dest.y() = static_cast<T>(std::floor(m(1) + 0.5));
}
};
// ----------------------------------------------------------------------------------------
template <typename T>
class vector<T,3> : public matrix<T,3,1>
{
/*!
INITIAL VALUE
- x() == 0
- y() == 0
- z() == 0
CONVENTION
- (*this)(0) == x()
- (*this)(1) == y()
- (*this)(2) == z()
!*/
// This insanity here is to work around a bug in visual studio 8.
template <typename V, long N>
struct vc_rebind
{
typedef vector<V,N> type;
};
template <typename V, typename U, long N>
struct vc_rebind_promote
{
typedef vector<typename vect_promote<V,U>::type,N> type;
};
public:
typedef T type;
vector (
)
{
x() = 0;
y() = 0;
z() = 0;
}
// ---------------------------------------
vector (
const T _x,
const T _y,
const T _z
)
{
x() = _x;
y() = _y;
z() = _z;
}
// ---------------------------------------
vector (
const vector& item
) : matrix<T,3,1>(item)
{
}
// ---------------------------------------
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>
vector& 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
);
vector_assign_helper<T, typename EXP::type>::assign(*this, m);
return *this;
}
// ---------------------------------------
template <typename U, long N>
vector& operator = (
const vector<U,N>& item
)
{
vector_assign_helper<T,U>::assign(*this, item);
return *this;
}
// ---------------------------------------
vector& operator= (
const vector& item
)
{
x() = item.x();
y() = item.y();
z() = item.z();
return *this;
}
// ---------------------------------------
double length(
) const
{
return std::sqrt((double)(x()*x() + y()*y() + z()*z()));
}
// ---------------------------------------
double length_squared(
) const
{
return (double)(x()*x() + y()*y() + z()*z());
}
// ---------------------------------------
typename vc_rebind<double,3>::type normalize (
) const
{
const double tmp = std::sqrt((double)(x()*x() + y()*y() + z()*z()));
return vector<double,3> ( x()/tmp,
y()/tmp,
z()/tmp
);
}
// ---------------------------------------
T& x (
)
{
return (*this)(0);
}
// ---------------------------------------
T& y (
)
{
return (*this)(1);
}
// ---------------------------------------
T& z (
)
{
return (*this)(2);
}
// ---------------------------------------
const T& x (
) const
{
return (*this)(0);
}
// ---------------------------------------
const T& y (
) const
{
return (*this)(1);
}
// ---------------------------------------
const T& z (
) const
{
return (*this)(2);
}
// ---------------------------------------
T dot (
const vector& rhs
) const
{
return x()*rhs.x() + y()*rhs.y() + z()*rhs.z();
}
// ---------------------------------------
template <typename U, long N>
typename vect_promote<T,U>::type dot (
const vector<U,N>& rhs
) const
{
return x()*rhs.x() + y()*rhs.y() + z()*rhs.z();
}
// ---------------------------------------
template <typename U, long N>
typename vc_rebind_promote<T,U,3>::type cross (
const vector<U,N>& rhs
) const
{
typedef vector<typename vect_promote<T,U>::type,3> ret_type;
return ret_type (
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
{
return vector(-x(), -y(), -z());
}
// ---------------------------------------
template <typename U>
typename vc_rebind_promote<T,U,3>::type operator / (
const U& val
) const
{
typedef vector<typename vect_promote<T,U>::type,3> ret_type;
return ret_type(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);
}
// ---------------------------------------
void swap (
vector& item
)
{
dlib::exchange(x(), item.x());
dlib::exchange(y(), item.y());
dlib::exchange(z(), item.z());
}
// ---------------------------------------
};
// ----------------------------------------------------------------------------------------
template <typename T>
class vector<T,2> : public matrix<T,2,1>
{
/*!
INITIAL VALUE
- x() == 0
- y() == 0
CONVENTION
- (*this)(0) == x()
- (*this)(1) == y()
- z() == 0
!*/
// This insanity here is to work around a bug in visual studio 8.
template <typename V, long N>
struct vc_rebind
{
typedef vector<V,N> type;
};
template <typename V, typename U, long N>
struct vc_rebind_promote
{
typedef vector<typename vect_promote<V,U>::type,N> type;
};
public:
typedef T type;
vector (
)
{
x() = 0;
y() = 0;
}
// ---------------------------------------
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
) : matrix<T,2,1>(item)
{
}
// ---------------------------------------
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>
vector& 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
);
vector_assign_helper<T, typename EXP::type>::assign(*this, m);
return *this;
}
// ---------------------------------------
template <typename U, long N>
vector& operator = (
const vector<U,N>& item
)
{
vector_assign_helper<T,U>::assign(*this, item);
return *this;
}
// ---------------------------------------
vector& operator= (
const vector& item
)
{
x() = item.x();
y() = item.y();
return *this;
}
// ---------------------------------------
double length(
) const
{
return std::sqrt((double)(x()*x() + y()*y()));
}
// ---------------------------------------
double length_squared(
) const
{
return (double)(x()*x() + y()*y());
}
// ---------------------------------------
typename vc_rebind<double,2>::type normalize (
) const
{
const double tmp = std::sqrt((double)(x()*x() + y()*y()));
return vector<double,2> ( x()/tmp,
y()/tmp
);
}
// ---------------------------------------
T& x (
)
{
return (*this)(0);
}
// ---------------------------------------
T& y (
)
{
return (*this)(1);
}
// ---------------------------------------
const T& x (
) const
{
return (*this)(0);
}
// ---------------------------------------
const T& y (
) const
{
return (*this)(1);
}
// ---------------------------------------
const T z (
) const
{
return 0;
}
// ---------------------------------------
T dot (
const vector& rhs
) const
{
return x()*rhs.x() + y()*rhs.y();
}
// ---------------------------------------
template <typename U, long N>
typename vect_promote<T,U>::type dot (
const vector<U,N>& rhs
) const
{
return x()*rhs.x() + y()*rhs.y() + z()*rhs.z();
}
// ---------------------------------------
vector& operator += (
const vector& rhs
)
{
x() += rhs.x();
y() += rhs.y();
return *this;
}
// ---------------------------------------
vector& operator -= (
const vector& rhs
)
{
x() -= rhs.x();
y() -= rhs.y();
return *this;
}
// ---------------------------------------
vector& operator /= (
const T& rhs
)
{
x() /= rhs;
y() /= rhs;
return *this;
}
// ---------------------------------------
vector& operator *= (
const T& rhs
)
{
x() *= rhs;
y() *= rhs;
return *this;
}
// ---------------------------------------
vector operator - (
) const
{
return vector(-x(), -y());
}
// ---------------------------------------
template <typename U>
typename vc_rebind_promote<T,U,2>::type operator / (
const U& val
) const
{
typedef vector<typename vect_promote<T,U>::type,2> ret_type;
return ret_type(x()/val, y()/val);
}
// ---------------------------------------
template <typename U, long NR2>
bool operator== (
const vector<U,NR2>& rhs
) const
{
return x()==rhs.x() && y()==rhs.y() && z()==rhs.z();
}
// ---------------------------------------
bool operator== (
const vector& rhs
) const
{
return x()==rhs.x() && y()==rhs.y();
}
// ---------------------------------------
template <typename U, long NR2>
bool operator!= (
const vector<U,NR2>& rhs
) const
{
return !(*this == rhs);
}
// ---------------------------------------
bool operator!= (
const vector& rhs
) const
{
return !(*this == rhs);
}
// ---------------------------------------
void swap (
vector& item
)
{
dlib::exchange(x(), item.x());
dlib::exchange(y(), item.y());
}
// ---------------------------------------
template <typename U, long N>
typename vc_rebind_promote<T,U,3>::type cross (
const vector<U,N>& rhs
) const
{
typedef vector<typename vect_promote<T,U>::type,3> ret_type;
return ret_type (
y()*rhs.z(),
- x()*rhs.z(),
x()*rhs.y() - y()*rhs.x()
);
}
// ---------------------------------------
};
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline const typename vc_rebind_promote<T,U,2>::type operator+ (
const vector<T,2>& lhs,
const vector<U,2>& rhs
)
{
typedef typename vc_rebind_promote<T,U,2>::type ret_type;
return ret_type(lhs.x()+rhs.x(), lhs.y()+rhs.y());
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline const typename vc_rebind_promote<T,U,3>::type operator+ (
const vector<T,3>& lhs,
const vector<U,3>& rhs
)
{
typedef typename vc_rebind_promote<T,U,3>::type ret_type;
return ret_type(lhs.x()+rhs.x(), lhs.y()+rhs.y(), lhs.z()+rhs.z());
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline const typename vc_rebind_promote<T,U,3>::type operator+ (
const vector<T,2>& lhs,
const vector<U,3>& rhs
)
{
typedef typename vc_rebind_promote<T,U,3>::type ret_type;
return ret_type(lhs.x()+rhs.x(), lhs.y()+rhs.y(), rhs.z());
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline const typename vc_rebind_promote<T,U,3>::type operator+ (
const vector<T,3>& lhs,
const vector<U,2>& rhs
)
{
typedef typename vc_rebind_promote<T,U,3>::type ret_type;
return ret_type(lhs.x()+rhs.x(), lhs.y()+rhs.y(), lhs.z());
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline const typename vc_rebind_promote<T,U,2>::type operator- (
const vector<T,2>& lhs,
const vector<U,2>& rhs
)
{
typedef typename vc_rebind_promote<T,U,2>::type ret_type;
return ret_type(lhs.x()-rhs.x(), lhs.y()-rhs.y());
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline const typename vc_rebind_promote<T,U,3>::type operator- (
const vector<T,3>& lhs,
const vector<U,3>& rhs
)
{
typedef typename vc_rebind_promote<T,U,3>::type ret_type;
return ret_type(lhs.x()-rhs.x(), lhs.y()-rhs.y(), lhs.z()-rhs.z());
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline const typename vc_rebind_promote<T,U,3>::type operator- (
const vector<T,2>& lhs,
const vector<U,3>& rhs
)
{
typedef typename vc_rebind_promote<T,U,3>::type ret_type;
return ret_type(lhs.x()-rhs.x(), lhs.y()-rhs.y(), -rhs.z());
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline const typename vc_rebind_promote<T,U,3>::type operator- (
const vector<T,3>& lhs,
const vector<U,2>& rhs
)
{
typedef typename vc_rebind_promote<T,U,3>::type ret_type;
return ret_type(lhs.x()-rhs.x(), lhs.y()-rhs.y(), lhs.z());
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline typename disable_if<is_matrix<U>, const typename vc_rebind_promote<T,U,2>::type >::type operator* (
const vector<T,2>& v,
const U& s
)
{
typedef typename vc_rebind_promote<T,U,2>::type ret_type;
return ret_type(v.x()*s, v.y()*s);
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline typename disable_if<is_matrix<U>, const typename vc_rebind_promote<T,U,2>::type >::type operator* (
const U& s,
const vector<T,2>& v
)
{
typedef typename vc_rebind_promote<T,U,2>::type ret_type;
return ret_type(v.x()*s, v.y()*s);
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline typename disable_if<is_matrix<U>, const typename vc_rebind_promote<T,U,3>::type >::type operator* (
const vector<T,3>& v,
const U& s
)
{
typedef typename vc_rebind_promote<T,U,3>::type ret_type;
return ret_type(v.x()*s, v.y()*s, v.z()*s);
}
// ----------------------------------------------------------------------------------------
template <typename T, typename U>
inline typename disable_if<is_matrix<U>, const typename vc_rebind_promote<T,U,3>::type >::type operator* (
const U& s,
const vector<T,3>& v
)
{
typedef typename vc_rebind_promote<T,U,3>::type ret_type;
return ret_type(v.x()*s, v.y()*s, v.z()*s);
}
// ----------------------------------------------------------------------------------------
template<typename T, long NR>
inline void swap (
vector<T,NR> & a,
vector<T,NR> & b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
template<typename T>
inline void serialize (
const vector<T,3>& 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,3>& 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>
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,3>& item
)
{
out << "(" << item.x() << ", " << item.y() << ", " << item.z() << ")";
return out;
}
template<typename T>
std::istream& operator>>(
std::istream& in,
vector<T,3>& 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;
}
// ----------------------------------------------------------------------------------------
template<typename T>
std::ostream& operator<< (
std::ostream& out,
const vector<T,2>& item
)
{
out << "(" << item.x() << ", " << item.y() << ")";
return out;
}
template<typename T>
std::istream& operator>>(
std::istream& in,
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();
// 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 ')'
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;
}
// ----------------------------------------------------------------------------------------
typedef vector<long,2> point;
typedef vector<double,2> dpoint;
// ----------------------------------------------------------------------------------------
inline bool is_convex_quadrilateral (
const std::array<dpoint,4>& pts
)
{
auto orientation = [&](size_t i)
{
size_t a = (i+1)%4;
size_t b = (i+3)%4;
return (pts[a]-pts[i]).cross(pts[b]-pts[i]).z();
};
// If pts has any infinite points then this isn't a valid quadrilateral.
for (auto& p : pts)
{
if (p.x() == std::numeric_limits<double>::infinity())
return false;
if (p.y() == std::numeric_limits<double>::infinity())
return false;
}
double s0 = orientation(0);
double s1 = orientation(1);
double s2 = orientation(2);
double s3 = orientation(3);
// if all these things have the same sign then it's convex.
return (s0>0&&s1>0&&s2>0&&s3>0) || (s0<0&&s1<0&&s2<0&&s3<0);
}
// ----------------------------------------------------------------------------------------
template <
typename array_of_dpoints
>
inline double polygon_area (
const array_of_dpoints& pts
)
{
if (pts.size() <= 2)
return 0;
double val = 0;
for (size_t i = 1; i < pts.size(); ++i)
val += (double)pts[i].x()*pts[i-1].y() - pts[i].y()*pts[i-1].x();
const size_t end = pts.size()-1;
val += (double)pts[0].x()*pts[end].y() - pts[0].y()*pts[end].x();
return std::abs(val)/2.0;
}
// ----------------------------------------------------------------------------------------
}
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> >
{
typedef dlib::vector<T, 3> first_argument_type;
typedef dlib::vector<T, 3> second_argument_type;
typedef bool result_type;
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> >
{
typedef dlib::vector<T, 2> first_argument_type;
typedef dlib::vector<T, 2> second_argument_type;
typedef bool result_type;
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;
}
};
}
#if defined(_MSC_VER) && _MSC_VER < 1400
// restore warnings back to their previous settings
#pragma warning(pop)
#endif
#endif // DLIB_VECTOr_H_