// Copyright (c) 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; } /// /// Calculates a rectangle that contains the shared part of both rectangles. /// /// The first rectangle. /// The second rectangle. /// Rectangle that contains shared part of a and b rectangles. static RotatedRectangle Shared(const RotatedRectangle& a, const Rectangle& b) { // Clip the rotated rectangle bounds within the given AABB RotatedRectangle result = a; result.TopLeft = Float2::Max(a.TopLeft, b.GetTopLeft()); // TODO: do a little better math below (in case of actually rotated rectangle) result.ExtentX.X = Math::Min(result.TopLeft.X + result.ExtentX.X, b.GetRight()) - result.TopLeft.X; result.ExtentY.Y = Math::Min(result.TopLeft.Y + result.ExtentY.Y, b.GetBottom()) - result.TopLeft.Y; return result; } public: bool operator ==(const RotatedRectangle& other) const { return TopLeft == other.TopLeft && ExtentX == other.ExtentX && ExtentY == other.ExtentY; } }; template<> struct TIsPODType { enum { Value = true }; };