test_curve_fitting.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #include <catch2/catch.hpp>
  2. #include <test_utils.hpp>
  3. #include <libslic3r/Geometry/Curves.hpp>
  4. #include <libslic3r/Utils.hpp>
  5. #include <libslic3r/SVG.hpp>
  6. TEST_CASE("Curves: cubic b spline fit test", "[Curves]") {
  7. using namespace Slic3r;
  8. using namespace Slic3r::Geometry;
  9. auto fx = [&](size_t index) {
  10. return float(index) / 200.0f;
  11. };
  12. auto fy = [&](size_t index) {
  13. return 1.0f;
  14. };
  15. std::vector<Vec<1, float>> observations { };
  16. std::vector<float> observation_points { };
  17. std::vector<float> weights { };
  18. for (size_t index = 0; index < 200; ++index) {
  19. observations.push_back(Vec<1, float> { fy(index) });
  20. observation_points.push_back(fx(index));
  21. weights.push_back(1);
  22. }
  23. Vec2f fmin { fx(0), fy(0) };
  24. Vec2f fmax { fx(200), fy(200) };
  25. auto bspline = fit_cubic_bspline(observations, observation_points, weights, 1);
  26. Approx ap(1.0f);
  27. ap.epsilon(0.1f);
  28. for (int p = 0; p < 200; ++p) {
  29. float fitted_val = bspline.get_fitted_value(fx(p))(0);
  30. float expected = fy(p);
  31. REQUIRE(fitted_val == ap(expected));
  32. }
  33. }
  34. TEST_CASE("Curves: quadratic f cubic b spline fit test", "[Curves]") {
  35. using namespace Slic3r;
  36. using namespace Slic3r::Geometry;
  37. auto fx = [&](size_t index) {
  38. return float(index) / 100.0f;
  39. };
  40. auto fy = [&](size_t index) {
  41. return (fx(index) - 1) * (fx(index) - 1);
  42. };
  43. std::vector<Vec<1, float>> observations { };
  44. std::vector<float> observation_points { };
  45. std::vector<float> weights { };
  46. for (size_t index = 0; index < 200; ++index) {
  47. observations.push_back(Vec<1, float> { fy(index) });
  48. observation_points.push_back(fx(index));
  49. weights.push_back(1);
  50. }
  51. Vec2f fmin { fx(0), fy(0) };
  52. Vec2f fmax { fx(200), fy(200) };
  53. auto bspline = fit_cubic_bspline(observations, observation_points, weights, 10);
  54. for (int p = 0; p < 200; ++p) {
  55. float fitted_val = bspline.get_fitted_value(fx(p))(0);
  56. float expected = fy(p);
  57. auto check = [](float a, float b) {
  58. return abs(a - b) < 0.2f;
  59. };
  60. //Note: checking is problematic, splines will not perfectly align
  61. REQUIRE(check(fitted_val, expected));
  62. }
  63. }
  64. TEST_CASE("Curves: polynomial fit test", "[Curves]") {
  65. using namespace Slic3r;
  66. using namespace Slic3r::Geometry;
  67. auto fx = [&](size_t index) {
  68. return float(index) / 100.0f;
  69. };
  70. auto fy = [&](size_t index) {
  71. return (fx(index) - 1) * (fx(index) - 1);
  72. };
  73. std::vector<Vec<1, float>> observations { };
  74. std::vector<float> observation_points { };
  75. std::vector<float> weights { };
  76. for (size_t index = 0; index < 200; ++index) {
  77. observations.push_back(Vec<1, float> { fy(index) });
  78. observation_points.push_back(fx(index));
  79. weights.push_back(1);
  80. }
  81. Vec2f fmin { fx(0), fy(0) };
  82. Vec2f fmax { fx(200), fy(200) };
  83. Approx ap(1.0f);
  84. ap.epsilon(0.1f);
  85. auto poly = fit_polynomial(observations, observation_points, weights, 2);
  86. REQUIRE(poly.coefficients(0, 0) == ap(1));
  87. REQUIRE(poly.coefficients(0, 1) == ap(-2));
  88. REQUIRE(poly.coefficients(0, 2) == ap(1));
  89. }