#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 // If the library is compiled as a DLL, this ensures symbols are exported #define NUCLEX_GEOMETRY_SOURCE 1 #include "Nuclex/Geometry/Lines/Interpolators/NearestInterpolator.h" #include "Nuclex/Geometry/Point2.h" #include namespace { // ------------------------------------------------------------------------------------------- // /// Vertex traits for Point2 types when used in interpolators struct Point2VertexTraits { /// Type that is used to measure distance between vertices public: typedef float TDistance; /// Type that is used to specify the interpolation interval public: typedef float TScalar; /// A vertex with a value of zero public: static const Nuclex::Geometry::Point2 ZeroVertex; /// Measures the distance between two vertices /// First vertex for the distance calculation /// Second vertex for the distance calculation /// The distance between the two vertices public: static TDistance DistanceBetween( const Nuclex::Geometry::Point2 &first, const Nuclex::Geometry::Point2 &second ) { return Nuclex::Geometry::Point2::DistanceBetween(first, second); } /// Rounds a scalar / interval value to the closest integer /// Scalar / interval value that will be rounded /// The closest integer to the specified scalar / interval value public: static std::size_t RoundScalarToInteger(float t) { return static_cast(t + 0.5f); } /// Truncates a scalar / interval value to the next lower integer /// Scalar / interval value that will be truncated /// The next lower integer to the specified scalar / interval value public: static std::size_t TruncateScalarToInteger(float t) { return static_cast(t); } }; // ------------------------------------------------------------------------------------------- // const Nuclex::Geometry::Point2 Point2VertexTraits::ZeroVertex(0.0f, 0.0f); // ------------------------------------------------------------------------------------------- // /// Interpolator we use for testing typedef Nuclex::Geometry::Lines::Interpolators::NearestInterpolator< Nuclex::Geometry::Point2, Point2VertexTraits > InterpolatorType; // ------------------------------------------------------------------------------------------- // } // anonymous namespace namespace Nuclex { namespace Geometry { namespace Lines { namespace Interpolators { // ------------------------------------------------------------------------------------------- // TEST(NearestInterpolatorTest, InterpolateByTimeHandlesEmptyPath) { std::vector> vertices; EXPECT_EQ( Point2::Zero, InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), 0.5f) ); } // ------------------------------------------------------------------------------------------- // TEST(NearestInterpolatorTest, InterpolateByTimeHandlesSingleVertex) { std::vector> vertices; vertices.push_back(Point2(5.0f, 5.0f)); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), -1.1f) ); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), 0.0f) ); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), 1.1f) ); } // ------------------------------------------------------------------------------------------- // TEST(NearestInterpolatorTest, VertexCanBeFoundByTime) { std::vector> vertices; vertices.push_back(Point2(1.0f, 5.0f)); vertices.push_back(Point2(10.0f, 6.0f)); vertices.push_back(Point2(9.0f, 10.0f)); vertices.push_back(Point2(5.0f, 1.0f)); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), 0.0f) ); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), 0.49f) ); EXPECT_EQ( vertices[1], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), 0.51f) ); EXPECT_EQ( vertices[2], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), 2.48f) ); EXPECT_EQ( vertices[3], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), 2.52f) ); } // ------------------------------------------------------------------------------------------- // TEST(NearestInterpolatorTest, InterpolateByTimeClamps) { std::vector> vertices; vertices.push_back(Point2(1.0f, 5.0f)); vertices.push_back(Point2(10.0f, 1.0f)); vertices.push_back(Point2(5.0f, 10.0f)); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), -0.1f) ); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), -2.5f) ); EXPECT_EQ( vertices[2], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), 2.1f) ); EXPECT_EQ( vertices[2], InterpolatorType::InterpolateByTime(vertices.begin(), vertices.end(), 4.5f) ); } // ------------------------------------------------------------------------------------------- // TEST(NearestInterpolatorTest, InterpolateByDistanceHandlesEmptyPath) { std::vector> vertices; EXPECT_EQ( Point2::Zero, InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), 0.5f) ); } // ------------------------------------------------------------------------------------------- // TEST(NearestInterpolatorTest, InterpolateByDistanceHandlesSingleVertex) { std::vector> vertices; vertices.push_back(Point2(5.0f, 5.0f)); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), -1.1f) ); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), 0.0f) ); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), 1.1f) ); } // ------------------------------------------------------------------------------------------- // TEST(NearestInterpolatorTest, VertexCanBeFoundByDistance) { std::vector> vertices; vertices.push_back(Point2(1.0f, 5.0f)); vertices.push_back(Point2(10.0f, 6.0f)); vertices.push_back(Point2(9.0f, 10.0f)); vertices.push_back(Point2(5.0f, 1.0f)); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), 0.0f) ); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), 4.5f) ); EXPECT_EQ( vertices[1], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), 4.6f) ); EXPECT_EQ( vertices[2], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), 18.0f) ); EXPECT_EQ( vertices[3], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), 18.2f) ); } // ------------------------------------------------------------------------------------------- // TEST(NearestInterpolatorTest, InterpolateByDistanceClamps) { std::vector> vertices; vertices.push_back(Point2(1.0f, 5.0f)); vertices.push_back(Point2(10.0f, 1.0f)); vertices.push_back(Point2(5.0f, 10.0f)); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), -0.1f) ); EXPECT_EQ( vertices[0], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), -15.0f) ); EXPECT_EQ( vertices[2], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), 23.1f) ); EXPECT_EQ( vertices[2], InterpolatorType::InterpolateByDistance(vertices.begin(), vertices.end(), 35.0f) ); } // ------------------------------------------------------------------------------------------- // }}}} // namespace Nuclex::Geometry::Lines::Interpolators