From ef5c94f90adec4f77ec56e3dd5f32b564dde8bc7 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Fri, 6 Aug 2021 15:11:20 +0200 Subject: [PATCH] Fix: prevent degeneration of model during simplification --- src/libslic3r/QuadricEdgeCollapse.cpp | 27 ++++++++++- tests/data/simplification.obj | 46 +++++++++++++++++++ tests/libslic3r/test_indexed_triangle_set.cpp | 12 ++++- 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 tests/data/simplification.obj diff --git a/src/libslic3r/QuadricEdgeCollapse.cpp b/src/libslic3r/QuadricEdgeCollapse.cpp index e42ed5deb..ffe1e5ca7 100644 --- a/src/libslic3r/QuadricEdgeCollapse.cpp +++ b/src/libslic3r/QuadricEdgeCollapse.cpp @@ -77,7 +77,8 @@ namespace QuadricEdgeCollapse { uint32_t ti, const EdgeInfos& e_infos, const Indices& indices); bool is_flipped(const Vec3f &new_vertex, uint32_t ti0, uint32_t ti1, const VertexInfo& v_info, const TriangleInfos &t_infos, const EdgeInfos &e_infos, const indexed_triangle_set &its); - + bool degenerate(uint32_t vi, uint32_t ti0, uint32_t ti1, const VertexInfo &v_info, + const EdgeInfos &e_infos, const Indices &indices); // find edge with smallest error in triangle Vec3d calculate_3errors(const Triangle &t, const Vertices &vertices, const VertexInfos &v_infos); Error calculate_error(uint32_t ti, const Triangle& t,const Vertices &vertices, const VertexInfos& v_infos, unsigned char& min_index); @@ -179,6 +180,8 @@ void Slic3r::its_quadric_edge_collapse( find_triangle_index1(vi1, v_info0, ti0, e_infos, its.indices) : find_triangle_index1(vi0, v_info1, ti0, e_infos, its.indices) ; if (!ti1_opt.has_value() || // edge has only one triangle + degenerate(vi0, ti0, *ti1_opt, v_info1, e_infos, its.indices) || + degenerate(vi1, ti0, *ti1_opt, v_info0, e_infos, its.indices) || is_flipped(new_vertex0, ti0, *ti1_opt, v_info0, t_infos, e_infos, its) || is_flipped(new_vertex0, ti0, *ti1_opt, v_info1, t_infos, e_infos, its)) { // try other triangle's edge @@ -487,6 +490,28 @@ bool QuadricEdgeCollapse::is_flipped(const Vec3f & new_vertex, return false; } +bool QuadricEdgeCollapse::degenerate(uint32_t vi, + uint32_t ti0, + uint32_t ti1, + const VertexInfo &v_info, + const EdgeInfos & e_infos, + const Indices & indices) +{ + // check surround triangle do not contain vertex index + // protect from creation of triangle with two same vertices inside + size_t v_info_end = v_info.start + v_info.count; + for (size_t ei = v_info.start; ei < v_info_end; ++ei) { + assert(ei < e_infos.size()); + const EdgeInfo &e_info = e_infos[ei]; + if (e_info.t_index == ti0) continue; // ti0 will be deleted + if (e_info.t_index == ti1) continue; // ti1 will be deleted + const Triangle &t = indices[e_info.t_index]; + for (size_t i = 0; i < 3; ++i) + if (t[i] == vi) return true; + } + return false; +} + Vec3d QuadricEdgeCollapse::calculate_3errors(const Triangle & t, const Vertices & vertices, const VertexInfos &v_infos) diff --git a/tests/data/simplification.obj b/tests/data/simplification.obj new file mode 100644 index 000000000..f509e695c --- /dev/null +++ b/tests/data/simplification.obj @@ -0,0 +1,46 @@ +v 39.349007 -54.069000 -199.819000 +v 39.489006 -54.029007 -199.815002 +v 39.419006 -53.993011 -199.769012 +v 39.629005 -53.975006 -199.815002 +v 39.639008 -53.947006 -199.805023 +v 39.651001 -53.919006 -199.795013 +v 39.807007 -53.863007 -199.796997 +v 39.729004 -53.891006 -199.796997 +v 39.727005 -53.935013 -199.813019 +v 39.767006 -53.899002 -199.805023 +v 39.871002 -53.835007 -199.801025 +v 39.443001 -53.829010 -199.878998 +v 39.523003 -53.965012 -199.827026 +v 39.807007 -53.863007 -199.796997 +v 39.833008 -53.723007 -199.723022 +v 39.759003 -53.822998 -199.822998 +v 39.867004 -53.845001 -199.805023 +v 39.937004 -53.805008 -199.805023 +f 1 2 3 +f 4 5 2 +f 2 6 3 +f 7 8 4 +f 9 10 4 +f 10 9 11 +f 12 2 1 +f 13 6 4 +f 13 4 2 +f 8 7 9 +f 6 9 4 +f 6 14 15 +f 16 14 6 +f 17 18 9 +f 3 6 15 +f 12 16 6 +f 12 6 13 +f 12 13 2 +f 5 4 8 +f 6 8 9 +f 5 6 2 +f 6 5 8 +f 17 9 7 +f 7 11 17 +f 18 11 9 +f 11 18 17 +f 10 7 4 +f 7 10 11 diff --git a/tests/libslic3r/test_indexed_triangle_set.cpp b/tests/libslic3r/test_indexed_triangle_set.cpp index b640d8410..0e08749bf 100644 --- a/tests/libslic3r/test_indexed_triangle_set.cpp +++ b/tests/libslic3r/test_indexed_triangle_set.cpp @@ -246,4 +246,14 @@ TEST_CASE("Simplify mesh by Quadric edge collapse to 5%", "[its]") CHECK(fabs(original_volume - volume) < 33.); float avg_distance = compare(mesh.its, its, 10); CHECK(avg_distance < 0.022f); // 0.02022 | 0.0199614074 -} \ No newline at end of file +} + +TEST_CASE("Simplify trouble case", "[its]") +{ + TriangleMesh tm = load_model("simplification.obj"); + REQUIRE_FALSE(tm.empty()); + float max_error = std::numeric_limits::max(); + uint32_t wanted_count = 8; + its_quadric_edge_collapse(tm.its, wanted_count, &max_error); + CHECK(tm.its.indices.size() <= 8); +}