#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2015 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_GEOMETRY_AREAS_RECTANGLE2_H #define NUCLEX_GEOMETRY_AREAS_RECTANGLE2_H #include "../Point2.h" #include "../Vector2.h" #include "../Math.h" #include namespace Nuclex { namespace Geometry { namespace Areas { // ------------------------------------------------------------------------------------------- // /// 2D rectangle defined through minimum and a maximum corner coordinates template struct Rectangle2 { /// A rectangle with zero area public: static const Rectangle2 Empty; /// Builds a rectangle from given minimum and maximum cordinates /// X coordinate of the rectangle's left side /// Y coordinate of the rectangle's top side /// X coordinate of the rectangle's right side /// Y coordinate of the rectangle's bottom side /// A new rectangle using the specified coordinates public: static Rectangle2 FromMinAndMax( TScalar minX, TScalar minY, TScalar maxX, TScalar maxY ) { Rectangle2 rectangle; rectangle.Min.X = minX; rectangle.Min.Y = minY; rectangle.Max.X = maxX; rectangle.Max.Y = maxY; return rectangle; } /// Builds a rectangle from a given location and size /// X coordinate of the rectangle's corner /// Y coordinate of the rectangle's corner /// Width of the rectangle on the X axis /// Height of the rectangle on the Y axis /// A new rectangle using the specified coordinates public: static Rectangle2 FromPointAndSize( TScalar minX, TScalar minY, TScalar width, TScalar height ) { Rectangle2 rectangle; rectangle.Min.X = minX; rectangle.Min.Y = minY; rectangle.Max.X = minX + width; rectangle.Max.Y = minY + height; return rectangle; } #if WANT_CONFUSING_CONSTRUCTOR /// Initializes a rectangle using the specified position and size /// Position of the rectangle's upper left corner /// Size of the rectangle public: Rectangle2(const Point2 &position, const Vector2 &size) : Min(position), Max(position + size) {} #endif /// Constructs an uninitialized rectangle public: Rectangle2() {} /// Initializes a rectangle using the specified corner coordinates /// Position of the rectangle's upper left corner /// Position of the rectangle's lower right corner public: Rectangle2(const Point2 &min, const Point2 &max) : Min(min), Max(max) {} /// Returns the width of the rectangle /// The rectangle's width public: TScalar GetWidth() const { return this->Max.X - this->Min.X; } /// Returns the length of the rectangle /// The rectangle's length public: TScalar GetLength() const { return this->Max.Y - this->Min.Y; } /// Returns a point that lies in the center of the rectangle /// The center of the rectangle public: Point2 GetCenter() const { return Point2( (this->Min.X + this->Max.X) / 2, (this->Min.Y + this->Max.Y) / 2 ); } /// Calculates the area of the rectangle /// The area of the rectangle public: TScalar GetArea() const { EnforceNotFlipped(); return (this->Max.X - this->Min.X) * (this->Max.Y - this->Min.Y); } /// Calculates the perimeter of the rectangle /// The rectangle's perimeter public: TScalar GetPerimeter() const { EnforceNotFlipped(); TScalar horizontal = (this->Max.X - this->Min.X) * 2; TScalar vertical = (this->Max.Y - this->Min.Y) * 2; return horizontal + vertical; } /// Ensures that the rectangle is not flipped on any axis public: void Unflip() { if(this->Min.X > this->Max.X) { std::swap(this->Min.X, this->Max.X); } if(this->Min.Y > this->Max.Y) { std::swap(this->Min.Y, this->Max.Y); } } /// Offsets the entire rectangle by the specified amount /// Amount the rectangle will be offset on the X axis /// Amount the rectangle will be offset on the Y axis public: void ShiftBy(TScalar amountX, TScalar amountY) { this->Min.X += amountX; this->Max.X += amountX; this->Min.Y += amountY; this->Max.Y += amountY; } /// Offsets the entire rectangle by the specified amount /// Amount the rectangle will be offset public: void ShiftBy(const Vector2 &amount) { this->Min += amount; this->Max += amount; } #if WANT_CONFUSING_PLACEMENT /// Moves the rectangle to the specified location /// X coordinate the rectangle's minimum corner will end up at /// Y coordinate the rectangle's minimum corner will end up at public: void PlaceAt(TScalar x, TScalar y) { this->Max.X = x + (this->Max.X - this->Min.X); this->Max.Y = y + (this->Max.Y - this->Min.Y); this->Min.X = x; this->Min.Y = y; } /// Moves the rectangle to the specified location /// Position the rectangle's minimum corner will end up at public: void PlaceAt(const Point2 &position) { this->Max = position + (this->Max - this->Min); this->Min = position; } #endif // WANT_CONFUSING_PLACEMENT /// Triggers an assertion if the rectangle is flipped on any axis public: void EnforceNotFlipped() const { using namespace std; assert((this->Min.X <= this->Max.X) && "Rectangle must not be flipped on the X axis"); assert((this->Min.Y <= this->Max.Y) && "Rectangle must not be flipped on the Y axis"); } /// Coordinates of the rectangle's lower left corner public: Point2 Min; /// Coordinates of the rectangle's upper right corner public: Point2 Max; }; // ------------------------------------------------------------------------------------------- // template const Rectangle2 Rectangle2::Empty( Point2::Zero, Point2::Zero ); // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Geometry::Areas #endif // NUCLEX_GEOMETRY_AREAS_RECTANGLE2_H