649949e9212f22d45515be5adf1e687b6c68fb91
[platform/core/uifw/dali-core.git] / dali / public-api / math / rect.h
1 #ifndef DALI_RECT_H
2 #define DALI_RECT_H
3
4 /*
5  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <math.h>
23 #include <ostream>
24
25 // INTERNAL INCLUDES
26 #include <dali/public-api/math/math-utils.h>
27
28 namespace Dali
29 {
30 /**
31  * @addtogroup dali_core_math
32  * @{
33  */
34
35 /**
36  * @brief Template class to create and operate on rectangles.
37  * @SINCE_1_0.0
38  */
39
40 template< typename T = float >
41 struct Rect
42 {
43 // Methods
44
45   /**
46    * @brief Constructor.
47    * @SINCE_1_0.0
48    */
49   Rect()
50   : x(0),
51     y(0),
52     width(0),
53     height(0)
54   {
55   }
56
57   /**
58    * @brief Constructor.
59    *
60    * @SINCE_1_0.0
61    * @param[in] x      X coordinate (or left)
62    * @param[in] y      Y coordinate (or right)
63    * @param[in] width  Width (or bottom)
64    * @param[in] height Height (or top)
65    */
66   Rect(T x, T y, T width, T height)
67   : x(x),
68     y(y),
69     width(width),
70     height(height)
71   {
72   }
73
74   /**
75    * @brief Conversion constructor from Vector4.
76    *
77    * @SINCE_1_9.14
78    * @param[in] vec4 Vector4 to convert from
79    */
80   Rect( const Vector4& vec4 )
81   {
82     x = vec4.x;
83     y = vec4.y;
84     width = vec4.z;
85     height = vec4.w;
86   }
87
88   /**
89    * @brief Copy constructor.
90    *
91    * @SINCE_1_0.0
92    * @param[in] rhs The original object
93    */
94   Rect(const Rect<T>& rhs)
95   {
96     x = rhs.x;
97     y = rhs.y;
98     width = rhs.width;
99     height = rhs.height;
100   }
101
102   /**
103    * @brief Assignment operator.
104    *
105    * @SINCE_1_0.0
106    * @param[in] rhs The original object
107    * @return Reference to this
108    */
109   Rect<T>& operator= (const Rect<T>& rhs)
110   {
111     if (this != &rhs)
112     {
113       x = rhs.x;
114       y = rhs.y;
115       width = rhs.width;
116       height = rhs.height;
117     }
118
119     return *this;
120   }
121
122   /**
123    * @brief Assignment from individual values.
124    *
125    * @SINCE_1_0.0
126    * @param[in] newX      X coordinate
127    * @param[in] newY      Y coordinate
128    * @param[in] newWidth  Width
129    * @param[in] newHeight Height
130    */
131   void Set(T newX, T newY, T newWidth, T newHeight)
132   {
133     x = newX;
134     y = newY;
135     width = newWidth;
136     height = newHeight;
137   }
138
139   /**
140    * @brief Determines whether or not this Rectangle is empty.
141    *
142    * @SINCE_1_0.0
143    * @return True if width or height are zero
144    */
145   bool IsEmpty() const
146   {
147     return width  == 0 ||
148       height == 0;
149   }
150
151   /**
152    * @brief Gets the left of the rectangle.
153    *
154    * @SINCE_1_0.0
155    * @return The left edge of the rectangle
156    */
157   T Left() const
158   {
159     return x;
160   }
161   /**
162    * @brief Gets the right of the rectangle.
163    *
164    * @SINCE_1_0.0
165    * @return The right edge of the rectangle
166    */
167   T Right() const
168   {
169     return x + width;
170   }
171
172   /**
173    * @brief Gets the top of the rectangle.
174    *
175    * @SINCE_1_0.0
176    * @return The top of the rectangle
177    */
178   T Top() const
179   {
180     return y;
181   }
182
183   /**
184    * @brief Gets the bottom of the rectangle.
185    *
186    * @SINCE_1_0.0
187    * @return The bottom of the rectangle
188    */
189   T Bottom() const
190   {
191     return y + height;
192   }
193
194   /**
195    * @brief Gets the area of the rectangle.
196    *
197    * @SINCE_1_0.0
198    * @return The area of the rectangle
199    */
200   T Area() const
201   {
202     return width * height;
203   }
204
205   /**
206    * @brief Determines whether or not this rectangle and the specified rectangle intersect.
207    *
208    * @SINCE_1_0.0
209    * @param[in] other The other rectangle to test against this rectangle
210    * @return True if the rectangles intersect
211    */
212   bool Intersects(const Rect<T>& other) const
213   {
214     return (other.x + other.width)  > x           &&
215       other.x                 < (x + width) &&
216                                 (other.y + other.height) > y           &&
217       other.y                 < (y + height);
218   }
219
220   /**
221    * @brief Determines whether or not this Rectangle contains the specified rectangle.
222    *
223    * @SINCE_1_0.0
224    * @param[in] other The other rectangle to test against this rectangle
225    * @return True if the specified rectangle is contained
226    */
227   bool Contains(const Rect<T>& other) const
228   {
229     return other.x                  >= x           &&
230       (other.x + other.width)  <= (x + width) &&
231       other.y                  >= y           &&
232       (other.y + other.height) <= (y + height);
233   }
234
235 public:   // Data
236
237   union
238   {
239     T x;      ///< X position of the rectangle
240     T left;   ///< The left value
241   };
242
243   union
244   {
245     T y;      ///< Y position of the rectangle
246     T right;  ///< The right value
247   };
248
249   union
250   {
251     T width;  ///< width of the rectangle
252     T bottom; ///< The bottom value
253   };
254
255   union
256   {
257     T height; ///< height of the rectangle
258     T top;    ///< The top value
259   };
260 };
261
262 /**
263  * @brief Equality operator.
264  *
265  * @SINCE_1_0.0
266  * @param[in] lhs First operand
267  * @param[in] rhs Second operand
268  * @return True if boxes are exactly same
269  */
270 template< typename T >
271 inline bool operator==( const Rect<T>& lhs, const Rect<T>& rhs )
272 {
273   return ( lhs.x == rhs.x )&&
274     ( lhs.y == rhs.y )&&
275     ( lhs.width == rhs.width )&&
276     ( lhs.height == rhs.height );
277 }
278
279 /**
280  * @brief Inequality operator.
281  *
282  * @SINCE_1_0.0
283  * @param[in] lhs The first rectangle
284  * @param[in] rhs The second rectangle
285  * @return True if rectangles are not identical
286  */
287 template< typename T >
288 inline bool operator!=( const Rect<T>& lhs, const Rect<T>& rhs )
289 {
290   return !(lhs == rhs);
291 }
292
293 /**
294  * @brief Equality operator specialization for float.
295  *
296  * @SINCE_1_0.0
297  * @param[in] lhs The first rectangle
298  * @param[in] rhs The second rectangle
299  * @return True if rectangles are exactly same
300  */
301 template<>
302 inline bool operator==( const Rect<float>& lhs, const Rect<float>& rhs )
303 {
304   return ( fabsf( lhs.x - rhs.x ) < GetRangedEpsilon(lhs.x, rhs.x) )&&
305     ( fabsf( lhs.y - rhs.y ) < GetRangedEpsilon(lhs.y, rhs.y) )&&
306     ( fabsf( lhs.width - rhs.width ) < GetRangedEpsilon(lhs.width, rhs.width) )&&
307     ( fabsf( lhs.height - rhs.height ) < GetRangedEpsilon(lhs.height, rhs.height) );
308 }
309
310 /**
311  * @brief IsEmpty specialization for float.
312  *
313  * @SINCE_1_0.0
314  * @return True if the rectangle has zero size
315  */
316 template<>
317 inline bool Rect<float>::IsEmpty() const
318 {
319   return (fabsf(width)  <= GetRangedEpsilon(width, width)
320           ||
321           fabsf(height) <= GetRangedEpsilon(height, height));
322 }
323
324 /**
325  * @brief Converts the value of the rectangle into a string and insert in to an output stream.
326  *
327  * @SINCE_1_0.0
328  * @param[in] stream The output stream operator
329  * @param[in] rectangle the rectangle to output
330  * @return The output stream operator
331  */
332 template< typename T >
333 inline std::ostream& operator<< (std::ostream& stream, const Rect<T>& rectangle)
334 {
335   return stream << "[" << rectangle.x << ", " << rectangle.y << ", " << rectangle.width << ", " << rectangle.height << "]";
336 }
337
338 /**
339  * @}
340  */
341 } // namespace Dali
342
343 #endif // DALI_RECT_H