#pragma once // These are not directly used but would otherwise be included in most files. // Leaving them included here. #include #include #include #include #include #include #include #include #include #include // Disable lengthy tests in debug mode #ifdef NDEBUG #define IGL_DEBUG_OFF "" #else #define IGL_DEBUG_OFF "[!hide]" #endif #if !defined(NDEBUG) && defined(__linux__) #include #define IGL_PUSH_FPE \ fexcept_t current_exceptions; \ fegetexceptflag(¤t_exceptions, FE_ALL_EXCEPT); \ fedisableexcept(FE_ALL_EXCEPT); #define IGL_POP_FPE \ /* Surprise! Use fesetexceptflag here not feenableexcept */ \ fesetexceptflag(¤t_exceptions,FE_ALL_EXCEPT); #else // No-op #define IGL_PUSH_FPE #define IGL_POP_FPE #endif #include template<> struct Catch::StringMaker > { static std::string convert(std::tuple const& t) { return STR("("<(t)<<","<(t)<<","<(t)<<")"); } }; template<> struct Catch::StringMaker > { static std::string convert(std::tuple const& t) { return STR("("<(t)<<","<(t)<<","<(t)<<")"); } }; namespace test_common { template void run_test_cases(const std::vector ¶ms, Fun test_case) { for(const auto &p : params) { // Can't use INFO( p ) because we're not sure how to print p test_case(p); } } template void run_test_cases(const std::vector ¶ms, Fun test_case) { for(const auto &p : params) { INFO( p ); test_case(p); } } inline std::vector closed_genus_0_meshes() { return { "cube.obj", "decimated-knight.obj", "boolean_minus_test_cube.obj", "boolean_minus_test_green.obj", }; }; inline std::vector closed_manifold_meshes() { std::vector meshes = closed_genus_0_meshes(); meshes.insert(meshes.end(), { "TinyTorus.obj", }); return meshes; }; inline std::vector manifold_meshes() { std::vector meshes = closed_manifold_meshes(); meshes.insert(meshes.end(), { "bunny.off", "elephant.off", "hemisphere.obj", }); return meshes; }; inline std::vector tet_meshes() { return { "decimated-knight.mesh" }; }; inline std::vector all_meshes() { std::vector meshes = manifold_meshes(); meshes.insert(meshes.end(), { "truck.obj", }); return meshes; }; inline std::string data_path(std::string s) { return std::string(LIBIGL_DATA_DIR) + "/" + s; }; template void assert_eq( const Eigen::MatrixBase & A, const Eigen::MatrixBase & B) { // Sizes should match REQUIRE(A.rows() == B.rows()); REQUIRE(A.cols() == B.cols()); for(int i = 0;i Aijv {i,j,A(i,j)}; std::tuple Bijv {i,j,B(i,j)}; REQUIRE(Aijv == Bijv); } } } template void assert_neq( const Eigen::MatrixBase & A, const Eigen::MatrixBase & B) { // Sizes should match REQUIRE(A.rows() == B.rows()); REQUIRE(A.cols() == B.cols()); bool all_equals = true; for(int i = 0;i void assert_eq( const Eigen::SparseMatrix & A, const Eigen::SparseMatrix & B) { // Sizes should match REQUIRE(A.rows() == B.rows()); REQUIRE(A.cols() == B.cols()); Eigen::Matrix AI,AJ; Eigen::Matrix BI,BJ; Eigen::Matrix AV; Eigen::Matrix BV; // Assumes A and B are in same Major Ordering igl::find(A,AI,AJ,AV); igl::find(B,BI,BJ,BV); // This doesn't generalized to assert_near nicely, and it makes it hard to // tell which entries are different: assert_eq(AI,BI); assert_eq(AJ,BJ); assert_eq(AV,BV); } template void assert_near( const Eigen::MatrixBase & A, const Eigen::MatrixBase & B, const EpsType & eps) { // Sizes should match REQUIRE(A.rows() == B.rows()); REQUIRE(A.cols() == B.cols()); for(int i = 0;i Aijv {i,j,A(i,j)}; // std::tuple Bijv {i,j,B(i,j)+eps}; REQUIRE(A(i,j) < B(i,j)+eps); } { // std::tuple Aijv {i,j,A(i,j)+eps}; // std::tuple Bijv {i,j,B(i,j)}; REQUIRE(A(i,j)+eps > B(i,j)); } } } } }