| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- #include <test_common.h>
- #include <igl/cat.h>
- #include <igl/triangle/scaf.h>
- #include <igl/slice.h>
- #include <igl/harmonic.h>
- #include <igl/boundary_loop.h>
- #include <igl/map_vertices_to_circle.h>
- #include <igl/flip_avoiding_line_search.h>
- // Assert that building the SCAF equation system via scaf_system() and
- // solving it manually yields the same result as calling scaf_solve() directly.
- TEST_CASE("scaf_system: Test scaf_system() vs scaf_solve()", "[igl]")
- {
- // Read cube mesh
- Eigen::MatrixXd V;
- Eigen::MatrixXi F;
- igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F);
- // Cut to disk
- F = F.topRows(F.rows() - 1).eval();
- // Compute Tutte's embedding
- Eigen::MatrixXd uv_init;
- {
- Eigen::MatrixXd bnd_uv;
- std::vector<int> boundary;
- igl::boundary_loop(F, boundary);
- Eigen::VectorXi bnd = Eigen::Map<Eigen::VectorXi>(boundary.data(), boundary.size());
- igl::map_vertices_to_circle(V, bnd, bnd_uv);
- igl::harmonic(F, bnd, bnd_uv ,1, uv_init);
- uv_init.conservativeResize(V.rows(), 2);
- }
- // Init empty constraint vectors
- Eigen::VectorXi b;
- Eigen::MatrixXd bc;
- // Run one scaf iteration as reference
- igl::triangle::SCAFData s_ref;
- {
- igl::triangle::scaf_precompute(V, F, uv_init, igl::MappingEnergyType::SYMMETRIC_DIRICHLET, b, bc, 0, s_ref);
- igl::triangle::scaf_solve(1, s_ref);
- }
- // Obtain SCAF linear system perform iteration manually
- igl::triangle::SCAFData s_test;
- {
- // Set up system
- igl::triangle::scaf_precompute(V, F, uv_init, igl::MappingEnergyType::SYMMETRIC_DIRICHLET, b, bc, 0, s_test);
- Eigen::SparseMatrix<double> L;
- Eigen::VectorXd rhs;
- igl::triangle::scaf_system(s_test, L, rhs);
- // Solve
- Eigen::SimplicialLDLT<Eigen::SparseMatrix<double>> solver;
- auto x = solver.compute(L).solve(rhs);
- // Write result to uv_target
- Eigen::MatrixXd uv_target = s_test.w_uv;
- const int n_v_var = s_test.w_uv.rows() - s_test.frame_ids.size();
- for (int i = 0; i < n_v_var; ++i)
- {
- int row = i;
- if (i >= s_test.v_num)
- row += s_test.frame_ids.size();
- uv_target(row, 0) = x[i];
- uv_target(row, 1) = x[i + n_v_var];
- }
- // Line search
- std::function<double(Eigen::MatrixXd&)> E =
- [&s_test](Eigen::MatrixXd &uv) { return igl::triangle::scaf::compute_energy(s_test, uv, true); };
- Eigen::MatrixXi w_T;
- igl::cat(1, s_test.m_T, s_test.s_T, w_T);
- igl::flip_avoiding_line_search(w_T, s_test.w_uv, uv_target, E, -1);
- }
- // Compare both results
- REQUIRE(s_test.w_uv == s_ref.w_uv);
- }
|