You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.1 KiB
112 lines
3.1 KiB
1 year ago
|
#include <test_common.h>
|
||
|
#include <igl/massmatrix.h>
|
||
|
#include <igl/doublearea.h>
|
||
|
#include <igl/edges.h>
|
||
|
#include <igl/vertex_triangle_adjacency.h>
|
||
|
|
||
|
TEST_CASE("massmatrix: full", "[igl]" )
|
||
|
{
|
||
|
const auto test_case = [](const std::string ¶m)
|
||
|
{
|
||
|
const double epsilon = 1e-15;
|
||
|
|
||
|
Eigen::MatrixXd V;
|
||
|
Eigen::MatrixXi F;
|
||
|
// Load example mesh: GetParam() will be name of mesh file
|
||
|
igl::read_triangle_mesh(test_common::data_path(param), V, F);
|
||
|
Eigen::SparseMatrix<double> M;
|
||
|
igl::massmatrix(V,F,igl::MASSMATRIX_TYPE_FULL,M);
|
||
|
REQUIRE(M.rows() == V.rows());
|
||
|
REQUIRE(M.cols() == V.rows());
|
||
|
Eigen::MatrixXd dblA;
|
||
|
igl::doublearea(V,F,dblA);
|
||
|
REQUIRE(M.sum() == Approx(dblA.sum()/2.).margin(epsilon));
|
||
|
};
|
||
|
|
||
|
test_common::run_test_cases(test_common::all_meshes(), test_case);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("massmatrix: barycentric", "[igl]" )
|
||
|
{
|
||
|
const auto test_case = [](const std::string ¶m)
|
||
|
{
|
||
|
const double epsilon = 1e-15;
|
||
|
|
||
|
Eigen::MatrixXd V;
|
||
|
Eigen::MatrixXi F;
|
||
|
// Load example mesh: GetParam() will be name of mesh file
|
||
|
igl::read_triangle_mesh(test_common::data_path(param), V, F);
|
||
|
Eigen::SparseMatrix<double> M;
|
||
|
igl::massmatrix(V,F,igl::MASSMATRIX_TYPE_BARYCENTRIC,M);
|
||
|
REQUIRE(M.rows() == V.rows());
|
||
|
REQUIRE(M.cols() == V.rows());
|
||
|
Eigen::MatrixXd dblA;
|
||
|
igl::doublearea(V,F,dblA);
|
||
|
REQUIRE(M.sum() == Approx(dblA.sum()/2.).margin(epsilon));
|
||
|
};
|
||
|
|
||
|
test_common::run_test_cases(test_common::all_meshes(), test_case);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("massmatrix: cube_barycentric", "[igl]")
|
||
|
{
|
||
|
//The allowed error for this test
|
||
|
const double epsilon = 1e-15;
|
||
|
|
||
|
Eigen::MatrixXd V;
|
||
|
Eigen::MatrixXi F;
|
||
|
//This is a cube of dimensions 1.0x1.0x1.0
|
||
|
igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F);
|
||
|
|
||
|
Eigen::SparseMatrix<double> M;
|
||
|
|
||
|
//Check the mass matrix of the cube
|
||
|
igl::massmatrix(V,F,igl::MASSMATRIX_TYPE_BARYCENTRIC,M);
|
||
|
|
||
|
REQUIRE(M.rows() == V.rows());
|
||
|
REQUIRE(M.cols() == V.rows());
|
||
|
//All triangles' areas are 0.5
|
||
|
//barycentric area for a vertex is {number of adj triangles} * 0.5 / 3
|
||
|
Eigen::VectorXi adj(8);
|
||
|
adj << 6,4,4,4,4,4,6,4;
|
||
|
for(int f = 0;f<M.rows();f++)
|
||
|
{
|
||
|
REQUIRE(M.coeff(f,f) == Approx(0.5/3*adj(f)).margin(epsilon));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TEST_CASE("massmatrix: cube_full", "[igl]")
|
||
|
{
|
||
|
//The allowed error for this test
|
||
|
const double epsilon = 1e-15;
|
||
|
|
||
|
Eigen::MatrixXd V;
|
||
|
Eigen::MatrixXi F;
|
||
|
//Check the mass matrix of the cube
|
||
|
igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F);
|
||
|
|
||
|
Eigen::SparseMatrix<double> M;
|
||
|
|
||
|
//Check the regular tetrahedron of side sqrt(2)
|
||
|
igl::massmatrix(V,F,igl::MASSMATRIX_TYPE_FULL,M);
|
||
|
|
||
|
REQUIRE(M.rows() == V.rows());
|
||
|
REQUIRE(M.cols() == V.rows());
|
||
|
Eigen::VectorXi adj(8);
|
||
|
adj << 6,4,4,4,4,4,6,4;
|
||
|
//All triangles' areas are 0.5
|
||
|
//full mass matrix on diagnol is {number of adj triangles} * 0.5 / 6
|
||
|
for(int f=0;f<M.rows();++f)
|
||
|
{
|
||
|
REQUIRE(M.coeff(f,f) == Approx(0.5/6*adj(f)).margin(epsilon));
|
||
|
}
|
||
|
for (int i=0;i<F.rows();++i)
|
||
|
{
|
||
|
for (int j=0;j<3;++j)
|
||
|
{
|
||
|
REQUIRE(M.coeff(F(i,j),F(i,(j+1)%3)) == Approx(0.5/6).margin(epsilon));
|
||
|
REQUIRE(M.coeff(F(i,(j+1)%3),F(i,j)) == Approx(0.5/6).margin(epsilon));
|
||
|
}
|
||
|
}
|
||
|
}
|