Rename smooth/smooth_along_curvature_flow to smooth_mesh/shape

Also fix edge protection in the demo
This commit is contained in:
Mael Rouxel-Labbé 2019-06-19 10:17:26 +02:00
parent 431d07effb
commit 3b53ce20e3
10 changed files with 101 additions and 166 deletions

View File

@ -27,9 +27,9 @@ Release date: September 2019
### Polygon Mesh Processing
- Added the function `CGAL::Polygon_mesh_processing::centroid()` which computes
the centroid of a closed triangle mesh.
- Added the mesh smoothing function `smooth()`, which can be used to
- Added the mesh smoothing function `smooth_mesh()`, which can be used to
improve the quality of triangle elements based on various geometric characteristics.
- Added the shape smoothing function `smooth_along_curvature_flow()`, which can be used to
- Added the shape smoothing function `smooth_shape()`, which can be used to
smooth the surface of a triangle mesh, using the mean curvature flow to perform noise removal.
### IO Streams

View File

@ -143,7 +143,7 @@ is the solver used.\n
is provided as default value:\n
in `fair()`:\n
\code CGAL::Eigen_solver_traits<Eigen::SparseLU<CGAL::Eigen_sparse_matrix<double>::EigenType, Eigen::COLAMDOrdering<int> > > \endcode
in `smooth_along_curvature_flow()`:\n
in `smooth_shape()`:\n
\code CGAL::Eigen_solver_traits<Eigen::BiCGSTAB<CGAL::Eigen_sparse_matrix<double>::EigenType, Eigen::IncompleteLUT<double> > > \endcode
\cgalNPEnd
@ -392,7 +392,7 @@ if orientation should matter when determining whether two faces are duplicates.
\cgalNPEnd
\cgalNPBegin{use_angle_smoothing_t} \anchor PMP_use_angle_smoothing
Parameter used in the function `smooth()` to indicate if angle-based smoothing should be used.
Parameter used in the function `smooth_mesh()` to indicate if angle-based smoothing should be used.
When this type of smoothing is used, the algorithm attempts to equalize angles incident to each vertex.
\n
@ -401,7 +401,7 @@ When this type of smoothing is used, the algorithm attempts to equalize angles i
\cgalNPEnd
\cgalNPBegin{use_area_smoothing_t} \anchor PMP_use_area_smoothing
Parameter used in the function `smooth()` to indicate if area-based smoothing should be used.
Parameter used in the function `smooth_mesh()` to indicate if area-based smoothing should be used.
When this type of smoothing is used, the algorithm attempts to equalize the areas of the triangles
incident to each vertex. Since this can create elongated triangles, a second phase uses Delaunay-based
flips to recover good shapes, unless specified otherwise (see below).
@ -412,7 +412,7 @@ flips to recover good shapes, unless specified otherwise (see below).
\cgalNPEnd
\cgalNPBegin{use_Delaunay_flips_t} \anchor PMP_use_Delaunay_flips
Parameter used in the function `smooth()` to indicate if Delaunay-based flips should be used
Parameter used in the function `smooth_mesh()` to indicate if Delaunay-based flips should be used
after area-based smoothing has been performed. A user wishing to preserve combinatorial information
can set this parameter to `false`, but the mesh might have elongated elements.
@ -422,18 +422,7 @@ can set this parameter to `false`, but the mesh might have elongated elements.
\cgalNPEnd
\cgalNPBegin{use_safety_constraints} \anchor PMP_use_safety_constraints
Parameter used in the function `smooth()` to indicate if some sanity checks should be used to decide
if the move of a vertex should be applied or rejected. These sanity checks consists of checking that
no face incident to the vertex becomes inverted and that the minimum angle of the incident faces
is not decreased by the move.
\n
<b>Type:</b> `bool` \n
<b>Default:</b> `true`
\cgalNPEnd
\cgalNPBegin{use_safety_constraints} \anchor PMP_use_safety_constraints
Parameter used in the function `smooth()` to indicate if some sanity checks should be used to decide
Parameter used in the function `smooth_mesh()` to indicate if some sanity checks should be used to decide
if the move of a vertex should be applied or rejected. These sanity checks consists of checking that
no face incident to the vertex becomes inverted and that the minimum angle of the incident faces
is not decreased by the move.

