| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include <catch2/catch_test_macros.hpp> |
| #include <catch2/catch_approx.hpp> |
|
|
| #include "rs_debug.h" |
| #include "rs_spline.h" |
| #include "lc_splinehelper.h" |
| #include "rs_vector.h" |
| #include "rs_math.h" |
|
|
| using Catch::Approx; |
|
|
| namespace { |
| bool compareVector(const RS_Vector& va, const RS_Vector& vb, double tol = 1e-4) { |
| return va.distanceTo(vb) <= tol; |
| } |
| } |
|
|
| TEST_CASE("RS_Spline Basic Functionality", "[RS_Spline]") |
| { |
| RS_SplineData splineData(3, false); |
| RS_Spline spline(nullptr, splineData); |
|
|
| SECTION("Construction and Getters") |
| { |
| REQUIRE(spline.getDegree() == 3); |
| REQUIRE(!spline.isClosed()); |
| REQUIRE(spline.getNumberOfControlPoints() == 0); |
| REQUIRE(spline.getNumberOfKnots() == 0); |
| } |
|
|
| SECTION("Set Degree") |
| { |
| spline.setDegree(2); |
| REQUIRE(spline.getDegree() == 2); |
|
|
| REQUIRE_THROWS_AS(spline.setDegree(0), std::invalid_argument); |
| REQUIRE_THROWS_AS(spline.setDegree(4), std::invalid_argument); |
| } |
| } |
|
|
|
|
| TEST_CASE("Non-uniform knot vectors - validation and type handling", "[RS_Spline][nonuniform]") |
| { |
| SECTION("ClampedOpen non-uniform knots - valid") |
| { |
| RS_SplineData d(3, false); |
| d.type = RS_SplineData::SplineType::ClampedOpen; |
| d.controlPoints = { |
| RS_Vector(0,0), RS_Vector(10,20), RS_Vector(30,30), RS_Vector(50,20), RS_Vector(60,0), RS_Vector(70,10), RS_Vector(80,0) |
| }; |
| d.weights = {1.0, 2.0, 1.5, 1.0, 1.0, 1.2, 1.0}; |
|
|
| d.knotslist = {0.0, 0.0, 0.0, 0.0, 8.0, 25.0, 55.0, 100.0, 100.0, 100.0, 100.0}; |
|
|
| RS_Spline s(nullptr, d); |
| REQUIRE(s.validate() == true); |
| REQUIRE(s.isClosed() == false); |
| REQUIRE(s.getDegree() == 3); |
| REQUIRE(s.getNumberOfControlPoints() == 7); |
| } |
|
|
| SECTION("ClampedOpen non-uniform - invalid (wrong end multiplicity)") |
| { |
| RS_SplineData d(3, false); |
| d.type = RS_SplineData::SplineType::ClampedOpen; |
| d.controlPoints = { |
| RS_Vector(0,0), RS_Vector(10,20), RS_Vector(30,30), RS_Vector(50,20), RS_Vector(60,0), RS_Vector(70,10), RS_Vector(80,0) |
| }; |
| d.weights = {1.0, 2.0, 1.5, 1.0, 1.0, 1.2, 1.0}; |
|
|
| |
| d.knotslist = {0.0, 0.0, 0.0, 0.0, 8.0, 25.0, 55.0, 90.0, 100.0, 100.0, 100.0}; |
|
|
| RS_Spline s(nullptr, d); |
| REQUIRE(s.validate() == false); |
| } |
|
|
| SECTION("Standard (open non-clamped non-uniform) - valid") |
| { |
| RS_SplineData d(3, false); |
| d.type = RS_SplineData::SplineType::Standard; |
| d.controlPoints = { |
| RS_Vector(0,0), RS_Vector(15,25), RS_Vector(40,35), RS_Vector(80,0) |
| }; |
| d.weights.assign(4, 1.0); |
| d.knotslist = {0.0, 12.0, 35.0, 60.0, 100.0, 140.0, 180.0, 220.0}; |
|
|
| RS_Spline s(nullptr, d); |
| REQUIRE(s.validate() == true); |
| } |
|
|
| SECTION("Standard non-uniform - invalid (accidental clamping at start)") |
| { |
| RS_SplineData d(3, false); |
| d.type = RS_SplineData::SplineType::Standard; |
| d.controlPoints = { |
| RS_Vector(0,0), RS_Vector(15,25), RS_Vector(40,35), RS_Vector(80,0) |
| }; |
| d.weights.assign(4, 1.0); |
| d.knotslist = {0.0, 0.0, 0.0, 0.0, 20.0, 50.0, 100.0, 150.0}; |
|
|
| RS_Spline s(nullptr, d); |
| REQUIRE(s.validate() == false); |
| } |
|
|
| SECTION("WrappedClosed non-uniform knots - valid") |
| { |
| RS_SplineData d(3, true); |
| d.type = RS_SplineData::SplineType::WrappedClosed; |
| d.controlPoints = { |
| RS_Vector(0,0), RS_Vector(15,25), RS_Vector(40,35), RS_Vector(70,20), RS_Vector(80,0), |
| RS_Vector(0,0), RS_Vector(15,25), RS_Vector(40,35) |
| }; |
| d.weights = {1.0, 1.5, 2.0, 1.5, 1.0, 1.0, 1.5, 2.0}; |
| d.knotslist = {0.0, 12.0, 35.0, 60.0, 100.0, 140.0, 180.0, 220.0, 260.0, 290.0, 320.0, 350.0}; |
|
|
| RS_Spline s(nullptr, d); |
| REQUIRE(s.validate() == true); |
| REQUIRE(s.isClosed() == true); |
| REQUIRE(s.hasWrappedControlPoints() == true); |
| } |
|
|
| SECTION("WrappedClosed non-uniform - invalid (clamped-style ends)") |
| { |
| RS_SplineData d(3, true); |
| d.type = RS_SplineData::SplineType::WrappedClosed; |
| d.controlPoints.resize(8); |
| d.weights.assign(8, 1.0); |
| d.knotslist = {0.0, 0.0, 0.0, 0.0, 20.0, 50.0, 100.0, 150.0, 150.0, 150.0, 150.0}; |
|
|
| RS_Spline s(nullptr, d); |
| REQUIRE(s.validate() == false); |
| } |
|
|
| SECTION("WrappedClosed non-uniform - valid (missing wrapped control points)") |
| { |
| RS_SplineData d(3, true); |
| d.type = RS_SplineData::SplineType::WrappedClosed; |
| d.controlPoints = { |
| RS_Vector(0,0), RS_Vector(10,10), RS_Vector(20,10), RS_Vector(30,10), RS_Vector(40,0), |
| RS_Vector(99,99), RS_Vector(99,99), RS_Vector(99,99) |
| }; |
| d.weights.assign(8, 1.0); |
| d.knotslist = {0.0, 10.0, 20.0, 35.0, 55.0, 80.0, 110.0, 140.0, 170.0, 200.0, 230.0, 260.0}; |
|
|
| |
| RS_Spline s(nullptr, d); |
| REQUIRE(s.validate()); |
| } |
| } |
|
|