1 // SPDX-FileCopyrightText: 2002 Dominique Devriese <devriese@kde.org>
2
3 // SPDX-License-Identifier: GPL-2.0-or-later
4
5 #include "rect.h"
6 #include "common.h"
7
operator =(const Rect & other)8 Rect& Rect::operator=( const Rect& other )
9 {
10 if (this != &other)
11 {
12 setBottomLeft( other.bottomLeft() );
13 setWidth( other.width() );
14 setHeight( other.height() );
15 }
16 normalize();
17 return *this;
18 }
19
operator ==(const Rect & r,const Rect & s)20 bool operator==( const Rect& r, const Rect& s )
21 {
22 return ( r.bottomLeft() == s.bottomLeft()
23 && r.width() == s.width()
24 && r.height() == s.height() );
25 }
26
operator <<(QDebug & s,const Rect & t)27 QDebug& operator<<( QDebug& s, const Rect& t )
28 {
29 s << "left: " << t.left()
30 << "bottom: " << t.bottom()
31 << "right: " << t.right()
32 << "top: " << t.top();
33 return s;
34 }
35
Rect(const Coordinate & bottomLeft,const Coordinate & topRight)36 Rect::Rect( const Coordinate &bottomLeft, const Coordinate &topRight )
37 : mBottomLeft(bottomLeft)
38 {
39 mwidth = topRight.x - bottomLeft.x;
40 mheight = topRight.y - bottomLeft.y;
41 normalize();
42 }
43
Rect(const Coordinate & p,const double width,const double height)44 Rect::Rect( const Coordinate &p, const double width, const double height )
45 : mBottomLeft(p),
46 mwidth(width),
47 mheight(height)
48 {
49 normalize();
50 }
51
Rect(double xa,double ya,double width,double height)52 Rect::Rect( double xa, double ya, double width, double height )
53 : mBottomLeft( xa, ya ),
54 mwidth( width ),
55 mheight( height )
56 {
57 normalize();
58 }
59
Rect(const Rect & r)60 Rect::Rect( const Rect& r )
61 : mBottomLeft (r.mBottomLeft),
62 mwidth(r.mwidth),
63 mheight(r.mheight)
64 {
65 normalize();
66 }
67
Rect()68 Rect::Rect()
69 : mwidth(0),
70 mheight(0)
71 {
72 }
73
setBottomLeft(const Coordinate & p)74 void Rect::setBottomLeft( const Coordinate &p )
75 {
76 mBottomLeft = p;
77 }
78
setBottomRight(const Coordinate & p)79 void Rect::setBottomRight( const Coordinate &p )
80 {
81 mBottomLeft = p - Coordinate(mwidth,0);
82 }
83
setTopRight(const Coordinate & p)84 void Rect::setTopRight( const Coordinate &p )
85 {
86 mBottomLeft = p - Coordinate(mwidth, mheight);
87 }
88
setCenter(const Coordinate & p)89 void Rect::setCenter( const Coordinate &p )
90 {
91 mBottomLeft = p - Coordinate(mwidth, mheight)/2;
92 }
93
setLeft(const double p)94 void Rect::setLeft( const double p )
95 {
96 double r = right();
97 mBottomLeft.x = p;
98 setRight( r );
99 }
100
setRight(const double p)101 void Rect::setRight( const double p )
102 {
103 mwidth = p - left();
104 }
105
setBottom(const double p)106 void Rect::setBottom( const double p )
107 {
108 double t = top();
109 mBottomLeft.y = p;
110 setTop( t );
111 }
112
setTop(const double p)113 void Rect::setTop( const double p )
114 {
115 mheight = p - bottom();
116 }
117
setWidth(const double w)118 void Rect::setWidth( const double w )
119 {
120 mwidth = w;
121 }
122
setHeight(const double h)123 void Rect::setHeight( const double h )
124 {
125 mheight = h;
126 }
127
normalize()128 void Rect::normalize()
129 {
130 if ( mwidth < 0 )
131 {
132 mBottomLeft.x += mwidth;
133 mwidth = -mwidth;
134 };
135 if ( mheight < 0 )
136 {
137 mBottomLeft.y += mheight;
138 mheight = -mheight;
139 };
140 }
141
moveBy(const Coordinate & p)142 void Rect::moveBy( const Coordinate &p )
143 {
144 mBottomLeft += p;
145 }
146
scale(const double r)147 void Rect::scale( const double r )
148 {
149 mwidth *= r;
150 mheight *= r;
151 }
152
153
toQRect() const154 QRect Rect::toQRect() const
155 {
156 return QRect(mBottomLeft.toQPoint(), topRight().toQPoint());
157 }
158
bottomLeft() const159 Coordinate Rect::bottomLeft() const
160 {
161 return mBottomLeft;
162 }
163
bottomRight() const164 Coordinate Rect::bottomRight() const
165 {
166 return mBottomLeft + Coordinate(mwidth, 0);
167 }
168
topLeft() const169 Coordinate Rect::topLeft() const
170 {
171 return mBottomLeft + Coordinate(0, mheight);
172 }
173
topRight() const174 Coordinate Rect::topRight() const
175 {
176 return mBottomLeft + Coordinate(mwidth, mheight);
177 }
178
center() const179 Coordinate Rect::center() const
180 {
181 return mBottomLeft + Coordinate(mwidth, mheight)/2;
182 }
183
left() const184 double Rect::left() const
185 {
186 return mBottomLeft.x;
187 }
right() const188 double Rect::right() const
189 {
190 return left() + mwidth;
191 }
bottom() const192 double Rect::bottom() const
193 {
194 return mBottomLeft.y;
195 }
196
top() const197 double Rect::top() const
198 {
199 return bottom() + mheight;
200 }
201
width() const202 double Rect::width() const
203 {
204 return mwidth;
205 }
206
height() const207 double Rect::height() const
208 {
209 return mheight;
210 }
211
contains(const Coordinate & p,double allowed_miss) const212 bool Rect::contains( const Coordinate& p, double allowed_miss ) const
213 {
214 return p.x - left() >= - allowed_miss &&
215 p.y - bottom() >= - allowed_miss &&
216 p.x - left() - width() <= allowed_miss &&
217 p.y - bottom() - height() <= allowed_miss;
218 }
219
contains(const Coordinate & p) const220 bool Rect::contains( const Coordinate& p ) const
221 {
222 return p.x >= left() &&
223 p.y >= bottom() &&
224 p.x - left() <= width() &&
225 p.y - bottom() <= height();
226 }
227
intersects(const Rect & p) const228 bool Rect::intersects( const Rect& p ) const
229 {
230 // never thought it was this simple :)
231 if( p.left() < left() && p.right() < left()) return false;
232 if( p.left() > right() && p.right() > right()) return false;
233 if( p.bottom() < bottom() && p.top() < bottom()) return false;
234 if( p.bottom() > top() && p.top() > top()) return false;
235 return true;
236 }
237
setContains(const Coordinate & p)238 void Rect::setContains( const Coordinate &p )
239 {
240 normalize();
241 if( p.x < left() ) setLeft( p.x );
242 if( p.x > right() ) setRight(p.x);
243 if( p.y < bottom() ) setBottom( p.y );
244 if( p.y > top() ) setTop( p.y );
245 }
246
normalized() const247 Rect Rect::normalized() const
248 {
249 Rect t = *this;
250 (void) t.normalize();
251 return t;
252 }
253
fromQRect(const QRect & r)254 Rect Rect::fromQRect( const QRect& r )
255 {
256 return Rect( r.left(), r.top(), r.right(), r.bottom() );
257 }
258
setTopLeft(const Coordinate & p)259 void Rect::setTopLeft( const Coordinate &p )
260 {
261 Coordinate bl = Coordinate( p.x, p.y - mheight );
262 setBottomLeft( bl );
263 }
264
operator |(const Rect & lhs,const Rect & rhs)265 Rect operator|( const Rect& lhs, const Rect& rhs )
266 {
267 Rect r( lhs );
268 r |= rhs;
269 return r;
270 }
271
eat(const Rect & r)272 void Rect::eat( const Rect& r )
273 {
274 setLeft( kigMin( left(), r.left() ) );
275 setRight( kigMax( right(), r.right() ) );
276 setBottom( kigMin( bottom(), r.bottom() ) );
277 setTop( kigMax( top(), r.top() ) );
278 }
279
matchShape(const Rect & rhs,bool shrink) const280 Rect Rect::matchShape( const Rect& rhs, bool shrink ) const
281 {
282 Rect ret = *this;
283 Coordinate c = center();
284 double v = width()/height(); // current ratio
285 double w = rhs.width()/rhs.height(); // wanted ratio
286
287 // we don't show less than r, if the dimensions don't match, we
288 // extend r into some dimension...
289 if( ( v > w ) ^ shrink )
290 ret.setHeight( ret.width() / w );
291 else
292 ret.setWidth( ret.height() * w );
293
294 ret.setCenter(c);
295 return ret.normalized();
296 }
297
valid()298 bool Rect::valid()
299 {
300 return mBottomLeft.valid() && mwidth != double_inf && mheight != double_inf;
301 }
302
invalidRect()303 Rect Rect::invalidRect()
304 {
305 return Rect( Coordinate::invalidCoord(), double_inf, double_inf );
306 }
307