#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_LINES_POLYLINE2_H #define NUCLEX_GEOMETRY_LINES_POLYLINE2_H #include "Nuclex/Geometry/Config.h" #include "Nuclex/Geometry/Point2.h" #include namespace Nuclex { namespace Geometry { namespace Lines { // ------------------------------------------------------------------------------------------- // /// Strip of connected 2D line segments template struct PolyLine2 { /// Constructs an uninitialized polyline public: PolyLine2() {} /// Constructs a polyline as copy of an existing polyline /// Other polyline that will be coeeid public: PolyLine2(const PolyLine2 &other) : Vertices(other.Vertices) {} /// Calculates the length of the polyline /// The polyline's length public: TScalar GetLength() const { std::size_t vertexCount = this->Vertices.size(); if(vertexCount < 2) { return 0; } TScalar length = Point2::DistanceBetween(this->Vertices[0], this->Vertices[1]); for(std::size_t index = 1; index < vertexCount - 1; ++index) { length += Point2::DistanceBetween( this->Vertices[index], this->Vertices[index + 1] ); } return length; } /// Clones a subset of the poly line /// Index of the first vertex to place in the clone /// Number of vertices that should be added to the clone /// A poly line containing the specified range of vertices public: PolyLine2 Subset(std::size_t firstIndex, std::size_t count) const { PolyLine2 result; result.Vertices.reserve(count); count += firstIndex; for(std::size_t index = firstIndex; index < count; ++index) { result.Vertices.push_back(this->Vertices[index]); } return result; } /// Clones a subset of the poly line /// Index of the first vertex to place in the clone /// A poly line containing the specified range of vertices public: PolyLine2 Subset(std::size_t firstIndex) const { PolyLine2 result; std::size_t count = this->Vertices.size(); result.Vertices.reserve(count - firstIndex); for(std::size_t index = firstIndex; index < count; ++index) { result.Vertices.push_back(this->Vertices[index]); } return result; } /// Offsets the entire polyline by the specified amount /// Amount the polyline will be offset on the X axis /// Amount the polyline 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 polyline by the specified amount /// Amount the polyline will be offset public: void ShiftBy(const Vector2 &amount) { for(std::size_t index = 0; index < this->count; ++index) { this->Vertices[index] += amount; } } /// Finds the index of the vertex that is closest to a given point /// Point to which the closes vertex will be found /// The index of the closest vertex public: std::size_t GetClosestVertexIndex(const Point2 &referencePoint) const { return GetClosestVertexIndex(referencePoint.X, referencePoint.Y); } /// Finds the index of the vertex that is closest to a given point /// X coordinate to which the closes vertex will be found /// Y coordinate to which the closes vertex will be found /// The index of the closest vertex public: std::size_t GetClosestVertexIndex(TScalar x, TScalar y) const { if(this->Vertices.empty()) { throw std::runtime_error("No closest vertex because poly line contains no vertices"); } std::size_t closestIndex = 0; TScalar closestSquaredDistance = this->Vertices[0].SquaredDistanceTo(x, y); for(std::size_t index = 1; index < this->Vertices.size(); ++index) { TScalar squaredDistance = this->Vertices[index].SquaredDistanceTo(x, y); if(squaredDistance < closestSquaredDistance) { closestIndex = index; closestSquaredDistance = squaredDistance; } } return closestIndex; } /// The polyline's vertices public: std::vector< Point2 > Vertices; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Geometry::Lines #endif // NUCLEX_GEOMETRY_LINES_POLYLINE2_H