// Copyright (C) 2002 Dominique Devriese // This program 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 2 // of the License, or (at your option) any later version. // This program 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 this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA // 02110-1301, USA. #include "rect.h" #include "common.h" bool operator==( const Rect& r, const Rect& s ) { return ( r.bottomLeft() == s.bottomLeft() && r.width() == s.width() && r.height() == s.height() ); } kdbgstream& operator<<( kdbgstream& s, const Rect& t ) { s << "left: " << t.left() << "bottom: " << t.bottom() << "right: " << t.right() << "top: " << t.top() << endl; return s; } Rect::Rect( const Coordinate bottomLeft, const Coordinate topRight ) : mBottomLeft(bottomLeft) { mwidth = topRight.x - bottomLeft.x; mheight = topRight.y - bottomLeft.y; normalize(); } Rect::Rect( const Coordinate p, const double width, const double height ) : mBottomLeft(p), mwidth(width), mheight(height) { normalize(); } Rect::Rect( double xa, double ya, double width, double height ) : mBottomLeft( xa, ya ), mwidth( width ), mheight( height ) { normalize(); } Rect::Rect( const Rect& r ) : mBottomLeft (r.mBottomLeft), mwidth(r.mwidth), mheight(r.mheight) { normalize(); } Rect::Rect() : mwidth(0), mheight(0) { } void Rect::setBottomLeft( const Coordinate p ) { mBottomLeft = p; } void Rect::setBottomRight( const Coordinate p ) { mBottomLeft = p - Coordinate(mwidth,0); } void Rect::setTopRight( const Coordinate p ) { mBottomLeft = p - Coordinate(mwidth, mheight); } void Rect::setCenter( const Coordinate p ) { mBottomLeft = p - Coordinate(mwidth, mheight)/2; } void Rect::setLeft( const double p ) { double r = right(); mBottomLeft.x = p; setRight( r ); } void Rect::setRight( const double p ) { mwidth = p - left(); } void Rect::setBottom( const double p ) { double t = top(); mBottomLeft.y = p; setTop( t ); } void Rect::setTop( const double p ) { mheight = p - bottom(); } void Rect::setWidth( const double w ) { mwidth = w; } void Rect::setHeight( const double h ) { mheight = h; } void Rect::normalize() { if ( mwidth < 0 ) { mBottomLeft.x += mwidth; mwidth = -mwidth; }; if ( mheight < 0 ) { mBottomLeft.y += mheight; mheight = -mheight; }; } void Rect::moveBy( const Coordinate p ) { mBottomLeft += p; } void Rect::scale( const double r ) { mwidth *= r; mheight *= r; } TQRect Rect::toTQRect() const { return TQRect(mBottomLeft.toTQPoint(), topRight().toTQPoint()); } Coordinate Rect::bottomLeft() const { return mBottomLeft; } Coordinate Rect::bottomRight() const { return mBottomLeft + Coordinate(mwidth, 0); } Coordinate Rect::topLeft() const { return mBottomLeft + Coordinate(0, mheight); } Coordinate Rect::topRight() const { return mBottomLeft + Coordinate(mwidth, mheight); } Coordinate Rect::center() const { return mBottomLeft + Coordinate(mwidth, mheight)/2; } double Rect::left() const { return mBottomLeft.x; } double Rect::right() const { return left() + mwidth; } double Rect::bottom() const { return mBottomLeft.y; } double Rect::top() const { return bottom() + mheight; } double Rect::width() const { return mwidth; } double Rect::height() const { return mheight; } bool Rect::contains( const Coordinate& p, double allowed_miss ) const { return p.x - left() >= - allowed_miss && p.y - bottom() >= - allowed_miss && p.x - left() - width() <= allowed_miss && p.y - bottom() - height() <= allowed_miss; } bool Rect::contains( const Coordinate& p ) const { return p.x >= left() && p.y >= bottom() && p.x - left() <= width() && p.y - bottom() <= height(); } bool Rect::intersects( const Rect& p ) const { // never thought it was this simple :) if( p.left() < left() && p.right() < left()) return false; if( p.left() > right() && p.right() > right()) return false; if( p.bottom() < bottom() && p.top() < bottom()) return false; if( p.bottom() > top() && p.top() > top()) return false; return true; } void Rect::setContains( Coordinate p ) { normalize(); if( p.x < left() ) setLeft( p.x ); if( p.x > right() ) setRight(p.x); if( p.y < bottom() ) setBottom( p.y ); if( p.y > top() ) setTop( p.y ); } Rect Rect::normalized() const { Rect t = *this; (void) t.normalize(); return t; } Rect Rect::fromTQRect( const TQRect& r ) { return Rect( r.left(), r.top(), r.right(), r.bottom() ); } void Rect::setTopLeft( const Coordinate p ) { Coordinate bl = Coordinate( p.x, p.y - mheight ); setBottomLeft( bl ); } Rect operator|( const Rect& lhs, const Rect& rhs ) { Rect r( lhs ); r |= rhs; return r; } void Rect::eat( const Rect& r ) { setLeft( kigMin( left(), r.left() ) ); setRight( kigMax( right(), r.right() ) ); setBottom( kigMin( bottom(), r.bottom() ) ); setTop( kigMax( top(), r.top() ) ); } Rect Rect::matchShape( const Rect& rhs, bool shrink ) const { Rect ret = *this; Coordinate c = center(); double v = width()/height(); // current ratio double w = rhs.width()/rhs.height(); // wanted ratio // we don't show less than r, if the dimensions don't match, we // extend r into some dimension... if( ( v > w ) ^ shrink ) ret.setHeight( ret.width() / w ); else ret.setWidth( ret.height() * w ); ret.setCenter(c); return ret.normalized(); } bool Rect::valid() { return mBottomLeft.valid() && mwidth != double_inf && mheight != double_inf; } Rect Rect::invalidRect() { return Rect( Coordinate::invalidCoord(), double_inf, double_inf ); }