diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/snap_polygon_soup.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/snap_polygon_soup.cpp index 6b1fc9919bd..87ed4a5b978 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/snap_polygon_soup.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/snap_polygon_soup.cpp @@ -1,10 +1,11 @@ #define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE +#define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE #include #include #include -#include #include +#include #include #include #include @@ -14,6 +15,8 @@ #include +#include + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Cartesian Cartesian; typedef Kernel::Point_3 Point; @@ -26,7 +29,7 @@ int main(int argc, char** argv) : std::string(argv[1]); const int grid_size = argc == 2 ? 23 - : std::stoi(std::string(argv[2])); + : std::stoi(std::string(argv[2])); std::vector input_points; std::vector> input_triangles; @@ -40,15 +43,16 @@ int main(int argc, char** argv) CGAL::Real_timer t; t.start(); - PMP::snap_polygon_soup(input_points, input_triangles, CGAL::parameters::erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size)); + PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::do_snap(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size)); t.stop(); std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << " in " << t.time() << " sec." << std::endl; std::vector output_points; + std::cout << "Does self-intersect: " << PMP::does_triangle_soup_self_intersect(input_points, input_triangles) << std::endl; for(auto &p: input_points) output_points.emplace_back(CGAL::to_double(p.x()),CGAL::to_double(p.y()),CGAL::to_double(p.z())); + CGAL::IO::write_polygon_soup("rounded_soup.off", output_points, input_triangles, CGAL::parameters::stream_precision(17)); - // CGAL::IO::write_polygon_soup("rounded_soup.off", input_points, input_triangles, CGAL::parameters::stream_precision(17)); return 0; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h index a2dafa3dd36..c3edc5315f9 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -33,7 +33,6 @@ #include #include - #ifdef CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE #define CGAL_PMP_AUTOREFINE_VERBOSE(X) std::cout << X << "\n"; #endif @@ -975,6 +974,15 @@ void generate_subtriangles(std::size_t ti, } // end of autorefine_impl #endif +namespace internal{ +// Forward declaration +template +bool snap_polygon_soup(PointRange &points, + PolygonRange &triangles, + const NamedParameters& np = parameters::default_values()); +} + + /** * \ingroup PMP_corefinement_grp * @@ -986,6 +994,10 @@ void generate_subtriangles(std::size_t ti, * `soup_triangles` will be updated to contain both the input triangles and the new subdivided triangles. Degenerate triangles will be removed. * Also triangles in `soup_triangles` will be triangles without intersection first, followed by triangles coming from a subdivision induced * by an intersection. The named parameter `visitor()` can be used to track +* If the do_snap parameter is set to true, the coordinates of the vertices are rounded to fit within the precision of a double-precision floating point, +* while preserving the model free of intersections. Note that this option does not guarantee an intersection-free output; however, +* the returned boolean will be true if the output is free of self-intersections. The snap_grid_size parameter limits the drift of the snapped vertices. +* A smaller value is more likely to output an intersection free output and perform more vertex collapses, but it may increase the Hausdorff distance from the input. * * @tparam PointRange a model of the concept `RandomAccessContainer` * whose value type is the point type @@ -1021,13 +1033,32 @@ void generate_subtriangles(std::size_t ti, * \cgalParamDefault{`Autorefinement::Default_visitor`} * \cgalParamExtra{The visitor will be copied.} * \cgalParamNEnd +* \cgalParamNBegin{do_snap} +* \cgalParamDescription{Enable the rounding of the coordinates so that they fit in doubles.} +* \cgalParamType{boolean} +* \cgalParamDefault{false} +* \cgalParamNEnd +* \cgalParamNBegin{snap_grid_size} +* \cgalParamDescription{Scale the points to [-2^gs, 2^gs] where gs is the snap_grid_size before to round them on integer. Use only if do_snap is true.} +* \cgalParamType{unsigned int} +* \cgalParamDefault{23} +* \cgalParamExtra{Must be lower than 52.} +* \cgalParamNEnd +* \cgalParamNBegin{numbers_of_iteration} +* \cgalParamDescription{Maximum number of iteration performed by the snap algorithm. Use only if do_snap is true.} +* \cgalParamType{unsigned int} +* \cgalParamDefault{15} +* \cgalParamNEnd * \cgalNamedParamsEnd * +* \return `true` if the modified triangle soup is free from self-intersection, and `false` if the algorithm was not +* able to provide such a triangle soup within the number of iterations. */ template -void autorefine_triangle_soup(PointRange& soup_points, +bool autorefine_triangle_soup(PointRange& soup_points, TriangleRange& soup_triangles, const NamedParameters& np = parameters::default_values()) + { using parameters::choose_parameter; using parameters::get_parameter; @@ -1050,6 +1081,17 @@ void autorefine_triangle_soup(PointRange& soup_points, > ::type Visitor; Visitor visitor(choose_parameter(get_parameter(np, internal_np::visitor))); + //TODO just modify do_snap instead of getting np one by one + const bool do_snap = choose_parameter(get_parameter(np, internal_np::do_snap), false); + const int grid_size = choose_parameter(get_parameter(np, internal_np::snap_grid_size), 23); + const unsigned int nb_of_iteration = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 15); + const bool ead = choose_parameter(get_parameter(np, internal_np::erase_all_duplicates), false); + + if(do_snap) + { + CGAL_PMP_AUTOREFINE_VERBOSE("Snap polygon soup"); + return internal::snap_polygon_soup(soup_points, soup_triangles, parameters::point_map(pm).snap_grid_size(grid_size).number_of_iterations(nb_of_iteration).erase_all_duplicates(ead).concurrency_tag(Concurrency_tag())); + } constexpr bool parallel_execution = std::is_same_v; @@ -1077,7 +1119,7 @@ void autorefine_triangle_soup(PointRange& soup_points, for(std::size_t i=0; i #include #include #include -#include +// #include #include #include @@ -30,7 +30,6 @@ namespace CGAL namespace Polygon_mesh_processing { - namespace internal { @@ -69,7 +68,6 @@ double ceil(NT x){ return std::ceil(to_double(x)); } }; -} /** * @@ -116,17 +114,21 @@ double ceil(NT x){ * \cgalParamNBegin{numbers_of_iteration} * \cgalParamDescription{Maximum number of iteration performed by the algorithm.} * \cgalParamType{unsigned int} -* \cgalParamDefault{20} +* \cgalParamDefault{15} * \cgalParamNEnd * \cgalNamedParamsEnd * * \return `true` if the modified triangle soup is free from self-intersection, and `false` if the algorithm was not * able to provide such a triangle soup within the number of iterations. */ -template +template bool snap_polygon_soup(PointRange &points, PolygonRange &triangles, - const NamedParameters& np = parameters::default_values()) + const NamedParameters& np) +// template +// bool snap_polygon_soup(PointRange &points, + // PolygonRange &triangles, + // const NamedParameters& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -141,8 +143,8 @@ bool snap_polygon_soup(PointRange &points, Sequential_tag > ::type Concurrency_tag; - // constexpr bool parallel_execution = std::is_same_v; - constexpr bool parallel_execution = false; + constexpr bool parallel_execution = std::is_same_v; + // constexpr bool parallel_execution = false; #ifndef CGAL_LINKED_WITH_TBB static_assert (!parallel_execution, @@ -154,10 +156,11 @@ bool snap_polygon_soup(PointRange &points, // Get the grid size from the named parameter, the grid size could not be greater than 52 const unsigned int grid_size = (std::min)(52,choose_parameter(get_parameter(np, internal_np::snap_grid_size), 23)); - const unsigned int max_nb_of_iteration = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 20); + const unsigned int max_nb_of_iteration = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 15); #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Compute the scaling of the coordinates" << std::endl; + std::cout << grid_size << std::endl; #endif auto exp = [](const double v) @@ -345,7 +348,6 @@ bool snap_polygon_soup(PointRange &points, repair_polygon_soup(points, triangles, np); - //TODO do not pass all triangles #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Model size: " << points.size() << " " << triangles.size() << std::endl; std::cout << "Autorefine the soup" << std::endl; @@ -355,6 +357,6 @@ bool snap_polygon_soup(PointRange &points, return false; } -} } //end of CGAL::Polygon_mesh_processing namespace +} } } //end of CGAL::Polygon_mesh_processing::internal namespace -#endif //CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING_H +#endif //CGAL_POLYGON_MESH_PROCESSING_SNAP_POLYGON_SOUP_H diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index d64d5575d87..211a749b103 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -220,6 +220,7 @@ CGAL_add_named_parameter(scan_angle_t, scan_angle_map, scan_angle_map) CGAL_add_named_parameter(scanline_id_t, scanline_id_map, scanline_id_map) CGAL_add_named_parameter(min_points_per_cell_t, min_points_per_cell, min_points_per_cell) CGAL_add_named_parameter(scalar_t, scalar_map, scalar_map) +CGAL_add_named_parameter(do_snap_t, do_snap, do_snap) CGAL_add_named_parameter(snap_grid_size_t, snap_grid_size, snap_grid_size) // List of named parameters used in Surface_mesh_approximation package