#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_GENERATORS_RECTANGLE2GENERATOR_H #define NUCLEX_GEOMETRY_AREAS_GENERATORS_RECTANGLE2GENERATOR_H #include "Nuclex/Geometry/Config.h" #include "Nuclex/Geometry/Math.h" #include "Nuclex/Geometry/Areas/Rectangle2.h" #include "Nuclex/Geometry/Areas/Disc2.h" namespace Nuclex { namespace Geometry { namespace Areas { namespace Generators { // ------------------------------------------------------------------------------------------- // /// Point and area generation methods for 2D discs template class Rectangle2Generator { /// Returns a random point within the rectangle /// Rectangle in which a random point will be generated /// Random number generator that will be used /// A random point inside the rectangle public: template static Point2 GetRandomPointInside( const Rectangle2 &rectangle, TRandomNumberEngine &random ) { rectangle.EnforceNotFlipped(); return new Point2( Math::Random(random, rectangle.Min.X, rectangle.Max.X), Math::Random(random, rectangle.Min.Y, rectangle.Max.Y) ); } /// Returns a random point on the outline of the rectangle /// /// Rectangle on whose outline a random point will be generated /// /// Random number generator that will be used /// A random point on the rectangle's outline public: template static Point2 GetRandomPointOnOutline( const Rectangle2 &rectangle, TRandomNumberEngine &random ) { rectangle.EnforceNotFlipped(); TScalar width = rectangle.Max.X - rectangle.Min.X; TScalar height = rectangle.Max.Y - rectangle.Min.Y; TScalar doubleWidth = width * 2; TScalar distance = Math::Random(random, doubleWidth + (height * 2)); if(distance < doubleWidth) { if(distance < width) { return Point2(rectangle.Min.X + distance, rectangle.Min.Y); } else { return Point2(rectangle.Min.X + distance - width, rectangle.Max.Y); } } else { distance -= doubleWidth; if(distance < height) { return Point2(rectangle.Min.X, rectangle.Min.Y + distance); } else { return Point2(rectangle.Max.X, rectangle.Min.Y + distance - height); } } } /// Determines the closest point to another point inside the rectangle /// Rectangle in which the closest point will be found /// Point to which the closest point will be determined /// The closest point to the specified point inside the rectangle public: static Point2 GetClosestPointInside( const Rectangle2 &rectangle, const Point2 &point ) { rectangle.EnforceNotFlipped(); return Point2( Math::Clamp(point.X, rectangle.Min.X, rectangle.Max.X), Math::Clamp(point.Y, rectangle.Min.Y, rectangle.Max.Y) ); } /// Determines the closest point to another point on the disc's outline /// Rectangle on whose outline the closest point will be found /// Point to which the closest point will be determined /// The closest point to the specified point on the disc's outline public: static Point2 GetClosestPointOnOutline( const Rectangle2 &rectangle, const Point2 &point ) { rectangle.EnforceNotFlipped(); Point2 closest; if(point.X - rectangle.Min.X < rectangle.Max.X - point.X) { closest.X = rectangle.Min.X; } else { closest.X = rectangle.Max.X; } if(point.Y - rectangle.Min.Y < rectangle.Max.Y - point.Y) { closest.Y = rectangle.Min.Y; } else { closest.Y = rectangle.Max.Y; } return closest; } /// Calculates the bounding rectangle of a rectangle /// /// Rectangle of which the bounding rectangle will be calculated /// /// The rectangle's bounding rectangle /// /// This is a no-op, but provided for completeness so templated algorithms /// can assume this member to be there in any generator type. /// public: static Rectangle2 GetBoundingRectangle( const Rectangle2 &rectangle ) { return rectangle; } /// Calculates the bounding disc of a rectangle /// Rectangle of which the bounding disc will be calculated /// The rectangle's bounding disc public: static Disc2 GetBoundingDisc(const Rectangle2 &rectangle) { Point2 center = rectangle.GetCenter(); return Disc2(center, Point2::Distance(center, rectangle.Min)); } }; // ------------------------------------------------------------------------------------------- // }}}} // namespace Nuclex::Geometry::Areas::Generators #endif // NUCLEX_GEOMETRY_AREAS_GENERATORS_RECTANGLE2GENERATOR_H