made snap polygon soup an option of autorefine_triangle_soup

This commit is contained in:
Léo Valque 2025-02-17 14:17:45 +01:00
parent 8079f69f8b
commit d4e66753ad
4 changed files with 72 additions and 22 deletions

View File

@ -1,10 +1,11 @@
#define PMP_ROUNDING_VERTICES_IN_POLYGON_SOUP_VERBOSE
#define CGAL_PMP_AUTOREFINE_USE_DEFAULT_VERBOSE
#include <CGAL/Cartesian.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_mesh_processing/snap_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/repair_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/autorefinement.h>
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>
#include <CGAL/IO/polygon_soup_io.h>
@ -14,6 +15,8 @@
#include <iostream>
#include <CGAL/Polygon_mesh_processing/internal/snap_polygon_soup.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Cartesian<double> 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<Point> input_points;
std::vector<boost::container::small_vector<std::size_t, 3>> 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<Cartesian::Point_3> 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;
}

View File

@ -33,7 +33,6 @@
#include <CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h>
#include <CGAL/Polygon_mesh_processing/polygon_mesh_to_polygon_soup.h>
#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 <typename PointRange, typename PolygonRange, class NamedParameters = parameters::Default_named_parameters>
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 <class PointRange, class TriangleRange, class NamedParameters = parameters::Default_named_parameters>
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<Visitor>(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<Parallel_tag, Concurrency_tag>;
@ -1077,7 +1119,7 @@ void autorefine_triangle_soup(PointRange& soup_points,
for(std::size_t i=0; i<soup_triangles.size(); ++i)
visitor.verbatim_triangle_copy(i, i);
}
return;
return true;
}
// mark degenerate faces so that we can ignore them
@ -1642,6 +1684,7 @@ void autorefine_triangle_soup(PointRange& soup_points,
swap(soup_triangles, soup_triangles_out);
CGAL_PMP_AUTOREFINE_VERBOSE("done");
return true;
}
/**

View File

@ -7,17 +7,17 @@
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Léo Valque
// Author(s) : Léo Valque, Sylvain Lazard
#ifndef CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING_H
#define CGAL_POLYGON_MESH_PROCESSING_POLYGON_SOUP_ROUNDING_H
#ifndef CGAL_POLYGON_MESH_PROCESSING_SNAP_POLYGON_SOUP_H
#define CGAL_POLYGON_MESH_PROCESSING_SNAP_POLYGON_SOUP_H
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Algebraic_structure_traits.h>
#include <CGAL/number_utils.h>
#include <CGAL/license/Polygon_mesh_processing/geometric_repair.h>
#include <CGAL/Polygon_mesh_processing/autorefinement.h>
// #include <CGAL/Polygon_mesh_processing/autorefinement.h>
#include <CGAL/Polygon_mesh_processing/repair_polygon_soup.h>
#include <CGAL/Fraction_traits.h>
@ -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 <typename PointRange, typename PolygonRange, class NamedParameters = parameters::Default_named_parameters>
template <typename PointRange, typename PolygonRange, class NamedParameters>
bool snap_polygon_soup(PointRange &points,
PolygonRange &triangles,
const NamedParameters& np = parameters::default_values())
const NamedParameters& np)
// template <typename PointRange, typename PolygonRange, class NamedParameters = parameters::Default_named_parameters>
// 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<Parallel_tag, Concurrency_tag>;
constexpr bool parallel_execution = false;
constexpr bool parallel_execution = std::is_same_v<Parallel_tag, Concurrency_tag>;
// 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

View File

@ -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