diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/remove_degeneracies_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/remove_degeneracies_test.cpp new file mode 100644 index 00000000000..7d5e93c3f13 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/remove_degeneracies_test.cpp @@ -0,0 +1,252 @@ +#include +#include + +#include +#include + +#include + +#include +#include + +//note : when +//CGAL::get_default_random()::get_seed() = 1473902576 +//the last test (on trihole.off) does not terminate +// + +namespace PMP = CGAL::Polygon_mesh_processing; + +typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; +typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; + +template +void detect_degeneracies(const EdgeRange& edge_range, + const FaceRange& face_range, + const Mesh& mesh, + const std::size_t expected_dedges_n, + const std::size_t expected_dfaces_n) +{ + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + // API tests + std::set dedges; + PMP::degenerate_edges(mesh, std::inserter(dedges, dedges.end())); + PMP::degenerate_edges(edge_range, mesh, std::inserter(dedges, dedges.begin())); + PMP::degenerate_edges(mesh, std::inserter(dedges, dedges.end()), CGAL::parameters::all_default()); + + dedges.clear(); + PMP::degenerate_edges(edge_range, mesh, std::inserter(dedges, dedges.begin()), CGAL::parameters::all_default()); + std::cout << "\t" << dedges.size() << " degenerate edges, expected " << expected_dedges_n << std::endl; + assert(dedges.size() == expected_dedges_n); + + // API tests + std::vector dfaces; + PMP::degenerate_faces(mesh, std::back_inserter(dfaces)); + PMP::degenerate_faces(face_range, mesh, std::back_inserter(dfaces)); + PMP::degenerate_faces(mesh, std::back_inserter(dfaces), CGAL::parameters::all_default()); + + dfaces.clear(); + PMP::degenerate_faces(face_range, mesh, std::back_inserter(dfaces), CGAL::parameters::all_default()); + std::cout << "\t" << dfaces.size() << " degenerate faces, expected " << expected_dfaces_n << std::endl; + assert(dfaces.size() == expected_dfaces_n); +} + +template +void detect_degeneracies(const std::vector& edges_selection_ids, + const std::vector& faces_selection_ids, + const Mesh& mesh, + const std::size_t expected_dedges_n, + const std::size_t expected_dfaces_n) +{ + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + // Convert IDs to descriptors + std::vector all_edges(edges(mesh).begin(), edges(mesh).end()); + std::vector all_faces(faces(mesh).begin(), faces(mesh).end()); + + std::vector edge_range; + for(std::size_t edge_id : edges_selection_ids) + edge_range.push_back(all_edges[edge_id]); + + std::set face_range; + for(std::size_t face_id : faces_selection_ids) + face_range.insert(all_faces[face_id]); + + return detect_degeneracies(edge_range, face_range, mesh, expected_dedges_n, expected_dfaces_n); +} + +template +void detect_degeneracies(const Mesh& mesh, + const std::size_t expected_dedges_n, + const std::size_t expected_dfaces_n) +{ + return detect_degeneracies(edges(mesh), faces(mesh), mesh, expected_dedges_n, expected_dfaces_n); +} + +template +bool remove_dedges(const std::vector& edges_selection_ids, + Mesh& mesh) +{ + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + + // Convert IDs to descriptors + std::vector all_edges(edges(mesh).begin(), edges(mesh).end()); + + std::vector edge_range; + for(std::size_t edge_id : edges_selection_ids) + edge_range.push_back(all_edges[edge_id]); + + return CGAL::Polygon_mesh_processing::remove_degenerate_edges(edge_range, mesh, CGAL::parameters::all_default()); +} + +template +bool remove_dfaces(const std::vector& faces_selection_ids, + Mesh& mesh) +{ + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + // Convert IDs to descriptors + std::vector all_faces(faces(mesh).begin(), faces(mesh).end()); + + std::vector face_range; + for(std::size_t face_id : faces_selection_ids) + face_range.push_back(all_faces[face_id]); + + return CGAL::Polygon_mesh_processing::remove_degenerate_faces(face_range, mesh, CGAL::parameters::all_default()); +} + +template +void test(const char* filename, + const std::vector& edges_selection_ids, + const std::vector& faces_selection_ids, + const std::size_t expected_all_degen_edges_n, + const std::size_t expected_all_degen_faces_n, + const std::size_t expected_partial_degen_edges_n, + const std::size_t expected_partial_degen_faces_n, + const std::size_t expected_post_removal_degen_edges_n, + const std::size_t expected_post_removal_degen_faces_n) +{ + std::cout << " test file: " << filename << std::endl; + + std::ifstream input(filename); + Mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) + { + std::cerr << filename << " is not a valid off file.\n"; + exit(1); + } + + Mesh mesh_cpy = mesh; + + // Count + std::cout << " Count..." << std::endl; + detect_degeneracies(mesh, expected_all_degen_edges_n, expected_all_degen_faces_n); + detect_degeneracies(edges_selection_ids, faces_selection_ids, mesh, expected_partial_degen_edges_n, expected_partial_degen_faces_n); + + // Complete remove + std::cout << " Remove all..." << std::endl; + mesh = mesh_cpy; + /* bool all_removed = */ CGAL::Polygon_mesh_processing::remove_degenerate_edges(mesh, CGAL::parameters::all_default()); + //assert(all_removed); + assert(CGAL::is_valid_polygon_mesh(mesh)); + + mesh = mesh_cpy; + /* all_removed = */ CGAL::Polygon_mesh_processing::remove_degenerate_faces(mesh, CGAL::parameters::all_default()); + // assert(all_removed); + assert(CGAL::is_valid_polygon_mesh(mesh)); + + // Check that everything is gone + std::cout << " Count (Post All-Remove)..." << std::endl; + detect_degeneracies(mesh, 0, 0); + + // Partial remove + std::cout << " Partial remove..." << std::endl; + mesh = mesh_cpy; + remove_dedges(edges_selection_ids, mesh); + assert(CGAL::is_valid_polygon_mesh(mesh)); + + mesh = mesh_cpy; + remove_dfaces(faces_selection_ids, mesh); + assert(CGAL::is_valid_polygon_mesh(mesh)); + + // Count how much is left after partial removal + std::cout << " Count (Post Partial-Remove)..." << std::endl; + detect_degeneracies(mesh, expected_post_removal_degen_edges_n, expected_post_removal_degen_faces_n); + + std::cout << " Done" << std::endl; +} + +template +void test() +{ + test("data_degeneracies/degtri_2dt_1edge_split_twice.off", + std::initializer_list({0, 1, 4, 3}), // edge selection + std::initializer_list({0}), // face selection + 0, 2, // expected number of degenerate edges/faces in the complete mesh + 0, 1, // expected number of degenerate edges/faces in the selection + 0, 0); // expected number of degenerate edges/faces in the mesh after partial removal + + test("data_degeneracies/degtri_four.off", + std::initializer_list({1}), + std::initializer_list({3}), + 0, 1, 0, 0, 0, 1); + + test("data_degeneracies/degtri_four-2.off", + std::initializer_list({2}), + std::initializer_list({3}), + 0, 1, 0, 0, 0, 1); + + test("data_degeneracies/degtri_on_border.off", + std::initializer_list({2}), + std::initializer_list({0}), + 0, 1, 0, 1, 0, 0); + + test("data_degeneracies/degtri_three.off", + std::initializer_list({2}), + std::initializer_list({1}), + 0, 1, 0, 0, 0, 1); + + test("data_degeneracies/degtri_single.off", + std::initializer_list({0, 1, 2}), + std::initializer_list({0}), + 0, 1, 0, 1, 0, 0); + + test("data_degeneracies/degtri_nullface.off", + std::initializer_list({3, 6, 7}), + std::initializer_list({0, 1, 2}), + 3, 4, 1, 2, 0, 0); + + test("data_degeneracies/trihole.off", + std::initializer_list({12}), + std::initializer_list({4, 5}), + 1, 3, 1, 2, 0, 0); + + test("data_degeneracies/degtri_sliding.off", + std::initializer_list({2}), + std::initializer_list({2, 4}), + 0, 4, 0, 2, 0, 0); + + test("data_degeneracies/fused_vertices.off", + std::initializer_list({5, 10, 13, 15, 27, 45}), + std::initializer_list({1, 3, 5, 10, 19}), + 6, 7, 2, 4, 3, 3); +} + +int main() +{ + std::cout << "EPICK SM TESTS" << std::endl; + test >(); + + std::cout << "EPICK POLYHEDRON TESTS" << std::endl; + test>(); + + std::cout << "EPICK SM TESTS" << std::endl; + test >(); + + std::cout << "EPECK POLYHEDRON TESTS" << std::endl; + test >(); + + return EXIT_SUCCESS; +}