You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeedu/kig/misc/rect.cc

309 lines
6.0 KiB

// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
// 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;
}
QRect Rect::toQRect() const
{
return QRect(mBottomLeft.toQPoint(), topRight().toQPoint());
}
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::fromQRect( const QRect& 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 );
}