UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
Box2D.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Containers/Array.h"
7#include "CoreTypes.h"
8#include "Math/MathFwd.h" // IWYU pragma: export
10#include "Math/Vector.h"
11#include "Math/Vector2D.h"
18#include "UObject/NameTypes.h"
19#include "UObject/UnrealNames.h"
20
21template <typename T> struct TIsPODType;
22
26namespace UE {
27namespace Math {
28
29template<typename T>
30struct TBox2
31{
32public:
33 using FReal = T;
34
37
40
43
44public:
45
47 [[nodiscard]] TBox2() = default;
48
56 [[nodiscard]] explicit TBox2<T>( EForceInit )
57 {
58 Init();
59 }
60
68 : Min(InMin)
69 , Max(InMax)
70 , bIsValid(true)
71 { }
72
79 [[nodiscard]] TBox2<T>( const TVector2<T>* Points, const int32 Count );
80
86 [[nodiscard]] TBox2<T>( const TArray<TVector2<T>>& Points );
87
88public:
89
96 [[nodiscard]] bool operator==( const TBox2<T>& Other ) const
97 {
98 return (Min == Other.Min) && (Max == Other.Max);
99 }
100
107 [[nodiscard]] bool operator!=( const TBox2<T>& Other ) const
108 {
109 return !(*this == Other);
110 }
111
119 [[nodiscard]] bool Equals( const TBox2<T>& Other, T Tolerance = UE_KINDA_SMALL_NUMBER ) const
120 {
121 return Min.Equals(Other.Min, Tolerance) && Max.Equals(Other.Max, Tolerance);
122 }
123
131
139 {
140 return TBox2<T>(*this) += Other;
141 }
142
150
158 {
159 return TBox2<T>(*this) += Other;
160 }
161
169 {
170 check((Index >= 0) && (Index < 2));
171
172 if (Index == 0)
173 {
174 return Min;
175 }
176
177 return Max;
178 }
179
187 {
188 check((Index >= 0) && (Index < 2));
189
190 if (Index == 0)
191 {
192 return Min;
193 }
194
195 return Max;
196 }
197
198
199public:
200
208 {
209 // Accumulates the distance as we iterate axis
210 T DistSquared = 0.f;
211
212 if (Point.X < Min.X)
213 {
214 DistSquared += FMath::Square(Point.X - Min.X);
215 }
216 else if (Point.X > Max.X)
217 {
218 DistSquared += FMath::Square(Point.X - Max.X);
219 }
220
221 if (Point.Y < Min.Y)
222 {
223 DistSquared += FMath::Square(Point.Y - Min.Y);
224 }
225 else if (Point.Y > Max.Y)
226 {
227 DistSquared += FMath::Square(Point.Y - Max.Y);
228 }
229
230 return (T)DistSquared;
231 }
232
239 [[nodiscard]] TBox2<T> ExpandBy( const T W ) const
240 {
241 return TBox2<T>(Min - TVector2<T>(W, W), Max + TVector2<T>(W, W));
242 }
243
251 {
252 return TBox2<T>(Min - V, Max + V);
253 }
254
261 [[nodiscard]] T GetArea() const
262 {
263 return (Max.X - Min.X) * (Max.Y - Min.Y);
264 }
265
273 {
274 return TVector2<T>((Min + Max) * 0.5f);
275 }
276
285 {
286 Extents = GetExtent();
287 center = Min + Extents;
288 }
289
298
306 {
307 return 0.5f * TVector2<T>(Max - Min);
308 }
309
310
318 {
319 return TVector2<T>(Max - Min);
320 }
321
325 void Init()
326 {
327 // Zero padding for deterministic cooking with UPS serialize-as-zero for immutable/atomic noexport types
328 FMemory::Memset(this, 0, sizeof(TBox2));
329 }
330
338
345 [[nodiscard]] inline bool Intersect( const TBox2<T> & Other ) const;
346
353 [[nodiscard]] bool IsInside( const TVector2<T> & TestPoint ) const
354 {
355 return ((TestPoint.X > Min.X) && (TestPoint.X < Max.X) && (TestPoint.Y > Min.Y) && (TestPoint.Y < Max.Y));
356 }
357
366 {
367 return ((TestPoint.X >= Min.X) && (TestPoint.X <= Max.X) && (TestPoint.Y >= Min.Y) && (TestPoint.Y <= Max.Y));
368 }
369
376 [[nodiscard]] bool IsInside( const TBox2<T>& Other ) const
377 {
378 return (IsInside(Other.Min) && IsInside(Other.Max));
379 }
380
388 {
389 return TBox2<T>(Min + Offset, Max + Offset);
390 }
391
398 [[nodiscard]] TBox2<T> MoveTo(const TVector2<T>& Destination) const
399 {
400 const TVector2<T> Offset = Destination - GetCenter();
401 return TBox2<T>(Min + Offset, Max + Offset);
402 }
403
409 [[nodiscard]] FString ToString() const;
410
418 [[nodiscard]] static TBox2<T> BuildAABB( const TVector2<T>& Origin, const TVector2<T>& Extent )
419 {
420 TBox2<T> NewBox(Origin - Extent, Origin + Extent);
421
422 return NewBox;
423 }
424
425public:
426
436 {
437 return Ar << Box.Min << Box.Max << Box.bIsValid;
438 }
439
440 // Note: TBox2 is usually written via binary serialization. This function exists for SerializeFromMismatchedTag conversion usage.
442 {
443 Ar << Min << Max;
444 // Can't do Ar << bIsValid as that performs legacy UBOOL (uint32) serialization.
445 uint8 bValid = bIsValid;
446 Ar.Serialize(&bValid, sizeof(uint8));
447 bIsValid = !!bValid;
448 return true;
449 }
450
452 {
453 if constexpr (std::is_same_v<T, float>)
454 {
455 return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Ar, Box2D, Box2f, Box2d);
456 }
457 else if constexpr (std::is_same_v<T, double>)
458 {
459 return UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(Ar, Box2D, Box2d, Box2f);
460 }
461 else
462 {
463 static_assert(sizeof(T) == 0, "Unimplemented");
464 return false;
465 }
466 }
467
468 // Conversion from other type.
469 template<typename FArg UE_REQUIRES(!std::is_same_v<T, FArg>)>
470 explicit TBox2(const TBox2<FArg>& From)
471 : Min((TVector2<T>)From.Min)
472 , Max((TVector2<T>)From.Max)
473 , bIsValid(From.bIsValid)
474 {
475 }
476};
477
478
479/* TBox2 inline functions
480 *****************************************************************************/
481
482template<typename T>
484 : Min(0.f, 0.f)
485 , Max(0.f, 0.f)
486 , bIsValid(false)
487{
488 for (int32 PointItr = 0; PointItr < Count; PointItr++)
489 {
490 *this += Points[PointItr];
491 }
492}
493
494template<typename T>
496 : Min(0.f, 0.f)
497 , Max(0.f, 0.f)
498 , bIsValid(false)
499{
500 for(const TVector2<T>& EachPoint : Points)
501 {
502 *this += EachPoint;
503 }
504}
505
506
507template<typename T>
509{
510 if (bIsValid)
511 {
512 Min.X = FMath::Min(Min.X, Other.X);
513 Min.Y = FMath::Min(Min.Y, Other.Y);
514
515 Max.X = FMath::Max(Max.X, Other.X);
516 Max.Y = FMath::Max(Max.Y, Other.Y);
517
518 }
519 else
520 {
521 Min = Max = Other;
522 bIsValid = true;
523 }
524
525 return *this;
526}
527
528template<typename T>
530{
531 if (bIsValid && Other.bIsValid)
532 {
533 Min.X = FMath::Min(Min.X, Other.Min.X);
534 Min.Y = FMath::Min(Min.Y, Other.Min.Y);
535
536 Max.X = FMath::Max(Max.X, Other.Max.X);
537 Max.Y = FMath::Max(Max.Y, Other.Max.Y);
538 }
539 else if (Other.bIsValid)
540 {
541 *this = Other;
542 }
543
544 return *this;
545}
546
547template<typename T>
549{
550 // start by considering the point inside the box
551 TVector2<T> ClosestPoint = Point;
552
553 // now clamp to inside box if it's outside
554 if (Point.X < Min.X)
555 {
556 ClosestPoint.X = Min.X;
557 }
558 else if (Point.X > Max.X)
559 {
560 ClosestPoint.X = Max.X;
561 }
562
563 // now clamp to inside box if it's outside
564 if (Point.Y < Min.Y)
565 {
566 ClosestPoint.Y = Min.Y;
567 }
568 else if (Point.Y > Max.Y)
569 {
570 ClosestPoint.Y = Max.Y;
571 }
572
573 return ClosestPoint;
574}
575
576template<typename T>
578{
579 if (Intersect(Other) == false)
580 {
582 return EmptyBox;
583 }
584
585 // otherwise they overlap
586 // so find overlapping box
588
589 MinVector.X = FMath::Max(Min.X, Other.Min.X);
590 MaxVector.X = FMath::Min(Max.X, Other.Max.X);
591
592 MinVector.Y = FMath::Max(Min.Y, Other.Min.Y);
593 MaxVector.Y = FMath::Min(Max.Y, Other.Max.Y);
594
596}
597
598template<typename T>
599inline bool TBox2<T>::Intersect( const TBox2<T> & Other ) const
600{
601 if ((Min.X > Other.Max.X) || (Other.Min.X > Max.X))
602 {
603 return false;
604 }
605
606 if ((Min.Y > Other.Max.Y) || (Other.Min.Y > Max.Y))
607 {
608 return false;
609 }
610
611 return true;
612}
613
614template<typename T>
616{
617 return FString::Printf(TEXT("bIsValid=%s, Min=(%s), Max=(%s)"), bIsValid ? TEXT("true") : TEXT("false"), *Min.ToString(), *Max.ToString());
618}
619
620} // namespace Math
621} // namespace UE
622
624
625//template<> struct TCanBulkSerialize<FBox2f> { enum { Value = true }; };
626template<> struct TIsPODType<FBox2f> { enum { Value = true }; };
627template<> struct TIsUECoreVariant<FBox2f> { enum { Value = true }; };
628
629//template<> struct TCanBulkSerialize<FBox2d> { enum { Value = false }; }; // LWC_TODO: This can be done (via versioning) once LWC is fixed to on.
630template<> struct TIsPODType<FBox2d> { enum { Value = true }; };
631template<> struct TIsUECoreVariant<FBox2d> { enum { Value = true }; };
632
633/* FMath inline functions
634 *****************************************************************************/
635
636template<typename FReal>
638 (
640 const UE::Math::TVector2<FReal>& Start,
642 )
643{
644 using VectorType = UE::Math::TVector2<FReal>;
645
646 // The segment is intersecting if its endpoints lie on any of the edges or inside the box
647 if (Box.IsInsideOrOn(Start) || Box.IsInsideOrOn(End))
648 {
649 return true;
650 }
651
652 const VectorType BoxSize = Box.GetSize();
653 const FVector SegmentStart(Start.X, Start.Y, 0);
654 const FVector SegmentEnd(End.X, End.Y, 0);
655 FVector OutIntersectionPoint; // We don't do anything with this value, but it is needed by the SegmentIntersection2D function
656
657 // A ____ B
658 // | |
659 // | |
660 // C ____ D
661 const FVector PointA = FVector(Box.Min.X, Box.Min.Y, 0);
662 const FVector PointB = PointA + FVector(BoxSize.X, 0, 0);
663
665 {
666 return true;
667 }
668
669 const FVector PointC = PointA + FVector(0, BoxSize.Y, 0);
671 {
672 return true;
673 }
674
675 const FVector PointD = PointA + FVector(BoxSize.X, BoxSize.Y, 0);;
677 {
678 return true;
679 }
680
682 {
683 return true;
684 }
685
686 return false;
687}
#define check(expr)
Definition AssertionMacros.h:314
EForceInit
Definition CoreMiscDefines.h:154
@ ForceInit
Definition CoreMiscDefines.h:155
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UE_FORCEINLINE_HINT
Definition Platform.h:723
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
return true
Definition ExternalRpcRegistry.cpp:601
#define FVector
Definition IOSSystemIncludes.h:8
#define UE_SERIALIZE_VARIANT_FROM_MISMATCHED_TAG(AR_OR_SLOT, ALIAS, TYPE, ALT_TYPE)
Definition LargeWorldCoordinatesSerializer.h:9
#define UE_DECLARE_LWC_TYPE(...)
Definition LargeWorldCoordinates.h:27
FVector MaxVector(const FVector &VectorA, const FVector &VectorB)
Definition PhysicsFieldComponent.cpp:172
FVector MinVector(const FVector &VectorA, const FVector &VectorB)
Definition PhysicsFieldComponent.cpp:167
#define UE_KINDA_SMALL_NUMBER
Definition UnrealMathUtility.h:131
uint32 Offset
Definition VulkanMemory.cpp:4033
uint8_t uint8
Definition binka_ue_file_header.h:8
Definition Archive.h:1208
virtual void Serialize(void *V, int64 Length)
Definition Archive.h:1689
Definition NameTypes.h:617
Definition Array.h:670
Definition AdvancedWidgetsModule.cpp:13
@ false
Definition radaudio_common.h:23
U16 Index
Definition radfft.cpp:71
static CORE_API bool SegmentIntersection2D(const FVector &SegmentStartA, const FVector &SegmentEndA, const FVector &SegmentStartB, const FVector &SegmentEndB, FVector &out_IntersectionPoint)
Definition UnrealMath.cpp:1972
static constexpr UE_FORCEINLINE_HINT T Square(const T A)
Definition UnrealMathUtility.h:578
static bool LineBoxIntersection2D(const UE::Math::TBox2< FReal > &Box, const UE::Math::TVector2< FReal > &Start, const UE::Math::TVector2< FReal > &End)
Definition Box2D.h:638
static UE_FORCEINLINE_HINT void * Memset(void *Dest, uint8 Char, SIZE_T Count)
Definition UnrealMemory.h:119
Definition IsPODType.h:12
@ Value
Definition IsPODType.h:13
Definition IsUECoreType.h:19
@ Value
Definition IsUECoreType.h:20
Definition Box2D.h:31
TBox2< T > ExpandBy(const TVector2< T > &V) const
Definition Box2D.h:250
TBox2< T > MoveTo(const TVector2< T > &Destination) const
Definition Box2D.h:398
TBox2< T > & operator+=(const TVector2< T > &Other)
Definition Box2D.h:508
TBox2< T > & operator+=(const TBox2< T > &Other)
Definition Box2D.h:529
TBox2< T > operator+(const TBox2< T > &Other) const
Definition Box2D.h:157
bool operator==(const TBox2< T > &Other) const
Definition Box2D.h:96
TBox2< T > ShiftBy(const TVector2< T > &Offset) const
Definition Box2D.h:387
bool IsInside(const TBox2< T > &Other) const
Definition Box2D.h:376
TBox2(const TBox2< FArg > &From)
Definition Box2D.h:470
FString ToString() const
Definition Box2D.h:615
TVector2< T > & operator[](int32 Index)
Definition Box2D.h:168
TBox2< T > operator+(const TVector2< T > &Other) const
Definition Box2D.h:138
void Init()
Definition Box2D.h:325
T GetArea() const
Definition Box2D.h:261
TBox2< T > Overlap(const TBox2< T > &Other) const
Definition Box2D.h:577
bool SerializeFromMismatchedTag(FName StructTag, FArchive &Ar)
Definition Box2D.h:451
bool IsInsideOrOn(const TVector2< T > &TestPoint) const
Definition Box2D.h:365
bool operator!=(const TBox2< T > &Other) const
Definition Box2D.h:107
TVector2< T > Max
Definition Box2D.h:39
bool Intersect(const TBox2< T > &Other) const
Definition Box2D.h:599
bool bIsValid
Definition Box2D.h:42
bool Equals(const TBox2< T > &Other, T Tolerance=UE_KINDA_SMALL_NUMBER) const
Definition Box2D.h:119
TBox2< T > ExpandBy(const T W) const
Definition Box2D.h:239
TVector2< T > GetClosestPointTo(const TVector2< T > &Point) const
Definition Box2D.h:548
bool Serialize(FArchive &Ar)
Definition Box2D.h:441
T ComputeSquaredDistanceToPoint(const TVector2< T > &Point) const
Definition Box2D.h:207
const TVector2< T > & operator[](int32 Index) const
Definition Box2D.h:186
static TBox2< T > BuildAABB(const TVector2< T > &Origin, const TVector2< T > &Extent)
Definition Box2D.h:418
friend FArchive & operator<<(FArchive &Ar, TBox2< T > &Box)
Definition Box2D.h:435
TVector2< T > GetSize() const
Definition Box2D.h:317
TVector2< T > GetExtent() const
Definition Box2D.h:305
T FReal
Definition Box2D.h:33
bool IsInside(const TVector2< T > &TestPoint) const
Definition Box2D.h:353
TBox2()=default
TVector2< T > Min
Definition Box2D.h:36
TVector2< T > GetCenter() const
Definition Box2D.h:272
void GetCenterAndExtents(TVector2< T > &center, TVector2< T > &Extents) const
Definition Box2D.h:284
Definition Vector2D.h:38
T Y
Definition Vector2D.h:52
T X
Definition Vector2D.h:49
T Y
Definition Vector.h:65
T X
Definition Vector.h:62