diff --git a/region.cpp b/region.cpp index 16af1ed7..4d43f88d 100644 --- a/region.cpp +++ b/region.cpp @@ -21,6 +21,7 @@ #include "region.hpp" #include "debug.hpp" +#include "types/casts.hpp" #include #include @@ -89,8 +90,8 @@ bool region::includes (const point<2> &p) const { return p.x >= x && p.y >= y && - p.x <= x + w && - p.y <= y + h; + p.x - x <= w && + p.y - y <= h; } @@ -99,8 +100,8 @@ bool region::contains (const point<2> &p) const { return p.x > x && p.y > y && - p.x < x + w && - p.y < y + h; + p.x - x < w && + p.y - y < h; } @@ -108,23 +109,28 @@ template bool region::overlaps (const region &rhs) const { //return !overlap (rhs).empty (); - - return x < rhs.x + rhs.w && - x + w > rhs.x && - y < rhs.y + rhs.h && - y + h > rhs.y; + + return x < sign_cast (rhs.w) + rhs.x && + rhs.x < sign_cast ( w) + x && + y < sign_cast (rhs.h) + rhs.y && + rhs.y < sign_cast ( h) + y; } template region region::overlap (const region &rhs) const { - double newx1 = max (x, rhs.x), - newy1 = max (y, rhs.y), - newx2 = min (x + w, rhs.x + w), - newy2 = min (y + h, rhs.y + h); + 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)); - return region (newx1, newy1, newx2 - newx1, newy2 - newy1); + if (newx2 < newx1 || newy2 < newy1) + throw std::logic_error ("No overlap"); + + size_type nw = sign_cast (newx2 - newx1); + size_type nh = sign_cast (newy2 - newy1); + return region (newx1, newy1, nw, nh); } @@ -139,25 +145,30 @@ region::operator ==(const region& rhs) const template -void region::sanity (void) const - { CHECK (w >= 0 && h >= 0); } +void +region::sanity (void) const { + static_assert(!std::is_floating_point::value, + "Floating point types need width and height checks"); +} namespace util { template <> - void region::sanity (void) const - { return; } + void region::sanity (void) const { + CHECK (w >= 0 && h >= 0); + } template <> - void region::sanity (void) const - { return; } + void region::sanity (void) const { + CHECK (w >= 0 && h >= 0); + } } template std::ostream& -operator<< (std::ostream &os, const region &rhs) { +util::operator<< (std::ostream &os, const region &rhs) { os << "region(" << rhs.x << ", " << rhs.y << ", " << rhs.w << ", " << rhs.h << ")"; return os; }