From d9cb114484e34d18397cab9a4f7fc6599ddb6b5c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 13 Oct 2014 15:54:20 +0200 Subject: [PATCH 1/4] get_umbrella fixed. It was responsible for holes on the output mesh surface it collects edges incident to the internal facets of the conflict zone, that are restricted to the surface. For each such edge : - if it appears once, we keep it - if it appears twice, we don't consider it - if it appears more than twice, we are in a non-manifold configuration, and the move (pump) is canceled --- Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h | 103 ++++++++++++++++---- 1 file changed, 86 insertions(+), 17 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h index 7f6a06f9ed5..62c37a1692d 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h +++ b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h @@ -38,6 +38,7 @@ #include #include #include +#include #include @@ -403,7 +404,8 @@ private: // Types // weighted point conflict zone. Such facets are represented by their edge // which do not contain the pumped vertex typedef std::pair Ordered_edge; - typedef std::map Umbrella; + typedef std::pair Patch_and_counter; + typedef std::map Umbrella; // Boundary_facets_from_outside represents the facet of the conflict zone // seen from outside of it. It stores Surface_patch_index of the facet, and @@ -531,14 +533,15 @@ private: /** * Returns the umbrella of internal_facets vector */ - Umbrella get_umbrella(const Facet_vector& internal_facets, - const Vertex_handle& v) const; + boost::optional + get_umbrella(const Facet_vector& internal_facets, + const Vertex_handle& v) const; /** * Updates the mesh with new_point */ template - void update_mesh(const Weighted_point& new_point, + bool update_mesh(const Weighted_point& new_point, const Vertex_handle& old_vertex, bool *could_lock_zone = NULL); @@ -567,6 +570,20 @@ private: std::swap(h1, h2); } + template + static + void order_three_handles(Handle& h1, Handle& h2, Handle& h3) + { + std::vector handles; + handles.push_back(h1); + handles.push_back(h2); + handles.push_back(h3); + std::sort(handles.begin(), handles.end()); + h1 = handles[0]; + h2 = handles[1]; + h3 = handles[2]; + } + /** * Initialization */ @@ -1110,9 +1127,10 @@ pump_vertex(const Vertex_handle& pumped_vertex, Weighted_point wp(pumped_vertex->point(), best_weight); // Insert weighted point into mesh - update_mesh(wp, pumped_vertex, could_lock_zone); - - return true; + // note it can fail if the mesh is non-manifold at pumped_vertex + return update_mesh(wp, + pumped_vertex, + could_lock_zone); } return false; @@ -1355,12 +1373,12 @@ get_best_weight(const Vertex_handle& v, bool *could_lock_zone) const template -typename Slivers_exuder::Umbrella +boost::optional::Umbrella > Slivers_exuder:: -get_umbrella(const Facet_vector& facets, +get_umbrella(const Facet_vector& facets,//internal_facets of conflict zone const Vertex_handle& v) const { - Umbrella umbrella; + Umbrella umbrella; //std::map // Insert into umbrella surface_index of facets which are on the surface typename Facet_vector::const_iterator fit = facets.begin(); @@ -1368,11 +1386,55 @@ get_umbrella(const Facet_vector& facets, { if ( c3t3_.is_in_complex(*fit) ) { - Ordered_edge edge = get_opposite_ordered_edge(*fit, v); - umbrella.insert(std::make_pair(edge, c3t3_.surface_patch_index(*fit))); + Facet f = *fit; + Vertex_handle v1 = f.first->vertex((f.second+1)%4); + Vertex_handle v2 = f.first->vertex((f.second+2)%4); + Vertex_handle v3 = f.first->vertex((f.second+3)%4); + order_three_handles(v1, v2, v3); + std::vector edges; + edges.push_back(Ordered_edge(v1, v2)); + edges.push_back(Ordered_edge(v2, v3)); + edges.push_back(Ordered_edge(v1, v3)); + + for(std::size_t i = 0; i < 3; ++i) + { + Ordered_edge oe = edges[i]; + typename Umbrella::iterator uit = umbrella.find(oe); + if(uit == umbrella.end()) //umbrella does not contain oe yet + { + umbrella.insert(std::make_pair(oe, + std::make_pair(c3t3_.surface_patch_index(f), 1))); + } + else //umbrella already contains oe. Increment counter or return + { + std::size_t count = (*uit).second.second; + if(count == 2) //there will be more than 3 after insertion + return boost::none; //non-manifold configuration + + umbrella.insert(uit, + std::make_pair(oe, + std::make_pair(c3t3_.surface_patch_index(f), count + 1))); + } + } } } + // erase edges that have been counted twice + //each Oriented_edge should appear only once + // twice means it belongs to two internal facets that are restricted + // three or more corresponds to a non-manifold geometry + typename Umbrella::iterator uit = umbrella.begin(); + while(uit != umbrella.end()) + { + if((*uit).second.second == 2) + { + typename Umbrella::iterator to_be_erased = uit++; + umbrella.erase(to_be_erased); + } + else + ++uit; + } + return umbrella; } @@ -1438,6 +1500,8 @@ Slivers_exuder::get_opposite_ordered_edge( const Facet& facet, const Vertex_handle& vertex) const { + CGAL_assertion(tr_.has_vertex(facet, vertex)); + Vertex_handle v1; Vertex_handle v2; @@ -1484,7 +1548,7 @@ restore_internal_facets(const Umbrella& umbrella, const typename Umbrella::const_iterator um_it = umbrella.find(edge); if( um_it != umbrella.end() ) { - c3t3_.add_to_complex(*fit, um_it->second); + c3t3_.add_to_complex(*fit, um_it->second.first); } } } @@ -1492,7 +1556,7 @@ restore_internal_facets(const Umbrella& umbrella, template template -void +bool Slivers_exuder:: update_mesh(const Weighted_point& new_point, const Vertex_handle& old_vertex, @@ -1516,13 +1580,16 @@ update_mesh(const Weighted_point& new_point, could_lock_zone); if (could_lock_zone && *could_lock_zone == false) - return; + return false; // Get some datas to restore mesh Boundary_facets_from_outside boundary_facets_from_outside = get_boundary_facets_from_outside(boundary_facets); - Umbrella umbrella = get_umbrella(internal_facets, old_vertex); + boost::optional umbrella + = get_umbrella(internal_facets, old_vertex); + if(umbrella == boost::none) + return false; //abort pumping this vertex // Delete old cells from queue (they aren't in the triangulation anymore) this->delete_cells_from_queue(deleted_cells); @@ -1546,10 +1613,12 @@ update_mesh(const Weighted_point& new_point, // Restore mesh restore_cells_and_boundary_facets( boundary_facets_from_outside, new_vertex); - restore_internal_facets(umbrella, new_vertex); + restore_internal_facets(*umbrella, new_vertex); // Only true for sequential version CGAL_assertion(could_lock_zone || nb_vert == tr_.number_of_vertices()); + + return true;//pump was done successfully } From 2ff8f82bf2e185a8c048a3414da8cde3c6d73a46 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 14 Oct 2014 10:27:37 +0200 Subject: [PATCH 2/4] improve the sorting function --- Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h index 62c37a1692d..989ad7c6d05 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h +++ b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h @@ -574,14 +574,9 @@ private: static void order_three_handles(Handle& h1, Handle& h2, Handle& h3) { - std::vector handles; - handles.push_back(h1); - handles.push_back(h2); - handles.push_back(h3); - std::sort(handles.begin(), handles.end()); - h1 = handles[0]; - h2 = handles[1]; - h3 = handles[2]; + if(h1 > h2) std::swap(h1, h2); + if(h2 > h3) std::swap(h2, h3); + if(h1 > h2) std::swap(h1, h2); } /** From 47708fd7e59d6f07fb5369ce65ec5956aa258d9c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 17 Oct 2014 10:46:13 +0200 Subject: [PATCH 3/4] Fix a warning --- Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h index 989ad7c6d05..106da977687 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h +++ b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h @@ -1371,7 +1371,8 @@ template boost::optional::Umbrella > Slivers_exuder:: get_umbrella(const Facet_vector& facets,//internal_facets of conflict zone - const Vertex_handle& v) const + + const Vertex_handle& /* v no longer used */) const { Umbrella umbrella; //std::map From df0ec2e54de3b0a6c3e814f02eca917d02e460ab Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 21 Oct 2014 11:29:07 +0200 Subject: [PATCH 4/4] mention exuder bug fix in changes.html --- Installation/changes.html | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Installation/changes.html b/Installation/changes.html index 83afb8388f8..57181c394b0 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -59,6 +59,7 @@ +
4.5.1  (XX 2014)
4.5  (October 2014)
4.4  (April 2014)
4.3.1  (November 2013) @@ -109,6 +110,17 @@ and src/ directories).
+ +

Release 4.5.1

+
+

Release date: XX 2014

+ +

3D Mesh Generation

+
    +
  • Fix a bug in the sliver exudation preservation of boundaries.
  • +
+
+

Release 4.5

Release date: October 2014