mirror of https://github.com/CGAL/cgal
Merge pull request #5012 from MaelRL/PMP-Repair_degeneracies_fixes-5.1-GF
PMP: Degeneracy removal fixes
This commit is contained in:
commit
40338b2a23
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue