coord: move operators out of subclasses
This commit is contained in:
parent
872499360f
commit
439bb19679
44
bezier.cpp
44
bezier.cpp
@ -26,22 +26,6 @@
|
||||
#include <iterator>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// HACK: point multiplication isn't defined, but it's way more convenient than
|
||||
// casting between vector/coord
|
||||
namespace util {
|
||||
template <typename T>
|
||||
util::point2f
|
||||
operator* (T a, util::point2f b)
|
||||
{
|
||||
return {
|
||||
a * b.data[0],
|
||||
a * b.data[1]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S>
|
||||
util::bezier<S>::bezier (const util::point2f (&_points)[S+1])
|
||||
@ -147,10 +131,10 @@ namespace util {
|
||||
const auto &v = m_coeffs;
|
||||
|
||||
return {
|
||||
-1 * v[0] +3 * v[1] -3 * v[2] +1 * v[3],
|
||||
3 * v[0] -6 * v[1] +3 * v[2],
|
||||
-3 * v[0] +3 * v[1],
|
||||
1 * v[0]
|
||||
-1.f * v[0] +3.f * v[1] -3.f * v[2] +1.f * v[3],
|
||||
3.f * v[0] -6.f * v[1] +3.f * v[2],
|
||||
-3.f * v[0] +3.f * v[1],
|
||||
1.f * v[0]
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -165,9 +149,9 @@ namespace util {
|
||||
auto &v = m_coeffs;
|
||||
|
||||
return {
|
||||
+1 * v[2] -2 * v[1] + 1 * v[0],
|
||||
-2 * v[2] +2 * v[1],
|
||||
+1 * v[2]
|
||||
+1.f * v[2] -2.f * v[1] + 1.f * v[0],
|
||||
-2.f * v[2] +2.f * v[1],
|
||||
+1.f * v[2]
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -182,8 +166,8 @@ namespace util {
|
||||
auto &v = m_coeffs;
|
||||
|
||||
return {
|
||||
-1 * v[1] + 1 * v[0],
|
||||
+1 * v[1],
|
||||
-1.f * v[1] + 1.f * v[0],
|
||||
+1.f * v[1],
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -378,12 +362,10 @@ util::bezier<S>::region (void) const
|
||||
y1 = max (y1, m_points[i].y);
|
||||
}
|
||||
|
||||
return {
|
||||
x0,
|
||||
y0,
|
||||
x1 - x0,
|
||||
y1 - y0
|
||||
};
|
||||
util::point2f p0 { x0, y0 };
|
||||
util::point2f p1 { x1, y1 };
|
||||
|
||||
return { p0, p1 };
|
||||
}
|
||||
|
||||
|
||||
|
182
detail/coord.hpp
182
detail/coord.hpp
@ -20,15 +20,30 @@
|
||||
#ifndef __UTIL_COORD_HPP
|
||||
#define __UTIL_COORD_HPP
|
||||
|
||||
#include "../preprocessor.hpp"
|
||||
#include "../platform.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace util {
|
||||
template <size_t,typename> class point;
|
||||
template <size_t,typename> class extent;
|
||||
template <size_t,typename> class vector;
|
||||
|
||||
namespace detail {
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// tags for accessor names
|
||||
struct rgba { };
|
||||
struct xyzw { };
|
||||
struct stpq { };
|
||||
struct whd { };
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Disable GCC warnings about validity of anonyous structures in
|
||||
// unions. Push comes to shove I'll manually redsign everything to
|
||||
// keep this syntax anyway.
|
||||
@ -40,14 +55,6 @@ namespace util {
|
||||
#pragma GCC diagnostic ignored "-Wgnu"
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// tags for accessor names
|
||||
struct rgba { };
|
||||
struct xyzw { };
|
||||
struct stpq { };
|
||||
struct whd { };
|
||||
|
||||
|
||||
template <size_t S, typename T, typename...>
|
||||
struct coord_base {
|
||||
T data[S];
|
||||
@ -145,8 +152,9 @@ namespace util {
|
||||
};
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// coord types are not really intended to have arbitrary dimension, so
|
||||
// don't add specialisations (or a general case) without a decent
|
||||
// reason.
|
||||
@ -157,6 +165,7 @@ namespace util {
|
||||
template <typename T, typename ...tags>
|
||||
struct coord_init<1,T,tags...> : public coord_base<1,T,tags...>
|
||||
{
|
||||
using coord_base<1,T,tags...>::coord_base;
|
||||
coord_init () = default;
|
||||
coord_init (T v0):
|
||||
coord_base<1,T,tags...> ({v0})
|
||||
@ -168,6 +177,7 @@ namespace util {
|
||||
template <typename T, typename ...tags>
|
||||
struct coord_init<2,T,tags...> : public coord_base<2,T,tags...>
|
||||
{
|
||||
using coord_base<2,T,tags...>::coord_base;
|
||||
coord_init () = default;
|
||||
coord_init (T v0, T v1):
|
||||
coord_base<2,T,tags...> ({ v0, v1 })
|
||||
@ -179,6 +189,7 @@ namespace util {
|
||||
template <typename T, typename ...tags>
|
||||
struct coord_init<3,T,tags...> : public coord_base<3,T,tags...>
|
||||
{
|
||||
using coord_base<3,T,tags...>::coord_base;
|
||||
coord_init () = default;
|
||||
coord_init (T v0, T v1, T v2):
|
||||
coord_base<3,T,tags...> ({v0, v1, v2})
|
||||
@ -190,14 +201,14 @@ namespace util {
|
||||
template <typename T, typename ...tags>
|
||||
struct coord_init<4,T,tags...> : public coord_base<4,T,tags...>
|
||||
{
|
||||
using coord_base<4,T,tags...>::coord_base;
|
||||
coord_init () = default;
|
||||
coord_init (T v0, T v1, T v2, T v3):
|
||||
coord_base<4,T,tags...> ({ v0, v1, v2, v3 })
|
||||
{ ; }
|
||||
};
|
||||
|
||||
|
||||
////---------------------------------------------------------------------
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T, typename ...tags>
|
||||
struct coord : public coord_init<S,T,tags...> {
|
||||
static_assert (S > 0, "coord dimensions must be strictly positive");
|
||||
@ -206,17 +217,19 @@ namespace util {
|
||||
static constexpr size_t dimension = S;
|
||||
static constexpr size_t elements = S;
|
||||
|
||||
size_t size (void) const { return S; }
|
||||
|
||||
// constructors
|
||||
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); }
|
||||
|
||||
coord (const coord<S,T,tags...> &rhs) = default;
|
||||
coord& operator= (const coord<S,T,tags...> &rhs) = default;
|
||||
|
||||
// element accessors
|
||||
T& operator[] (size_t i) { return this->data[i]; }
|
||||
T operator[] (size_t i) const { return this->data[i]; }
|
||||
|
||||
@ -228,19 +241,138 @@ namespace util {
|
||||
};
|
||||
|
||||
|
||||
////---------------------------------------------------------------------
|
||||
// XXX: Unsure whether this should really be defined for arbitrary
|
||||
// types in a semantic sense, but practicality suggestes this is the
|
||||
// best option; point/vector dot product is too useful.
|
||||
template <size_t S, typename T, typename ...tag_a, typename ...tag_b>
|
||||
T dot (const coord<S,T,tag_a...> &a, const coord<S,T,tag_b...> &b)
|
||||
{
|
||||
return std::inner_product (std::begin (a.data),
|
||||
std::end (a.data),
|
||||
std::begin (b.data),
|
||||
T {0});
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
template <
|
||||
size_t S,
|
||||
typename T,
|
||||
template <size_t,typename> class A,
|
||||
template <size_t,typename> class B
|
||||
>
|
||||
struct coord_traits { };
|
||||
|
||||
|
||||
template <size_t S, typename T> struct coord_traits<S,T,extent,extent> { typedef extent<S,T> result; };
|
||||
template <size_t S, typename T> struct coord_traits<S,T,extent,vector> { typedef extent<S,T> result; };
|
||||
template <size_t S, typename T> struct coord_traits<S,T,point,extent> { typedef point<S,T> result; };
|
||||
template <size_t S, typename T> struct coord_traits<S,T,point,vector> { typedef point<S,T> result; };
|
||||
template <size_t S, typename T> struct coord_traits<S,T,vector,vector> { typedef vector<S,T> result; };
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// vector operators
|
||||
#define ELEMENT_OP(OP) \
|
||||
template < \
|
||||
size_t S, \
|
||||
typename T, \
|
||||
template <size_t,typename> class A, \
|
||||
template <size_t,typename> class B \
|
||||
> \
|
||||
typename detail::coord_traits<S,T,A,B>::result \
|
||||
operator OP (A<S,T> a, B<S,T> b) \
|
||||
{ \
|
||||
typename detail::coord_traits<S,T,A,B>::result out; \
|
||||
for (size_t i = 0; i < S; ++i) \
|
||||
out[i] = a[i] OP b[i]; \
|
||||
return out; \
|
||||
} \
|
||||
\
|
||||
template < \
|
||||
size_t S, \
|
||||
typename T, \
|
||||
template <size_t,typename> class A, \
|
||||
template <size_t,typename> class B \
|
||||
> \
|
||||
typename detail::coord_traits<S,T,A,B>::result& \
|
||||
operator PASTE(OP,=) (A<S,T>& a, B<S,T> b) \
|
||||
{ \
|
||||
for (size_t i = 0; i < S; ++i) \
|
||||
a[i] PASTE(OP,=) b[i]; \
|
||||
return a; \
|
||||
}
|
||||
|
||||
ELEMENT_OP(+)
|
||||
ELEMENT_OP(-)
|
||||
ELEMENT_OP(*)
|
||||
ELEMENT_OP(/)
|
||||
#undef ELEMENT_OP
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// scalar operators
|
||||
#define SCALAR_OP(OP) \
|
||||
template <size_t S, typename T, template <size_t,typename> class K> \
|
||||
K<S,T> \
|
||||
operator OP (T t, K<S,T> k) \
|
||||
{ \
|
||||
K<S,T> out; \
|
||||
for (size_t i = 0; i < S; ++i) \
|
||||
out[i] = t OP k[i]; \
|
||||
return out; \
|
||||
} \
|
||||
\
|
||||
template <size_t S, typename T, template <size_t,typename> class K> \
|
||||
K<S,T> \
|
||||
operator OP (K<S,T> k, T t) \
|
||||
{ \
|
||||
K<S,T> out; \
|
||||
for (size_t i = 0; i < S; ++i) \
|
||||
out[i] = t OP k[i]; \
|
||||
return out; \
|
||||
}
|
||||
|
||||
SCALAR_OP(+)
|
||||
SCALAR_OP(-)
|
||||
SCALAR_OP(*)
|
||||
SCALAR_OP(/)
|
||||
|
||||
#undef SCALAR_OP
|
||||
|
||||
|
||||
#define SCALAR_OP(OP) \
|
||||
template <size_t S, typename T, template <size_t,typename> class K> \
|
||||
K<S,T>& \
|
||||
operator OP (K<S,T> &k, T t) \
|
||||
{ \
|
||||
for (size_t i = 0; i < S; ++i) \
|
||||
k[i] OP t; \
|
||||
return k; \
|
||||
}
|
||||
|
||||
SCALAR_OP(+=)
|
||||
SCALAR_OP(-=)
|
||||
SCALAR_OP(*=)
|
||||
SCALAR_OP(/=)
|
||||
#undef SCALAR_OP
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// logic operators
|
||||
template <size_t S, typename T, template <size_t,typename> class K>
|
||||
bool operator== (K<S,T> a, K<S,T> b)
|
||||
{ return std::equal (std::begin (a), std::end (a), std::begin (b)); }
|
||||
|
||||
template <size_t S, typename T, template <size_t,typename> class K>
|
||||
bool operator!= (K<S,T> a, K<S,T> b)
|
||||
{ return !(a == b); }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// special operators
|
||||
template <size_t S, typename T> vector<S,T> operator- (point<S,T> a, point<S,T> b)
|
||||
{
|
||||
vector<S,T> out;
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out[i] = a[i] - b[i];
|
||||
return out;
|
||||
}
|
||||
|
||||
template <size_t S, typename T, template<size_t,typename> class A, template <size_t,typename> class B>
|
||||
T dot (A<S,T> a, B<S,T> b)
|
||||
{
|
||||
T sum { 0 };
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
sum += a[i] * b[i];
|
||||
return sum;
|
||||
}
|
||||
}
|
||||
|
||||
|
45
extent.cpp
45
extent.cpp
@ -27,9 +27,12 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T>
|
||||
util::extent<S,T>::extent (vector<S,T> _v):
|
||||
extent (_v.x, _v.y)
|
||||
{ ; }
|
||||
util::extent<S,T>::extent (vector<S,T> _v)
|
||||
{
|
||||
std::copy (std::begin (_v.data),
|
||||
std::end (_v.data),
|
||||
std::begin (this->data));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -87,32 +90,6 @@ util::extent<S,T>::empty (void) const
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T>
|
||||
util::extent<S,T>
|
||||
util::extent<S,T>::operator+ (vector<S,T> rhs) const
|
||||
{
|
||||
extent<S,T> out;
|
||||
std::adjacent_difference (std::begin (this->data),
|
||||
std::end (this->data),
|
||||
std::begin (rhs.data),
|
||||
std::plus<T> ());
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T>
|
||||
bool
|
||||
util::extent<S,T>::operator ==(const extent& rhs) const
|
||||
{
|
||||
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 };
|
||||
@ -131,7 +108,9 @@ namespace debug {
|
||||
struct validator<util::extent,S,T> {
|
||||
static bool is_valid (const util::extent<S,T> &e)
|
||||
{
|
||||
return e.w >= 0 && e.h >= 0;
|
||||
return std::all_of (std::begin (e.data),
|
||||
std::end (e.data),
|
||||
[] (auto i) { return i >= 0; });
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -148,7 +127,11 @@ template <size_t S, typename T>
|
||||
std::ostream&
|
||||
util::operator<< (std::ostream &os, util::extent<S,T> e)
|
||||
{
|
||||
os << "[" << e.w << ", " << e.h << "]";
|
||||
os << "[";
|
||||
std::copy (std::begin (e.data),
|
||||
std::end (e.data),
|
||||
std::ostream_iterator<T> (os, ", "));
|
||||
os << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
11
extent.hpp
11
extent.hpp
@ -30,8 +30,10 @@ namespace util {
|
||||
* A pure two-dimensional size, without positioning
|
||||
*/
|
||||
template <size_t S, typename T>
|
||||
struct extent : public detail::coord<S,T,detail::whd> {
|
||||
struct extent : public detail::coord<S,T,detail::whd>
|
||||
{
|
||||
using detail::coord<S,T,detail::whd>::coord;
|
||||
|
||||
extent () = default;
|
||||
extent (vector<S,T>);
|
||||
|
||||
@ -43,12 +45,6 @@ namespace util {
|
||||
|
||||
bool empty (void) const;
|
||||
|
||||
extent<S,T> operator+ (vector<S,T>) const;
|
||||
|
||||
bool operator ==(const extent& rhs) const;
|
||||
bool operator !=(const extent& rhs) const
|
||||
{ return !(*this == rhs); }
|
||||
|
||||
template <typename U>
|
||||
extent<S,U> cast (void) const;
|
||||
|
||||
@ -63,6 +59,7 @@ namespace util {
|
||||
typedef extent<2,int> extent2i;
|
||||
typedef extent<2,size_t> extent2u;
|
||||
typedef extent<2,float> extent2f;
|
||||
typedef extent<2,double> extent2d;
|
||||
|
||||
template <size_t S, typename T>
|
||||
std::ostream& operator<< (std::ostream&, util::extent<S,T>);
|
||||
|
@ -236,8 +236,8 @@ cellular::eval (double x, double y) const {
|
||||
for (signed x_off = -1; x_off <= 1; ++x_off) {
|
||||
auto pos = point2d (double (x_off), double (y_off));
|
||||
auto off = generate<vector2d> (x_int + x_off, y_int + y_off, this->seed);
|
||||
off += 1;
|
||||
off /= 2;
|
||||
off += 1.;
|
||||
off /= 2.;
|
||||
|
||||
CHECK (off.x >= 0 && off.x <= 1.0);
|
||||
CHECK (off.y >= 0 && off.y <= 1.0);
|
||||
|
117
point.cpp
117
point.cpp
@ -27,112 +27,6 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if defined(COMPILER_GCC)
|
||||
#pragma GCC optimize("-O3")
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::point<S,T>&
|
||||
util::point<S,T>::operator*= (T f) {
|
||||
for (auto &i: this->data)
|
||||
i *= f;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template <size_t S, typename T>
|
||||
util::point<S,T>
|
||||
util::point<S,T>::operator* (T f) const {
|
||||
util::point<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] * f;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::point<S,T>&
|
||||
util::point<S,T>::operator/= (T f)
|
||||
{
|
||||
std::transform (std::begin (this->data),
|
||||
std::end (this->data),
|
||||
std::begin (this->data),
|
||||
[f] (auto i) { return i / f; });
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::point<S,T>
|
||||
util::point<S,T>::operator/ (T f) const
|
||||
{
|
||||
point<S,T> out;
|
||||
|
||||
std::transform (std::begin (this->data),
|
||||
std::end (this->data),
|
||||
std::begin (out.data),
|
||||
[f] (auto i) { return i / f; });
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::point<S,T>
|
||||
util::point<S,T>::operator- (const vector<S,T> &rhs) const {
|
||||
util::point<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] - rhs.data[i];
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
template <size_t S, typename T>
|
||||
util::point<S,T>&
|
||||
util::point<S,T>::operator-= (const util::vector<S,T> &rhs) {
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
this->data[i] -= rhs.data[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::point<S,T>
|
||||
util::point<S,T>::operator+ (const vector<S,T> &rhs) const {
|
||||
util::point<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] + rhs.data[i];
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
template <size_t S, typename T>
|
||||
util::point<S,T>&
|
||||
util::point<S,T>::operator+= (const util::vector<S,T> &rhs) {
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
this->data[i] += rhs.data[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>
|
||||
util::point<S,T>::operator- (const point<S,T> &rhs) const {
|
||||
util::vector<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] - rhs.data[i];
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
@ -146,17 +40,6 @@ util::point<S,T>::to (const point<S,T> &rhs) const {
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
bool
|
||||
util::point<S,T>::operator== (const util::point<S,T> &rhs) const
|
||||
{
|
||||
return std::equal (std::begin (this->data),
|
||||
std::end (this->data),
|
||||
std::begin (rhs.data));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
void
|
||||
|
20
point.hpp
20
point.hpp
@ -20,6 +20,7 @@
|
||||
#ifndef __UTIL_POINT_HPP
|
||||
#define __UTIL_POINT_HPP
|
||||
|
||||
#include "extent.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "detail/coord.hpp"
|
||||
|
||||
@ -31,7 +32,8 @@
|
||||
namespace util {
|
||||
/// An n-dimensional position in space.
|
||||
template <size_t S, typename T>
|
||||
struct point : public detail::coord<S,T,detail::xyzw> {
|
||||
struct point : public detail::coord<S,T,detail::xyzw>
|
||||
{
|
||||
using detail::coord<S,T,detail::xyzw>::coord;
|
||||
|
||||
// point operators
|
||||
@ -41,22 +43,6 @@ namespace util {
|
||||
|
||||
vector<S,T> to (const point&) const;
|
||||
|
||||
// arithetic operators
|
||||
point<S,T>& operator*= (T);
|
||||
point<S,T> operator* (T) const;
|
||||
point<S,T>& operator/= (T);
|
||||
point<S,T> operator/ (T) const;
|
||||
|
||||
vector<S,T> operator- (const point<S,T>&) const;
|
||||
|
||||
point<S,T> operator- (const vector<S,T>&) const;
|
||||
point<S,T>& operator-= (const vector<S,T>&);
|
||||
point<S,T> operator+ (const vector<S,T>&) const;
|
||||
point<S,T>& operator+= (const vector<S,T>&);
|
||||
|
||||
// logical operators
|
||||
bool operator== (const point<S,T>&) const;
|
||||
|
||||
template <size_t D> point<D,T> redim (void) const;
|
||||
template <size_t D> point<D,T> redim (const util::point<D,T> &fill) const;
|
||||
template <size_t D> point<D,T> redim (T fill) const;
|
||||
|
@ -52,7 +52,7 @@ quaternion<T>::rotation (vector<3,T> from, vector<3,T> to) {
|
||||
auto v = util::cross (from, to);
|
||||
|
||||
return {
|
||||
std::acos (from.dot (to)),
|
||||
std::acos (dot (from, to)),
|
||||
v.x,
|
||||
v.y,
|
||||
v.z
|
||||
|
237
region.cpp
237
region.cpp
@ -36,12 +36,10 @@ util::region<S,T>::region (extent_t _extent):
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::region<S,T>::region (point_t _point,
|
||||
extent_t _size):
|
||||
x (_point.x),
|
||||
y (_point.y),
|
||||
w (_size.w),
|
||||
h (_size.h)
|
||||
util::region<S,T>::region (point_t _p,
|
||||
extent_t _e):
|
||||
p (_p),
|
||||
e (_e)
|
||||
{ ; }
|
||||
|
||||
|
||||
@ -50,19 +48,25 @@ template <size_t S, typename T>
|
||||
util::region<S,T>::region (point_t _a,
|
||||
point_t _b):
|
||||
region (_a, _b - _a)
|
||||
{ ; }
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::region<S,T>::region (std::array<T,S*2> args)
|
||||
{
|
||||
CHECK_GE (_b.x, _a.x);
|
||||
CHECK_GE (_b.y, _a.y);
|
||||
std::copy (&args[0], &args[S], p.data);
|
||||
std::copy (&args[S], &args[S*2], e.data);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::region<S,T>::region (position_type _x,
|
||||
position_type _y,
|
||||
size_type _w,
|
||||
size_type _h):
|
||||
region (point_t {_x, _y}, extent<S,T> {_w, _h})
|
||||
{ ; }
|
||||
util::region<S,T>::region (position_type _p,
|
||||
size_type _e):
|
||||
region (point_t {_p}, extent_t {_e})
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -70,7 +74,7 @@ template <size_t S, typename T>
|
||||
typename util::region<S,T>::size_type
|
||||
util::region<S,T>::area (void) const
|
||||
{
|
||||
return w * h;
|
||||
return e.area ();
|
||||
}
|
||||
|
||||
|
||||
@ -79,7 +83,7 @@ template <size_t S, typename T>
|
||||
typename util::region<S,T>::size_type
|
||||
util::region<S,T>::diameter (void) const
|
||||
{
|
||||
return static_cast<size_type> (std::sqrt (w * w + h * h));
|
||||
return e.diameter ();
|
||||
}
|
||||
|
||||
|
||||
@ -88,19 +92,17 @@ template <size_t S, typename T>
|
||||
typename util::region<S,T>::extent_t
|
||||
util::region<S,T>::magnitude (void) const
|
||||
{
|
||||
return { w, h };
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
typename util::region<S,T>::extent_t
|
||||
util::region<S,T>::magnitude (extent_t e)
|
||||
util::region<S,T>::magnitude (extent_t _e)
|
||||
{
|
||||
w = e.w;
|
||||
h = e.h;
|
||||
|
||||
return magnitude ();
|
||||
e = _e;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
@ -109,11 +111,9 @@ template <size_t S, typename T>
|
||||
void
|
||||
util::region<S,T>::scale (T factor)
|
||||
{
|
||||
x -= (w * factor - w) / T{2};
|
||||
y -= (h * factor - h) / T{2};
|
||||
|
||||
w = w * factor;
|
||||
h = h * factor;
|
||||
auto o = (e * factor - e) / T{2};
|
||||
p -= o;
|
||||
e *= factor;
|
||||
}
|
||||
|
||||
|
||||
@ -126,24 +126,12 @@ util::region<S,T>::empty (void) const
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
typename util::region<S,T>::point_t
|
||||
util::region<S,T>::rebase (point_t p)
|
||||
{
|
||||
x = p.x;
|
||||
y = p.y;
|
||||
|
||||
return base ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
typename util::region<S,T>::point_t
|
||||
util::region<S,T>::base (void) const
|
||||
{
|
||||
return { x, y };
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
@ -152,7 +140,7 @@ template <size_t S, typename T>
|
||||
typename util::region<S,T>::point_t
|
||||
util::region<S,T>::away (void) const
|
||||
{
|
||||
return { x + w, y + h };
|
||||
return p + e;
|
||||
}
|
||||
|
||||
|
||||
@ -161,51 +149,49 @@ template <size_t S, typename T>
|
||||
typename util::region<S,T>::point_t
|
||||
util::region<S,T>::centre (void) const
|
||||
{
|
||||
T cx = x + w / T{2},
|
||||
cy = y + h / T{2};
|
||||
|
||||
return point_t { cx, cy };
|
||||
return p + e / T{2};
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
typename util::region<S,T>::point_t
|
||||
util::region<S,T>::closest (point_t p) const
|
||||
util::region<S,T>::closest (point_t q) const
|
||||
{
|
||||
return {
|
||||
p.x < x ? x :
|
||||
p.x > x + w ? x + w :
|
||||
p.x,
|
||||
point_t out;
|
||||
|
||||
p.y < y ? y :
|
||||
p.y > y + h ? y + h :
|
||||
p.y
|
||||
};
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out[i] = q[i] < p[i] ? p[i] :
|
||||
q[i] > p[i] ? p[i] + e[i] :
|
||||
q[i];
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
bool
|
||||
util::region<S,T>::includes (point_t p) const
|
||||
util::region<S,T>::includes (point_t q) const
|
||||
{
|
||||
return p.x >= x &&
|
||||
p.y >= y &&
|
||||
p.x - x <= w &&
|
||||
p.y - y <= h;
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
if (q[i] < p[i] || q[i] > p[i] + e[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
bool
|
||||
util::region<S,T>::contains (point_t p) const
|
||||
util::region<S,T>::contains (point_t q) const
|
||||
{
|
||||
return p.x > x &&
|
||||
p.y > y &&
|
||||
p.x - x < w &&
|
||||
p.y - y < h;
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
if (q[i] <= p[i] || q[i] >= p[i] + e[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -216,33 +202,32 @@ template <size_t S, typename T>
|
||||
bool
|
||||
util::region<S,T>::intersects (region<S,T> rhs) const
|
||||
{
|
||||
return x < rhs.x + rhs.w &&
|
||||
rhs.x < x + w &&
|
||||
y < rhs.y + rhs.h &&
|
||||
rhs.y < y + h;
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
if (p[i] >= rhs.p[i] + rhs.e[i] ||
|
||||
rhs.p[i] >= p[i] + e[i])
|
||||
{ return false; }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
void
|
||||
util::region<S,T>::constrain (point_t &p) const
|
||||
util::region<S,T>::constrain (point_t &q) const
|
||||
{
|
||||
p.x = std::min (std::max (p.x, x), x + w);
|
||||
p.y = std::min (std::max (p.y, y), y + h);
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
q[i] = limit (q[i], p[i], p[i] + e[i]);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
typename util::region<S,T>::point_t
|
||||
util::region<S,T>::constrained (point_t p) const
|
||||
util::region<S,T>::constrained (point_t q) const
|
||||
{
|
||||
point_t v;
|
||||
v.x = std::min (std::max (p.x, x), x + w);
|
||||
v.y = std::min (std::max (p.y, y), y + h);
|
||||
|
||||
return v;
|
||||
constrain (q);
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
@ -251,41 +236,54 @@ template<size_t S, typename T>
|
||||
util::region<S,T>
|
||||
util::region<S,T>::intersection (region<S,T> rhs) const
|
||||
{
|
||||
T newx1 = max (x, rhs.x),
|
||||
newy1 = max (y, rhs.y),
|
||||
newx2 = min (x + sign_cast<T> (w), rhs.x + sign_cast<T> (rhs.w)),
|
||||
newy2 = min (y + sign_cast<T> (h), rhs.y + sign_cast<T> (rhs.h));
|
||||
// find the intersection corners
|
||||
point_t a, b;
|
||||
|
||||
if (newx2 < newx1 || newy2 < newy1)
|
||||
throw std::logic_error ("No overlap");
|
||||
for (size_t i = 0; i < S; ++i) {
|
||||
a[i] = max (p[i], rhs.p[i]);
|
||||
b[i] = min (p[i] + e[i], rhs.p[i] + rhs.e[i]);
|
||||
|
||||
size_type nw = sign_cast<size_type> (newx2 - newx1);
|
||||
size_type nh = sign_cast<size_type> (newy2 - newy1);
|
||||
return util::region<S,T> (newx1, newy1, nw, nh);
|
||||
if (b[i] < a[i])
|
||||
throw std::logic_error ("no overlap");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::region<S,T>
|
||||
util::region<S,T>::inset (T mag)
|
||||
{
|
||||
CHECK_GE (w, 2 * mag);
|
||||
CHECK_GE (h, 2 * mag);
|
||||
|
||||
return { x + mag, y + mag, w - 2 * mag, h - 2 * mag };
|
||||
return { a, b };
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::region<S,T>&
|
||||
util::region<S,T>::expand (T _w, T _h)
|
||||
util::region<S,T>::resize (extent<S,T> _e)
|
||||
{
|
||||
x -= _w;
|
||||
y -= _h;
|
||||
w += _w * 2;
|
||||
h += _h * 2;
|
||||
e = _e;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::region<S,T>
|
||||
util::region<S,T>::inset (T mag)
|
||||
{
|
||||
// ensure we have enough space to inset
|
||||
CHECK (std::all_of (std::begin (e.data),
|
||||
std::end (e.data),
|
||||
[mag] (auto i) { return i >= 2 * mag; }));
|
||||
|
||||
return {
|
||||
p + mag,
|
||||
e - 2 * mag
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::region<S,T>&
|
||||
util::region<S,T>::expand (vector<S,T> v)
|
||||
{
|
||||
p -= v;
|
||||
e += v * T{2};
|
||||
|
||||
return *this;
|
||||
}
|
||||
@ -296,20 +294,18 @@ template <size_t S, typename T>
|
||||
util::region<S,T>&
|
||||
util::region<S,T>::expand (T mag)
|
||||
{
|
||||
return expand (mag, mag);
|
||||
return expand ({mag});
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::region<S,T>
|
||||
util::region<S,T>::expanded (T _w, T _h) const
|
||||
util::region<S,T>::expanded (vector<S,T> v) const
|
||||
{
|
||||
return {
|
||||
x - _w,
|
||||
y - _h,
|
||||
w + _w * 2,
|
||||
h + _h * 2,
|
||||
p - v,
|
||||
e + v * T{2}
|
||||
};
|
||||
}
|
||||
|
||||
@ -319,7 +315,7 @@ template <size_t S, typename T>
|
||||
util::region<S,T>
|
||||
util::region<S,T>::expanded (T mag) const
|
||||
{
|
||||
return expanded (mag, mag);
|
||||
return expanded ({mag});
|
||||
}
|
||||
|
||||
|
||||
@ -328,7 +324,7 @@ template <size_t S, typename T>
|
||||
util::region<S,T>
|
||||
util::region<S,T>::operator+ (vector<S,T> rhs) const
|
||||
{
|
||||
return { x + rhs.x, y + rhs.y, w, h };
|
||||
return { p + rhs, e };
|
||||
}
|
||||
|
||||
|
||||
@ -337,7 +333,7 @@ template <size_t S, typename T>
|
||||
util::region<S,T>
|
||||
util::region<S,T>::operator- (vector<S,T> rhs) const
|
||||
{
|
||||
return { x - rhs.x, y - rhs.y, w, h };
|
||||
return { p - rhs, e };
|
||||
}
|
||||
|
||||
|
||||
@ -346,10 +342,7 @@ template <size_t S, typename T>
|
||||
bool
|
||||
util::region<S,T>::operator== (region rhs) const
|
||||
{
|
||||
return almost_equal (x, rhs.x) &&
|
||||
almost_equal (y, rhs.y) &&
|
||||
almost_equal (w, rhs.w) &&
|
||||
almost_equal (h, rhs.h);
|
||||
return p == rhs.p && e == rhs.e;
|
||||
}
|
||||
|
||||
|
||||
@ -357,8 +350,8 @@ util::region<S,T>::operator== (region rhs) const
|
||||
template <size_t S, typename T>
|
||||
void
|
||||
util::region<S,T>::sanity (void) const {
|
||||
CHECK_GE (w, 0);
|
||||
CHECK_GE (h, 0);
|
||||
CHECK_GE (e.area (), 0);
|
||||
|
||||
static_assert(!std::is_floating_point<T>::value,
|
||||
"Floating point types need width and height checks");
|
||||
}
|
||||
@ -368,15 +361,13 @@ util::region<S,T>::sanity (void) const {
|
||||
namespace util {
|
||||
template <>
|
||||
void region<2,double>::sanity (void) const {
|
||||
CHECK_GE (w, 0);
|
||||
CHECK_GE (h, 0);
|
||||
CHECK_GE (e.area (), 0);
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
void region<2,float>::sanity (void) const {
|
||||
CHECK_GE (w, 0);
|
||||
CHECK_GE (h, 0);
|
||||
CHECK_GE (e.area (), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -393,22 +384,20 @@ template <size_t S, typename T>
|
||||
const util::region<S,T>
|
||||
util::region<S,T>::MAX (
|
||||
std::numeric_limits<T>::lowest () / 2,
|
||||
std::numeric_limits<T>::lowest () / 2,
|
||||
std::numeric_limits<T>::max (),
|
||||
std::numeric_limits<T>::max ()
|
||||
);
|
||||
|
||||
|
||||
template <size_t S, typename T>
|
||||
const util::region<S,T>
|
||||
util::region<S,T>::UNIT (0, 0, 1, 1);
|
||||
util::region<S,T>::UNIT ({0}, {1});
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
std::ostream&
|
||||
util::operator<< (std::ostream &os, const util::region<S,T> &rhs) {
|
||||
os << "region(" << rhs.x << ", " << rhs.y << ", " << rhs.w << ", " << rhs.h << ")";
|
||||
os << "region(" << rhs.p << ", " << rhs.e << ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
46
region.hpp
46
region.hpp
@ -35,22 +35,43 @@ namespace util {
|
||||
using position_type = T;
|
||||
using size_type = typename try_unsigned<T>::type;
|
||||
|
||||
static constexpr size_t dimension = S;
|
||||
static constexpr size_t elements = dimension * 2;
|
||||
using value_type = T;
|
||||
|
||||
using extent_t = util::extent<S,size_type>;
|
||||
using point_t = util::point<S,position_type>;
|
||||
|
||||
position_type x, y;
|
||||
size_type w, h;
|
||||
using value_type = T;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
static constexpr size_t dimension = S;
|
||||
static constexpr size_t elements = extent_t::elements + point_t::elements;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#if defined(COMPILER_GCC)
|
||||
#pragma GCC diagnostic ignored "-pedantic"
|
||||
#endif
|
||||
#if defined(COMPILER_CLANG)
|
||||
#pragma GCC diagnostic ignored "-Wgnu"
|
||||
#endif
|
||||
union {
|
||||
struct {
|
||||
point_t p;
|
||||
extent_t e;
|
||||
};
|
||||
struct {
|
||||
T x, y;
|
||||
T w, h;
|
||||
};
|
||||
};
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
region () = default;
|
||||
region (extent_t);
|
||||
region (point_t, extent_t);
|
||||
region (point_t, point_t);
|
||||
region (T _x, T _y, size_type _w, size_type _h);
|
||||
region (std::array<T,S*2>);
|
||||
region (position_type, size_type);
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
size_type area (void) const;
|
||||
size_type diameter (void) const;
|
||||
extent_t magnitude (void) const;
|
||||
@ -60,13 +81,13 @@ namespace util {
|
||||
|
||||
bool empty (void) const;
|
||||
|
||||
point_t rebase (point_t);
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
point_t base (void) const;
|
||||
point_t away (void) const;
|
||||
point_t centre (void) const;
|
||||
point_t closest (point_t) const;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
// Point and region relation queries
|
||||
bool includes (point_t) const; // inclusive of borders
|
||||
bool contains (point_t) const; // exclusive of borders
|
||||
@ -79,14 +100,17 @@ namespace util {
|
||||
// Compute binary region combinations
|
||||
region intersection (region<S,T>) const;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
region& resize (extent<S,T>);
|
||||
|
||||
// Compute a region `mag` units into the region
|
||||
region inset (T mag);
|
||||
|
||||
region expanded (T mag) const;
|
||||
region expanded (T w, T h) const;
|
||||
region expanded (vector<S,T>) const;
|
||||
|
||||
region& expand (T mag);
|
||||
region& expand (T w, T h);
|
||||
region& expand (vector<S,T>);
|
||||
|
||||
// arithmetic operators
|
||||
region operator+ (vector<S,T>) const;
|
||||
|
@ -167,15 +167,20 @@ template <>
|
||||
void
|
||||
test_region<1> (void)
|
||||
{
|
||||
static const util::bezier<1> upright ({{0.f, 0.f}, {100.f, 100.f}});
|
||||
static const util::bezier<1> downleft ({{100.f, 100.f}, {0.f, 0.f}});
|
||||
static const util::bezier<1> vertical ({{0.f, 0.f}, {0.f, 100.f}});
|
||||
static const util::bezier<1> horizontal ({{0.f, 0.f}, {100.f, 0.f}});
|
||||
util::point2f p0 { 0, 0 },
|
||||
p1 { 100, 0 },
|
||||
p2 { 100, 100 },
|
||||
p3 { 0, 100 };
|
||||
|
||||
CHECK_EQ (upright.region (), util::region2f (0.f, 0.f, 100.f, 100.f));
|
||||
CHECK_EQ (downleft.region (), util::region2f (0.f, 0.f, 100.f, 100.f));
|
||||
CHECK_EQ (vertical.region (), util::region2f (0.f, 0.f, 0.f, 100.f));
|
||||
CHECK_EQ (horizontal.region (), util::region2f (0.f, 0.f, 100.f, 0.f));
|
||||
static const util::bezier<1> upright ({p0, p2});
|
||||
static const util::bezier<1> downleft ({p2, p0});
|
||||
static const util::bezier<1> vertical ({p0, p3});
|
||||
static const util::bezier<1> horizontal ({p0, p2});
|
||||
|
||||
CHECK_EQ (upright.region (), util::region2f (p0, p2));
|
||||
CHECK_EQ (downleft.region (), util::region2f (p0, p2));
|
||||
CHECK_EQ (vertical.region (), util::region2f (p0, p3));
|
||||
CHECK_EQ (horizontal.region (), util::region2f (p0, p2));
|
||||
}
|
||||
|
||||
|
||||
@ -184,9 +189,13 @@ template <>
|
||||
void
|
||||
test_region<2> (void)
|
||||
{
|
||||
static const util::bezier<2> upright({{0.f, 0.f}, {50.f, 50.f}, {100.f, 100.f}});
|
||||
util::point2f p0 { 0, 0 },
|
||||
p1 { 50, 50 },
|
||||
p2 { 100, 100 };
|
||||
|
||||
CHECK_EQ (upright.region (), util::region2f (0.0f, 0.f, 100.f, 100.0f));
|
||||
static const util::bezier<2> upright({p0, p1, p2});
|
||||
|
||||
CHECK_EQ (upright.region (), util::region2f (p0, p2));
|
||||
}
|
||||
|
||||
|
||||
@ -195,9 +204,14 @@ template <>
|
||||
void
|
||||
test_region<3> (void)
|
||||
{
|
||||
static const util::bezier<3> upright({{0.f, 0.f}, {33.f, 33.f}, {67.f, 67.f}, {100.f, 100.f}});
|
||||
util::point2f p0 { 0, 0 },
|
||||
p1 { 33, 33 },
|
||||
p2 { 67, 67 },
|
||||
p3 { 100, 100 };
|
||||
|
||||
CHECK_EQ (upright.region (), util::region2f (0.0f, 0.f, 100.f, 100.0f));
|
||||
static const util::bezier<3> upright({p0, p1, p2, p3});
|
||||
|
||||
CHECK_EQ (upright.region (), util::region2f (p0, p3));
|
||||
}
|
||||
|
||||
|
||||
|
@ -7,8 +7,14 @@ using namespace util;
|
||||
int
|
||||
main (int, char **) {
|
||||
{
|
||||
region2d a {32.7, -6.09703, 0.8, 2};
|
||||
region2d b {33.5, -4.5, 0.5, 0.5};
|
||||
util::point2d ap { 32.7, -6.09703 };
|
||||
util::extent2d ae { 0.8, 2. };
|
||||
|
||||
util::point2d bp {33.5, -4.5};
|
||||
util::extent2d be { 0.5, 0.5 };
|
||||
|
||||
region2d a (ap, ae);
|
||||
region2d b (bp, be);
|
||||
|
||||
CHECK (!a.intersects (b));
|
||||
}
|
||||
@ -19,13 +25,16 @@ main (int, char **) {
|
||||
CHECK_EQ (region2d::UNIT.area (), 1.0);
|
||||
CHECK_EQ (region2f::UNIT.area (), 1.0f);
|
||||
|
||||
CHECK (region2u (0, 0, 2, 2).includes (point2u {1, 1}));
|
||||
CHECK (region2u (0, 0, 2, 2).includes (point2u {0, 0}));
|
||||
CHECK (region2u (0, 0, 2, 2).includes (point2u {2, 2}));
|
||||
util::point2u p0 { 0 };
|
||||
util::extent2u e0 { 2 };
|
||||
|
||||
CHECK ( region2u (0, 0, 2, 2).contains (point2u {1, 1}));
|
||||
CHECK (!region2u (0, 0, 2, 2).contains (point2u {0, 0}));
|
||||
CHECK (!region2u (0, 0, 2, 2).contains (point2u {2, 2}));
|
||||
CHECK (region2u (p0, e0).includes (point2u {1, 1}));
|
||||
CHECK (region2u (p0, e0).includes (point2u {0, 0}));
|
||||
CHECK (region2u (p0, e0).includes (point2u {2, 2}));
|
||||
|
||||
CHECK ( region2u (p0, e0).contains (point2u {1, 1}));
|
||||
CHECK (!region2u (p0, e0).contains (point2u {0, 0}));
|
||||
CHECK (!region2u (p0, e0).contains (point2u {2, 2}));
|
||||
|
||||
//CHECK (region<2,intmax_t> (0, 0, 10, 10).includes (point2d (0.4, 0.01)));
|
||||
//CHECK (region<2,intmax_t> (0, 0, 10, 10).contains (point2d (0.4, 0.01)));
|
||||
|
252
vector.cpp
252
vector.cpp
@ -28,209 +28,11 @@
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
|
||||
#if defined(COMPILER_GCC)
|
||||
#pragma GCC optimize("-O3")
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
using namespace util;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>
|
||||
util::vector<S,T>::operator* (T rhs) const {
|
||||
util::vector<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] * rhs;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>&
|
||||
util::vector<S,T>::operator*= (T rhs) {
|
||||
for (auto &i: this->data)
|
||||
i *= rhs;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>
|
||||
util::vector<S,T>::operator* (const vector<S,T> &rhs) const {
|
||||
util::vector<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] * rhs.data[i];
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>&
|
||||
util::vector<S,T>::operator*= (const vector<S,T> &rhs) {
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
this->data[i] *= rhs.data[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>
|
||||
util::vector<S,T>::operator/ (T rhs) const {
|
||||
util::vector<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] / rhs;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>&
|
||||
util::vector<S,T>::operator/= (T rhs) {
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
this->data[i] /= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>
|
||||
util::vector<S,T>::operator+ (const util::vector<S,T> &rhs) const {
|
||||
util::vector<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] + rhs.data[i];
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>
|
||||
util::vector<S,T>::operator+ (T rhs) const {
|
||||
util::vector<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] + rhs;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>&
|
||||
util::vector<S,T>::operator+= (const util::vector<S,T> &rhs) {
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
this->data[i] += rhs.data[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>&
|
||||
util::vector<S,T>::operator+= (T rhs) {
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
this->data[i] += rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>
|
||||
util::vector<S,T>::operator- (void) const {
|
||||
util::vector<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = -this->data[i];
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>
|
||||
util::vector<S,T>::operator- (const util::vector<S,T> &rhs) const {
|
||||
util::vector<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] - rhs.data[i];
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>&
|
||||
util::vector<S,T>::operator-= (const util::vector<S,T> &rhs) {
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
this->data[i] -= rhs.data[i];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>
|
||||
util::vector<S,T>::operator- (T rhs) const {
|
||||
util::vector<S,T> out;
|
||||
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
out.data[i] = this->data[i] - rhs;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>&
|
||||
util::vector<S,T>::operator-= (T rhs) {
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
this->data[i] -= rhs;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
util::vector<S,T>&
|
||||
util::vector<S,T>::operator= (const util::vector<S,T> &rhs) {
|
||||
std::copy (std::begin (rhs.data), std::end (rhs.data), std::begin (this->data));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T>
|
||||
bool
|
||||
util::vector<S,T>::operator== (const util::vector<S,T> &rhs) const {
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
if (!almost_equal (this->data[i], rhs.data[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
T
|
||||
@ -306,16 +108,6 @@ util::polar_to_cartesian (const util::vector<2,T> &v) {
|
||||
};
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
T
|
||||
util::vector<S,T>::dot (const util::vector<S,T> &rhs) const {
|
||||
T total { 0 };
|
||||
for (size_t i = 0; i < S; ++i)
|
||||
total += this->data[i] * rhs.data[i];
|
||||
return total;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
@ -386,44 +178,6 @@ util::vector<S,T>::sanity (void) const {
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
template <size_t S, typename T, typename U>
|
||||
util::vector<S,T>
|
||||
util::operator* (U a, const util::vector<S,T> &b)
|
||||
{
|
||||
return b * T(a);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T, typename U>
|
||||
util::vector<S,T>
|
||||
util::operator+ (U a, const util::vector<S,T> &b)
|
||||
{
|
||||
return b + T(a);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T, typename U>
|
||||
util::vector<S,T>
|
||||
util::operator- (U a, const util::vector<S,T> &b)
|
||||
{
|
||||
return a + (-b);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <size_t S, typename T>
|
||||
T
|
||||
util::dot (vector<S,T> a, vector<S,T> b)
|
||||
{
|
||||
return std::inner_product (std::begin (a),
|
||||
std::end (a),
|
||||
std::begin (b),
|
||||
T{0});
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// ostream
|
||||
|
||||
@ -460,12 +214,6 @@ util::operator>> (const json::tree::node &node, util::vector<S,T> &v) {
|
||||
|
||||
#define INSTANTIATE_S_T(S,T) \
|
||||
template struct util::vector<S,T>; \
|
||||
template util::vector<S,T> util::operator* (int, const util::vector<S,T>&); \
|
||||
template util::vector<S,T> util::operator* (unsigned, const util::vector<S,T>&); \
|
||||
template util::vector<S,T> util::operator* (float, const util::vector<S,T>&); \
|
||||
template util::vector<S,T> util::operator+ (T, const util::vector<S,T>&); \
|
||||
template util::vector<S,T> util::operator- (T, const util::vector<S,T>&); \
|
||||
template T util::dot (util::vector<S,T>, util::vector<S,T>); \
|
||||
template std::ostream& util::operator<< (std::ostream&, const util::vector<S,T> &v);\
|
||||
template const json::tree::node& util::operator>> (const json::tree::node&, util::vector<S,T>&);
|
||||
|
||||
|
37
vector.hpp
37
vector.hpp
@ -32,35 +32,6 @@ namespace util {
|
||||
struct vector : public detail::coord<S,T,detail::xyzw,detail::stpq> {
|
||||
using detail::coord<S,T,detail::xyzw,detail::stpq>::coord;
|
||||
|
||||
// arithmetic operators
|
||||
vector<S,T> operator* (T) const;
|
||||
vector<S,T>& operator*=(T);
|
||||
|
||||
vector<S,T> operator/ (T) const;
|
||||
vector<S,T>& operator/=(T);
|
||||
|
||||
vector<S,T> operator+ (T) const;
|
||||
vector<S,T>& operator+=(T);
|
||||
|
||||
vector<S,T> operator- (T) const;
|
||||
vector<S,T>& operator-=(T);
|
||||
|
||||
// element operators
|
||||
vector<S,T> operator* (const vector<S,T>&) const;
|
||||
vector<S,T>& operator*=(const vector<S,T>&);
|
||||
|
||||
vector<S,T> operator+ (const vector<S,T>&) const;
|
||||
vector<S,T>& operator+=(const vector<S,T>&);
|
||||
|
||||
vector<S,T> operator- (void) const;
|
||||
vector<S,T> operator- (const vector<S,T>&) const;
|
||||
vector<S,T>& operator-=(const vector<S,T>&);
|
||||
|
||||
vector<S, T>& operator =(const vector<S,T>&);
|
||||
|
||||
// logical operators
|
||||
bool operator== (const vector<S,T>&) const;
|
||||
|
||||
bool is_zero (void) const;
|
||||
|
||||
// vector operators
|
||||
@ -70,8 +41,6 @@ namespace util {
|
||||
T difference (const vector<S,T>&) const;
|
||||
T difference2 (const vector<S,T>&) const;
|
||||
|
||||
T dot (const vector<S,T>&) const;
|
||||
|
||||
vector<S,T>& normalise (void);
|
||||
vector<S,T> normalised [[gnu::warn_unused_result]] (void) const;
|
||||
|
||||
@ -93,12 +62,6 @@ namespace util {
|
||||
template <typename T> vector<3,T> spherical_to_cartesian (const vector<3,T>&);
|
||||
template <typename T> vector<3,T> cartesian_to_spherical (const vector<3,T>&);
|
||||
|
||||
template <size_t S, typename T, typename U> vector<S,T> operator* (U, const vector<S,T>&);
|
||||
template <size_t S, typename T, typename U> vector<S,T> operator+ (U, const vector<S,T>&);
|
||||
template <size_t S, typename T, typename U> vector<S,T> operator- (U, const vector<S,T>&);
|
||||
|
||||
template <size_t S, typename T> T dot (vector<S,T>, vector<S,T>);
|
||||
|
||||
// output and serialisation operators
|
||||
template <size_t S, typename T> std::ostream& operator<< (std::ostream&, const vector<S,T>&);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user