#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_POLYGON2GENERATOR_H
#define NUCLEX_GEOMETRY_AREAS_GENERATORS_POLYGON2GENERATOR_H
#include "Nuclex/Geometry/Config.h"
#include "Nuclex/Geometry/Areas/Polygon2.h"
#include "Nuclex/Geometry/Areas/Disc2.h"
#include "Nuclex/Geometry/Areas/Rectangle2.h"
namespace Nuclex { namespace Geometry { namespace Areas { namespace Generators {
// ------------------------------------------------------------------------------------------- //
/// Point and area generation methods for 2D polygons
template
class Polygon2Generator {
/// Returns a random point within the polygon
/// Polygon in which a random point will be generated
/// Random number generator that will be used
/// A random point inside the polygon
public: template
static Point2 GetRandomPointInside(
const Polygon2 &polygon, TRandomNumberEngine &random
) {
static_assert("Not implemented yet");
}
/// Returns a random point on the outline of the polygon
/// Polygon on whose outline a random point will be generated
/// Random number generator that will be used
/// A random point on the polygon's outline
public: template
static Point2 GetRandomPointOnOutline(
const Polygon2 &polygon, TRandomNumberEngine &random
) {
std::size_t vertexCount = polygon->Vertices.size();
if(vertexCount < 2) {
if(vertexCount == 0) {
throw std::runtime_error(
"Random point on outline of polygon without vertices does not exist"
);
}
return polygon->Vertices[0];
}
// Calculate the total perimeter of the polygon
TScalar squaredPerimeter = Point2::SquaredDistanceBetween(
polygon->Vertices[vertexCount - 1], polygon->Vertices[0]
);
for(std::size_t index = 0; index < vertexCount - 1; ++index) {
squaredPerimeter += Point2::SquaredDistanceBetween(
polygon->Vertices[index], polygon->Vertices[index + 1]
);
}
// Take a random distance on the polygon's perimeter
TScalar randomSquaredDistance = Math::Random(random, squaredPerimeter);
// Find the line segment in which this random distance falls
squaredPerimeter = 0;
for(std::size_t index = 0; index < vertexCount - 1; ++index) {
TScalar squaredLength = Point2::SquaredDistanceBetween(
polygon->Vertices[index], polygon->Vertices[index + 1]
);
TScalar previousSquaredPerimeter = squaredPerimeter;
squaredPerimeter += squaredLength;
if(randomSquaredDistance < squaredPerimeter) {
return Point2::Lerp(
polygon->Vertices[index], polygon->Vertices[index + 1],
(randomSquaredDistance - previousSquaredPerimeter) / squaredLength
);
}
}
// Only the closing line segment remains, thus the random distance falls within it
TScalar squaredLength = Point2::SquaredDistanceBetween(
polygon->Vertices[vertexCount - 1], polygon->Vertices[0]
);
return Point2::Lerp(
polygon->Vertices[vertexCount - 1], polygon->Vertices[0],
(randomSquaredDistance - squaredPerimeter) / squaredLength
);
}
/// Determines the closest point to another point inside the polygon
/// Polygon 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 polygon
public: static Point2 GetClosestPointInside(
const Polygon2 &polygon, const Point2 &point
) {
static_assert("Not implemented yet");
}
/// Determines the closest point to another point on the polygon's outline
/// Polygon 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 polygon's outline
public: Point2 GetClosestPointOnOutline(
const Polygon2 &polygon, const Point2 &point
) const {
std::size_t vertexCount = polygon->Vertices.size();
if(vertexCount < 2) {
if(vertexCount == 0) {
throw std::runtime_error(
"Closest point on outline of polygon without vertices does not exist"
);
}
return polygon.Vertices[0];
}
static_assert("Not implemented yet");
/*
TScalar closestSquaredDistance = polygon.Vertices[0].SquaredDistanceTo(point);
std::size_t closestIndex = 0;
for(std::size_t index = 1; index < polygon.Vertices.size(); ++index) {
TScalar squaredDistance = polygon.Vertices[index].SquaredDistanceTo(point);
if(squaredDistance < closestSquaredDistance) {
closestIndex = index;
closestSquaredDistance =
}
}
*/
}
/// Calculates the bounding rectangle of a polygon
/// Polygon of which the bounding rectangle will be calculated
/// The polygon's bounding rectangle
public: Rectangle2 GetBoundingRectangle(const Polygon2 &polygon) const {
std::size_t vertexCount = polygon.Vertices.size();
if(vertexCount == 0) {
return Rectangle2::Empty;
}
Rectangle2 boundingRectangle;
boundingRectangle.Min = boundingRectangle.Max = polygon.Vertices[0];
for(std::size_t index = 1; index < polygon.Vertices.size(); ++index) {
const Point2 &vertex = polygon.Vertices[index];
if(vertex.X < boundingRectangle.Min.X) {
boundingRectangle.Min.X = vertex.X;
}
if(vertex.X >= boundingRectangle.Max.X) {
boundingRectangle.Max.X = vertex.X;
}
if(vertex.Y < boundingRectangle.Min.Y) {
boundingRectangle.Min.Y = vertex.Y;
}
if(vertex.Y >= boundingRectangle.Max.Y) {
boundingRectangle.Max.Y = vertex.Y;
}
}
return boundingRectangle;
}
/// Calculates the bounding disc of a polygon
/// Polygon of which the bounding disc will be calculated
/// The disc's bounding disc
///
/// This is a no-op, but provided for completeness so templated algorithms
/// can assume this member to be there in any generator type.
///
public: Disc2 GetBoundingDisc(const Polygon2 &polygon) const {
static_assert("Not implemented yet");
}
};
// ------------------------------------------------------------------------------------------- //
}}}} // namespace Nuclex::Geometry::Areas::Generators
#endif // NUCLEX_GEOMETRY_AREAS_GENERATORS_POLYGON2GENERATOR_H