mirror of https://github.com/CGAL/cgal
Merge pull request #2514 from janetournois/Polyhedron_demo-fix_isotropic_remeshing_plugin-jtournois
Polyhedron demo - fix isotropic remeshing plugin
This commit is contained in:
commit
7caa6ea021
|
|
@ -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_;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue