From ca7548b341e69b0c62f23dd05009eb52b46dd699 Mon Sep 17 00:00:00 2001 From: ange-clement Date: Tue, 7 Nov 2023 15:25:50 +0100 Subject: [PATCH] Removed example + Modified example mesh_3D_image_with_custom_initialization to use new API + Changed InitialPointsGenerator concept : outputs std::tuple instead of std::tuple + custom initialization will be called even if a feature detector is set --- .../Mesh_3/Concepts/InitialPointsGenerator.h | 12 +- Mesh_3/doc/Mesh_3/Mesh_3.txt | 41 +------ Mesh_3/doc/Mesh_3/examples.txt | 1 - Mesh_3/examples/Mesh_3/CMakeLists.txt | 6 - ..._gray_image_with_custom_initialization.cpp | 115 ------------------ ...sh_3D_image_with_custom_initialization.cpp | 93 +++++++------- .../Construct_initial_points_labeled_image.h | 2 +- Mesh_3/include/CGAL/make_mesh_3.h | 21 ++-- .../internal/mesh_option_classes.h | 53 ++++---- 9 files changed, 88 insertions(+), 256 deletions(-) delete mode 100644 Mesh_3/examples/Mesh_3/mesh_3D_gray_image_with_custom_initialization.cpp diff --git a/Mesh_3/doc/Mesh_3/Concepts/InitialPointsGenerator.h b/Mesh_3/doc/Mesh_3/Concepts/InitialPointsGenerator.h index c5097a9ca07..f2ea33d691b 100644 --- a/Mesh_3/doc/Mesh_3/Concepts/InitialPointsGenerator.h +++ b/Mesh_3/doc/Mesh_3/Concepts/InitialPointsGenerator.h @@ -21,13 +21,13 @@ public: /*! Output a set of (`n`) surface points to the output iterator `pts`, as objects of type -`std::tuple`. -`Point_3` is the point's position, +`std::tuple`. +`Weighted_point_3` is the point's position and weight, `int` is the dimension of the minimal dimension subcomplex on which the point lies, and `Index` is the underlying subcomplex index. @tparam OutputIterator model of `OutputIterator`, containing points of type -`std::tuple` +`std::tuple` @tparam MeshDomain model of `MeshDomain_3` @tparam C3t3 model of `MeshComplex_3InTriangulation_3` @param n an estimation of the number of points to output @@ -39,15 +39,15 @@ OutputIterator operator()(OutputIterator pts, const MeshDomain& domain, const C3 /*! Output a set of surface points to the output iterator `pts`, as objects of type -`std::tuple`. -`Point_3` is the point's position, +`std::tuple`. +`Weighted_point_3` is the point's position and weight, `int` is the dimension of the minimal dimension subcomplex on which the point lies, and `Index` is the underlying subcomplex index. As `n` is not given, the functor must provide enough points to initialize the mesh generation process. @tparam OutputIterator model of `OutputIterator`, containing points of type -`std::tuple` +`std::tuple` @tparam MeshDomain model of `MeshDomain_3` @tparam C3t3 model of `MeshComplex_3InTriangulation_3` diff --git a/Mesh_3/doc/Mesh_3/Mesh_3.txt b/Mesh_3/doc/Mesh_3/Mesh_3.txt index 1340e9ac3c6..edf2e81d985 100644 --- a/Mesh_3/doc/Mesh_3/Mesh_3.txt +++ b/Mesh_3/doc/Mesh_3/Mesh_3.txt @@ -795,45 +795,10 @@ Mesh_3/random_labeled_image.h. The example \ref Mesh_3/mesh_3D_image_with_custom_initialization.cpp features -another way to achieve these results. It is a modification -of \ref Mesh_3/mesh_3D_image.cpp. +a custom functor that initialize the triangulation. -For the meshing, in the previous example (\ref Mesh_3/mesh_3D_image.cpp), we called `make_mesh_3()` as follows. - -\snippet Mesh_3/mesh_3D_image.cpp Meshing - -In the example \ref Mesh_3/mesh_3D_image_with_custom_initialization.cpp, -that call is replaced by: - -# the creation of an empty `%c3t3` object, - -# a call to the function - `initialize_triangulation_from_labeled_image()` that inserts points in - the triangulation, - -# then the call to `refine_mesh_3()`. - -\snippet Mesh_3/mesh_3D_image_with_custom_initialization.cpp Meshing - -The function `initialize_triangulation_from_labeled_image()` gets points from -\ref CGAL/Mesh_3/Construct_initial_points_labeled_image.h and inserts them -in the triangulation. The following lines show how to insert new -points in the `%c3t3` object, with the calls to -`MeshVertexBase_3::set_dimension()` and -`MeshVertexBase_3::set_index()`. - -\snippet Mesh_3/mesh_3D_image_with_custom_initialization.cpp insert initial points - -The value of `index` must be consistent with the possible values of -`Mesh_domain::Index`. - -The example \ref Mesh_3/mesh_3D_gray_image_with_custom_initialization.cpp is another -custom initialization example, for meshing of 3D gray-level images. Similarly to -the segmented image example above, the code consists in: - -# the creation of an empty `%c3t3` object, - -# a call to the function - `initialize_triangulation_from_gray_image()` that inserts points in - the triangulation, - -# then the call to `refine_mesh_3()`. - -\snippet Mesh_3/mesh_3D_gray_image_with_custom_initialization.cpp Meshing +A struct `Custom_Initial_points_generator` that places 1D-feature points +alongside a line is created. \subsection Mesh_3UsingVariableSizingField Using Variable Sizing Field diff --git a/Mesh_3/doc/Mesh_3/examples.txt b/Mesh_3/doc/Mesh_3/examples.txt index e4528dfa9b1..969fb7fd1bf 100644 --- a/Mesh_3/doc/Mesh_3/examples.txt +++ b/Mesh_3/doc/Mesh_3/examples.txt @@ -1,7 +1,6 @@ /*! \example Mesh_3/implicit_functions.cpp \example Mesh_3/mesh_3D_image.cpp -\example Mesh_3/mesh_3D_gray_image_with_custom_initialization.cpp \example Mesh_3/mesh_3D_image_with_features.cpp \example Mesh_3/mesh_3D_image_with_custom_initialization.cpp \example Mesh_3/mesh_3D_image_with_initial_points.cpp diff --git a/Mesh_3/examples/Mesh_3/CMakeLists.txt b/Mesh_3/examples/Mesh_3/CMakeLists.txt index 90857127a80..4899a15d588 100644 --- a/Mesh_3/examples/Mesh_3/CMakeLists.txt +++ b/Mesh_3/examples/Mesh_3/CMakeLists.txt @@ -162,11 +162,6 @@ if(TARGET CGAL::CGAL_ImageIO) target_link_libraries(mesh_3D_image_with_custom_initialization PUBLIC CGAL::Eigen3_support) - create_single_source_cgal_program( - "mesh_3D_gray_image_with_custom_initialization.cpp") - target_link_libraries(mesh_3D_gray_image_with_custom_initialization - PUBLIC CGAL::Eigen3_support) - create_single_source_cgal_program( "mesh_3D_image_with_initial_points.cpp") target_link_libraries(mesh_3D_image_with_initial_points @@ -205,7 +200,6 @@ if(CGAL_ACTIVATE_CONCURRENT_MESH_3 AND TARGET CGAL::TBB_support) mesh_3D_weighted_image mesh_3D_image_variable_size mesh_3D_image_with_custom_initialization - mesh_3D_gray_image_with_custom_initialization mesh_3D_image_with_initial_points mesh_3D_image_with_features mesh_3D_image_with_detection_of_features diff --git a/Mesh_3/examples/Mesh_3/mesh_3D_gray_image_with_custom_initialization.cpp b/Mesh_3/examples/Mesh_3/mesh_3D_gray_image_with_custom_initialization.cpp deleted file mode 100644 index b734240f4cc..00000000000 --- a/Mesh_3/examples/Mesh_3/mesh_3D_gray_image_with_custom_initialization.cpp +++ /dev/null @@ -1,115 +0,0 @@ - -#include - -#include -#include -#include - -#include - -#include -#include -#include -#include - -typedef float Image_word_type; - -// Domain -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Labeled_mesh_domain_3 Mesh_domain; - -// Parallel tag -#ifdef CGAL_CONCURRENT_MESH_3 -typedef CGAL::Parallel_tag Concurrency_tag; -#else -typedef CGAL::Sequential_tag Concurrency_tag; -#endif - -// Triangulation -typedef CGAL::Mesh_triangulation_3::type Tr; -typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; - -// Criteria -typedef CGAL::Mesh_criteria_3 Mesh_criteria; - -namespace params = CGAL::parameters; - -template -void initialize_triangulation_from_gray_image(C3T3& c3t3, - const MeshDomain& domain, - const CGAL::Image_3& image, - const FT& iso_value) -{ - typedef typename C3T3::Triangulation Tr; - typedef typename Tr::Geom_traits GT; - typedef typename Tr::Weighted_point Weighted_point; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename MeshDomain::Point_3 Point_3; - typedef typename MeshDomain::Index Index; - - typedef typename std::tuple ConstructedPoint; - - Tr& tr = c3t3.triangulation(); - - typename GT::Construct_weighted_point_3 cwp = - tr.geom_traits().construct_weighted_point_3_object(); - - std::vector constructedPoints; - - CGAL::Construct_initial_points_gray_image construct(image, iso_value); - construct(std::back_inserter(constructedPoints), domain, c3t3); - - std::cout << " " << constructedPoints.size() << " constructed points" << std::endl; - - for (const ConstructedPoint & constructedPoint : constructedPoints) - { - const Point_3& point = std::get<0>(constructedPoint); - const int& dimension = std::get<1>(constructedPoint); - const Index& index = std::get<2>(constructedPoint); - - Weighted_point pi = cwp(point); - - /// The following lines show how to insert initial points in the - /// `c3t3` object. [insert initial points] - Vertex_handle v = tr.insert(pi); - // `v` could be null if `pi` is hidden by other vertices of `tr`. - CGAL_assertion(v != Vertex_handle()); - c3t3.set_dimension(v, dimension); - c3t3.set_index(v, index); - /// [insert initial points] - } -} - -int main(int argc, char* argv[]) -{ - const std::string fname = (argc > 1) ? argv[1] : CGAL::data_file_path("images/skull_2.9.inr"); - /// [Load image] - CGAL::Image_3 image; - if (!image.read(fname)) { - std::cerr << "Error: Cannot read file " << fname << std::endl; - return EXIT_FAILURE; - } - /// [Domain creation] - Mesh_domain domain = - Mesh_domain::create_gray_image_mesh_domain(image, params::iso_value(2.9f).value_outside(0.f)); - /// [Domain creation] - - /// [Mesh criteria] - Mesh_criteria criteria(params::facet_angle(30).facet_size(6).facet_distance(2). - cell_radius_edge_ratio(3).cell_size(8)); - - /// [Meshing] - C3t3 c3t3; - initialize_triangulation_from_gray_image(c3t3, - domain, - image, - 2.9f//isolevel - ); - CGAL::refine_mesh_3(c3t3, domain, criteria); - /// [Meshing] - - /// Output - CGAL::dump_c3t3(c3t3, "out"); - - return 0; -} diff --git a/Mesh_3/examples/Mesh_3/mesh_3D_image_with_custom_initialization.cpp b/Mesh_3/examples/Mesh_3/mesh_3D_image_with_custom_initialization.cpp index feff42b26b3..ff8716e85c4 100644 --- a/Mesh_3/examples/Mesh_3/mesh_3D_image_with_custom_initialization.cpp +++ b/Mesh_3/examples/Mesh_3/mesh_3D_image_with_custom_initialization.cpp @@ -5,17 +5,19 @@ #include #include -#include - #include #include #include #include + +#include + // Domain typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Labeled_mesh_domain_3 Mesh_domain; +typedef CGAL::Labeled_mesh_domain_3 Image_domain; +typedef CGAL::Mesh_domain_with_polyline_features_3 Mesh_domain; #ifdef CGAL_CONCURRENT_MESH_3 typedef CGAL::Parallel_tag Concurrency_tag; @@ -33,70 +35,57 @@ typedef CGAL::Mesh_criteria_3 Mesh_criteria; namespace params = CGAL::parameters; -template -void initialize_triangulation_from_labeled_image(C3T3& c3t3, - const MeshDomain& domain, - const CGAL::Image_3& image) +struct Custom_Initial_points_generator { - typedef typename C3T3::Triangulation Tr; - typedef typename Tr::Geom_traits GT; - typedef typename Tr::Weighted_point Weighted_point; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename MeshDomain::Point_3 Point_3; - typedef typename MeshDomain::Index Index; + CGAL::Image_3& image_; + Custom_Initial_points_generator(CGAL::Image_3& image) : image_(image) { } - typedef typename std::tuple ConstructedPoint; - - Tr& tr = c3t3.triangulation(); - - typename GT::Construct_weighted_point_3 cwp = - tr.geom_traits().construct_weighted_point_3_object(); - - std::vector constructedPoints; - - CGAL::Construct_initial_points_labeled_image construct(image); - construct(std::back_inserter(constructedPoints), domain, c3t3); - - std::cout << " " << constructedPoints.size() << " constructed points" << std::endl; - - for (const ConstructedPoint & constructedPoint : constructedPoints) + template + OutputIterator operator()(OutputIterator pts, const MeshDomain& domain, const C3t3& c3t3, int n = 1) const { - const Point_3& point = std::get<0>(constructedPoint); - const int& dimension = std::get<1>(constructedPoint); - const Index& index = std::get<2>(constructedPoint); + typedef typename C3t3::Triangulation::Geom_traits::Point_3 Point_3; - Weighted_point pi = cwp(point); + typename C3t3::Triangulation::Geom_traits::Construct_weighted_point_3 cwp = + c3t3.triangulation().geom_traits().construct_weighted_point_3_object(); - /// The following lines show how to insert initial points in the - /// `c3t3` object. [insert initial points] - Vertex_handle v = tr.insert(pi); - // `v` could be null if `pi` is hidden by other vertices of `tr`. - CGAL_assertion(v != Vertex_handle()); - c3t3.set_dimension(v, dimension); - c3t3.set_index(v, index); - /// [insert initial points] + // Add points along the segment from + // ( 0.0 50.0 66.66) to + // (100.0 50.0 66.66) + double edge_size = 5; + std::size_t nb = static_cast(100.0 / edge_size); + for (std::size_t i = 1; i < nb; i++) + { + *pts++ = std::make_tuple( + cwp(Point_3(i*edge_size, 50.0, 66.66), edge_size*edge_size), 1, 0); + } + return pts; } -} +}; int main() { - /// [Create the image] - CGAL::Image_3 image = random_labeled_image(); - /// [Create the image] + const std::string fname = CGAL::data_file_path("images/420.inr"); + // Loads image + CGAL::Image_3 image; + if(!image.read(fname)){ + std::cerr << "Error: Cannot read file " << fname << std::endl; + return EXIT_FAILURE; + } // Domain - Mesh_domain domain = Mesh_domain::create_labeled_image_mesh_domain(image); + Mesh_domain domain = Mesh_domain::create_labeled_image_mesh_domain(image + , params::features_detector(CGAL::Mesh_3::Detect_features_on_image_bbox()) + ); // Mesh criteria - Mesh_criteria criteria(params::facet_angle(30).facet_size(3).facet_distance(1). - cell_radius_edge_ratio(3).cell_size(3)); + Mesh_criteria criteria(params::facet_angle(30).facet_size(3).facet_distance(1).edge_size(3) + .cell_radius_edge_ratio(3).cell_size(3) + ); /// [Meshing] - C3t3 c3t3; - initialize_triangulation_from_labeled_image(c3t3, - domain, - image); - CGAL::refine_mesh_3(c3t3, domain, criteria); + C3t3 c3t3 = CGAL::make_mesh_3(domain, criteria + , params::initial_points_generator(Custom_Initial_points_generator(image)) + ); /// [Meshing] // Output diff --git a/Mesh_3/include/CGAL/Mesh_3/Construct_initial_points_labeled_image.h b/Mesh_3/include/CGAL/Mesh_3/Construct_initial_points_labeled_image.h index 27ee3d09be0..f9cf60d1a8a 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Construct_initial_points_labeled_image.h +++ b/Mesh_3/include/CGAL/Mesh_3/Construct_initial_points_labeled_image.h @@ -286,7 +286,7 @@ struct Construct_initial_points_labeled_image if (pi_inside_protecting_sphere) continue; - *pts++ = std::make_tuple(intersect_point, 2, intersect_index); // dimension 2 by construction, points are on surface + *pts++ = std::make_tuple(cwp(intersect_point), 2, intersect_index); // dimension 2 by construction, points are on surface } } } diff --git a/Mesh_3/include/CGAL/make_mesh_3.h b/Mesh_3/include/CGAL/make_mesh_3.h index 6a5eec6a25a..5a8b83b88e9 100644 --- a/Mesh_3/include/CGAL/make_mesh_3.h +++ b/Mesh_3/include/CGAL/make_mesh_3.h @@ -44,10 +44,9 @@ init_c3t3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria&, const int nb_initial_points, const parameters::internal::Initial_points_generator_options& generator = parameters::internal::Initial_points_generator_generator()()) { - typedef typename MeshDomain::Point_3 Point_3; + typedef typename C3T3::Triangulation::Geom_traits::Weighted_point_3 Weighted_point_3; typedef typename MeshDomain::Index Index; - typedef std::vector > Initial_points_vector; - typedef typename Initial_points_vector::iterator Ipv_iterator; + typedef std::vector > Initial_points_vector; typedef typename C3T3::Vertex_handle Vertex_handle; // Mesh initialization : get some points and add them to the mesh @@ -58,21 +57,15 @@ init_c3t3(C3T3& c3t3, const MeshDomain& domain, const MeshCriteria&, else //use default number of points generator(std::back_inserter(initial_points), domain, c3t3); - typename C3T3::Triangulation::Geom_traits::Construct_weighted_point_3 cwp = - c3t3.triangulation().geom_traits().construct_weighted_point_3_object(); - // Insert points and set their index and dimension - for ( Ipv_iterator it = initial_points.begin() ; - it != initial_points.end() ; - ++it ) - { - Vertex_handle v = c3t3.triangulation().insert(cwp(std::get<0>(*it))); + for (const auto& [weighted_point_3, dimension, index] : initial_points) { + Vertex_handle v = c3t3.triangulation().insert(weighted_point_3); // v could be null if point is hidden if ( v != Vertex_handle() ) { - c3t3.set_dimension(v,std::get<1>(*it)); - c3t3.set_index(v,std::get<2>(*it)); + c3t3.set_dimension(v,dimension); + c3t3.set_index(v,index); } } } @@ -234,7 +227,7 @@ struct C3t3_initializer < C3T3, MD, MC, true, CGAL::Tag_true > // If c3t3 initialization is not sufficient (may happen if there is only // a planar curve as feature for example), add some surface points - bool need_more_init = c3t3.triangulation().dimension() != 3; + bool need_more_init = c3t3.triangulation().dimension() != 3 || !generator.is_default(); if(!need_more_init) { CGAL::Mesh_3::C3T3_helpers helper(c3t3, domain); helper.update_restricted_facets(); diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/mesh_option_classes.h b/STL_Extension/include/CGAL/STL_Extension/internal/mesh_option_classes.h index 5a33d9d3cd1..c80235b10ab 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/mesh_option_classes.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/mesh_option_classes.h @@ -14,6 +14,7 @@ #include #include +#include namespace CGAL { @@ -172,12 +173,15 @@ private: template struct Initial_points_generator_options { - typedef typename std::back_insert_iterator>> OutputIterator; + typedef typename C3t3::Triangulation::Geom_traits::Weighted_point_3 Weighted_point_3; + typedef typename MeshDomain::Index Index; + typedef typename std::back_insert_iterator>> OutputIterator; template - Initial_points_generator_options(const Initial_points_generator& generator) + Initial_points_generator_options(const Initial_points_generator& generator, bool is_default = false) : initial_points_generator_no_number_of_points_(generator) , initial_points_generator_(generator) + , is_default_(is_default) { } OutputIterator operator()(OutputIterator pts, const MeshDomain& domain, const C3t3& c3t3) const @@ -190,7 +194,10 @@ struct Initial_points_generator_options return initial_points_generator_(pts, domain, c3t3, n); } + bool is_default() const { return is_default_; } + private: + const bool is_default_; const std::function initial_points_generator_no_number_of_points_; const std::function initial_points_generator_; }; @@ -242,7 +249,9 @@ struct Domain_features_generator< MeshDomain, true > template struct Initial_points_generator_generator { - typedef typename std::back_insert_iterator>> OutputIterator; + typedef typename C3t3::Triangulation::Geom_traits::Weighted_point_3 Weighted_point_3; + typedef typename MeshDomain::Index Index; + typedef typename std::back_insert_iterator>> OutputIterator; typedef typename CGAL::parameters::internal::Initial_points_generator_options Initial_points_generator_options; @@ -250,28 +259,26 @@ struct Initial_points_generator_generator { OutputIterator operator()(OutputIterator pts, const MeshDomain& domain, const C3t3& c3t3) { - typedef typename MeshDomain::Point_3 Point_3; - typedef typename MeshDomain::Index Index; - typedef typename std::pair Domain_generated_point; - std::vector domain_generated_points; - domain.construct_initial_points_object()(std::back_inserter(domain_generated_points)); - for (Domain_generated_point domain_generated_point : domain_generated_points) - { - *pts++ = std::make_tuple(domain_generated_point.first, 2, domain_generated_point.second); - } + // Use boost to easily create an output iterator. + // This iterator take the domain's construct_initial_points_object output : an std::pair + // and outputs an std::tuple + // As points are on the surfaces by construction, dimension is always 2. + typename C3t3::Triangulation::Geom_traits::Construct_weighted_point_3 cwp = + c3t3.triangulation().geom_traits().construct_weighted_point_3_object(); + domain.construct_initial_points_object()( + boost::make_function_output_iterator([&](const auto& domain_generated_point) { + *pts++ = std::make_tuple(cwp(domain_generated_point.first), 2, domain_generated_point.second); + })); return pts; } OutputIterator operator()(OutputIterator pts, const MeshDomain& domain, const C3t3& c3t3, int n) { - typedef typename MeshDomain::Point_3 Point_3; - typedef typename MeshDomain::Index Index; - typedef typename std::pair Domain_generated_point; - std::vector domain_generated_points; - domain.construct_initial_points_object()(std::back_inserter(domain_generated_points), n); - for (Domain_generated_point domain_generated_point : domain_generated_points) - { - *pts++ = std::make_tuple(domain_generated_point.first, 2, domain_generated_point.second); - } + typename C3t3::Triangulation::Geom_traits::Construct_weighted_point_3 cwp = + c3t3.triangulation().geom_traits().construct_weighted_point_3_object(); + domain.construct_initial_points_object()( + boost::make_function_output_iterator([&](const auto& domain_generated_point) { + *pts++ = std::make_tuple(cwp(domain_generated_point.first), 2, domain_generated_point.second); + }), n); return pts; } }; @@ -279,7 +286,7 @@ struct Initial_points_generator_generator template Initial_points_generator_options operator()(const InitialPointsGenerator& initial_points_generator) { - return Initial_points_generator_options(initial_points_generator); + return Initial_points_generator_options(initial_points_generator, false); } Initial_points_generator_options operator()(const Null_functor&) @@ -289,7 +296,7 @@ struct Initial_points_generator_generator Initial_points_generator_options operator()() { - return Initial_points_generator_options(Initial_points_generator_domain_traductor()); + return Initial_points_generator_options(Initial_points_generator_domain_traductor(), true); } };