mirror of https://github.com/CGAL/cgal
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
This commit is contained in:
parent
70b5a14c9a
commit
d9cb114484
|
|
@ -38,6 +38,7 @@
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <boost/type_traits/is_convertible.hpp>
|
#include <boost/type_traits/is_convertible.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include <CGAL/Timer.h>
|
#include <CGAL/Timer.h>
|
||||||
|
|
||||||
|
|
@ -403,7 +404,8 @@ private: // Types
|
||||||
// weighted point conflict zone. Such facets are represented by their edge
|
// weighted point conflict zone. Such facets are represented by their edge
|
||||||
// which do not contain the pumped vertex
|
// which do not contain the pumped vertex
|
||||||
typedef std::pair<Vertex_handle,Vertex_handle> Ordered_edge;
|
typedef std::pair<Vertex_handle,Vertex_handle> Ordered_edge;
|
||||||
typedef std::map<Ordered_edge, Surface_patch_index > Umbrella;
|
typedef std::pair<Surface_patch_index, std::size_t> Patch_and_counter;
|
||||||
|
typedef std::map<Ordered_edge, Patch_and_counter> Umbrella;
|
||||||
|
|
||||||
// Boundary_facets_from_outside represents the facet of the conflict zone
|
// 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
|
// 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
|
* Returns the umbrella of internal_facets vector
|
||||||
*/
|
*/
|
||||||
Umbrella get_umbrella(const Facet_vector& internal_facets,
|
boost::optional<Umbrella>
|
||||||
const Vertex_handle& v) const;
|
get_umbrella(const Facet_vector& internal_facets,
|
||||||
|
const Vertex_handle& v) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the mesh with new_point
|
* Updates the mesh with new_point
|
||||||
*/
|
*/
|
||||||
template <bool pump_vertices_on_surfaces>
|
template <bool pump_vertices_on_surfaces>
|
||||||
void update_mesh(const Weighted_point& new_point,
|
bool update_mesh(const Weighted_point& new_point,
|
||||||
const Vertex_handle& old_vertex,
|
const Vertex_handle& old_vertex,
|
||||||
bool *could_lock_zone = NULL);
|
bool *could_lock_zone = NULL);
|
||||||
|
|
||||||
|
|
@ -567,6 +570,20 @@ private:
|
||||||
std::swap(h1, h2);
|
std::swap(h1, h2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Handle>
|
||||||
|
static
|
||||||
|
void order_three_handles(Handle& h1, Handle& h2, Handle& h3)
|
||||||
|
{
|
||||||
|
std::vector<Handle> 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
|
* Initialization
|
||||||
*/
|
*/
|
||||||
|
|
@ -1110,9 +1127,10 @@ pump_vertex(const Vertex_handle& pumped_vertex,
|
||||||
Weighted_point wp(pumped_vertex->point(), best_weight);
|
Weighted_point wp(pumped_vertex->point(), best_weight);
|
||||||
|
|
||||||
// Insert weighted point into mesh
|
// Insert weighted point into mesh
|
||||||
update_mesh<pump_vertices_on_surfaces>(wp, pumped_vertex, could_lock_zone);
|
// note it can fail if the mesh is non-manifold at pumped_vertex
|
||||||
|
return update_mesh<pump_vertices_on_surfaces>(wp,
|
||||||
return true;
|
pumped_vertex,
|
||||||
|
could_lock_zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1355,12 +1373,12 @@ get_best_weight(const Vertex_handle& v, bool *could_lock_zone) const
|
||||||
|
|
||||||
|
|
||||||
template <typename C3T3, typename SC, typename V_, typename FT>
|
template <typename C3T3, typename SC, typename V_, typename FT>
|
||||||
typename Slivers_exuder<C3T3,SC,V_,FT>::Umbrella
|
boost::optional<typename Slivers_exuder<C3T3,SC,V_,FT>::Umbrella >
|
||||||
Slivers_exuder<C3T3,SC,V_,FT>::
|
Slivers_exuder<C3T3,SC,V_,FT>::
|
||||||
get_umbrella(const Facet_vector& facets,
|
get_umbrella(const Facet_vector& facets,//internal_facets of conflict zone
|
||||||
const Vertex_handle& v) const
|
const Vertex_handle& v) const
|
||||||
{
|
{
|
||||||
Umbrella umbrella;
|
Umbrella umbrella; //std::map<Ordered_edge, Patch_and_counter>
|
||||||
|
|
||||||
// Insert into umbrella surface_index of facets which are on the surface
|
// Insert into umbrella surface_index of facets which are on the surface
|
||||||
typename Facet_vector::const_iterator fit = facets.begin();
|
typename Facet_vector::const_iterator fit = facets.begin();
|
||||||
|
|
@ -1368,11 +1386,55 @@ get_umbrella(const Facet_vector& facets,
|
||||||
{
|
{
|
||||||
if ( c3t3_.is_in_complex(*fit) )
|
if ( c3t3_.is_in_complex(*fit) )
|
||||||
{
|
{
|
||||||
Ordered_edge edge = get_opposite_ordered_edge(*fit, v);
|
Facet f = *fit;
|
||||||
umbrella.insert(std::make_pair(edge, c3t3_.surface_patch_index(*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<Ordered_edge> 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;
|
return umbrella;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1438,6 +1500,8 @@ Slivers_exuder<C3T3,SC,V_,FT>::get_opposite_ordered_edge(
|
||||||
const Facet& facet,
|
const Facet& facet,
|
||||||
const Vertex_handle& vertex) const
|
const Vertex_handle& vertex) const
|
||||||
{
|
{
|
||||||
|
CGAL_assertion(tr_.has_vertex(facet, vertex));
|
||||||
|
|
||||||
Vertex_handle v1;
|
Vertex_handle v1;
|
||||||
Vertex_handle v2;
|
Vertex_handle v2;
|
||||||
|
|
||||||
|
|
@ -1484,7 +1548,7 @@ restore_internal_facets(const Umbrella& umbrella,
|
||||||
const typename Umbrella::const_iterator um_it = umbrella.find(edge);
|
const typename Umbrella::const_iterator um_it = umbrella.find(edge);
|
||||||
if( um_it != umbrella.end() )
|
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 <typename C3T3, typename SC, typename V_, typename FT>
|
template <typename C3T3, typename SC, typename V_, typename FT>
|
||||||
template <bool pump_vertices_on_surfaces>
|
template <bool pump_vertices_on_surfaces>
|
||||||
void
|
bool
|
||||||
Slivers_exuder<C3T3,SC,V_,FT>::
|
Slivers_exuder<C3T3,SC,V_,FT>::
|
||||||
update_mesh(const Weighted_point& new_point,
|
update_mesh(const Weighted_point& new_point,
|
||||||
const Vertex_handle& old_vertex,
|
const Vertex_handle& old_vertex,
|
||||||
|
|
@ -1516,13 +1580,16 @@ update_mesh(const Weighted_point& new_point,
|
||||||
could_lock_zone);
|
could_lock_zone);
|
||||||
|
|
||||||
if (could_lock_zone && *could_lock_zone == false)
|
if (could_lock_zone && *could_lock_zone == false)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// Get some datas to restore mesh
|
// Get some datas to restore mesh
|
||||||
Boundary_facets_from_outside boundary_facets_from_outside =
|
Boundary_facets_from_outside boundary_facets_from_outside =
|
||||||
get_boundary_facets_from_outside(boundary_facets);
|
get_boundary_facets_from_outside(boundary_facets);
|
||||||
|
|
||||||
Umbrella umbrella = get_umbrella(internal_facets, old_vertex);
|
boost::optional<Umbrella> 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)
|
// Delete old cells from queue (they aren't in the triangulation anymore)
|
||||||
this->delete_cells_from_queue(deleted_cells);
|
this->delete_cells_from_queue(deleted_cells);
|
||||||
|
|
@ -1546,10 +1613,12 @@ update_mesh(const Weighted_point& new_point,
|
||||||
// Restore mesh
|
// Restore mesh
|
||||||
restore_cells_and_boundary_facets<pump_vertices_on_surfaces>(
|
restore_cells_and_boundary_facets<pump_vertices_on_surfaces>(
|
||||||
boundary_facets_from_outside, new_vertex);
|
boundary_facets_from_outside, new_vertex);
|
||||||
restore_internal_facets(umbrella, new_vertex);
|
restore_internal_facets(*umbrella, new_vertex);
|
||||||
|
|
||||||
// Only true for sequential version
|
// Only true for sequential version
|
||||||
CGAL_assertion(could_lock_zone || nb_vert == tr_.number_of_vertices());
|
CGAL_assertion(could_lock_zone || nb_vert == tr_.number_of_vertices());
|
||||||
|
|
||||||
|
return true;//pump was done successfully
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue