#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_POLYLINE3_H #define NUCLEX_GEOMETRY_LINES_POLYLINE3_H #include "Nuclex/Geometry/Config.h" #include "Nuclex/Geometry/Point3.h" #include namespace Nuclex { namespace Geometry { namespace Lines { // ------------------------------------------------------------------------------------------- // /// Strip of connected 3D line segments template struct PolyLine3 { /// Constructs an uninitialized polyline public: PolyLine3() {} /// 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 = Point3::DistanceBetween(this->Vertices[0], this->Vertices[1]); for(std::size_t index = 1; index < vertexCount - 1; ++index) { length += Point3::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: PolyLine3 Subset(std::size_t firstIndex, std::size_t count) const { PolyLine3 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: PolyLine3 Subset(std::size_t firstIndex) const { PolyLine3 result; std::size_t endIndex = this->Vertices.size(); result.Vertices.reserve(endIndex - firstIndex); for(std::size_t index = firstIndex; index < endIndex; ++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 /// Amount the polyline will be offset on the Z axis public: void ShiftBy(TScalar amountX, TScalar amountY, TScalar amountZ) { for(std::size_t index = 0; index < this->count; ++index) { this->vertices[index].X += amountX; this->vertices[index].Y += amountY; this->vertices[index].Z += amountZ; } } /// Offsets the entire polyline by the specified amount /// Amount the polyline will be offset public: void ShiftBy(const Vector3 &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 Point3 &referencePoint) const { return GetClosestVertexIndex(referencePoint.X, referencePoint.Y, referencePoint.Z); } /// 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 /// Z coordinate to which the closes vertex will be found /// The index of the closest vertex public: std::size_t GetClosestVertexIndex(TScalar x, TScalar y, TScalar z) 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, z); for(std::size_t index = 1; index < this->Vertices.size(); ++index) { TScalar squaredDistance = this->Vertices[index].SquaredDistanceTo(x, y,z); if(squaredDistance < closestSquaredDistance) { closestIndex = index; closestSquaredDistance = squaredDistance; } } return closestIndex; } /// The polyline's vertices public: std::vector< Point3 > Vertices; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Geometry::Lines #endif // NUCLEX_GEOMETRY_LINES_POLYLINE3_H