// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Math/Rectangle.h"
///
/// Represents a rectangle that has been transformed by an arbitrary render transform.
///
struct RotatedRectangle
{
public:
///
/// The transformed top left corner.
///
Float2 TopLeft;
///
/// The transformed X extent (right-left).
///
Float2 ExtentX;
///
/// The transformed Y extent (bottom-top).
///
Float2 ExtentY;
public:
///
/// Initializes a new instance of the struct.
///
RotatedRectangle()
{
}
///
/// Initializes a new instance of the struct.
///
/// The aligned rectangle.
explicit RotatedRectangle(const Rectangle& rect)
: TopLeft(rect.GetUpperLeft())
, ExtentX(rect.GetWidth(), 0.0f)
, ExtentY(0.0f, rect.GetHeight())
{
}
///
/// Initializes a new instance of the struct.
///
/// The top left corner.
/// The extent on X axis.
/// The extent on Y axis.
RotatedRectangle(const Float2& topLeft, const Float2& extentX, const Float2& extentY)
: TopLeft(topLeft)
, ExtentX(extentX)
, ExtentY(extentY)
{
}
public:
///
/// Convert rotated rectangle to the axis-aligned rectangle that builds rotated rectangle bounding box.
///
/// The bounds rectangle.
Rectangle ToBoundingRect() const
{
Float2 points[4] =
{
TopLeft,
TopLeft + ExtentX,
TopLeft + ExtentY,
TopLeft + ExtentX + ExtentY
};
return Rectangle::FromPoints(points, 4);
}
///
/// Determines whether the specified location is contained within this rotated rectangle.
///
/// The location to test.
/// true if the specified location is contained by this rotated rectangle; otherwise, false.
bool ContainsPoint(const Float2& location) const
{
const Float2 offset = location - TopLeft;
const float det = Float2::Cross(ExtentX, ExtentY);
const float s = Float2::Cross(offset, ExtentX) / -det;
if (Math::IsInRange(s, 0.0f, 1.0f))
{
const float t = Float2::Cross(offset, ExtentY) / det;
return Math::IsInRange(t, 0.0f, 1.0f);
}
return false;
}
public:
bool operator ==(const RotatedRectangle& other) const
{
return
TopLeft == other.TopLeft &&
ExtentX == other.ExtentX &&
ExtentY == other.ExtentY;
}
};
template<>
struct TIsPODType
{
enum { Value = true };
};