Merge pull request #5012 from MaelRL/PMP-Repair_degeneracies_fixes-5.1-GF

PMP: Degeneracy removal fixes
This commit is contained in:
Laurent Rineau 2020-10-09 16:50:29 +02:00
commit 40338b2a23
4 changed files with 41 additions and 45 deletions

View File

@ -256,7 +256,7 @@ std::size_t remove_connected_components_of_negligible_size(TriangleMesh& tmesh,
// Volumes make no sense for CCs that are not closed // Volumes make no sense for CCs that are not closed
std::vector<bool> cc_closeness(num, true); std::vector<bool> cc_closeness(num, true);
std::vector<FT> component_volumes(num); std::vector<FT> component_volumes(num, FT(0));
if(use_volumes) if(use_volumes)
{ {

View File

@ -183,13 +183,15 @@ bool is_collapse_geometrically_valid(typename boost::graph_traits<TriangleMesh>:
*/ */
template <class TriangleMesh, typename VPM, typename Traits> template <class TriangleMesh, typename VPM, typename Traits>
boost::optional<double> get_collapse_volume(typename boost::graph_traits<TriangleMesh>::halfedge_descriptor h, boost::optional<typename Traits::FT>
get_collapse_volume(typename boost::graph_traits<TriangleMesh>::halfedge_descriptor h,
const TriangleMesh& tmesh, const TriangleMesh& tmesh,
const VPM& vpm, const VPM& vpm,
const Traits& gt) const Traits& gt)
{ {
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename Traits::FT FT;
typedef typename boost::property_traits<VPM>::reference Point_ref; typedef typename boost::property_traits<VPM>::reference Point_ref;
typedef typename Traits::Vector_3 Vector_3; typedef typename Traits::Vector_3 Vector_3;
@ -204,7 +206,7 @@ boost::optional<double> get_collapse_volume(typename boost::graph_traits<Triangl
Point_ref removed= get(vpm, target(h, tmesh)); Point_ref removed= get(vpm, target(h, tmesh));
// init volume with incident triangles (reversed orientation // init volume with incident triangles (reversed orientation
double delta_vol = volume(removed, kept, get(vpm, target(next(h, tmesh), tmesh)), origin) + FT delta_vol = volume(removed, kept, get(vpm, target(next(h, tmesh), tmesh)), origin) +
volume(kept, removed, get(vpm, target(next(opposite(h, tmesh), tmesh), tmesh)), origin); volume(kept, removed, get(vpm, target(next(opposite(h, tmesh), tmesh), tmesh)), origin);
// consider triangles incident to the vertex removed // consider triangles incident to the vertex removed
@ -248,13 +250,14 @@ get_best_edge_orientation(typename boost::graph_traits<TriangleMesh>::edge_descr
const Traits& gt) const Traits& gt)
{ {
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename Traits::FT FT;
halfedge_descriptor h = halfedge(e, tmesh), ho = opposite(h, tmesh); halfedge_descriptor h = halfedge(e, tmesh), ho = opposite(h, tmesh);
CGAL_assertion(!get(vcm, source(h, tmesh)) || !get(vcm, target(h, tmesh))); CGAL_assertion(!get(vcm, source(h, tmesh)) || !get(vcm, target(h, tmesh)));
boost::optional<double> dv1 = get_collapse_volume(h, tmesh, vpm, gt); boost::optional<FT> dv1 = get_collapse_volume(h, tmesh, vpm, gt);
boost::optional<double> dv2 = get_collapse_volume(ho, tmesh, vpm, gt); boost::optional<FT> dv2 = get_collapse_volume(ho, tmesh, vpm, gt);
// the resulting point of the collapse of a halfedge is the target of the halfedge before collapse // the resulting point of the collapse of a halfedge is the target of the halfedge before collapse
if(get(vcm, source(h, tmesh))) if(get(vcm, source(h, tmesh)))
@ -288,6 +291,7 @@ bool should_flip(typename boost::graph_traits<TriangleMesh>::edge_descriptor e,
{ {
typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits<TriangleMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename Traits::FT FT;
typedef typename boost::property_traits<VPM>::reference Point_ref; typedef typename boost::property_traits<VPM>::reference Point_ref;
typedef typename Traits::Vector_3 Vector_3; typedef typename Traits::Vector_3 Vector_3;
@ -318,14 +322,14 @@ bool should_flip(typename boost::graph_traits<TriangleMesh>::edge_descriptor e,
const Vector_3 v23 = gt.construct_vector_3_object()(p2, p3); const Vector_3 v23 = gt.construct_vector_3_object()(p2, p3);
const Vector_3 v30 = gt.construct_vector_3_object()(p3, p0); const Vector_3 v30 = gt.construct_vector_3_object()(p3, p0);
const double p1p3 = gt.compute_scalar_product_3_object()( const FT p1p3 = gt.compute_scalar_product_3_object()(
gt.construct_cross_product_vector_3_object()(v12, v23), gt.construct_cross_product_vector_3_object()(v12, v23),
gt.construct_cross_product_vector_3_object()(v30, v01)); gt.construct_cross_product_vector_3_object()(v30, v01));
const Vector_3 v21 = gt.construct_opposite_vector_3_object()(v12); const Vector_3 v21 = gt.construct_opposite_vector_3_object()(v12);
const Vector_3 v03 = gt.construct_opposite_vector_3_object()(v30); const Vector_3 v03 = gt.construct_opposite_vector_3_object()(v30);
const double p0p2 = gt.compute_scalar_product_3_object()( const FT p0p2 = gt.compute_scalar_product_3_object()(
gt.construct_cross_product_vector_3_object()(v01, v21), gt.construct_cross_product_vector_3_object()(v01, v21),
gt.construct_cross_product_vector_3_object()(v23, v03)); gt.construct_cross_product_vector_3_object()(v23, v03));
@ -1694,37 +1698,23 @@ bool remove_degenerate_faces(const FaceRange& face_range,
// Ignore faces with null edges // Ignore faces with null edges
if(!all_removed) if(!all_removed)
{ {
std::map<edge_descriptor, bool> are_degenerate_edges; typename std::set<face_descriptor>::iterator it = degenerate_face_set.begin();
while(it != degenerate_face_set.end())
for(face_descriptor fd : degenerate_face_set)
{ {
for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, tmesh), tmesh)) bool has_degenerate_edge = false;
for(halfedge_descriptor hd : halfedges_around_face(halfedge(*it, tmesh), tmesh))
{ {
edge_descriptor ed = edge(hd, tmesh); const edge_descriptor ed = edge(hd, tmesh);
std::pair<typename std::map<edge_descriptor, bool>::iterator, bool> is_insert_successful = if(is_degenerate_edge(ed, tmesh, np))
are_degenerate_edges.insert(std::make_pair(ed, false));
bool is_degenerate = false;
if(is_insert_successful.second)
{ {
// did not previously exist in the map, so actually have to check if it is degenerate has_degenerate_edge = true;
if(traits.equal_3_object()(get(vpmap, target(ed, tmesh)), get(vpmap, source(ed, tmesh)))) it = degenerate_face_set.erase(it);
is_degenerate = true; break;
}
is_insert_successful.first->second = is_degenerate;
if(is_degenerate)
{
halfedge_descriptor h = halfedge(ed, tmesh);
if(!is_border(h, tmesh))
degenerate_face_set.erase(face(h, tmesh));
h = opposite(h, tmesh);
if(!is_border(h, tmesh))
degenerate_face_set.erase(face(h, tmesh));
} }
} }
if(!has_degenerate_edge)
++it;
} }
} }

View File

@ -403,7 +403,7 @@ is_needle_triangle_face(typename boost::graph_traits<TriangleMesh>::face_descrip
if(min_sq_length == 0) if(min_sq_length == 0)
return min_h; return min_h;
const FT sq_threshold = threshold * threshold; const FT sq_threshold = square(FT(threshold));
if(max_sq_length / min_sq_length >= sq_threshold) if(max_sq_length / min_sq_length >= sq_threshold)
{ {
CGAL_assertion(min_h != boost::graph_traits<TriangleMesh>::null_halfedge()); CGAL_assertion(min_h != boost::graph_traits<TriangleMesh>::null_halfedge());
@ -482,7 +482,7 @@ is_cap_triangle_face(typename boost::graph_traits<TriangleMesh>::face_descriptor
typedef typename Traits::FT FT; typedef typename Traits::FT FT;
typedef typename Traits::Vector_3 Vector_3; typedef typename Traits::Vector_3 Vector_3;
const FT sq_threshold = threshold * threshold; const FT sq_threshold = square(FT(threshold));
const halfedge_descriptor h0 = halfedge(f, tm); const halfedge_descriptor h0 = halfedge(f, tm);
std::array<FT, 3> sq_lengths; std::array<FT, 3> sq_lengths;

View File

@ -1,6 +1,7 @@
#define CGAL_PMP_DEBUG_SMALL_CC_REMOVAL #define CGAL_PMP_DEBUG_SMALL_CC_REMOVAL
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h> #include <CGAL/Surface_mesh.h>
#include <CGAL/Polyhedron_3.h> #include <CGAL/Polyhedron_3.h>
@ -21,6 +22,7 @@ namespace PMP = CGAL::Polygon_mesh_processing;
namespace CP = CGAL::parameters; namespace CP = CGAL::parameters;
typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK;
typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK;
template <typename K, typename EdgeRange, typename FaceRange, typename Mesh> template <typename K, typename EdgeRange, typename FaceRange, typename Mesh>
void detect_degeneracies(const EdgeRange& edge_range, void detect_degeneracies(const EdgeRange& edge_range,
@ -340,17 +342,21 @@ void test()
typedef CGAL::Surface_mesh<Point_3> Surface_mesh; typedef CGAL::Surface_mesh<Point_3> Surface_mesh;
typedef CGAL::Polyhedron_3<Kernel, CGAL::Polyhedron_items_with_id_3> Polyhedron_with_ID; typedef CGAL::Polyhedron_3<Kernel, CGAL::Polyhedron_items_with_id_3> Polyhedron_with_ID;
std::cout << "EPICK SM TESTS" << std::endl; std::cout << "SM TESTS" << std::endl;
test<Kernel, Surface_mesh>(); test<Kernel, Surface_mesh>();
std::cout << "EPICK POLYHEDRON TESTS" << std::endl; std::cout << "POLYHEDRON TESTS" << std::endl;
test<Kernel, Polyhedron_with_ID>(); test<Kernel, Polyhedron_with_ID>();
} }
int main(int /*argc*/, char** /*argv*/) int main(int /*argc*/, char** /*argv*/)
{ {
std::cout << "EPICK TESTS" << std::endl;
test<EPICK>(); test<EPICK>();
std::cout << "EPECK TESTS" << std::endl;
test<EPECK>();
std::cout << "Done" << std::endl; std::cout << "Done" << std::endl;
return EXIT_SUCCESS; return EXIT_SUCCESS;