// 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 }; };