Ocean
Loading...
Searching...
No Matches
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"
14#include "ocean/math/Vector2.h"
15
17
18namespace Ocean
19{
20
21// Forward declaration.
22template <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 */
50template <typename T>
51using BoxesT2 = std::vector<BoxT2<T>>;
52
53/**
54 * Definition of a vector holding Box2 objects.
55 * @see Box2
56 * @ingroup math
57 */
58using Boxes2 = std::vector<Box2>;
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 */
66template <typename T>
67class BoxT2
68{
69 public:
70
71 /**
72 * Definition of the used data type.
73 */
74 using Type = T;
75
76 public:
77
78 /**
79 * Creates an invalid box object.
80 */
81 BoxT2() = default;
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 Right position
173 */
174 inline const T& right() const;
175
176 /**
177 * Returns the vertical position of the higher corner of this box.
178 * @return Bottom 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 y 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 y 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 */
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, then 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, then 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, then 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
461template <typename T>
462BoxT2<T>::BoxT2(const VectorT2<T>& first, const VectorT2<T>& second) :
463 lower_(min(first.x(), second.x()), min(first.y(), second.y())),
464 higher_(max(first.x(), second.x()), max(first.y(), second.y()))
465{
466 ocean_assert(isValid());
467}
468
469template <typename T>
470BoxT2<T>::BoxT2(const VectorT2<T>& center, const T width, const T height) :
471 lower_(center.x() - width * T(0.5), center.y() - height * T(0.5)),
472 higher_(center.x() + width * T(0.5), center.y() + height * T(0.5))
473{
474 ocean_assert(isValid());
475}
476
477template <typename T>
478BoxT2<T>::BoxT2(const T width, const T height, const VectorT2<T>& topLeft) :
479 lower_(topLeft),
480 higher_(topLeft.x() + width, topLeft.y() + height)
481{
482 ocean_assert(isValid());
483}
484
485template <typename T>
486BoxT2<T>::BoxT2(const T left, const T top, const T right, const T bottom) :
487 lower_(min(left, right), min(top, bottom)),
488 higher_(max(left, right), max(top, bottom))
489{
490 // nothing to do here
491}
492
493template <typename T>
494BoxT2<T>::BoxT2(const std::vector<VectorT2<T>>& points) :
495 lower_(NumericT<T>::maxValue(), NumericT<T>::maxValue()),
496 higher_(NumericT<T>::minValue(), NumericT<T>::minValue())
497{
498 for (typename std::vector<VectorT2<T>>::const_iterator i = points.begin(); i != points.end(); ++i)
499 {
500 if (i->x() < lower_.x())
501 {
502 lower_.x() = i->x();
503 }
504
505 if (i->x() > higher_.x())
506 {
507 higher_.x() = i->x();
508 }
509
510 if (i->y() < lower_.y())
511 {
512 lower_.y() = i->y();
513 }
514
515 if (i->y() > higher_.y())
516 {
517 higher_.y() = i->y();
518 }
519 }
520}
521
522template <typename T>
523BoxT2<T>::BoxT2(const std::vector<TriangleT2<T>>& triangles) :
524 lower_(NumericT<T>::maxValue(), NumericT<T>::maxValue()),
525 higher_(NumericT<T>::minValue(), NumericT<T>::minValue())
526{
527 for (const TriangleT2<T>& triangle : triangles)
528 {
529 ocean_assert(triangle.isValid());
530
531 *this += triangle.point0();
532 *this += triangle.point1();
533 *this += triangle.point2();
534 }
535}
536
537template <typename T>
538BoxT2<T>::BoxT2(const VectorT2<T>* points, const size_t number) :
539 lower_(NumericT<T>::maxValue(), NumericT<T>::maxValue()),
540 higher_(NumericT<T>::minValue(), NumericT<T>::minValue())
541{
542 const VectorT2<T>* const pointsEnd = points + number;
543
544 while (points != pointsEnd)
545 {
546 if (points->x() < lower_.x())
547 {
548 lower_.x() = points->x();
549 }
550
551 if (points->x() > higher_.x())
552 {
553 higher_.x() = points->x();
554 }
555
556 if (points->y() < lower_.y())
557 {
558 lower_.y() = points->y();
559 }
560
561 if (points->y() > higher_.y())
562 {
563 higher_.y() = points->y();
564 }
565
566 ++points;
567 }
568}
569
570template <typename T>
571inline BoxT2<T>::BoxT2(const TriangleT2<T>& triangle) :
572 lower_(NumericT<T>::maxValue(), NumericT<T>::maxValue()),
573 higher_(NumericT<T>::minValue(), NumericT<T>::minValue())
574{
575 *this += triangle.point0();
576 *this += triangle.point1();
577 *this += triangle.point2();
578}
579
580template <typename T>
581inline const VectorT2<T>& BoxT2<T>::lower() const
582{
583 ocean_assert(isValid());
584 return lower_;
585}
586
587template <typename T>
588inline const VectorT2<T>& BoxT2<T>::higher() const
589{
590 ocean_assert(isValid());
591 return higher_;
592}
593
594template <typename T>
595inline const T& BoxT2<T>::left() const
596{
597 ocean_assert(isValid());
598 return lower_.x();
599}
600
601template <typename T>
602inline const T& BoxT2<T>::top() const
603{
604 ocean_assert(isValid());
605 return lower_.y();
606}
607
608template <typename T>
609inline const T& BoxT2<T>::right() const
610{
611 ocean_assert(isValid());
612 return higher_.x();
613}
614
615template <typename T>
616inline const T& BoxT2<T>::bottom() const
617{
618 ocean_assert(isValid());
619 return higher_.y();
620}
621
622template <typename T>
623inline T BoxT2<T>::width() const
624{
625 ocean_assert(isValid());
626 return higher_.x() - lower_.x();
627}
628
629template <typename T>
630inline T BoxT2<T>::height() const
631{
632 ocean_assert(isValid());
633 return higher_.y() - lower_.y();
634}
635
636template <typename T>
638{
639 ocean_assert(isValid());
640 return VectorT2<T>((higher_.x() + lower_.x()) * T(0.5), (higher_.y() + lower_.y()) * T(0.5));
641}
642
643template <typename T>
644inline T BoxT2<T>::xDimension() const
645{
646 ocean_assert(isValid());
647 return higher_.x() - lower_.x();
648}
649
650template <typename T>
651inline T BoxT2<T>::yDimension() const
652{
653 ocean_assert(isValid());
654 return higher_.y() - lower_.y();
655}
656
657template <typename T>
658inline T BoxT2<T>::area() const
659{
660 ocean_assert(isValid());
661 return xDimension() * yDimension();
662}
663
664template <typename T>
665inline bool BoxT2<T>::isInside(const VectorT2<T>& point) const
666{
667 return point.x() >= lower_.x() && point.x() <= higher_.x() && point.y() >= lower_.y() && point.y() <= higher_.y();
668}
669
670template <typename T>
671inline bool BoxT2<T>::isInside(const VectorT2<T>& point, const T& epsilon) const
672{
673 ocean_assert(epsilon >= 0);
674
675 return point.x() + epsilon >= lower_.x()
676 && point.x() - epsilon <= higher_.x()
677 && point.y() + epsilon >= lower_.y()
678 && point.y() - epsilon <= higher_.y();
679}
680
681template <typename T>
682inline bool BoxT2<T>::isInside(const BoxT2<T>& box) const
683{
684 return isInside(box.lower()) && isInside(box.higher());
685}
686
687template <typename T>
688inline bool BoxT2<T>::intersects(const BoxT2<T>& box) const
689{
690 return !(lower_.x() > box.higher_.x() || box.lower_.x() > higher_.x()
691 || lower_.y() > box.higher_.y() || box.lower_.y() > higher_.y());
692}
693
694template <typename T>
696{
697 const T xLower = max(lower_.x(), box.lower_.x());
698 const T yLower = max(lower_.y(), box.lower_.y());
699 const T xHigher = min(higher_.x(), box.higher_.x());
700 const T yHigher = min(higher_.y(), box.higher_.y());
701
702 if (xLower > xHigher || yLower > yHigher)
703 {
704 return BoxT2<T>();
705 }
706
707 return BoxT2<T>(VectorT2<T>(xLower, yLower), VectorT2<T>(xHigher, yHigher));
708}
709
710template <typename T>
712{
713 ocean_assert(isValid());
714
715 const T roundedLeft = T(NumericT<T>::round32(left()));
716 const T roundedTop = T(NumericT<T>::round32(top()));
717
718 const T roundedRight = T(NumericT<T>::round32(right()));
719 const T roundedBottom = T(NumericT<T>::round32(bottom()));
720
721 return BoxT2<T>(roundedLeft, roundedTop, roundedRight, roundedBottom);
722}
723
724template <typename T>
725inline VectorT2<T> BoxT2<T>::corner(const unsigned int index) const
726{
727 ocean_assert(index <= 3u);
728
729 switch (index)
730 {
731 case 1u:
732 return VectorT2<T>(left(), bottom());
733
734 case 2u:
735 return VectorT2<T>(right(), bottom());
736
737 case 3u:
738 return VectorT2<T>(right(), top());
739
740 default:
741 break;
742 }
743
744 ocean_assert(index == 0u);
745 return VectorT2<T>(left(), top());
746}
747
748template <typename T>
749inline bool BoxT2<T>::isPoint() const
750{
751 return lower_.x() == higher_.x() && lower_.y() == higher_.y();
752}
753
754template <typename T>
755inline bool BoxT2<T>::isEqual(const BoxT2<T>& box, const T epsilon) const
756{
757 return lower_.isEqual(box.lower_, epsilon) && higher_.isEqual(box.higher_, epsilon);
758}
759
760template <typename T>
761inline bool BoxT2<T>::isValid() const
762{
763 return lower_.x() <= higher_.x() && lower_.y() <= higher_.y();
764}
765
766template <typename T>
768{
769 BoxT2<T> result(*this);
770 result += right;
771 return result;
772}
773
774template <typename T>
776{
777 BoxT2<T> result(*this);
778
779 result += triangle.point0();
780 result += triangle.point1();
781 result += triangle.point2();
782
783 return result;
784}
785
786template <typename T>
788{
789 BoxT2<T> result(*this);
790 result += point;
791
792 return result;
793}
794
795template <typename T>
796BoxT2<T> BoxT2<T>::operator+(const T signedBorder) const
797{
798 BoxT2<T> result(*this);
799 result += signedBorder;
800
801 return result;
802}
803
804template <typename T>
806{
807 ocean_assert(right.isValid());
808
809 lower_.x() = min(lower_.x(), right.lower_.x());
810 lower_.y() = min(lower_.y(), right.lower_.y());
811 higher_.x() = max(higher_.x(), right.higher_.x());
812 higher_.y() = max(higher_.y(), right.higher_.y());
813
814 return *this;
815}
816
817template <typename T>
819{
820 *this += triangle.point0();
821 *this += triangle.point1();
822 *this += triangle.point2();
823
824 return *this;
825}
826
827template <typename T>
829{
830 lower_.x() = min(lower_.x(), point.x());
831 lower_.y() = min(lower_.y(), point.y());
832 higher_.x() = max(higher_.x(), point.x());
833 higher_.y() = max(higher_.y(), point.y());
834
835 return *this;
836}
837
838template <typename T>
839BoxT2<T>& BoxT2<T>::operator+=(const T signedBorder)
840{
841 ocean_assert(isValid());
842
843 if (signedBorder >= 0)
844 {
845 lower_.x() -= signedBorder;
846 lower_.y() -= signedBorder;
847
848 higher_.x() += signedBorder;
849 higher_.y() += signedBorder;
850 }
851 else
852 {
853 const VectorT2<T> currentCenter = center();
854
855 lower_.x() = std::min(lower_.x() - signedBorder, currentCenter.x());
856 lower_.y() = std::min(lower_.y() - signedBorder, currentCenter.y());
857
858 higher_.x() = std::max(currentCenter.x(), higher_.x() + signedBorder);
859 higher_.y() = std::max(currentCenter.y(), higher_.y() + signedBorder);
860 }
861
862 return *this;
863}
864
865template <typename T>
866inline BoxT2<T> BoxT2<T>::operator*(const T factor) const
867{
868 ocean_assert(isValid());
869
870 return BoxT2<T>(lower_ * factor, higher_ * factor);
871}
872
873template <typename T>
874inline BoxT2<T>& BoxT2<T>::operator*=(const T factor)
875{
876 ocean_assert(isValid());
877
878 *this = *this * factor;
879 return *this;
880}
881
882template <typename T>
883inline BoxT2<T> BoxT2<T>::operator*(const SquareMatrixT3<T>& transformation) const
884{
885 ocean_assert(isValid() && !transformation.isSingular());
886
887 BoxT2<T> result;
888
889 result += transformation * VectorT2<T>(left(), bottom());
890 result += transformation * VectorT2<T>(right(), bottom());
891 result += transformation * VectorT2<T>(right(), top());
892 result += transformation * VectorT2<T>(left(), top());
893
894 return result;
895}
896
897template <typename T>
898inline BoxT2<T>& BoxT2<T>::operator*=(const SquareMatrixT3<T>& transformation)
899{
900 *this = *this * transformation;
901 return *this;
902}
903
904template <typename T>
905inline bool BoxT2<T>::operator==(const BoxT2<T>& right) const
906{
907 return isEqual(right, NumericT<T>::eps());
908}
909
910template <typename T>
911inline bool BoxT2<T>::operator!=(const BoxT2<T>& right) const
912{
913 return !(*this == right);
914}
915
916template <typename T>
917inline BoxT2<T>::operator bool() const
918{
919 return isValid();
920}
921
922template <typename T>
923bool 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
924{
925 ocean_assert(isValid());
926 ocean_assert(constraintLeft <= constraintRight && constraintTop <= constraintBottom);
927
928 if (!isValid())
929 {
930 intersectionLeft = constraintLeft;
931 intersectionTop = constraintTop;
932
933 intersectionWidth = (unsigned int)(constraintRight - constraintLeft) + 1u;
934 intersectionHeight = (unsigned int)(constraintBottom - constraintTop) + 1u;
935
936 return true;
937 }
938
939 if (left() > T(constraintRight) || top() > T(constraintBottom) || right() < T(constraintLeft) || bottom() < T(constraintTop))
940 {
941 return false;
942 }
943
944 intersectionLeft = minmax(constraintLeft, int(NumericT<T>::floor(left())), constraintRight);
945 intersectionTop = minmax(constraintTop, int(NumericT<T>::floor(top())), constraintBottom);
946
947 const int subRegionRight = minmax(intersectionLeft, int(NumericT<T>::floor(right())), constraintRight);
948 const int subRegionBottom = minmax(intersectionTop, int(NumericT<T>::floor(bottom())), constraintBottom);
949
950 ocean_assert(intersectionLeft <= subRegionRight);
951 ocean_assert(intersectionTop <= subRegionBottom);
952
953 intersectionWidth = (unsigned int)(subRegionRight - intersectionLeft) + 1u;
954 intersectionHeight = (unsigned int)(subRegionBottom - intersectionTop) + 1u;
955
956 ocean_assert(T(intersectionLeft) <= max(T(constraintLeft), left()));
957 ocean_assert(T(intersectionTop) <= max(T(constraintTop), top()));
958 ocean_assert(T(intersectionLeft) + T(intersectionWidth) >= min(T(constraintRight), right()));
959 ocean_assert(T(intersectionTop) + T(intersectionHeight) >= min(T(constraintBottom), bottom()));
960
961 return true;
962}
963
964template <typename T>
965bool BoxT2<T>::box2integer(const unsigned int maximalWidth, const unsigned int maximalHeight, unsigned int& intersectionLeft, unsigned int& intersectionTop, unsigned int& intersectionWidth, unsigned int& intersectionHeight) const
966{
967 ocean_assert(isValid());
968
969 if (maximalWidth == 0u || maximalHeight == 0u)
970 {
971 return false;
972 }
973
974 if (!isValid())
975 {
976 intersectionLeft = 0u;
977 intersectionTop = 0u;
978 intersectionWidth = maximalWidth;
979 intersectionHeight = maximalHeight;
980
981 return false;
982 }
983
984 if (left() >= T(maximalWidth) || top() >= T(maximalHeight) || right() < 0 || bottom() < 0)
985 {
986 return false;
987 }
988
989 intersectionLeft = minmax(0, int(left()), int(maximalWidth - 1u));
990 intersectionTop = minmax(0, int(top()), int(maximalHeight - 1u));
991 const unsigned int intersectionRight = minmax(int(intersectionLeft), int(right()), int(maximalWidth - 1u));
992 const unsigned int intersectionBottom = minmax(int(intersectionTop), int(bottom()), int(maximalHeight - 1u));
993
994 intersectionWidth = intersectionRight - intersectionLeft + 1u;
995 intersectionHeight = intersectionBottom - intersectionTop + 1u;
996
997 return true;
998}
999
1000template <typename T>
1001bool 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
1002{
1003 if (!box2integer(maximalWidth, maximalHeight, intersectionLeft, intersectionTop, intersectionWidth, intersectionHeight))
1004 {
1005 return false;
1006 }
1007
1008 if (extraBorder == 0u)
1009 {
1010 return true;
1011 }
1012
1013 ocean_assert(intersectionWidth >= 0u);
1014 ocean_assert(intersectionHeight >= 0u);
1015
1016 unsigned int intersectionRight = intersectionLeft + intersectionWidth - 1u;
1017 unsigned int intersectionBottom = intersectionTop + intersectionHeight - 1u;
1018
1019 ocean_assert(intersectionRight < maximalWidth);
1020 ocean_assert(intersectionBottom < maximalHeight);
1021
1022 intersectionRight = min(intersectionRight + extraBorder, maximalWidth - 1u);
1023 intersectionBottom = min(intersectionBottom + extraBorder, maximalHeight - 1u);
1024
1025 intersectionLeft = max(0, int(intersectionLeft) - int(extraBorder));
1026 intersectionTop = max(0, int(intersectionTop) - int(extraBorder));
1027
1028 intersectionWidth = intersectionRight - intersectionLeft + 1u;
1029 intersectionHeight = intersectionBottom - intersectionTop + 1u;
1030
1031 return true;
1032}
1033
1034}
1035
1036#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:883
T xDimension() const
Returns the dimension in x axis, which could e.g.
Definition Box2.h:644
BoxT2< T > & operator+=(const BoxT2< T > &right)
Adds a box to this box.
Definition Box2.h:805
VectorT2< T > corner(const unsigned int index) const
Returns one of the four corners of this 2D box.
Definition Box2.h:725
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:828
BoxT2< T > & operator+=(const TriangleT2< T > &triangle)
Adds a triangle (the three points of the triangle) to this box.
Definition Box2.h:818
BoxT2(const TriangleT2< T > &triangle)
Creates a new box object that covers a given triangle.
Definition Box2.h:571
BoxT2< T > rounded() const
Returns this box with corners rounded to integer locations.
Definition Box2.h:711
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:755
BoxT2()=default
Creates an invalid box object.
const VectorT2< T > & higher() const
Returns the higher corner of this box.
Definition Box2.h:588
bool isValid() const
Returns whether the box holds valid parameters.
Definition Box2.h:761
BoxT2< T > operator+(const VectorT2< T > &point) const
Extends this box by another 2D point and returns the result.
Definition Box2.h:787
BoxT2< T > operator+(const BoxT2< T > &right) const
Returns the combined box given by this one and a second box.
Definition Box2.h:767
T width() const
Returns the width of the box.
Definition Box2.h:623
bool operator==(const BoxT2< T > &right) const
Returns whether two boxes are identical.
Definition Box2.h:905
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:478
BoxT2< T > operator+(const T signedBorder) const
Extends this box by adding a border around the box.
Definition Box2.h:796
const T & left() const
Returns the horizontal position of the lower corner of this box.
Definition Box2.h:595
T yDimension() const
Returns the dimension in y axis, which could e.g.
Definition Box2.h:651
const T & top() const
Returns the vertical position of the lower corner of this box.
Definition Box2.h:602
bool operator!=(const BoxT2< T > &right) const
Returns whether two boxes are not identical.
Definition Box2.h:911
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:581
BoxT2< T > & operator+=(const T signedBorder)
Extends this box by adding a border around the box.
Definition Box2.h:839
BoxT2< T > operator*(const T factor) const
Returns a new bounding box with scaled dimensions.
Definition Box2.h:866
BoxT2(const std::vector< TriangleT2< T > > &triangles)
Creates a new box object by a set of triangles.
Definition Box2.h:523
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:486
bool isInside(const VectorT2< T > &point) const
Returns whether a given point is inside the box.
Definition Box2.h:665
BoxT2< T > & operator*=(const T factor)
Scales this bounding box with a scalar factor.
Definition Box2.h:874
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:671
BoxT2< T > operator+(const TriangleT2< T > &triangle) const
Extends this box by a triangle (by the three points of the triangle).
Definition Box2.h:775
BoxT2< T > & operator*=(const SquareMatrixT3< T > &transformation)
Transforms this bounding box with a transformation matrix.
Definition Box2.h:898
bool isInside(const BoxT2< T > &box) const
Returns whether a given box is entirely inside this box.
Definition Box2.h:682
BoxT2< T > intersection(const BoxT2< T > &box) const
Returns the intersection of two boxes.
Definition Box2.h:695
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:470
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:923
T Type
Definition of the used data type.
Definition Box2.h:74
BoxT2(const VectorT2< T > *points, const size_t number)
Creates a new box object by a set of points.
Definition Box2.h:538
bool intersects(const BoxT2< T > &box) const
Returns whether a given box intersects this one.
Definition Box2.h:688
T area() const
Returns the area covered by this box.
Definition Box2.h:658
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:965
bool isPoint() const
Returns whether the box holds exactly one point.
Definition Box2.h:749
VectorT2< T > center() const
Returns the center of this box.
Definition Box2.h:637
BoxT2(const VectorT2< T > &first, const VectorT2< T > &second)
Creates a new box object by two opposite corner positions.
Definition Box2.h:462
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:1001
T height() const
Returns the height of the box.
Definition Box2.h:630
const T & right() const
Returns the horizontal position of the higher corner of this box.
Definition Box2.h:609
const T & bottom() const
Returns the vertical position of the higher corner of this box.
Definition Box2.h:616
BoxT2(const std::vector< VectorT2< T > > &points)
Creates a new box object by a set of points.
Definition Box2.h:494
This class provides basic numeric functionalities.
Definition Numeric.h:57
This class implements a 3x3 square matrix.
Definition SquareMatrix3.h:89
bool isSingular() const
Returns whether this matrix is singular (and thus cannot be inverted).
Definition SquareMatrix3.h:1342
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:710
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:722
static VectorT2< T > minValue()
Returns a 2D vector with all elements set to NumericT::minValue().
Definition Vector2.h:926
static VectorT2< T > maxValue()
Returns a 2D vector with all elements set to NumericT::maxValue().
Definition Vector2.h:932
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:973
std::vector< BoxT2< T > > BoxesT2
Definition of a typename alias for vectors with BoxT2 objects.
Definition Box2.h:51
std::vector< Box2 > Boxes2
Definition of a vector holding Box2 objects.
Definition Box2.h:58
The namespace covering the entire Ocean framework.
Definition Accessor.h:15