Ocean
Box2.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_MATH_BOX_2_H
9 #define META_OCEAN_MATH_BOX_2_H
10 
11 #include "ocean/math/Math.h"
13 #include "ocean/math/Triangle2.h"
14 #include "ocean/math/Vector2.h"
15 
16 #include "ocean/base/Utilities.h"
17 
18 namespace Ocean
19 {
20 
21 // Forward declaration.
22 template <typename T> class BoxT2;
23 
24 /**
25  * Definition of the Box2 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single or double precision float data type.
26  * @see BoxT2
27  * @ingroup math
28  */
30 
31 /**
32  * Instantiation of the BoxT2 template class using a double precision float data type.
33  * @see BoxT2
34  * @ingroup math
35  */
37 
38 /**
39  * Instantiation of the BoxT2 template class using a single precision float data type.
40  * @see BoxT2
41  * @ingroup math
42  */
44 
45 /**
46  * Definition of a typename alias for vectors with BoxT2 objects.
47  * @see BoxT2
48  * @ingroup math
49  */
50 template <typename T>
51 using BoxesT2 = std::vector<BoxT2<T>>;
52 
53 /**
54  * Definition of a vector holding Box2 objects.
55  * @see Box2
56  * @ingroup math
57  */
58 typedef std::vector<Box2> Boxes2;
59 
60 /**
61  * This class implements an axis aligned 2D box object.
62  * @tparam T Data type used to represent coordinates
63  * @see Box2, BoxF2, BoxD2.
64  * @ingroup math
65  */
66 template <typename T>
67 class BoxT2
68 {
69  public:
70 
71  /**
72  * Definition of the used data type.
73  */
74  typedef T Type;
75 
76  public:
77 
78  /**
79  * Creates an invalid box object.
80  */
81  BoxT2();
82 
83  /**
84  * Creates a new box object by two opposite corner positions.
85  * @param first The first 2D corner position, (-infinity, infinity)x(-infinity, infinity)
86  * @param second The second 2D corner position (opposite to the first position), (-infinity, infinity)x(-infinity, infinity)
87  */
88  BoxT2(const VectorT2<T>& first, const VectorT2<T>& second);
89 
90  /**
91  * Creates a new box object by the center position and the box's dimension.
92  * @param center The center position of the box to create
93  * @param width The width or horizontal dimension of the box, with range [0, infinity)
94  * @param height The height or vertical dimension of the box, with range [0, infinity)
95  */
96  BoxT2(const VectorT2<T>& center, const T width, const T height);
97 
98  /**
99  * Creates a new box object by the center position and the box's dimension.
100  * @param width The width or horizontal dimension of the box, with range [0, infinity)
101  * @param height The height or vertical dimension of the box, with range [0, infinity)
102  * @param topLeft The top left location of this bounding box, with range (-infinity, infinity)x(-infinity, infinity)
103  */
104  BoxT2(const T width, const T height, const VectorT2<T>& topLeft);
105 
106  /**
107  * Creates a new box object by the four borders.
108  * @param left Left box border position, with range (-infinity, infinity)
109  * @param top Top box border position, with range (-infinity, infinity)
110  * @param right Right box border position, with range [left, infinity)
111  * @param bottom Bottom box border position, with range [top, infinity)
112  */
113  BoxT2(const T left, const T top, const T right, const T bottom);
114 
115  /**
116  * Creates a new box object by a set of points.
117  * The resulting box will cover all given points.<br>
118  * If no point is provided, the resulting box will be invalid.
119  * @param points Points to create the box from, can be empty
120  */
121  explicit BoxT2(const std::vector<VectorT2<T>>& points);
122 
123  /**
124  * Creates a new box object that covers a given triangle.
125  * @param triangle Triangle to create the box from
126  */
127  inline explicit BoxT2(const TriangleT2<T>& triangle);
128 
129  /**
130  * Creates a new box object by a set of triangles.
131  * The resulting box will cover all given triangles.<br>
132  * If no triangle is provided, the resulting box will be invalid.
133  * @param triangles Triangles to create the box from, can be empty
134  */
135  explicit BoxT2(const std::vector<TriangleT2<T>>& triangles);
136 
137  /**
138  * Creates a new box object by a set of points.
139  * The resulting box will cover all given points.<br>
140  * If no point is provided, the resulting box will be invalid.
141  * @param points The points to create the box from, can be nullptr if `number == 0`
142  * @param number The number of given points, with range [0, infinity)
143  */
144  BoxT2(const VectorT2<T>* points, const size_t number);
145 
146  /**
147  * Returns the lower corner of this box.
148  * @return Lower corner
149  */
150  inline const VectorT2<T>& lower() const;
151 
152  /**
153  * Returns the higher corner of this box.
154  * @return Higher corner
155  */
156  inline const VectorT2<T>& higher() const;
157 
158  /**
159  * Returns the horizontal position of the lower corner of this box.
160  * @return Left position
161  */
162  inline const T& left() const;
163 
164  /**
165  * Returns the vertical position of the lower corner of this box.
166  * @return Top position
167  */
168  inline const T& top() const;
169 
170  /**
171  * Returns the horizontal position of the higher corner of this box.
172  * @return Left position
173  */
174  inline const T& right() const;
175 
176  /**
177  * Returns the vertical position of the higher corner of this box.
178  * @return Top position
179  */
180  inline const T& bottom() const;
181 
182  /**
183  * Returns the width of the box.
184  * @return Horizontal box dimension
185  */
186  inline T width() const;
187 
188  /**
189  * Returns the height of the box.
190  * @return Vertical box dimension
191  */
192  inline T height() const;
193 
194  /**
195  * Returns the center of this box.
196  * @return Box center
197  */
198  inline VectorT2<T> center() const;
199 
200  /**
201  * Returns the dimension in x axis, which could e.g. be the width of this box.
202  * Beware: The result is undefined for an invalid box.
203  * @return Dimension in x axis
204  */
205  inline T xDimension() const;
206 
207  /**
208  * Returns the dimension in x axis, which could e.g. be the height of this box.
209  * Beware: The result is undefined for an invalid box.
210  * @return Dimension in x axis
211  */
212  inline T yDimension() const;
213 
214  /**
215  * Returns the area covered by this box.
216  * The result is undefined for invalid boxes.
217  * @return Box area
218  */
219  inline T area() const;
220 
221  /**
222  * Returns whether a given point is inside the box.
223  * @param point The point to check
224  * @return True, if so
225  */
226  inline bool isInside(const VectorT2<T>& point) const;
227 
228  /**
229  * Returns whether a given point is inside the box including a thin epsilon boundary.
230  * @param point The point to check
231  * @param epsilon The accuracy epsilon, with range [0, infinity)
232  * @return True, if so
233  */
234  inline bool isInside(const VectorT2<T>& point, const T& epsilon) const;
235 
236  /**
237  * Returns whether a given box is entirely inside this box.
238  * @param box The box to check
239  * @return True, if so
240  */
241  inline bool isInside(const BoxT2<T>& box) const;
242 
243  /**
244  * Returns whether a given box intersects this one.
245  * @param box The box to check
246  * @return True, if so
247  */
248  inline bool intersects(const BoxT2<T>& box) const;
249 
250  /**
251  * Returns the intersection of two boxes.
252  * @param box Second box for the intersection
253  * @return Box defining the intersection
254  */
255  BoxT2<T> intersection(const BoxT2<T>& box) const;
256 
257  /**
258  * Returns this box with corners rounded to integer locations.
259  * Beware: Ensure that this box is valid before calling the function.
260  * @return The box with rounded corners
261  */
262  inline BoxT2<T> rounded() const;
263 
264  /**
265  * Returns one of the four corners of this 2D box.
266  * The corners have a counter-clockwise order: (left, top), (left, bottom), (right, bottom), (right top).
267  * @param index The index of the corner to return, with range [0, 3]
268  * @return The requested corner
269  */
270  inline VectorT2<T> corner(const unsigned int index) const;
271 
272  /**
273  * Returns whether the box holds exactly one point.
274  * @return True, if so
275  */
276  inline bool isPoint() const;
277 
278  /**
279  * Returns whether two box objects are equal up to an epsilon.
280  * @param box The box to compare with, can be invalid
281  * @param epsilon The accuracy epsilon, with range [0, infinity)
282  * @return True, if so
283  */
284  inline bool isEqual(const BoxT2<T>& box, const T epsilon = NumericT<T>::eps()) const;
285 
286  /**
287  * Returns whether the box holds valid parameters.
288  * A valid box can have a dimension of zero.
289  * @return True, if so
290  */
291  inline bool isValid() const;
292 
293  /**
294  * Returns the combined box given by this one and a second box.
295  * @param right Second box
296  * @return Combined box
297  */
299 
300  /**
301  * Extends this box by a triangle (by the three points of the triangle).
302  * @param triangle The triangle that extends this box
303  * @return Extended box
304  */
305  BoxT2<T> operator+(const TriangleT2<T>& triangle) const;
306 
307  /**
308  * Extends this box by another 2D point and returns the result.
309  * If the 2D point fits into this box the box is untouched, otherwise the dimension of the box will be extended.
310  * @param point The point to be added
311  * @return Extended box
312  */
313  BoxT2<T> operator+(const VectorT2<T>& point) const;
314 
315  /**
316  * Extends this box by adding a border around the box.
317  * @param signedBorder The size of the signed border to extend the box, a positive border increases the box; a negative border decreases the box, with range (-infinity, infinity)
318  * @return The modified box
319  */
320  BoxT2<T> operator+(const T signedBorder) const;
321 
322  /**
323  * Adds a box to this box.
324  * @param right Right box to add
325  * @return Reference to this enlarged box
326  */
328 
329  /**
330  * Adds a triangle (the three points of the triangle) to this box.
331  * @param triangle Triangle to add
332  * @return Reference to this enlarged box
333  */
334  BoxT2<T>& operator+=(const TriangleT2<T>& triangle);
335 
336  /**
337  * Extends this box by another 2D point.
338  * If the 2D point fits into this box the box is untouched, otherwise the dimension of the box will be extended.
339  * @param point Point to be added
340  * @return Reference to this enlarged box
341  */
343 
344  /**
345  * Extends this box by adding a border around the box.
346  * This box needs to be valid.
347  * @param signedBorder The size of the signed border to extend the box, a positive border increases the box; a negative border decreases the box, with range (-infinity, infinity)
348  * @return Reference to this modified box
349  */
350  BoxT2<T>& operator+=(const T signedBorder);
351 
352  /**
353  * Returns a new bounding box with scaled dimensions.
354  * The corners of this bounding box will be scaled with a scalar defining new scaled corners for the new bounding box object.<br>
355  * This box needs to be valid.
356  * @param factor Factor that is applied to each bounding box corner, with range (-infinity, infinity)
357  * @return Scaled bounding box
358  */
359  inline BoxT2<T> operator*(const T factor) const;
360 
361  /**
362  * Scales this bounding box with a scalar factor.
363  * The corners of this bounding box will be scaled with a scalar.<br>
364  * This box needs to be valid.
365  * @param factor Factor that is applied to each bounding box corner, with range (-infinity, infinity)
366  * @return Reference to this scaled bounding box
367  */
368  inline BoxT2<T>& operator*=(const T factor);
369 
370  /**
371  * Returns a new bounding box enclosing the transformed corners of this bounding box.
372  * The corners of this bounding box will be transformed with a given 3x3 transformation matrix (a homography).
373  * @param transformation The transformation to be applied to each bounding box corner, must be valid
374  * @return The transformed bounding box
375  */
376  inline BoxT2<T> operator*(const SquareMatrixT3<T>& transformation) const;
377 
378  /**
379  * Transforms this bounding box with a transformation matrix.
380  * The corners of the bounding box will be transformed with a given 3x3 transformation matrix (a homography).
381  * @param transformation The transformation to be applied to each bounding box corner, must be valid
382  * @return Reference to this transformed bounding box
383  */
384  inline BoxT2<T>& operator*=(const SquareMatrixT3<T>& transformation);
385 
386  /**
387  * Returns whether two boxes are identical.
388  * @param right Second box object
389  * @return True, if so
390  */
391  inline bool operator==(const BoxT2<T>& right) const;
392 
393  /**
394  * Returns whether two boxes are not identical.
395  * @param right Second box object
396  * @return True, if so
397  */
398  inline bool operator!=(const BoxT2<T>& right) const;
399 
400  /**
401  * Returns whether this box is not a default box.
402  * @return True, if so
403  */
404  explicit inline operator bool() const;
405 
406  /**
407  * Calculates the intersection of this bounding box (with floating point accuracy) and a second bounding box (with integer accuracy).
408  * The resulting intersection (with integer accuracy) will entirely enclose this floating point bounding box - unless not possible due to the given constraints e.g., 'constraintLeft', 'constraintTop', ...<br>
409  * If this box is invalid, than the provided integer bounding box will be returned.
410  * @param constraintLeft Most left (including) position of the resulting intersection, with range (-infinity, infinity)
411  * @param constraintTop Most top (including) position of the resulting intersection, with range (-infinity, infinity)
412  * @param constraintRight Most right (including) position of the resulting intersection, with range [left, infinity)
413  * @param constraintBottom Most bottom (including) position of the resulting intersection, with range [top, infinity)
414  * @param intersectionLeft Resulting horizontal start position of the intersection, with range [constraintLeft, constraintRight]
415  * @param intersectionTop Resulting vertical start position of the intersection, with range [constraintTop, constraintBottom]
416  * @param intersectionWidth Resulting width of the sub-region, with range [0, constraintRight - constraintLeft + 1]
417  * @param intersectionHeight Resulting height of the sub-region, with range [0, constraintBottom - constraintTop + 1]
418  * @return True, if the resulting intersection has an area larger than zero (if the intersection is valid)
419  */
420  bool box2integer(const int constraintLeft, const int constraintTop, const int constraintRight, const int constraintBottom, int& intersectionLeft, int& intersectionTop, unsigned int& intersectionWidth, unsigned int& intersectionHeight) const;
421 
422  /**
423  * Calculates the intersection of this bounding box (with floating point accuracy) and a second bounding box (with integer accuracy).
424  * The resulting intersection (with integer accuracy) will entirely enclose this floating point bounding box - unless not possible due to the given constraints e.g., 'maximalWidth', 'maximalHeight', ...<br>
425  * If this box is invalid, than the provided integer bounding box will be returned.<br>
426  * Actually, this function returns box2integer(0, 0, maximalWidth - 1, maximalHeight - 1, intersectionLeft, intersectionTop, intersectionWidth, intersectionHeight)
427  * @param maximalWidth Maximal width of the resulting intersection, with range [0, infinity)
428  * @param maximalHeight Maximal height of the resulting intersection, with range [0, infinity)
429  * @param intersectionLeft Resulting horizontal start position of the intersection, with range [0, maximalWidth - 1]
430  * @param intersectionTop Resulting vertical start position of the intersection, with range [0, maximalHeight - 1]
431  * @param intersectionWidth Resulting width of the sub-region, with range [0, maximalWidth]
432  * @param intersectionHeight Resulting height of the sub-region, with range [0, maximalHeight]
433  * @return True, if the resulting intersection has an area larger than zero (if the intersection is valid)
434  */
435  bool box2integer(const unsigned int maximalWidth, const unsigned int maximalHeight, unsigned int& intersectionLeft, unsigned int& intersectionTop, unsigned int& intersectionWidth, unsigned int& intersectionHeight) const;
436 
437  /**
438  * Calculates the intersection of this bounding box (with floating point accuracy) and a second bounding box (with integer accuracy).
439  * The resulting intersection (with integer accuracy) will entirely enclose this floating point bounding box - unless not possible due to the given constraints e.g., 'maximalWidth', 'maximalHeight', ...<br>
440  * If this box is invalid, than the provided integer bounding box will be returned.
441  * @param maximalWidth Maximal width of the sub-region, with range [0, infinity)
442  * @param maximalHeight Maximal height of the sub-region, with range [0, infinity)
443  * @param extraBorder Explicit border that will be added to the left, top, right and bottom borders of the resulting intersection (as long as the specified constraints 'maximalWidth' and 'maximalHeight' parameters are not violated)
444  * @param intersectionLeft Resulting horizontal start position of the intersection, with range [0, maximalWidth - 1]
445  * @param intersectionTop Resulting vertical start position of the intersection, with range [0, maximalHeight - 1]
446  * @param intersectionWidth Resulting width of the sub-region, with range [0, maximalWidth]
447  * @param intersectionHeight Resulting height of the sub-region, with range [0, maximalHeight]
448  * @return True, if the resulting intersection has an area larger than zero (if the intersection is valid)
449  */
450  bool box2integer(const unsigned int maximalWidth, const unsigned int maximalHeight, const unsigned int extraBorder, unsigned int& intersectionLeft, unsigned int& intersectionTop, unsigned int& intersectionWidth, unsigned int& intersectionHeight) const;
451 
452  protected:
453 
454  /// Lower box corner.
456 
457  /// Higher box corner.
459 };
460 
461 template <typename T>
463  lower_(NumericT<T>::maxValue(), NumericT<T>::maxValue()),
464  higher_(NumericT<T>::minValue(), NumericT<T>::minValue())
465 {
466  ocean_assert(!isValid());
467 }
468 
469 template <typename T>
470 BoxT2<T>::BoxT2(const VectorT2<T>& first, const VectorT2<T>& second) :
471  lower_(min(first.x(), second.x()), min(first.y(), second.y())),
472  higher_(max(first.x(), second.x()), max(first.y(), second.y()))
473 {
474  ocean_assert(isValid());
475 }
476 
477 template <typename T>
478 BoxT2<T>::BoxT2(const VectorT2<T>& center, const T width, const T height) :
479  lower_(center.x() - width * T(0.5), center.y() - height * T(0.5)),
480  higher_(center.x() + width * T(0.5), center.y() + height * T(0.5))
481 {
482  ocean_assert(isValid());
483 }
484 
485 template <typename T>
486 BoxT2<T>::BoxT2(const T width, const T height, const VectorT2<T>& topLeft) :
487  lower_(topLeft),
488  higher_(topLeft.x() + width, topLeft.y() + height)
489 {
490  ocean_assert(isValid());
491 }
492 
493 template <typename T>
494 BoxT2<T>::BoxT2(const T left, const T top, const T right, const T bottom) :
495  lower_(min(left, right), min(top, bottom)),
496  higher_(max(left, right), max(top, bottom))
497 {
498  // nothing to do here
499 }
500 
501 template <typename T>
502 BoxT2<T>::BoxT2(const std::vector<VectorT2<T>>& points) :
503  lower_(NumericT<T>::maxValue(), NumericT<T>::maxValue()),
504  higher_(NumericT<T>::minValue(), NumericT<T>::minValue())
505 {
506  for (typename std::vector<VectorT2<T>>::const_iterator i = points.begin(); i != points.end(); ++i)
507  {
508  if (i->x() < lower_.x())
509  {
510  lower_.x() = i->x();
511  }
512 
513  if (i->x() > higher_.x())
514  {
515  higher_.x() = i->x();
516  }
517 
518  if (i->y() < lower_.y())
519  {
520  lower_.y() = i->y();
521  }
522 
523  if (i->y() > higher_.y())
524  {
525  higher_.y() = i->y();
526  }
527  }
528 }
529 
530 template <typename T>
531 BoxT2<T>::BoxT2(const std::vector<TriangleT2<T>>& triangles) :
532  lower_(NumericT<T>::maxValue(), NumericT<T>::maxValue()),
533  higher_(NumericT<T>::minValue(), NumericT<T>::minValue())
534 {
535  for (const TriangleT2<T>& triangle : triangles)
536  {
537  ocean_assert(triangle.isValid());
538 
539  *this += triangle.point0();
540  *this += triangle.point1();
541  *this += triangle.point2();
542  }
543 }
544 
545 template <typename T>
546 BoxT2<T>::BoxT2(const VectorT2<T>* points, const size_t number) :
547  lower_(NumericT<T>::maxValue(), NumericT<T>::maxValue()),
548  higher_(NumericT<T>::minValue(), NumericT<T>::minValue())
549 {
550  const VectorT2<T>* const pointsEnd = points + number;
551 
552  while (points != pointsEnd)
553  {
554  if (points->x() < lower_.x())
555  {
556  lower_.x() = points->x();
557  }
558 
559  if (points->x() > higher_.x())
560  {
561  higher_.x() = points->x();
562  }
563 
564  if (points->y() < lower_.y())
565  {
566  lower_.y() = points->y();
567  }
568 
569  if (points->y() > higher_.y())
570  {
571  higher_.y() = points->y();
572  }
573 
574  ++points;
575  }
576 }
577 
578 template <typename T>
579 inline BoxT2<T>::BoxT2(const TriangleT2<T>& triangle) :
580  lower_(NumericT<T>::maxValue(), NumericT<T>::maxValue()),
581  higher_(NumericT<T>::minValue(), NumericT<T>::minValue())
582 {
583  *this += triangle.point0();
584  *this += triangle.point1();
585  *this += triangle.point2();
586 }
587 
588 template <typename T>
589 inline const VectorT2<T>& BoxT2<T>::lower() const
590 {
591  ocean_assert(isValid());
592  return lower_;
593 }
594 
595 template <typename T>
596 inline const VectorT2<T>& BoxT2<T>::higher() const
597 {
598  ocean_assert(isValid());
599  return higher_;
600 }
601 
602 template <typename T>
603 inline const T& BoxT2<T>::left() const
604 {
605  ocean_assert(isValid());
606  return lower_.x();
607 }
608 
609 template <typename T>
610 inline const T& BoxT2<T>::top() const
611 {
612  ocean_assert(isValid());
613  return lower_.y();
614 }
615 
616 template <typename T>
617 inline const T& BoxT2<T>::right() const
618 {
619  ocean_assert(isValid());
620  return higher_.x();
621 }
622 
623 template <typename T>
624 inline const T& BoxT2<T>::bottom() const
625 {
626  ocean_assert(isValid());
627  return higher_.y();
628 }
629 
630 template <typename T>
631 inline T BoxT2<T>::width() const
632 {
633  ocean_assert(isValid());
634  return higher_.x() - lower_.x();
635 }
636 
637 template <typename T>
638 inline T BoxT2<T>::height() const
639 {
640  ocean_assert(isValid());
641  return higher_.y() - lower_.y();
642 }
643 
644 template <typename T>
646 {
647  ocean_assert(isValid());
648  return VectorT2<T>((higher_.x() + lower_.x()) * T(0.5), (higher_.y() + lower_.y()) * T(0.5));
649 }
650 
651 template <typename T>
652 inline T BoxT2<T>::xDimension() const
653 {
654  ocean_assert(isValid());
655  return higher_.x() - lower_.x();
656 }
657 
658 template <typename T>
659 inline T BoxT2<T>::yDimension() const
660 {
661  ocean_assert(isValid());
662  return higher_.y() - lower_.y();
663 }
664 
665 template <typename T>
666 inline T BoxT2<T>::area() const
667 {
668  ocean_assert(isValid());
669  return xDimension() * yDimension();
670 }
671 
672 template <typename T>
673 inline bool BoxT2<T>::isInside(const VectorT2<T>& point) const
674 {
675  return point.x() >= lower_.x() && point.x() <= higher_.x() && point.y() >= lower_.y() && point.y() <= higher_.y();
676 }
677 
678 template <typename T>
679 inline bool BoxT2<T>::isInside(const VectorT2<T>& point, const T& epsilon) const
680 {
681  ocean_assert(epsilon >= 0);
682 
683  return point.x() + epsilon >= lower_.x()
684  && point.x() - epsilon <= higher_.x()
685  && point.y() + epsilon >= lower_.y()
686  && point.y() - epsilon <= higher_.y();
687 }
688 
689 template <typename T>
690 inline bool BoxT2<T>::isInside(const BoxT2<T>& box) const
691 {
692  return isInside(box.lower()) && isInside(box.higher());
693 }
694 
695 template <typename T>
696 inline bool BoxT2<T>::intersects(const BoxT2<T>& box) const
697 {
698  return !(lower_.x() > box.higher_.x() || box.lower_.x() > higher_.x()
699  || lower_.y() > box.higher_.y() || box.lower_.y() > higher_.y());
700 }
701 
702 template <typename T>
704 {
705  const T xLower = max(lower_.x(), box.lower_.x());
706  const T yLower = max(lower_.y(), box.lower_.y());
707  const T xHigher = min(higher_.x(), box.higher_.x());
708  const T yHigher = min(higher_.y(), box.higher_.y());
709 
710  if (xLower > xHigher || yLower > yHigher)
711  {
712  return BoxT2<T>();
713  }
714 
715  return BoxT2<T>(VectorT2<T>(xLower, yLower), VectorT2<T>(xHigher, yHigher));
716 }
717 
718 template <typename T>
720 {
721  ocean_assert(isValid());
722 
723  const T roundedLeft = T(NumericT<T>::round32(left()));
724  const T roundedTop = T(NumericT<T>::round32(top()));
725 
726  const T roundedRight = T(NumericT<T>::round32(right()));
727  const T roundedBottom = T(NumericT<T>::round32(bottom()));
728 
729  return BoxT2<T>(roundedLeft, roundedTop, roundedRight, roundedBottom);
730 }
731 
732 template <typename T>
733 inline VectorT2<T> BoxT2<T>::corner(const unsigned int index) const
734 {
735  ocean_assert(index <= 3u);
736 
737  switch (index)
738  {
739  case 1u:
740  return VectorT2<T>(left(), bottom());
741 
742  case 2u:
743  return VectorT2<T>(right(), bottom());
744 
745  case 3u:
746  return VectorT2<T>(right(), top());
747  }
748 
749  ocean_assert(index == 0u);
750  return VectorT2<T>(left(), top());
751 }
752 
753 template <typename T>
754 inline bool BoxT2<T>::isPoint() const
755 {
756  return lower_.x() == higher_.x() && lower_.y() == higher_.y();
757 }
758 
759 template <typename T>
760 inline bool BoxT2<T>::isEqual(const BoxT2<T>& box, const T epsilon) const
761 {
762  return lower_.isEqual(box.lower_, epsilon) && higher_.isEqual(box.higher_, epsilon);
763 }
764 
765 template <typename T>
766 inline bool BoxT2<T>::isValid() const
767 {
768  return lower_.x() <= higher_.x() && lower_.y() <= higher_.y();
769 }
770 
771 template <typename T>
773 {
774  BoxT2<T> result(*this);
775  result += right;
776  return result;
777 }
778 
779 template <typename T>
781 {
782  BoxT2<T> result(*this);
783 
784  result += triangle.point0();
785  result += triangle.point1();
786  result += triangle.point2();
787 
788  return result;
789 }
790 
791 template <typename T>
793 {
794  BoxT2<T> result(*this);
795  result += point;
796 
797  return result;
798 }
799 
800 template <typename T>
801 BoxT2<T> BoxT2<T>::operator+(const T signedBorder) const
802 {
803  BoxT2<T> result(*this);
804  result += signedBorder;
805 
806  return result;
807 }
808 
809 template <typename T>
811 {
812  ocean_assert(right.isValid());
813 
814  lower_.x() = min(lower_.x(), right.lower_.x());
815  lower_.y() = min(lower_.y(), right.lower_.y());
816  higher_.x() = max(higher_.x(), right.higher_.x());
817  higher_.y() = max(higher_.y(), right.higher_.y());
818 
819  return *this;
820 }
821 
822 template <typename T>
824 {
825  *this += triangle.point0();
826  *this += triangle.point1();
827  *this += triangle.point2();
828 
829  return *this;
830 }
831 
832 template <typename T>
834 {
835  lower_.x() = min(lower_.x(), point.x());
836  lower_.y() = min(lower_.y(), point.y());
837  higher_.x() = max(higher_.x(), point.x());
838  higher_.y() = max(higher_.y(), point.y());
839 
840  return *this;
841 }
842 
843 template <typename T>
844 BoxT2<T>& BoxT2<T>::operator+=(const T signedBorder)
845 {
846  ocean_assert(isValid());
847 
848  if (signedBorder >= 0)
849  {
850  lower_.x() -= signedBorder;
851  lower_.y() -= signedBorder;
852 
853  higher_.x() += signedBorder;
854  higher_.y() += signedBorder;
855  }
856  else
857  {
858  const VectorT2<T> currentCenter = center();
859 
860  lower_.x() = std::min(lower_.x() - signedBorder, currentCenter.x());
861  lower_.y() = std::min(lower_.y() - signedBorder, currentCenter.y());
862 
863  higher_.x() = std::max(currentCenter.x(), higher_.x() + signedBorder);
864  higher_.y() = std::max(currentCenter.y(), higher_.y() + signedBorder);
865  }
866 
867  return *this;
868 }
869 
870 template <typename T>
871 inline BoxT2<T> BoxT2<T>::operator*(const T factor) const
872 {
873  ocean_assert(isValid());
874 
875  return BoxT2<T>(lower_ * factor, higher_ * factor);
876 }
877 
878 template <typename T>
879 inline BoxT2<T>& BoxT2<T>::operator*=(const T factor)
880 {
881  ocean_assert(isValid());
882 
883  *this = *this * factor;
884  return *this;
885 }
886 
887 template <typename T>
888 inline BoxT2<T> BoxT2<T>::operator*(const SquareMatrixT3<T>& transformation) const
889 {
890  ocean_assert(isValid() && !transformation.isSingular());
891 
892  BoxT2<T> result;
893 
894  result += transformation * VectorT2<T>(left(), bottom());
895  result += transformation * VectorT2<T>(right(), bottom());
896  result += transformation * VectorT2<T>(right(), top());
897  result += transformation * VectorT2<T>(left(), top());
898 
899  return result;
900 }
901 
902 template <typename T>
903 inline BoxT2<T>& BoxT2<T>::operator*=(const SquareMatrixT3<T>& transformation)
904 {
905  *this = *this * transformation;
906  return *this;
907 }
908 
909 template <typename T>
910 inline bool BoxT2<T>::operator==(const BoxT2<T>& right) const
911 {
912  return isEqual(right, NumericT<T>::eps());
913 }
914 
915 template <typename T>
916 inline bool BoxT2<T>::operator!=(const BoxT2<T>& right) const
917 {
918  return !(*this == right);
919 }
920 
921 template <typename T>
922 inline BoxT2<T>::operator bool() const
923 {
924  return isValid();
925 }
926 
927 template <typename T>
928 bool BoxT2<T>::box2integer(const int constraintLeft, const int constraintTop, const int constraintRight, const int constraintBottom, int& intersectionLeft, int& intersectionTop, unsigned int& intersectionWidth, unsigned int& intersectionHeight) const
929 {
930  ocean_assert(isValid());
931  ocean_assert(constraintLeft <= constraintRight && constraintTop <= constraintBottom);
932 
933  if (!isValid())
934  {
935  intersectionLeft = constraintLeft;
936  intersectionTop = constraintTop;
937 
938  intersectionWidth = (unsigned int)(constraintRight - constraintLeft) + 1u;
939  intersectionHeight = (unsigned int)(constraintBottom - constraintTop) + 1u;
940 
941  return true;
942  }
943 
944  if (left() > T(constraintRight) || top() > T(constraintBottom) || right() < T(constraintLeft) || bottom() < T(constraintTop))
945  {
946  return false;
947  }
948 
949  intersectionLeft = minmax(constraintLeft, int(NumericT<T>::floor(left())), constraintRight);
950  intersectionTop = minmax(constraintTop, int(NumericT<T>::floor(top())), constraintBottom);
951 
952  const int subRegionRight = minmax(intersectionLeft, int(NumericT<T>::floor(right())), constraintRight);
953  const int subRegionBottom = minmax(intersectionTop, int(NumericT<T>::floor(bottom())), constraintBottom);
954 
955  ocean_assert(intersectionLeft <= subRegionRight);
956  ocean_assert(intersectionTop <= subRegionBottom);
957 
958  intersectionWidth = (unsigned int)(subRegionRight - intersectionLeft) + 1u;
959  intersectionHeight = (unsigned int)(subRegionBottom - intersectionTop) + 1u;
960 
961  ocean_assert(T(intersectionLeft) <= max(T(constraintLeft), left()));
962  ocean_assert(T(intersectionTop) <= max(T(constraintTop), top()));
963  ocean_assert(T(intersectionLeft) + T(intersectionWidth) >= min(T(constraintRight), right()));
964  ocean_assert(T(intersectionTop) + T(intersectionHeight) >= min(T(constraintBottom), bottom()));
965 
966  return true;
967 }
968 
969 template <typename T>
970 bool BoxT2<T>::box2integer(const unsigned int maximalWidth, const unsigned int maximalHeight, unsigned int& intersectionLeft, unsigned int& intersectionTop, unsigned int& intersectionWidth, unsigned int& intersectionHeight) const
971 {
972  ocean_assert(isValid());
973 
974  if (maximalWidth == 0u || maximalHeight == 0u)
975  {
976  return false;
977  }
978 
979  if (!isValid())
980  {
981  intersectionLeft = 0u;
982  intersectionTop = 0u;
983  intersectionWidth = maximalWidth;
984  intersectionHeight = maximalHeight;
985  }
986 
987  if (left() >= T(maximalWidth) || top() >= T(maximalHeight) || right() < 0 || bottom() < 0)
988  {
989  return false;
990  }
991 
992  intersectionLeft = minmax(0, int(left()), int(maximalWidth - 1u));
993  intersectionTop = minmax(0, int(top()), int(maximalHeight - 1u));
994  const unsigned int intersectionRight = minmax(int(intersectionLeft), int(right()), int(maximalWidth - 1u));
995  const unsigned int intersectionBottom = minmax(int(intersectionTop), int(bottom()), int(maximalHeight - 1u));
996 
997  intersectionWidth = intersectionRight - intersectionLeft + 1u;
998  intersectionHeight = intersectionBottom - intersectionTop + 1u;
999 
1000  return true;
1001 }
1002 
1003 template <typename T>
1004 bool BoxT2<T>::box2integer(const unsigned int maximalWidth, const unsigned int maximalHeight, const unsigned int extraBorder, unsigned int& intersectionLeft, unsigned int& intersectionTop, unsigned int& intersectionWidth, unsigned int& intersectionHeight) const
1005 {
1006  if (!box2integer(maximalWidth, maximalHeight, intersectionLeft, intersectionTop, intersectionWidth, intersectionHeight))
1007  {
1008  return false;
1009  }
1010 
1011  if (extraBorder == 0u)
1012  {
1013  return true;
1014  }
1015 
1016  ocean_assert(intersectionWidth >= 0u);
1017  ocean_assert(intersectionHeight >= 0u);
1018 
1019  unsigned int intersectionRight = intersectionLeft + intersectionWidth - 1u;
1020  unsigned int intersectionBottom = intersectionTop + intersectionHeight - 1u;
1021 
1022  ocean_assert(intersectionRight < maximalWidth);
1023  ocean_assert(intersectionTop < maximalHeight);
1024 
1025  intersectionRight = min(intersectionRight + extraBorder, maximalWidth - 1u);
1026  intersectionBottom = min(intersectionBottom + extraBorder, maximalHeight - 1u);
1027 
1028  intersectionLeft = max(0, int(intersectionLeft) - int(extraBorder));
1029  intersectionTop = max(0, int(intersectionTop) - int(extraBorder));
1030 
1031  intersectionWidth = intersectionRight - intersectionLeft + 1u;
1032  intersectionHeight = intersectionBottom - intersectionTop + 1u;
1033 
1034  return true;
1035 }
1036 
1037 }
1038 
1039 #endif // META_OCEAN_MATH_BOX_2_H
BoxT2< T > operator*(const SquareMatrixT3< T > &transformation) const
Returns a new bounding box enclosing the transformed corners of this bounding box.
Definition: Box2.h:888
T xDimension() const
Returns the dimension in x axis, which could e.g.
Definition: Box2.h:652
BoxT2< T > & operator+=(const BoxT2< T > &right)
Adds a box to this box.
Definition: Box2.h:810
VectorT2< T > corner(const unsigned int index) const
Returns one of the four corners of this 2D box.
Definition: Box2.h:733
VectorT2< T > lower_
Lower box corner.
Definition: Box2.h:455
BoxT2< T > & operator+=(const VectorT2< T > &point)
Extends this box by another 2D point.
Definition: Box2.h:833
BoxT2< T > & operator+=(const TriangleT2< T > &triangle)
Adds a triangle (the three points of the triangle) to this box.
Definition: Box2.h:823
BoxT2(const TriangleT2< T > &triangle)
Creates a new box object that covers a given triangle.
Definition: Box2.h:579
BoxT2< T > rounded() const
Returns this box with corners rounded to integer locations.
Definition: Box2.h:719
bool isEqual(const BoxT2< T > &box, const T epsilon=NumericT< T >::eps()) const
Returns whether two box objects are equal up to an epsilon.
Definition: Box2.h:760
const VectorT2< T > & higher() const
Returns the higher corner of this box.
Definition: Box2.h:596
bool isValid() const
Returns whether the box holds valid parameters.
Definition: Box2.h:766
BoxT2< T > operator+(const VectorT2< T > &point) const
Extends this box by another 2D point and returns the result.
Definition: Box2.h:792
BoxT2< T > operator+(const BoxT2< T > &right) const
Returns the combined box given by this one and a second box.
Definition: Box2.h:772
T width() const
Returns the width of the box.
Definition: Box2.h:631
BoxT2()
Creates an invalid box object.
Definition: Box2.h:462
bool operator==(const BoxT2< T > &right) const
Returns whether two boxes are identical.
Definition: Box2.h:910
BoxT2(const T width, const T height, const VectorT2< T > &topLeft)
Creates a new box object by the center position and the box's dimension.
Definition: Box2.h:486
BoxT2< T > operator+(const T signedBorder) const
Extends this box by adding a border around the box.
Definition: Box2.h:801
T Type
Definition of the used data type.
Definition: Box2.h:74
const T & left() const
Returns the horizontal position of the lower corner of this box.
Definition: Box2.h:603
T yDimension() const
Returns the dimension in x axis, which could e.g.
Definition: Box2.h:659
const T & top() const
Returns the vertical position of the lower corner of this box.
Definition: Box2.h:610
bool operator!=(const BoxT2< T > &right) const
Returns whether two boxes are not identical.
Definition: Box2.h:916
VectorT2< T > higher_
Higher box corner.
Definition: Box2.h:458
const VectorT2< T > & lower() const
Returns the lower corner of this box.
Definition: Box2.h:589
BoxT2< T > & operator+=(const T signedBorder)
Extends this box by adding a border around the box.
Definition: Box2.h:844
BoxT2< T > operator*(const T factor) const
Returns a new bounding box with scaled dimensions.
Definition: Box2.h:871
BoxT2(const T left, const T top, const T right, const T bottom)
Creates a new box object by the four borders.
Definition: Box2.h:494
bool isInside(const VectorT2< T > &point) const
Returns whether a given point is inside the box.
Definition: Box2.h:673
BoxT2(const std::vector< VectorT2< T >> &points)
Creates a new box object by a set of points.
Definition: Box2.h:502
BoxT2< T > & operator*=(const T factor)
Scales this bounding box with a scalar factor.
Definition: Box2.h:879
bool isInside(const VectorT2< T > &point, const T &epsilon) const
Returns whether a given point is inside the box including a thin epsilon boundary.
Definition: Box2.h:679
BoxT2< T > operator+(const TriangleT2< T > &triangle) const
Extends this box by a triangle (by the three points of the triangle).
Definition: Box2.h:780
BoxT2< T > & operator*=(const SquareMatrixT3< T > &transformation)
Transforms this bounding box with a transformation matrix.
Definition: Box2.h:903
bool isInside(const BoxT2< T > &box) const
Returns whether a given box is entirely inside this box.
Definition: Box2.h:690
BoxT2< T > intersection(const BoxT2< T > &box) const
Returns the intersection of two boxes.
Definition: Box2.h:703
BoxT2(const VectorT2< T > &center, const T width, const T height)
Creates a new box object by the center position and the box's dimension.
Definition: Box2.h:478
bool box2integer(const int constraintLeft, const int constraintTop, const int constraintRight, const int constraintBottom, int &intersectionLeft, int &intersectionTop, unsigned int &intersectionWidth, unsigned int &intersectionHeight) const
Calculates the intersection of this bounding box (with floating point accuracy) and a second bounding...
Definition: Box2.h:928
BoxT2(const VectorT2< T > *points, const size_t number)
Creates a new box object by a set of points.
Definition: Box2.h:546
bool intersects(const BoxT2< T > &box) const
Returns whether a given box intersects this one.
Definition: Box2.h:696
T area() const
Returns the area covered by this box.
Definition: Box2.h:666
bool box2integer(const unsigned int maximalWidth, const unsigned int maximalHeight, unsigned int &intersectionLeft, unsigned int &intersectionTop, unsigned int &intersectionWidth, unsigned int &intersectionHeight) const
Calculates the intersection of this bounding box (with floating point accuracy) and a second bounding...
Definition: Box2.h:970
bool isPoint() const
Returns whether the box holds exactly one point.
Definition: Box2.h:754
VectorT2< T > center() const
Returns the center of this box.
Definition: Box2.h:645
BoxT2(const VectorT2< T > &first, const VectorT2< T > &second)
Creates a new box object by two opposite corner positions.
Definition: Box2.h:470
BoxT2(const std::vector< TriangleT2< T >> &triangles)
Creates a new box object by a set of triangles.
Definition: Box2.h:531
bool box2integer(const unsigned int maximalWidth, const unsigned int maximalHeight, const unsigned int extraBorder, unsigned int &intersectionLeft, unsigned int &intersectionTop, unsigned int &intersectionWidth, unsigned int &intersectionHeight) const
Calculates the intersection of this bounding box (with floating point accuracy) and a second bounding...
Definition: Box2.h:1004
T height() const
Returns the height of the box.
Definition: Box2.h:638
const T & right() const
Returns the horizontal position of the higher corner of this box.
Definition: Box2.h:617
const T & bottom() const
Returns the vertical position of the higher corner of this box.
Definition: Box2.h:624
This class provides basic numeric functionalities.
Definition: Numeric.h:57
This class implements a 3x3 square matrix.
Definition: SquareMatrix3.h:88
bool isSingular() const
Returns whether this matrix is singular (and thus cannot be inverted).
Definition: SquareMatrix3.h:1341
This class implements a 2D triangle with Cartesian coordinates.
Definition: Triangle2.h:81
const VectorT2< T > & point2() const
Returns the third triangle corner.
Definition: Triangle2.h:415
const VectorT2< T > & point0() const
Returns the first triangle corner.
Definition: Triangle2.h:403
const VectorT2< T > & point1() const
Returns the second triangle corner.
Definition: Triangle2.h:409
This class implements a vector with two elements.
Definition: Vector2.h:96
const T & x() const noexcept
Returns the x value.
Definition: Vector2.h:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
T minmax(const T &lowerBoundary, const T &value, const T &upperBoundary)
This function fits a given parameter into a specified value range.
Definition: base/Utilities.h:903
BoxT2< double > BoxD2
Instantiation of the BoxT2 template class using a double precision float data type.
Definition: Box2.h:36
std::vector< Box2 > Boxes2
Definition of a vector holding Box2 objects.
Definition: Box2.h:58
BoxT2< float > BoxF2
Instantiation of the BoxT2 template class using a single precision float data type.
Definition: Box2.h:43
std::vector< BoxT2< T > > BoxesT2
Definition of a typename alias for vectors with BoxT2 objects.
Definition: Box2.h:51
BoxT2< Scalar > Box2
Definition of the Box2 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single or...
Definition: Box2.h:22
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15