From 730bbba98bbce3c9983644e02a66fb45c508cdf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 20 Nov 2023 10:03:16 +0100 Subject: [PATCH 1/6] add an example with a dummy custom sizing field --- .../Polygon_mesh_processing/CMakeLists.txt | 1 + ...c_remeshing_with_custom_sizing_example.cpp | 102 ++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_with_custom_sizing_example.cpp diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 590305c0c8ad..38d1bce078b0 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -51,6 +51,7 @@ create_single_source_cgal_program("match_faces.cpp") create_single_source_cgal_program("cc_compatible_orientations.cpp") create_single_source_cgal_program("hausdorff_distance_remeshing_example.cpp") create_single_source_cgal_program("hausdorff_bounded_error_distance_example.cpp") +create_single_source_cgal_program("isotropic_remeshing_with_custom_sizing_example.cpp") find_package(Eigen3 3.2.0 QUIET) #(requires 3.2.0 or greater) include(CGAL_Eigen3_support) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_with_custom_sizing_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_with_custom_sizing_example.cpp new file mode 100644 index 000000000000..1fc70906f7d7 --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_with_custom_sizing_example.cpp @@ -0,0 +1,102 @@ +#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; + +// a sizing fied that is increasing the size of edge along the y-axis +// starting at a minimum size at y-max and ending at a maximum size at +// y-min, with a linear interpolation of sizes in between the two extreme +// sizing values +struct My_sizing_field +{ + double min_size, max_size; + double ymin, ymax; + const Mesh& mesh; + + My_sizing_field(double min_size, double max_size, double ymin, double ymax, const Mesh& mesh) + : min_size(min_size) + , max_size(max_size) + , ymin(ymin) + , ymax(ymax) + , mesh(mesh) + {} + + double at(K::Point_3 p) const + { + double y=p.y(); + return CGAL::square( (y-ymin)/(ymax-ymin) * (min_size - max_size) + max_size ); + } + double at(const Mesh::Vertex_index v) const { return at(mesh.point(v)); } + + std::optional is_too_long(const Mesh::Vertex_index va, + const Mesh::Vertex_index vb) const + { + // TODO: no mesh as parameters? + K::Point_3 mp = CGAL::midpoint(mesh.point(va), mesh.point(vb)); + double sql_at = at(mp); + double sql = CGAL::squared_distance(mesh.point(va), mesh.point(vb)); + if (sql > sql_at) + return sql / sql_at; + return std::nullopt; + } + + std::optional is_too_short(const Mesh::Halfedge_index h, + const Mesh&) const + { + K::Point_3 mp = CGAL::midpoint(mesh.point(source(h, mesh)), mesh.point(target(h, mesh))); + double sql_at = at(mp); + double sql = CGAL::squared_distance(mesh.point(source(h, mesh)), mesh.point(target(h, mesh))); + if (sql < sql_at) + return sql / sql_at; + return std::nullopt; + } + + K::Point_3 split_placement(const Mesh::Halfedge_index h, + const Mesh&) const + { + return CGAL::midpoint(mesh.point(source(h, mesh)), mesh.point(target(h, mesh))); + } + + void update(const Mesh::Vertex_index, const Mesh&) {} +}; + + +int main(int argc, char* argv[]) +{ + const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/elk.off"); + + Mesh mesh; + if (!PMP::IO::read_polygon_mesh(filename, mesh) || !CGAL::is_triangle_mesh(mesh)) { + std::cerr << "Not a valid input file." << std::endl; + return 1; + } + + std::cout << "Start remeshing of " << filename + << " (" << num_faces(mesh) << " faces)..." << std::endl; + + CGAL::Bbox_3 bb = PMP::bbox(mesh); + My_sizing_field sizing_field(0.1, 30, bb.ymin(), bb.ymax(), mesh); + unsigned int nb_iter = 5; + + PMP::isotropic_remeshing( + faces(mesh), + sizing_field, + mesh, + CGAL::parameters::number_of_iterations(nb_iter) + .number_of_relaxation_steps(3) + ); + + CGAL::IO::write_polygon_mesh("custom_remesh_out.off", mesh, CGAL::parameters::stream_precision(17)); + + std::cout << "Remeshing done." << std::endl; + + return 0; +} From 37fb95b5cd7619848b829677de5dd64d6f97a6d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 20 Nov 2023 11:28:50 +0100 Subject: [PATCH 2/6] improve concept --- .../Concepts/PMPSizingField.h | 27 ++++++++++--------- ...c_remeshing_with_custom_sizing_example.cpp | 17 ++++++------ .../Adaptive_sizing_field.h | 6 ++--- .../Uniform_sizing_field.h | 6 ++--- .../Isotropic_remeshing/remesh_impl.h | 24 ++++++++--------- .../internal/Sizing_field_base.h | 7 ++--- .../tangential_relaxation.h | 6 ++--- 7 files changed, 48 insertions(+), 45 deletions(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h index 8641c30c6caf..02822cea9e70 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h @@ -16,6 +16,7 @@ class PMPSizingField{ public: /// @name Types +/// These types are used for the documentation of the functions of the concept and not needed implementation wise. /// @{ /// Vertex descriptor type @@ -38,27 +39,29 @@ typedef unspecified_type FT; /// @name Functions /// @{ -/// a function that returns the sizing value at `v`. -FT at(const vertex_descriptor v) const; +/// returns the sizing value at `v` (used during tangential relaxation). +FT at(const vertex_descriptor v, const PolygonMesh& pmesh) const; -/// a function controlling edge split and edge collapse, -/// returning the ratio of the current edge length and the local target edge length between -/// the points of `va` and `vb` in case the current edge is too long, and `std::nullopt` otherwise. +/// returns the ratio of the current edge squared length and the local target edge squared length between +/// the points of `va` and `vb` in case the current edge is too long, and `std::nullopt` otherwise +/// (used for triggering edge splits and preventing some edge collapses). std::optional is_too_long(const vertex_descriptor va, - const vertex_descriptor vb) const; + const vertex_descriptor vb, + const PolygonMesh& pmesh) const; -/// a function controlling edge collapse by returning the ratio of the squared length of `h` and the -/// local target edge length if it is too short, and `std::nullopt` otherwise. +/// returns the ratio of the squared length of `h` and the +/// local target edge squared length if it is too short, and `std::nullopt` otherwise +/// (used for triggering edge collapses). std::optional is_too_short(const halfedge_descriptor h, const PolygonMesh& pmesh) const; -/// a function returning the location of the split point of the edge of `h`. +/// returns the position of the new vertex created when splitting the edge of `h`. Point_3 split_placement(const halfedge_descriptor h, const PolygonMesh& pmesh) const; -/// a function that updates the sizing field value at the vertex `v`. -void update(const vertex_descriptor v, - const PolygonMesh& pmesh); +/// function called after the addition of the split vertex `v` in `pmesh`. +void register_split_vertex(const vertex_descriptor v, + const PolygonMesh& pmesh); /// @} }; diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_with_custom_sizing_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_with_custom_sizing_example.cpp index 1fc70906f7d7..53d70af603ff 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_with_custom_sizing_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/isotropic_remeshing_with_custom_sizing_example.cpp @@ -19,14 +19,12 @@ struct My_sizing_field { double min_size, max_size; double ymin, ymax; - const Mesh& mesh; - My_sizing_field(double min_size, double max_size, double ymin, double ymax, const Mesh& mesh) + My_sizing_field(double min_size, double max_size, double ymin, double ymax) : min_size(min_size) , max_size(max_size) , ymin(ymin) , ymax(ymax) - , mesh(mesh) {} double at(K::Point_3 p) const @@ -34,10 +32,11 @@ struct My_sizing_field double y=p.y(); return CGAL::square( (y-ymin)/(ymax-ymin) * (min_size - max_size) + max_size ); } - double at(const Mesh::Vertex_index v) const { return at(mesh.point(v)); } + double at(const Mesh::Vertex_index v, const Mesh& mesh) const { return at(mesh.point(v)); } std::optional is_too_long(const Mesh::Vertex_index va, - const Mesh::Vertex_index vb) const + const Mesh::Vertex_index vb, + const Mesh& mesh) const { // TODO: no mesh as parameters? K::Point_3 mp = CGAL::midpoint(mesh.point(va), mesh.point(vb)); @@ -49,7 +48,7 @@ struct My_sizing_field } std::optional is_too_short(const Mesh::Halfedge_index h, - const Mesh&) const + const Mesh& mesh) const { K::Point_3 mp = CGAL::midpoint(mesh.point(source(h, mesh)), mesh.point(target(h, mesh))); double sql_at = at(mp); @@ -60,12 +59,12 @@ struct My_sizing_field } K::Point_3 split_placement(const Mesh::Halfedge_index h, - const Mesh&) const + const Mesh& mesh) const { return CGAL::midpoint(mesh.point(source(h, mesh)), mesh.point(target(h, mesh))); } - void update(const Mesh::Vertex_index, const Mesh&) {} + void register_split_vertex(const Mesh::Vertex_index, const Mesh&) {} }; @@ -83,7 +82,7 @@ int main(int argc, char* argv[]) << " (" << num_faces(mesh) << " faces)..." << std::endl; CGAL::Bbox_3 bb = PMP::bbox(mesh); - My_sizing_field sizing_field(0.1, 30, bb.ymin(), bb.ymax(), mesh); + My_sizing_field sizing_field(0.1, 30, bb.ymin(), bb.ymax()); unsigned int nb_iter = 5; PMP::isotropic_remeshing( diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h index a61edc699d06..d576df0e447b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h @@ -213,13 +213,13 @@ class Adaptive_sizing_field } public: - FT at(const vertex_descriptor v) const + FT at(const vertex_descriptor v, const PolygonMesh& /* pmesh */) const { CGAL_assertion(get(m_vertex_sizing_map, v)); return get(m_vertex_sizing_map, v); } - std::optional is_too_long(const vertex_descriptor va, const vertex_descriptor vb) const + std::optional is_too_long(const vertex_descriptor va, const vertex_descriptor vb, const PolygonMesh& /* pmesh */) const { const FT sqlen = sqlength(va, vb); FT sqtarg_len = CGAL::square(4./3. * (CGAL::min)(get(m_vertex_sizing_map, va), @@ -251,7 +251,7 @@ class Adaptive_sizing_field get(m_vpmap, source(h, pmesh))); } - void update(const vertex_descriptor v, const PolygonMesh& pmesh) + void register_split_vertex(const vertex_descriptor v, const PolygonMesh& pmesh) { // calculating it as the average of two vertices on other ends // of halfedges as updating is done during an edge split diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Uniform_sizing_field.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Uniform_sizing_field.h index a4144ceee650..d14f4be9666d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Uniform_sizing_field.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Uniform_sizing_field.h @@ -102,12 +102,12 @@ class Uniform_sizing_field } public: - FT at(const vertex_descriptor /* v */) const + FT at(const vertex_descriptor /* v */, const PolygonMesh& /* pmesh */) const { return m_size; } - std::optional is_too_long(const vertex_descriptor va, const vertex_descriptor vb) const + std::optional is_too_long(const vertex_descriptor va, const vertex_descriptor vb, const PolygonMesh& /* pmesh */) const { const FT sqlen = sqlength(va, vb); if (sqlen > m_sq_long) @@ -133,7 +133,7 @@ class Uniform_sizing_field get(m_vpmap, source(h, pmesh))); } - void update(const vertex_descriptor /* v */, const PolygonMesh& /* pmesh */) + void register_split_vertex(const vertex_descriptor /* v */, const PolygonMesh& /* pmesh */) {} private: diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h index c1696428d756..30d201d1ef51 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h @@ -246,7 +246,7 @@ namespace internal { get(ecmap, e) || get(fpm, face(h,pmesh))!=get(fpm, face(opposite(h,pmesh),pmesh)) ) { - if (sizing.is_too_long(source(h, pmesh), target(h, pmesh))) + if (sizing.is_too_long(source(h, pmesh), target(h, pmesh), pmesh)) { return false; } @@ -400,7 +400,7 @@ namespace internal { for(edge_descriptor e : edge_range) { const halfedge_descriptor he = halfedge(e, mesh_); - std::optional sqlen = sizing.is_too_long(source(he, mesh_), target(he, mesh_)); + std::optional sqlen = sizing.is_too_long(source(he, mesh_), target(he, mesh_), mesh_); if(sqlen != std::nullopt) long_edges.emplace(he, sqlen.value()); } @@ -433,16 +433,16 @@ namespace internal { std::cout << " refinement point : " << refinement_point << std::endl; #endif //update sizing field with the new point - sizing.update(vnew, mesh_); + sizing.register_split_vertex(vnew, mesh_); //check sub-edges //if it was more than twice the "long" threshold, insert them - std::optional sqlen_new = sizing.is_too_long(source(hnew, mesh_), target(hnew, mesh_)); + std::optional sqlen_new = sizing.is_too_long(source(hnew, mesh_), target(hnew, mesh_), mesh_); if(sqlen_new != std::nullopt) long_edges.emplace(hnew, sqlen_new.value()); const halfedge_descriptor hnext = next(hnew, mesh_); - sqlen_new = sizing.is_too_long(source(hnext, mesh_), target(hnext, mesh_)); + sqlen_new = sizing.is_too_long(source(hnext, mesh_), target(hnext, mesh_), mesh_); if (sqlen_new != std::nullopt) long_edges.emplace(hnext, sqlen_new.value()); @@ -500,7 +500,7 @@ namespace internal { if (!is_split_allowed(e)) continue; const halfedge_descriptor he = halfedge(e, mesh_); - std::optional sqlen = sizing.is_too_long(source(he, mesh_), target(he, mesh_)); + std::optional sqlen = sizing.is_too_long(source(he, mesh_), target(he, mesh_), mesh_); if(sqlen != std::nullopt) long_edges.emplace(halfedge(e, mesh_), sqlen.value()); } @@ -550,16 +550,16 @@ namespace internal { halfedge_added(hnew_opp, status(opposite(he, mesh_))); //update sizing field with the new point - sizing.update(vnew, mesh_); + sizing.register_split_vertex(vnew, mesh_); //check sub-edges //if it was more than twice the "long" threshold, insert them - std::optional sqlen_new = sizing.is_too_long(source(hnew, mesh_), target(hnew, mesh_)); + std::optional sqlen_new = sizing.is_too_long(source(hnew, mesh_), target(hnew, mesh_), mesh_); if(sqlen_new != std::nullopt) long_edges.emplace(hnew, sqlen_new.value()); const halfedge_descriptor hnext = next(hnew, mesh_); - sqlen_new = sizing.is_too_long(source(hnext, mesh_), target(hnext, mesh_)); + sqlen_new = sizing.is_too_long(source(hnext, mesh_), target(hnext, mesh_), mesh_); if (sqlen_new != std::nullopt) long_edges.emplace(hnext, sqlen_new.value()); @@ -580,7 +580,7 @@ namespace internal { if (snew == PATCH) { - std::optional sql = sizing.is_too_long(source(hnew2, mesh_), target(hnew2, mesh_)); + std::optional sql = sizing.is_too_long(source(hnew2, mesh_), target(hnew2, mesh_), mesh_); if(sql != std::nullopt) long_edges.emplace(hnew2, sql.value()); } @@ -603,7 +603,7 @@ namespace internal { if (snew == PATCH) { - std::optional sql = sizing.is_too_long(source(hnew2, mesh_), target(hnew2, mesh_)); + std::optional sql = sizing.is_too_long(source(hnew2, mesh_), target(hnew2, mesh_), mesh_); if (sql != std::nullopt) long_edges.emplace(hnew2, sql.value()); } @@ -747,7 +747,7 @@ namespace internal { for(halfedge_descriptor ha : halfedges_around_target(va, mesh_)) { vertex_descriptor va_i = source(ha, mesh_); - std::optional sqha = sizing.is_too_long(vb, va_i); + std::optional sqha = sizing.is_too_long(vb, va_i, mesh_); if (sqha != std::nullopt) { collapse_ok = false; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Sizing_field_base.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Sizing_field_base.h index f13135cd873e..c06f0568e681 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Sizing_field_base.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Sizing_field_base.h @@ -60,13 +60,14 @@ class Sizing_field_base typedef typename K::FT FT; public: - virtual FT at(const vertex_descriptor v) const = 0; + virtual FT at(const vertex_descriptor v, const PolygonMesh&) const = 0; virtual std::optional is_too_long(const vertex_descriptor va, - const vertex_descriptor vb) const = 0; + const vertex_descriptor vb, + const PolygonMesh&) const = 0; virtual std::optional is_too_short(const halfedge_descriptor h, const PolygonMesh& pmesh) const = 0; virtual Point_3 split_placement(const halfedge_descriptor h, const PolygonMesh& pmesh) const = 0; - virtual void update(const vertex_descriptor v, const PolygonMesh& pmesh) = 0; + virtual void register_split_vertex(const vertex_descriptor v, const PolygonMesh& pmesh) = 0; }; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/tangential_relaxation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/tangential_relaxation.h index 6693524324a9..145d5a24135f 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/tangential_relaxation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/tangential_relaxation.h @@ -288,9 +288,9 @@ void tangential_relaxation(const VertexRange& vertices, const double tri_area = gt_area(get(vpm, v), get(vpm, v1), get(vpm, v2)); const double face_weight = tri_area - / (1. / 3. * (sizing.at(v) - + sizing.at(v1) - + sizing.at(v2))); + / (1. / 3. * (sizing.at(v, tm) + + sizing.at(v1, tm) + + sizing.at(v2, tm))); weight += face_weight; const Point_3 centroid = gt_centroid(get(vpm, v), get(vpm, v1), get(vpm, v2)); From fe32ee586e5ee817cc32fa81421745ed2092fe3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 20 Nov 2023 11:36:06 +0100 Subject: [PATCH 3/6] at Eigen dependency --- .../CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h index d576df0e447b..5c3a99efef5b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h @@ -38,6 +38,8 @@ namespace Polygon_mesh_processing * Edges too long with respect to the local target edge length are split in two, while * edges that are too short are collapsed. * +* This class depends on the Eigen library. +* * \cgalModels{PMPSizingField} * * \sa `isotropic_remeshing()` From dc04e5baa58f856c386e4b5fa8bc4de84cbe6746 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 7 Dec 2023 11:30:17 +0100 Subject: [PATCH 4/6] use doxygen macro --- .../CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h index 5c3a99efef5b..e673ac9dfbb7 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Adaptive_sizing_field.h @@ -38,7 +38,7 @@ namespace Polygon_mesh_processing * Edges too long with respect to the local target edge length are split in two, while * edges that are too short are collapsed. * -* This class depends on the Eigen library. +* This class depends on the \eigen library. * * \cgalModels{PMPSizingField} * From 7aab407b8cfd3a39ecad5f207ea88403246d1735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 7 Dec 2023 11:32:17 +0100 Subject: [PATCH 5/6] add user friendly use case --- .../doc/Polygon_mesh_processing/Concepts/PMPSizingField.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h index 02822cea9e70..e3c647510c99 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h @@ -60,6 +60,7 @@ Point_3 split_placement(const halfedge_descriptor h, const PolygonMesh& pmesh) const; /// function called after the addition of the split vertex `v` in `pmesh`. +/// This function can be used for exemple to update a pre-computed sizing field. void register_split_vertex(const vertex_descriptor v, const PolygonMesh& pmesh); From 96955790a1fd1069343605b7dcb8752ad1e6309a Mon Sep 17 00:00:00 2001 From: Sebastien Loriot Date: Thu, 7 Dec 2023 11:57:42 +0100 Subject: [PATCH 6/6] typo Co-authored-by: Jane Tournois --- .../doc/Polygon_mesh_processing/Concepts/PMPSizingField.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h index e3c647510c99..b1216f3281ea 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPSizingField.h @@ -60,7 +60,7 @@ Point_3 split_placement(const halfedge_descriptor h, const PolygonMesh& pmesh) const; /// function called after the addition of the split vertex `v` in `pmesh`. -/// This function can be used for exemple to update a pre-computed sizing field. +/// This function can be used for example to update a pre-computed sizing field. void register_split_vertex(const vertex_descriptor v, const PolygonMesh& pmesh);