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 */
58typedef 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 */
66template <typename T>
67class 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 */
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 */
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
461template <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
469template <typename T>
470BoxT2<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
477template <typename T>
478BoxT2<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
485template <typename T>
486BoxT2<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
493template <typename T>
494BoxT2<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
501template <typename T>
502BoxT2<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
530template <typename T>
531BoxT2<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
545template <typename T>
546BoxT2<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
578template <typename T>
579inline 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
588template <typename T>
589inline const VectorT2<T>& BoxT2<T>::lower() const
590{
591 ocean_assert(isValid());
592 return lower_;
593}
594
595template <typename T>
596inline const VectorT2<T>& BoxT2<T>::higher() const
597{
598 ocean_assert(isValid());
599 return higher_;
600}
601
602template <typename T>
603inline const T& BoxT2<T>::left() const
604{
605 ocean_assert(isValid());
606 return lower_.x();
607}
608
609template <typename T>
610inline const T& BoxT2<T>::top() const
611{
612 ocean_assert(isValid());
613 return lower_.y();
614}
615
616template <typename T>
617inline const T& BoxT2<T>::right() const
618{
619 ocean_assert(isValid());
620 return higher_.x();
621}
622
623template <typename T>
624inline const T& BoxT2<T>::bottom() const
625{
626 ocean_assert(isValid());
627 return higher_.y();
628}
629
630template <typename T>
631inline T BoxT2<T>::width() const
632{
633 ocean_assert(isValid());
634 return higher_.x() - lower_.x();
635}
636
637template <typename T>
638inline T BoxT2<T>::height() const
639{
640 ocean_assert(isValid());
641 return higher_.y() - lower_.y();
642}
643
644template <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
651template <typename T>
652inline T BoxT2<T>::xDimension() const
653{
654 ocean_assert(isValid());
655 return higher_.x() - lower_.x();
656}
657
658template <typename T>
659inline T BoxT2<T>::yDimension() const
660{
661 ocean_assert(isValid());
662 return higher_.y() - lower_.y();
663}
664
665template <typename T>
666inline T BoxT2<T>::area() const
667{
668 ocean_assert(isValid());
669 return xDimension() * yDimension();
670}
671
672template <typename T>
673inline 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
678template <typename T>
679inline 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
689template <typename T>
690inline bool BoxT2<T>::isInside(const BoxT2<T>& box) const
691{
692 return isInside(box.lower()) && isInside(box.higher());
693}
694
695template <typename T>
696inline 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
702template <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
718template <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
732template <typename T>
733inline 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
753template <typename T>
754inline bool BoxT2<T>::isPoint() const
755{
756 return lower_.x() == higher_.x() && lower_.y() == higher_.y();
757}
758
759template <typename T>
760inline 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
765template <typename T>
766inline bool BoxT2<T>::isValid() const
767{
768 return lower_.x() <= higher_.x() && lower_.y() <= higher_.y();
769}
770
771template <typename T>
773{
774 BoxT2<T> result(*this);
775 result += right;
776 return result;
777}
778
779template <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
791template <typename T>
793{
794 BoxT2<T> result(*this);
795 result += point;
796
797 return result;
798}
799
800template <typename T>
801BoxT2<T> BoxT2<T>::operator+(const T signedBorder) const
802{
803 BoxT2<T> result(*this);
804 result += signedBorder;
805
806 return result;
807}
808
809template <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
822template <typename T>
824{
825 *this += triangle.point0();
826 *this += triangle.point1();
827 *this += triangle.point2();
828
829 return *this;
830}
831
832template <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
843template <typename T>
844BoxT2<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
870template <typename T>
871inline 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
878template <typename T>
879inline BoxT2<T>& BoxT2<T>::operator*=(const T factor)
880{
881 ocean_assert(isValid());
882
883 *this = *this * factor;
884 return *this;
885}
886
887template <typename T>
888inline 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
902template <typename T>
903inline BoxT2<T>& BoxT2<T>::operator*=(const SquareMatrixT3<T>& transformation)
904{
905 *this = *this * transformation;
906 return *this;
907}
908
909template <typename T>
910inline bool BoxT2<T>::operator==(const BoxT2<T>& right) const
911{
912 return isEqual(right, NumericT<T>::eps());
913}
914
915template <typename T>
916inline bool BoxT2<T>::operator!=(const BoxT2<T>& right) const
917{
918 return !(*this == right);
919}
920
921template <typename T>
922inline BoxT2<T>::operator bool() const
923{
924 return isValid();
925}
926
927template <typename T>
928bool 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
969template <typename T>
970bool 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
1003template <typename T>
1004bool 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
This class implements an axis aligned 2D box object.
Definition Box2.h:68
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 std::vector< TriangleT2< T > > &triangles)
Creates a new box object by a set of triangles.
Definition Box2.h:531
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< 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
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
BoxT2(const std::vector< VectorT2< T > > &points)
Creates a new box object by a set of points.
Definition Box2.h:502
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:710
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:722
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:29
The namespace covering the entire Ocean framework.
Definition Accessor.h:15