View File

@ -96,8 +96,8 @@ and provides a list of the parameters that are used in this package.
\cgalCRPSection{Meshing Functions}
- `CGAL::Polygon_mesh_processing::fair()`
- `CGAL::Polygon_mesh_processing::refine()`
- `CGAL::Polygon_mesh_processing::smooth()`
- `CGAL::Polygon_mesh_processing::smooth_along_curvature_flow()`
- `CGAL::Polygon_mesh_processing::smooth_mesh()`
- `CGAL::Polygon_mesh_processing::smooth_shape()`
- `CGAL::Polygon_mesh_processing::triangulate_face()`
- `CGAL::Polygon_mesh_processing::triangulate_faces()`
- \link PMP_meshing_grp `CGAL::Polygon_mesh_processing::isotropic_remeshing()` \endlink

View File

@ -36,9 +36,9 @@ int main(int argc, char** argv)
CGAL::Boolean_property_map<std::set<Mesh::Vertex_index> > vcmap(constrained_vertices);
std::cout << "Smoothing... (" << nb_iterations << " iterations)" << std::endl;
PMP::smooth(mesh, PMP::parameters::number_of_iterations(nb_iterations)
.use_safety_constraints(false) // authorize all moves
.vertex_is_constrained_map(vcmap));
PMP::smooth_mesh(mesh, PMP::parameters::number_of_iterations(nb_iterations)
.use_safety_constraints(false) // authorize all moves
.vertex_is_constrained_map(vcmap));
std::ofstream output("mesh_smoothed.off");
output << mesh;

View File

