From 3787d4b0ac96943dbe5b2d0a179f7fa70390fc26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 4 Feb 2025 11:26:46 +0100 Subject: [PATCH 001/113] Add snap polygon soup to PMP --- .../Polygon_mesh_processing/CMakeLists.txt | 2 + .../snap_polygon_soup.cpp | 43 +++++++ .../snap_polygon_soup.h | 114 ++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/snap_polygon_soup.cpp create mode 100644 Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 6f010df3bab..2d6599d2c73 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -58,6 +58,7 @@ create_single_source_cgal_program("isotropic_remeshing_with_custom_sizing_exampl create_single_source_cgal_program("isotropic_remeshing_with_allow_move.cpp") create_single_source_cgal_program("triangle_mesh_autorefinement.cpp") create_single_source_cgal_program("soup_autorefinement.cpp") +create_single_source_cgal_program("snap_polygon_soup.cpp") find_package(Eigen3 3.2.0 QUIET) #(requires 3.2.0 or greater) include(CGAL_Eigen3_support) @@ -138,6 +139,7 @@ if(TARGET CGAL::TBB_support) target_link_libraries(hausdorff_distance_remeshing_example PRIVATE CGAL::TBB_support) target_link_libraries(hausdorff_bounded_error_distance_example PRIVATE CGAL::TBB_support) target_link_libraries(soup_autorefinement PRIVATE CGAL::TBB_support) + target_link_libraries(snap_polygon_soup PRIVATE CGAL::TBB_support) create_single_source_cgal_program("corefinement_parallel_union_meshes.cpp") target_link_libraries(corefinement_parallel_union_meshes PRIVATE CGAL::TBB_support) 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 new file mode 100644 index 00000000000..b91e5a54e26 --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/snap_polygon_soup.cpp @@ -0,0 +1,43 @@ +#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef Kernel::Point_3 Point; + +namespace PMP = CGAL::Polygon_mesh_processing; + +int main(int argc, char** argv) +{ + const std::string filename = argc == 1 ? CGAL::data_file_path("meshes/elephant.off") + : std::string(argv[1]); + + std::vector input_points; + std::vector> input_triangles; + if (!CGAL::IO::read_polygon_soup(filename, input_points, input_triangles)) + { + std::cerr << "Cannot read " << filename << "\n"; + return 1; + } + PMP::repair_polygon_soup(input_points, input_triangles); + PMP::triangulate_polygons(input_points, input_triangles); + + CGAL::Real_timer t; + t.start(); + PMP::snap_polygon_soup(input_points, input_triangles); + t.stop(); + std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << " in " << t.time() << " sec." << std::endl; + 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/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h new file mode 100644 index 00000000000..9d3952ba4de --- /dev/null +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h @@ -0,0 +1,114 @@ +// Copyright (c) 2025 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Léo Valque + +#ifndef CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING +#define CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING + +#include + +#include +#include + +namespace CGAL +{ + +namespace Polygon_mesh_processing +{ + +template +bool snap_polygon_soup(PointRange &points, + PolygonRange &triangles) +{ + using Point_3 = std::remove_cv_t::value_type>; + using Kernel = typename Kernel_traits::Kernel; + static constexpr int coarseness = 23; + // TODO named parameters + + auto exp = [](const double v) + { + int n; + frexp(v, &n); + return n + 1; + }; + + Bbox_3 bb = bbox_3(points.begin(), points.end()); + std::array max_abs{(std::max)(-bb.xmin(), bb.xmax()), + (std::max)(-bb.ymin(), bb.ymax()), + (std::max)(-bb.zmin(), bb.zmax())}; + std::array scale{std::pow(2, coarseness - exp(max_abs[0])), + std::pow(2, coarseness - exp(max_abs[1])), + std::pow(2, coarseness - exp(max_abs[2]))}; + + // If EPECK, use exact TODO + auto snap = [](typename Kernel::FT x, double scale) + { + return std::ceil(CGAL::to_double(x * scale) + 0.5) / scale; + }; + auto snap_p = [scale, snap](const Point_3 &p) + { + return Point_3(snap(p.x(),scale[0]), + snap(p.y(),scale[1]), + snap(p.z(),scale[2]) ); + }; + + static constexpr std::size_t nb_max_of_iteration = 20; // TODO named parameter + for (std::size_t i = 0; i <= nb_max_of_iteration; ++i) + { + std::cout << "after autorefine " << triangles.size() << std::endl; + + for (Point_3 &p : points) + p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); + repair_polygon_soup(points, triangles); + + std::vector> out; + triangle_soup_self_intersections(points, triangles, std::back_inserter(out)); + + if (out.empty()) + { + CGAL_assertion(!does_triangle_soup_self_intersect(points, triangles)); + return true; + } + + std::vector snap_points; + snap_points.reserve(out.size() * 3); + + for (auto &pair : out) + { + for (size_t pi : triangles[pair.first]) + snap_points.emplace_back(snap_p(points[pi])); + for (size_t pi : triangles[pair.second]) + snap_points.emplace_back(snap_p(points[pi])); + } + + std::sort(snap_points.begin(), snap_points.end()); + snap_points.erase(std::unique(snap_points.begin(), snap_points.end()), snap_points.end()); + + for (Point_3 &p : points) + { + Point_3 p_snap = snap_p(p); + if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) + p = p_snap; + } + + repair_polygon_soup(points, triangles); + //TODO do not pass all triangles +#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + std::cout << "Before autorefine " << triangles.size() << std::endl; +#endif + autorefine_triangle_soup(points, triangles, parameters::concurrency_tag(Parallel_tag())); + } + return false; +} +} + +} + +#endif From 14ccffcd13888596abb30cffad655a827b1b8225 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 4 Feb 2025 13:51:53 +0100 Subject: [PATCH 002/113] Doc, verbose and named parameter of snap_polygon_soup --- .../snap_polygon_soup.cpp | 7 +- .../snap_polygon_soup.h | 145 +++++++++++++++--- .../internal/parameters_interface.h | 1 + 3 files changed, 133 insertions(+), 20 deletions(-) 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 b91e5a54e26..88bc13233ce 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,4 +1,4 @@ -#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE +//#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE #include #include @@ -22,6 +22,9 @@ int main(int argc, char** argv) const std::string filename = argc == 1 ? CGAL::data_file_path("meshes/elephant.off") : std::string(argv[1]); + const int grid_size = argc == 2 ? 23 + : std::stoi(std::string(argv[2])); + std::vector input_points; std::vector> input_triangles; if (!CGAL::IO::read_polygon_soup(filename, input_points, input_triangles)) @@ -34,7 +37,7 @@ int main(int argc, char** argv) CGAL::Real_timer t; t.start(); - PMP::snap_polygon_soup(input_points, input_triangles); + 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)); t.stop(); std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << " in " << t.time() << " sec." << std::endl; CGAL::IO::write_polygon_soup("rounded_soup.off", input_points, input_triangles, CGAL::parameters::stream_precision(17)); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h index 9d3952ba4de..21e69847092 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h @@ -23,29 +23,117 @@ namespace CGAL namespace Polygon_mesh_processing { -template +/** +* +* +* Round the coordinates of the points so that they fit in doubles while keeping the model intersection free. +* The input can be any triangle soup and the output is an intersection-free triangle soup with Hausdorff distance +* between the input and the output bounded by M*2^-gs*k where M is the maximum absolute coordinate in the model, gs the snap_grid_size (see below) and k the number of iteration +* performed by the algorithm. +* +* @tparam PointRange a model of the concept `RandomAccessContainer` +* whose value type is the point type +* @tparam TriangleRange a model of the concepts `RandomAccessContainer`, `BackInsertionSequence` and `Swappable`, whose +* value type is a model of the concept `RandomAccessContainer` whose value type is convertible to `std::size_t` and that +* is constructible from an `std::initializer_list` of size 3. +* @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" +* +* @param soup_points points of the soup of polygons +* @param soup_triangles each element in the range describes a triangle using the indexed position of the points in `soup_points` +* @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below +* +* \cgalNamedParamsBegin +* \cgalParamNBegin{concurrency_tag} +* \cgalParamDescription{a tag indicating if the task should be done using one or several threads.} +* \cgalParamType{Either `CGAL::Sequential_tag`, or `CGAL::Parallel_tag`, or `CGAL::Parallel_if_available_tag`} +* \cgalParamDefault{`CGAL::Sequential_tag`} +* \cgalParamNEnd +* \cgalParamNBegin{point_map} +* \cgalParamDescription{a property map associating points to the elements of the range `soup_points`} +* \cgalParamType{a model of `ReadWritePropertyMap` whose value type is a point type} +* \cgalParamDefault{`CGAL::Identity_property_map`} +* \cgalParamNEnd +* \cgalParamNBegin{geom_traits} +* \cgalParamDescription{an instance of a geometric traits class} +* \cgalParamType{a class model of `Kernel`} +* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} +* \cgalParamExtra{The geometric traits class must be compatible with the point type.} +* \cgalParamNEnd +* \cgalParamNBegin{visitor} +* \cgalParamDescription{a visitor used to track the creation of new faces} +* \cgalParamType{a class model of `PMPAutorefinementVisitor`} +* \cgalParamDefault{`Autorefinement::Default_visitor`} +* \cgalParamExtra{The visitor will be copied.} +* \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.} +* \cgalParamType{unsigned int} +* \cgalParamDefault{23} +* \cgalParamExtra{Must be lower than 52.} +* \cgalParamNEnd +* \cgalNamedParamsEnd +* +*/ +template bool snap_polygon_soup(PointRange &points, - PolygonRange &triangles) + PolygonRange &triangles, + const NamedParameters& np = parameters::default_values()) { + using parameters::choose_parameter; + using parameters::get_parameter; + + typedef typename GetPolygonSoupGeomTraits::type GT; + typedef typename GetPointMap::const_type Point_map; + Point_map pm = choose_parameter(get_parameter(np, internal_np::point_map)); + + typedef typename internal_np::Lookup_named_param_def < + internal_np::concurrency_tag_t, + NamedParameters, + Sequential_tag + > ::type Concurrency_tag; + + // visitor + typedef typename internal_np::Lookup_named_param_def < + internal_np::visitor_t, + NamedParameters, + Autorefinement::Default_visitor//default + > ::type Visitor; + Visitor visitor(choose_parameter(get_parameter(np, internal_np::visitor))); + + + constexpr bool parallel_execution = std::is_same_v; + +#ifndef CGAL_LINKED_WITH_TBB + static_assert (!parallel_execution, + "Parallel_tag is enabled but TBB is unavailable."); +#endif + using Point_3 = std::remove_cv_t::value_type>; using Kernel = typename Kernel_traits::Kernel; - static constexpr int coarseness = 23; - // TODO named parameters + //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)); + + +#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + std::cout << "Compute the scaling of the coordinates" << std::endl; +#endif + + // auto exp = [](const double v) { int n; frexp(v, &n); - return n + 1; + return n; }; Bbox_3 bb = bbox_3(points.begin(), points.end()); std::array max_abs{(std::max)(-bb.xmin(), bb.xmax()), (std::max)(-bb.ymin(), bb.ymax()), (std::max)(-bb.zmin(), bb.zmax())}; - std::array scale{std::pow(2, coarseness - exp(max_abs[0])), - std::pow(2, coarseness - exp(max_abs[1])), - std::pow(2, coarseness - exp(max_abs[2]))}; + std::array scale{std::pow(2, grid_size - exp(max_abs[0]) - 1), + std::pow(2, grid_size - exp(max_abs[1]) - 1), + std::pow(2, grid_size - exp(max_abs[2]) - 1)}; // If EPECK, use exact TODO auto snap = [](typename Kernel::FT x, double scale) @@ -62,25 +150,39 @@ bool snap_polygon_soup(PointRange &points, static constexpr std::size_t nb_max_of_iteration = 20; // TODO named parameter for (std::size_t i = 0; i <= nb_max_of_iteration; ++i) { - std::cout << "after autorefine " << triangles.size() << std::endl; +#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + std::cout << "Start Iteration " << i << std::endl; + std::cout << "Model size: " << points.size() << " " << triangles.size() << std::endl; +#endif +#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + std::cout << "Round all coordinates on doubles" << std::endl; +#endif for (Point_3 &p : points) p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); - repair_polygon_soup(points, triangles); + repair_polygon_soup(points, triangles, np); - std::vector> out; - triangle_soup_self_intersections(points, triangles, std::back_inserter(out)); + std::vector> pairs_of_intersecting_triangles; + triangle_soup_self_intersections(points, triangles, std::back_inserter(pairs_of_intersecting_triangles)); - if (out.empty()) + if (pairs_of_intersecting_triangles.empty()) { +#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + std::cout << "End of the snapping" << std::endl; +#endif CGAL_assertion(!does_triangle_soup_self_intersect(points, triangles)); return true; } +#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + std::cout << "Snap the coordinates of the vertices of the intersecting triangles" << std::endl; +#endif + //Get all the snap version of the points of the vertices of the intersecting triangles + //Note: points will not be modified here, they will be modified in the next for loop std::vector snap_points; - snap_points.reserve(out.size() * 3); + snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); - for (auto &pair : out) + for (auto &pair : pairs_of_intersecting_triangles) { for (size_t pi : triangles[pair.first]) snap_points.emplace_back(snap_p(points[pi])); @@ -88,9 +190,15 @@ bool snap_polygon_soup(PointRange &points, snap_points.emplace_back(snap_p(points[pi])); } +#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + std::cout << "Snap the coordinates of the vertices close-by the previous ones" << std::endl; +#endif + //TODO: TBB version of this for loop + std::sort(snap_points.begin(), snap_points.end()); snap_points.erase(std::unique(snap_points.begin(), snap_points.end()), snap_points.end()); + //If the snapped version of a point correspond to one of the previous point, we snap it too for (Point_3 &p : points) { Point_3 p_snap = snap_p(p); @@ -98,12 +206,13 @@ bool snap_polygon_soup(PointRange &points, p = p_snap; } - repair_polygon_soup(points, triangles); + repair_polygon_soup(points, triangles, np); //TODO do not pass all triangles #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE - std::cout << "Before autorefine " << triangles.size() << std::endl; + std::cout << "Autorefine the soup" << std::endl; + std::cout << "Model size: " << points.size() << " " << triangles.size() << std::endl; #endif - autorefine_triangle_soup(points, triangles, parameters::concurrency_tag(Parallel_tag())); + autorefine_triangle_soup(points, triangles, np); } return false; } 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 c95d2933e89..d64d5575d87 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(snap_grid_size_t, snap_grid_size, snap_grid_size) // List of named parameters used in Surface_mesh_approximation package CGAL_add_named_parameter(verbose_level_t, verbose_level, verbose_level) From 3a64fe3fcdfa16a0265c269b940e36f45803c1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 4 Feb 2025 14:11:28 +0100 Subject: [PATCH 003/113] add number_of_iterations as a named parameter for snap_polygon_soup --- .../snap_polygon_soup.h | 38 +++++++------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h index 21e69847092..0a1071f1606 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h @@ -9,8 +9,8 @@ // // Author(s) : Léo Valque -#ifndef CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING -#define CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING +#ifndef CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING_H +#define CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING_H #include @@ -26,7 +26,7 @@ namespace Polygon_mesh_processing /** * * -* Round the coordinates of the points so that they fit in doubles while keeping the model intersection free. +* rounds the coordinates of the points so that they fit in doubles while keeping the model intersection free. * The input can be any triangle soup and the output is an intersection-free triangle soup with Hausdorff distance * between the input and the output bounded by M*2^-gs*k where M is the maximum absolute coordinate in the model, gs the snap_grid_size (see below) and k the number of iteration * performed by the algorithm. @@ -59,20 +59,21 @@ namespace Polygon_mesh_processing * \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} * \cgalParamExtra{The geometric traits class must be compatible with the point type.} * \cgalParamNEnd -* \cgalParamNBegin{visitor} -* \cgalParamDescription{a visitor used to track the creation of new faces} -* \cgalParamType{a class model of `PMPAutorefinementVisitor`} -* \cgalParamDefault{`Autorefinement::Default_visitor`} -* \cgalParamExtra{The visitor will be copied.} -* \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.} * \cgalParamType{unsigned int} * \cgalParamDefault{23} * \cgalParamExtra{Must be lower than 52.} * \cgalParamNEnd +* \cgalParamNBegin{numbers_of_iteration} +* \cgalParamDescription{Maximum number of iteration performed by the algorithm.} +* \cgalParamType{unsigned int} +* \cgalParamDefault{20} +* \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 bool snap_polygon_soup(PointRange &points, @@ -92,15 +93,6 @@ bool snap_polygon_soup(PointRange &points, Sequential_tag > ::type Concurrency_tag; - // visitor - typedef typename internal_np::Lookup_named_param_def < - internal_np::visitor_t, - NamedParameters, - Autorefinement::Default_visitor//default - > ::type Visitor; - Visitor visitor(choose_parameter(get_parameter(np, internal_np::visitor))); - - constexpr bool parallel_execution = std::is_same_v; #ifndef CGAL_LINKED_WITH_TBB @@ -113,7 +105,7 @@ 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); #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Compute the scaling of the coordinates" << std::endl; @@ -147,8 +139,7 @@ bool snap_polygon_soup(PointRange &points, snap(p.z(),scale[2]) ); }; - static constexpr std::size_t nb_max_of_iteration = 20; // TODO named parameter - for (std::size_t i = 0; i <= nb_max_of_iteration; ++i) + for (std::size_t i = 0; i <= max_nb_of_iteration; ++i) { #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Start Iteration " << i << std::endl; @@ -216,8 +207,7 @@ bool snap_polygon_soup(PointRange &points, } return false; } -} -} +} } //end of CGAL::Polygon_mesh_processing namespace -#endif +#endif //CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING_H From 3811271150d5839d05f0b16e1b3b51051227d4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 4 Feb 2025 15:17:20 +0100 Subject: [PATCH 004/113] add more verbose in snap_polygon_soup --- .../include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h index 0a1071f1606..002d8cc3f3e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h @@ -165,6 +165,10 @@ bool snap_polygon_soup(PointRange &points, return true; } +#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + std::cout << "Number of pairs of intersecting triangles: " << pairs_of_intersecting_triangles.size() << std::endl; +#endif + #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Snap the coordinates of the vertices of the intersecting triangles" << std::endl; #endif From 3dc12cd8fbf7998aa6ded0f50c8c50e03c945643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 4 Feb 2025 16:15:08 +0100 Subject: [PATCH 005/113] New alternative version of snap_polygon_soup for testing --- .../snap_polygon_soup.cpp | 2 +- .../snap_polygon_soup.h | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) 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 88bc13233ce..6492422d922 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,4 +1,4 @@ -//#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE +#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE #include #include diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h index 002d8cc3f3e..7b82b8f9dc7 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h @@ -174,6 +174,8 @@ bool snap_polygon_soup(PointRange &points, #endif //Get all the snap version of the points of the vertices of the intersecting triangles //Note: points will not be modified here, they will be modified in the next for loop + +#if 1 std::vector snap_points; snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); @@ -200,6 +202,56 @@ bool snap_polygon_soup(PointRange &points, if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) p = p_snap; } +#else + std::map snap_points; + std::size_t index=0; + for (auto &pair : pairs_of_intersecting_triangles) + { + for (size_t pi : triangles[pair.first]) + { + auto res=snap_points.emplace(snap_p(points[pi]), index); + if(res.second) + ++index; + } + for (size_t pi : triangles[pair.second]) + { + auto res=snap_points.emplace(snap_p(points[pi]), index); + if(res.second) + ++index; + } + } + + //TODO: TBB version of this for loop + + std::vector> identical_points(index); + //If the snapped version of a point correspond to one of the previous point, we snap it too + for (size_t i=0; i!=points.size(); ++i) + { + Point_3 p_snap = snap_p(points[i]); + auto it=snap_points.find(p_snap); + if (it!=snap_points.end()){ + identical_points[it->second].push_back(i); + } + } + + for(const auto &v: identical_points){ + if(v.size()>1){ + std::array a{0,0,0}; + for(auto i: v){ + a[0]+=points[i].x(); + a[1]+=points[i].y(); + a[2]+=points[i].z(); + } + a[0]/=v.size(); + a[1]/=v.size(); + a[2]/=v.size(); + for(auto i: v){ + points[i]=Point_3(a[0],a[1],a[2]); + } + } + } +#endif + repair_polygon_soup(points, triangles, np); //TODO do not pass all triangles From 4d4763fa8b0feb466e0997de9fcf2baf800aaf16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Fri, 7 Feb 2025 10:15:49 +0100 Subject: [PATCH 006/113] Fig a bug when the scaling have a negative exponent --- .../Polygon_mesh_processing/snap_polygon_soup.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h index 7b82b8f9dc7..7c1bfb096bb 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h @@ -119,13 +119,21 @@ bool snap_polygon_soup(PointRange &points, return n; }; + auto pow_2 = [](const int k){ + return (k>=0)?std::pow(2,k):1/std::pow(2,-k); + }; + Bbox_3 bb = bbox_3(points.begin(), points.end()); std::array max_abs{(std::max)(-bb.xmin(), bb.xmax()), (std::max)(-bb.ymin(), bb.ymax()), (std::max)(-bb.zmin(), bb.zmax())}; - std::array scale{std::pow(2, grid_size - exp(max_abs[0]) - 1), - std::pow(2, grid_size - exp(max_abs[1]) - 1), - std::pow(2, grid_size - exp(max_abs[2]) - 1)}; + std::array scale{pow_2(grid_size - exp(max_abs[0]) - 1), + pow_2(grid_size - exp(max_abs[1]) - 1), + pow_2(grid_size - exp(max_abs[2]) - 1)}; + +#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + std::cout << "Scaling: " << scale[0] << " " << scale[1] << " " << scale[2] << std::endl; +#endif // If EPECK, use exact TODO auto snap = [](typename Kernel::FT x, double scale) @@ -256,8 +264,8 @@ 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 << "Autorefine the soup" << std::endl; std::cout << "Model size: " << points.size() << " " << triangles.size() << std::endl; + std::cout << "Autorefine the soup" << std::endl; #endif autorefine_triangle_soup(points, triangles, np); } From aef30f0e9d1d5f089853f008d231cc22b7bdfcfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 11 Feb 2025 17:01:10 +0100 Subject: [PATCH 007/113] Write a generic ceil function to use snap_polygon_soup with various number type; tested with EPECK et EPICK --- .../snap_polygon_soup.cpp | 10 +++- .../snap_polygon_soup.h | 52 ++++++++++++++++--- 2 files changed, 55 insertions(+), 7 deletions(-) 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 6492422d922..6b1fc9919bd 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,5 +1,7 @@ #define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE +#include +#include #include #include #include @@ -13,6 +15,7 @@ #include typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef CGAL::Cartesian Cartesian; typedef Kernel::Point_3 Point; namespace PMP = CGAL::Polygon_mesh_processing; @@ -40,7 +43,12 @@ int main(int argc, char** argv) 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)); t.stop(); std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << " in " << t.time() << " sec." << std::endl; - CGAL::IO::write_polygon_soup("rounded_soup.off", input_points, input_triangles, CGAL::parameters::stream_precision(17)); + + std::vector output_points; + 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/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h index 7c1bfb096bb..f05eae3352c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h @@ -12,17 +12,58 @@ #ifndef CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING_H #define CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING_H +#include +#include +#include #include #include #include +#include +#include +#include + namespace CGAL { namespace Polygon_mesh_processing { + +namespace internal +{ + +template double ceil(Lazy_exact_nt< NT > x); +template double ceil(NT x); + +template +double ceil(Lazy_exact_nt< NT > x){ + double ceil_left=std::ceil(to_interval(x).first); + if(ceil_left==std::ceil(to_interval(x).second)) + return ceil_left; + x.exact(); + ceil_left=std::ceil(to_interval(x).first); + if(ceil_left==std::ceil(to_interval(x).second)) + return ceil_left; + return ceil( x.exact()); +}; + +template +double ceil(NT x){ + typedef Fraction_traits FT; + if constexpr(std::is_same::value){ + typename FT::Numerator_type num, r, e; + typename FT::Denominator_type denom; + typename FT::Decompose()(x,num,denom); + div_mod(num, denom, r, e); + return to_double(r); + } else { + return std::ceil(to_double(x)); + } +}; +} + /** * * @@ -135,10 +176,9 @@ bool snap_polygon_soup(PointRange &points, std::cout << "Scaling: " << scale[0] << " " << scale[1] << " " << scale[2] << std::endl; #endif - // If EPECK, use exact TODO auto snap = [](typename Kernel::FT x, double scale) { - return std::ceil(CGAL::to_double(x * scale) + 0.5) / scale; + return internal::ceil((x * scale) + 0.5) / scale; }; auto snap_p = [scale, snap](const Point_3 &p) { @@ -183,7 +223,7 @@ bool snap_polygon_soup(PointRange &points, //Get all the snap version of the points of the vertices of the intersecting triangles //Note: points will not be modified here, they will be modified in the next for loop -#if 1 +#if 0 std::vector snap_points; snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); @@ -246,9 +286,9 @@ bool snap_polygon_soup(PointRange &points, if(v.size()>1){ std::array a{0,0,0}; for(auto i: v){ - a[0]+=points[i].x(); - a[1]+=points[i].y(); - a[2]+=points[i].z(); + a[0]+=to_double(points[i].x()); + a[1]+=to_double(points[i].y()); + a[2]+=to_double(points[i].z()); } a[0]/=v.size(); a[1]/=v.size(); From 64c4fd25a9cf5080e64ae6d198b896b8dd177055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 12 Feb 2025 10:51:31 +0100 Subject: [PATCH 008/113] ceil for negative rational and comments --- .../snap_polygon_soup.h | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h index f05eae3352c..ef63e6c4a97 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h @@ -35,30 +35,37 @@ namespace internal { template double ceil(Lazy_exact_nt< NT > x); -template double ceil(NT x); +template double ceil(NT x); template double ceil(Lazy_exact_nt< NT > x){ + // If both sides are in the same ceil, return this ceil double ceil_left=std::ceil(to_interval(x).first); if(ceil_left==std::ceil(to_interval(x).second)) return ceil_left; + // If not refine interval by contracting the DAG and try again x.exact(); ceil_left=std::ceil(to_interval(x).first); if(ceil_left==std::ceil(to_interval(x).second)) return ceil_left; + // If not return the ceil of the exact value return ceil( x.exact()); }; -template +template double ceil(NT x){ typedef Fraction_traits FT; if constexpr(std::is_same::value){ + // If NT is a fraction, the ceil value is the result of the euclidian division of the numerator and the denominator. typename FT::Numerator_type num, r, e; typename FT::Denominator_type denom; typename FT::Decompose()(x,num,denom); div_mod(num, denom, r, e); + if((r<0) && e!=0) //If the result is negative, the ceil value is one below + return to_double(r-1); return to_double(r); } else { + // Return the ceil of the approximation return std::ceil(to_double(x)); } }; @@ -67,7 +74,7 @@ double ceil(NT x){ /** * * -* rounds the coordinates of the points so that they fit in doubles while keeping the model intersection free. +* Rounds the coordinates of the points so that they fit in doubles while making and keeping the model intersection free by potentially subdividing the triangles. * The input can be any triangle soup and the output is an intersection-free triangle soup with Hausdorff distance * between the input and the output bounded by M*2^-gs*k where M is the maximum absolute coordinate in the model, gs the snap_grid_size (see below) and k the number of iteration * performed by the algorithm. @@ -144,7 +151,7 @@ bool snap_polygon_soup(PointRange &points, using Point_3 = std::remove_cv_t::value_type>; using Kernel = typename Kernel_traits::Kernel; - //Get the grid size from the named parameter, the grid size could not be greater than 52 + // 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); @@ -152,22 +159,23 @@ bool snap_polygon_soup(PointRange &points, std::cout << "Compute the scaling of the coordinates" << std::endl; #endif - // auto exp = [](const double v) { int n; frexp(v, &n); return n; }; - - auto pow_2 = [](const int k){ - return (k>=0)?std::pow(2,k):1/std::pow(2,-k); + auto pow_2 = [](const int k) + { + return (k>=0)?std::pow(2,k):1./std::pow(2,-k); }; + // Get max absolute value of each dimension Bbox_3 bb = bbox_3(points.begin(), points.end()); std::array max_abs{(std::max)(-bb.xmin(), bb.xmax()), (std::max)(-bb.ymin(), bb.ymax()), (std::max)(-bb.zmin(), bb.zmax())}; + // Compute scale so that the exponent of max absolute value are 52-1. std::array scale{pow_2(grid_size - exp(max_abs[0]) - 1), pow_2(grid_size - exp(max_abs[1]) - 1), pow_2(grid_size - exp(max_abs[2]) - 1)}; @@ -178,11 +186,12 @@ bool snap_polygon_soup(PointRange &points, auto snap = [](typename Kernel::FT x, double scale) { + // Scale the coordinate, round to nearest integer and scale back return internal::ceil((x * scale) + 0.5) / scale; }; auto snap_p = [scale, snap](const Point_3 &p) { - return Point_3(snap(p.x(),scale[0]), + return Point_3( snap(p.x(),scale[0]), snap(p.y(),scale[1]), snap(p.z(),scale[2]) ); }; @@ -201,6 +210,7 @@ bool snap_polygon_soup(PointRange &points, p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); repair_polygon_soup(points, triangles, np); + // Get all intersecting triangles std::vector> pairs_of_intersecting_triangles; triangle_soup_self_intersections(points, triangles, std::back_inserter(pairs_of_intersecting_triangles)); @@ -220,10 +230,13 @@ bool snap_polygon_soup(PointRange &points, #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Snap the coordinates of the vertices of the intersecting triangles" << std::endl; #endif - //Get all the snap version of the points of the vertices of the intersecting triangles - //Note: points will not be modified here, they will be modified in the next for loop #if 0 + // Version where points are rounded to the center of their voxel. + + // Get all the snap version of the points of the vertices of the intersecting triangles + // Note: points will not be modified here, they will be modified in the next for loop + std::vector snap_points; snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); @@ -243,7 +256,7 @@ bool snap_polygon_soup(PointRange &points, std::sort(snap_points.begin(), snap_points.end()); snap_points.erase(std::unique(snap_points.begin(), snap_points.end()), snap_points.end()); - //If the snapped version of a point correspond to one of the previous point, we snap it too + // If the snapped version of a point correspond to one of the previous point, we snap it for (Point_3 &p : points) { Point_3 p_snap = snap_p(p); @@ -251,6 +264,9 @@ bool snap_polygon_soup(PointRange &points, p = p_snap; } #else + // Version where points in a voxel are rounded to their barycenter. + + // Group the points of the vertices of the intersecting triangles by their voxel std::map snap_points; std::size_t index=0; for (auto &pair : pairs_of_intersecting_triangles) @@ -269,10 +285,7 @@ bool snap_polygon_soup(PointRange &points, } } - //TODO: TBB version of this for loop - std::vector> identical_points(index); - //If the snapped version of a point correspond to one of the previous point, we snap it too for (size_t i=0; i!=points.size(); ++i) { Point_3 p_snap = snap_p(points[i]); @@ -282,6 +295,7 @@ bool snap_polygon_soup(PointRange &points, } } + // Replace all points in a voxel by their barycenter for(const auto &v: identical_points){ if(v.size()>1){ std::array a{0,0,0}; From 8079f69f8b684a7ddc4767f1fd16d77f7d7d385f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 12 Feb 2025 13:16:43 +0100 Subject: [PATCH 009/113] Add some parallellisation --- .../snap_polygon_soup.h | 45 +++++++++++++++---- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h index ef63e6c4a97..b35908cbc3b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/snap_polygon_soup.h @@ -54,7 +54,7 @@ double ceil(Lazy_exact_nt< NT > x){ template double ceil(NT x){ - typedef Fraction_traits FT; + using FT = Fraction_traits; if constexpr(std::is_same::value){ // If NT is a fraction, the ceil value is the result of the euclidian division of the numerator and the denominator. typename FT::Numerator_type num, r, e; @@ -131,8 +131,8 @@ bool snap_polygon_soup(PointRange &points, using parameters::choose_parameter; using parameters::get_parameter; - typedef typename GetPolygonSoupGeomTraits::type GT; - typedef typename GetPointMap::const_type Point_map; + using GT=typename GetPolygonSoupGeomTraits::type; + using Point_map=typename GetPointMap::const_type; Point_map pm = choose_parameter(get_parameter(np, internal_np::point_map)); typedef typename internal_np::Lookup_named_param_def < @@ -141,7 +141,8 @@ bool snap_polygon_soup(PointRange &points, Sequential_tag > ::type Concurrency_tag; - constexpr bool parallel_execution = std::is_same_v; + // constexpr bool parallel_execution = std::is_same_v; + constexpr bool parallel_execution = false; #ifndef CGAL_LINKED_WITH_TBB static_assert (!parallel_execution, @@ -206,20 +207,32 @@ bool snap_polygon_soup(PointRange &points, #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Round all coordinates on doubles" << std::endl; #endif + +#ifdef CGAL_LINKED_WITH_TBB + if(parallel_execution) + { + tbb::parallel_for(tbb::blocked_range(0, points.size()), + [&](const tbb::blocked_range& r){ + for(size_t pi = r.begin(); pi != r.end(); ++pi) + points[pi] = Point_3(to_double(points[pi].x()), to_double(points[pi].y()), to_double(points[pi].z())); + } + ); + } else +#endif for (Point_3 &p : points) p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); repair_polygon_soup(points, triangles, np); // Get all intersecting triangles std::vector> pairs_of_intersecting_triangles; - triangle_soup_self_intersections(points, triangles, std::back_inserter(pairs_of_intersecting_triangles)); + triangle_soup_self_intersections(points, triangles, std::back_inserter(pairs_of_intersecting_triangles), np); if (pairs_of_intersecting_triangles.empty()) { #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "End of the snapping" << std::endl; #endif - CGAL_assertion(!does_triangle_soup_self_intersect(points, triangles)); + CGAL_assertion(!does_triangle_soup_self_intersect(points, triangles, np)); return true; } @@ -231,12 +244,14 @@ bool snap_polygon_soup(PointRange &points, std::cout << "Snap the coordinates of the vertices of the intersecting triangles" << std::endl; #endif -#if 0 +#if 1 // Version where points are rounded to the center of their voxel. // Get all the snap version of the points of the vertices of the intersecting triangles // Note: points will not be modified here, they will be modified in the next for loop + //TODO: TBB version of this for loop + std::vector snap_points; snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); @@ -251,18 +266,32 @@ bool snap_polygon_soup(PointRange &points, #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Snap the coordinates of the vertices close-by the previous ones" << std::endl; #endif - //TODO: TBB version of this for loop std::sort(snap_points.begin(), snap_points.end()); snap_points.erase(std::unique(snap_points.begin(), snap_points.end()), snap_points.end()); // If the snapped version of a point correspond to one of the previous point, we snap it +#ifdef CGAL_LINKED_WITH_TBB + if(parallel_execution) + { + tbb::parallel_for(tbb::blocked_range(0, points.size()), + [&](const tbb::blocked_range& r){ + for(size_t pi = r.begin(); pi != r.end(); ++pi){ + Point_3 p_snap=snap_p(points[pi]); + if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) + points[pi] = p_snap; + } + } + ); + } else +#endif for (Point_3 &p : points) { Point_3 p_snap = snap_p(p); if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) p = p_snap; } + #else // Version where points in a voxel are rounded to their barycenter. From d4e66753ad97d9988c1759293d89686707e677f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 17 Feb 2025 14:17:45 +0100 Subject: [PATCH 010/113] made snap polygon soup an option of autorefine_triangle_soup --- .../snap_polygon_soup.cpp | 12 +++-- .../Polygon_mesh_processing/autorefinement.h | 49 +++++++++++++++++-- .../{ => internal}/snap_polygon_soup.h | 32 ++++++------ .../internal/parameters_interface.h | 1 + 4 files changed, 72 insertions(+), 22 deletions(-) rename Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/{ => internal}/snap_polygon_soup.h (93%) 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 From ac7bf3c45f3a8e52871bfd86a4893e6d361fc7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 17 Feb 2025 15:44:10 +0100 Subject: [PATCH 011/113] Doc modification of autorefine and Polygon mesh processing --- Documentation/doc/biblio/geom.bib | 13 +++++++++++++ .../Polygon_mesh_processing.txt | 10 +++++++--- .../Polygon_mesh_processing/snap_polygon_soup.cpp | 2 -- .../CGAL/Polygon_mesh_processing/autorefinement.h | 4 +++- 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Documentation/doc/biblio/geom.bib b/Documentation/doc/biblio/geom.bib index 270267703f8..b71da6e6bdf 100644 --- a/Documentation/doc/biblio/geom.bib +++ b/Documentation/doc/biblio/geom.bib @@ -152085,3 +152085,16 @@ keywords = {polygonal surface mesh, Surface reconstruction, kinetic framework, s year={2014}, publisher={Elsevier} } + +@unpublished{lazard:hal-04907149, + TITLE = {{Removing self-intersections in 3D meshes while preserving floating-point coordinates}}, + AUTHOR = {Lazard, Sylvain and Valque, Leo}, + URL = {https://inria.hal.science/hal-04907149}, + NOTE = {working paper or preprint}, + YEAR = {2025}, + MONTH = Jan, + KEYWORDS = {Snap rounding ; mesh intersection ; robustness}, + PDF = {https://inria.hal.science/hal-04907149v1/file/Snap-HAL.pdf}, + HAL_ID = {hal-04907149}, + HAL_VERSION = {v1}, +} diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index 08d8d798f41..1240d8107fa 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -4,7 +4,7 @@ namespace CGAL { \anchor Chapter_PolygonMeshProcessing \cgalAutoToc -\authors David Coeurjolly, Jaques-Olivier Lachaud, Konstantinos Katrioplas, Sébastien Loriot, Ivan Pađen, Mael Rouxel-Labbé, Hossam Saeed, Jane Tournois, and Ilker %O. Yaz +\authors David Coeurjolly, Jaques-Olivier Lachaud, Sylvain Lazard, Konstantinos Katrioplas, Sébastien Loriot, Ivan Pađen, Mael Rouxel-Labbé, Hossam Saeed, Jane Tournois, Léo Valque and Ilker %O. Yaz \image html neptun_head.jpg \image latex neptun_head.jpg @@ -889,8 +889,10 @@ would then also includes overlaps of duplicated points. The function `CGAL::Polygon_mesh_processing::autorefine_triangle_soup()` provides a way to refine a triangle soup using the intersections of the triangles from the soup. In particular, if some points are duplicated they will be merged. Note that if a kernel with exact predicates but inexact constructions is used, some new self-intersections -might be introduced due to rounding issues of points coordinates. -To guarantee that the triangle soup is free from self-intersections, a kernel with exact constructions must be used. +might be introduced due to rounding issues of points coordinates. The `do_snap` option can be used to resolve this issue. +When set to `true`, it ensures the coordinates are rounded to fit in `double` with potential additional subdivisions, +preventing any self-intersections from occurring. + \subsection PMPRemoveCapsNeedles Removal of Almost Degenerate Triangle Faces Triangle faces of a mesh made up of almost collinear points are badly shaped elements that @@ -1439,5 +1441,7 @@ used as a reference during the project. The curvature-based sizing field version of isotropic remeshing was added by Ivan Pađen during GSoC 2023, under the supervision of Sébastien Loriot and Jane Tournois. +The `do_snap` option for autorefinement were implemented during 2025. This was implemented by Léo Valque and Sylvain Lazard. The implementation is based on \cgalCite{lazard:hal-04907149}. + */ } /* namespace CGAL */ 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 87ed4a5b978..e577ee4f79e 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 @@ -15,8 +15,6 @@ #include -#include - typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Cartesian Cartesian; typedef Kernel::Point_3 Point; 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 c3edc5315f9..e13fe7aafca 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1090,7 +1090,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, 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())); + return internal::snap_polygon_soup(soup_points, soup_triangles, parameters::point_map(pm).visitor(visitor).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; @@ -1760,4 +1760,6 @@ autorefine( TriangleMesh& tm, #endif #endif +#include + #endif // CGAL_POLYGON_MESH_PROCESSING_AUTOREFINEMENT_H From 9b84d4c73cfad5ab31e47943267f9179f3ed8e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 17 Feb 2025 18:09:04 +0100 Subject: [PATCH 012/113] rename do_snap to apply_iterative_snap_rounding, remove trailing whitespace --- .../Polygon_mesh_processing.txt | 4 ++-- .../Polygon_mesh_processing/snap_polygon_soup.cpp | 8 ++++---- .../CGAL/Polygon_mesh_processing/autorefinement.h | 12 ++++++------ .../internal/snap_polygon_soup.h | 6 +++--- .../STL_Extension/internal/parameters_interface.h | 2 +- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index 1240d8107fa..43915c02013 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -889,7 +889,7 @@ would then also includes overlaps of duplicated points. The function `CGAL::Polygon_mesh_processing::autorefine_triangle_soup()` provides a way to refine a triangle soup using the intersections of the triangles from the soup. In particular, if some points are duplicated they will be merged. Note that if a kernel with exact predicates but inexact constructions is used, some new self-intersections -might be introduced due to rounding issues of points coordinates. The `do_snap` option can be used to resolve this issue. +might be introduced due to rounding issues of points coordinates. The `apply_iterative_snap_rounding` option can be used to resolve this issue. When set to `true`, it ensures the coordinates are rounded to fit in `double` with potential additional subdivisions, preventing any self-intersections from occurring. @@ -1441,7 +1441,7 @@ used as a reference during the project. The curvature-based sizing field version of isotropic remeshing was added by Ivan Pađen during GSoC 2023, under the supervision of Sébastien Loriot and Jane Tournois. -The `do_snap` option for autorefinement were implemented during 2025. This was implemented by Léo Valque and Sylvain Lazard. The implementation is based on \cgalCite{lazard:hal-04907149}. +The `apply_iterative_snap_rounding` option for autorefinement were implemented during 2025. This was implemented by Léo Valque and Sylvain Lazard. The implementation is based on \cgalCite{lazard:hal-04907149}. */ } /* namespace CGAL */ 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 e577ee4f79e..8a3cde8036b 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,5 +1,5 @@ -#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE -#define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE +#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE +// #define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE #include #include @@ -41,10 +41,10 @@ int main(int argc, char** argv) CGAL::Real_timer t; t.start(); - 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)); + PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(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) 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 e13fe7aafca..e770806feea 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -994,7 +994,7 @@ bool snap_polygon_soup(PointRange &points, * `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, +* If the `apply_iterative_snap_rounding` 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. @@ -1033,19 +1033,19 @@ bool snap_polygon_soup(PointRange &points, * \cgalParamDefault{`Autorefinement::Default_visitor`} * \cgalParamExtra{The visitor will be copied.} * \cgalParamNEnd -* \cgalParamNBegin{do_snap} +* \cgalParamNBegin{apply_iterative_snap_rounding} * \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.} +* \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 `apply_iterative_snap_rounding` 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.} +* \cgalParamDescription{Maximum number of iteration performed by the snap algorithm. Use only if `apply_iterative_snap_rounding` is true.} * \cgalParamType{unsigned int} * \cgalParamDefault{15} * \cgalParamNEnd @@ -1081,8 +1081,8 @@ bool 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); + //TODO just modify apply_iterative_snap_rounding instead of getting np one by one + const bool do_snap = choose_parameter(get_parameter(np, internal_np::apply_iterative_snap_rounding), 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); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/snap_polygon_soup.h index a744ff86ae4..6080a367a1e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/snap_polygon_soup.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/snap_polygon_soup.h @@ -70,9 +70,9 @@ double ceil(NT x){ }; /** -* * -* Rounds the coordinates of the points so that they fit in doubles while making and keeping the model intersection free by potentially subdividing the triangles. +* +* Rounds the coordinates of the points so that they fit in doubles while making and keeping the model intersection free by potentially subdividing the triangles. * The input can be any triangle soup and the output is an intersection-free triangle soup with Hausdorff distance * between the input and the output bounded by M*2^-gs*k where M is the maximum absolute coordinate in the model, gs the snap_grid_size (see below) and k the number of iteration * performed by the algorithm. @@ -118,7 +118,7 @@ double ceil(NT x){ * \cgalParamNEnd * \cgalNamedParamsEnd * -* \return `true` if the modified triangle soup is free from self-intersection, and `false` if the algorithm was not +* \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 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 211a749b103..de0b8774b99 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -220,7 +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(apply_iterative_snap_rounding_t, apply_iterative_snap_rounding, apply_iterative_snap_rounding) CGAL_add_named_parameter(snap_grid_size_t, snap_grid_size, snap_grid_size) // List of named parameters used in Surface_mesh_approximation package From 139e047595ae318c54fd60cceb0df2eee663edec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 17 Feb 2025 18:14:42 +0100 Subject: [PATCH 013/113] remove trailing whitespace --- .../examples/Polygon_mesh_processing/snap_polygon_soup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8a3cde8036b..53f2a05443d 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 @@ -44,7 +44,7 @@ int main(int argc, char** argv) PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(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) From 09239da1790badaa27eb9ebe39dee9f3ed834052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 19 Feb 2025 11:36:20 +0100 Subject: [PATCH 014/113] rename snap_polygon_soup to triangle_soup_snap_rounding and fix bug in snap_polygon_soup.cpp --- .../snap_polygon_soup.cpp | 2 +- .../Polygon_mesh_processing/autorefinement.h | 12 +++++------ ...n_soup.h => triangle_soup_snap_rounding.h} | 21 ++++++------------- 3 files changed, 13 insertions(+), 22 deletions(-) rename Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/{snap_polygon_soup.h => triangle_soup_snap_rounding.h} (93%) 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 53f2a05443d..d0265ee9fab 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 @@ -26,7 +26,7 @@ int main(int argc, char** argv) const std::string filename = argc == 1 ? CGAL::data_file_path("meshes/elephant.off") : std::string(argv[1]); - const int grid_size = argc == 2 ? 23 + const int grid_size = argc <= 2 ? 23 : std::stoi(std::string(argv[2])); std::vector input_points; 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 e770806feea..c9aa67b93d7 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -977,9 +977,9 @@ void generate_subtriangles(std::size_t ti, namespace internal{ // Forward declaration template -bool snap_polygon_soup(PointRange &points, - PolygonRange &triangles, - const NamedParameters& np = parameters::default_values()); +bool polygon_soup_snap_rounding(PointRange &points, + PolygonRange &triangles, + const NamedParameters& np = parameters::default_values()); } @@ -1044,7 +1044,7 @@ bool snap_polygon_soup(PointRange &points, * \cgalParamDefault{23} * \cgalParamExtra{Must be lower than 52.} * \cgalParamNEnd -* \cgalParamNBegin{numbers_of_iteration} +* \cgalParamNBegin{number_of_iterations} * \cgalParamDescription{Maximum number of iteration performed by the snap algorithm. Use only if `apply_iterative_snap_rounding` is true.} * \cgalParamType{unsigned int} * \cgalParamDefault{15} @@ -1090,7 +1090,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, if(do_snap) { CGAL_PMP_AUTOREFINE_VERBOSE("Snap polygon soup"); - return internal::snap_polygon_soup(soup_points, soup_triangles, parameters::point_map(pm).visitor(visitor).snap_grid_size(grid_size).number_of_iterations(nb_of_iteration).erase_all_duplicates(ead).concurrency_tag(Concurrency_tag())); + return internal::polygon_soup_snap_rounding(soup_points, soup_triangles, parameters::point_map(pm).visitor(visitor).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; @@ -1760,6 +1760,6 @@ autorefine( TriangleMesh& tm, #endif #endif -#include +#include #endif // CGAL_POLYGON_MESH_PROCESSING_AUTOREFINEMENT_H diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/snap_polygon_soup.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h similarity index 93% rename from Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/snap_polygon_soup.h rename to Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 6080a367a1e..62a67de0501 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/snap_polygon_soup.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -9,8 +9,8 @@ // // Author(s) : Léo Valque, Sylvain Lazard -#ifndef CGAL_POLYGON_MESH_PROCESSING_SNAP_POLYGON_SOUP_H -#define CGAL_POLYGON_MESH_PROCESSING_SNAP_POLYGON_SOUP_H +#ifndef CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H +#define CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H #include #include @@ -70,7 +70,7 @@ double ceil(NT x){ }; /** -* +* DEPRECATED SINCE INTERNAL * * Rounds the coordinates of the points so that they fit in doubles while making and keeping the model intersection free by potentially subdividing the triangles. * The input can be any triangle soup and the output is an intersection-free triangle soup with Hausdorff distance @@ -111,7 +111,7 @@ double ceil(NT x){ * \cgalParamDefault{23} * \cgalParamExtra{Must be lower than 52.} * \cgalParamNEnd -* \cgalParamNBegin{numbers_of_iteration} +* \cgalParamNBegin{number_of_iterations} * \cgalParamDescription{Maximum number of iteration performed by the algorithm.} * \cgalParamType{unsigned int} * \cgalParamDefault{15} @@ -122,21 +122,13 @@ double ceil(NT x){ * able to provide such a triangle soup within the number of iterations. */ template -bool snap_polygon_soup(PointRange &points, +bool polygon_soup_snap_rounding(PointRange &points, PolygonRange &triangles, 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; - using GT=typename GetPolygonSoupGeomTraits::type; - using Point_map=typename GetPointMap::const_type; - Point_map pm = choose_parameter(get_parameter(np, internal_np::point_map)); - typedef typename internal_np::Lookup_named_param_def < internal_np::concurrency_tag_t, NamedParameters, @@ -144,7 +136,6 @@ bool snap_polygon_soup(PointRange &points, > ::type Concurrency_tag; constexpr bool parallel_execution = std::is_same_v; - // constexpr bool parallel_execution = false; #ifndef CGAL_LINKED_WITH_TBB static_assert (!parallel_execution, @@ -359,4 +350,4 @@ bool snap_polygon_soup(PointRange &points, } } } //end of CGAL::Polygon_mesh_processing::internal namespace -#endif //CGAL_POLYGON_MESH_PROCESSING_SNAP_POLYGON_SOUP_H +#endif //CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H From 0bbaa2a661d0d8207ff971bdefa7631cff4cdead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 19 Feb 2025 17:33:57 +0100 Subject: [PATCH 015/113] replace #ifdef CGAL_LINED_WITH_TBB by constexpr --- .../internal/triangle_soup_snap_rounding.h | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 62a67de0501..bdcd35296e0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -135,6 +135,7 @@ bool polygon_soup_snap_rounding(PointRange &points, Sequential_tag > ::type Concurrency_tag; + constexpr bool parallel_execution = std::is_same_v; #ifndef CGAL_LINKED_WITH_TBB @@ -202,19 +203,18 @@ bool polygon_soup_snap_rounding(PointRange &points, std::cout << "Round all coordinates on doubles" << std::endl; #endif -#ifdef CGAL_LINKED_WITH_TBB - if(parallel_execution) - { - tbb::parallel_for(tbb::blocked_range(0, points.size()), - [&](const tbb::blocked_range& r){ - for(size_t pi = r.begin(); pi != r.end(); ++pi) - points[pi] = Point_3(to_double(points[pi].x()), to_double(points[pi].y()), to_double(points[pi].z())); - } - ); - } else -#endif - for (Point_3 &p : points) - p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); + if constexpr(parallel_execution) + { + tbb::parallel_for(tbb::blocked_range(0, points.size()), + [&](const tbb::blocked_range& r){ + for(size_t pi = r.begin(); pi != r.end(); ++pi) + points[pi] = Point_3(to_double(points[pi].x()), to_double(points[pi].y()), to_double(points[pi].z())); + } + ); + } else { + for (Point_3 &p : points) + p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); + } repair_polygon_soup(points, triangles, np); // Get all intersecting triangles @@ -265,25 +265,25 @@ bool polygon_soup_snap_rounding(PointRange &points, snap_points.erase(std::unique(snap_points.begin(), snap_points.end()), snap_points.end()); // If the snapped version of a point correspond to one of the previous point, we snap it -#ifdef CGAL_LINKED_WITH_TBB - if(parallel_execution) - { - tbb::parallel_for(tbb::blocked_range(0, points.size()), - [&](const tbb::blocked_range& r){ - for(size_t pi = r.begin(); pi != r.end(); ++pi){ - Point_3 p_snap=snap_p(points[pi]); - if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) - points[pi] = p_snap; - } - } - ); - } else -#endif - for (Point_3 &p : points) + + if constexpr(parallel_execution) { - Point_3 p_snap = snap_p(p); - if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) - p = p_snap; + tbb::parallel_for(tbb::blocked_range(0, points.size()), + [&](const tbb::blocked_range& r){ + for(size_t pi = r.begin(); pi != r.end(); ++pi){ + Point_3 p_snap=snap_p(points[pi]); + if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) + points[pi] = p_snap; + } + } + ); + } else { + for (Point_3 &p : points) + { + Point_3 p_snap = snap_p(p); + if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) + p = p_snap; + } } #else From 20e54eb8fda06720759df6faeb9062fd67726463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Thu, 20 Feb 2025 09:14:01 +0100 Subject: [PATCH 016/113] reintroduced #ifdef CGAL_LINKED_WITH_TBB --- .../internal/triangle_soup_snap_rounding.h | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index bdcd35296e0..5aa68a4df5a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -203,6 +203,7 @@ bool polygon_soup_snap_rounding(PointRange &points, std::cout << "Round all coordinates on doubles" << std::endl; #endif +#ifdef CGAL_LINKED_WITH_TBB if constexpr(parallel_execution) { tbb::parallel_for(tbb::blocked_range(0, points.size()), @@ -211,10 +212,11 @@ bool polygon_soup_snap_rounding(PointRange &points, points[pi] = Point_3(to_double(points[pi].x()), to_double(points[pi].y()), to_double(points[pi].z())); } ); - } else { - for (Point_3 &p : points) - p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); - } + } else +#else + for (Point_3 &p : points) + p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); +#endif repair_polygon_soup(points, triangles, np); // Get all intersecting triangles @@ -265,7 +267,7 @@ bool polygon_soup_snap_rounding(PointRange &points, snap_points.erase(std::unique(snap_points.begin(), snap_points.end()), snap_points.end()); // If the snapped version of a point correspond to one of the previous point, we snap it - +#ifdef CGAL_LINKED_WITH_TBB if constexpr(parallel_execution) { tbb::parallel_for(tbb::blocked_range(0, points.size()), @@ -277,14 +279,15 @@ bool polygon_soup_snap_rounding(PointRange &points, } } ); - } else { - for (Point_3 &p : points) - { - Point_3 p_snap = snap_p(p); - if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) - p = p_snap; - } + } else +#else + for (Point_3 &p : points) + { + Point_3 p_snap = snap_p(p); + if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) + p = p_snap; } +#endif #else // Version where points in a voxel are rounded to their barycenter. From 5d3ec39dd1a9ed9fa314250465736309728dce63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 24 Feb 2025 15:25:22 +0100 Subject: [PATCH 017/113] Add more soup information in snap_polygon_soup.cpp --- .../snap_polygon_soup.cpp | 92 ++++++++++++++----- 1 file changed, 69 insertions(+), 23 deletions(-) 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 d0265ee9fab..e23fcdbaa9f 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,12 +1,13 @@ -#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE +// #define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE // #define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE -#include +#include #include #include #include #include #include +#include #include #include #include @@ -15,9 +16,9 @@ #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; -typedef CGAL::Cartesian Cartesian; -typedef Kernel::Point_3 Point; +typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; +typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; +typedef CGAL::Simple_cartesian Cartesian; namespace PMP = CGAL::Polygon_mesh_processing; @@ -26,31 +27,76 @@ int main(int argc, char** argv) const std::string filename = argc == 1 ? CGAL::data_file_path("meshes/elephant.off") : std::string(argv[1]); + // const std::string out_file = argc <= 2 ? "rounded_soup.off" + // : std::string(argv[2]); + const std::string out_file = "rounded_soup.off"; + const int grid_size = argc <= 2 ? 23 : std::stoi(std::string(argv[2])); - std::vector input_points; - std::vector> input_triangles; - if (!CGAL::IO::read_polygon_soup(filename, input_points, input_triangles)) + const bool epeck = argc <= 3 ? false + : std::string(argv[3])=="EPECK"; + + if(epeck) { - std::cerr << "Cannot read " << filename << "\n"; - return 1; + std::vector input_points; + std::vector> input_triangles; + + std::cout << "Snap rounding apply on " << filename << " with EPECK\n"; + if (!CGAL::IO::read_polygon_soup(filename, input_points, input_triangles)) + { + std::cerr << "Cannot read " << filename << "\n"; + return 1; + } + std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << std::endl; + std::cout << "Is 2-manifold: " << PMP::is_polygon_soup_a_polygon_mesh(input_triangles) << std::endl; + + PMP::repair_polygon_soup(input_points, input_triangles); + PMP::triangulate_polygons(input_points, input_triangles); + + CGAL::Real_timer t; + t.start(); + PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(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::cout << "Does self-intersect: " << PMP::does_triangle_soup_self_intersect(input_points, input_triangles) << std::endl; + std::cout << "Is 2-manifold: " << PMP::orient_polygon_soup(input_points, input_triangles) << "\n\n" << std::endl; + + std::vector output_points; + 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(out_file, output_points, input_triangles, CGAL::parameters::stream_precision(17)); } - PMP::repair_polygon_soup(input_points, input_triangles); - PMP::triangulate_polygons(input_points, input_triangles); + else + { + std::vector input_points; + std::vector> input_triangles; + std::cout << "Snap rounding on " << filename << " with EPICK\n"; + if (!CGAL::IO::read_polygon_soup(filename, input_points, input_triangles)) + { + std::cerr << "Cannot read " << filename << "\n"; + return 1; + } + std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << std::endl; + std::cout << "Is 2-manifold: " << PMP::is_polygon_soup_a_polygon_mesh(input_triangles) << std::endl; - CGAL::Real_timer t; - t.start(); - PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(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> pairs_of_intersecting_triangles; + PMP::triangle_soup_self_intersections(input_points, input_triangles, std::back_inserter(pairs_of_intersecting_triangles)); + std::cout << "Nb of pairs of intersecting triangles: " << pairs_of_intersecting_triangles.size() << 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)); + PMP::repair_polygon_soup(input_points, input_triangles); + PMP::triangulate_polygons(input_points, input_triangles); + CGAL::Real_timer t; + t.start(); + PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size)); + t.stop(); + std::cout << "\nOutput:" << std::endl; + std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << " in " << t.time() << " sec." << std::endl; + std::cout << "Does self-intersect: " << PMP::does_triangle_soup_self_intersect(input_points, input_triangles) << std::endl; + std::cout << "Is 2-manifold: " << PMP::orient_polygon_soup(input_points, input_triangles) << "\n\n" << std::endl; + CGAL::IO::write_polygon_soup(out_file, input_points, input_triangles, CGAL::parameters::stream_precision(17)); + } return 0; } From 3b29156f29370eb5acc4ed3f164a6cbc71c43ba9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 25 Feb 2025 09:41:09 +0100 Subject: [PATCH 018/113] Bug solved: Shift before ceil was in the wrong direction --- .../internal/triangle_soup_snap_rounding.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 5aa68a4df5a..e7a2d5c6821 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -183,7 +183,9 @@ bool polygon_soup_snap_rounding(PointRange &points, auto snap = [](typename Kernel::FT x, double scale) { // Scale the coordinate, round to nearest integer and scale back - return internal::ceil((x * scale) + 0.5) / scale; + // TODO replace this ceil by the one of Algebraic_fondation when it will be add to master + return internal::ceil((x * scale) - 0.5) / scale; + // return ceil((x * scale) - 0.5) / scale; }; auto snap_p = [scale, snap](const Point_3 &p) { From 88bad8a2e572ae2c8d63d5cc2feb5585748a8806 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Fri, 28 Feb 2025 11:44:23 +0100 Subject: [PATCH 019/113] Clean doc autorefine Co-authored-by: Sebastien Loriot --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 c9aa67b93d7..ea782f556f1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -994,9 +994,9 @@ bool polygon_soup_snap_rounding(PointRange &points, * `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 `apply_iterative_snap_rounding` 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. +* the creation of new triangles. +* If the `apply_iterative_snap_rounding()` parameter is set to true, the coordinates of the vertices are rounded to fit within the precision of a double-precision floating point, +* while trying to make the triangle soup free of 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` From 05ecac919d058c9f3755b165e9aed908eef34d0b Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Fri, 28 Feb 2025 11:45:00 +0100 Subject: [PATCH 020/113] Clean doc autorefine return description Co-authored-by: Sebastien Loriot --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 ea782f556f1..cdd5542d8b2 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1051,8 +1051,7 @@ bool polygon_soup_snap_rounding(PointRange &points, * \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. +* \return `true` if the modified triangle soup is free from self-intersection, and `false` otherwise. The return value is only meaningful when the option `apply_snap_rounding()` is set to true. */ template bool autorefine_triangle_soup(PointRange& soup_points, From b99ae574d1a9d0f66d7bc0d532f3b881aae41f99 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Fri, 28 Feb 2025 11:45:47 +0100 Subject: [PATCH 021/113] Clean doc autorefine snap_grid_size description Co-authored-by: Sebastien Loriot --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 cdd5542d8b2..73dc2983aef 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1039,7 +1039,7 @@ bool polygon_soup_snap_rounding(PointRange &points, * \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 `apply_iterative_snap_rounding` is true.} +* \cgalParamDescription{A value `gs` used to scale the points to `[-2^gs, 2^gs]` before rounding them on integers. Used only if `apply_iterative_snap_rounding()` is set to `true`.} * \cgalParamType{unsigned int} * \cgalParamDefault{23} * \cgalParamExtra{Must be lower than 52.} From 15e80b0a781241e9dd8c13fe58813ccb2535a2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 3 Mar 2025 15:26:25 +0100 Subject: [PATCH 022/113] solved conflict --- .../Polygon_mesh_processing/autorefinement.h | 8 +++++--- .../internal/triangle_soup_snap_rounding.h | 17 ++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) 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 73dc2983aef..458d23466e3 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1039,19 +1039,21 @@ bool polygon_soup_snap_rounding(PointRange &points, * \cgalParamDefault{false} * \cgalParamNEnd * \cgalParamNBegin{snap_grid_size} -* \cgalParamDescription{A value `gs` used to scale the points to `[-2^gs, 2^gs]` before rounding them on integers. Used only if `apply_iterative_snap_rounding()` is set to `true`.} +* \cgalParamDescription{A value `gs` used to scale the points to `[-2^gs, 2^gs]` before rounding them on integers. Used only if `apply_iterative_snap_rounding()` is set to `true`} * \cgalParamType{unsigned int} * \cgalParamDefault{23} * \cgalParamExtra{Must be lower than 52.} * \cgalParamNEnd * \cgalParamNBegin{number_of_iterations} -* \cgalParamDescription{Maximum number of iteration performed by the snap algorithm. Use only if `apply_iterative_snap_rounding` is true.} +* \cgalParamDescription{Maximum number of iterations performed by the snap algorithm. Used only if `apply_iterative_snap_rounding` is true.} * \cgalParamType{unsigned int} * \cgalParamDefault{15} * \cgalParamNEnd * \cgalNamedParamsEnd * -* \return `true` if the modified triangle soup is free from self-intersection, and `false` otherwise. The return value is only meaningful when the option `apply_snap_rounding()` is set to true. +* \return `true` if `apply_iterative_snap_rounding` is set to `false`; otherwise, return `true` if the modified triangle soup is free from +* self-intersection, and `false` if the algorithm was unable to provide such a triangle soup within the number of iterations. +* */ template bool autorefine_triangle_soup(PointRange& soup_points, diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index e7a2d5c6821..c1fa810db6c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -22,7 +22,6 @@ #include #include -#include namespace CGAL { @@ -33,11 +32,11 @@ namespace Polygon_mesh_processing namespace internal { -template double ceil(Lazy_exact_nt< NT > x); -template double ceil(NT x); +template double double_ceil(Lazy_exact_nt< NT > x); +template double double_ceil(NT x); template -double ceil(Lazy_exact_nt< NT > x){ +double double_ceil(Lazy_exact_nt< NT > x){ // If both sides are in the same ceil, return this ceil double ceil_left=std::ceil(to_interval(x).first); if(ceil_left==std::ceil(to_interval(x).second)) @@ -48,11 +47,11 @@ double ceil(Lazy_exact_nt< NT > x){ if(ceil_left==std::ceil(to_interval(x).second)) return ceil_left; // If not return the ceil of the exact value - return ceil( x.exact()); + return double_ceil( x.exact()); }; template -double ceil(NT x){ +double double_ceil(NT x){ using FT = Fraction_traits; if constexpr(std::is_same::value){ // If NT is a fraction, the ceil value is the result of the euclidian division of the numerator and the denominator. @@ -60,8 +59,8 @@ double ceil(NT x){ typename FT::Denominator_type denom; typename FT::Decompose()(x,num,denom); div_mod(num, denom, r, e); - if((r<0) && e!=0) //If the result is negative, the ceil value is one below - return to_double(r-1); + if((r>=0) && e!=0) //If the result is positive, the ceil value is one above + return to_double(r+1); return to_double(r); } else { // Return the ceil of the approximation @@ -184,7 +183,7 @@ bool polygon_soup_snap_rounding(PointRange &points, { // Scale the coordinate, round to nearest integer and scale back // TODO replace this ceil by the one of Algebraic_fondation when it will be add to master - return internal::ceil((x * scale) - 0.5) / scale; + return internal::double_ceil((x * scale) - 0.5) / scale; // return ceil((x * scale) - 0.5) / scale; }; auto snap_p = [scale, snap](const Point_3 &p) From f615b6537d46f98d9654e9bd829e274e07541ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 3 Mar 2025 15:33:36 +0100 Subject: [PATCH 023/113] missing word in the doc --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 458d23466e3..a4752e8365c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1045,7 +1045,7 @@ bool polygon_soup_snap_rounding(PointRange &points, * \cgalParamExtra{Must be lower than 52.} * \cgalParamNEnd * \cgalParamNBegin{number_of_iterations} -* \cgalParamDescription{Maximum number of iterations performed by the snap algorithm. Used only if `apply_iterative_snap_rounding` is true.} +* \cgalParamDescription{Maximum number of iterations performed by the snap rounding algorithm. Used only if `apply_iterative_snap_rounding` is true.} * \cgalParamType{unsigned int} * \cgalParamDefault{15} * \cgalParamNEnd From 4200d928ff3de733d60fbc82265ee3413409c2af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 3 Mar 2025 16:03:55 +0100 Subject: [PATCH 024/113] Reduce default number of iterations --- .../internal/triangle_soup_snap_rounding.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index c1fa810db6c..9c6bad3839c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -113,7 +113,7 @@ double double_ceil(NT x){ * \cgalParamNBegin{number_of_iterations} * \cgalParamDescription{Maximum number of iteration performed by the algorithm.} * \cgalParamType{unsigned int} -* \cgalParamDefault{15} +* \cgalParamDefault{5} * \cgalParamNEnd * \cgalNamedParamsEnd * @@ -147,7 +147,7 @@ bool polygon_soup_snap_rounding(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), 15); + const unsigned int max_nb_of_iteration = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 5); #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Compute the scaling of the coordinates" << std::endl; From ebbd529ef64f60aaf35e5fe7ebd0e0354f887e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Thu, 13 Mar 2025 18:57:12 +0100 Subject: [PATCH 025/113] Modify soup_triangles_snap_rounding to support a visitor --- .../Concepts/PMPAutorefinementVisitor.h | 3 + .../snap_polygon_soup.cpp | 22 +- .../Polygon_mesh_processing/autorefinement.h | 201 ++++++++++-------- .../internal/triangle_soup_snap_rounding.h | 155 +++++++++++++- 4 files changed, 280 insertions(+), 101 deletions(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h index ef2f124329b..c7494db4879 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h @@ -23,5 +23,8 @@ public: /// called for each subtriangle created from a triangle with intersection, `tgt_id` is the position in the triangle container after calling /// `autorefine_triangle_soup()` of the subtriangle, while `src_id` was the position of the original support triangle before calling the function. void new_subtriangle(std::size_t tgt_id, std::size_t src_id); + /// called for each triangle delete because it was or became degenerated, `src_id` was its position before calling `autorefine_triangle_soup()`. + /// A triangle may degenerate inside `autorefine_triangle_soup()` if and only if `apply_iterative_snap_rounding` is set to `true`. + void delete_triangle(std::size_t src_id); /// @} }; 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 e23fcdbaa9f..f03bb5a2388 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 @@ -22,6 +22,21 @@ typedef CGAL::Simple_cartesian Cartesian; namespace PMP = CGAL::Polygon_mesh_processing; +struct Track_visitor +{ + // inline void number_of_output_triangles(std::size_t nbt) { std::cout << "total number of triangles: " << nbt << std::endl;} + inline void number_of_output_triangles(std::size_t /*nbt*/) {} + + // inline void verbatim_triangle_copy(std::size_t tgt_id, std::size_t src_id) { std::cout << src_id << " goes to " << tgt_id << std::endl;} + inline void verbatim_triangle_copy(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} + + // inline void new_subtriangle(std::size_t tgt_id, std::size_t src_id) { std::cout << src_id << " subdivides to " << tgt_id << std::endl;} + inline void new_subtriangle(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} + + // inline void delete_triangle(std::size_t src_id) { std::cout << src_id << " deleted" << std::endl;} + inline void delete_triangle(std::size_t /*src_id*/) {} +}; + int main(int argc, char** argv) { const std::string filename = argc == 1 ? CGAL::data_file_path("meshes/elephant.off") @@ -90,13 +105,18 @@ int main(int argc, char** argv) CGAL::Real_timer t; t.start(); +#if 0 + Track_visitor visitor; + PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).visitor(visitor)); +#else PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size)); +#endif t.stop(); std::cout << "\nOutput:" << std::endl; std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << " in " << t.time() << " sec." << std::endl; std::cout << "Does self-intersect: " << PMP::does_triangle_soup_self_intersect(input_points, input_triangles) << std::endl; - std::cout << "Is 2-manifold: " << PMP::orient_polygon_soup(input_points, input_triangles) << "\n\n" << std::endl; CGAL::IO::write_polygon_soup(out_file, input_points, input_triangles, CGAL::parameters::stream_precision(17)); + std::cout << "Is 2-manifold: " << PMP::orient_polygon_soup(input_points, input_triangles) << "\n\n" << std::endl; } 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 a4752e8365c..fe221f554ec 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -89,6 +89,7 @@ struct Default_visitor inline void number_of_output_triangles(std::size_t /*nbt*/) {} inline void verbatim_triangle_copy(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} inline void new_subtriangle(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} + inline void delete_triangle(std::size_t /*src_id*/) {} }; } // end of Autorefinement visitor @@ -980,86 +981,14 @@ template +class Indexes_range; -/** -* \ingroup PMP_corefinement_grp -* -* refines a soup of triangles so that no pair of triangles intersects. -* Output triangles may share a common edge or a common vertex (but with the same indexed position in `points`). -* Note that points in `soup_points` can only be added (intersection points) at the end of the container, with the initial order preserved. -* Note that if `soup_points` contains two or more identical points then only the first copy (following the order in the `soup_points`) -* will be used in `soup_triangles`. -* `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 -* the creation of new triangles. -* If the `apply_iterative_snap_rounding()` parameter is set to true, the coordinates of the vertices are rounded to fit within the precision of a double-precision floating point, -* while trying to make the triangle soup free of 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 -* @tparam TriangleRange a model of the concepts `RandomAccessContainer`, `BackInsertionSequence` and `Swappable`, whose -* value type is a model of the concept `RandomAccessContainer` whose value type is convertible to `std::size_t` and that -* is constructible from an `std::initializer_list` of size 3. -* @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" -* -* @param soup_points points of the soup of polygons -* @param soup_triangles each element in the range describes a triangle using the indexed position of the points in `soup_points` -* @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below -* -* \cgalNamedParamsBegin -* \cgalParamNBegin{concurrency_tag} -* \cgalParamDescription{a tag indicating if the task should be done using one or several threads.} -* \cgalParamType{Either `CGAL::Sequential_tag`, or `CGAL::Parallel_tag`, or `CGAL::Parallel_if_available_tag`} -* \cgalParamDefault{`CGAL::Sequential_tag`} -* \cgalParamNEnd -* \cgalParamNBegin{point_map} -* \cgalParamDescription{a property map associating points to the elements of the range `soup_points`} -* \cgalParamType{a model of `ReadWritePropertyMap` whose value type is a point type} -* \cgalParamDefault{`CGAL::Identity_property_map`} -* \cgalParamNEnd -* \cgalParamNBegin{geom_traits} -* \cgalParamDescription{an instance of a geometric traits class} -* \cgalParamType{a class model of `Kernel`} -* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} -* \cgalParamExtra{The geometric traits class must be compatible with the point type.} -* \cgalParamNEnd -* \cgalParamNBegin{visitor} -* \cgalParamDescription{a visitor used to track the creation of new faces} -* \cgalParamType{a class model of `PMPAutorefinementVisitor`} -* \cgalParamDefault{`Autorefinement::Default_visitor`} -* \cgalParamExtra{The visitor will be copied.} -* \cgalParamNEnd -* \cgalParamNBegin{apply_iterative_snap_rounding} -* \cgalParamDescription{Enable the rounding of the coordinates so that they fit in doubles.} -* \cgalParamType{boolean} -* \cgalParamDefault{false} -* \cgalParamNEnd -* \cgalParamNBegin{snap_grid_size} -* \cgalParamDescription{A value `gs` used to scale the points to `[-2^gs, 2^gs]` before rounding them on integers. Used only if `apply_iterative_snap_rounding()` is set to `true`} -* \cgalParamType{unsigned int} -* \cgalParamDefault{23} -* \cgalParamExtra{Must be lower than 52.} -* \cgalParamNEnd -* \cgalParamNBegin{number_of_iterations} -* \cgalParamDescription{Maximum number of iterations performed by the snap rounding algorithm. Used only if `apply_iterative_snap_rounding` is true.} -* \cgalParamType{unsigned int} -* \cgalParamDefault{15} -* \cgalParamNEnd -* \cgalNamedParamsEnd -* -* \return `true` if `apply_iterative_snap_rounding` is set to `false`; otherwise, return `true` if the modified triangle soup is free from -* self-intersection, and `false` if the algorithm was unable to provide such a triangle soup within the number of iterations. -* -*/ template -bool autorefine_triangle_soup(PointRange& soup_points, - TriangleRange& soup_triangles, - const NamedParameters& np = parameters::default_values()) - +bool autorefine_triangle_soup_(PointRange& soup_points, + TriangleRange& soup_triangles, + const NamedParameters& np = parameters::default_values()) { using parameters::choose_parameter; using parameters::get_parameter; @@ -1082,18 +1011,6 @@ bool autorefine_triangle_soup(PointRange& soup_points, > ::type Visitor; Visitor visitor(choose_parameter(get_parameter(np, internal_np::visitor))); - //TODO just modify apply_iterative_snap_rounding instead of getting np one by one - const bool do_snap = choose_parameter(get_parameter(np, internal_np::apply_iterative_snap_rounding), 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::polygon_soup_snap_rounding(soup_points, soup_triangles, parameters::point_map(pm).visitor(visitor).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; #ifndef CGAL_LINKED_WITH_TBB @@ -1498,15 +1415,18 @@ bool autorefine_triangle_soup(PointRange& soup_points, std::vector tri_inter_ids_inverse(triangles.size()); for (Input_TID f=0; f) + visitor.delete_triangle(f); + continue; //skip degenerate faces + } int tiid = tri_inter_ids[f]; if (tiid == -1) { visitor.verbatim_triangle_copy(soup_triangles_out.size(), f); - soup_triangles_out.push_back( - {soup_triangles[f][0], soup_triangles[f][1], soup_triangles[f][2]} - ); + soup_triangles_out.push_back(soup_triangles[f]); } else { @@ -1688,6 +1608,101 @@ bool autorefine_triangle_soup(PointRange& soup_points, return true; } +} // end of internal + +/** +* \ingroup PMP_corefinement_grp +* +* refines a soup of triangles so that no pair of triangles intersects. +* Output triangles may share a common edge or a common vertex (but with the same indexed position in `points`). +* Note that points in `soup_points` can only be added (intersection points) at the end of the container, with the initial order preserved. +* Note that if `soup_points` contains two or more identical points then only the first copy (following the order in the `soup_points`) +* will be used in `soup_triangles`. +* `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 +* the creation of new triangles. +* If the `apply_iterative_snap_rounding()` parameter is set to true, the coordinates of the vertices are rounded to fit within the precision of a double-precision floating point, +* while trying to make the triangle soup free of 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 +* @tparam TriangleRange a model of the concepts `RandomAccessContainer`, `BackInsertionSequence` and `Swappable`, whose +* value type is a model of the concept `RandomAccessContainer` whose value type is convertible to `std::size_t` and that +* is constructible from an `std::initializer_list` of size 3. +* @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" +* +* @param soup_points points of the soup of polygons +* @param soup_triangles each element in the range describes a triangle using the indexed position of the points in `soup_points` +* @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below +* +* \cgalNamedParamsBegin +* \cgalParamNBegin{concurrency_tag} +* \cgalParamDescription{a tag indicating if the task should be done using one or several threads.} +* \cgalParamType{Either `CGAL::Sequential_tag`, or `CGAL::Parallel_tag`, or `CGAL::Parallel_if_available_tag`} +* \cgalParamDefault{`CGAL::Sequential_tag`} +* \cgalParamNEnd +* \cgalParamNBegin{point_map} +* \cgalParamDescription{a property map associating points to the elements of the range `soup_points`} +* \cgalParamType{a model of `ReadWritePropertyMap` whose value type is a point type} +* \cgalParamDefault{`CGAL::Identity_property_map`} +* \cgalParamNEnd +* \cgalParamNBegin{geom_traits} +* \cgalParamDescription{an instance of a geometric traits class} +* \cgalParamType{a class model of `Kernel`} +* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} +* \cgalParamExtra{The geometric traits class must be compatible with the point type.} +* \cgalParamNEnd +* \cgalParamNBegin{visitor} +* \cgalParamDescription{a visitor used to track the creation of new faces} +* \cgalParamType{a class model of `PMPAutorefinementVisitor`} +* \cgalParamDefault{`Autorefinement::Default_visitor`} +* \cgalParamExtra{The visitor will be copied.} +* \cgalParamNEnd +* \cgalParamNBegin{apply_iterative_snap_rounding} +* \cgalParamDescription{Enable the rounding of the coordinates so that they fit in doubles.} +* \cgalParamType{boolean} +* \cgalParamDefault{false} +* \cgalParamNEnd +* \cgalParamNBegin{snap_grid_size} +* \cgalParamDescription{A value `gs` used to scale the points to `[-2^gs, 2^gs]` before rounding them on integers. Used only if `apply_iterative_snap_rounding()` is set to `true`} +* \cgalParamType{unsigned int} +* \cgalParamDefault{23} +* \cgalParamExtra{Must be lower than 52.} +* \cgalParamNEnd +* \cgalParamNBegin{number_of_iterations} +* \cgalParamDescription{Maximum number of iterations performed by the snap rounding algorithm. Used only if `apply_iterative_snap_rounding` is true.} +* \cgalParamType{unsigned int} +* \cgalParamDefault{15} +* \cgalParamNEnd +* \cgalNamedParamsEnd +* +* \return `true` if `apply_iterative_snap_rounding` is set to `false`; otherwise, return `true` if the modified triangle soup is free from +* self-intersection, and `false` if the algorithm was unable to provide such a triangle soup within the number of iterations. +* +*/ +template +bool autorefine_triangle_soup(PointRange& soup_points, + TriangleRange& soup_triangles, + const NamedParameters& np = parameters::default_values()) +{ + using parameters::choose_parameter; + using parameters::get_parameter; + + const bool do_snap = choose_parameter(get_parameter(np, internal_np::apply_iterative_snap_rounding), false); + if(do_snap) + { + CGAL_PMP_AUTOREFINE_VERBOSE("Snap polygon soup"); + return internal::polygon_soup_snap_rounding(soup_points, soup_triangles, np); + } + else + { + return internal::autorefine_triangle_soup_(soup_points, soup_triangles, np); + } +} + + /** * \ingroup PMP_corefinement_grp * refines a triangle mesh so that no triangles intersects in their interior. diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 9c6bad3839c..c67e5ba0745 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -17,12 +17,13 @@ #include #include -// #include #include #include #include +#include + namespace CGAL { @@ -68,8 +69,69 @@ double double_ceil(NT x){ } }; +CGAL_MUTEX map_mutex; + +template +class Indexes_range{ + typedef std::remove_cv_t::value_type> Value_type; +public: + typedef typename Range::const_iterator const_iterator; + typedef typename Range::iterator iterator; + + Indexes_range(){} + Indexes_range(std::initializer_list l): poly(l), m_id(0), modified(true){} + Indexes_range(const Indexes_range &ir):poly(ir.range()), m_id(ir.id()), modified(ir.was_modified()){} + Indexes_range(Range &p):poly(p), modified(true){} + Indexes_range(Range &p, size_t id):poly(p), m_id(id),modified(false){} + + void operator=(std::initializer_list l) + { + poly=l; + modified=true; + } + + inline size_t id() const { return m_id; } + inline void set_id(size_t id){ m_id=id; } + inline bool was_modified() const { return modified; } + + inline size_t size(){ return poly.size(); } + + inline iterator begin(){ return poly.begin(); } + inline iterator end(){ return poly.end(); } + inline const_iterator begin() const{ return poly.begin(); } + inline const_iterator end() const{ return poly.end(); } + + inline Value_type operator[](size_t i){ return poly[i]; } + inline const Value_type operator[](size_t i) const{ return poly[i]; } + + inline void push_back(Value_type v){ poly.push_back(v);} + inline Range range(){ return poly;} + inline const Range range() const{ return poly;} +private: + Range poly; + size_t m_id; + bool modified; +}; + +template +struct Wrapp_id_visitor +{ + Wrapp_id_visitor(PolygonRange* tr, Map* map):triangles(tr), map_newtriangles(map){} + inline void number_of_output_triangles(std::size_t /*nbt*/) {} + inline void verbatim_triangle_copy(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} + inline void new_subtriangle(std::size_t tgt_id, std::size_t src_id) + { + CGAL_SCOPED_LOCK(map_mutex); + (*map_newtriangles)[(*triangles)[src_id].id()].push_back(tgt_id); + } + inline void delete_triangle(std::size_t /*src_id*/) {} + +private: + PolygonRange* triangles; + Map* map_newtriangles; +}; + /** -* DEPRECATED SINCE INTERNAL * * Rounds the coordinates of the points so that they fit in doubles while making and keeping the model intersection free by potentially subdividing the triangles. * The input can be any triangle soup and the output is an intersection-free triangle soup with Hausdorff distance @@ -121,21 +183,34 @@ double double_ceil(NT x){ * able to provide such a triangle soup within the number of iterations. */ template -bool polygon_soup_snap_rounding(PointRange &points, +bool polygon_soup_snap_rounding_(PointRange &points, PolygonRange &triangles, const NamedParameters& np) { using parameters::choose_parameter; using parameters::get_parameter; + // typedef typename GetPolygonSoupGeomTraits::type GT; + typedef typename GetPointMap::const_type Point_map; + Point_map pm = choose_parameter(get_parameter(np, internal_np::point_map)); + typedef typename internal_np::Lookup_named_param_def < internal_np::concurrency_tag_t, NamedParameters, Sequential_tag > ::type Concurrency_tag; + // visitor + typedef typename internal_np::Lookup_named_param_def < + internal_np::visitor_t, + NamedParameters, + Autorefinement::Default_visitor//default + >::type Visitor; + Visitor visitor(choose_parameter(get_parameter(np, internal_np::visitor))); + constexpr bool has_visitor = !std::is_same_v; constexpr bool parallel_execution = std::is_same_v; + const size_t number_of_input_triangles = triangles.size(); #ifndef CGAL_LINKED_WITH_TBB static_assert (!parallel_execution, @@ -184,7 +259,6 @@ bool polygon_soup_snap_rounding(PointRange &points, // Scale the coordinate, round to nearest integer and scale back // TODO replace this ceil by the one of Algebraic_fondation when it will be add to master return internal::double_ceil((x * scale) - 0.5) / scale; - // return ceil((x * scale) - 0.5) / scale; }; auto snap_p = [scale, snap](const Point_3 &p) { @@ -222,14 +296,32 @@ bool polygon_soup_snap_rounding(PointRange &points, // Get all intersecting triangles std::vector> pairs_of_intersecting_triangles; - triangle_soup_self_intersections(points, triangles, std::back_inserter(pairs_of_intersecting_triangles), np); + triangle_soup_self_intersections(points, triangles, std::back_inserter(pairs_of_intersecting_triangles), np); if (pairs_of_intersecting_triangles.empty()) { #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "End of the snapping" << std::endl; #endif - CGAL_assertion(!does_triangle_soup_self_intersect(points, triangles, np)); + CGAL_assertion(!does_triangle_soup_self_intersect(points, triangles, np)); + if constexpr(has_visitor) + { + std::vector > map_io(number_of_input_triangles); + size_t id=0; + for(auto &t: triangles) + map_io[t.id()].push_back(id++); + + visitor.number_of_output_triangle(triangles.size()); + for(size_t src_id=0; src_id!=map_io.size(); ++src_id){ + if(map_io[src_id].size()==0) + visitor.delete_triangle(src_id); + else if(map_io[src_id].size()==1 && !triangles[map_io[src_id][0]].was_modified()) + visitor.verbatim_triangle_copy(map_io[src_id][0],src_id); + else + for(size_t new_id: map_io[src_id]) + visitor.new_subtriangle(new_id,src_id); + } + } return true; } @@ -347,11 +439,60 @@ bool polygon_soup_snap_rounding(PointRange &points, std::cout << "Model size: " << points.size() << " " << triangles.size() << std::endl; std::cout << "Autorefine the soup" << std::endl; #endif - autorefine_triangle_soup(points, triangles, np); + if constexpr(has_visitor) + { +#ifdef CGAL_LINKED_WITH_TBB + std::conditional_t >, + std::map > > map_newtriangles; +#else + std::map > map_newtriangles; +#endif + Wrapp_id_visitor visitor(&triangles, &map_newtriangles); + autorefine_triangle_soup_(points, triangles, parameters::point_map(pm).concurrency_tag(Concurrency_tag()).visitor(visitor)); + for(auto &pair: map_newtriangles) + for(size_t new_id: pair.second) + triangles[new_id].set_id(pair.first); + } + else + { + autorefine_triangle_soup_(points, triangles, parameters::point_map(pm).concurrency_tag(Concurrency_tag())); + } } return false; } +template +bool polygon_soup_snap_rounding(PointRange &soup_points, + PolygonRange &soup_triangles, + const NamedParameters& np) +{ + typedef typename internal_np::Lookup_named_param_def < + internal_np::visitor_t, + NamedParameters, + Autorefinement::Default_visitor//default + > ::type Visitor; + constexpr bool has_visitor = !std::is_same_v; + if constexpr(has_visitor) + { + using Triangle = std::remove_cv_t::value_type>; + std::vector > indexes_soup_triangles; + size_t id=0; + for(typename PolygonRange::iterator it=soup_triangles.begin(); it!=soup_triangles.end(); ++it) + indexes_soup_triangles.emplace_back((*it), id++); + std::cout << "Test 0" << std::endl; + bool res=polygon_soup_snap_rounding_(soup_points, indexes_soup_triangles, np); + soup_triangles.clear(); + for(const Indexes_range &t: indexes_soup_triangles) + soup_triangles.push_back({t[0],t[1],t[2]}); + return res; + } + else + { + return polygon_soup_snap_rounding_(soup_points, soup_triangles, np); + } +} + } } } //end of CGAL::Polygon_mesh_processing::internal namespace #endif //CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H From 5404b37aa28c6e7416bd69787df08d5a940253eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Thu, 13 Mar 2025 19:04:13 +0100 Subject: [PATCH 026/113] correct typo in function name --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index c67e5ba0745..3553f9f0696 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -311,7 +311,7 @@ bool polygon_soup_snap_rounding_(PointRange &points, for(auto &t: triangles) map_io[t.id()].push_back(id++); - visitor.number_of_output_triangle(triangles.size()); + visitor.number_of_output_triangles(triangles.size()); for(size_t src_id=0; src_id!=map_io.size(); ++src_id){ if(map_io[src_id].size()==0) visitor.delete_triangle(src_id); From aa765c2332c6c65b5cd4deba58e073f3b63a7bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Fri, 14 Mar 2025 13:58:45 +0100 Subject: [PATCH 027/113] Add variant where cluster of points are round to the closest of them to the voxel center instead of the voxel center --- .../snap_polygon_soup.cpp | 13 +++-- .../internal/triangle_soup_snap_rounding.h | 49 +++++++++++++++++++ 2 files changed, 57 insertions(+), 5 deletions(-) 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 f03bb5a2388..81e596ceb6b 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,4 +1,4 @@ -// #define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE +#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE // #define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE #include @@ -105,16 +105,19 @@ int main(int argc, char** argv) CGAL::Real_timer t; t.start(); -#if 0 +#if 1 Track_visitor visitor; - PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).visitor(visitor)); + bool success=PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).visitor(visitor)); #else - PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size)); + bool success=PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15)); #endif t.stop(); std::cout << "\nOutput:" << std::endl; std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << " in " << t.time() << " sec." << std::endl; - std::cout << "Does self-intersect: " << PMP::does_triangle_soup_self_intersect(input_points, input_triangles) << std::endl; + if(success) + std::cout << "Does self-intersect: " << PMP::does_triangle_soup_self_intersect(input_points, input_triangles) << std::endl; + else + std::cout << "ROUNDING FAILED" << std::endl; CGAL::IO::write_polygon_soup(out_file, input_points, input_triangles, CGAL::parameters::stream_precision(17)); std::cout << "Is 2-manifold: " << PMP::orient_polygon_soup(input_points, input_triangles) << "\n\n" << std::endl; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 3553f9f0696..68540b6d022 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -382,6 +382,55 @@ bool polygon_soup_snap_rounding_(PointRange &points, } #endif +#elif 1 + // Version where points in a voxel are rounded to the closest point + + // Group the points of the vertices of the intersecting triangles by their voxel + std::map snap_points; + std::size_t index=0; + for (auto &pair : pairs_of_intersecting_triangles) + { + for (size_t pi : triangles[pair.first]) + { + auto res=snap_points.emplace(snap_p(points[pi]), index); + if(res.second) + ++index; + } + for (size_t pi : triangles[pair.second]) + { + auto res=snap_points.emplace(snap_p(points[pi]), index); + if(res.second) + ++index; + } + } + + std::vector> identical_points(index); + for (size_t i=0; i!=points.size(); ++i) + { + Point_3 p_snap = snap_p(points[i]); + auto it=snap_points.find(p_snap); + if (it!=snap_points.end()){ + identical_points[it->second].push_back(i); + } + } + + // Replace all points in a voxel by the closest point + for(const auto &v: identical_points){ + if(v.size()>1){ + Point_3 center = snap_p(points[v[0]]); + size_t argmin(0); + for(size_t i=1; i!=v.size(); ++i){ + if(Kernel().compare_squared_distance_3_object()(center, points[v[i]], center, points[v[argmin]])==SMALLER) + { + argmin=i; + } + } + for(auto i: v){ + points[i]=points[v[argmin]]; + } + } + } + #else // Version where points in a voxel are rounded to their barycenter. From 26debef54aea4be0dd5b55b949c4948a03d0ef9e Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 18 Mar 2025 09:03:20 +0100 Subject: [PATCH 028/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h Co-authored-by: Andreas Fabri --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 fe221f554ec..95ca157a4f1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1622,7 +1622,7 @@ bool autorefine_triangle_soup_(PointRange& soup_points, * 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 * the creation of new triangles. -* If the `apply_iterative_snap_rounding()` parameter is set to true, the coordinates of the vertices are rounded to fit within the precision of a double-precision floating point, +* If the `apply_iterative_snap_rounding()` parameter is set to `true`, the coordinates of the vertices are rounded to fit within the precision of a double-precision floating point, * while trying to make the triangle soup free of 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. * From 3a0c0980ee696bd3bd75e1871fe4cd2188444ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 18 Mar 2025 15:50:16 +0100 Subject: [PATCH 029/113] add delete_triangle function to the visitor of test_autorefinement --- .../test/Polygon_mesh_processing/test_autorefinement.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_autorefinement.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_autorefinement.cpp index e04e07ba556..a265be44b8e 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_autorefinement.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_autorefinement.cpp @@ -66,6 +66,11 @@ struct My_visitor tgt_check[tgt_id]=1; } + void delete_triangle(std::size_t src_id) + { + assert(src_id tgt_check; From 0009f99680e3e4ad319571b646168d69cd3c71c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 19 Mar 2025 09:52:54 +0100 Subject: [PATCH 030/113] Debug the visitor of triangle_soup_snap_rounding --- .../internal/triangle_soup_snap_rounding.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 68540b6d022..da6790e4e5c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -94,7 +94,7 @@ public: inline void set_id(size_t id){ m_id=id; } inline bool was_modified() const { return modified; } - inline size_t size(){ return poly.size(); } + inline size_t size() const{ return poly.size(); } inline iterator begin(){ return poly.begin(); } inline iterator end(){ return poly.end(); } @@ -303,7 +303,7 @@ bool polygon_soup_snap_rounding_(PointRange &points, #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "End of the snapping" << std::endl; #endif - CGAL_assertion(!does_triangle_soup_self_intersect(points, triangles, np)); + CGAL_assertion(!does_triangle_soup_self_intersect(points, triangles)); if constexpr(has_visitor) { std::vector > map_io(number_of_input_triangles); From 32f07e7d7afd35af65408ad588bb972de331dc54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 19 Mar 2025 11:12:13 +0100 Subject: [PATCH 031/113] Move the mutex inside the class Indexes_range who using it --- .../internal/triangle_soup_snap_rounding.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index da6790e4e5c..ec0be216dc8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -69,8 +69,6 @@ double double_ceil(NT x){ } }; -CGAL_MUTEX map_mutex; - template class Indexes_range{ typedef std::remove_cv_t::value_type> Value_type; @@ -129,6 +127,7 @@ struct Wrapp_id_visitor private: PolygonRange* triangles; Map* map_newtriangles; + inline static CGAL_MUTEX map_mutex; }; /** From fddc0aa4002150fcf05bc70cf66577f3a5e2d9c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 19 Mar 2025 11:35:42 +0100 Subject: [PATCH 032/113] Change name of internal functions --- .../Polygon_mesh_processing/autorefinement.h | 5 +++-- .../internal/triangle_soup_snap_rounding.h | 22 +++++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) 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 95ca157a4f1..d48c95b029b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -986,7 +986,7 @@ template class Indexes_range; template -bool autorefine_triangle_soup_(PointRange& soup_points, +bool autorefine_triangle_soup(PointRange& soup_points, TriangleRange& soup_triangles, const NamedParameters& np = parameters::default_values()) { @@ -1690,6 +1690,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, using parameters::choose_parameter; using parameters::get_parameter; + //Dispatch the execution according the apply_iterative_snap_rounding parameter const bool do_snap = choose_parameter(get_parameter(np, internal_np::apply_iterative_snap_rounding), false); if(do_snap) { @@ -1698,7 +1699,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, } else { - return internal::autorefine_triangle_soup_(soup_points, soup_triangles, np); + return internal::autorefine_triangle_soup(soup_points, soup_triangles, np); } } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index ec0be216dc8..2d6a03e2a6a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -182,9 +182,9 @@ private: * able to provide such a triangle soup within the number of iterations. */ template -bool polygon_soup_snap_rounding_(PointRange &points, - PolygonRange &triangles, - const NamedParameters& np) +bool polygon_soup_snap_rounding_impl(PointRange &points, + PolygonRange &triangles, + const NamedParameters& np) { using parameters::choose_parameter; using parameters::get_parameter; @@ -497,14 +497,14 @@ bool polygon_soup_snap_rounding_(PointRange &points, std::map > map_newtriangles; #endif Wrapp_id_visitor visitor(&triangles, &map_newtriangles); - autorefine_triangle_soup_(points, triangles, parameters::point_map(pm).concurrency_tag(Concurrency_tag()).visitor(visitor)); + autorefine_triangle_soup(points, triangles, parameters::point_map(pm).concurrency_tag(Concurrency_tag()).visitor(visitor)); for(auto &pair: map_newtriangles) for(size_t new_id: pair.second) triangles[new_id].set_id(pair.first); } else { - autorefine_triangle_soup_(points, triangles, parameters::point_map(pm).concurrency_tag(Concurrency_tag())); + autorefine_triangle_soup(points, triangles, parameters::point_map(pm).concurrency_tag(Concurrency_tag())); } } return false; @@ -512,24 +512,28 @@ bool polygon_soup_snap_rounding_(PointRange &points, template bool polygon_soup_snap_rounding(PointRange &soup_points, - PolygonRange &soup_triangles, - const NamedParameters& np) + PolygonRange &soup_triangles, + const NamedParameters& np) { typedef typename internal_np::Lookup_named_param_def < internal_np::visitor_t, NamedParameters, Autorefinement::Default_visitor//default > ::type Visitor; + constexpr bool has_visitor = !std::is_same_v; if constexpr(has_visitor) { + //If a visitor is provided, we color the triangles with the index of their source to correctly track the modification using Triangle = std::remove_cv_t::value_type>; std::vector > indexes_soup_triangles; size_t id=0; for(typename PolygonRange::iterator it=soup_triangles.begin(); it!=soup_triangles.end(); ++it) indexes_soup_triangles.emplace_back((*it), id++); std::cout << "Test 0" << std::endl; - bool res=polygon_soup_snap_rounding_(soup_points, indexes_soup_triangles, np); + + bool res=polygon_soup_snap_rounding_impl(soup_points, indexes_soup_triangles, np); + soup_triangles.clear(); for(const Indexes_range &t: indexes_soup_triangles) soup_triangles.push_back({t[0],t[1],t[2]}); @@ -537,7 +541,7 @@ bool polygon_soup_snap_rounding(PointRange &soup_points, } else { - return polygon_soup_snap_rounding_(soup_points, soup_triangles, np); + return polygon_soup_snap_rounding_impl(soup_points, soup_triangles, np); } } From d48a00306923cf7612635d8eaff718d6f8067e00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Thu, 3 Apr 2025 10:26:22 +0200 Subject: [PATCH 033/113] Solve bug with macro that skip repair_polygon_soup --- .../Polygon_mesh_processing/snap_polygon_soup.cpp | 2 +- .../internal/triangle_soup_snap_rounding.h | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) 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 81e596ceb6b..b6f443f3a67 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 @@ -105,7 +105,7 @@ int main(int argc, char** argv) CGAL::Real_timer t; t.start(); -#if 1 +#if 0 Track_visitor visitor; bool success=PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).visitor(visitor)); #else diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 2d6a03e2a6a..8bff8c7ecc7 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -287,10 +287,10 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, } ); } else -#else +#endif for (Point_3 &p : points) p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); -#endif + repair_polygon_soup(points, triangles, np); // Get all intersecting triangles @@ -372,14 +372,14 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, } ); } else -#else +#endif for (Point_3 &p : points) { Point_3 p_snap = snap_p(p); if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) p = p_snap; } -#endif + #elif 1 // Version where points in a voxel are rounded to the closest point @@ -530,7 +530,6 @@ bool polygon_soup_snap_rounding(PointRange &soup_points, size_t id=0; for(typename PolygonRange::iterator it=soup_triangles.begin(); it!=soup_triangles.end(); ++it) indexes_soup_triangles.emplace_back((*it), id++); - std::cout << "Test 0" << std::endl; bool res=polygon_soup_snap_rounding_impl(soup_points, indexes_soup_triangles, np); From 80265d0e54b6adc379262472ca7045e12c1f153c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Thu, 3 Apr 2025 11:42:31 +0200 Subject: [PATCH 034/113] factorize snap_polygon_soup --- .../snap_polygon_soup.cpp | 86 +++++++------------ 1 file changed, 33 insertions(+), 53 deletions(-) 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 b6f443f3a67..6fd64832d32 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,4 +1,4 @@ -#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE +// #define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE // #define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE #include @@ -37,61 +37,17 @@ struct Track_visitor inline void delete_triangle(std::size_t /*src_id*/) {} }; -int main(int argc, char** argv) -{ - const std::string filename = argc == 1 ? CGAL::data_file_path("meshes/elephant.off") - : std::string(argv[1]); - - // const std::string out_file = argc <= 2 ? "rounded_soup.off" - // : std::string(argv[2]); - const std::string out_file = "rounded_soup.off"; - - const int grid_size = argc <= 2 ? 23 - : std::stoi(std::string(argv[2])); - - const bool epeck = argc <= 3 ? false - : std::string(argv[3])=="EPECK"; - - if(epeck) - { - std::vector input_points; +template +struct Example{ + void operator()(const std::string& filename, int grid_size){ + const std::string out_file = "rounded_soup.off"; + std::vector input_points; std::vector> input_triangles; - - std::cout << "Snap rounding apply on " << filename << " with EPECK\n"; + std::cout << "Snap rounding on " << filename << " with " << typeid(Kernel).name() << "\n"; if (!CGAL::IO::read_polygon_soup(filename, input_points, input_triangles)) { std::cerr << "Cannot read " << filename << "\n"; - return 1; - } - std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << std::endl; - std::cout << "Is 2-manifold: " << PMP::is_polygon_soup_a_polygon_mesh(input_triangles) << std::endl; - - PMP::repair_polygon_soup(input_points, input_triangles); - PMP::triangulate_polygons(input_points, input_triangles); - - CGAL::Real_timer t; - t.start(); - PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(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::cout << "Does self-intersect: " << PMP::does_triangle_soup_self_intersect(input_points, input_triangles) << std::endl; - std::cout << "Is 2-manifold: " << PMP::orient_polygon_soup(input_points, input_triangles) << "\n\n" << std::endl; - - std::vector output_points; - 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(out_file, output_points, input_triangles, CGAL::parameters::stream_precision(17)); - } - else - { - std::vector input_points; - std::vector> input_triangles; - std::cout << "Snap rounding on " << filename << " with EPICK\n"; - if (!CGAL::IO::read_polygon_soup(filename, input_points, input_triangles)) - { - std::cerr << "Cannot read " << filename << "\n"; - return 1; + return; } std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << std::endl; std::cout << "Is 2-manifold: " << PMP::is_polygon_soup_a_polygon_mesh(input_triangles) << std::endl; @@ -118,8 +74,32 @@ int main(int argc, char** argv) std::cout << "Does self-intersect: " << PMP::does_triangle_soup_self_intersect(input_points, input_triangles) << std::endl; else std::cout << "ROUNDING FAILED" << std::endl; - CGAL::IO::write_polygon_soup(out_file, input_points, input_triangles, CGAL::parameters::stream_precision(17)); + + std::vector output_points; + 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(out_file, output_points, input_triangles, CGAL::parameters::stream_precision(17)); std::cout << "Is 2-manifold: " << PMP::orient_polygon_soup(input_points, input_triangles) << "\n\n" << std::endl; } +}; + +int main(int argc, char** argv) +{ + const std::string filename = argc == 1 ? CGAL::data_file_path("meshes/elephant.off") + : std::string(argv[1]); + + // const std::string out_file = argc <= 2 ? "rounded_soup.off" + // : std::string(argv[2]); + + const int grid_size = argc <= 2 ? 23 + : std::stoi(std::string(argv[2])); + + const bool epeck = argc <= 3 ? false + : std::string(argv[3])=="EPECK"; + + if(epeck) + Example()(filename, grid_size); + else + Example()(filename, grid_size); return 0; } From a2a76cf874c3549257920808444631fa9f38186b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Thu, 3 Apr 2025 14:31:04 +0200 Subject: [PATCH 035/113] add zhou and naive version --- .../Polygon_mesh_processing/snap_polygon_soup.cpp | 1 + .../internal/triangle_soup_snap_rounding.h | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) 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 6fd64832d32..40714d169bc 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,5 +1,6 @@ // #define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE // #define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE +// TODO delete those verbose line macro before release #include #include diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 8bff8c7ecc7..343c2118150 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -381,7 +381,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, } -#elif 1 +#elif 0 // Version where points in a voxel are rounded to the closest point // Group the points of the vertices of the intersecting triangles by their voxel @@ -430,7 +430,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, } } -#else +#elif 0 // Version where points in a voxel are rounded to their barycenter. // Group the points of the vertices of the intersecting triangles by their voxel @@ -479,6 +479,16 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, } } } +#elif 0 //Zhou et al. version with round on float + for (auto &pair : pairs_of_intersecting_triangles) + { + for (size_t pi : triangles[pair.first]) + points[pi]=Point_3( (float) to_double(points[pi].x()), (float) to_double(points[pi].y()), (float) to_double(points[pi].z())); + for (size_t pi : triangles[pair.second]) + points[pi]=Point_3( (float) to_double(points[pi].x()), (float) to_double(points[pi].y()), (float) to_double(points[pi].z())); + } +#else //Naive version + //Nothing #endif From a28b294f0818c045eac641443d4e94d3706db335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Thu, 3 Apr 2025 15:14:48 +0200 Subject: [PATCH 036/113] add internal_new_subtriangle to Visistor of autorefinement --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 7 +++++++ .../internal/triangle_soup_snap_rounding.h | 5 +---- 2 files changed, 8 insertions(+), 4 deletions(-) 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 d48c95b029b..0ba1c28cdc1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -90,6 +90,10 @@ struct Default_visitor inline void verbatim_triangle_copy(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} inline void new_subtriangle(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} inline void delete_triangle(std::size_t /*src_id*/) {} + + // Not documented + template< typename Triangle> + inline void internal_new_subtriangle(Triangle& /*new_t*/ , const Triangle& /*old_t*/) {} }; } // end of Autorefinement visitor @@ -1505,6 +1509,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, { triangle_buffer[ti][0]->second, triangle_buffer[ti][1]->second, triangle_buffer[ti][2]->second }; + visitor.new_subtriangle(soup_triangles_out[offset + ti], soup_triangle[tri_inter_ids_inverse[new_triangles[ti].second]]); } } ); @@ -1562,6 +1567,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, { triangle_buffer[ti][0]->second, triangle_buffer[ti][1]->second, triangle_buffer[ti][2]->second }; + visitor.internal_new_subtriangle(soup_triangles_out[offset + ti], soup_triangles[tri_inter_ids_inverse[new_triangles[ti].second]]); } } ); @@ -1580,6 +1586,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, soup_triangles_out.push_back({ get_point_id(t_and_id.first[0]), get_point_id(t_and_id.first[1]), get_point_id(t_and_id.first[2]) }); + visitor.internal_new_subtriangle(soup_triangles_out[soup_triangles_out.size()-1], soup_triangles[tri_inter_ids_inverse[t_and_id.second]]); } } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 343c2118150..5af08f455e8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -112,17 +112,14 @@ private: }; template -struct Wrapp_id_visitor +struct Wrapp_id_visitor : public Autorefinement::Default_visitor { Wrapp_id_visitor(PolygonRange* tr, Map* map):triangles(tr), map_newtriangles(map){} - inline void number_of_output_triangles(std::size_t /*nbt*/) {} - inline void verbatim_triangle_copy(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} inline void new_subtriangle(std::size_t tgt_id, std::size_t src_id) { CGAL_SCOPED_LOCK(map_mutex); (*map_newtriangles)[(*triangles)[src_id].id()].push_back(tgt_id); } - inline void delete_triangle(std::size_t /*src_id*/) {} private: PolygonRange* triangles; From 9055d56e1fd748eb283a1787ccb8c6596e90bef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Thu, 3 Apr 2025 18:40:51 +0200 Subject: [PATCH 037/113] use the new internal function of the visitor of autorefinement for the wrapp_visitor of snap_rounding --- .../snap_polygon_soup.cpp | 6 +- .../internal/triangle_soup_snap_rounding.h | 78 +++++++------------ 2 files changed, 33 insertions(+), 51 deletions(-) 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 40714d169bc..29d15359250 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,4 +1,4 @@ -// #define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE +#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE // #define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE // TODO delete those verbose line macro before release @@ -23,7 +23,7 @@ typedef CGAL::Simple_cartesian Cartesian; namespace PMP = CGAL::Polygon_mesh_processing; -struct Track_visitor +struct Track_visitor : PMP::Autorefinement::Default_visitor { // inline void number_of_output_triangles(std::size_t nbt) { std::cout << "total number of triangles: " << nbt << std::endl;} inline void number_of_output_triangles(std::size_t /*nbt*/) {} @@ -62,7 +62,7 @@ struct Example{ CGAL::Real_timer t; t.start(); -#if 0 +#if 1 Track_visitor visitor; bool success=PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).visitor(visitor)); #else diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 5af08f455e8..fa7b2062dc1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -70,61 +70,54 @@ double double_ceil(NT x){ }; template -class Indexes_range{ +class Indexes_range : public Range{ typedef std::remove_cv_t::value_type> Value_type; public: typedef typename Range::const_iterator const_iterator; typedef typename Range::iterator iterator; Indexes_range(){} - Indexes_range(std::initializer_list l): poly(l), m_id(0), modified(true){} - Indexes_range(const Indexes_range &ir):poly(ir.range()), m_id(ir.id()), modified(ir.was_modified()){} - Indexes_range(Range &p):poly(p), modified(true){} - Indexes_range(Range &p, size_t id):poly(p), m_id(id),modified(false){} + Indexes_range(std::initializer_list l): Range(l), m_id(0), modified(true){} + Indexes_range(const Indexes_range &ir): Range(ir), m_id(ir.id()), modified(ir.was_modified()){} + Indexes_range(Range &p): Range(p), modified(true){} + Indexes_range(Range &p, size_t id): Range(p), m_id(id),modified(false){} - void operator=(std::initializer_list l) + void operator=(const Indexes_range &ir) { - poly=l; - modified=true; + Range::operator=(ir); + modified=ir.was_modified(); + m_id=ir.id(); } inline size_t id() const { return m_id; } inline void set_id(size_t id){ m_id=id; } inline bool was_modified() const { return modified; } - inline size_t size() const{ return poly.size(); } - - inline iterator begin(){ return poly.begin(); } - inline iterator end(){ return poly.end(); } - inline const_iterator begin() const{ return poly.begin(); } - inline const_iterator end() const{ return poly.end(); } - - inline Value_type operator[](size_t i){ return poly[i]; } - inline const Value_type operator[](size_t i) const{ return poly[i]; } - - inline void push_back(Value_type v){ poly.push_back(v);} - inline Range range(){ return poly;} - inline const Range range() const{ return poly;} private: - Range poly; size_t m_id; bool modified; }; -template +//repair_polygon_soup for triangles +template ::Polygon_3, + typename NamedParameters> +void repair_triangle_soup(PointRange& points, + PolygonRange& polygons, + const NamedParameters& np) +{ + merge_duplicate_points_in_polygon_soup(points, polygons, np); + remove_invalid_polygons_in_polygon_soup(points, polygons); + merge_duplicate_polygons_in_polygon_soup(points, polygons, np); + remove_isolated_points_in_polygon_soup(points, polygons); +} + struct Wrapp_id_visitor : public Autorefinement::Default_visitor { - Wrapp_id_visitor(PolygonRange* tr, Map* map):triangles(tr), map_newtriangles(map){} - inline void new_subtriangle(std::size_t tgt_id, std::size_t src_id) - { - CGAL_SCOPED_LOCK(map_mutex); - (*map_newtriangles)[(*triangles)[src_id].id()].push_back(tgt_id); + template< typename Triangle> + inline void internal_new_subtriangle(Triangle& new_t, const Triangle& old_t) { + new_t.set_id(old_t.id()); } - -private: - PolygonRange* triangles; - Map* map_newtriangles; - inline static CGAL_MUTEX map_mutex; }; /** @@ -288,7 +281,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, for (Point_3 &p : points) p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); - repair_polygon_soup(points, triangles, np); + repair_triangle_soup(points, triangles, np); // Get all intersecting triangles std::vector> pairs_of_intersecting_triangles; @@ -312,7 +305,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, if(map_io[src_id].size()==0) visitor.delete_triangle(src_id); else if(map_io[src_id].size()==1 && !triangles[map_io[src_id][0]].was_modified()) - visitor.verbatim_triangle_copy(map_io[src_id][0],src_id); + visitor.verbatim_triangle_copy(map_io[src_id][0],src_id); else for(size_t new_id: map_io[src_id]) visitor.new_subtriangle(new_id,src_id); @@ -488,26 +481,15 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, //Nothing #endif - - repair_polygon_soup(points, triangles, np); + repair_triangle_soup(points, triangles, np); #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; #endif if constexpr(has_visitor) { -#ifdef CGAL_LINKED_WITH_TBB - std::conditional_t >, - std::map > > map_newtriangles; -#else - std::map > map_newtriangles; -#endif - Wrapp_id_visitor visitor(&triangles, &map_newtriangles); + Wrapp_id_visitor visitor; autorefine_triangle_soup(points, triangles, parameters::point_map(pm).concurrency_tag(Concurrency_tag()).visitor(visitor)); - for(auto &pair: map_newtriangles) - for(size_t new_id: pair.second) - triangles[new_id].set_id(pair.first); } else { From 3cdcc73201fef11d1773721bb0d3c732d2e09c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Thu, 3 Apr 2025 19:32:13 +0200 Subject: [PATCH 038/113] clone test_autorefinement.cmd to test_snap_rounding.cpp to test snap_rounding --- .../Polygon_mesh_processing/CMakeLists.txt | 1 + .../test_autorefinement.cpp | 2 +- .../test_snap_rounding.cpp | 181 ++++++++++++++++++ 3 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index 1e442ae768f..db8aa3c1efe 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -42,6 +42,7 @@ create_single_source_cgal_program("test_coref_epic_points_identity.cpp") create_single_source_cgal_program("test_does_bound_a_volume.cpp") create_single_source_cgal_program("test_pmp_clip.cpp") create_single_source_cgal_program("test_autorefinement.cpp") +create_single_source_cgal_program("test_snap_rounding.cpp") create_single_source_cgal_program("autorefinement_sm.cpp") create_single_source_cgal_program( "corefine_non_manifold.cpp" ) create_single_source_cgal_program("triangulate_hole_polyline_test.cpp") diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_autorefinement.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_autorefinement.cpp index a265be44b8e..e67dc15a4d8 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_autorefinement.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_autorefinement.cpp @@ -30,7 +30,7 @@ struct My_exp_visitor : std::shared_ptr i; }; -struct My_visitor +struct My_visitor : public PMP::Autorefinement::Default_visitor { My_visitor(std::size_t nb_input, std::size_t expected_nb_output) : nb_input(nb_input) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp new file mode 100644 index 00000000000..76d806a50fc --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp @@ -0,0 +1,181 @@ + +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Surface_mesh Mesh; + +namespace PMP = CGAL::Polygon_mesh_processing; + +template +struct My_exp_visitor : + public CGAL::Polygon_mesh_processing::Corefinement::Default_visitor +{ + void after_subface_creations(TriangleMesh&){++(*i);} + + My_exp_visitor() + : i (new int(0) ) + {} + + std::shared_ptr i; +}; + +struct My_visitor : public PMP::Autorefinement::Default_visitor +{ + My_visitor(std::size_t nb_input, std::size_t expected_nb_output) + : nb_input(nb_input) + , expected_nb_output(expected_nb_output) + {} + + ~My_visitor() + { + for(std::size_t i=0; i tgt_check; +}; + +void test_coref_based(const char* fname, std::size_t nb_polylines, std::size_t total_nb_points, + std::size_t nb_vertices_after_autorefine, bool all_fixed, std::size_t nb_vertices_after_fix, + bool triple_intersection) +{ + std::cout << "Running tests (coref based) on " << fname << "\n"; + std::ifstream input(fname); + + Mesh mesh; + if (!input || !(input >> mesh)) + { + std::cerr << " Input mesh is not a valid off file." << std::endl; + exit(EXIT_FAILURE); + } + input.close(); + std::size_t nb_vertices_before_autorefine = num_vertices(mesh); + +// Testing PMP::experimental::surface_self_intersection() + try{ + std::vector< std::vector >polylines; + PMP::experimental::surface_self_intersection(mesh, std::back_inserter(polylines)); + assert(polylines.size() == nb_polylines); + std::size_t total_nb_pt=0; + for(const std::vector& polyline : polylines) + total_nb_pt+=polyline.size(); + assert(total_nb_points == total_nb_pt); + assert( !triple_intersection ); + } + catch(const PMP::Corefinement::Triple_intersection_exception&) + { + assert( triple_intersection ); + } + +// Testing PMP::experimental::autorefine() + try{ + My_exp_visitor visitor; + PMP::experimental::autorefine(mesh, + CGAL::parameters::visitor(visitor)); + mesh.collect_garbage(); + assert( nb_vertices_after_autorefine==num_vertices(mesh)); + assert( (nb_vertices_before_autorefine!=nb_vertices_after_autorefine)== (*(visitor.i) != 0) ); + assert( !triple_intersection ); + } + catch(const PMP::Corefinement::Triple_intersection_exception&) + { + assert( triple_intersection ); + } + +// Testing PMP::experimental::autorefine_and_remove_self_intersections() + try{ + input.open(fname); + mesh.clear(); + input >> mesh; + bool res=PMP::experimental::autorefine_and_remove_self_intersections(mesh); + assert(res==all_fixed); + mesh.collect_garbage(); + assert( nb_vertices_after_fix==num_vertices(mesh)); + assert( !triple_intersection ); + } + catch(const PMP::Corefinement::Triple_intersection_exception&) + { + assert( triple_intersection ); + } +} + +template +void test(const char* fname, std::size_t nb_vertices_after_autorefine, std::size_t expected_nb_output, Tag tag) +{ + std::cout << "Running tests on " << fname; + if (std::is_same_v) + std::cout << " (Sequential)\n"; + else + std::cout << " (Parallel)\n"; + + std::vector points; + std::vector< std::vector > triangles; + if (!CGAL::IO::read_polygon_soup(fname, points, triangles)) + { + std::cerr << " Input mesh is not a valid file." << std::endl; + exit(EXIT_FAILURE); + } + +// Testing autorefine() + My_visitor visitor(triangles.size(), expected_nb_output); + PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::visitor(visitor).concurrency_tag(tag).apply_iterative_snap_rounding(true)); + assert( nb_vertices_after_autorefine==points.size()); + assert( expected_nb_output==triangles.size()); + assert( !PMP::does_triangle_soup_self_intersect(points, triangles) ); +// CGAL::IO::write_polygon_soup("/tmp/debug.off", points, triangles); +} + +int main(int argc, const char** argv) +{ + // file nb_polylines total_nb_points nb_vertices_after_autorefine all_fixed nb_vertices_after_fix triple_intersection + for (int i=0;i<(argc-1)/9; ++i) + { + test_coref_based(argv[1+9*i], atoi(argv[1+9*i+1]), atoi(argv[1+9*i+2]), + atoi(argv[1+9*i+3]), atoi(argv[1+9*i+4])==0?false:true, atoi(argv[1+9*i+5]), atoi(argv[1+9*i+6])==0?false:true); + test(argv[1+9*i], atoi(argv[1+9*i+7]), atoi(argv[1+9*i+8]), CGAL::Sequential_tag()); +#ifdef CGAL_LINKED_WITH_TBB + test(argv[1+9*i], atoi(argv[1+9*i+7]), atoi(argv[1+9*i+8]), CGAL::Parallel_tag()); +#endif + } +} From 2cf7cef9123b9d6d042890a82da333af3c09bbc7 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 8 Apr 2025 10:39:53 +0200 Subject: [PATCH 039/113] Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h Co-authored-by: Sebastien Loriot --- .../Concepts/PMPAutorefinementVisitor.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h index c7494db4879..7b4ef6a1c9d 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h @@ -23,8 +23,7 @@ public: /// called for each subtriangle created from a triangle with intersection, `tgt_id` is the position in the triangle container after calling /// `autorefine_triangle_soup()` of the subtriangle, while `src_id` was the position of the original support triangle before calling the function. void new_subtriangle(std::size_t tgt_id, std::size_t src_id); - /// called for each triangle delete because it was or became degenerated, `src_id` was its position before calling `autorefine_triangle_soup()`. - /// A triangle may degenerate inside `autorefine_triangle_soup()` if and only if `apply_iterative_snap_rounding` is set to `true`. + /// called for each input triangle deleted because it was degenerated, `src_id` was the position of the original support triangle before calling the function. Additionally, if `apply_iterative_snap_rounding()` is set to `true`, some extra triangle might become degenerated and will be absent from the output range of triangles. Those triangles are also reported in this function. void delete_triangle(std::size_t src_id); /// @} }; From f588a1506b2bfcf63175c473d29798005576fda1 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 8 Apr 2025 10:52:05 +0200 Subject: [PATCH 040/113] Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt Co-authored-by: Sebastien Loriot --- .../doc/Polygon_mesh_processing/Polygon_mesh_processing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index 43110b1285c..64d202af9da 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -4,7 +4,7 @@ namespace CGAL { \anchor Chapter_PolygonMeshProcessing \cgalAutoToc -\authors David Coeurjolly, Jaques-Olivier Lachaud, Sylvain Lazard, Konstantinos Katrioplas, Sébastien Loriot, Ivan Pađen, Mael Rouxel-Labbé, Hossam Saeed, Jane Tournois, Léo Valque and Ilker %O. Yaz +\authors David Coeurjolly, Jaques-Olivier Lachaud, Konstantinos Katrioplas, Sébastien Loriot, Ivan Pađen, Mael Rouxel-Labbé, Hossam Saeed, Jane Tournois, Léo Valque and Ilker %O. Yaz \image html neptun_head.jpg \image latex neptun_head.jpg From 26de563455203e2826613d560dad35b0e8b7f5e2 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 8 Apr 2025 10:52:18 +0200 Subject: [PATCH 041/113] Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt Co-authored-by: Sebastien Loriot --- .../doc/Polygon_mesh_processing/Polygon_mesh_processing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index 64d202af9da..c0ae3307054 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -1452,7 +1452,7 @@ used as a reference during the project. The curvature-based sizing field version of isotropic remeshing was added by Ivan Pađen during GSoC 2023, under the supervision of Sébastien Loriot and Jane Tournois. -The `apply_iterative_snap_rounding` option for autorefinement were implemented during 2025. This was implemented by Léo Valque and Sylvain Lazard. The implementation is based on \cgalCite{lazard:hal-04907149}. +The `apply_iterative_snap_rounding` option for autorefinement was implemented in 2025, by Léo Valque, based on his work with Sylvain Lazard \cgalCite{lazard:hal-04907149}. */ } /* namespace CGAL */ From cb7bc4f64d95f8a6a73d86e012ca137fac74b524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 8 Apr 2025 10:37:02 +0200 Subject: [PATCH 042/113] use macro to define snap version --- .../snap_polygon_soup.cpp | 2 + .../internal/triangle_soup_snap_rounding.h | 105 +++++++++--------- 2 files changed, 54 insertions(+), 53 deletions(-) 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 29d15359250..a3a2d3d0ff1 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,5 +1,7 @@ #define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE // #define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE +// #define PMP_ROUNDING_VERTICES_NAIVE_SNAP +// #define PMP_ROUNDING_VERTICES_FLOAT_SNAP // TODO delete those verbose line macro before release #include diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index fa7b2062dc1..bafab19a41e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -322,56 +322,10 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, std::cout << "Snap the coordinates of the vertices of the intersecting triangles" << std::endl; #endif -#if 1 - // Version where points are rounded to the center of their voxel. +#if defined(PMP_ROUNDING_VERTICES_NAIVE_SNAP) + // Nothing - // Get all the snap version of the points of the vertices of the intersecting triangles - // Note: points will not be modified here, they will be modified in the next for loop - - //TODO: TBB version of this for loop - - std::vector snap_points; - snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); - - for (auto &pair : pairs_of_intersecting_triangles) - { - for (size_t pi : triangles[pair.first]) - snap_points.emplace_back(snap_p(points[pi])); - for (size_t pi : triangles[pair.second]) - snap_points.emplace_back(snap_p(points[pi])); - } - -#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE - std::cout << "Snap the coordinates of the vertices close-by the previous ones" << std::endl; -#endif - - std::sort(snap_points.begin(), snap_points.end()); - snap_points.erase(std::unique(snap_points.begin(), snap_points.end()), snap_points.end()); - - // If the snapped version of a point correspond to one of the previous point, we snap it -#ifdef CGAL_LINKED_WITH_TBB - if constexpr(parallel_execution) - { - tbb::parallel_for(tbb::blocked_range(0, points.size()), - [&](const tbb::blocked_range& r){ - for(size_t pi = r.begin(); pi != r.end(); ++pi){ - Point_3 p_snap=snap_p(points[pi]); - if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) - points[pi] = p_snap; - } - } - ); - } else -#endif - for (Point_3 &p : points) - { - Point_3 p_snap = snap_p(p); - if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) - p = p_snap; - } - - -#elif 0 +#elif defined(PMP_ROUNDING_VERTICES_CLOSEST_POINT_SNAP) // Version where points in a voxel are rounded to the closest point // Group the points of the vertices of the intersecting triangles by their voxel @@ -420,7 +374,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, } } -#elif 0 +#elif defined(PMP_ROUNDING_VERTICES_BARYCENTER_SNAP) // Version where points in a voxel are rounded to their barycenter. // Group the points of the vertices of the intersecting triangles by their voxel @@ -469,7 +423,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, } } } -#elif 0 //Zhou et al. version with round on float +#elif defined(PMP_ROUNDING_VERTICES_FLOAT_SNAP) for (auto &pair : pairs_of_intersecting_triangles) { for (size_t pi : triangles[pair.first]) @@ -477,8 +431,53 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, for (size_t pi : triangles[pair.second]) points[pi]=Point_3( (float) to_double(points[pi].x()), (float) to_double(points[pi].y()), (float) to_double(points[pi].z())); } -#else //Naive version - //Nothing +#else // Default Version + // Version where points are rounded to the center of their voxel. + + // Get all the snap version of the points of the vertices of the intersecting triangles + // Note: points will not be modified here, they will be modified in the next for loop + + //TODO: TBB version of this for loop + + std::vector snap_points; + snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); + + for (auto &pair : pairs_of_intersecting_triangles) + { + for (size_t pi : triangles[pair.first]) + snap_points.emplace_back(snap_p(points[pi])); + for (size_t pi : triangles[pair.second]) + snap_points.emplace_back(snap_p(points[pi])); + } + +#ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE + std::cout << "Snap the coordinates of the vertices close-by the previous ones" << std::endl; +#endif + + std::sort(snap_points.begin(), snap_points.end()); + snap_points.erase(std::unique(snap_points.begin(), snap_points.end()), snap_points.end()); + + // If the snapped version of a point correspond to one of the previous point, we snap it +#ifdef CGAL_LINKED_WITH_TBB + if constexpr(parallel_execution) + { + tbb::parallel_for(tbb::blocked_range(0, points.size()), + [&](const tbb::blocked_range& r){ + for(size_t pi = r.begin(); pi != r.end(); ++pi){ + Point_3 p_snap=snap_p(points[pi]); + if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) + points[pi] = p_snap; + } + } + ); + } else +#endif + for (Point_3 &p : points) + { + Point_3 p_snap = snap_p(p); + if (std::binary_search(snap_points.begin(), snap_points.end(), p_snap)) + p = p_snap; + } #endif repair_triangle_soup(points, triangles, np); From 09f7df81275bd68bd9e71a70e19cf5e72ce8fb26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 8 Apr 2025 10:52:40 +0200 Subject: [PATCH 043/113] add missing reserve for the visitor --- .../internal/triangle_soup_snap_rounding.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index bafab19a41e..86115e6717c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -522,6 +522,7 @@ bool polygon_soup_snap_rounding(PointRange &soup_points, bool res=polygon_soup_snap_rounding_impl(soup_points, indexes_soup_triangles, np); soup_triangles.clear(); + soup_triangles.reserve(indexes_soup_triangles.size()); for(const Indexes_range &t: indexes_soup_triangles) soup_triangles.push_back({t[0],t[1],t[2]}); return res; From e2a1c276fc8e3ca23660dce1b9c93527e78b091f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Fri, 25 Apr 2025 17:20:17 +0200 Subject: [PATCH 044/113] Experiment with iterative rotated around x cubes --- .../coplanar_cubes_autorefinement.cpp | 135 ++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp new file mode 100644 index 00000000000..af178634597 --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp @@ -0,0 +1,135 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef Kernel K; +typedef CGAL::Surface_mesh Mesh; +typedef K::Point_3 Point_3; + +typedef CGAL::Simple_cartesian Cartesian; +typedef Cartesian::Point_3 Double_Point_3; + +namespace PMP = CGAL::Polygon_mesh_processing; +namespace params = CGAL::parameters; + +struct Sphere_function { + double radius; + Sphere_function(double r) : radius(r) {} + Kernel::FT operator()(const Kernel::Point_3& p) const { + return p.x()*p.x() + p.y()*p.y() + p.z()*p.z() - radius*radius; + } +}; + +//Thanks Roberto! +K::Aff_transformation_3 +random_rotation(CGAL::Random &gen) +{ + double a=gen.get_double(0,2*CGAL_PI); + + double ca = cos(a); + double sa = sin(a); + + K::Aff_transformation_3 aff(1, 0, 0, + 0, ca,-sa, + 0, sa, ca); + std::cout << "Rotation by " << a << std::endl; + return aff; +} + +int main(int argc, char** argv) +{ + Mesh cube; + std::vector points; + std::vector> faces; + + CGAL::make_hexahedron( + Point_3(-1,-1,-1), + Point_3(1,-1,-1), + Point_3(1,1,-1), + Point_3(-1,1,-1), + Point_3(-1,1,1), + Point_3(-1,-1,1), + Point_3(1,-1,1), + Point_3(1,1,1), + cube, + CGAL::parameters::do_not_triangulate_faces(false) + ); + + std::cout << "Iterative intersection of rotative cubes with snapping" << std::endl; + + int i=0; + CGAL::Random random_gen = argc == 1 ? CGAL::get_default_random() : CGAL::Random(std::stoi(argv[1])); + + Mesh inter=cube; + while(true) + { + std::cout << "Iteration " << i << std::endl; + + CGAL::Real_timer t; + t.start(); + + std::cout << "Add a randomly rotated cube to the scene" << std::endl; + Mesh rotated_cube=cube; + PMP::transform(random_rotation(random_gen), rotated_cube); + + std::cout << "compute_intersection" << std::endl; + bool OK = PMP::corefine_and_compute_intersection(inter, rotated_cube, inter); + + if(!OK){ + std::cout << "No manifold, stop experiment" << std::endl; + exit(0); + } + + points.clear(); + faces.clear(); + PMP::polygon_mesh_to_polygon_soup(inter, points, faces); + + std::cout << "Snapped the points on double" << std::endl; + bool success=PMP::autorefine_triangle_soup(points, faces, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag())); + t.stop(); + if(!success){ + std::cout << "Round failed" << std::endl; + exit(0); + } + + //dump model every 100 iterations + if(i%100==0){ + std::cout << "Dump model" << std::endl; + std::vector double_points; + for(auto &p: points) + double_points.emplace_back(CGAL::to_double(p.x()),CGAL::to_double(p.y()),CGAL::to_double(p.z())); + std::ofstream outfile("cubes_"+std::to_string(i)+".off"); + outfile.precision(17); + outfile << "OFF\n" << points.size() << " " << faces.size() << " 0\n"; + for(auto p : points) + outfile << p.x() << " " << p.y() << " " << p.z() << std::endl; + + for(auto &t : faces) + outfile << "3" << " " << t[0] << " " << t[1] << " " << t[2] << std::endl; + outfile.close();// + } + + std::cout << "#points = " << points.size() << " and #triangles = " << faces.size() << " in " << t.time() << " sec.\n\n" << std::endl; + + inter.clear(); + PMP::polygon_soup_to_polygon_mesh(points, faces, inter); + ++i; + } + + return 0; +} + From 94eb667a9aa7fc67c92ace4608a4ce2e58f25820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Fri, 25 Apr 2025 17:21:07 +0200 Subject: [PATCH 045/113] Experiment with iterative rotated along all axis cubes --- .../rotated_cubes_autorefinement.cpp | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp new file mode 100644 index 00000000000..b0cfa6b15b9 --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp @@ -0,0 +1,137 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef Kernel K; +typedef CGAL::Surface_mesh Mesh; +typedef K::Point_3 Point_3; + +typedef CGAL::Simple_cartesian Cartesian; +typedef Cartesian::Point_3 Double_Point_3; + +namespace PMP = CGAL::Polygon_mesh_processing; +namespace params = CGAL::parameters; + +struct Sphere_function { + double radius; + Sphere_function(double r) : radius(r) {} + Kernel::FT operator()(const Kernel::Point_3& p) const { + return p.x()*p.x() + p.y()*p.y() + p.z()*p.z() - radius*radius; + } +}; + +//Thanks Roberto! +K::Aff_transformation_3 +random_rotation(CGAL::Random &gen) +{ + double a=gen.get_double(0,2*CGAL_PI); + double b=gen.get_double(0,2*CGAL_PI); + double c=gen.get_double(0,2*CGAL_PI); + + double ca = cos(a), cb = cos(b), cc = cos(c); + double sa = sin(a), sb = sin(b), sc = sin(c); + + K::Aff_transformation_3 aff(cb * cc, cc* sa* sb - ca * sc, ca* cc* sb + sa * sc, + cb* sc, ca* cc + sa * sb * sc, ca* sb* sc - cc * sa, + -sb, cb* sa, ca* cb); + std::cout << "Rotation by " << a << " " << b << " " << c << std::endl; + return aff; +} + +int main(int argc, char** argv) +{ + Mesh cube; + std::vector points; + std::vector> faces; + + CGAL::make_hexahedron( + Point_3(-1,-1,-1), + Point_3(1,-1,-1), + Point_3(1,1,-1), + Point_3(-1,1,-1), + Point_3(-1,1,1), + Point_3(-1,-1,1), + Point_3(1,-1,1), + Point_3(1,1,1), + cube, + CGAL::parameters::do_not_triangulate_faces(false) + ); + + std::cout << "Iterative intersection of rotative cubes with snapping" << std::endl; + + int i=0; + CGAL::Random random_gen = argc == 1 ? CGAL::get_default_random() : CGAL::Random(std::stoi(argv[1])); + + Mesh inter=cube; + while(true) + { + std::cout << "Iteration " << i << std::endl; + + CGAL::Real_timer t; + t.start(); + + std::cout << "Add a randomly rotated cube to the scene" << std::endl; + Mesh rotated_cube=cube; + PMP::transform(random_rotation(random_gen), rotated_cube); + + std::cout << "compute_intersection" << std::endl; + bool OK = PMP::corefine_and_compute_intersection(inter, rotated_cube, inter); + + if(!OK){ + std::cout << "No manifold, stop experiment" << std::endl; + exit(0); + } + + points.clear(); + faces.clear(); + PMP::polygon_mesh_to_polygon_soup(inter, points, faces); + + std::cout << "Snapped the points on double" << std::endl; + bool success=PMP::autorefine_triangle_soup(points, faces, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag())); + t.stop(); + if(!success){ + std::cout << "Round failed" << std::endl; + exit(0); + } + + //dump model every 100 iterations + if(i%100==0){ + std::cout << "Dump model" << std::endl; + std::vector double_points; + for(auto &p: points) + double_points.emplace_back(CGAL::to_double(p.x()),CGAL::to_double(p.y()),CGAL::to_double(p.z())); + std::ofstream outfile("cubes_"+std::to_string(i)+".off"); + outfile.precision(17); + outfile << "OFF\n" << points.size() << " " << faces.size() << " 0\n"; + for(auto p : points) + outfile << p.x() << " " << p.y() << " " << p.z() << std::endl; + + for(auto &t : faces) + outfile << "3" << " " << t[0] << " " << t[1] << " " << t[2] << std::endl; + outfile.close();// + } + + std::cout << "#points = " << points.size() << " and #triangles = " << faces.size() << " in " << t.time() << " sec.\n\n" << std::endl; + + inter.clear(); + PMP::polygon_soup_to_polygon_mesh(points, faces, inter); + ++i; + } + + return 0; +} + From b926bec8fafc4db2c7cd5a6181f71216d56c60b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Fri, 25 Apr 2025 17:23:01 +0200 Subject: [PATCH 046/113] remove visitor of example snap_polygon_soup --- .../snap_polygon_soup.cpp | 31 +------------------ 1 file changed, 1 insertion(+), 30 deletions(-) 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 a3a2d3d0ff1..8ec5e8bff86 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,9 +1,3 @@ -#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE -// #define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE -// #define PMP_ROUNDING_VERTICES_NAIVE_SNAP -// #define PMP_ROUNDING_VERTICES_FLOAT_SNAP -// TODO delete those verbose line macro before release - #include #include #include @@ -25,21 +19,6 @@ typedef CGAL::Simple_cartesian Cartesian; namespace PMP = CGAL::Polygon_mesh_processing; -struct Track_visitor : PMP::Autorefinement::Default_visitor -{ - // inline void number_of_output_triangles(std::size_t nbt) { std::cout << "total number of triangles: " << nbt << std::endl;} - inline void number_of_output_triangles(std::size_t /*nbt*/) {} - - // inline void verbatim_triangle_copy(std::size_t tgt_id, std::size_t src_id) { std::cout << src_id << " goes to " << tgt_id << std::endl;} - inline void verbatim_triangle_copy(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} - - // inline void new_subtriangle(std::size_t tgt_id, std::size_t src_id) { std::cout << src_id << " subdivides to " << tgt_id << std::endl;} - inline void new_subtriangle(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} - - // inline void delete_triangle(std::size_t src_id) { std::cout << src_id << " deleted" << std::endl;} - inline void delete_triangle(std::size_t /*src_id*/) {} -}; - template struct Example{ void operator()(const std::string& filename, int grid_size){ @@ -64,12 +43,7 @@ struct Example{ CGAL::Real_timer t; t.start(); -#if 1 - Track_visitor visitor; - bool success=PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).visitor(visitor)); -#else - bool success=PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15)); -#endif + bool success=PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(false).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15)); t.stop(); std::cout << "\nOutput:" << std::endl; std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << " in " << t.time() << " sec." << std::endl; @@ -91,9 +65,6 @@ int main(int argc, char** argv) const std::string filename = argc == 1 ? CGAL::data_file_path("meshes/elephant.off") : std::string(argv[1]); - // const std::string out_file = argc <= 2 ? "rounded_soup.off" - // : std::string(argv[2]); - const int grid_size = argc <= 2 ? 23 : std::stoi(std::string(argv[2])); From 32075dbdbad1aaac9f1a31dbce9b8aac9d0a798d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Fri, 25 Apr 2025 17:32:53 +0200 Subject: [PATCH 047/113] add data for snap rounding test --- .../data-snap/collapse_1.off | 16 ++ .../data-snap/collapse_2.off | 19 ++ .../data-snap/collapse_3.off | 19 ++ .../data-snap/coplanar_cubes.off | 202 +++++++++++++++++ .../data-snap/cubes.off | 204 ++++++++++++++++++ .../data-snap/intersection_when_rounded_1.off | 14 ++ .../data-snap/intersection_when_rounded_2.off | 15 ++ .../data-snap/intersection_when_rounded_3.off | 19 ++ .../data-snap/no_collapse_1.off | 16 ++ .../data-snap/no_collapse_2.off | 19 ++ 10 files changed, 543 insertions(+) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_1.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_2.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_3.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/coplanar_cubes.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/cubes.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_1.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_2.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_3.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/no_collapse_1.off create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/no_collapse_2.off diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_1.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_1.off new file mode 100644 index 00000000000..b0df88993a7 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_1.off @@ -0,0 +1,16 @@ +OFF +8 4 0 + +0 0 0 +0 1 0 +1 1 0 +1 0 0 +0 0 1 +0 1 1 +1 1 -1e-10 +1 0 -1e-10 +3 0 1 2 +3 0 2 3 +3 4 5 7 +3 5 6 7 + diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_2.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_2.off new file mode 100644 index 00000000000..212333059d3 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_2.off @@ -0,0 +1,19 @@ +OFF +12 4 0 + +-1 -1 -1 +-1 -1 1 +1 -1e-15 0 +-1 1 -1 +-1 1 1 +1 1e-15 0 +0 -1e-15 -1 +0 -1e-15 1 +0 -2 0 +0 1e-15 -1 +0 1e-15 1 +0 2 0 +3 0 1 2 +3 3 4 5 +3 6 7 8 +3 9 10 11 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_3.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_3.off new file mode 100644 index 00000000000..9e70e0d3303 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/collapse_3.off @@ -0,0 +1,19 @@ +OFF +12 4 0 + +-1 -1 -1 +-1 -1 1 +1 -1e-15 0 +1 1 -1 +1 1 1 +1 1e-15 0 +0 -1e-15 -1 +0 -1e-15 1 +0 -2 0 +0 1e-15 -1 +0 1e-15 1 +0 2 0 +3 0 1 2 +3 3 4 5 +3 6 7 8 +3 9 10 11 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/coplanar_cubes.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/coplanar_cubes.off new file mode 100644 index 00000000000..dfc01c0eea7 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/coplanar_cubes.off @@ -0,0 +1,202 @@ +OFF +80 120 0 +-1 -5.627423701743102e-06 1.4142135623618981 +1 -5.627423701743102e-06 1.4142135623618981 +1 -1.4142135623618981 -5.627423701743102e-06 +-1 -1.4142135623618981 -5.627423701743102e-06 +-1 5.627423701743102e-06 -1.4142135623618981 +-1 1.4142135623618981 5.627423701743102e-06 +1 1.4142135623618981 5.627423701743102e-06 +1 5.627423701743102e-06 -1.4142135623618981 +-1 -4.9339086289293424e-06 1.4142135623644878 +1 -4.9339086289293424e-06 1.4142135623644878 +1 -1.4142135623644878 -4.9339086289293424e-06 +-1 -1.4142135623644878 -4.9339086289293424e-06 +-1 4.9339086289293424e-06 -1.4142135623644878 +-1 1.4142135623644878 4.9339086289293424e-06 +1 1.4142135623644878 4.9339086289293424e-06 +1 4.9339086289293424e-06 -1.4142135623644878 +-1 -4.3072127542901049e-06 1.4142135623665355 +1 -4.3072127542901049e-06 1.4142135623665355 +1 -1.4142135623665355 -4.3072127542901049e-06 +-1 -1.4142135623665355 -4.3072127542901049e-06 +-1 4.3072127542901049e-06 -1.4142135623665355 +-1 1.4142135623665355 4.3072127542901049e-06 +1 1.4142135623665355 4.3072127542901049e-06 +1 4.3072127542901049e-06 -1.4142135623665355 +-1 -3.7949909043547426e-06 1.4142135623680028 +1 -3.7949909043547426e-06 1.4142135623680028 +1 -1.4142135623680028 -3.7949909043547426e-06 +-1 -1.4142135623680028 -3.7949909043547426e-06 +-1 3.7949909043547426e-06 -1.4142135623680028 +-1 1.4142135623680028 3.7949909043547426e-06 +1 1.4142135623680028 3.7949909043547426e-06 +1 3.7949909043547426e-06 -1.4142135623680028 +-1 -3.6070768958898969e-06 1.4142135623684944 +1 -3.6070768958898969e-06 1.4142135623684944 +1 -1.4142135623684944 -3.6070768958898969e-06 +-1 -1.4142135623684944 -3.6070768958898969e-06 +-1 3.6070768958898969e-06 -1.4142135623684944 +-1 1.4142135623684944 3.6070768958898969e-06 +1 1.4142135623684944 3.6070768958898969e-06 +1 3.6070768958898969e-06 -1.4142135623684944 +-1 -2.4904507319126939e-06 1.4142135623709018 +1 -2.4904507319126939e-06 1.4142135623709018 +1 -1.4142135623709018 -2.4904507319126939e-06 +-1 -1.4142135623709018 -2.4904507319126939e-06 +-1 2.4904507319126939e-06 -1.4142135623709018 +-1 1.4142135623709018 2.4904507319126939e-06 +1 1.4142135623709018 2.4904507319126939e-06 +1 2.4904507319126939e-06 -1.4142135623709018 +-1 0.99999891029865429 1.0000010897001574 +1 0.99999891029865429 1.0000010897001574 +1 -1.0000010897001574 0.99999891029865429 +-1 -1.0000010897001574 0.99999891029865429 +-1 -0.99999891029865429 -1.0000010897001574 +-1 1.0000010897001574 -0.99999891029865429 +1 1.0000010897001574 -0.99999891029865429 +1 -0.99999891029865429 -1.0000010897001574 +-1 1.4142135623724554 1.3448878106118537e-06 +1 1.4142135623724554 1.3448878106118537e-06 +1 -1.3448878106118537e-06 1.4142135623724554 +-1 -1.3448878106118537e-06 1.4142135623724554 +-1 -1.4142135623724554 -1.3448878106118537e-06 +-1 1.3448878106118537e-06 -1.4142135623724554 +1 1.3448878106118537e-06 -1.4142135623724554 +1 -1.4142135623724554 -1.3448878106118537e-06 +-1 1.0000000341206472 -0.99999996587935136 +1 1.0000000341206472 -0.99999996587935136 +1 0.99999996587935136 1.0000000341206472 +-1 0.99999996587935136 1.0000000341206472 +-1 -1.0000000341206472 0.99999996587935136 +-1 -0.99999996587935136 -1.0000000341206472 +1 -0.99999996587935136 -1.0000000341206472 +1 -1.0000000341206472 0.99999996587935136 +-1 1.5942993642314858e-08 -1.4142135623730947 +1 1.5942993642314858e-08 -1.4142135623730947 +1 1.4142135623730947 1.5942993642314858e-08 +-1 1.4142135623730947 1.5942993642314858e-08 +-1 -1.5942993642314858e-08 1.4142135623730947 +-1 -1.4142135623730947 -1.5942993642314858e-08 +1 -1.4142135623730947 -1.5942993642314858e-08 +1 -1.5942993642314858e-08 1.4142135623730947 +3 6 7 4 +3 3 2 1 +3 6 1 2 +3 5 0 1 +3 4 3 0 +3 7 2 3 +3 1 0 3 +3 4 5 6 +3 2 7 6 +3 1 6 5 +3 0 5 4 +3 3 4 7 +3 14 15 12 +3 11 10 9 +3 14 9 10 +3 13 8 9 +3 12 11 8 +3 15 10 11 +3 9 8 11 +3 12 13 14 +3 10 15 14 +3 9 14 13 +3 8 13 12 +3 11 12 15 +3 22 23 20 +3 19 18 17 +3 22 17 18 +3 21 16 17 +3 20 19 16 +3 23 18 19 +3 17 16 19 +3 20 21 22 +3 18 23 22 +3 17 22 21 +3 16 21 20 +3 19 20 23 +3 30 31 28 +3 27 26 25 +3 30 25 26 +3 29 24 25 +3 28 27 24 +3 31 26 27 +3 25 24 27 +3 28 29 30 +3 26 31 30 +3 25 30 29 +3 24 29 28 +3 27 28 31 +3 38 39 36 +3 35 34 33 +3 38 33 34 +3 37 32 33 +3 36 35 32 +3 39 34 35 +3 33 32 35 +3 36 37 38 +3 34 39 38 +3 33 38 37 +3 32 37 36 +3 35 36 39 +3 46 47 44 +3 43 42 41 +3 46 41 42 +3 45 40 41 +3 44 43 40 +3 47 42 43 +3 41 40 43 +3 44 45 46 +3 42 47 46 +3 41 46 45 +3 40 45 44 +3 43 44 47 +3 54 55 52 +3 51 50 49 +3 54 49 50 +3 53 48 49 +3 52 51 48 +3 55 50 51 +3 49 48 51 +3 52 53 54 +3 50 55 54 +3 49 54 53 +3 48 53 52 +3 51 52 55 +3 62 63 60 +3 59 58 57 +3 62 57 58 +3 61 56 57 +3 60 59 56 +3 63 58 59 +3 57 56 59 +3 60 61 62 +3 58 63 62 +3 57 62 61 +3 56 61 60 +3 59 60 63 +3 70 71 68 +3 67 66 65 +3 70 65 66 +3 69 64 65 +3 68 67 64 +3 71 66 67 +3 65 64 67 +3 68 69 70 +3 66 71 70 +3 65 70 69 +3 64 69 68 +3 67 68 71 +3 78 79 76 +3 75 74 73 +3 78 73 74 +3 77 72 73 +3 76 75 72 +3 79 74 75 +3 73 72 75 +3 76 77 78 +3 74 79 78 +3 73 78 77 +3 72 77 76 +3 75 76 79 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/cubes.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/cubes.off new file mode 100644 index 00000000000..493092d1a6a --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/cubes.off @@ -0,0 +1,204 @@ +OFF +80 120 0 + +-0.61594615543034026 -1.0701741879286757 -1.2146347356723264 +1.0452131429007676 -1.3737111650653515 -0.14299342950741956 +1.5883443594490732 0.52704573278436739 -0.44652546552251943 +-0.072814938882034802 0.83058270992104299 -1.5181667716874265 +-1.0452131429007676 1.3737111650653515 0.14299342950741956 +-1.5883443594490732 -0.52704573278436739 0.44652546552251943 +0.072814938882034802 -0.83058270992104299 1.5181667716874265 +0.61594615543034026 1.0701741879286757 1.2146347356723264 +-0.61594639934604423 -1.0701743934138028 -1.2146344309355146 +1.0452122820086462 -1.3737119347288513 -0.14299232819208521 +1.5883448836888012 0.52704444686667884 -0.44652511853937799 +-0.072813797665889982 0.83058198818172735 -1.518167221282807 +-1.0452122820086462 1.3737119347288513 0.14299232819208521 +-1.5883448836888012 -0.52704444686667884 0.44652511853937799 +0.072813797665889982 -0.83058198818172735 1.518167221282807 +0.61594639934604423 1.0701743934138028 1.2146344309355146 +-0.6159463762173395 -1.07017459735539 -1.2146342629779363 +1.0452117929893034 -1.3737123992443807 -0.14299144015755649 +1.5883452549553072 0.52704365666978259 -0.44652473058622827 +-0.072812914251335584 0.83058145855877352 -1.518167553406609 +-1.0452117929893034 1.3737123992443807 0.14299144015755649 +-1.5883452549553072 -0.52704365666978259 0.44652473058622827 +0.072812914251335584 -0.83058145855877352 1.518167553406609 +0.6159463762173395 1.07017459735539 1.2146342629779363 +-0.61594668912789197 -1.0701744000985252 -1.2146342780961472 +1.0452104492672072 -1.3737135467380566 -0.14299023830665158 +1.5883461040242048 0.52704182836364122 -0.44652386832759344 +-0.072811034370893465 0.83058097500317263 -1.5181679081170896 +-1.0452104492672072 1.3737135467380566 0.14299023830665158 +-1.5883461040242048 -0.52704182836364122 0.44652386832759344 +0.072811034370893465 -0.83058097500317263 1.5181679081170896 +0.61594668912789197 1.0701744000985252 1.2146342780961472 +-0.6159468868925585 -1.070174149353629 -1.2146343987318162 +1.0452090174071582 -1.3737147790282049 -0.14298886603597585 +1.5883470704382798 0.52703987181399814 -0.44652274001266495 +-0.072808833861436925 0.83058050148857432 -1.5181682727085062 +-1.0452090174071582 1.3737147790282049 0.14298886603597585 +-1.5883470704382798 -0.52703987181399814 0.44652274001266495 +0.072808833861436925 -0.83058050148857432 1.5181682727085062 +0.6159468868925585 1.070174149353629 1.2146343987318162 +-0.61594620872112704 -1.0701743005704609 -1.2146346094034179 +1.0452091168725113 -1.3737147792450597 -0.14298813688653067 +1.5883473052656241 0.52703984477504562 -0.44652193661109801 +-0.072808020328014339 0.83058032344964505 -1.5181684091279861 +-1.0452091168725113 1.3737147792450597 0.14298813688653067 +-1.5883473052656241 -0.52703984477504562 0.44652193661109801 +0.072808020328014339 -0.83058032344964505 1.5181684091279861 +0.61594620872112704 1.0701743005704609 1.2146346094034179 +0.015812704102963069 -1.4305657319567158 -0.97633582590218304 +-0.063147971057831695 -1.3970994075162435 1.0218246323460018 +1.3734324159237437 -0.0060147457399582988 1.0552948506097966 +1.4523930910845384 -0.03948107018043074 -0.94286560763838845 +0.063147971057831695 1.3970994075162435 -1.0218246323460018 +-1.3734324159237437 0.0060147457399582988 -1.0552948506097966 +-1.4523930910845384 0.03948107018043074 0.94286560763838845 +-0.015812704102963069 1.4305657319567158 0.97633582590218304 +-0.017005997503037738 -1.7115480160220284 -0.26516822000379986 +-1.4526640017493855 -0.672335677974221 0.66161320584190753 +-0.062496589720092359 0.32138030895690106 1.7008259385628288 +1.3731614145262554 -0.71783202909090671 0.77404451271712071 +1.4526640017493855 0.672335677974221 -0.66161320584190753 +0.062496589720092359 -0.32138030895690106 -1.7008259385628288 +-1.3731614145262554 0.71783202909090671 -0.77404451271712071 +0.017005997503037738 1.7115480160220284 0.26516822000379986 +-0.67677662809399264 -1.5909903432533568 0.10355251489119292 +-1.5303314706074931 -0.030328946305495721 -0.81065760039877899 +-1.0732219475484153 1.1338825933415291 0.75000327720449067 +-0.21966710503491477 -0.42677880360633264 1.6642133924944624 +1.5303314706074931 0.030328946305495721 0.81065760039877899 +1.0732219475484153 -1.1338825933415291 -0.75000327720449067 +0.21966710503491477 0.42677880360633264 -1.6642133924944624 +0.67677662809399264 1.5909903432533568 -0.10355251489119292 +-1.207106772440474 -1.2071067303442111 -0.29289346439627145 +-0.20710789493838763 -0.20710532012834212 -1.7071068233208859 +-0.50000073181889593 1.5000005345367655 -0.70710512978621964 +-1.4999996093209822 0.4999991243208966 0.70710822913839488 +0.20710789493838763 0.20710532012834212 1.7071068233208859 +0.50000073181889593 -1.5000005345367655 0.70710512978621964 +1.4999996093209822 -0.4999991243208966 -0.70710822913839488 +1.207106772440474 1.2071067303442111 0.29289346439627145 +3 6 7 4 +3 3 2 1 +3 6 1 2 +3 5 0 1 +3 4 3 0 +3 7 2 3 +3 1 0 3 +3 4 5 6 +3 2 7 6 +3 1 6 5 +3 0 5 4 +3 3 4 7 +3 14 15 12 +3 11 10 9 +3 14 9 10 +3 13 8 9 +3 12 11 8 +3 15 10 11 +3 9 8 11 +3 12 13 14 +3 10 15 14 +3 9 14 13 +3 8 13 12 +3 11 12 15 +3 22 23 20 +3 19 18 17 +3 22 17 18 +3 21 16 17 +3 20 19 16 +3 23 18 19 +3 17 16 19 +3 20 21 22 +3 18 23 22 +3 17 22 21 +3 16 21 20 +3 19 20 23 +3 30 31 28 +3 27 26 25 +3 30 25 26 +3 29 24 25 +3 28 27 24 +3 31 26 27 +3 25 24 27 +3 28 29 30 +3 26 31 30 +3 25 30 29 +3 24 29 28 +3 27 28 31 +3 38 39 36 +3 35 34 33 +3 38 33 34 +3 37 32 33 +3 36 35 32 +3 39 34 35 +3 33 32 35 +3 36 37 38 +3 34 39 38 +3 33 38 37 +3 32 37 36 +3 35 36 39 +3 46 47 44 +3 43 42 41 +3 46 41 42 +3 45 40 41 +3 44 43 40 +3 47 42 43 +3 41 40 43 +3 44 45 46 +3 42 47 46 +3 41 46 45 +3 40 45 44 +3 43 44 47 +3 54 55 52 +3 51 50 49 +3 54 49 50 +3 53 48 49 +3 52 51 48 +3 55 50 51 +3 49 48 51 +3 52 53 54 +3 50 55 54 +3 49 54 53 +3 48 53 52 +3 51 52 55 +3 62 63 60 +3 59 58 57 +3 62 57 58 +3 61 56 57 +3 60 59 56 +3 63 58 59 +3 57 56 59 +3 60 61 62 +3 58 63 62 +3 57 62 61 +3 56 61 60 +3 59 60 63 +3 70 71 68 +3 67 66 65 +3 70 65 66 +3 69 64 65 +3 68 67 64 +3 71 66 67 +3 65 64 67 +3 68 69 70 +3 66 71 70 +3 65 70 69 +3 64 69 68 +3 67 68 71 +3 78 79 76 +3 75 74 73 +3 78 73 74 +3 77 72 73 +3 76 75 72 +3 79 74 75 +3 73 72 75 +3 76 77 78 +3 74 79 78 +3 73 78 77 +3 72 77 76 +3 75 76 79 + diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_1.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_1.off new file mode 100644 index 00000000000..bd804a21a3a --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_1.off @@ -0,0 +1,14 @@ +OFF +7 3 0 + +0 0 0 +1 2 0 +1 0 0 +0 1 0 +1e-30 0 -8 +1 2 16 +2 2 2 +3 0 1 3 +3 0 2 3 +3 4 5 6 + diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_2.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_2.off new file mode 100644 index 00000000000..622155e02cb --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_2.off @@ -0,0 +1,15 @@ +OFF +9 3 0 + +0 1 0 +0 0 0 +2 1 0 +1 1 0 +2 0 0 +1.00000000000002 0 0 +1.00000000000001 1e-30 0 +2 -1 0 +1.00000000000002 -1 0 +3 0 1 2 +3 3 4 5 +3 6 7 8 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_3.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_3.off new file mode 100644 index 00000000000..9cd7437d4e0 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/intersection_when_rounded_3.off @@ -0,0 +1,19 @@ +OFF +12 4 0 + +0 0 0 +0 8.000000000001 0 +8.000000000001 0 0 +4.000000000002 4.000000000002 0 +4 8.000000000001 0 +8.000000000001 4 0 +6.000000000002 6.000000000002 0 +6 8.000000000001 0 +8.000000000001 6 0 +6.5 6.5 0 +6.5 8.000000000001 0 +8.000000000001 6.5 0 +3 0 1 2 +3 3 4 5 +3 6 7 8 +3 9 10 11 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/no_collapse_1.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/no_collapse_1.off new file mode 100644 index 00000000000..62b413a8497 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/no_collapse_1.off @@ -0,0 +1,16 @@ +OFF +8 4 0 + +0 0 0 +0 1 0 +1 1 0 +1 0 0 +0 0 1 +0 1 1 +1 1 1e-10 +1 0 1e-10 +3 0 1 2 +3 0 2 3 +3 4 5 7 +3 5 6 7 + diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/no_collapse_2.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/no_collapse_2.off new file mode 100644 index 00000000000..754d0a50ba0 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-snap/no_collapse_2.off @@ -0,0 +1,19 @@ +OFF +12 4 0 + +1 -1 -1 +1 -1 1 +3 -1e-15 0 +1 1 -1 +1 1 1 +3 1e-15 0 +0 -1e-15 -1 +0 -1e-15 1 +0 -2 0 +0 1e-15 -1 +0 1e-15 1 +0 2 0 +3 0 1 2 +3 3 4 5 +3 6 7 8 +3 9 10 11 From d37fcb16f6e1902ee089f849f991710dc0df1134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Fri, 25 Apr 2025 17:33:23 +0200 Subject: [PATCH 048/113] Test for snap rounding --- .../test_snap_rounding.cmd | 39 ++++++++ .../test_snap_rounding.cpp | 94 ++----------------- 2 files changed, 47 insertions(+), 86 deletions(-) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd new file mode 100644 index 00000000000..f82ae47ab66 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd @@ -0,0 +1,39 @@ +data-autoref/test_01.off 4 2 +data-autoref/test_02.off 10 17 +data-autoref/test_03.off 11 14 +data-autoref/test_04.off 12 20 +data-autoref/test_05.off 12 20 +data-autoref/test_06.off 89 248 +data-autoref/test_07.off 8 12 +data-autoref/test_08.off 57 148 +data-autoref/test_09.off 4 3 +data-autoref/test_10.off 10 13 +data-autoref/test_11.off 9 12 +data-autoref/test_12.off 9 6 +data-autoref/test_13.off 12 22 +data-autoref/test_14.off 12 22 +data-autoref/test_15.off 12 22 +data-autoref/test_16.off 4 2 +data-autoref/test_17.off 4 2 +data-autoref/triple_inter_exception/triple.off 15 18 +data-autoref/triple_inter_exception/cubes_cpln_1.off 66 206 +data-autoref/triple_inter_exception/cubes_cpln_2.off 54 158 +data-autoref/triple_inter_exception/cubes_cpln_3.off 61 188 +data-autoref/open_01.off 1313 2622 +data-autoref/open_02.off 562 1056 +data-autoref/cpln_01.off 30 78 +data-autoref/cpln_02.off 24 56 +data-autoref/cpln_03.off 27 68 +data-autoref/four_cubes.off 106 352 +data-autoref/spiral.off 19 31 +data-snap/intersection_when_rounded_1.off 9 6 +data-snap/intersection_when_rounded_2.off 10 7 +data-snap/intersection_when_rounded_3.off 16 14 +data-snap/collapse_1.off 6 4 +data-snap/collapse_2.off 13 16 +data-snap/collapse_3.off 11 10 +data-snap/no_collapse_1.off 8 4 +data-snap/no_collapse_2.off 12 4 +data-snap/cubes.off 5042 26036 +data-snap/coplanar_cubes.off 1514 5544 +data-snap/coplanar_refined_cubes.off 1872 6880 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp index 76d806a50fc..f2e6a35bb57 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp @@ -3,33 +3,18 @@ #include #include #include +#include #include - -#include #include #include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Surface_mesh Mesh; namespace PMP = CGAL::Polygon_mesh_processing; -template -struct My_exp_visitor : - public CGAL::Polygon_mesh_processing::Corefinement::Default_visitor -{ - void after_subface_creations(TriangleMesh&){++(*i);} - - My_exp_visitor() - : i (new int(0) ) - {} - - std::shared_ptr i; -}; - struct My_visitor : public PMP::Autorefinement::Default_visitor { My_visitor(std::size_t nb_input, std::size_t expected_nb_output) @@ -47,6 +32,7 @@ struct My_visitor : public PMP::Autorefinement::Default_visitor void number_of_output_triangles(std::size_t nbt) { tgt_check.assign(expected_nb_output, 0); + std::cout << nbt << " " << expected_nb_output << std::endl; assert(nbt==expected_nb_output); } @@ -76,70 +62,6 @@ struct My_visitor : public PMP::Autorefinement::Default_visitor std::vector tgt_check; }; -void test_coref_based(const char* fname, std::size_t nb_polylines, std::size_t total_nb_points, - std::size_t nb_vertices_after_autorefine, bool all_fixed, std::size_t nb_vertices_after_fix, - bool triple_intersection) -{ - std::cout << "Running tests (coref based) on " << fname << "\n"; - std::ifstream input(fname); - - Mesh mesh; - if (!input || !(input >> mesh)) - { - std::cerr << " Input mesh is not a valid off file." << std::endl; - exit(EXIT_FAILURE); - } - input.close(); - std::size_t nb_vertices_before_autorefine = num_vertices(mesh); - -// Testing PMP::experimental::surface_self_intersection() - try{ - std::vector< std::vector >polylines; - PMP::experimental::surface_self_intersection(mesh, std::back_inserter(polylines)); - assert(polylines.size() == nb_polylines); - std::size_t total_nb_pt=0; - for(const std::vector& polyline : polylines) - total_nb_pt+=polyline.size(); - assert(total_nb_points == total_nb_pt); - assert( !triple_intersection ); - } - catch(const PMP::Corefinement::Triple_intersection_exception&) - { - assert( triple_intersection ); - } - -// Testing PMP::experimental::autorefine() - try{ - My_exp_visitor visitor; - PMP::experimental::autorefine(mesh, - CGAL::parameters::visitor(visitor)); - mesh.collect_garbage(); - assert( nb_vertices_after_autorefine==num_vertices(mesh)); - assert( (nb_vertices_before_autorefine!=nb_vertices_after_autorefine)== (*(visitor.i) != 0) ); - assert( !triple_intersection ); - } - catch(const PMP::Corefinement::Triple_intersection_exception&) - { - assert( triple_intersection ); - } - -// Testing PMP::experimental::autorefine_and_remove_self_intersections() - try{ - input.open(fname); - mesh.clear(); - input >> mesh; - bool res=PMP::experimental::autorefine_and_remove_self_intersections(mesh); - assert(res==all_fixed); - mesh.collect_garbage(); - assert( nb_vertices_after_fix==num_vertices(mesh)); - assert( !triple_intersection ); - } - catch(const PMP::Corefinement::Triple_intersection_exception&) - { - assert( triple_intersection ); - } -} - template void test(const char* fname, std::size_t nb_vertices_after_autorefine, std::size_t expected_nb_output, Tag tag) { @@ -160,6 +82,8 @@ void test(const char* fname, std::size_t nb_vertices_after_autorefine, std::size // Testing autorefine() My_visitor visitor(triangles.size(), expected_nb_output); PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::visitor(visitor).concurrency_tag(tag).apply_iterative_snap_rounding(true)); + std::cout << points.size() << " " << nb_vertices_after_autorefine << std::endl; + std::cout << triangles.size() << " " << expected_nb_output << std::endl; assert( nb_vertices_after_autorefine==points.size()); assert( expected_nb_output==triangles.size()); assert( !PMP::does_triangle_soup_self_intersect(points, triangles) ); @@ -168,14 +92,12 @@ void test(const char* fname, std::size_t nb_vertices_after_autorefine, std::size int main(int argc, const char** argv) { - // file nb_polylines total_nb_points nb_vertices_after_autorefine all_fixed nb_vertices_after_fix triple_intersection - for (int i=0;i<(argc-1)/9; ++i) + // file expected_nb_of_vertices expected_nb_of_faces (after repair) + for (int i=0;i<(argc-1)/3; ++i) { - test_coref_based(argv[1+9*i], atoi(argv[1+9*i+1]), atoi(argv[1+9*i+2]), - atoi(argv[1+9*i+3]), atoi(argv[1+9*i+4])==0?false:true, atoi(argv[1+9*i+5]), atoi(argv[1+9*i+6])==0?false:true); - test(argv[1+9*i], atoi(argv[1+9*i+7]), atoi(argv[1+9*i+8]), CGAL::Sequential_tag()); + test(argv[1+3*i], atoi(argv[1+3*i+1]), atoi(argv[1+3*i+2]), CGAL::Sequential_tag()); #ifdef CGAL_LINKED_WITH_TBB - test(argv[1+9*i], atoi(argv[1+9*i+7]), atoi(argv[1+9*i+8]), CGAL::Parallel_tag()); + test(argv[1+3*i], atoi(argv[1+3*i+1]), atoi(argv[1+3*i+2]), CGAL::Parallel_tag()); #endif } } From dd63fd28ca51ff032fb22d57a56998db95597c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Fri, 25 Apr 2025 17:34:15 +0200 Subject: [PATCH 049/113] update cmakelist to compile examples with rotated cubes --- .../examples/Polygon_mesh_processing/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 1747148f26f..da14e538df4 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -59,6 +59,8 @@ create_single_source_cgal_program("isotropic_remeshing_with_allow_move.cpp") create_single_source_cgal_program("triangle_mesh_autorefinement.cpp") create_single_source_cgal_program("soup_autorefinement.cpp") create_single_source_cgal_program("snap_polygon_soup.cpp") +create_single_source_cgal_program("rotated_cubes_autorefinement.cpp") +create_single_source_cgal_program("coplanar_cubes_autorefinement.cpp") find_package(Eigen3 3.2.0 QUIET) #(requires 3.2.0 or greater) include(CGAL_Eigen3_support) @@ -140,6 +142,8 @@ if(TARGET CGAL::TBB_support) target_link_libraries(hausdorff_bounded_error_distance_example PRIVATE CGAL::TBB_support) target_link_libraries(soup_autorefinement PRIVATE CGAL::TBB_support) target_link_libraries(snap_polygon_soup PRIVATE CGAL::TBB_support) + target_link_libraries(rotated_cubes_autorefinement PRIVATE CGAL::TBB_support) + target_link_libraries(coplanar_cubes_autorefinement PRIVATE CGAL::TBB_support) create_single_source_cgal_program("corefinement_parallel_union_meshes.cpp") target_link_libraries(corefinement_parallel_union_meshes PRIVATE CGAL::TBB_support) From f03faa7298985ea1b18bc5ff548236e0b8cae97f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Fri, 25 Apr 2025 17:35:04 +0200 Subject: [PATCH 050/113] Solve mistake in test_snap_rounding.cmd --- .../test/Polygon_mesh_processing/test_snap_rounding.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd index f82ae47ab66..82f194039a5 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd @@ -36,4 +36,4 @@ data-snap/no_collapse_1.off 8 4 data-snap/no_collapse_2.off 12 4 data-snap/cubes.off 5042 26036 data-snap/coplanar_cubes.off 1514 5544 -data-snap/coplanar_refined_cubes.off 1872 6880 +data-snap/refined_coplanar_cubes.off 1872 6880 From c4b1667b13c510e159d4f5ca59aea5d1e193f84b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 28 Apr 2025 11:51:19 +0200 Subject: [PATCH 051/113] simplify the example code of snap_rounding --- .../snap_polygon_soup.cpp | 87 ++++++++----------- 1 file changed, 35 insertions(+), 52 deletions(-) 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 8ec5e8bff86..cc81e6ffbdb 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,5 +1,3 @@ -#include -#include #include #include #include @@ -13,53 +11,9 @@ #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; -typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; -typedef CGAL::Simple_cartesian Cartesian; - +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; namespace PMP = CGAL::Polygon_mesh_processing; -template -struct Example{ - void operator()(const std::string& filename, int grid_size){ - const std::string out_file = "rounded_soup.off"; - std::vector input_points; - std::vector> input_triangles; - std::cout << "Snap rounding on " << filename << " with " << typeid(Kernel).name() << "\n"; - if (!CGAL::IO::read_polygon_soup(filename, input_points, input_triangles)) - { - std::cerr << "Cannot read " << filename << "\n"; - return; - } - std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << std::endl; - std::cout << "Is 2-manifold: " << PMP::is_polygon_soup_a_polygon_mesh(input_triangles) << std::endl; - - std::vector> pairs_of_intersecting_triangles; - PMP::triangle_soup_self_intersections(input_points, input_triangles, std::back_inserter(pairs_of_intersecting_triangles)); - std::cout << "Nb of pairs of intersecting triangles: " << pairs_of_intersecting_triangles.size() << std::endl; - - PMP::repair_polygon_soup(input_points, input_triangles); - PMP::triangulate_polygons(input_points, input_triangles); - - CGAL::Real_timer t; - t.start(); - bool success=PMP::autorefine_triangle_soup(input_points, input_triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(false).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15)); - t.stop(); - std::cout << "\nOutput:" << std::endl; - std::cout << "#points = " << input_points.size() << " and #triangles = " << input_triangles.size() << " in " << t.time() << " sec." << std::endl; - if(success) - std::cout << "Does self-intersect: " << PMP::does_triangle_soup_self_intersect(input_points, input_triangles) << std::endl; - else - std::cout << "ROUNDING FAILED" << std::endl; - - std::vector output_points; - 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(out_file, output_points, input_triangles, CGAL::parameters::stream_precision(17)); - std::cout << "Is 2-manifold: " << PMP::orient_polygon_soup(input_points, input_triangles) << "\n\n" << std::endl; - } -}; - int main(int argc, char** argv) { const std::string filename = argc == 1 ? CGAL::data_file_path("meshes/elephant.off") @@ -68,12 +22,41 @@ int main(int argc, char** argv) const int grid_size = argc <= 2 ? 23 : std::stoi(std::string(argv[2])); - const bool epeck = argc <= 3 ? false - : std::string(argv[3])=="EPECK"; + const std::string out_file = "rounded_soup.off"; - if(epeck) - Example()(filename, grid_size); + std::vector points; + std::vector> triangles; + + std::cout << "Snap rounding on " << filename << "\n"; + if (!CGAL::IO::read_polygon_soup(filename, points, triangles)) + { + std::cerr << "Cannot read " << filename << "\n"; + return 1; + } + + std::cout << "#points = " << points.size() << " and #triangles = " << triangles.size() << std::endl; + std::cout << "Is 2-manifold: " << PMP::is_polygon_soup_a_polygon_mesh(triangles) << std::endl; + + std::vector> pairs_of_intersecting_triangles; + PMP::triangle_soup_self_intersections(points, triangles, std::back_inserter(pairs_of_intersecting_triangles)); + std::cout << "Nb of pairs of intersecting triangles: " << pairs_of_intersecting_triangles.size() << std::endl; + + PMP::repair_polygon_soup(points, triangles); + PMP::triangulate_polygons(points, triangles); + + CGAL::Real_timer t; + t.start(); + bool success=PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(false).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15)); + t.stop(); + + std::cout << "\nOutput:" << std::endl; + std::cout << "#points = " << points.size() << " and #triangles = " << triangles.size() << " in " << t.time() << " sec." << std::endl; + if(success) + std::cout << "Does self-intersect: " << PMP::does_triangle_soup_self_intersect(points, triangles) << std::endl; else - Example()(filename, grid_size); + std::cout << "ROUNDING FAILED" << std::endl; + + CGAL::IO::write_polygon_soup(out_file, points, triangles, CGAL::parameters::stream_precision(17)); + std::cout << "Is 2-manifold: " << PMP::orient_polygon_soup(points, triangles) << "\n\n" << std::endl; return 0; } From 4aa96bee9950eeed3358ee238e0624ddd4d72922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 28 Apr 2025 12:00:05 +0200 Subject: [PATCH 052/113] less verbose test and add another test file --- .../test/Polygon_mesh_processing/test_snap_rounding.cmd | 1 + .../test/Polygon_mesh_processing/test_snap_rounding.cpp | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd index 82f194039a5..44c57e68d6d 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd @@ -35,5 +35,6 @@ data-snap/collapse_3.off 11 10 data-snap/no_collapse_1.off 8 4 data-snap/no_collapse_2.off 12 4 data-snap/cubes.off 5042 26036 +data-snap/refined_cubes.off 5908 29863 data-snap/coplanar_cubes.off 1514 5544 data-snap/refined_coplanar_cubes.off 1872 6880 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp index f2e6a35bb57..b8d8689a752 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp @@ -32,7 +32,6 @@ struct My_visitor : public PMP::Autorefinement::Default_visitor void number_of_output_triangles(std::size_t nbt) { tgt_check.assign(expected_nb_output, 0); - std::cout << nbt << " " << expected_nb_output << std::endl; assert(nbt==expected_nb_output); } @@ -82,8 +81,6 @@ void test(const char* fname, std::size_t nb_vertices_after_autorefine, std::size // Testing autorefine() My_visitor visitor(triangles.size(), expected_nb_output); PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::visitor(visitor).concurrency_tag(tag).apply_iterative_snap_rounding(true)); - std::cout << points.size() << " " << nb_vertices_after_autorefine << std::endl; - std::cout << triangles.size() << " " << expected_nb_output << std::endl; assert( nb_vertices_after_autorefine==points.size()); assert( expected_nb_output==triangles.size()); assert( !PMP::does_triangle_soup_self_intersect(points, triangles) ); From de0c054c2793321701a2d1079282c671b05b2390 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 28 Apr 2025 14:21:27 +0200 Subject: [PATCH 053/113] add specialization of repair_triangle_soup for indexes_range of array --- .../internal/triangle_soup_snap_rounding.h | 72 ++++++++++++++++--- 1 file changed, 63 insertions(+), 9 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 86115e6717c..776d47066e4 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -33,6 +33,7 @@ namespace Polygon_mesh_processing namespace internal { +// Certified ceil function for exact number types template double double_ceil(Lazy_exact_nt< NT > x); template double double_ceil(NT x); @@ -42,7 +43,7 @@ double double_ceil(Lazy_exact_nt< NT > x){ double ceil_left=std::ceil(to_interval(x).first); if(ceil_left==std::ceil(to_interval(x).second)) return ceil_left; - // If not refine interval by contracting the DAG and try again + // If not refine the interval by contracting the DAG and try again x.exact(); ceil_left=std::ceil(to_interval(x).first); if(ceil_left==std::ceil(to_interval(x).second)) @@ -69,6 +70,7 @@ double double_ceil(NT x){ } }; +// Color a range by an index, it is used by the visitor to track the correspondance between the input and the output template class Indexes_range : public Range{ typedef std::remove_cv_t::value_type> Value_type; @@ -98,18 +100,71 @@ private: bool modified; }; -//repair_polygon_soup for triangles +// Repair_polygon_soup without remove_pinched_polygons since our polygon are triangles template ::Polygon_3, - typename NamedParameters> + typename Polygon = typename Polygon_types::Polygon_3> +struct Triangle_soup_fixer +{ + template + void operator()(PointRange& points, + PolygonRange& polygons, + const NamedParameters& np) const + { + using parameters::get_parameter; + using parameters::choose_parameter; + + typedef typename GetPolygonGeomTraits::type Traits; + Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); + + merge_duplicate_points_in_polygon_soup(points, polygons, np); + simplify_polygons_in_polygon_soup(points, polygons, traits); + remove_invalid_polygons_in_polygon_soup(points, polygons); + merge_duplicate_polygons_in_polygon_soup(points, polygons, np); + remove_isolated_points_in_polygon_soup(points, polygons); + } +}; + +// Specialization for array and Indexes_range of array +template +struct Triangle_soup_fixer > +{ + template + void operator()(PointRange& points, + PolygonRange& polygons, + const NamedParameters& np) const + { + repair_polygon_soup(points, polygons, np); + } +}; + +template +struct Triangle_soup_fixer > > +{ + template + void operator()(PointRange& points, + PolygonRange& polygons, + const NamedParameters& np) const + { + using parameters::get_parameter; + using parameters::choose_parameter; + + typedef typename GetPolygonGeomTraits::type Traits; + Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); + + merge_duplicate_points_in_polygon_soup(points, polygons, np); + remove_invalid_polygons_in_array_polygon_soup(points, polygons, traits); + merge_duplicate_polygons_in_polygon_soup(points, polygons, np); + remove_isolated_points_in_polygon_soup(points, polygons); + } +}; + +template void repair_triangle_soup(PointRange& points, PolygonRange& polygons, const NamedParameters& np) { - merge_duplicate_points_in_polygon_soup(points, polygons, np); - remove_invalid_polygons_in_polygon_soup(points, polygons); - merge_duplicate_polygons_in_polygon_soup(points, polygons, np); - remove_isolated_points_in_polygon_soup(points, polygons); + Triangle_soup_fixer fixer; + fixer(points, polygons, np); } struct Wrapp_id_visitor : public Autorefinement::Default_visitor @@ -280,7 +335,6 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, #endif for (Point_3 &p : points) p = Point_3(to_double(p.x()), to_double(p.y()), to_double(p.z())); - repair_triangle_soup(points, triangles, np); // Get all intersecting triangles From d9e53aa23211016e543077242530f743a894700c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 28 Apr 2025 14:36:02 +0200 Subject: [PATCH 054/113] some cleaning --- .../internal/triangle_soup_snap_rounding.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 776d47066e4..26d81d8a170 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -167,6 +167,7 @@ void repair_triangle_soup(PointRange& points, fixer(points, polygons, np); } +// A visitor of Autorefinement to track the correspondance between input and output triangles struct Wrapp_id_visitor : public Autorefinement::Default_visitor { template< typename Triangle> @@ -248,7 +249,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, typedef typename internal_np::Lookup_named_param_def < internal_np::visitor_t, NamedParameters, - Autorefinement::Default_visitor//default + Autorefinement::Default_visitor >::type Visitor; Visitor visitor(choose_parameter(get_parameter(np, internal_np::visitor))); @@ -301,7 +302,6 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, auto snap = [](typename Kernel::FT x, double scale) { // Scale the coordinate, round to nearest integer and scale back - // TODO replace this ceil by the one of Algebraic_fondation when it will be add to master return internal::double_ceil((x * scale) - 0.5) / scale; }; auto snap_p = [scale, snap](const Point_3 &p) @@ -376,6 +376,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, std::cout << "Snap the coordinates of the vertices of the intersecting triangles" << std::endl; #endif +// Variants of the rounding process depending of the macros defined #if defined(PMP_ROUNDING_VERTICES_NAIVE_SNAP) // Nothing @@ -478,6 +479,8 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, } } #elif defined(PMP_ROUNDING_VERTICES_FLOAT_SNAP) + // Version where points are rounded to the closest simple precision float. + for (auto &pair : pairs_of_intersecting_triangles) { for (size_t pi : triangles[pair.first]) @@ -491,8 +494,6 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, // Get all the snap version of the points of the vertices of the intersecting triangles // Note: points will not be modified here, they will be modified in the next for loop - //TODO: TBB version of this for loop - std::vector snap_points; snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); From 13c21b6cb68a6033228914c689ee2c9c027a8e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 28 Apr 2025 16:40:43 +0200 Subject: [PATCH 055/113] move experiments with rotated cubes in benchmark --- .../benchmark/Polygon_mesh_processing/CMakeLists.txt | 10 ++++++++++ .../coplanar_cubes_autorefinement.cpp | 0 .../rotated_cubes_autorefinement.cpp | 0 .../examples/Polygon_mesh_processing/CMakeLists.txt | 4 ---- 4 files changed, 10 insertions(+), 4 deletions(-) rename Polygon_mesh_processing/{examples => benchmark}/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp (100%) rename Polygon_mesh_processing/{examples => benchmark}/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp (100%) diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt index c24a90d7904..a59b7181d0c 100644 --- a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt @@ -37,7 +37,17 @@ else() endif() create_single_source_cgal_program("fast.cpp") +create_single_source_cgal_program("rotated_cubes_autorefinement.cpp") +create_single_source_cgal_program("coplanar_cubes_autorefinement.cpp") create_single_source_cgal_program("polygon_mesh_slicer.cpp") target_link_libraries(polygon_mesh_slicer PRIVATE CGAL::Eigen3_support) +find_package(TBB QUIET) +include(CGAL_TBB_support) +if(TARGET CGAL::TBB_support) + target_link_libraries(rotated_cubes_autorefinement PRIVATE CGAL::TBB_support) + target_link_libraries(coplanar_cubes_autorefinement PRIVATE CGAL::TBB_support) +else() + message(STATUS "NOTICE: Intel TBB was not found. Sequential code will be used.") +endif() \ No newline at end of file diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp similarity index 100% rename from Polygon_mesh_processing/examples/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp rename to Polygon_mesh_processing/benchmark/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp similarity index 100% rename from Polygon_mesh_processing/examples/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp rename to Polygon_mesh_processing/benchmark/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index da14e538df4..1747148f26f 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -59,8 +59,6 @@ create_single_source_cgal_program("isotropic_remeshing_with_allow_move.cpp") create_single_source_cgal_program("triangle_mesh_autorefinement.cpp") create_single_source_cgal_program("soup_autorefinement.cpp") create_single_source_cgal_program("snap_polygon_soup.cpp") -create_single_source_cgal_program("rotated_cubes_autorefinement.cpp") -create_single_source_cgal_program("coplanar_cubes_autorefinement.cpp") find_package(Eigen3 3.2.0 QUIET) #(requires 3.2.0 or greater) include(CGAL_Eigen3_support) @@ -142,8 +140,6 @@ if(TARGET CGAL::TBB_support) target_link_libraries(hausdorff_bounded_error_distance_example PRIVATE CGAL::TBB_support) target_link_libraries(soup_autorefinement PRIVATE CGAL::TBB_support) target_link_libraries(snap_polygon_soup PRIVATE CGAL::TBB_support) - target_link_libraries(rotated_cubes_autorefinement PRIVATE CGAL::TBB_support) - target_link_libraries(coplanar_cubes_autorefinement PRIVATE CGAL::TBB_support) create_single_source_cgal_program("corefinement_parallel_union_meshes.cpp") target_link_libraries(corefinement_parallel_union_meshes PRIVATE CGAL::TBB_support) From e0cea67e6c65c7da8a7cdcb2fac91d82d443c781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 28 Apr 2025 16:41:21 +0200 Subject: [PATCH 056/113] modified example of cmd --- .../test/Polygon_mesh_processing/test_snap_rounding.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd index 44c57e68d6d..fa1b6a98c71 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd @@ -1,6 +1,6 @@ data-autoref/test_01.off 4 2 data-autoref/test_02.off 10 17 -data-autoref/test_03.off 11 14 +data-autoref/test_03.off 13 20 data-autoref/test_04.off 12 20 data-autoref/test_05.off 12 20 data-autoref/test_06.off 89 248 From cdfd8de6a5fa398bd1f0361424d79729c6cdc3d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Mon, 28 Apr 2025 18:34:09 +0200 Subject: [PATCH 057/113] reduce running time of test_snap_rounding, add a full test version --- .../test_snap_rounding.cmd | 2 - .../test_snap_rounding_full.cmd | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding_full.cmd diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd index fa1b6a98c71..81ea3e2afad 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd @@ -34,7 +34,5 @@ data-snap/collapse_2.off 13 16 data-snap/collapse_3.off 11 10 data-snap/no_collapse_1.off 8 4 data-snap/no_collapse_2.off 12 4 -data-snap/cubes.off 5042 26036 -data-snap/refined_cubes.off 5908 29863 data-snap/coplanar_cubes.off 1514 5544 data-snap/refined_coplanar_cubes.off 1872 6880 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding_full.cmd b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding_full.cmd new file mode 100644 index 00000000000..fa1b6a98c71 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding_full.cmd @@ -0,0 +1,40 @@ +data-autoref/test_01.off 4 2 +data-autoref/test_02.off 10 17 +data-autoref/test_03.off 13 20 +data-autoref/test_04.off 12 20 +data-autoref/test_05.off 12 20 +data-autoref/test_06.off 89 248 +data-autoref/test_07.off 8 12 +data-autoref/test_08.off 57 148 +data-autoref/test_09.off 4 3 +data-autoref/test_10.off 10 13 +data-autoref/test_11.off 9 12 +data-autoref/test_12.off 9 6 +data-autoref/test_13.off 12 22 +data-autoref/test_14.off 12 22 +data-autoref/test_15.off 12 22 +data-autoref/test_16.off 4 2 +data-autoref/test_17.off 4 2 +data-autoref/triple_inter_exception/triple.off 15 18 +data-autoref/triple_inter_exception/cubes_cpln_1.off 66 206 +data-autoref/triple_inter_exception/cubes_cpln_2.off 54 158 +data-autoref/triple_inter_exception/cubes_cpln_3.off 61 188 +data-autoref/open_01.off 1313 2622 +data-autoref/open_02.off 562 1056 +data-autoref/cpln_01.off 30 78 +data-autoref/cpln_02.off 24 56 +data-autoref/cpln_03.off 27 68 +data-autoref/four_cubes.off 106 352 +data-autoref/spiral.off 19 31 +data-snap/intersection_when_rounded_1.off 9 6 +data-snap/intersection_when_rounded_2.off 10 7 +data-snap/intersection_when_rounded_3.off 16 14 +data-snap/collapse_1.off 6 4 +data-snap/collapse_2.off 13 16 +data-snap/collapse_3.off 11 10 +data-snap/no_collapse_1.off 8 4 +data-snap/no_collapse_2.off 12 4 +data-snap/cubes.off 5042 26036 +data-snap/refined_cubes.off 5908 29863 +data-snap/coplanar_cubes.off 1514 5544 +data-snap/refined_coplanar_cubes.off 1872 6880 From 54b27f8d907760f9e0e743e54071b8e28feed268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 10:17:00 +0200 Subject: [PATCH 058/113] Delete unused includes and solve a compilation error on some testing --- .../internal/triangle_soup_snap_rounding.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 26d81d8a170..3ae0c445fdc 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -12,18 +12,16 @@ #ifndef CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H #define CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H -#include +#include + #include #include -#include #include #include #include -#include - namespace CGAL { @@ -102,7 +100,7 @@ private: // Repair_polygon_soup without remove_pinched_polygons since our polygon are triangles template ::Polygon_3> + typename Polygon = typename internal::Polygon_types::Polygon_3> struct Triangle_soup_fixer { template From f39de8cb66268316dfaf514031583ae9eec75e3f Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 29 Apr 2025 14:00:42 +0200 Subject: [PATCH 059/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h Co-authored-by: Sebastien Loriot --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0ba1c28cdc1..50ab119eb3d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1669,7 +1669,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, * \cgalParamNEnd * \cgalParamNBegin{apply_iterative_snap_rounding} * \cgalParamDescription{Enable the rounding of the coordinates so that they fit in doubles.} -* \cgalParamType{boolean} +* \cgalParamType{Boolean} * \cgalParamDefault{false} * \cgalParamNEnd * \cgalParamNBegin{snap_grid_size} From 7868d68902fcdf946f4a4a4ae6270a05e83c83cb Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 29 Apr 2025 14:01:36 +0200 Subject: [PATCH 060/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h Co-authored-by: Sebastien Loriot --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 50ab119eb3d..addd24128ae 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1628,7 +1628,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, * `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 -* the creation of new triangles. +* the creation and removal of triangles. * If the `apply_iterative_snap_rounding()` parameter is set to `true`, the coordinates of the vertices are rounded to fit within the precision of a double-precision floating point, * while trying to make the triangle soup free of 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. From 54bb86af41e8fa7a0fc183f32023de113fba1f83 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 29 Apr 2025 14:08:39 +0200 Subject: [PATCH 061/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h Co-authored-by: Sebastien Loriot --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 addd24128ae..5a70fe94714 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1629,7 +1629,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, * 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 * the creation and removal of triangles. -* If the `apply_iterative_snap_rounding()` parameter is set to `true`, the coordinates of the vertices are rounded to fit within the precision of a double-precision floating point, +* If the `apply_iterative_snap_rounding()` parameter is set to `true`, each coordinate of the point of each vertex is rounded to fit within the precision of a double-precision floating point number, * while trying to make the triangle soup free of 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. * From 61295296fdd5d77a080100b19048a1a586371781 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 29 Apr 2025 14:11:00 +0200 Subject: [PATCH 062/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h Co-authored-by: Sebastien Loriot --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5a70fe94714..c930b50b3f7 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1674,7 +1674,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, * \cgalParamNEnd * \cgalParamNBegin{snap_grid_size} * \cgalParamDescription{A value `gs` used to scale the points to `[-2^gs, 2^gs]` before rounding them on integers. Used only if `apply_iterative_snap_rounding()` is set to `true`} -* \cgalParamType{unsigned int} +* \cgalParamType{`unsigned int`} * \cgalParamDefault{23} * \cgalParamExtra{Must be lower than 52.} * \cgalParamNEnd From 2d96e2af23eee1af9bb59f818bc456885b20d27e Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 29 Apr 2025 14:11:58 +0200 Subject: [PATCH 063/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h Co-authored-by: Sebastien Loriot --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 3ae0c445fdc..c377bd1c06a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -7,7 +7,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Léo Valque, Sylvain Lazard +// Author(s) : Léo Valque #ifndef CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H #define CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H From fdcd4b6838d03b26c154c76d0d58950c01ff10b3 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 29 Apr 2025 14:14:19 +0200 Subject: [PATCH 064/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h Co-authored-by: Sebastien Loriot --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c930b50b3f7..3b478fc4ee2 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1685,7 +1685,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, * \cgalParamNEnd * \cgalNamedParamsEnd * -* \return `true` if `apply_iterative_snap_rounding` is set to `false`; otherwise, return `true` if the modified triangle soup is free from +* \return `true` if `apply_iterative_snap_rounding` is set to `false`; otherwise, returns `true` if the modified triangle soup is free from * self-intersection, and `false` if the algorithm was unable to provide such a triangle soup within the number of iterations. * */ From 9c42d3c7de6610f5ad28eab261f5f77d825ef994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 14:17:56 +0200 Subject: [PATCH 065/113] solved conflict on the documentation of autorefinement --- .../CGAL/Polygon_mesh_processing/autorefinement.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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 3b478fc4ee2..c365857ce7f 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1622,14 +1622,14 @@ bool autorefine_triangle_soup(PointRange& soup_points, * * refines a soup of triangles so that no pair of triangles intersects. * Output triangles may share a common edge or a common vertex (but with the same indexed position in `points`). -* Note that points in `soup_points` can only be added (intersection points) at the end of the container, with the initial order preserved. +* Note that if `apply_iterative_snap_rounding` option is set to `false`, points in `soup_points` can only be added (intersection points) at the end of the container, with the initial order preserved. * Note that if `soup_points` contains two or more identical points then only the first copy (following the order in the `soup_points`) -* will be used in `soup_triangles`. +* will be used in `soup_triangles`. if `apply_iterative_snap_rounding` is set to `true`, all duplicates points are removed. * `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 -* the creation and removal of triangles. -* If the `apply_iterative_snap_rounding()` parameter is set to `true`, each coordinate of the point of each vertex is rounded to fit within the precision of a double-precision floating point number, +* Also if `apply_iterative_snap_rounding` option is set to `false`, 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 the creation and removal of triangles independantly of +* the `apply_iterative_snap_rounding` option. +* If the `apply_iterative_snap_rounding` parameter is set to `true`, the coordinates of the vertices are rounded to fit within the precision of a double-precision floating point, * while trying to make the triangle soup free of 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. * From 9a04f2dee4be46c1cf88170cb420e6059dbabfaf Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 29 Apr 2025 14:49:35 +0200 Subject: [PATCH 066/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h Co-authored-by: Sebastien Loriot --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index c377bd1c06a..7c0c287d507 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -321,7 +321,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, #endif #ifdef CGAL_LINKED_WITH_TBB - if constexpr(parallel_execution) + if constexpr (parallel_execution) { tbb::parallel_for(tbb::blocked_range(0, points.size()), [&](const tbb::blocked_range& r){ From ccde78e64eb22a7f7ba57650b09aa0a46c306e22 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 29 Apr 2025 14:50:38 +0200 Subject: [PATCH 067/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h Co-authored-by: Sebastien Loriot --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 7c0c287d507..ec8701385e5 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -342,7 +342,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, if (pairs_of_intersecting_triangles.empty()) { #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE - std::cout << "End of the snapping" << std::endl; + std::cout << "End of the snapping" << std::endl; #endif CGAL_assertion(!does_triangle_soup_self_intersect(points, triangles)); if constexpr(has_visitor) From fbbd635b6a8f272ebe9e3e4ad41aa18990621d2a Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 29 Apr 2025 14:51:22 +0200 Subject: [PATCH 068/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h Co-authored-by: Sebastien Loriot --- .../internal/triangle_soup_snap_rounding.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index ec8701385e5..fb9c1a5f7cc 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -344,7 +344,6 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "End of the snapping" << std::endl; #endif - CGAL_assertion(!does_triangle_soup_self_intersect(points, triangles)); if constexpr(has_visitor) { std::vector > map_io(number_of_input_triangles); From a1bc4c474a2ead9e317ff526aa538b00b3efcc61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 14:22:43 +0200 Subject: [PATCH 069/113] avoid copy of the input in double_ceil --- .../internal/triangle_soup_snap_rounding.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index fb9c1a5f7cc..75e282f0293 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -32,11 +32,11 @@ namespace internal { // Certified ceil function for exact number types -template double double_ceil(Lazy_exact_nt< NT > x); -template double double_ceil(NT x); +template double double_ceil(const Lazy_exact_nt< NT > &x); +template double double_ceil(const NT &x); template -double double_ceil(Lazy_exact_nt< NT > x){ +double double_ceil(const Lazy_exact_nt< NT > &x){ // If both sides are in the same ceil, return this ceil double ceil_left=std::ceil(to_interval(x).first); if(ceil_left==std::ceil(to_interval(x).second)) @@ -51,7 +51,7 @@ double double_ceil(Lazy_exact_nt< NT > x){ }; template -double double_ceil(NT x){ +double double_ceil(const NT &x){ using FT = Fraction_traits; if constexpr(std::is_same::value){ // If NT is a fraction, the ceil value is the result of the euclidian division of the numerator and the denominator. From 89c559f0882a966c9171cc6c8f038f64dadf8806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 14:27:43 +0200 Subject: [PATCH 070/113] simplify constexpr test of NT is a fraction --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 75e282f0293..68de2864268 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -53,7 +53,7 @@ double double_ceil(const Lazy_exact_nt< NT > &x){ template double double_ceil(const NT &x){ using FT = Fraction_traits; - if constexpr(std::is_same::value){ + if constexpr(FT::Is_fraction::value){ // If NT is a fraction, the ceil value is the result of the euclidian division of the numerator and the denominator. typename FT::Numerator_type num, r, e; typename FT::Denominator_type denom; From f0bdb950f2b6ca159834795c9d8a6dbe369e32c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 14:31:41 +0200 Subject: [PATCH 071/113] avoid copy in indexes_range constructor --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 68de2864268..f92a724a6fa 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -77,7 +77,7 @@ public: typedef typename Range::iterator iterator; Indexes_range(){} - Indexes_range(std::initializer_list l): Range(l), m_id(0), modified(true){} + Indexes_range(const std::initializer_list &l): Range(l), m_id(0), modified(true){} Indexes_range(const Indexes_range &ir): Range(ir), m_id(ir.id()), modified(ir.was_modified()){} Indexes_range(Range &p): Range(p), modified(true){} Indexes_range(Range &p, size_t id): Range(p), m_id(id),modified(false){} From ba2dbce57460b905a071b49346d41245cc161b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 14:33:16 +0200 Subject: [PATCH 072/113] add internal in copy protection macro of triangle_soup_snap_rounding --- .../internal/triangle_soup_snap_rounding.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index f92a724a6fa..d8e5f77649d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -9,8 +9,8 @@ // // Author(s) : Léo Valque -#ifndef CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H -#define CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H +#ifndef CGAL_POLYGON_MESH_PROCESSING_INTERNAL_POLYGON_SOUP_SNAP_ROUNDING_H +#define CGAL_POLYGON_MESH_PROCESSING_INTERNAL_POLYGON_SOUP_SNAP_ROUNDING_H #include From c41a0c7b9f8a8298e1f78cece2f98aed3a66c815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 14:36:54 +0200 Subject: [PATCH 073/113] correct Indexes_range constructor --- .../internal/triangle_soup_snap_rounding.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index d8e5f77649d..b1821a1b88b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -76,9 +76,8 @@ public: typedef typename Range::const_iterator const_iterator; typedef typename Range::iterator iterator; - Indexes_range(){} + Indexes_range() = default; Indexes_range(const std::initializer_list &l): Range(l), m_id(0), modified(true){} - Indexes_range(const Indexes_range &ir): Range(ir), m_id(ir.id()), modified(ir.was_modified()){} Indexes_range(Range &p): Range(p), modified(true){} Indexes_range(Range &p, size_t id): Range(p), m_id(id),modified(false){} From 6cd79562739690c4d35f8837005fbd044f57ae18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 14:41:35 +0200 Subject: [PATCH 074/113] add std:: to size_t use in indexes_range --- .../internal/triangle_soup_snap_rounding.h | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index b1821a1b88b..0562e335b64 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -79,21 +79,14 @@ public: Indexes_range() = default; Indexes_range(const std::initializer_list &l): Range(l), m_id(0), modified(true){} Indexes_range(Range &p): Range(p), modified(true){} - Indexes_range(Range &p, size_t id): Range(p), m_id(id),modified(false){} + Indexes_range(Range &p, std::size_t id): Range(p), m_id(id),modified(false){} - void operator=(const Indexes_range &ir) - { - Range::operator=(ir); - modified=ir.was_modified(); - m_id=ir.id(); - } - - inline size_t id() const { return m_id; } - inline void set_id(size_t id){ m_id=id; } + inline std::size_t id() const { return m_id; } + inline void set_id(std::size_t id){ m_id=id; } inline bool was_modified() const { return modified; } private: - size_t m_id; + std::size_t m_id; bool modified; }; From 7b5cf516d6c15e7b9959f0e0b17526401bef7820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 14:42:50 +0200 Subject: [PATCH 075/113] solved orthograph mystake in wrapp_id_visitor --- .../internal/triangle_soup_snap_rounding.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 0562e335b64..406af631985 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -158,7 +158,7 @@ void repair_triangle_soup(PointRange& points, } // A visitor of Autorefinement to track the correspondance between input and output triangles -struct Wrapp_id_visitor : public Autorefinement::Default_visitor +struct Wrap_id_visitor : public Autorefinement::Default_visitor { template< typename Triangle> inline void internal_new_subtriangle(Triangle& new_t, const Triangle& old_t) { @@ -531,7 +531,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, #endif if constexpr(has_visitor) { - Wrapp_id_visitor visitor; + Wrap_id_visitor visitor; autorefine_triangle_soup(points, triangles, parameters::point_map(pm).concurrency_tag(Concurrency_tag()).visitor(visitor)); } else From 898bf5853c610a44f5fb26d0b465f0606eb6e144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 14:44:47 +0200 Subject: [PATCH 076/113] Correct default value of number_of_iterations in the documentation --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c365857ce7f..722829cb678 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1681,7 +1681,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, * \cgalParamNBegin{number_of_iterations} * \cgalParamDescription{Maximum number of iterations performed by the snap rounding algorithm. Used only if `apply_iterative_snap_rounding` is true.} * \cgalParamType{unsigned int} -* \cgalParamDefault{15} +* \cgalParamDefault{5} * \cgalParamNEnd * \cgalNamedParamsEnd * From c4452030f197a3ae7b96072a95d2dcd39632c403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 15:00:18 +0200 Subject: [PATCH 077/113] remove useless forward declaration --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 3 --- 1 file changed, 3 deletions(-) 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 722829cb678..08914b1de66 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -986,9 +986,6 @@ bool polygon_soup_snap_rounding(PointRange &points, PolygonRange &triangles, const NamedParameters& np = parameters::default_values()); -template -class Indexes_range; - template bool autorefine_triangle_soup(PointRange& soup_points, TriangleRange& soup_triangles, From b08f7f2a5c86ad0dcaef9f51913d1c6a3e80a3af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 15:01:50 +0200 Subject: [PATCH 078/113] remove useless inline in Wrap_id_visitor --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 406af631985..e5c711fb841 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -161,7 +161,7 @@ void repair_triangle_soup(PointRange& points, struct Wrap_id_visitor : public Autorefinement::Default_visitor { template< typename Triangle> - inline void internal_new_subtriangle(Triangle& new_t, const Triangle& old_t) { + void internal_new_subtriangle(Triangle& new_t, const Triangle& old_t) { new_t.set_id(old_t.id()); } }; From 8f7c8819f62f656c5bf5fa951877d7186b68f9da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 16:02:13 +0200 Subject: [PATCH 079/113] use a set in triangle_soup_snap_rounding instead of vector, sort and unique --- .../internal/triangle_soup_snap_rounding.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index e5c711fb841..524bf5bd396 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -483,24 +483,19 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, // Get all the snap version of the points of the vertices of the intersecting triangles // Note: points will not be modified here, they will be modified in the next for loop - std::vector snap_points; - snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); - + std::set snap_points; for (auto &pair : pairs_of_intersecting_triangles) { for (size_t pi : triangles[pair.first]) - snap_points.emplace_back(snap_p(points[pi])); + snap_points.emplace(snap_p(points[pi])); for (size_t pi : triangles[pair.second]) - snap_points.emplace_back(snap_p(points[pi])); + snap_points.emplace(snap_p(points[pi])); } #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Snap the coordinates of the vertices close-by the previous ones" << std::endl; #endif - std::sort(snap_points.begin(), snap_points.end()); - snap_points.erase(std::unique(snap_points.begin(), snap_points.end()), snap_points.end()); - // If the snapped version of a point correspond to one of the previous point, we snap it #ifdef CGAL_LINKED_WITH_TBB if constexpr(parallel_execution) From 61936188e33e0dc11ea9653065889e479ea639ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 18:17:48 +0200 Subject: [PATCH 080/113] Revert "use a set in triangle_soup_snap_rounding instead of vector, sort and unique" This reverts commit d98154a3896a64c58e466e3d291879f04305e453. --- .../internal/triangle_soup_snap_rounding.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 524bf5bd396..e5c711fb841 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -483,19 +483,24 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, // Get all the snap version of the points of the vertices of the intersecting triangles // Note: points will not be modified here, they will be modified in the next for loop - std::set snap_points; + std::vector snap_points; + snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); + for (auto &pair : pairs_of_intersecting_triangles) { for (size_t pi : triangles[pair.first]) - snap_points.emplace(snap_p(points[pi])); + snap_points.emplace_back(snap_p(points[pi])); for (size_t pi : triangles[pair.second]) - snap_points.emplace(snap_p(points[pi])); + snap_points.emplace_back(snap_p(points[pi])); } #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Snap the coordinates of the vertices close-by the previous ones" << std::endl; #endif + std::sort(snap_points.begin(), snap_points.end()); + snap_points.erase(std::unique(snap_points.begin(), snap_points.end()), snap_points.end()); + // If the snapped version of a point correspond to one of the previous point, we snap it #ifdef CGAL_LINKED_WITH_TBB if constexpr(parallel_execution) From 1e30aab6bccdf16a858867d175b1fa3b991a0c75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 18:19:31 +0200 Subject: [PATCH 081/113] Correct namepaspace of Polygon_types --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index e5c711fb841..d24d4ccc860 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -92,7 +92,7 @@ private: // Repair_polygon_soup without remove_pinched_polygons since our polygon are triangles template ::Polygon_3> + typename Polygon = typename CGAL::internal::Polygon_types::Polygon_3> struct Triangle_soup_fixer { template From 2416588b60f43af8d3390cc790dc83c9798edd41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 29 Apr 2025 18:20:34 +0200 Subject: [PATCH 082/113] Correct namespace of Polygon_types --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index d24d4ccc860..0bf4de2552e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -92,7 +92,7 @@ private: // Repair_polygon_soup without remove_pinched_polygons since our polygon are triangles template ::Polygon_3> + typename Polygon = typename ::CGAL::internal::Polygon_types::Polygon_3> struct Triangle_soup_fixer { template From fe028147ae993a4ec12d664edc9ecb622886e991 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Wed, 7 May 2025 10:43:51 +0200 Subject: [PATCH 083/113] Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h Co-authored-by: Sebastien Loriot --- .../Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h index 7b4ef6a1c9d..cf5b658686e 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h @@ -23,7 +23,7 @@ public: /// called for each subtriangle created from a triangle with intersection, `tgt_id` is the position in the triangle container after calling /// `autorefine_triangle_soup()` of the subtriangle, while `src_id` was the position of the original support triangle before calling the function. void new_subtriangle(std::size_t tgt_id, std::size_t src_id); - /// called for each input triangle deleted because it was degenerated, `src_id` was the position of the original support triangle before calling the function. Additionally, if `apply_iterative_snap_rounding()` is set to `true`, some extra triangle might become degenerated and will be absent from the output range of triangles. Those triangles are also reported in this function. + /// called for each input triangle absent in the outputbecause it was degenerate. `src_id` is the position of that triangle in the input range. Additionally, if `apply_iterative_snap_rounding()` is set to `true`, some extra triangles might become degenerate and will be absent in the output. Those triangles are also reported by this function. void delete_triangle(std::size_t src_id); /// @} }; From 21e7e681ce0c578f25d9786ce35b45e955b466e1 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Wed, 7 May 2025 10:44:57 +0200 Subject: [PATCH 084/113] missing space in doc if AutorefinementVisitor --- .../Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h index cf5b658686e..7cff8ea4bc0 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPAutorefinementVisitor.h @@ -23,7 +23,7 @@ public: /// called for each subtriangle created from a triangle with intersection, `tgt_id` is the position in the triangle container after calling /// `autorefine_triangle_soup()` of the subtriangle, while `src_id` was the position of the original support triangle before calling the function. void new_subtriangle(std::size_t tgt_id, std::size_t src_id); - /// called for each input triangle absent in the outputbecause it was degenerate. `src_id` is the position of that triangle in the input range. Additionally, if `apply_iterative_snap_rounding()` is set to `true`, some extra triangles might become degenerate and will be absent in the output. Those triangles are also reported by this function. + /// called for each input triangle absent in the output because it was degenerate. `src_id` is the position of that triangle in the input range. Additionally, if `apply_iterative_snap_rounding()` is set to `true`, some extra triangles might become degenerate and will be absent in the output. Those triangles are also reported by this function. void delete_triangle(std::size_t src_id); /// @} }; From 5039d5c44c161e72217c02e53f9448e23efbb7f3 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Wed, 7 May 2025 10:46:55 +0200 Subject: [PATCH 085/113] Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt Co-authored-by: Sebastien Loriot --- .../doc/Polygon_mesh_processing/Polygon_mesh_processing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index c0ae3307054..2c9c35dc823 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -889,7 +889,7 @@ would then also includes overlaps of duplicated points. The function `CGAL::Polygon_mesh_processing::autorefine_triangle_soup()` provides a way to refine a triangle soup using the intersections of the triangles from the soup. In particular, if some points are duplicated they will be merged. Note that if a kernel with exact predicates but inexact constructions is used, some new self-intersections -might be introduced due to rounding issues of points coordinates. The `apply_iterative_snap_rounding` option can be used to resolve this issue. +might be introduced due to the rounding of the coordinates of intersection points. The `apply_iterative_snap_rounding` option can be used to resolve this issue. When set to `true`, it ensures the coordinates are rounded to fit in `double` with potential additional subdivisions, preventing any self-intersections from occurring. From e1c2c72276d1cad4a29bf1754e1862e56d9b7d90 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Wed, 7 May 2025 10:47:13 +0200 Subject: [PATCH 086/113] Update Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt Co-authored-by: Sebastien Loriot --- .../doc/Polygon_mesh_processing/Polygon_mesh_processing.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index 2c9c35dc823..864bf794472 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -890,7 +890,7 @@ The function `CGAL::Polygon_mesh_processing::autorefine_triangle_soup()` provide using the intersections of the triangles from the soup. In particular, if some points are duplicated they will be merged. Note that if a kernel with exact predicates but inexact constructions is used, some new self-intersections might be introduced due to the rounding of the coordinates of intersection points. The `apply_iterative_snap_rounding` option can be used to resolve this issue. -When set to `true`, it ensures the coordinates are rounded to fit in `double` with potential additional subdivisions, +When set to `true`, it ensures that the coordinates are rounded to fit in `double` with potential additional subdivisions, preventing any self-intersections from occurring. From 01929fe195a7093b22d81303a3a35adbb856c3fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 7 May 2025 14:49:38 +0200 Subject: [PATCH 087/113] rename visitor of triangle_soup_snap_rounding and catch it specifically in autorefinement --- .../Polygon_mesh_processing/snap_polygon_soup.cpp | 6 +++--- .../CGAL/Polygon_mesh_processing/autorefinement.h | 10 +++++++--- .../internal/triangle_soup_snap_rounding.h | 6 +++--- 3 files changed, 13 insertions(+), 9 deletions(-) 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 cc81e6ffbdb..61a69b83ee7 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 @@ -34,6 +34,9 @@ int main(int argc, char** argv) return 1; } + PMP::repair_polygon_soup(points, triangles); + PMP::triangulate_polygons(points, triangles); + std::cout << "#points = " << points.size() << " and #triangles = " << triangles.size() << std::endl; std::cout << "Is 2-manifold: " << PMP::is_polygon_soup_a_polygon_mesh(triangles) << std::endl; @@ -41,9 +44,6 @@ int main(int argc, char** argv) PMP::triangle_soup_self_intersections(points, triangles, std::back_inserter(pairs_of_intersecting_triangles)); std::cout << "Nb of pairs of intersecting triangles: " << pairs_of_intersecting_triangles.size() << std::endl; - PMP::repair_polygon_soup(points, triangles); - PMP::triangulate_polygons(points, triangles); - CGAL::Real_timer t; t.start(); bool success=PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(false).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15)); 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 08914b1de66..67d9ff68197 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -981,6 +981,7 @@ void generate_subtriangles(std::size_t ti, namespace internal{ // Forward declaration +struct Wrap_snap_visitor; template bool polygon_soup_snap_rounding(PointRange &points, PolygonRange &triangles, @@ -1564,7 +1565,8 @@ bool autorefine_triangle_soup(PointRange& soup_points, { triangle_buffer[ti][0]->second, triangle_buffer[ti][1]->second, triangle_buffer[ti][2]->second }; - visitor.internal_new_subtriangle(soup_triangles_out[offset + ti], soup_triangles[tri_inter_ids_inverse[new_triangles[ti].second]]); + if constexpr(std::is_same_v) + visitor.new_subtriangle(soup_triangles_out[offset + ti], soup_triangles[tri_inter_ids_inverse[new_triangles[ti].second]]); } } ); @@ -1579,11 +1581,13 @@ bool autorefine_triangle_soup(PointRange& soup_points, soup_triangles_out.reserve(offset + new_triangles.size()); for (const std::pair, std::size_t>& t_and_id : new_triangles) { - visitor.new_subtriangle(soup_triangles_out.size(), tri_inter_ids_inverse[t_and_id.second]); + if constexpr(std::is_same_v) + visitor.new_subtriangle(soup_triangles_out[soup_triangles_out.size()-1], soup_triangles[tri_inter_ids_inverse[t_and_id.second]]); + else + visitor.new_subtriangle(soup_triangles_out.size(), tri_inter_ids_inverse[t_and_id.second]); soup_triangles_out.push_back({ get_point_id(t_and_id.first[0]), get_point_id(t_and_id.first[1]), get_point_id(t_and_id.first[2]) }); - visitor.internal_new_subtriangle(soup_triangles_out[soup_triangles_out.size()-1], soup_triangles[tri_inter_ids_inverse[t_and_id.second]]); } } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 0bf4de2552e..1c2fdec462c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -158,10 +158,10 @@ void repair_triangle_soup(PointRange& points, } // A visitor of Autorefinement to track the correspondance between input and output triangles -struct Wrap_id_visitor : public Autorefinement::Default_visitor +struct Wrap_snap_visitor : public Autorefinement::Default_visitor { template< typename Triangle> - void internal_new_subtriangle(Triangle& new_t, const Triangle& old_t) { + void new_subtriangle(Triangle& new_t, const Triangle& old_t) { new_t.set_id(old_t.id()); } }; @@ -531,7 +531,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, #endif if constexpr(has_visitor) { - Wrap_id_visitor visitor; + Wrap_snap_visitor visitor; autorefine_triangle_soup(points, triangles, parameters::point_map(pm).concurrency_tag(Concurrency_tag()).visitor(visitor)); } else From 8917e119f25394fe0b96111c723dfa6d9d7d0fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 7 May 2025 14:50:51 +0200 Subject: [PATCH 088/113] Changes.md --- Installation/CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index c52ea9139f0..95832ccb374 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -9,7 +9,7 @@ ### [Polygon Mesh Processing](https://doc.cgal.org/6.1/Manual/packages.html#PkgPolygonMeshProcessing) - Added the function `CGAL::Polygon_mesh_processing::discrete_mean_curvature` and `CGAL::Polygon_mesh_processing::discrete_Guassian_curvature` to evaluate the discrete curvature at a vertex of a mesh. - Added the function `CGAL::Polygon_mesh_processing::angle_sum` to compute the sum of the angles around a vertex. - +- Added the parameter `apply_iterative_snap_rounding` to the function `CGAL::Polygon_mesh_processing::autorefine_triangle_soup`. When set to `true`, the coordinates are rounded to fit in double and may perform additional subdivisions to ensure the output remains free of self-intersections. ### [Algebraic Kernel](https://doc.cgal.org/6.1/Manual/packages.html#PkgAlgebraicKernelD) From e1da8c31a17930201dfa0d8b71f8e113d8c22454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 7 May 2025 15:32:17 +0200 Subject: [PATCH 089/113] Change namespace from internal to autorefine_impl --- .../Polygon_mesh_processing/autorefinement.h | 15 +++------ .../internal/triangle_soup_snap_rounding.h | 32 ++++++++++--------- 2 files changed, 22 insertions(+), 25 deletions(-) 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 67d9ff68197..2f91e709833 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -90,10 +90,6 @@ struct Default_visitor inline void verbatim_triangle_copy(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} inline void new_subtriangle(std::size_t /*tgt_id*/, std::size_t /*src_id*/) {} inline void delete_triangle(std::size_t /*src_id*/) {} - - // Not documented - template< typename Triangle> - inline void internal_new_subtriangle(Triangle& /*new_t*/ , const Triangle& /*old_t*/) {} }; } // end of Autorefinement visitor @@ -979,7 +975,7 @@ void generate_subtriangles(std::size_t ti, } // end of autorefine_impl #endif -namespace internal{ +namespace autorefine_impl{ // Forward declaration struct Wrap_snap_visitor; template @@ -1419,8 +1415,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, { if (is_degen[f]) { - if constexpr (!std::is_same_v) - visitor.delete_triangle(f); + visitor.delete_triangle(f); continue; //skip degenerate faces } @@ -1616,7 +1611,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, return true; } -} // end of internal +} // end of autorefine_impl /** * \ingroup PMP_corefinement_grp @@ -1703,11 +1698,11 @@ bool autorefine_triangle_soup(PointRange& soup_points, if(do_snap) { CGAL_PMP_AUTOREFINE_VERBOSE("Snap polygon soup"); - return internal::polygon_soup_snap_rounding(soup_points, soup_triangles, np); + return autorefine_impl::polygon_soup_snap_rounding(soup_points, soup_triangles, np); } else { - return internal::autorefine_triangle_soup(soup_points, soup_triangles, np); + return autorefine_impl::autorefine_triangle_soup(soup_points, soup_triangles, np); } } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 1c2fdec462c..623db2cb67e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -28,7 +28,7 @@ namespace CGAL namespace Polygon_mesh_processing { -namespace internal +namespace autorefine_impl { // Certified ceil function for exact number types @@ -79,7 +79,9 @@ public: Indexes_range() = default; Indexes_range(const std::initializer_list &l): Range(l), m_id(0), modified(true){} Indexes_range(Range &p): Range(p), modified(true){} + Indexes_range(Range &&p): Range(std::move(p)), modified(true){} Indexes_range(Range &p, std::size_t id): Range(p), m_id(id),modified(false){} + Indexes_range(Range &&p, std::size_t id): Range(std::move(p)), m_id(id),modified(false){} inline std::size_t id() const { return m_id; } inline void set_id(std::size_t id){ m_id=id; } @@ -103,14 +105,14 @@ struct Triangle_soup_fixer using parameters::get_parameter; using parameters::choose_parameter; - typedef typename GetPolygonGeomTraits::type Traits; + typedef typename CGAL::Polygon_mesh_processing::internal::GetPolygonGeomTraits::type Traits; Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); - merge_duplicate_points_in_polygon_soup(points, polygons, np); - simplify_polygons_in_polygon_soup(points, polygons, traits); - remove_invalid_polygons_in_polygon_soup(points, polygons); - merge_duplicate_polygons_in_polygon_soup(points, polygons, np); - remove_isolated_points_in_polygon_soup(points, polygons); + CGAL::Polygon_mesh_processing::merge_duplicate_points_in_polygon_soup(points, polygons, np); + CGAL::Polygon_mesh_processing::internal::simplify_polygons_in_polygon_soup(points, polygons, traits); + CGAL::Polygon_mesh_processing::internal::remove_invalid_polygons_in_polygon_soup(points, polygons); + CGAL::Polygon_mesh_processing::merge_duplicate_polygons_in_polygon_soup(points, polygons, np); + CGAL::Polygon_mesh_processing::remove_isolated_points_in_polygon_soup(points, polygons); } }; @@ -138,13 +140,13 @@ struct Triangle_soup_fixer::type Traits; + typedef typename CGAL::Polygon_mesh_processing::internal::GetPolygonGeomTraits::type Traits; Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); - merge_duplicate_points_in_polygon_soup(points, polygons, np); - remove_invalid_polygons_in_array_polygon_soup(points, polygons, traits); - merge_duplicate_polygons_in_polygon_soup(points, polygons, np); - remove_isolated_points_in_polygon_soup(points, polygons); + CGAL::Polygon_mesh_processing::merge_duplicate_points_in_polygon_soup(points, polygons, np); + CGAL::Polygon_mesh_processing::internal::remove_invalid_polygons_in_array_polygon_soup(points, polygons, traits); + CGAL::Polygon_mesh_processing::merge_duplicate_polygons_in_polygon_soup(points, polygons, np); + CGAL::Polygon_mesh_processing::remove_isolated_points_in_polygon_soup(points, polygons); } }; @@ -292,7 +294,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, auto snap = [](typename Kernel::FT x, double scale) { // Scale the coordinate, round to nearest integer and scale back - return internal::double_ceil((x * scale) - 0.5) / scale; + return double_ceil((x * scale) - 0.5) / scale; }; auto snap_p = [scale, snap](const Point_3 &p) { @@ -301,7 +303,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, snap(p.z(),scale[2]) ); }; - for (std::size_t i = 0; i <= max_nb_of_iteration; ++i) + for (std::size_t i = 0; i < max_nb_of_iteration; ++i) { #ifdef PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE std::cout << "Start Iteration " << i << std::endl; @@ -577,6 +579,6 @@ bool polygon_soup_snap_rounding(PointRange &soup_points, } } -} } } //end of CGAL::Polygon_mesh_processing::internal namespace +} } } //end of CGAL::Polygon_mesh_processing::autorefine_impl namespace #endif //CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_SNAP_ROUNDING_H From 863c86edfc3fd80898d5bf8ce56c1e43485a5067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 7 May 2025 15:52:47 +0200 Subject: [PATCH 090/113] rename internal function of snap visitor new_subtriangle to new_subdivision --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 4 ++-- .../internal/triangle_soup_snap_rounding.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 2f91e709833..c273e36f064 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1561,7 +1561,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, triangle_buffer[ti][1]->second, triangle_buffer[ti][2]->second }; if constexpr(std::is_same_v) - visitor.new_subtriangle(soup_triangles_out[offset + ti], soup_triangles[tri_inter_ids_inverse[new_triangles[ti].second]]); + visitor.new_subdivision(soup_triangles_out[offset + ti], soup_triangles[tri_inter_ids_inverse[new_triangles[ti].second]]); } } ); @@ -1577,7 +1577,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, for (const std::pair, std::size_t>& t_and_id : new_triangles) { if constexpr(std::is_same_v) - visitor.new_subtriangle(soup_triangles_out[soup_triangles_out.size()-1], soup_triangles[tri_inter_ids_inverse[t_and_id.second]]); + visitor.new_subdivision(soup_triangles_out[soup_triangles_out.size()-1], soup_triangles[tri_inter_ids_inverse[t_and_id.second]]); else visitor.new_subtriangle(soup_triangles_out.size(), tri_inter_ids_inverse[t_and_id.second]); soup_triangles_out.push_back({ get_point_id(t_and_id.first[0]), diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 623db2cb67e..278dac77c10 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -163,7 +163,7 @@ void repair_triangle_soup(PointRange& points, struct Wrap_snap_visitor : public Autorefinement::Default_visitor { template< typename Triangle> - void new_subtriangle(Triangle& new_t, const Triangle& old_t) { + void new_subdivision(Triangle& new_t, const Triangle& old_t) { new_t.set_id(old_t.id()); } }; From e989bb56b0aea195e39bf557e5532fce4b74d37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 7 May 2025 17:12:21 +0200 Subject: [PATCH 091/113] fix namespace --- .../internal/triangle_soup_snap_rounding.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 278dac77c10..4a2e8e77e44 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -105,7 +106,7 @@ struct Triangle_soup_fixer using parameters::get_parameter; using parameters::choose_parameter; - typedef typename CGAL::Polygon_mesh_processing::internal::GetPolygonGeomTraits::type Traits; + typedef typename GetPolygonGeomTraits::type Traits; Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); CGAL::Polygon_mesh_processing::merge_duplicate_points_in_polygon_soup(points, polygons, np); @@ -140,7 +141,7 @@ struct Triangle_soup_fixer::type Traits; + typedef typename GetPolygonGeomTraits::type Traits; Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); CGAL::Polygon_mesh_processing::merge_duplicate_points_in_polygon_soup(points, polygons, np); From 8edbef468b0dd145ed78b2c0a93df56d3a923df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 7 May 2025 19:07:46 +0200 Subject: [PATCH 092/113] solved bug when visitor is visited a triangle before its creation --- .../CGAL/Polygon_mesh_processing/autorefinement.h | 8 ++++---- .../internal/triangle_soup_snap_rounding.h | 2 +- .../test_snap_rounding.cpp | 15 ++++++++++----- 3 files changed, 15 insertions(+), 10 deletions(-) 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 c273e36f064..63cf789d0cc 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1576,13 +1576,13 @@ bool autorefine_triangle_soup(PointRange& soup_points, soup_triangles_out.reserve(offset + new_triangles.size()); for (const std::pair, std::size_t>& t_and_id : new_triangles) { - if constexpr(std::is_same_v) - visitor.new_subdivision(soup_triangles_out[soup_triangles_out.size()-1], soup_triangles[tri_inter_ids_inverse[t_and_id.second]]); - else - visitor.new_subtriangle(soup_triangles_out.size(), tri_inter_ids_inverse[t_and_id.second]); soup_triangles_out.push_back({ get_point_id(t_and_id.first[0]), get_point_id(t_and_id.first[1]), get_point_id(t_and_id.first[2]) }); + if constexpr(std::is_same_v) + visitor.new_subdivision(soup_triangles_out[soup_triangles_out.size()-1], soup_triangles[tri_inter_ids_inverse[t_and_id.second]]); + else + visitor.new_subtriangle(soup_triangles_out.size()-1, tri_inter_ids_inverse[t_and_id.second]); } } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 4a2e8e77e44..48021113d6b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -95,7 +95,7 @@ private: // Repair_polygon_soup without remove_pinched_polygons since our polygon are triangles template ::Polygon_3> + typename Polygon = typename ::CGAL::Polygon_mesh_processing::internal::Polygon_types::Polygon_3> struct Triangle_soup_fixer { template diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp index b8d8689a752..1a1f899b959 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp @@ -32,7 +32,7 @@ struct My_visitor : public PMP::Autorefinement::Default_visitor void number_of_output_triangles(std::size_t nbt) { tgt_check.assign(expected_nb_output, 0); - assert(nbt==expected_nb_output); + // assert(nbt==expected_nb_output); } void verbatim_triangle_copy(std::size_t tgt_id, std::size_t src_id) @@ -62,7 +62,7 @@ struct My_visitor : public PMP::Autorefinement::Default_visitor }; template -void test(const char* fname, std::size_t nb_vertices_after_autorefine, std::size_t expected_nb_output, Tag tag) +void test(const std::string fname, std::size_t nb_vertices_after_autorefine, std::size_t expected_nb_output, Tag tag) { std::cout << "Running tests on " << fname; if (std::is_same_v) @@ -80,11 +80,16 @@ void test(const char* fname, std::size_t nb_vertices_after_autorefine, std::size // Testing autorefine() My_visitor visitor(triangles.size(), expected_nb_output); - PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::visitor(visitor).concurrency_tag(tag).apply_iterative_snap_rounding(true)); + PMP::repair_polygon_soup(points, triangles); + PMP::triangulate_polygons(points, triangles); + PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::visitor(visitor).concurrency_tag(tag).erase_all_duplicates(false).apply_iterative_snap_rounding(true)); + // PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::concurrency_tag(tag).erase_all_duplicates(false).apply_iterative_snap_rounding(true).snap_grid_size(23).number_of_iterations(15)); + CGAL::IO::write_polygon_soup("/tmp/debug.off", points, triangles); assert( nb_vertices_after_autorefine==points.size()); assert( expected_nb_output==triangles.size()); assert( !PMP::does_triangle_soup_self_intersect(points, triangles) ); -// CGAL::IO::write_polygon_soup("/tmp/debug.off", points, triangles); + CGAL::IO::write_polygon_soup("/tmp/debug.off", points, triangles); + } int main(int argc, const char** argv) @@ -92,7 +97,7 @@ int main(int argc, const char** argv) // file expected_nb_of_vertices expected_nb_of_faces (after repair) for (int i=0;i<(argc-1)/3; ++i) { - test(argv[1+3*i], atoi(argv[1+3*i+1]), atoi(argv[1+3*i+2]), CGAL::Sequential_tag()); + test(std::string("/home/lvalque/CGAL/git/PMP_triangle_soup_rounding-GF/Polygon_mesh_processing/test/Polygon_mesh_processing/")+argv[1+3*i], atoi(argv[1+3*i+1]), atoi(argv[1+3*i+2]), CGAL::Sequential_tag()); #ifdef CGAL_LINKED_WITH_TBB test(argv[1+3*i], atoi(argv[1+3*i+1]), atoi(argv[1+3*i+2]), CGAL::Parallel_tag()); #endif From 0197d1bfd5c2f384ce6926d67870cee4a768cc27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 7 May 2025 19:12:07 +0200 Subject: [PATCH 093/113] Revert "solved bug when visitor is visited a triangle before its creation" This reverts commit f4f37cc82ba3e0135e5e9289b6890ab7257694d5. --- .../CGAL/Polygon_mesh_processing/autorefinement.h | 8 ++++---- .../internal/triangle_soup_snap_rounding.h | 2 +- .../test_snap_rounding.cpp | 15 +++++---------- 3 files changed, 10 insertions(+), 15 deletions(-) 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 63cf789d0cc..c273e36f064 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1576,13 +1576,13 @@ bool autorefine_triangle_soup(PointRange& soup_points, soup_triangles_out.reserve(offset + new_triangles.size()); for (const std::pair, std::size_t>& t_and_id : new_triangles) { - soup_triangles_out.push_back({ get_point_id(t_and_id.first[0]), - get_point_id(t_and_id.first[1]), - get_point_id(t_and_id.first[2]) }); if constexpr(std::is_same_v) visitor.new_subdivision(soup_triangles_out[soup_triangles_out.size()-1], soup_triangles[tri_inter_ids_inverse[t_and_id.second]]); else - visitor.new_subtriangle(soup_triangles_out.size()-1, tri_inter_ids_inverse[t_and_id.second]); + visitor.new_subtriangle(soup_triangles_out.size(), tri_inter_ids_inverse[t_and_id.second]); + soup_triangles_out.push_back({ get_point_id(t_and_id.first[0]), + get_point_id(t_and_id.first[1]), + get_point_id(t_and_id.first[2]) }); } } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 48021113d6b..4a2e8e77e44 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -95,7 +95,7 @@ private: // Repair_polygon_soup without remove_pinched_polygons since our polygon are triangles template ::Polygon_3> + typename Polygon = typename ::CGAL::internal::Polygon_types::Polygon_3> struct Triangle_soup_fixer { template diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp index 1a1f899b959..b8d8689a752 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cpp @@ -32,7 +32,7 @@ struct My_visitor : public PMP::Autorefinement::Default_visitor void number_of_output_triangles(std::size_t nbt) { tgt_check.assign(expected_nb_output, 0); - // assert(nbt==expected_nb_output); + assert(nbt==expected_nb_output); } void verbatim_triangle_copy(std::size_t tgt_id, std::size_t src_id) @@ -62,7 +62,7 @@ struct My_visitor : public PMP::Autorefinement::Default_visitor }; template -void test(const std::string fname, std::size_t nb_vertices_after_autorefine, std::size_t expected_nb_output, Tag tag) +void test(const char* fname, std::size_t nb_vertices_after_autorefine, std::size_t expected_nb_output, Tag tag) { std::cout << "Running tests on " << fname; if (std::is_same_v) @@ -80,16 +80,11 @@ void test(const std::string fname, std::size_t nb_vertices_after_autorefine, std // Testing autorefine() My_visitor visitor(triangles.size(), expected_nb_output); - PMP::repair_polygon_soup(points, triangles); - PMP::triangulate_polygons(points, triangles); - PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::visitor(visitor).concurrency_tag(tag).erase_all_duplicates(false).apply_iterative_snap_rounding(true)); - // PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::concurrency_tag(tag).erase_all_duplicates(false).apply_iterative_snap_rounding(true).snap_grid_size(23).number_of_iterations(15)); - CGAL::IO::write_polygon_soup("/tmp/debug.off", points, triangles); + PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::visitor(visitor).concurrency_tag(tag).apply_iterative_snap_rounding(true)); assert( nb_vertices_after_autorefine==points.size()); assert( expected_nb_output==triangles.size()); assert( !PMP::does_triangle_soup_self_intersect(points, triangles) ); - CGAL::IO::write_polygon_soup("/tmp/debug.off", points, triangles); - +// CGAL::IO::write_polygon_soup("/tmp/debug.off", points, triangles); } int main(int argc, const char** argv) @@ -97,7 +92,7 @@ int main(int argc, const char** argv) // file expected_nb_of_vertices expected_nb_of_faces (after repair) for (int i=0;i<(argc-1)/3; ++i) { - test(std::string("/home/lvalque/CGAL/git/PMP_triangle_soup_rounding-GF/Polygon_mesh_processing/test/Polygon_mesh_processing/")+argv[1+3*i], atoi(argv[1+3*i+1]), atoi(argv[1+3*i+2]), CGAL::Sequential_tag()); + test(argv[1+3*i], atoi(argv[1+3*i+1]), atoi(argv[1+3*i+2]), CGAL::Sequential_tag()); #ifdef CGAL_LINKED_WITH_TBB test(argv[1+3*i], atoi(argv[1+3*i+1]), atoi(argv[1+3*i+2]), CGAL::Parallel_tag()); #endif From b01eb047df91efa2b94f3102277cc85cf89b2872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 7 May 2025 19:13:14 +0200 Subject: [PATCH 094/113] Solve a bug when visitor is called before the creation of the associated triangle --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 c273e36f064..d5df6c67eaa 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1576,13 +1576,13 @@ bool autorefine_triangle_soup(PointRange& soup_points, soup_triangles_out.reserve(offset + new_triangles.size()); for (const std::pair, std::size_t>& t_and_id : new_triangles) { + soup_triangles_out.push_back({ get_point_id(t_and_id.first[0]), + get_point_id(t_and_id.first[1]), + get_point_id(t_and_id.first[2]) }); if constexpr(std::is_same_v) visitor.new_subdivision(soup_triangles_out[soup_triangles_out.size()-1], soup_triangles[tri_inter_ids_inverse[t_and_id.second]]); else visitor.new_subtriangle(soup_triangles_out.size(), tri_inter_ids_inverse[t_and_id.second]); - soup_triangles_out.push_back({ get_point_id(t_and_id.first[0]), - get_point_id(t_and_id.first[1]), - get_point_id(t_and_id.first[2]) }); } } From 9d14651328989b99b8e702b1705bdf74e88cfb69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 7 May 2025 19:13:51 +0200 Subject: [PATCH 095/113] with the good index --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d5df6c67eaa..63cf789d0cc 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1582,7 +1582,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, if constexpr(std::is_same_v) visitor.new_subdivision(soup_triangles_out[soup_triangles_out.size()-1], soup_triangles[tri_inter_ids_inverse[t_and_id.second]]); else - visitor.new_subtriangle(soup_triangles_out.size(), tri_inter_ids_inverse[t_and_id.second]); + visitor.new_subtriangle(soup_triangles_out.size()-1, tri_inter_ids_inverse[t_and_id.second]); } } From c53223576f6cfd200d9ad7083d7dca2e8ed1b607 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Mon, 12 May 2025 11:27:58 +0200 Subject: [PATCH 096/113] Update Polygon_mesh_processing/benchmark/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp Co-authored-by: Andreas Fabri --- .../Polygon_mesh_processing/rotated_cubes_autorefinement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp index b0cfa6b15b9..69ae0b8c83e 100644 --- a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/rotated_cubes_autorefinement.cpp @@ -104,7 +104,7 @@ int main(int argc, char** argv) bool success=PMP::autorefine_triangle_soup(points, faces, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag())); t.stop(); if(!success){ - std::cout << "Round failed" << std::endl; + std::cout << "Rounding failed" << std::endl; exit(0); } From d4626c8fa26f30d8aec081a31315b1d8490abfe3 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Mon, 12 May 2025 11:28:11 +0200 Subject: [PATCH 097/113] Update Polygon_mesh_processing/benchmark/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp Co-authored-by: Andreas Fabri --- .../Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp index af178634597..b97ed8f0365 100644 --- a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/coplanar_cubes_autorefinement.cpp @@ -102,7 +102,7 @@ int main(int argc, char** argv) bool success=PMP::autorefine_triangle_soup(points, faces, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(true).concurrency_tag(CGAL::Parallel_if_available_tag())); t.stop(); if(!success){ - std::cout << "Round failed" << std::endl; + std::cout << "Rounding failed" << std::endl; exit(0); } From db443009560d8ae069c683708d3a0fb9b0474ce8 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Mon, 12 May 2025 11:36:21 +0200 Subject: [PATCH 098/113] Update Installation/CHANGES.md Co-authored-by: Andreas Fabri --- Installation/CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 95832ccb374..416e7dd5ae6 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -9,7 +9,7 @@ ### [Polygon Mesh Processing](https://doc.cgal.org/6.1/Manual/packages.html#PkgPolygonMeshProcessing) - Added the function `CGAL::Polygon_mesh_processing::discrete_mean_curvature` and `CGAL::Polygon_mesh_processing::discrete_Guassian_curvature` to evaluate the discrete curvature at a vertex of a mesh. - Added the function `CGAL::Polygon_mesh_processing::angle_sum` to compute the sum of the angles around a vertex. -- Added the parameter `apply_iterative_snap_rounding` to the function `CGAL::Polygon_mesh_processing::autorefine_triangle_soup`. When set to `true`, the coordinates are rounded to fit in double and may perform additional subdivisions to ensure the output remains free of self-intersections. +- Added the parameter `apply_iterative_snap_rounding` to the function `CGAL::Polygon_mesh_processing::autorefine_triangle_soup()`. When set to `true`, the coordinates are rounded to fit in double and may perform additional subdivisions to ensure the output remains free of self-intersections. ### [Algebraic Kernel](https://doc.cgal.org/6.1/Manual/packages.html#PkgAlgebraicKernelD) From 91ee4fa605357dbb7b77775dbd1dcbc960dd3457 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 12 May 2025 13:16:14 +0100 Subject: [PATCH 099/113] Workaround for Visual 2017 --- .../Polygon_mesh_processing/autorefinement.h | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) 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 63cf789d0cc..03d92e7a2e7 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1552,19 +1552,33 @@ bool autorefine_triangle_soup(PointRange& soup_points, } ); - tbb::parallel_for(tbb::blocked_range(0, new_triangles.size()), - [&](const tbb::blocked_range& r) { - for (size_t ti = r.begin(); ti != r.end(); ++ti) - { - soup_triangles_out[offset + ti] = - { triangle_buffer[ti][0]->second, - triangle_buffer[ti][1]->second, - triangle_buffer[ti][2]->second }; - if constexpr(std::is_same_v) - visitor.new_subdivision(soup_triangles_out[offset + ti], soup_triangles[tri_inter_ids_inverse[new_triangles[ti].second]]); + // The constexpr was initially inside the lammbda, but that did not compile with VC 2017 + if constexpr(std::is_same_v){ + tbb::parallel_for(tbb::blocked_range(0, new_triangles.size()), + [&](const tbb::blocked_range& r) { + for (size_t ti = r.begin(); ti != r.end(); ++ti) + { + soup_triangles_out[offset + ti] = + { triangle_buffer[ti][0]->second, + triangle_buffer[ti][1]->second, + triangle_buffer[ti][2]->second }; + visitor.new_subdivision(soup_triangles_out[offset + ti], soup_triangles[tri_inter_ids_inverse[new_triangles[ti].second]]); + } } - } - ); + ); + }else{ + tbb::parallel_for(tbb::blocked_range(0, new_triangles.size()), + [&](const tbb::blocked_range& r) { + for (size_t ti = r.begin(); ti != r.end(); ++ti) + { + soup_triangles_out[offset + ti] = + { triangle_buffer[ti][0]->second, + triangle_buffer[ti][1]->second, + triangle_buffer[ti][2]->second }; + } + } + ); + } #endif } else From bc0478d53c7afb40820d6b74d8019c763f1db5a8 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Mon, 19 May 2025 09:59:41 +0200 Subject: [PATCH 100/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h Co-authored-by: Andreas Fabri --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 4a2e8e77e44..cf37b048e55 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -201,7 +201,7 @@ struct Wrap_snap_visitor : public Autorefinement::Default_visitor * \cgalParamNBegin{geom_traits} * \cgalParamDescription{an instance of a geometric traits class} * \cgalParamType{a class model of `Kernel`} -* \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} +* \cgalParamDefault{a \cgal kernel deduced from the point type, using `CGAL::Kernel_traits`} * \cgalParamExtra{The geometric traits class must be compatible with the point type.} * \cgalParamNEnd * \cgalParamNBegin{snap_grid_size} From a8eb8c737cc181daa36afb451f870591ef1c3dfd Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Mon, 19 May 2025 10:01:04 +0200 Subject: [PATCH 101/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h Co-authored-by: Andreas Fabri --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index cf37b048e55..ecd2576db6d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -173,7 +173,7 @@ struct Wrap_snap_visitor : public Autorefinement::Default_visitor * * Rounds the coordinates of the points so that they fit in doubles while making and keeping the model intersection free by potentially subdividing the triangles. * The input can be any triangle soup and the output is an intersection-free triangle soup with Hausdorff distance -* between the input and the output bounded by M*2^-gs*k where M is the maximum absolute coordinate in the model, gs the snap_grid_size (see below) and k the number of iteration +* between the input and the output bounded by `M*2^-gs*k` where `M`is the maximum absolute coordinate in the model, `gs` the `snap_grid_size` (see below) and `k` the number of iterations * performed by the algorithm. * * @tparam PointRange a model of the concept `RandomAccessContainer` From 2fc5fde73b394a6131530b3254c55511177fa92c Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Mon, 19 May 2025 10:01:24 +0200 Subject: [PATCH 102/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h Co-authored-by: Andreas Fabri --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index ecd2576db6d..360ca8c1a9a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -171,7 +171,7 @@ struct Wrap_snap_visitor : public Autorefinement::Default_visitor /** * -* Rounds the coordinates of the points so that they fit in doubles while making and keeping the model intersection free by potentially subdividing the triangles. +* rounds the coordinates of the points so that they fit in doubles while making and keeping the model intersection free by potentially subdividing the triangles. * The input can be any triangle soup and the output is an intersection-free triangle soup with Hausdorff distance * between the input and the output bounded by `M*2^-gs*k` where `M`is the maximum absolute coordinate in the model, `gs` the `snap_grid_size` (see below) and `k` the number of iterations * performed by the algorithm. From 20526dddda3c7697a7d6d14a1eba54b53d242498 Mon Sep 17 00:00:00 2001 From: lvalque <131978677+LeoValque@users.noreply.github.com> Date: Tue, 20 May 2025 17:08:31 +0200 Subject: [PATCH 103/113] Apply suggestions from code review Co-authored-by: Andreas Fabri --- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 1 + 1 file changed, 1 insertion(+) 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 03d92e7a2e7..11e9a61dbee 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -978,6 +978,7 @@ void generate_subtriangles(std::size_t ti, namespace autorefine_impl{ // Forward declaration struct Wrap_snap_visitor; + template bool polygon_soup_snap_rounding(PointRange &points, PolygonRange &triangles, From c20e51715061b85ff22635cd5a973549549384b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 20 May 2025 17:38:26 +0200 Subject: [PATCH 104/113] Modification for review of Andres --- .../doc/Polygon_mesh_processing/examples.txt | 1 + .../CGAL/Polygon_mesh_processing/autorefinement.h | 7 +++++-- .../internal/triangle_soup_snap_rounding.h | 14 +++++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt index dba765d7f6a..181475dfc6c 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt @@ -52,4 +52,5 @@ \example Polygon_mesh_processing/remesh_almost_planar_patches.cpp \example Polygon_mesh_processing/sample_example.cpp \example Polygon_mesh_processing/soup_autorefinement.cpp +\example Polygon_mesh_processing/snap_polygon_soup.cpp */ 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 11e9a61dbee..37f1c7af220 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1696,8 +1696,11 @@ bool autorefine_triangle_soup(PointRange& soup_points, * \cgalParamNEnd * \cgalNamedParamsEnd * -* \return `true` if `apply_iterative_snap_rounding` is set to `false`; otherwise, returns `true` if the modified triangle soup is free from -* self-intersection, and `false` if the algorithm was unable to provide such a triangle soup within the number of iterations. +* \return `true` if `apply_iterative_snap_rounding` is set to `false`. +* Otherwise, returns `true` if the modified triangle soup is free of self-intersections, +* or `false` if the algorithm was unable to produce such a result within the allowed number of iterations. +* In the latter case, the output triangle soup represents a partial result from the final iteration, +* with no guarantee of its validity. * */ template diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 360ca8c1a9a..cea03a65fbd 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -69,7 +69,7 @@ double double_ceil(const NT &x){ } }; -// Color a range by an index, it is used by the visitor to track the correspondance between the input and the output +// Provide an index to the range, it is used by the visitor to track the correspondance between the input and the output template class Indexes_range : public Range{ typedef std::remove_cv_t::value_type> Value_type; @@ -106,7 +106,7 @@ struct Triangle_soup_fixer using parameters::get_parameter; using parameters::choose_parameter; - typedef typename GetPolygonGeomTraits::type Traits; + using Traits = typename ::CGAL::Polygon_mesh_processing::internal::GetPolygonGeomTraits::type; Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); CGAL::Polygon_mesh_processing::merge_duplicate_points_in_polygon_soup(points, polygons, np); @@ -141,7 +141,7 @@ struct Triangle_soup_fixer::type Traits; + using Traits = typename ::CGAL::Polygon_mesh_processing::internal::GetPolygonGeomTraits::type; Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); CGAL::Polygon_mesh_processing::merge_duplicate_points_in_polygon_soup(points, polygons, np); @@ -410,7 +410,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, Point_3 center = snap_p(points[v[0]]); size_t argmin(0); for(size_t i=1; i!=v.size(); ++i){ - if(Kernel().compare_squared_distance_3_object()(center, points[v[i]], center, points[v[argmin]])==SMALLER) + if(Kernel().compare_distance_3_object()(center, points[v[i]], points[v[argmin]])==SMALLER) { argmin=i; } @@ -427,7 +427,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, // Group the points of the vertices of the intersecting triangles by their voxel std::map snap_points; std::size_t index=0; - for (auto &pair : pairs_of_intersecting_triangles) + for (const auto &pair : pairs_of_intersecting_triangles) { for (size_t pi : triangles[pair.first]) { @@ -473,7 +473,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, #elif defined(PMP_ROUNDING_VERTICES_FLOAT_SNAP) // Version where points are rounded to the closest simple precision float. - for (auto &pair : pairs_of_intersecting_triangles) + for (const auto &pair : pairs_of_intersecting_triangles) { for (size_t pi : triangles[pair.first]) points[pi]=Point_3( (float) to_double(points[pi].x()), (float) to_double(points[pi].y()), (float) to_double(points[pi].z())); @@ -489,7 +489,7 @@ bool polygon_soup_snap_rounding_impl(PointRange &points, std::vector snap_points; snap_points.reserve(pairs_of_intersecting_triangles.size() * 3); - for (auto &pair : pairs_of_intersecting_triangles) + for (const auto &pair : pairs_of_intersecting_triangles) { for (size_t pi : triangles[pair.first]) snap_points.emplace_back(snap_p(points[pi])); From 99e53acafa85bd20f05e594a6c58db1168b999d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 20 May 2025 17:39:16 +0200 Subject: [PATCH 105/113] put new named_parameter at the good place --- .../CGAL/STL_Extension/internal/parameters_interface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 393b0666d4f..5832f79203f 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -164,6 +164,8 @@ CGAL_add_named_parameter(region_primitive_map_t, region_primitive_map, region_pr CGAL_add_named_parameter(postprocess_regions_t, postprocess_regions, postprocess_regions) CGAL_add_named_parameter(sizing_function_t, sizing_function, sizing_function) CGAL_add_named_parameter(bbox_scaling_t, bbox_scaling, bbox_scaling) +CGAL_add_named_parameter(apply_iterative_snap_rounding_t, apply_iterative_snap_rounding, apply_iterative_snap_rounding) +CGAL_add_named_parameter(snap_grid_size_t, snap_grid_size, snap_grid_size) // List of named parameters that we use in the package 'Surface Mesh Simplification' CGAL_add_named_parameter(get_cost_policy_t, get_cost_policy, get_cost) @@ -220,8 +222,6 @@ 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(apply_iterative_snap_rounding_t, apply_iterative_snap_rounding, apply_iterative_snap_rounding) -CGAL_add_named_parameter(snap_grid_size_t, snap_grid_size, snap_grid_size) // List of named parameters used in Surface_mesh_approximation package CGAL_add_named_parameter(verbose_level_t, verbose_level, verbose_level) From 549b8f1430d99e8b6818cd4c03c0a57f80123beb Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 20 May 2025 18:15:08 +0200 Subject: [PATCH 106/113] Update Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h --- .../internal/triangle_soup_snap_rounding.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index cea03a65fbd..00027fba4d5 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -69,7 +69,7 @@ double double_ceil(const NT &x){ } }; -// Provide an index to the range, it is used by the visitor to track the correspondance between the input and the output +// Provides an index to the range, which is used by the visitor to track the correspondence between the input and the output template class Indexes_range : public Range{ typedef std::remove_cv_t::value_type> Value_type; From 100ab58f33027945846d698418f7954d49fe4e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Tue, 20 May 2025 18:36:33 +0200 Subject: [PATCH 107/113] Benchmark script for Nicolas --- .../performance_snap_polygon_soup.cpp | 50 ++++++++ .../Performance/run_performance.sh | 28 +++++ .../Quality/quality_snap_polygon_soup.cpp | 60 +++++++++ .../Quality/run_quality.sh | 19 +++ .../robustness_snap_polygon_soup.cpp | 53 ++++++++ .../Robustness/run_robustness.sh | 38 ++++++ .../benchmarking_snap_polygon_soup.sh | 116 ++++++++++++++++++ 7 files changed, 364 insertions(+) create mode 100644 Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Performance/performance_snap_polygon_soup.cpp create mode 100755 Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Performance/run_performance.sh create mode 100644 Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Quality/quality_snap_polygon_soup.cpp create mode 100755 Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Quality/run_quality.sh create mode 100644 Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Robustness/robustness_snap_polygon_soup.cpp create mode 100755 Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Robustness/run_robustness.sh create mode 100755 Polygon_mesh_processing/benchmark/Polygon_mesh_processing/benchmarking_snap_polygon_soup.sh diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Performance/performance_snap_polygon_soup.cpp b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Performance/performance_snap_polygon_soup.cpp new file mode 100644 index 00000000000..d64cb27da9b --- /dev/null +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Performance/performance_snap_polygon_soup.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include + +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef typename Kernel::Point_3 Point_3; +namespace PMP = CGAL::Polygon_mesh_processing; + +enum EXIT_CODES { VALID_OUTPUT=0, + INVALID_INPUT=1, + ROUNDING_FAILED=2, + SIGSEGV=10, + SIGSABRT=11, + SIGFPE=12, + TIMEOUT=13 + }; + +int main(int argc, char** argv) +{ + if(argc<4){ + std::cout << "Invalid argument" << std::endl; + return 1; + } + + const std::string filename = std::string(argv[1]); + const int grid_size = std::stoi(std::string(argv[2])); + const bool erase_duplicate = std::stoi(argv[3])==1; + + std::vector points; + std::vector> triangles; + + if (!CGAL::IO::read_polygon_soup(filename, points, triangles)) + { + std::cerr << "Cannot read " << filename << "\n"; + return 1; + } + + PMP::repair_polygon_soup(points, triangles); + PMP::triangulate_polygons(points, triangles); + + PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(erase_duplicate).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15)); + + return 0; +} diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Performance/run_performance.sh b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Performance/run_performance.sh new file mode 100755 index 00000000000..aa6ea1a28ba --- /dev/null +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Performance/run_performance.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +set -e + +if [ "$#" -lt 4 ]; then + echo "Usage: $0 [component_params...]" + exit 1 +fi + +INPUT_FILE=$1 +TIMEOUT=$2 +GRID_SIZE=$3 +ERASE_ALL_DUPLICATE=$4 + +# Use /usr/bin/time for memory usage (maximum resident set size in KB) +TMP_LOG=$(mktemp) + +# Run the benchmarked command +/usr/bin/time -f "TIME:%e\nMEM:%M" timeout "$TIMEOUT"s performance_snap_polygon_soup "$INPUT_FILE" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE" 2> "$TMP_LOG" + +# Parse time and memory +SECONDS=$(grep "TIME" "$TMP_LOG" | cut -d':' -f2) +MEMORY=$(grep "MEM" "$TMP_LOG" | cut -d':' -f2) + +rm -f "$TMP_LOG" + +# Output JSON +echo "{\"seconds\": \"$SECONDS\", \"memory_peaks\": \"$MEMORY\"}" diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Quality/quality_snap_polygon_soup.cpp b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Quality/quality_snap_polygon_soup.cpp new file mode 100644 index 00000000000..8e4bb99c2ba --- /dev/null +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Quality/quality_snap_polygon_soup.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +typedef typename Kernel::Point_3 Point_3; +namespace PMP = CGAL::Polygon_mesh_processing; + +int main(int argc, char** argv) +{ + if(argc<4){ + std::cout << "Invalid argument" << std::endl; + return 1; + } + const std::string filename = std::string(argv[1]); + const int grid_size = std::stoi(std::string(argv[2])); + const bool erase_duplicate = std::stoi(argv[3])==1; + + std::vector points; + std::vector> triangles; + + CGAL::Bbox_3 bb = CGAL::bbox_3(points.begin(), points.end()); + double diag_length=std::sqrt((bb.xmax()-bb.xmin())*(bb.xmax()-bb.xmin()) + (bb.ymax()-bb.ymin())*(bb.ymax()-bb.ymin()) + (bb.zmax()-bb.zmin())*(bb.zmax()-bb.zmin())); + if (!CGAL::IO::read_polygon_soup(filename, points, triangles)) + { + std::cerr << "Cannot read " << filename << "\n"; + return 1; + } + + std::vector input_points(points.begin(), points.end()); + + PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(erase_duplicate).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15)); + + + std::cout << "{" << + "\"Nb_output_points\": \"" << points.size() << "\",\n" << + "\"Nb_output_triangles\": \"" << triangles.size() << "\",\n" << + "\"Is_2_manifold\": \"" << (PMP::orient_polygon_soup(points, triangles)?"True":"False") << "\",\n"; + CGAL::Surface_mesh sm; + PMP::polygon_soup_to_polygon_mesh(points, triangles, sm); + + std::cout << std::setprecision(17) << + "\"Hausdorff_distance_output_to_input_(divide_by_bbox_diag)\": \"" << PMP::max_distance_to_triangle_mesh(input_points, sm) / diag_length << "\",\n" << + "\"Closed_output\": \"" << (CGAL::is_closed(sm)?"True":"False") << "\",\n" << + "\"Ouput_bound_a_volume\": \"" << (PMP::does_bound_a_volume(sm)?"True":"False") << "\"\n}" + << std::endl; + + return 0; +} \ No newline at end of file diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Quality/run_quality.sh b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Quality/run_quality.sh new file mode 100755 index 00000000000..c3a194483eb --- /dev/null +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Quality/run_quality.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -e + +if [ "$#" -lt 4 ]; then + echo "Usage: $0 [component_params...]" + exit 1 +fi + +INPUT_FILE=$1 +TIMEOUT=$2 +GRID_SIZE=$3 +ERASE_ALL_DUPLICATE=$4 + +TMP_LOG=$(mktemp) +timeout "$TIMEOUT"s quality_snap_polygon_soup "$INPUT_FILE" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE" > "$TMP_LOG" + +cat $TMP_LOG +rm -f "$TMP_LOG" \ No newline at end of file diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Robustness/robustness_snap_polygon_soup.cpp b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Robustness/robustness_snap_polygon_soup.cpp new file mode 100644 index 00000000000..da424eb6422 --- /dev/null +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Robustness/robustness_snap_polygon_soup.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef typename Kernel::Point_3 Point_3; +namespace PMP = CGAL::Polygon_mesh_processing; + +enum EXIT_CODES { VALID_OUTPUT=0, + INVALID_INPUT=1, + ROUNDING_FAILED=2, + SELF_INTERSECTING_OUTPUT=3, + SIGSEGV=10, + SIGSABRT=11, + SIGFPE=12, + TIMEOUT=13 + }; + +int main(int argc, char** argv) +{ + if(argc<4){ + std::cout << "Invalid argument" << std::endl; + return 1; + } + + const std::string filename = std::string(argv[1]); + const int grid_size = std::stoi(std::string(argv[2])); + const bool erase_duplicate = std::stoi(argv[3])==1; + + std::vector points; + std::vector> triangles; + + if (!CGAL::IO::read_polygon_soup(filename, points, triangles) || points.size()==0 || triangles.size()==0) + { + return INVALID_INPUT; + } + + PMP::repair_polygon_soup(points, triangles); + PMP::triangulate_polygons(points, triangles); + + bool success=PMP::autorefine_triangle_soup(points, triangles, CGAL::parameters::apply_iterative_snap_rounding(true).erase_all_duplicates(erase_duplicate).concurrency_tag(CGAL::Parallel_if_available_tag()).snap_grid_size(grid_size).number_of_iterations(15)); + + if(!success) + return ROUNDING_FAILED; + if( PMP::does_triangle_soup_self_intersect(points, triangles) ) + return SELF_INTERSECTING_OUTPUT; + + return VALID_OUTPUT; +} diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Robustness/run_robustness.sh b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Robustness/run_robustness.sh new file mode 100755 index 00000000000..4e4e28dcdfd --- /dev/null +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/Robustness/run_robustness.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +if [ "$#" -lt 4 ]; then + echo "Usage: $0 [component_params...]" + exit 1 +fi + +timeout_bis() { + timeout 5 sleep 10 +} + +INPUT_FILE=$1 +TIMEOUT=$2 +GRID_SIZE=$3 +ERASE_ALL_DUPLICATE=$4 + +# Run with timeout, capture exit code +timeout "--foreground" "$TIMEOUT"s robustness_snap_polygon_soup "$INPUT_FILE" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE" +EXIT_CODE=$? + +# Interpret exit codes +declare -A TAGS +TAGS[0]="VALID_OUTPUT" +TAGS[1]="INPUT_IS_INVALID" +TAGS[2]="ROUNDING_FAILED" +TAGS[3]="SELF_INTERSECTING_OUTPUT" +TAGS[139]="SIGSEGV" +TAGS[11]="SIGSEGV" +TAGS[6]="SIGABRT" +TAGS[8]="SIGFPE" +TAGS[132]="SIGILL" +TAGS[124]="TIMEOUT" + +TAG_NAME=${TAGS[$EXIT_CODE]:-UNKNOWN} +TAG_DESC=$([[ "$EXIT_CODE" -eq 0 ]] && echo "OK" || echo "Error") + +# Output JSON +echo "{\"TAG_NAME\": \"$TAG_NAME\", \"TAG\": \"$TAG_DESC\"}" \ No newline at end of file diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/benchmarking_snap_polygon_soup.sh b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/benchmarking_snap_polygon_soup.sh new file mode 100755 index 00000000000..da3f363566a --- /dev/null +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/benchmarking_snap_polygon_soup.sh @@ -0,0 +1,116 @@ +#!/bin/bash + +# Temp directory for individual result JSONs +TMP_RESULT_DIR=$(mktemp -d) + +# Job control +JOBS=0 +MAX_JOBS=$NUM_THREADS + +# Function to process a single file +process_file() { + INPUT_PATH="$1" + INPUT_ID=$(basename "$INPUT_PATH" | cut -d. -f1) + COMPONENT_NAME="$2" + PROJECT_DIR="$3" + TIMEOUT="$4" + OUTPUT_DIR="$5" + TMP_RESULT_FILE="$6" + GRID_SIZE="$7" + ERASE_ALL_DUPLICATE="$8" + { + echo " \"$INPUT_ID\": {" + echo " \"path\": \"$INPUT_PATH\"," + + PERF_OUTPUT=$(bash "$PROJECT_DIR/Performance/run_performance.sh" "$INPUT_PATH" "$TIMEOUT" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE" 2>> "$OUTPUT_DIR/Logs/$COMPONENT_NAME/Performance/$INPUT_ID.log") + echo " \"Performance\": $PERF_OUTPUT," + + QUALITY_OUTPUT=$(bash "$PROJECT_DIR/Quality/run_quality.sh" "$INPUT_PATH" "$TIMEOUT" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE" 2>> "$OUTPUT_DIR/Logs/$COMPONENT_NAME/Quality/$INPUT_ID.log") + echo " \"Quality\": $QUALITY_OUTPUT," + + ROBUST_OUTPUT=$(bash "$PROJECT_DIR/Robustness/run_robustness.sh" "$INPUT_PATH" "$TIMEOUT" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE" 2>> "$OUTPUT_DIR/Logs/$COMPONENT_NAME/Robustness/$INPUT_ID.log") + echo " \"Robustness\": $ROBUST_OUTPUT" + + echo " }" + } > "$TMP_RESULT_FILE" +} +export -f process_file + +# Usage function +usage() { + echo "Usage: $0 [component_params...]" + exit 1 +} + +# Check parameters +if [ "$#" -lt 5 ]; then + usage +fi + +# Arguments +PROJECT_DIR=$1 +INPUT_DIR=$2 +OUTPUT_DIR=$3 +TIMEOUT=$4 +NUM_THREADS=$5 +GRID_SIZE=$6 +ERASE_ALL_DUPLICATE=$7 + +# Get component name from the project directory name +COMPONENT_NAME=$(basename "$PROJECT_DIR") +DATE_TAG=$(date +"%Y-%m-%d") +TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S") +RESULT_JSON="$OUTPUT_DIR/${COMPONENT_NAME}_results_${DATE_TAG}.json" + +# Compile +# Do not forget to define CGAL_DIR +cmake "$PROJECT_DIR" "-DCMAKE_BUILD_TYPE=Release" "-DCMAKE_CXX_FLAGS=-O3" +make -j $NUM_THREADS + +# Prepare log directories +mkdir -p "$OUTPUT_DIR/Logs/$COMPONENT_NAME/Performance" +mkdir -p "$OUTPUT_DIR/Logs/$COMPONENT_NAME/Quality" +mkdir -p "$OUTPUT_DIR/Logs/$COMPONENT_NAME/Robustness" + +# Initialize JSON +echo "{" > "$RESULT_JSON" +echo " \"$COMPONENT_NAME\": {" >> "$RESULT_JSON" +echo " \"Thingi10K\": {" >> "$RESULT_JSON" + +#process_file "$INPUT_DIR/100036.stl" "$COMPONENT_NAME" "$PROJECT_DIR" "$TIMEOUT" "$OUTPUT_DIR" "$TMP_RESULT_FILE" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE" +# Loop input files and spawn parallel jobs +for INPUT_FILE in "$INPUT_DIR"/*; do + INPUT_ID=$(basename "$INPUT_FILE" | cut -d. -f1) + TMP_RESULT_FILE="$TMP_RESULT_DIR/$INPUT_ID.json" + + process_file "$INPUT_FILE" "$COMPONENT_NAME" "$PROJECT_DIR" "$TIMEOUT" "$OUTPUT_DIR" "$TMP_RESULT_FILE" "$GRID_SIZE" "$ERASE_ALL_DUPLICATE" + + ((JOBS+=1)) + if [ "$JOBS" -ge "$NUM_THREADS" ]; then + wait + JOBS=0 + fi +done + +wait + +# Merge all partial JSONs +echo "{" > "$RESULT_JSON" +echo " \"$COMPONENT_NAME\": {" >> "$RESULT_JSON" +echo " \"Thingi10K\": {" >> "$RESULT_JSON" + +FIRST_ENTRY=true +for FILE in "$TMP_RESULT_DIR"/*.json; do + if [ "$FIRST_ENTRY" = true ]; then + FIRST_ENTRY=false + else + echo "," >> "$RESULT_JSON" + fi + cat "$FILE" >> "$RESULT_JSON" +done + +echo "" >> "$RESULT_JSON" +echo " }," >> "$RESULT_JSON" +echo " \"finished_at\": \"$TIMESTAMP\"" >> "$RESULT_JSON" +echo " }" >> "$RESULT_JSON" +echo "}" >> "$RESULT_JSON" \ No newline at end of file From 7ffed6caf5b54b53abf18f0a4a0afdf83ba67308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Valque?= Date: Wed, 21 May 2025 09:26:38 +0200 Subject: [PATCH 108/113] add new cpp in cmakelist of bench --- .../benchmark/Polygon_mesh_processing/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt index a59b7181d0c..ab1a6b06092 100644 --- a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt @@ -40,6 +40,10 @@ create_single_source_cgal_program("fast.cpp") create_single_source_cgal_program("rotated_cubes_autorefinement.cpp") create_single_source_cgal_program("coplanar_cubes_autorefinement.cpp") +create_single_source_cgal_program("Performance/performance_snap_polygon_soup.cpp") +create_single_source_cgal_program("Robustness/robustness_snap_polygon_soup.cpp") +create_single_source_cgal_program("Quality/quality_snap_polygon_soup.cpp") + create_single_source_cgal_program("polygon_mesh_slicer.cpp") target_link_libraries(polygon_mesh_slicer PRIVATE CGAL::Eigen3_support) @@ -50,4 +54,4 @@ if(TARGET CGAL::TBB_support) target_link_libraries(coplanar_cubes_autorefinement PRIVATE CGAL::TBB_support) else() message(STATUS "NOTICE: Intel TBB was not found. Sequential code will be used.") -endif() \ No newline at end of file +endif() From e816b145f5745768125ba883ec3c950138f849c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 5 Jun 2025 10:38:13 +0200 Subject: [PATCH 109/113] undo namespace change --- .../internal/triangle_soup_snap_rounding.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h index 00027fba4d5..2d5272364b5 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/triangle_soup_snap_rounding.h @@ -106,8 +106,8 @@ struct Triangle_soup_fixer using parameters::get_parameter; using parameters::choose_parameter; - using Traits = typename ::CGAL::Polygon_mesh_processing::internal::GetPolygonGeomTraits::type; - Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); + using Traits = typename GetPolygonGeomTraits::type; + Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits)); CGAL::Polygon_mesh_processing::merge_duplicate_points_in_polygon_soup(points, polygons, np); CGAL::Polygon_mesh_processing::internal::simplify_polygons_in_polygon_soup(points, polygons, traits); @@ -141,8 +141,8 @@ struct Triangle_soup_fixer::type; - Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); + using Traits = typename GetPolygonGeomTraits::type; + Traits traits = choose_parameter(get_parameter(np, internal_np::geom_traits)); CGAL::Polygon_mesh_processing::merge_duplicate_points_in_polygon_soup(points, polygons, np); CGAL::Polygon_mesh_processing::internal::remove_invalid_polygons_in_array_polygon_soup(points, polygons, traits); From 9a21a1478ae26da952263d6707a68eee1609e470 Mon Sep 17 00:00:00 2001 From: Sebastien Loriot Date: Tue, 10 Jun 2025 18:06:16 +0200 Subject: [PATCH 110/113] cosmetic --- Installation/CHANGES.md | 2 +- .../include/CGAL/Polygon_mesh_processing/autorefinement.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 416e7dd5ae6..6a9eed3ae0b 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -9,7 +9,7 @@ ### [Polygon Mesh Processing](https://doc.cgal.org/6.1/Manual/packages.html#PkgPolygonMeshProcessing) - Added the function `CGAL::Polygon_mesh_processing::discrete_mean_curvature` and `CGAL::Polygon_mesh_processing::discrete_Guassian_curvature` to evaluate the discrete curvature at a vertex of a mesh. - Added the function `CGAL::Polygon_mesh_processing::angle_sum` to compute the sum of the angles around a vertex. -- Added the parameter `apply_iterative_snap_rounding` to the function `CGAL::Polygon_mesh_processing::autorefine_triangle_soup()`. When set to `true`, the coordinates are rounded to fit in double and may perform additional subdivisions to ensure the output remains free of self-intersections. +- Added the parameter `apply_iterative_snap_rounding` to the function `CGAL::Polygon_mesh_processing::autorefine_triangle_soup()`. When set to `true`, the coordinates are rounded to fit in double and may perform additional subdivisions to ensure the output is free of self-intersections. ### [Algebraic Kernel](https://doc.cgal.org/6.1/Manual/packages.html#PkgAlgebraicKernelD) 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 37f1c7af220..5b5f913eb8d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1553,7 +1553,7 @@ bool autorefine_triangle_soup(PointRange& soup_points, } ); - // The constexpr was initially inside the lammbda, but that did not compile with VC 2017 + // The constexpr was initially inside the lambda, but that did not compile with VC 2017 if constexpr(std::is_same_v){ tbb::parallel_for(tbb::blocked_range(0, new_triangles.size()), [&](const tbb::blocked_range& r) { From f0464a9e2fa2d27c0a6909652b040ac352b87d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 10 Jun 2025 18:27:41 +0200 Subject: [PATCH 111/113] do not test datasets removed --- .../test/Polygon_mesh_processing/test_snap_rounding.cmd | 1 - .../test/Polygon_mesh_processing/test_snap_rounding_full.cmd | 2 -- 2 files changed, 3 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd index 81ea3e2afad..2d9a58e2f6e 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding.cmd @@ -35,4 +35,3 @@ data-snap/collapse_3.off 11 10 data-snap/no_collapse_1.off 8 4 data-snap/no_collapse_2.off 12 4 data-snap/coplanar_cubes.off 1514 5544 -data-snap/refined_coplanar_cubes.off 1872 6880 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding_full.cmd b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding_full.cmd index fa1b6a98c71..49eb20e9a00 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding_full.cmd +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_snap_rounding_full.cmd @@ -35,6 +35,4 @@ data-snap/collapse_3.off 11 10 data-snap/no_collapse_1.off 8 4 data-snap/no_collapse_2.off 12 4 data-snap/cubes.off 5042 26036 -data-snap/refined_cubes.off 5908 29863 data-snap/coplanar_cubes.off 1514 5544 -data-snap/refined_coplanar_cubes.off 1872 6880 From b8b7f6354eba08e7410268ee7afcc378560bf02b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 10 Jun 2025 20:32:07 +0200 Subject: [PATCH 112/113] also test parallel version --- .../test/Polygon_mesh_processing/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index db8aa3c1efe..7ed6e243833 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -111,6 +111,7 @@ if(TARGET CGAL::TBB_support) target_link_libraries(orient_polygon_soup_test PRIVATE CGAL::TBB_support) target_link_libraries(self_intersection_surface_mesh_test PRIVATE CGAL::TBB_support) target_link_libraries(test_autorefinement PRIVATE CGAL::TBB_support) + target_link_libraries(test_snap_rounding PRIVATE CGAL::TBB_support) else() message(STATUS "NOTICE: Intel TBB was not found. Tests will use sequential code.") endif() From bd0e60e95049752567f0e010590c26258a4c29a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 10 Jun 2025 20:32:19 +0200 Subject: [PATCH 113/113] fix mutex version --- .../Polygon_mesh_processing/autorefinement.h | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) 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 5b5f913eb8d..00a48f919e7 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/autorefinement.h @@ -1490,23 +1490,41 @@ bool autorefine_triangle_soup(PointRange& soup_points, [&](const tbb::blocked_range& r) { for (size_t ti = r.begin(); ti != r.end(); ++ti) { const std::array& t = new_triangles[ti].first; - visitor.new_subtriangle(offset+ti, tri_inter_ids_inverse[new_triangles[ti].second]); triangle_buffer[ti] = CGAL::make_array(concurrent_get_point_id(t[0]), concurrent_get_point_id(t[1]), concurrent_get_point_id(t[2])); } } ); - tbb::parallel_for(tbb::blocked_range(0, new_triangles.size()), - [&](const tbb::blocked_range& r) { - for (size_t ti = r.begin(); ti != r.end(); ++ti) - { - soup_triangles_out[offset + ti] = - { triangle_buffer[ti][0]->second, - triangle_buffer[ti][1]->second, - triangle_buffer[ti][2]->second }; - visitor.new_subtriangle(soup_triangles_out[offset + ti], soup_triangle[tri_inter_ids_inverse[new_triangles[ti].second]]); + + // The constexpr was initially inside the lambda, but that did not compile with VC 2017 + if constexpr(std::is_same_v){ + tbb::parallel_for(tbb::blocked_range(0, new_triangles.size()), + [&](const tbb::blocked_range& r) { + for (size_t ti = r.begin(); ti != r.end(); ++ti) + { + soup_triangles_out[offset + ti] = + { triangle_buffer[ti][0]->second, + triangle_buffer[ti][1]->second, + triangle_buffer[ti][2]->second }; + visitor.new_subdivision(soup_triangles_out[offset + ti], soup_triangles[tri_inter_ids_inverse[new_triangles[ti].second]]); + } } - } - ); + ); + } + else + { + tbb::parallel_for(tbb::blocked_range(0, new_triangles.size()), + [&](const tbb::blocked_range& r) { + for (size_t ti = r.begin(); ti != r.end(); ++ti) + { + soup_triangles_out[offset + ti] = + { triangle_buffer[ti][0]->second, + triangle_buffer[ti][1]->second, + triangle_buffer[ti][2]->second }; + visitor.new_subtriangle(offset+ti, tri_inter_ids_inverse[new_triangles[ti].second]); + } + } + ); + } #else //option 2 (without mutex) /// Lambda concurrent_get_point_id()