diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index 5ae7a827373..0500556f074 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -70,6 +70,10 @@ The only required parameter is a given target edge length that drives the remesh towards a high-quality tetrahedral mesh with improved dihedral angles, and a more uniform mesh, with edge lengths getting closer to the input parameter value. +By default, the cells with a non-zero `Subdomain_index` are +selected for remeshing. The cells with `Subdomain_index` equal to zero +are ignored by the remeshing algorithm. + \cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp } @@ -81,6 +85,10 @@ control on the remeshing process. In this example, a triangulation with two subd (defined by the `Subdomain_index` 2) of its subdomains is remeshed. +Only the cells with a non-zero `Subdomain_index` will be remeshed. +The named parameter `cell_is_selected_map` can be used to change this +behavior. + \cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index dc67ae6fa67..87f7de8cf35 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -19,7 +19,12 @@ int main(int argc, char* argv[]) const std::size_t nbv = (argc > 2) ? atoi(argv[2]) : 1000; Remeshing_triangulation tr; - CGAL::Tetrahedral_remeshing::generate_input_one_subdomain(nbv, tr); + CGAL::Tetrahedral_remeshing::insert_random_points_in_cube(nbv, tr); + + /// A subdomain index 0 is considered outside and is not remeshed + /// so we set finite cells to a non-zero `Subdomain_index` + for (auto cell : tr.finite_cell_handles()) + cell->set_subdomain_index(1); CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length); diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h index f0a9180b655..72322706175 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h @@ -22,40 +22,9 @@ namespace CGAL namespace Tetrahedral_remeshing { template - void generate_input_two_subdomains(const std::size_t& nbv, Tr& tr) + void insert_random_points_in_cube(const std::size_t& nbv, Tr& tr) { CGAL::Random rng; - - typedef typename Tr::Point Point; - typedef typename Tr::Cell_handle Cell_handle; - - while (tr.number_of_vertices() < nbv) - tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); - - using P = typename Tr::Geom_traits::Point_3; - const typename Tr::Geom_traits::Plane_3 - plane(P(0, 0, 0), P(0, 1, 0), P(0, 0, 1)); - - for (Cell_handle c : tr.finite_cell_handles()) - { - if (plane.has_on_positive_side( - CGAL::centroid(P(c->vertex(0)->point()), - P(c->vertex(1)->point()), - P(c->vertex(2)->point()), - P(c->vertex(3)->point())))) - c->set_subdomain_index(1); - else - c->set_subdomain_index(2); - } - assert(tr.is_valid(true)); - } - - - template - void generate_input_one_subdomain(const std::size_t nbv, Tr& tr) - { - CGAL::Random rng; - typedef typename Tr::Point Point; std::vector pts; while (pts.size() < nbv) @@ -67,11 +36,23 @@ namespace Tetrahedral_remeshing pts.push_back(Point(x, y, z)); } tr.insert(pts.begin(), pts.end()); + } - for (typename Tr::Cell_handle c : tr.finite_cell_handles()) - c->set_subdomain_index(1); + template + void insert_points_on_plane(const Plane& plane, const std::size_t& nbv, Tr& tr) + { + CGAL::Random rng; + typedef typename Tr::Point Point; + std::vector pts; + while (pts.size() < nbv) + { + const double x = rng.get_double(-1., 1.); + const double y = rng.get_double(-1., 1.); + const double z = rng.get_double(-1., 1.); - assert(tr.is_valid(true)); + pts.push_back(plane.projection(Point(x, y, z))); + } + tr.insert(pts.begin(), pts.end()); } template diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index 097b7955fb5..46feca51a48 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -5,29 +5,22 @@ #include "tetrahedral_remeshing_generate_input.h" -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - -typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +using K = CGAL::Exact_predicates_inexact_constructions_kernel; +using Remeshing_triangulation = CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3; +using Subdomain_index = Remeshing_triangulation::Tds::Cell::Subdomain_index; template struct Cells_of_subdomain_pmap { -private: - using Cell_handle = typename Tr::Cell_handle; - const int m_subdomain; public: - using key_type = Cell_handle; + using key_type = typename Tr::Cell_handle; using value_type = bool; using reference = bool; using category = boost::read_write_property_map_tag; - Cells_of_subdomain_pmap(const int& subdomain) - : m_subdomain(subdomain) - {} - friend value_type get(const Cells_of_subdomain_pmap& map, const key_type& c) { @@ -41,17 +34,54 @@ public: } }; +Subdomain_index subdomain_on_side_of_plane(const K::Point_3& p, + const K::Plane_3& plane) +{ + if (plane.has_on_positive_side(p)) + return 1; + else + return 2; +} + +K::Point_3 centroid(const Remeshing_triangulation::Cell_handle c) +{ + return CGAL::centroid(c->vertex(0)->point(), + c->vertex(1)->point(), + c->vertex(2)->point(), + c->vertex(3)->point()); +} + int main(int argc, char* argv[]) { - const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1; + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.05; const std::size_t nbv = (argc > 2) ? atoi(argv[2]) : 1000; + const std::size_t nbv_on_plane = (argc > 3) ? atoi(argv[3]) : 100; + /// Create a randomly generated triangulation of a sphere Remeshing_triangulation tr; - CGAL::Tetrahedral_remeshing::generate_input_two_subdomains(nbv, tr); + CGAL::Tetrahedral_remeshing::insert_random_points_in_cube(nbv, tr); - CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length, + /// Use vertical plane to split the mesh into two subdomains + const K::Plane_3 plane(0, 0, 1, 0); + CGAL::Tetrahedral_remeshing::insert_points_on_plane(plane, nbv_on_plane, tr); + + /// A subdomain index 0 is considered outside and is not remeshed + /// so we set finite cells to a non-zero `Subdomain_index` + /// (depending on the side of the plane they are on) + for (auto cell : tr.finite_cell_handles()) + { + const K::Point_3 cc = centroid(cell); + cell->set_subdomain_index(subdomain_on_side_of_plane(cc, plane)); + } + + /// Remesh only the cells of subdomain 2 + CGAL::tetrahedral_isotropic_remeshing(tr, + target_edge_length, CGAL::parameters::cell_is_selected_map( - Cells_of_subdomain_pmap(2))); + Cells_of_subdomain_pmap{2})); + + std::ofstream os("out.mesh"); + CGAL::IO::write_MEDIT(os, tr); return EXIT_SUCCESS; }