diff --git a/Installation/CHANGES b/Installation/CHANGES
index 7bbae6665fd..4ed4bc18762 100644
--- a/Installation/CHANGES
+++ b/Installation/CHANGES
@@ -1,4 +1,14 @@
+-------------------------------- 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
diff --git a/Installation/changes.html b/Installation/changes.html
index 83afb8388f8..00897af75b7 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
diff --git a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h
index 7f6a06f9ed5..106da977687 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,15 @@ private:
std::swap(h1, h2);
}
+ template
+ static
+ void order_three_handles(Handle& h1, Handle& h2, Handle& h3)
+ {
+ if(h1 > h2) std::swap(h1, h2);
+ if(h2 > h3) std::swap(h2, h3);
+ if(h1 > h2) std::swap(h1, h2);
+ }
+
/**
* Initialization
*/
@@ -1110,9 +1122,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 +1368,13 @@ 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,
- const Vertex_handle& v) const
+get_umbrella(const Facet_vector& facets,//internal_facets of conflict zone
+
+ const Vertex_handle& /* v no longer used */) 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 +1382,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 +1496,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 +1544,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 +1552,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 +1576,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 +1609,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
}
| |