Merge pull request #2514 from janetournois/Polyhedron_demo-fix_isotropic_remeshing_plugin-jtournois

Polyhedron demo - fix isotropic remeshing plugin
This commit is contained in:
Laurent Rineau 2017-10-23 16:53:18 +02:00
commit 7caa6ea021
2 changed files with 136 additions and 92 deletions

View File

@ -189,6 +189,9 @@ namespace internal {
patch_ids_map = CGAL::internal::add_property(Face_property_tag("PMP_patch_id"), pmesh); patch_ids_map = CGAL::internal::add_property(Face_property_tag("PMP_patch_id"), pmesh);
if (do_init) if (do_init)
{ {
#ifdef CGAL_PMP_REMESHING_VERBOSE
std::cout << "Compute connected components property map." << std::endl;
#endif
nb_cc nb_cc
= PMP::connected_components(pmesh, = PMP::connected_components(pmesh,
patch_ids_map, patch_ids_map,
@ -616,6 +619,10 @@ namespace internal {
#ifdef CGAL_PMP_REMESHING_VERBOSE #ifdef CGAL_PMP_REMESHING_VERBOSE
std::cout << "Collapse short edges (" << low << ", " << high << ")..." std::cout << "Collapse short edges (" << low << ", " << high << ")..."
<< std::endl; << std::endl;
#endif
#ifdef CGAL_PMP_REMESHING_VERBOSE_PROGRESS
std::cout << "Fill bimap...";
std::cout.flush();
#endif #endif
double sq_low = low*low; double sq_low = low*low;
double sq_high = high*high; double sq_high = high*high;
@ -627,6 +634,9 @@ namespace internal {
if( (sqlen < sq_low) && is_collapse_allowed(e) ) if( (sqlen < sq_low) && is_collapse_allowed(e) )
short_edges.insert(short_edge(halfedge(e, mesh_), sqlen)); short_edges.insert(short_edge(halfedge(e, mesh_), sqlen));
} }
#ifdef CGAL_PMP_REMESHING_VERBOSE_PROGRESS
std::cout << "done." << std::endl;
#endif
unsigned int nb_collapses = 0; unsigned int nb_collapses = 0;
while (!short_edges.empty()) while (!short_edges.empty())
@ -686,6 +696,8 @@ namespace internal {
if (is_on_patch_border(va) && !is_on_patch_border(vb)) if (is_on_patch_border(va) && !is_on_patch_border(vb))
continue;//we cannot swap again. It would lead to a face inversion continue;//we cannot swap again. It would lead to a face inversion
else if (is_corner(va) && !is_corner(vb))
continue;//idem
} }
else else
continue;//both directions invert a face continue;//both directions invert a face
@ -1355,34 +1367,10 @@ private:
//collect normals to faces around vs AND vt //collect normals to faces around vs AND vt
//vertices are at the same location, but connectivity is still be same, //vertices are at the same location, but connectivity is still be same,
//with plenty of degenerate triangles (which are common to both stars) //with plenty of degenerate triangles (which are common to both stars)
std::vector<Vector_3> normals_patch1; bool res = check_normals(
std::vector<Vector_3> normals_patch2; boost::range::join(
normals_patch1.reserve(8); halfedges_around_target(h, mesh_),
normals_patch2.reserve(8); halfedges_around_target(opposite(h, mesh_), mesh_)));
Patch_id patch1 = -1, patch2 = -1;
BOOST_FOREACH(halfedge_descriptor hd,
boost::range::join(halfedges_around_target(h, mesh_),
halfedges_around_target(opposite(h, mesh_), mesh_)))
{
Vector_3 n = compute_normal(face(hd, mesh_));
if (n == CGAL::NULL_VECTOR) //for degenerate faces
continue;
Patch_id pid = get_patch_id(face(hd, mesh_));
if (patch1 == Patch_id(-1))
patch1 = pid; //not met yet
else if (patch2 == Patch_id(-1) && patch1 != pid)
patch2 = pid; //not met yet
CGAL_assertion(pid == patch1 || pid == patch2);
if (pid == patch1) normals_patch1.push_back(n);
else normals_patch2.push_back(n);
}
//on each surface patch,
//check all normals have same orientation
bool res = check_orientation(normals_patch1)
&& check_orientation(normals_patch2);
//restore position //restore position
put(vpmap_, vs, ps); put(vpmap_, vs, ps);
@ -1436,7 +1424,7 @@ private:
if (GeomTraits().collinear_3_object()(p,q,r)) if (GeomTraits().collinear_3_object()(p,q,r))
return CGAL::NULL_VECTOR; return CGAL::NULL_VECTOR;
else else
return PMP::compute_face_normal(f, mesh_); return PMP::compute_face_normal(f, mesh_, parameters::vertex_point_map(vpmap_));
} }
template <typename FaceRange> template <typename FaceRange>
@ -1832,37 +1820,43 @@ private:
//have all their 2 by 2 dot products > 0 //have all their 2 by 2 dot products > 0
bool check_normals(const vertex_descriptor& v) const bool check_normals(const vertex_descriptor& v) const
{ {
if (is_corner(v)) return check_normals(halfedges_around_target(halfedge(v, mesh_), mesh_));
return true;//if we want to deal with this case, }
//we should use a multimap to store <Patch_id, Normal>
std::vector<Vector_3> normals_patch1; template <typename HalfedgeRange>
std::vector<Vector_3> normals_patch2; bool check_normals(const HalfedgeRange& hedges) const
normals_patch1.reserve(8); {
normals_patch2.reserve(8); typedef std::multimap<Patch_id, Vector_3> Normals_multimap;
Patch_id patch1 = -1, patch2 = -1; typedef typename Normals_multimap::iterator Normals_iterator;
BOOST_FOREACH(halfedge_descriptor hd,
halfedges_around_target(halfedge(v, mesh_), mesh_)) Normals_multimap normals_per_patch;
BOOST_FOREACH(halfedge_descriptor hd, hedges)
{ {
Vector_3 n = compute_normal(face(hd, mesh_)); Vector_3 n = compute_normal(face(hd, mesh_));
if (n == CGAL::NULL_VECTOR) if (n == CGAL::NULL_VECTOR) //for degenerate faces
continue; continue;
Patch_id pid = get_patch_id(face(hd, mesh_)); Patch_id pid = get_patch_id(face(hd, mesh_));
if (patch1 == Patch_id(-1)) normals_per_patch.insert(std::make_pair(pid, n));
patch1 = pid; //not met yet
else if (patch2 == Patch_id(-1) && patch1 != pid)
patch2 = pid; //not met yet
CGAL_assertion(pid == patch1 || pid == patch2);
if (pid == patch1) normals_patch1.push_back(n);
else normals_patch2.push_back(n);
} }
//on each surface patch, //on each surface patch,
//check all normals have same orientation //check all normals have same orientation
return check_orientation(normals_patch1) for (Normals_iterator it = normals_per_patch.begin();
&& check_orientation(normals_patch2); it != normals_per_patch.end();/*done inside loop*/)
{
std::vector<Vector_3> normals;
std::pair<Normals_iterator, Normals_iterator> n_range
= normals_per_patch.equal_range((*it).first);
for (Normals_iterator iit = n_range.first; iit != n_range.second; ++iit)
normals.push_back((*iit).second);
if (!check_orientation(normals))
return false;
it = n_range.second;
}
return true;
} }
bool check_normals(const halfedge_descriptor& h) const bool check_normals(const halfedge_descriptor& h) const
@ -1917,7 +1911,6 @@ private:
Patch_id_to_index_map patch_id_to_index_map; Patch_id_to_index_map patch_id_to_index_map;
Triangle_list input_triangles_; Triangle_list input_triangles_;
Patch_id_list input_patch_ids_; Patch_id_list input_patch_ids_;
Patch_id_to_index_map patch_id_to_index_map_;
Halfedge_status_pmap halfedge_status_pmap_; Halfedge_status_pmap halfedge_status_pmap_;
bool protect_constraints_; bool protect_constraints_;
FacePatchMap patch_ids_map_; FacePatchMap patch_ids_map_;

View File

@ -1,6 +1,7 @@
//#define CGAL_PMP_REMESHING_VERBOSE //#define CGAL_PMP_REMESHING_VERBOSE
//#define CGAL_PMP_REMESHING_DEBUG //#define CGAL_PMP_REMESHING_DEBUG
//#define CGAL_PMP_REMESHING_VERY_VERBOSE //#define CGAL_PMP_REMESHING_VERY_VERBOSE
//#define CGAL_PMP_REMESHING_VERBOSE_PROGRESS
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
@ -8,11 +9,15 @@
#ifdef USE_SURFACE_MESH #ifdef USE_SURFACE_MESH
#include "Scene_surface_mesh_item.h" #include "Scene_surface_mesh_item.h"
#include <CGAL/Mesh_3/properties_Surface_mesh.h>
#else #else
#include "Scene_polyhedron_item.h" #include "Scene_polyhedron_item.h"
#include "Polyhedron_type.h" #include "Polyhedron_type.h"
#include <CGAL/Mesh_3/properties_Polyhedron_3.h>
#endif #endif
#include <CGAL/Mesh_3/properties.h>
#include "Scene_polyhedron_selection_item.h" #include "Scene_polyhedron_selection_item.h"
#include <CGAL/iterator.h> #include <CGAL/iterator.h>
@ -341,11 +346,25 @@ public Q_SLOTS:
typedef boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor; typedef boost::graph_traits<FaceGraph>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<FaceGraph>::face_descriptor face_descriptor; typedef boost::graph_traits<FaceGraph>::face_descriptor face_descriptor;
const FaceGraph& pmesh = (poly_item != NULL) FaceGraph& pmesh = (poly_item != NULL)
? *poly_item->polyhedron() ? *poly_item->polyhedron()
: *selection_item->polyhedron(); : *selection_item->polyhedron();
reset_face_ids(pmesh); reset_face_ids(pmesh);
Patch_id_pmap fpmap = get(CGAL::face_patch_id_t<int>(), pmesh);
bool fpmap_valid = false;
{
BOOST_FOREACH(face_descriptor f, faces(pmesh))
{
if (get(fpmap, f) != 1)
{
fpmap_valid = true;
break;/*1 is the default value for both Surface_mesh and Polyhedron*/
}
}
}
if (selection_item) if (selection_item)
{ {
if (edges_only) if (edges_only)
@ -378,10 +397,7 @@ public Q_SLOTS:
else else
std::cout << "No selected or boundary edges to be split" << std::endl; std::cout << "No selected or boundary edges to be split" << std::endl;
} }
else else //not edges_only
{
if (selection_item->selected_facets.empty() &&
(!selection_item->selected_edges.empty() || !selection_item->selected_vertices.empty()))
{ {
if(protect && if(protect &&
!CGAL::Polygon_mesh_processing::internal::constraints_are_short_enough( !CGAL::Polygon_mesh_processing::internal::constraints_are_short_enough(
@ -399,8 +415,10 @@ public Q_SLOTS:
return; return;
} }
CGAL::Polygon_mesh_processing::isotropic_remeshing( if (selection_item->selected_facets.empty() && !selection_item->isEmpty())
faces(*selection_item->polyhedron()) {
if (fpmap_valid)
CGAL::Polygon_mesh_processing::isotropic_remeshing(faces(*selection_item->polyhedron())
, target_length , target_length
, *selection_item->polyhedron() , *selection_item->polyhedron()
, CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter) , CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
@ -409,12 +427,22 @@ public Q_SLOTS:
.relax_constraints(smooth_features) .relax_constraints(smooth_features)
.number_of_relaxation_steps(nb_smooth) .number_of_relaxation_steps(nb_smooth)
.vertex_is_constrained_map(selection_item->constrained_vertices_pmap()) .vertex_is_constrained_map(selection_item->constrained_vertices_pmap())
.face_patch_map(fpmap));
.face_patch_map(get(CGAL::face_patch_id_t<int>(), *selection_item->polyhedron())));
}
else else
CGAL::Polygon_mesh_processing::isotropic_remeshing( CGAL::Polygon_mesh_processing::isotropic_remeshing(faces(*selection_item->polyhedron())
selection_item->selected_facets , target_length
, *selection_item->polyhedron()
, CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
.protect_constraints(protect)
.edge_is_constrained_map(selection_item->constrained_edges_pmap())
.relax_constraints(smooth_features)
.number_of_relaxation_steps(nb_smooth)
.vertex_is_constrained_map(selection_item->constrained_vertices_pmap()));
}
else //selected_facets not empty
{
if (fpmap_valid)
CGAL::Polygon_mesh_processing::isotropic_remeshing(selection_item->selected_facets
, target_length , target_length
, *selection_item->polyhedron() , *selection_item->polyhedron()
, CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter) , CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
@ -423,12 +451,23 @@ public Q_SLOTS:
.relax_constraints(smooth_features) .relax_constraints(smooth_features)
.number_of_relaxation_steps(nb_smooth) .number_of_relaxation_steps(nb_smooth)
.vertex_is_constrained_map(selection_item->constrained_vertices_pmap()) .vertex_is_constrained_map(selection_item->constrained_vertices_pmap())
.face_patch_map(get(CGAL::face_patch_id_t<int>(), *selection_item->polyhedron()))); .face_patch_map(fpmap));
else
CGAL::Polygon_mesh_processing::isotropic_remeshing(selection_item->selected_facets
, target_length
, *selection_item->polyhedron()
, CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
.protect_constraints(protect)
.edge_is_constrained_map(selection_item->constrained_edges_pmap())
.relax_constraints(smooth_features)
.number_of_relaxation_steps(nb_smooth)
.vertex_is_constrained_map(selection_item->constrained_vertices_pmap()));
}
} }
#ifdef USE_SURFACE_MESH #ifdef USE_SURFACE_MESH
selection_item->polyhedron_item()->setColor( selection_item->polyhedron_item()->setColor(
selection_item->polyhedron_item()->color()); selection_item->polyhedron_item()->color());
selection_item->polyhedron_item()->setItemIsMulticolor(false); selection_item->polyhedron_item()->setItemIsMulticolor(fpmap_valid);
selection_item->polyhedron_item()->polyhedron()->collect_garbage(); selection_item->polyhedron_item()->polyhedron()->collect_garbage();
#else #else
if(!selection_item->polyhedron_item()->isItemMulticolor()) if(!selection_item->polyhedron_item()->isItemMulticolor())
@ -475,6 +514,18 @@ public Q_SLOTS:
} }
Scene_polyhedron_selection_item::Is_constrained_map<Edge_set> ecm(&edges_to_protect); Scene_polyhedron_selection_item::Is_constrained_map<Edge_set> ecm(&edges_to_protect);
if (fpmap_valid)
CGAL::Polygon_mesh_processing::isotropic_remeshing(
faces(*poly_item->polyhedron())
, target_length
, *poly_item->polyhedron()
, CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
.protect_constraints(protect)
.number_of_relaxation_steps(nb_smooth)
.edge_is_constrained_map(ecm)
.relax_constraints(smooth_features)
.face_patch_map(fpmap));
else
CGAL::Polygon_mesh_processing::isotropic_remeshing( CGAL::Polygon_mesh_processing::isotropic_remeshing(
faces(*poly_item->polyhedron()) faces(*poly_item->polyhedron())
, target_length , target_length
@ -482,9 +533,9 @@ public Q_SLOTS:
, CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter) , CGAL::Polygon_mesh_processing::parameters::number_of_iterations(nb_iter)
.protect_constraints(protect) .protect_constraints(protect)
.number_of_relaxation_steps(nb_smooth) .number_of_relaxation_steps(nb_smooth)
.face_patch_map(get(CGAL::face_patch_id_t<int>(), *poly_item->polyhedron()))
.edge_is_constrained_map(ecm) .edge_is_constrained_map(ecm)
.relax_constraints(smooth_features)); .relax_constraints(smooth_features));
} }
//destroys the patch_id_map for the Surface_mesh_item to avoid assertions. //destroys the patch_id_map for the Surface_mesh_item to avoid assertions.
#ifdef USE_SURFACE_MESH #ifdef USE_SURFACE_MESH