#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