5 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
26 #include <dali/public-api/math/math-utils.h>
31 * @addtogroup dali_core_math
36 * @brief Template class to create and operate on rectangles.
39 template<typename T = float>
60 * @param[in] x X coordinate (or left)
61 * @param[in] y Y coordinate (or right)
62 * @param[in] width Width (or bottom)
63 * @param[in] height Height (or top)
65 Rect(T x, T y, T width, T height)
74 * @brief Conversion constructor from Vector4.
77 * @param[in] vec4 Vector4 to convert from
79 Rect(const Vector4& vec4)
88 * @brief Default copy constructor.
91 * @param[in] rhs The original object
93 Rect(const Rect& rhs) = default;
96 * @brief Default copy assignment operator.
99 * @param[in] rhs The original object
100 * @return Reference to this
102 Rect<T>& operator=(const Rect<T>& rhs) = default;
105 * @brief Default move constructor.
108 * @param[in] rhs The original object
110 Rect(Rect&& rhs) noexcept = default;
113 * @brief Default move assignment operator.
116 * @param[in] rhs The original object
117 * @return Reference to this
119 Rect<T>& operator=(Rect<T>&& rhs) noexcept = default;
122 * @brief Assignment operator.
125 * @param[in] vec4 The Vector4 to assign
126 * @return Reference to this
128 Rect<T>& operator=(const Vector4& vec4)
139 * @brief Assignment from individual values.
142 * @param[in] newX X coordinate
143 * @param[in] newY Y coordinate
144 * @param[in] newWidth Width
145 * @param[in] newHeight Height
147 void Set(T newX, T newY, T newWidth, T newHeight)
156 * @brief Determines whether or not this Rectangle is empty.
159 * @return True if width or height are zero
168 * @brief Determines whether or not this Rectangle is valid.
171 * @return True if width and height are not negative
175 return !(width < 0 || height < 0);
179 * @brief Gets the left of the rectangle.
182 * @return The left edge of the rectangle
189 * @brief Gets the right of the rectangle.
192 * @return The right edge of the rectangle
200 * @brief Gets the top of the rectangle.
203 * @return The top of the rectangle
211 * @brief Gets the bottom of the rectangle.
214 * @return The bottom of the rectangle
222 * @brief Gets the area of the rectangle.
225 * @return The area of the rectangle
229 return width * height;
233 * @brief Determines whether or not this rectangle and the specified rectangle intersect.
236 * @param[in] other The other rectangle to test against this rectangle
237 * @return True if the rectangles intersect
239 bool Intersects(const Rect<T>& other) const
241 return (other.x + other.width) > x && other.x < (x + width) &&
242 (other.y + other.height) > y && other.y < (y + height);
246 * @brief Intersects this rectangle and the specified rectangle.
247 * The result of the intersection is stored in this rectangle.
250 * @param[in] rect The other rectangle to intersect with
251 * @return True if the rectangles intersect
253 bool Intersect(const Rect<T>& rect)
255 const int left = std::max(rect.x, x);
256 const int top = std::max(rect.y, y);
257 const int right = std::min(rect.x + rect.width, x + width);
258 const int bottom = std::min(rect.y + rect.height, y + height);
260 const int width = right - left;
261 const int height = bottom - top;
262 if(!(width < 0 || height < 0))
267 this->height = height;
275 * @brief Merges this rectangle and the specified rectangle.
276 * The result of the merge is stored in this rectangle.
279 * @param[in] rect The other rectangle to merge with
281 void Merge(const Rect<T>& rect)
283 const int left = std::min(rect.x, x);
284 const int top = std::min(rect.y, y);
285 const int right = std::max(rect.x + rect.width, x + width);
286 const int bottom = std::max(rect.y + rect.height, y + height);
289 width = right - left;
290 height = bottom - top;
294 * @brief Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards.
295 * If dx is negative, then the sides are moved outwards.
296 * The result of the inset is stored in this rectangle.
299 void Inset(T dx, T dy)
301 const int left = x - dx;
302 const int top = y - dy;
303 const int right = x + width + dx;
304 const int bottom = y + height + dy;
307 width = right - left;
308 height = bottom - top;
312 * @brief Determines whether or not this Rectangle contains the specified rectangle.
315 * @param[in] other The other rectangle to test against this rectangle
316 * @return True if the specified rectangle is contained
318 bool Contains(const Rect<T>& other) const
320 return other.x >= x && (other.x + other.width) <= (x + width) &&
321 other.y >= y && (other.y + other.height) <= (y + height);
327 T x; ///< X position of the rectangle
328 T left; ///< The left value
333 T y; ///< Y position of the rectangle
334 T right; ///< The right value
339 T width; ///< width of the rectangle
340 T bottom; ///< The bottom value
345 T height; ///< height of the rectangle
346 T top; ///< The top value
351 * @brief Equality operator.
354 * @param[in] lhs First operand
355 * @param[in] rhs Second operand
356 * @return True if boxes are exactly same
359 inline bool operator==(const Rect<T>& lhs, const Rect<T>& rhs)
361 return (lhs.x == rhs.x) &&
363 (lhs.width == rhs.width) &&
364 (lhs.height == rhs.height);
368 * @brief Inequality operator.
371 * @param[in] lhs The first rectangle
372 * @param[in] rhs The second rectangle
373 * @return True if rectangles are not identical
376 inline bool operator!=(const Rect<T>& lhs, const Rect<T>& rhs)
378 return !(lhs == rhs);
382 * @brief Equality operator specialization for float.
385 * @param[in] lhs The first rectangle
386 * @param[in] rhs The second rectangle
387 * @return True if rectangles are exactly same
390 inline bool operator==(const Rect<float>& lhs, const Rect<float>& rhs)
392 return (fabsf(lhs.x - rhs.x) < GetRangedEpsilon(lhs.x, rhs.x)) &&
393 (fabsf(lhs.y - rhs.y) < GetRangedEpsilon(lhs.y, rhs.y)) &&
394 (fabsf(lhs.width - rhs.width) < GetRangedEpsilon(lhs.width, rhs.width)) &&
395 (fabsf(lhs.height - rhs.height) < GetRangedEpsilon(lhs.height, rhs.height));
399 * @brief IsEmpty specialization for float.
402 * @return True if the rectangle has zero size
405 inline bool Rect<float>::IsEmpty() const
407 return (fabsf(width) <= GetRangedEpsilon(width, width) ||
408 fabsf(height) <= GetRangedEpsilon(height, height));
412 * @brief Converts the value of the rectangle into a string and insert in to an output stream.
415 * @param[in] stream The output stream operator
416 * @param[in] rectangle the rectangle to output
417 * @return The output stream operator
420 inline std::ostream& operator<<(std::ostream& stream, const Rect<T>& rectangle)
422 return stream << "[" << rectangle.x << ", " << rectangle.y << ", " << rectangle.width << ", " << rectangle.height << "]";
430 #endif // DALI_RECT_H