/* * This file is part of libgim. * * libgim is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * libgim is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with libgim. If not, see . * * Copyright 2010 Danny Robson */ #include "region.hpp" #include "debug.hpp" #include "types/casts.hpp" #include #include using namespace util; template region::region (T _x, T _y, size_type _w, size_type _h): x (_x), y (_y), w (_w), h (_h) { } template region& region::operator+= (const vector<2> &rhs) { x += rhs.x; y += rhs.y; return *this; } template typename region::size_type region::area (void) const { return w * h; } template typename region::size_type region::diameter (void) const { return static_cast (sqrt (w * w + h * h)); } template bool region::empty (void) const { return almost_equal (area (), 0); } template point<2> region::base (void) const { return { static_cast (x), static_cast (y) }; } template point<2> region::centre (void) const { double cx = x + static_cast(w / 2.0), cy = y + static_cast(h / 2.0); return { cx, cy }; } template bool region::includes (const point<2> &p) const { return p.x >= x && p.y >= y && p.x - x <= w && p.y - y <= h; } template bool region::contains (const point<2> &p) const { return p.x > x && p.y > y && p.x - x < w && p.y - y < h; } template bool region::overlaps (const region &rhs) const { //return !overlap (rhs).empty (); 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 { 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)); 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); } template bool region::operator ==(const region& rhs) const { return almost_equal (x, rhs.x) && almost_equal (y, rhs.y) && almost_equal (w, rhs.w) && almost_equal (h, rhs.h); } template 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 { CHECK (w >= 0 && h >= 0); } template <> void region::sanity (void) const { CHECK (w >= 0 && h >= 0); } } template std::ostream& util::operator<< (std::ostream &os, const region &rhs) { os << "region(" << rhs.x << ", " << rhs.y << ", " << rhs.w << ", " << rhs.h << ")"; return os; } namespace util { template struct region; template struct region; template struct region; template struct region; template struct region; template std::ostream& operator<< (std::ostream&, const region&); template std::ostream& operator<< (std::ostream&, const region&); }