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

View File

@ -1,6 +1,7 @@
//#define CGAL_PMP_REMESHING_VERBOSE
//#define CGAL_PMP_REMESHING_DEBUG
//#define CGAL_PMP_REMESHING_VERY_VERBOSE
//#define CGAL_PMP_REMESHING_VERBOSE_PROGRESS
#include <QtCore/qglobal.h>
@ -8,11 +9,15 @@
#ifdef USE_SURFACE_MESH
#include "Scene_surface_mesh_item.h"
#include <CGAL/Mesh_3/properties_Surface_mesh.h>
#else
#include "Scene_polyhedron_item.h"
#include "Polyhedron_type.h"
#include <CGAL/Mesh_3/properties_Polyhedron_3.h>
#endif
#include <CGAL/Mesh_3/properties.h>
#include "Scene_polyhedron_selection_item.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>::face_descriptor face_descriptor;
const FaceGraph& pmesh = (poly_item != NULL)
FaceGraph& pmesh = (poly_item != NULL)
? *poly_item->polyhedron()
: *selection_item->polyhedron();
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 (edges_only)
@ -378,11 +397,8 @@ public Q_SLOTS:
else
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 &&
!CGAL::Polygon_mesh_processing::internal::constraints_are_short_enough(
*selection_item->polyhedron(),
@ -399,36 +415,59 @@ public Q_SLOTS:
return;
}
CGAL::Polygon_mesh_processing::isotropic_remeshing(
faces(*selection_item->polyhedron())
, 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())
.face_patch_map(get(CGAL::face_patch_id_t<int>(), *selection_item->polyhedron())));
}
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())
.face_patch_map(get(CGAL::face_patch_id_t<int>(), *selection_item->polyhedron())));
if (selection_item->selected_facets.empty() && !selection_item->isEmpty())
{
if (fpmap_valid)
CGAL::Polygon_mesh_processing::isotropic_remeshing(faces(*selection_item->polyhedron())
, 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())
.face_patch_map(fpmap));
else
CGAL::Polygon_mesh_processing::isotropic_remeshing(faces(*selection_item->polyhedron())
, 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
, *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())
.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
selection_item->polyhedron_item()->setColor(
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();
#else
if(!selection_item->polyhedron_item()->isItemMulticolor())
@ -475,16 +514,28 @@ public Q_SLOTS:
}
Scene_polyhedron_selection_item::Is_constrained_map<Edge_set> ecm(&edges_to_protect);
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)
.face_patch_map(get(CGAL::face_patch_id_t<int>(), *poly_item->polyhedron()))
.edge_is_constrained_map(ecm)
.relax_constraints(smooth_features));
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(
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));
}
//destroys the patch_id_map for the Surface_mesh_item to avoid assertions.
#ifdef USE_SURFACE_MESH