extent: derive from generic coord class

This commit is contained in:
Danny Robson 2015-03-03 19:43:09 +11:00
parent 31d1d741e9
commit 872499360f
5 changed files with 55 additions and 116 deletions

View File

@ -209,6 +209,8 @@ namespace util {
using coord_init<S,T,tags...>::coord_init;
coord () = default;
size_t size (void) const { return S; }
explicit coord (T v)
{ std::fill (std::begin (this->data), std::end (this->data), v); }

View File

@ -24,59 +24,27 @@
#include <cmath>
///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T>
util::extent<S,T>::extent (const T _width, const T _height):
w (_width),
h (_height)
{
static_assert (S == 2, "extents currently only support 2 dimensions");
CHECK_GE (w, 0);
CHECK_GE (h, 0);
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
util::extent<S,T>::extent (T t):
extent (t, t)
{ ; }
//-----------------------------------------------------------------------------
template <size_t S, typename T>
util::extent<S,T>::extent (vector<S,T> _v):
extent (_v.x, _v.y)
{ ; }
//-----------------------------------------------------------------------------
template <size_t S, typename T>
util::extent<S,T>::extent (const util::extent<S,T> &rhs):
w (rhs.w),
h (rhs.h)
{ ; }
//-----------------------------------------------------------------------------
template <size_t S, typename T>
util::extent<S,T>&
util::extent<S,T>::operator= (extent<S,T> rhs)
{
w = rhs.w;
h = rhs.h;
return *this;
}
///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T>
T
util::extent<S,T>::diameter (void) const
{
return static_cast<T> (sqrt (w * w + h * h));
return static_cast<T> (
std::sqrt (
std::accumulate (std::begin (this->data),
std::end (this->data),
T {0},
[] (auto a, auto b) { return a + b * b; })
)
);
}
@ -85,7 +53,10 @@ template <size_t S, typename T>
T
util::extent<S,T>::area (void) const
{
return w * h;
return std::accumulate (std::begin (this->data),
std::end (this->data),
T {1},
std::multiplies<T> ());
}
@ -94,10 +65,7 @@ template <size_t S, typename T>
util::extent<S,T>
util::extent<S,T>::expanded (util::vector<S,T> mag) const
{
return {
w + mag.x,
h + mag.y
};
return *this + mag;
}
@ -110,15 +78,6 @@ util::extent<S,T>::expanded (T t) const
}
///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T>
float
util::extent<S,T>::aspect (void) const
{
return static_cast<float> (w) / static_cast<float> (h);
}
///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T>
bool
@ -130,40 +89,15 @@ util::extent<S,T>::empty (void) const
///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T>
T&
util::extent<S,T>::operator[] (size_t idx)
util::extent<S,T>
util::extent<S,T>::operator+ (vector<S,T> rhs) const
{
switch (idx) {
case 0: return w;
case 1: return h;
default:
unreachable ();
}
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
const T&
util::extent<S,T>::operator[] (size_t idx) const
{
switch (idx) {
case 0: return w;
case 1: return h;
default:
unreachable ();
}
}
//-----------------------------------------------------------------------------
template <size_t S, typename T>
size_t
util::extent<S,T>::size (void) const
{
return S;
extent<S,T> out;
std::adjacent_difference (std::begin (this->data),
std::end (this->data),
std::begin (rhs.data),
std::plus<T> ());
return out;
}
@ -172,22 +106,21 @@ template <size_t S, typename T>
bool
util::extent<S,T>::operator ==(const extent& rhs) const
{
return almost_equal (w, rhs.w) &&
almost_equal (h, rhs.h);
return std::equal (std::begin (this->data),
std::end (this->data),
std::begin (rhs.data),
almost_equal<T>);
}
///////////////////////////////////////////////////////////////////////////////
template <size_t S, typename T>
const util::extent<S,T> util::extent<S,T>::MIN {
0, 0
};
const util::extent<S,T> util::extent<S,T>::MIN { 0 };
//-----------------------------------------------------------------------------
template <size_t S, typename T>
const util::extent<S,T> util::extent<S,T>::MAX {
std::numeric_limits<T>::max (),
std::numeric_limits<T>::max ()
};

View File

@ -20,8 +20,8 @@
#ifndef __UTIL_EXTENT_HPP
#define __UTIL_EXTENT_HPP
#include "detail/coord.hpp"
#include "vector.hpp"
#include <iostream>
@ -30,15 +30,10 @@ namespace util {
* A pure two-dimensional size, without positioning
*/
template <size_t S, typename T>
struct extent {
T w, h;
extent (const T _width, const T _height);
extent (T);
extent (vector<S,T>);
extent (const extent&);
extent& operator= (extent);
struct extent : public detail::coord<S,T,detail::whd> {
using detail::coord<S,T,detail::whd>::coord;
extent () = default;
extent (vector<S,T>);
T area (void) const;
T diameter (void) const;
@ -46,14 +41,9 @@ namespace util {
extent expanded (vector<S,T>) const;
extent expanded (T) const;
float aspect (void) const;
bool empty (void) const;
T& operator[] (size_t idx);
const T& operator[] (size_t idx) const;
size_t size (void) const;
extent<S,T> operator+ (vector<S,T>) const;
bool operator ==(const extent& rhs) const;
bool operator !=(const extent& rhs) const
@ -66,6 +56,10 @@ namespace util {
static const extent MIN;
};
template <typename U, typename T>
U
aspect (extent<2,T>);
typedef extent<2,int> extent2i;
typedef extent<2,size_t> extent2u;
typedef extent<2,float> extent2f;

View File

@ -19,19 +19,29 @@
#ifdef __UTIL_EXTENT_IPP
#error "twice included ipp"
#error
#endif
#define __UTIL_EXTENT_IPP
#include <algorithm>
//-----------------------------------------------------------------------------
template <size_t S, typename T>
template <typename U>
util::extent<S,U>
util::extent<S,T>::cast (void) const
{
return {
static_cast<U> (w),
static_cast<U> (h)
};
util::extent<S,U> out;
std::copy (std::begin (this->data), std::end (this->data), std::begin (out.data));
return out;
}
//-----------------------------------------------------------------------------
template <typename U, typename T>
U
util::aspect (util::extent<2,T> e)
{
return static_cast<U> (e.w) / e.h;
}