diff --git a/bezier.cpp b/bezier.cpp index b19b5126..0d1744e1 100644 --- a/bezier.cpp +++ b/bezier.cpp @@ -26,22 +26,6 @@ #include -//----------------------------------------------------------------------------- -// HACK: point multiplication isn't defined, but it's way more convenient than -// casting between vector/coord -namespace util { - template - util::point2f - operator* (T a, util::point2f b) - { - return { - a * b.data[0], - a * b.data[1] - }; - } -} - - //----------------------------------------------------------------------------- template util::bezier::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::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 }; } diff --git a/detail/coord.hpp b/detail/coord.hpp index 8f051fe7..2d4517e3 100644 --- a/detail/coord.hpp +++ b/detail/coord.hpp @@ -20,15 +20,30 @@ #ifndef __UTIL_COORD_HPP #define __UTIL_COORD_HPP +#include "../preprocessor.hpp" #include "../platform.hpp" #include #include +#include #include namespace util { + template class point; + template class extent; + template 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 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 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 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 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 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 struct coord : public coord_init { 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::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 &rhs) = default; coord& operator= (const coord &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 - T dot (const coord &a, const coord &b) - { - return std::inner_product (std::begin (a.data), - std::end (a.data), - std::begin (b.data), - T {0}); - } -#pragma GCC diagnostic pop + /////////////////////////////////////////////////////////////////////// + template < + size_t S, + typename T, + template class A, + template class B + > + struct coord_traits { }; + + + template struct coord_traits { typedef extent result; }; + template struct coord_traits { typedef extent result; }; + template struct coord_traits { typedef point result; }; + template struct coord_traits { typedef point result; }; + template struct coord_traits { typedef vector result; }; + } + + + /////////////////////////////////////////////////////////////////////////// + // vector operators +#define ELEMENT_OP(OP) \ + template < \ + size_t S, \ + typename T, \ + template class A, \ + template class B \ + > \ + typename detail::coord_traits::result \ + operator OP (A a, B b) \ + { \ + typename detail::coord_traits::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 class A, \ + template class B \ + > \ + typename detail::coord_traits::result& \ + operator PASTE(OP,=) (A& a, B 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 class K> \ + K \ + operator OP (T t, K k) \ + { \ + K out; \ + for (size_t i = 0; i < S; ++i) \ + out[i] = t OP k[i]; \ + return out; \ + } \ + \ + template class K> \ + K \ + operator OP (K k, T t) \ + { \ + K 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 class K> \ + K& \ + operator OP (K &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 class K> + bool operator== (K a, K b) + { return std::equal (std::begin (a), std::end (a), std::begin (b)); } + + template class K> + bool operator!= (K a, K b) + { return !(a == b); } + + + /////////////////////////////////////////////////////////////////////////// + // special operators + template vector operator- (point a, point b) + { + vector out; + for (size_t i = 0; i < S; ++i) + out[i] = a[i] - b[i]; + return out; + } + + template class A, template class B> + T dot (A a, B b) + { + T sum { 0 }; + for (size_t i = 0; i < S; ++i) + sum += a[i] * b[i]; + return sum; } } diff --git a/extent.cpp b/extent.cpp index 28b78d96..444895b5 100644 --- a/extent.cpp +++ b/extent.cpp @@ -27,9 +27,12 @@ /////////////////////////////////////////////////////////////////////////////// template -util::extent::extent (vector _v): - extent (_v.x, _v.y) -{ ; } +util::extent::extent (vector _v) +{ + std::copy (std::begin (_v.data), + std::end (_v.data), + std::begin (this->data)); +} /////////////////////////////////////////////////////////////////////////////// @@ -87,32 +90,6 @@ util::extent::empty (void) const } -/////////////////////////////////////////////////////////////////////////////// -template -util::extent -util::extent::operator+ (vector rhs) const -{ - extent out; - std::adjacent_difference (std::begin (this->data), - std::end (this->data), - std::begin (rhs.data), - std::plus ()); - return out; -} - - -/////////////////////////////////////////////////////////////////////////////// -template -bool -util::extent::operator ==(const extent& rhs) const -{ - return std::equal (std::begin (this->data), - std::end (this->data), - std::begin (rhs.data), - almost_equal); -} - - /////////////////////////////////////////////////////////////////////////////// template const util::extent util::extent::MIN { 0 }; @@ -131,7 +108,9 @@ namespace debug { struct validator { static bool is_valid (const util::extent &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 std::ostream& util::operator<< (std::ostream &os, util::extent e) { - os << "[" << e.w << ", " << e.h << "]"; + os << "["; + std::copy (std::begin (e.data), + std::end (e.data), + std::ostream_iterator (os, ", ")); + os << "]"; return os; } diff --git a/extent.hpp b/extent.hpp index 1409ada5..62723d19 100644 --- a/extent.hpp +++ b/extent.hpp @@ -30,8 +30,10 @@ namespace util { * A pure two-dimensional size, without positioning */ template - struct extent : public detail::coord { + struct extent : public detail::coord + { using detail::coord::coord; + extent () = default; extent (vector); @@ -43,12 +45,6 @@ namespace util { bool empty (void) const; - extent operator+ (vector) const; - - bool operator ==(const extent& rhs) const; - bool operator !=(const extent& rhs) const - { return !(*this == rhs); } - template extent 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 std::ostream& operator<< (std::ostream&, util::extent); diff --git a/noise/basis.cpp b/noise/basis.cpp index d565dc1e..f7c62326 100644 --- a/noise/basis.cpp +++ b/noise/basis.cpp @@ -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 (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); diff --git a/point.cpp b/point.cpp index e0141805..104e55fc 100644 --- a/point.cpp +++ b/point.cpp @@ -27,112 +27,6 @@ using namespace std; -#if defined(COMPILER_GCC) - #pragma GCC optimize("-O3") -#endif - -//----------------------------------------------------------------------------- -template -util::point& -util::point::operator*= (T f) { - for (auto &i: this->data) - i *= f; - - return *this; -} - - -template -util::point -util::point::operator* (T f) const { - util::point out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] * f; - return out; -} - - -//----------------------------------------------------------------------------- -template -util::point& -util::point::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 -util::point -util::point::operator/ (T f) const -{ - point out; - - std::transform (std::begin (this->data), - std::end (this->data), - std::begin (out.data), - [f] (auto i) { return i / f; }); - - return out; -} - -//----------------------------------------------------------------------------- -template -util::point -util::point::operator- (const vector &rhs) const { - util::point out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] - rhs.data[i]; - return out; -} - - -template -util::point& -util::point::operator-= (const util::vector &rhs) { - for (size_t i = 0; i < S; ++i) - this->data[i] -= rhs.data[i]; - return *this; -} - -//----------------------------------------------------------------------------- -template -util::point -util::point::operator+ (const vector &rhs) const { - util::point out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] + rhs.data[i]; - return out; -} - - -template -util::point& -util::point::operator+= (const util::vector &rhs) { - for (size_t i = 0; i < S; ++i) - this->data[i] += rhs.data[i]; - return *this; -} - - -//----------------------------------------------------------------------------- -template -util::vector -util::point::operator- (const point &rhs) const { - util::vector out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] - rhs.data[i]; - return out; -} - //----------------------------------------------------------------------------- template @@ -146,17 +40,6 @@ util::point::to (const point &rhs) const { } -//----------------------------------------------------------------------------- -template -bool -util::point::operator== (const util::point &rhs) const -{ - return std::equal (std::begin (this->data), - std::end (this->data), - std::begin (rhs.data)); -} - - //----------------------------------------------------------------------------- template void diff --git a/point.hpp b/point.hpp index 9f811fd1..6bd94454 100644 --- a/point.hpp +++ b/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 - struct point : public detail::coord { + struct point : public detail::coord + { using detail::coord::coord; // point operators @@ -41,22 +43,6 @@ namespace util { vector to (const point&) const; - // arithetic operators - point& operator*= (T); - point operator* (T) const; - point& operator/= (T); - point operator/ (T) const; - - vector operator- (const point&) const; - - point operator- (const vector&) const; - point& operator-= (const vector&); - point operator+ (const vector&) const; - point& operator+= (const vector&); - - // logical operators - bool operator== (const point&) const; - template point redim (void) const; template point redim (const util::point &fill) const; template point redim (T fill) const; diff --git a/quaternion.cpp b/quaternion.cpp index 5f332329..4e8ca3f7 100644 --- a/quaternion.cpp +++ b/quaternion.cpp @@ -52,7 +52,7 @@ quaternion::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 diff --git a/region.cpp b/region.cpp index c72cf0c0..2365e702 100644 --- a/region.cpp +++ b/region.cpp @@ -36,12 +36,10 @@ util::region::region (extent_t _extent): //----------------------------------------------------------------------------- template -util::region::region (point_t _point, - extent_t _size): - x (_point.x), - y (_point.y), - w (_size.w), - h (_size.h) +util::region::region (point_t _p, + extent_t _e): + p (_p), + e (_e) { ; } @@ -50,19 +48,25 @@ template util::region::region (point_t _a, point_t _b): region (_a, _b - _a) +{ ; } + + +//----------------------------------------------------------------------------- +template +util::region::region (std::array 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 -util::region::region (position_type _x, - position_type _y, - size_type _w, - size_type _h): - region (point_t {_x, _y}, extent {_w, _h}) -{ ; } +util::region::region (position_type _p, + size_type _e): + region (point_t {_p}, extent_t {_e}) +{ + +} //----------------------------------------------------------------------------- @@ -70,7 +74,7 @@ template typename util::region::size_type util::region::area (void) const { - return w * h; + return e.area (); } @@ -79,7 +83,7 @@ template typename util::region::size_type util::region::diameter (void) const { - return static_cast (std::sqrt (w * w + h * h)); + return e.diameter (); } @@ -88,19 +92,17 @@ template typename util::region::extent_t util::region::magnitude (void) const { - return { w, h }; + return e; } //----------------------------------------------------------------------------- template typename util::region::extent_t -util::region::magnitude (extent_t e) +util::region::magnitude (extent_t _e) { - w = e.w; - h = e.h; - - return magnitude (); + e = _e; + return e; } @@ -109,11 +111,9 @@ template void util::region::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::empty (void) const } -//----------------------------------------------------------------------------- -template -typename util::region::point_t -util::region::rebase (point_t p) -{ - x = p.x; - y = p.y; - - return base (); -} - - //----------------------------------------------------------------------------- template typename util::region::point_t util::region::base (void) const { - return { x, y }; + return p; } @@ -152,7 +140,7 @@ template typename util::region::point_t util::region::away (void) const { - return { x + w, y + h }; + return p + e; } @@ -161,51 +149,49 @@ template typename util::region::point_t util::region::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 typename util::region::point_t -util::region::closest (point_t p) const +util::region::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 bool -util::region::includes (point_t p) const +util::region::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 bool -util::region::contains (point_t p) const +util::region::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 bool util::region::intersects (region 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 void -util::region::constrain (point_t &p) const +util::region::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 typename util::region::point_t -util::region::constrained (point_t p) const +util::region::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 util::region util::region::intersection (region rhs) const { - T newx1 = max (x, rhs.x), - newy1 = max (y, rhs.y), - newx2 = min (x + sign_cast (w), rhs.x + sign_cast (rhs.w)), - newy2 = min (y + sign_cast (h), rhs.y + sign_cast (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 (newx2 - newx1); - size_type nh = sign_cast (newy2 - newy1); - return util::region (newx1, newy1, nw, nh); -} + if (b[i] < a[i]) + throw std::logic_error ("no overlap"); + } - -//----------------------------------------------------------------------------- -template -util::region -util::region::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 util::region& -util::region::expand (T _w, T _h) +util::region::resize (extent _e) { - x -= _w; - y -= _h; - w += _w * 2; - h += _h * 2; + e = _e; + return *this; +} + +//----------------------------------------------------------------------------- +template +util::region +util::region::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 +util::region& +util::region::expand (vector v) +{ + p -= v; + e += v * T{2}; return *this; } @@ -296,20 +294,18 @@ template util::region& util::region::expand (T mag) { - return expand (mag, mag); + return expand ({mag}); } //----------------------------------------------------------------------------- template util::region -util::region::expanded (T _w, T _h) const +util::region::expanded (vector v) const { return { - x - _w, - y - _h, - w + _w * 2, - h + _h * 2, + p - v, + e + v * T{2} }; } @@ -319,7 +315,7 @@ template util::region util::region::expanded (T mag) const { - return expanded (mag, mag); + return expanded ({mag}); } @@ -328,7 +324,7 @@ template util::region util::region::operator+ (vector rhs) const { - return { x + rhs.x, y + rhs.y, w, h }; + return { p + rhs, e }; } @@ -337,7 +333,7 @@ template util::region util::region::operator- (vector rhs) const { - return { x - rhs.x, y - rhs.y, w, h }; + return { p - rhs, e }; } @@ -346,10 +342,7 @@ template bool util::region::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::operator== (region rhs) const template void util::region::sanity (void) const { - CHECK_GE (w, 0); - CHECK_GE (h, 0); + CHECK_GE (e.area (), 0); + static_assert(!std::is_floating_point::value, "Floating point types need width and height checks"); } @@ -368,15 +361,13 @@ util::region::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 const util::region util::region::MAX ( std::numeric_limits::lowest () / 2, - std::numeric_limits::lowest () / 2, - std::numeric_limits::max (), std::numeric_limits::max () ); template const util::region -util::region::UNIT (0, 0, 1, 1); +util::region::UNIT ({0}, {1}); //----------------------------------------------------------------------------- template std::ostream& util::operator<< (std::ostream &os, const util::region &rhs) { - os << "region(" << rhs.x << ", " << rhs.y << ", " << rhs.w << ", " << rhs.h << ")"; + os << "region(" << rhs.p << ", " << rhs.e << ")"; return os; } diff --git a/region.hpp b/region.hpp index 840ebdc8..e70c3712 100644 --- a/region.hpp +++ b/region.hpp @@ -35,22 +35,43 @@ namespace util { using position_type = T; using size_type = typename try_unsigned::type; - static constexpr size_t dimension = S; - static constexpr size_t elements = dimension * 2; - using value_type = T; - using extent_t = util::extent; using point_t = util::point; - 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); + 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) const; + //--------------------------------------------------------------------- + region& resize (extent); + // 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) const; region& expand (T mag); - region& expand (T w, T h); + region& expand (vector); // arithmetic operators region operator+ (vector) const; diff --git a/test/bezier.cpp b/test/bezier.cpp index 0d304c6a..51aff935 100644 --- a/test/bezier.cpp +++ b/test/bezier.cpp @@ -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)); } diff --git a/test/region.cpp b/test/region.cpp index d0b3aa5a..4a7578c4 100644 --- a/test/region.cpp +++ b/test/region.cpp @@ -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))); diff --git a/vector.cpp b/vector.cpp index 9c6f1dc6..1dea169f 100644 --- a/vector.cpp +++ b/vector.cpp @@ -28,209 +28,11 @@ #include #include -#if defined(COMPILER_GCC) -#pragma GCC optimize("-O3") -#endif //----------------------------------------------------------------------------- using namespace util; -//----------------------------------------------------------------------------- -template -util::vector -util::vector::operator* (T rhs) const { - util::vector out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] * rhs; - - return out; -} - - -//----------------------------------------------------------------------------- -template -util::vector& -util::vector::operator*= (T rhs) { - for (auto &i: this->data) - i *= rhs; - - return *this; -} - - -//----------------------------------------------------------------------------- -template -util::vector -util::vector::operator* (const vector &rhs) const { - util::vector out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] * rhs.data[i]; - - return out; -} - - -//----------------------------------------------------------------------------- -template -util::vector& -util::vector::operator*= (const vector &rhs) { - for (size_t i = 0; i < S; ++i) - this->data[i] *= rhs.data[i]; - - return *this; -} - - -//----------------------------------------------------------------------------- -template -util::vector -util::vector::operator/ (T rhs) const { - util::vector out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] / rhs; - return out; -} - - -//----------------------------------------------------------------------------- -template -util::vector& -util::vector::operator/= (T rhs) { - for (size_t i = 0; i < S; ++i) - this->data[i] /= rhs; - return *this; -} - - -//----------------------------------------------------------------------------- -template -util::vector -util::vector::operator+ (const util::vector &rhs) const { - util::vector out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] + rhs.data[i]; - return out; -} - - -//----------------------------------------------------------------------------- -template -util::vector -util::vector::operator+ (T rhs) const { - util::vector out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] + rhs; - return out; -} - - -//----------------------------------------------------------------------------- -template -util::vector& -util::vector::operator+= (const util::vector &rhs) { - for (size_t i = 0; i < S; ++i) - this->data[i] += rhs.data[i]; - - return *this; -} - - -//----------------------------------------------------------------------------- -template -util::vector& -util::vector::operator+= (T rhs) { - for (size_t i = 0; i < S; ++i) - this->data[i] += rhs; - return *this; -} - - -//----------------------------------------------------------------------------- -template -util::vector -util::vector::operator- (void) const { - util::vector out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = -this->data[i]; - return out; -} - - -//----------------------------------------------------------------------------- -template -util::vector -util::vector::operator- (const util::vector &rhs) const { - util::vector out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] - rhs.data[i]; - return out; -} - - -//----------------------------------------------------------------------------- -template -util::vector& -util::vector::operator-= (const util::vector &rhs) { - for (size_t i = 0; i < S; ++i) - this->data[i] -= rhs.data[i]; - - return *this; -} - - -//----------------------------------------------------------------------------- -template -util::vector -util::vector::operator- (T rhs) const { - util::vector out; - - for (size_t i = 0; i < S; ++i) - out.data[i] = this->data[i] - rhs; - return out; -} - - -//----------------------------------------------------------------------------- -template -util::vector& -util::vector::operator-= (T rhs) { - for (size_t i = 0; i < S; ++i) - this->data[i] -= rhs; - - return *this; -} - - -//----------------------------------------------------------------------------- -template -util::vector& -util::vector::operator= (const util::vector &rhs) { - std::copy (std::begin (rhs.data), std::end (rhs.data), std::begin (this->data)); - - return *this; -} - - -/////////////////////////////////////////////////////////////////////////////// -template -bool -util::vector::operator== (const util::vector &rhs) const { - for (size_t i = 0; i < S; ++i) - if (!almost_equal (this->data[i], rhs.data[i])) - return false; - - return true; -} - - //----------------------------------------------------------------------------- template T @@ -306,16 +108,6 @@ util::polar_to_cartesian (const util::vector<2,T> &v) { }; } -//----------------------------------------------------------------------------- -template -T -util::vector::dot (const util::vector &rhs) const { - T total { 0 }; - for (size_t i = 0; i < S; ++i) - total += this->data[i] * rhs.data[i]; - return total; -} - //----------------------------------------------------------------------------- template @@ -386,44 +178,6 @@ util::vector::sanity (void) const { } -/////////////////////////////////////////////////////////////////////////////// -template -util::vector -util::operator* (U a, const util::vector &b) -{ - return b * T(a); -} - - -//----------------------------------------------------------------------------- -template -util::vector -util::operator+ (U a, const util::vector &b) -{ - return b + T(a); -} - - -//----------------------------------------------------------------------------- -template -util::vector -util::operator- (U a, const util::vector &b) -{ - return a + (-b); -} - - -//----------------------------------------------------------------------------- -template -T -util::dot (vector a, vector 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 &v) { #define INSTANTIATE_S_T(S,T) \ template struct util::vector; \ -template util::vector util::operator* (int, const util::vector&); \ -template util::vector util::operator* (unsigned, const util::vector&); \ -template util::vector util::operator* (float, const util::vector&); \ -template util::vector util::operator+ (T, const util::vector&); \ -template util::vector util::operator- (T, const util::vector&); \ -template T util::dot (util::vector, util::vector); \ template std::ostream& util::operator<< (std::ostream&, const util::vector &v);\ template const json::tree::node& util::operator>> (const json::tree::node&, util::vector&); diff --git a/vector.hpp b/vector.hpp index 816c4547..f1ec03c5 100644 --- a/vector.hpp +++ b/vector.hpp @@ -32,35 +32,6 @@ namespace util { struct vector : public detail::coord { using detail::coord::coord; - // arithmetic operators - vector operator* (T) const; - vector& operator*=(T); - - vector operator/ (T) const; - vector& operator/=(T); - - vector operator+ (T) const; - vector& operator+=(T); - - vector operator- (T) const; - vector& operator-=(T); - - // element operators - vector operator* (const vector&) const; - vector& operator*=(const vector&); - - vector operator+ (const vector&) const; - vector& operator+=(const vector&); - - vector operator- (void) const; - vector operator- (const vector&) const; - vector& operator-=(const vector&); - - vector& operator =(const vector&); - - // logical operators - bool operator== (const vector&) const; - bool is_zero (void) const; // vector operators @@ -70,8 +41,6 @@ namespace util { T difference (const vector&) const; T difference2 (const vector&) const; - T dot (const vector&) const; - vector& normalise (void); vector normalised [[gnu::warn_unused_result]] (void) const; @@ -93,12 +62,6 @@ namespace util { template vector<3,T> spherical_to_cartesian (const vector<3,T>&); template vector<3,T> cartesian_to_spherical (const vector<3,T>&); - template vector operator* (U, const vector&); - template vector operator+ (U, const vector&); - template vector operator- (U, const vector&); - - template T dot (vector, vector); - // output and serialisation operators template std::ostream& operator<< (std::ostream&, const vector&);