#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