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
std::vector<bool> cc_closeness(num, true);
std::vector<FT> component_volumes(num);
std::vector<FT> component_volumes(num, FT(0));
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>
boost::optional<double> get_collapse_volume(typename boost::graph_traits<TriangleMesh>::halfedge_descriptor h,
const TriangleMesh& tmesh,
const VPM& vpm,
const Traits& gt)
boost::optional<typename Traits::FT>
get_collapse_volume(typename boost::graph_traits<TriangleMesh>::halfedge_descriptor h,
const TriangleMesh& tmesh,
const VPM& vpm,
const Traits& gt)
{
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 Traits::Vector_3 Vector_3;
@ -204,8 +206,8 @@ boost::optional<double> get_collapse_volume(typename boost::graph_traits<Triangl
Point_ref removed= get(vpm, target(h, tmesh));
// init volume with incident triangles (reversed orientation
double 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);
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);
// consider triangles incident to the vertex removed
halfedge_descriptor stop = prev(opposite(h, tmesh), tmesh);
@ -248,13 +250,14 @@ get_best_edge_orientation(typename boost::graph_traits<TriangleMesh>::edge_descr
const Traits& gt)
{
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);
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<double> dv2 = get_collapse_volume(ho, tmesh, vpm, gt);
boost::optional<FT> dv1 = get_collapse_volume(h, 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
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 Traits::FT FT;
typedef typename boost::property_traits<VPM>::reference Point_ref;
typedef typename Traits::Vector_3 Vector_3;
@ -318,16 +322,16 @@ 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 v30 = gt.construct_vector_3_object()(p3, p0);
const double p1p3 = gt.compute_scalar_product_3_object()(
gt.construct_cross_product_vector_3_object()(v12, v23),
gt.construct_cross_product_vector_3_object()(v30, v01));
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()(v30, v01));
const Vector_3 v21 = gt.construct_opposite_vector_3_object()(v12);
const Vector_3 v03 = gt.construct_opposite_vector_3_object()(v30);
const double p0p2 = gt.compute_scalar_product_3_object()(
gt.construct_cross_product_vector_3_object()(v01, v21),
gt.construct_cross_product_vector_3_object()(v23, v03));
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()(v23, v03));
return p0p2 <= p1p3;
}
@ -1694,37 +1698,23 @@ bool remove_degenerate_faces(const FaceRange& face_range,
// Ignore faces with null edges
if(!all_removed)
{
std::map<edge_descriptor, bool> are_degenerate_edges;
for(face_descriptor fd : degenerate_face_set)
typename std::set<face_descriptor>::iterator it = degenerate_face_set.begin();
while(it != degenerate_face_set.end())
{
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);
std::pair<typename std::map<edge_descriptor, bool>::iterator, bool> is_insert_successful =
are_degenerate_edges.insert(std::make_pair(ed, false));
bool is_degenerate = false;
if(is_insert_successful.second)
const edge_descriptor ed = edge(hd, tmesh);
if(is_degenerate_edge(ed, tmesh, np))
{
// did not previously exist in the map, so actually have to check if it is degenerate
if(traits.equal_3_object()(get(vpmap, target(ed, tmesh)), get(vpmap, source(ed, tmesh))))
is_degenerate = true;
}
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));
has_degenerate_edge = true;
it = degenerate_face_set.erase(it);
break;
}
}
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)
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)
{
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::Vector_3 Vector_3;
const FT sq_threshold = threshold * threshold;
const FT sq_threshold = square(FT(threshold));
const halfedge_descriptor h0 = halfedge(f, tm);
std::array<FT, 3> sq_lengths;

View File

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