#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_POLYGON2_H #define NUCLEX_GEOMETRY_AREAS_POLYGON2_H #include "Nuclex/Geometry/Config.h" #include "Nuclex/Geometry/Math.h" #include "Nuclex/Geometry/Point2.h" #include "Nuclex/Geometry/Vector2.h" #include namespace Nuclex { namespace Geometry { namespace Areas { // ------------------------------------------------------------------------------------------- // /// 2D polygon connecting a set of ordered vertices in a loop template struct Polygon2 { /// Initializes a polygon using the specified vertices /// Array containing the polygon's vertices /// Number of vertices in the array public: Polygon2(const Point2 *vertices, std::size_t count) : Vertices(vertices, count) {} /// Calculates the area of the polygon /// The area of the polygon /// /// Formula taken from http://stackoverflow.com/questions/451426 /// http://softsurfer.com/Archive/algorithm_0101/algorithm_0101.htm /// public: TScalar GetArea() const { std::size_t vertexCount = this->Vertices.size(); if(vertexCount < 3) { return 0; } TScalar area = this->Vertices[0].X * ( this->Vertices[1].Y - this->Vertices[vertexCount - 1].Y ); area += this->Vertices[vertexCount - 1].X * ( this->Vertices[0].Y - this->Vertices[vertexCount - 2].Y ); for(std::size_t index = 0; index < vertexCount - 2; ++index) { area += this->Vertices[index + 1].X * ( this->Vertices[index + 2].Y - this->Vertices[index].Y ); } return area / 2; } /// Calculates the perimeter of the polygon /// The polygon's perimeter public: TScalar GetPerimeter() const { std::size_t vertexCount = this->Vertices.size(); if(vertexCount < 2) { return 0; } TScalar length = Point2::DistanceBetween( this->Vertices[vertexCount - 1], this->Vertices[0] ); for(std::size_t index = 0; index < vertexCount - 1; ++index) { length += Point2::DistanceBetween( this->Vertices[index], this->Vertices[index + 1] ); } return length; } /// Offsets the entire polygon by the specified amount /// Amount the polygon will be offset on the X axis /// Amount the polygon will be offset on the Y axis public: void ShiftBy(TScalar amountX, TScalar amountY) { for(std::size_t index = 0; index < this->count; ++index) { this->vertices[index].X += amountX; this->vertices[index].Y += amountY; } } /// Offsets the entire polygon by the specified amount /// Amount the polygon will be offset public: void ShiftBy(const Vector2 &amount) { for(std::size_t index = 0; index < this->count; ++index) { this->Vertices[index] += amount; } } #if 0 public: void Rotate(TScalar angle) { for(std:.size_t index = 0; index < this->count; ++index) { this->Vertices[index] } } #endif /// Calculates the distance between two points /// First point for the distance calculation /// Second point for the distance calculation /// The distance between the two points private: static TScalar distance( const Point2 &first, const Point2 &second ) { TScalar x = second.X - first.X; TScalar y = second.Y - first.Y; return Math::SquareRoot((x * x) + (y * y)); } /// The polygon's vertices public: std::vector< Point2 > Vertices; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Geometry::Areas #endif // NUCLEX_GEOMETRY_AREAS_POLYGON2_H