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 default:
749 break;
750 }
751
752 ocean_assert(index == 0u);
753 return VectorT2<T>(left(), top());
754}
755
756template <typename T>
757inline bool BoxT2<T>::isPoint() const
758{
759 return lower_.x() == higher_.x() && lower_.y() == higher_.y();
760}
761
762template <typename T>
763inline bool BoxT2<T>::isEqual(const BoxT2<T>& box, const T epsilon) const
764{
765 return lower_.isEqual(box.lower_, epsilon) && higher_.isEqual(box.higher_, epsilon);
766}
767
768template <typename T>
769inline bool BoxT2<T>::isValid() const
770{
771 return lower_.x() <= higher_.x() && lower_.y() <= higher_.y();
772}
773
774template <typename T>
776{
777 BoxT2<T> result(*this);
778 result += right;
779 return result;
780}
781
782template <typename T>
784{
785 BoxT2<T> result(*this);
786
787 result += triangle.point0();
788 result += triangle.point1();
789 result += triangle.point2();
790
791 return result;
792}
793
794template <typename T>
796{
797 BoxT2<T> result(*this);
798 result += point;
799
800 return result;
801}
802
803template <typename T>
804BoxT2<T> BoxT2<T>::operator+(const T signedBorder) const
805{
806 BoxT2<T> result(*this);
807 result += signedBorder;
808
809 return result;
810}
811
812template <typename T>
814{
815 ocean_assert(right.isValid());
816
817 lower_.x() = min(lower_.x(), right.lower_.x());
818 lower_.y() = min(lower_.y(), right.lower_.y());
819 higher_.x() = max(higher_.x(), right.higher_.x());
820 higher_.y() = max(higher_.y(), right.higher_.y());
821
822 return *this;
823}
824
825template <typename T>
827{
828 *this += triangle.point0();
829 *this += triangle.point1();
830 *this += triangle.point2();
831
832 return *this;
833}
834
835template <typename T>
837{
838 lower_.x() = min(lower_.x(), point.x());
839 lower_.y() = min(lower_.y(), point.y());
840 higher_.x() = max(higher_.x(), point.x());
841 higher_.y() = max(higher_.y(), point.y());
842
843 return *this;
844}
845
846template <typename T>
847BoxT2<T>& BoxT2<T>::operator+=(const T signedBorder)
848{
849 ocean_assert(isValid());
850
851 if (signedBorder >= 0)
852 {
853 lower_.x() -= signedBorder;
854 lower_.y() -= signedBorder;
855
856 higher_.x() += signedBorder;
857 higher_.y() += signedBorder;
858 }
859 else
860 {
861 const VectorT2<T> currentCenter = center();
862
863 lower_.x() = std::min(lower_.x() - signedBorder, currentCenter.x());
864 lower_.y() = std::min(lower_.y() - signedBorder, currentCenter.y());
865
866 higher_.x() = std::max(currentCenter.x(), higher_.x() + signedBorder);
867 higher_.y() = std::max(currentCenter.y(), higher_.y() + signedBorder);
868 }
869
870 return *this;
871}
872
873template <typename T>
874inline BoxT2<T> BoxT2<T>::operator*(const T factor) const
875{
876 ocean_assert(isValid());
877
878 return BoxT2<T>(lower_ * factor, higher_ * factor);
879}
880
881template <typename T>
882inline BoxT2<T>& BoxT2<T>::operator*=(const T factor)
883{
884 ocean_assert(isValid());
885
886 *this = *this * factor;
887 return *this;
888}
889
890template <typename T>
891inline BoxT2<T> BoxT2<T>::operator*(const SquareMatrixT3<T>& transformation) const
892{
893 ocean_assert(isValid() && !transformation.isSingular());
894
895 BoxT2<T> result;
896
897 result += transformation * VectorT2<T>(left(), bottom());
898 result += transformation * VectorT2<T>(right(), bottom());
899 result += transformation * VectorT2<T>(right(), top());
900 result += transformation * VectorT2<T>(left(), top());
901
902 return result;
903}
904
905template <typename T>
906inline BoxT2<T>& BoxT2<T>::operator*=(const SquareMatrixT3<T>& transformation)
907{
908 *this = *this * transformation;
909 return *this;
910}
911
912template <typename T>
913inline bool BoxT2<T>::operator==(const BoxT2<T>& right) const
914{
915 return isEqual(right, NumericT<T>::eps());
916}
917
918template <typename T>
919inline bool BoxT2<T>::operator!=(const BoxT2<T>& right) const
920{
921 return !(*this == right);
922}
923
924template <typename T>
925inline BoxT2<T>::operator bool() const
926{
927 return isValid();
928}
929
930template <typename T>
931bool 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
932{
933 ocean_assert(isValid());
934 ocean_assert(constraintLeft <= constraintRight && constraintTop <= constraintBottom);
935
936 if (!isValid())
937 {
938 intersectionLeft = constraintLeft;
939 intersectionTop = constraintTop;
940
941 intersectionWidth = (unsigned int)(constraintRight - constraintLeft) + 1u;
942 intersectionHeight = (unsigned int)(constraintBottom - constraintTop) + 1u;
943
944 return true;
945 }
946
947 if (left() > T(constraintRight) || top() > T(constraintBottom) || right() < T(constraintLeft) || bottom() < T(constraintTop))
948 {
949 return false;
950 }
951
952 intersectionLeft = minmax(constraintLeft, int(NumericT<T>::floor(left())), constraintRight);
953 intersectionTop = minmax(constraintTop, int(NumericT<T>::floor(top())), constraintBottom);
954
955 const int subRegionRight = minmax(intersectionLeft, int(NumericT<T>::floor(right())), constraintRight);
956 const int subRegionBottom = minmax(intersectionTop, int(NumericT<T>::floor(bottom())), constraintBottom);
957
958 ocean_assert(intersectionLeft <= subRegionRight);
959 ocean_assert(intersectionTop <= subRegionBottom);
960
961 intersectionWidth = (unsigned int)(subRegionRight - intersectionLeft) + 1u;
962 intersectionHeight = (unsigned int)(subRegionBottom - intersectionTop) + 1u;
963
964 ocean_assert(T(intersectionLeft) <= max(T(constraintLeft), left()));
965 ocean_assert(T(intersectionTop) <= max(T(constraintTop), top()));
966 ocean_assert(T(intersectionLeft) + T(intersectionWidth) >= min(T(constraintRight), right()));
967 ocean_assert(T(intersectionTop) + T(intersectionHeight) >= min(T(constraintBottom), bottom()));
968
969 return true;
970}
971
972template <typename T>
973bool BoxT2<T>::box2integer(const unsigned int maximalWidth, const unsigned int maximalHeight, unsigned int& intersectionLeft, unsigned int& intersectionTop, unsigned int& intersectionWidth, unsigned int& intersectionHeight) const
974{
975 ocean_assert(isValid());
976
977 if (maximalWidth == 0u || maximalHeight == 0u)
978 {
979 return false;
980 }
981
982 if (!isValid())
983 {
984 intersectionLeft = 0u;
985 intersectionTop = 0u;
986 intersectionWidth = maximalWidth;
987 intersectionHeight = maximalHeight;
988 }
989
990 if (left() >= T(maximalWidth) || top() >= T(maximalHeight) || right() < 0 || bottom() < 0)
991 {
992 return false;
993 }
994
995 intersectionLeft = minmax(0, int(left()), int(maximalWidth - 1u));
996 intersectionTop = minmax(0, int(top()), int(maximalHeight - 1u));
997 const unsigned int intersectionRight = minmax(int(intersectionLeft), int(right()), int(maximalWidth - 1u));
998 const unsigned int intersectionBottom = minmax(int(intersectionTop), int(bottom()), int(maximalHeight - 1u));
999
1000 intersectionWidth = intersectionRight - intersectionLeft + 1u;
1001 intersectionHeight = intersectionBottom - intersectionTop + 1u;
1002
1003 return true;
1004}
1005
1006template <typename T>
1007bool 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
1008{
1009 if (!box2integer(maximalWidth, maximalHeight, intersectionLeft, intersectionTop, intersectionWidth, intersectionHeight))
1010 {
1011 return false;
1012 }
1013
1014 if (extraBorder == 0u)
1015 {
1016 return true;
1017 }
1018
1019 ocean_assert(intersectionWidth >= 0u);
1020 ocean_assert(intersectionHeight >= 0u);
1021
1022 unsigned int intersectionRight = intersectionLeft + intersectionWidth - 1u;
1023 unsigned int intersectionBottom = intersectionTop + intersectionHeight - 1u;
1024
1025 ocean_assert(intersectionRight < maximalWidth);
1026 ocean_assert(intersectionTop < maximalHeight);
1027
1028 intersectionRight = min(intersectionRight + extraBorder, maximalWidth - 1u);
1029 intersectionBottom = min(intersectionBottom + extraBorder, maximalHeight - 1u);
1030
1031 intersectionLeft = max(0, int(intersectionLeft) - int(extraBorder));
1032 intersectionTop = max(0, int(intersectionTop) - int(extraBorder));
1033
1034 intersectionWidth = intersectionRight - intersectionLeft + 1u;
1035 intersectionHeight = intersectionBottom - intersectionTop + 1u;
1036
1037 return true;
1038}
1039
1040}
1041
1042#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:891
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:813
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:836
BoxT2< T > & operator+=(const TriangleT2< T > &triangle)
Adds a triangle (the three points of the triangle) to this box.
Definition Box2.h:826
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:763
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:769
BoxT2< T > operator+(const VectorT2< T > &point) const
Extends this box by another 2D point and returns the result.
Definition Box2.h:795
BoxT2< T > operator+(const BoxT2< T > &right) const
Returns the combined box given by this one and a second box.
Definition Box2.h:775
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:913
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:804
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:919
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:847
BoxT2< T > operator*(const T factor) const
Returns a new bounding box with scaled dimensions.
Definition Box2.h:874
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:882
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:783
BoxT2< T > & operator*=(const SquareMatrixT3< T > &transformation)
Transforms this bounding box with a transformation matrix.
Definition Box2.h:906
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:931
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:973
bool isPoint() const
Returns whether the box holds exactly one point.
Definition Box2.h:757
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:1007
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:927
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