@ -63,17 +63,17 @@ namespace Polygon_mesh_processing {
* @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below.
*
* \cgalNamedParamsBegin
* \cgalParamBegin{use_angle_based_smoothing} Boolean value to indicate whether angle-based smoothing should be used.
* Default is `true`.
* \cgalParamBegin{use_angle_smoothing} Boolean value to indicate whether angle-based smoothing should be used.
* %Default is `true`.
* \cgalParamEnd
* \cgalParamBegin{use_area_based_smoothing} Boolean value to indicate whether area-based smoothing should be used.
* Default is `true`.
* \cgalParamBegin{use_area_smoothing} Boolean value to indicate whether area-based smoothing should be used.
* %Default is `true`.
* \cgalParamEnd
* \cgalParamBegin{number_of_iterations} the number of iterations for the
* sequence of the smoothing iterations performed (default is 1).
* \cgalParamEnd
* \cgalParamBegin{use_safety_constraints} if `true`, vertex moves that would worsen the mesh
* are ignored. Default is `false`.
* are ignored. %Default is `false`.
* \cgalParamEnd
* \cgalParamBegin{use_Delaunay_flips} if `true` (default value), area-based smoothing will be completed
* by a phase of Delaunay-based edge-flips to prevent the creation of elongated triangles.
@ -85,25 +85,26 @@ namespace Polygon_mesh_processing {
* constrained-or-not status of each vertex of `tmesh`. A constrained vertex
* cannot be modified at all during smoothing.
* \cgalParamEnd
* \cgalParamBegin{edge_is_constrained_map} a property map containing the
* \cgalParamBegin{edge_is_constrained_map} a property map, model of `ReadWritePropertyMap`, containing the
* constrained-or-not status of each edge of `tmesh`. A constrained edge cannot be flipped.
* \cgalParamEnd
* \cgalParamBegin{vertex_point_map} the property map with the points associated
* to the vertices of `tmesh`. Instance of a class model of `ReadWritePropertyMap`.
* \cgalParamBegin{vertex_point_map} the property map, model of `ReadWritePropertyMap`, with the points
* associated to the vertices of `tmesh`.
* \cgalParamEnd
* \cgalParamBegin{geom_traits} a geometric traits class instance, model of `Kernel`.
* Exact constructions kernels are not supported by this function.
* \cgalParamEnd
* \cgalNamedParamsEnd
*
* @warning The third party libraries Ceres (and Eigen) are required to use the area-based smoothing.
* @warning The third party libraries \link thirdpartyCeres Ceres \endlink (and \link installation_eigen Eigen \endlink)
* are required to use the area-based smoothing.
*
* @pre `tmesh` does not contain any degenerate faces
*/
template<typename TriangleMesh, typename FaceRange, typename NamedParameters>
void smooth(const FaceRange& faces,
TriangleMesh& tmesh,
const NamedParameters& np)
void smooth_mesh(const FaceRange& faces,
TriangleMesh& tmesh,
const NamedParameters& np)
{
typedef typename boost::graph_traits<TriangleMesh>::vertex_descriptor vertex_descriptor;
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
@ -158,12 +159,12 @@ void smooth(const FaceRange& faces,
const bool use_area_smoothing = choose_param(get_param(np, internal_np::use_area_smoothing), true);
if(!use_angle_smoothing && !use_area_smoothing)
std::cerr << "Warning: called PMP::smooth() but no smoothing method is being used" << std::endl;
std::cerr << "Warning: called PMP::smooth_mesh() but no smoothing method is being used" << std::endl;
std::size_t nb_iterations = choose_param(get_param(np, internal_np::number_of_iterations), 1);
const bool do_project = choose_param(get_param(np, internal_np::do_project), true);
const bool use_safety_constraints = choose_param(get_param(np, internal_np::use_safety_constraints), true);
const bool use_Delaunay_flips = choose_param(get_param(np, internal_np::use_Delaunay_flips), false);
const bool use_Delaunay_flips = choose_param(get_param(np, internal_np::use_Delaunay_flips), true);
// Construct the AABB tree (if needed for reprojection)
std::vector<Triangle> input_triangles;
@ -249,21 +250,21 @@ void smooth(const FaceRange& faces,
}
template <typename FaceRange, typename TriangleMesh>
void smooth(const FaceRange& face_range, TriangleMesh& tmesh)
void smooth_mesh(const FaceRange& face_range, TriangleMesh& tmesh)
{
smooth(face_range, tmesh, parameters::all_default());
smooth_mesh(face_range, tmesh, parameters::all_default());
}
template <typename TriangleMesh, typename CGAL_PMP_NP_TEMPLATE_PARAMETERS>
void smooth(TriangleMesh& tmesh, const CGAL_PMP_NP_CLASS& np)
void smooth_mesh(TriangleMesh& tmesh, const CGAL_PMP_NP_CLASS& np)
{
smooth(faces(tmesh), tmesh, np);
smooth_mesh(faces(tmesh), tmesh, np);
}
template<typename TriangleMesh>
void smooth(TriangleMesh& tmesh)
void smooth_mesh(TriangleMesh& tmesh)
{
smooth(faces(tmesh), tmesh, parameters::all_default());
smooth_mesh(faces(tmesh), tmesh, parameters::all_default());
}
@ -291,7 +292,7 @@ void aspect_ratio_evaluation(TriangleMesh& tmesh, GeomTraits traits, Stream& out
evaluator.calc_aspect_ratios();
evaluator.extract_aspect_ratios(output);
}
///\cond SKIP_IN_MANUAL
///\endcond SKIP_IN_MANUAL
} // namespace Polygon_mesh_processing
} // namespace CGAL

View File

@ -83,10 +83,10 @@ namespace Polygon_mesh_processing {
* @warning This function involves linear algebra, that is computed using a non-exact floating-point arithmetic.
*/
template<typename TriangleMesh, typename FaceRange, typename NamedParameters>
void smooth_along_curvature_flow(const FaceRange& faces,
TriangleMesh& tmesh,
const double time,
const NamedParameters& np)
void smooth_shape(const FaceRange& faces,
TriangleMesh& tmesh,
const double time,
const NamedParameters& np)
{
if(std::begin(faces) == std::end(faces))
return;
@ -177,26 +177,26 @@ void smooth_along_curvature_flow(const FaceRange& faces,
}
template<typename TriangleMesh, typename FaceRange>
void smooth_along_curvature_flow(const FaceRange& faces,
TriangleMesh& tmesh,
const double time)
void smooth_shape(const FaceRange& faces,
TriangleMesh& tmesh,
const double time)
{
smooth_along_curvature_flow(faces, tmesh, time, parameters::all_default());
smooth_shape(faces, tmesh, time, parameters::all_default());
}
template <typename TriangleMesh, typename CGAL_PMP_NP_TEMPLATE_PARAMETERS>
void smooth_along_curvature_flow(TriangleMesh& tmesh,
const double time,
const CGAL_PMP_NP_CLASS& np)
void smooth_shape(TriangleMesh& tmesh,
const double time,
const CGAL_PMP_NP_CLASS& np)
{
smooth_along_curvature_flow(faces(tmesh), tmesh, time, np);
smooth_shape(faces(tmesh), tmesh, time, np);
}
template<typename TriangleMesh>
void smooth_along_curvature_flow(TriangleMesh& tmesh,
const double time)
void smooth_shape(TriangleMesh& tmesh,
const double time)
{
smooth_along_curvature_flow(faces(tmesh), tmesh, time, parameters::all_default());
smooth_shape(faces(tmesh), tmesh, time, parameters::all_default());
}
} // Polygon_mesh_processing

View File

@ -52,6 +52,8 @@
#include <CGAL/Polygon_mesh_processing/shape_predicates.h>
#include <CGAL/Polygon_mesh_processing/repair_polygon_soup.h>
#include <CGAL/Polygon_mesh_processing/merge_border_vertices.h>
#include <CGAL/Polygon_mesh_processing/smooth_mesh.h>
#include <CGAL/Polygon_mesh_processing/smooth_shape.h>
// the named parameter header being not documented the doc is put here for now
#ifdef DOXYGEN_RUNNING

View File

@ -36,8 +36,8 @@ void test_smoothing(const char* filename)
Mesh mesh;
read_mesh(filename, mesh);
PMP::smooth(mesh);
PMP::smooth(mesh, CGAL::parameters::number_of_iterations(10));
PMP::smooth_mesh(mesh);
PMP::smooth_mesh(mesh, CGAL::parameters::number_of_iterations(10));
}
template <typename Mesh>
@ -46,9 +46,9 @@ void test_angle_smoothing(const char* filename)
Mesh mesh;
read_mesh(filename, mesh);
PMP::smooth(mesh);
PMP::smooth(mesh, CGAL::parameters::number_of_iterations(10)
.use_area_smoothing(false));
PMP::smooth_mesh(mesh);
PMP::smooth_mesh(mesh, CGAL::parameters::number_of_iterations(10)
.use_area_smoothing(false));
}
template <typename Mesh>
@ -57,9 +57,9 @@ void test_area_smoothing(const char* filename)
Mesh mesh;
read_mesh(filename, mesh);
PMP::smooth(mesh);
PMP::smooth(mesh, CGAL::parameters::number_of_iterations(10)
.use_angle_smoothing(false));
PMP::smooth_mesh(mesh);
PMP::smooth_mesh(mesh, CGAL::parameters::number_of_iterations(10)
.use_angle_smoothing(false));
}
template <typename Mesh>
@ -68,8 +68,8 @@ void test_angle_smoothing_without_projection(const char* filename)
Mesh mesh;
read_mesh(filename, mesh);
PMP::smooth(mesh, CGAL::parameters::do_project(false)
.use_area_smoothing(false));
PMP::smooth_mesh(mesh, CGAL::parameters::do_project(false)
.use_area_smoothing(false));
}
template <typename Mesh>
@ -78,8 +78,8 @@ void test_area_smoothing_without_projection(const char* filename)
Mesh mesh;
read_mesh(filename, mesh);
PMP::smooth(mesh, CGAL::parameters::do_project(false)
.use_angle_smoothing(false));
PMP::smooth_mesh(mesh, CGAL::parameters::do_project(false)
.use_angle_smoothing(false));
}
template <typename Mesh>
@ -104,7 +104,7 @@ void test_constrained_vertices(const char* filename)
CGAL::Boolean_property_map<std::set<vertex_descriptor> > vcmap(selected_vertices);
PMP::smooth(mesh, CGAL::parameters::vertex_is_constrained_map(vcmap));
PMP::smooth_mesh(mesh, CGAL::parameters::vertex_is_constrained_map(vcmap));
for(vertex_descriptor v : vertices(mesh))
{

View File

@ -54,8 +54,8 @@ void test_implicit_constrained_devil(Mesh mesh)
fixed_points[i++] = get(vpmap, v);
const double time_step = 1.0;
PMP::smooth_along_curvature_flow(mesh, time_step, CGAL::parameters::vertex_is_constrained_map(vcmap)
.number_of_iterations(2));
PMP::smooth_shape(mesh, time_step, CGAL::parameters::vertex_is_constrained_map(vcmap)
.number_of_iterations(2));
i = 0;
for(vertex_descriptor v : selected_vertices)
@ -97,9 +97,9 @@ void test_implicit_constrained_elephant(Mesh mesh)
Point fixed_point = get(vpmap, *selected_vertices.begin());
const double time_step = 1.0;
PMP::smooth_along_curvature_flow(mesh, time_step,
CGAL::parameters::vertex_is_constrained_map(vcmap)
.number_of_iterations(1));
PMP::smooth_shape(mesh, time_step,
CGAL::parameters::vertex_is_constrained_map(vcmap)
.number_of_iterations(1));
CGAL_assertion(equal_doubles(get(vpmap, *selected_vertices.begin()).x(), fixed_point.x(), 1e-14));
CGAL_assertion(equal_doubles(get(vpmap, *selected_vertices.begin()).y(), fixed_point.y(), 1e-14));
@ -120,7 +120,7 @@ void test_curvature_flow_time_step(Mesh mesh)
#endif
const double time_step = 1e-15;
PMP::smooth_along_curvature_flow(mesh, time_step);
PMP::smooth_shape(mesh, time_step);
#ifdef CGAL_PMP_SMOOTHING_VERBOSE
std::ofstream out("output_devil_time_step.off");
@ -137,7 +137,7 @@ void test_curvature_flow(Mesh mesh)
#endif
const double time_step = 1.0;
PMP::smooth_along_curvature_flow(mesh, time_step);
PMP::smooth_shape(mesh, time_step);
#ifdef CGAL_PMP_SMOOTHING_VERBOSE
std::ofstream out("output_precision_elephant.off");

View File

@ -179,34 +179,13 @@ public Q_SLOTS:
if(poly_item)
{
if(use_angle_smoothing)
{
if(use_area_smoothing)
{
smooth(pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.use_delaunay_triangulation(use_Delaunay_flips)
.use_safety_constraints(use_safety_measures)
.vertex_is_constrained_map(vcmap));
}
else
{
smooth(pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.use_safety_constraints(use_safety_measures)
.vertex_is_constrained_map(vcmap)
.use_area_smoothing(false));
}
}
else if(use_area_smoothing)
{
smooth(pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.use_delaunay_triangulation(use_Delaunay_flips)
.use_safety_constraints(use_safety_measures)
.vertex_is_constrained_map(vcmap)
.use_angle_smoothing(false));
}
smooth_mesh(pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.vertex_is_constrained_map(vcmap)
.use_safety_constraints(use_safety_measures)
.use_angle_smoothing(use_angle_smoothing)
.use_area_smoothing(use_area_smoothing)
.use_Delaunay_flips(use_Delaunay_flips));
poly_item->invalidateOpenGLBuffers();
poly_item->itemChanged();
@ -218,61 +197,25 @@ public Q_SLOTS:
// No faces selected --> use all faces
if(std::begin(selection_item->selected_facets) == std::end(selection_item->selected_facets))
{
if(use_angle_smoothing)
{
if(use_area_smoothing)
{
smooth(pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.use_safety_constraints(use_safety_measures)
.vertex_is_constrained_map(vcmap));
}
else
{
smooth(pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.use_safety_constraints(use_safety_measures)
.vertex_is_constrained_map(vcmap)
.use_area_smoothing(false));
}
}
else
{
smooth(pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.use_safety_constraints(use_safety_measures)
.vertex_is_constrained_map(vcmap)
.use_angle_smoothing(false));
}
smooth_mesh(pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.vertex_is_constrained_map(vcmap)
.edge_is_constrained_map(selection_item->constrained_edges_pmap())
.use_safety_constraints(use_safety_measures)
.use_angle_smoothing(use_angle_smoothing)
.use_area_smoothing(use_area_smoothing)
.use_Delaunay_flips(use_Delaunay_flips));
}
else // some faces exist in the selection
{
if(use_angle_smoothing)
{
if(use_area_smoothing)
{
smooth(selection_item->selected_facets, pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.use_safety_constraints(use_safety_measures)
.vertex_is_constrained_map(vcmap));
}
else
{
smooth(selection_item->selected_facets, pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.use_safety_constraints(use_safety_measures)
.vertex_is_constrained_map(vcmap)
.use_area_smoothing(false));
}
}
else
{
smooth(selection_item->selected_facets, pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.use_safety_constraints(use_safety_measures)
.vertex_is_constrained_map(vcmap)
.use_angle_smoothing(false));
}
smooth_mesh(selection_item->selected_facets, pmesh, parameters::do_project(projection)
.number_of_iterations(nb_iter)
.vertex_is_constrained_map(vcmap)
.edge_is_constrained_map(selection_item->constrained_edges_pmap())
.use_safety_constraints(use_safety_measures)
.use_angle_smoothing(use_angle_smoothing)
.use_area_smoothing(use_area_smoothing)
.use_Delaunay_flips(use_Delaunay_flips));
}
selection_item->poly_item_changed();
@ -309,8 +252,8 @@ public Q_SLOTS:
if(poly_item)
{
smooth_along_curvature_flow(pmesh, time_step, parameters::number_of_iterations(nb_iter)
.vertex_is_constrained_map(vcmap));
smooth_shape(pmesh, time_step, parameters::number_of_iterations(nb_iter)
.vertex_is_constrained_map(vcmap));
poly_item->invalidateOpenGLBuffers();
poly_item->itemChanged();
@ -321,14 +264,14 @@ public Q_SLOTS:
if(std::begin(selection_item->selected_facets) == std::end(selection_item->selected_facets))
{
smooth_along_curvature_flow(pmesh, time_step, parameters::number_of_iterations(nb_iter)
.vertex_is_constrained_map(vcmap));
smooth_shape(pmesh, time_step, parameters::number_of_iterations(nb_iter)
.vertex_is_constrained_map(vcmap));
}
else
{
smooth_along_curvature_flow(selection_item->selected_facets, pmesh, time_step,
parameters::number_of_iterations(nb_iter)
.vertex_is_constrained_map(vcmap));
smooth_shape(selection_item->selected_facets, pmesh, time_step,
parameters::number_of_iterations(nb_iter)
.vertex_is_constrained_map(vcmap));
}
selection_item->poly_item_changed();