Browse Source

SPE-1729: Try to compute the Voronoi diagram again on modified ExPolygon when an invalid Voronoi diagram is produced during the calculation of the medial axis.

There are several ExPolygons with very thin lines and holes formed by very close (1-5nm) vertices that are on the edge of our resolution. Those thin lines and holes are both unprintable and cause the Voronoi diagram to be invalid.
So, we filtered out such thin lines and holes and tried to compute the Voronoi diagram again.
Lukáš Hejl 1 year ago
parent
commit
8784ca0ecf
2 changed files with 72 additions and 0 deletions
  1. 16 0
      src/libslic3r/Geometry/MedialAxis.cpp
  2. 56 0
      tests/libslic3r/test_voronoi.cpp

+ 16 - 0
src/libslic3r/Geometry/MedialAxis.cpp

@@ -6,6 +6,9 @@
 
 #include "clipper.hpp"
 #include "VoronoiOffset.hpp"
+#include "ClipperUtils.hpp"
+
+#include <boost/log/trivial.hpp>
 
 #ifdef SLIC3R_DEBUG
 namespace boost { namespace polygon {
@@ -468,6 +471,19 @@ void MedialAxis::build(ThickPolylines* polylines)
     }
 #endif // NDEBUG
     m_vd.construct_voronoi(m_lines.begin(), m_lines.end());
+
+    // For several ExPolygons in SPE-1729, an invalid Voronoi diagram was produced that wasn't fixable by rotating input data.
+    // Those ExPolygons contain very thin lines and holes formed by very close (1-5nm) vertices that are on the edge of our resolution.
+    // Those thin lines and holes are both unprintable and cause the Voronoi diagram to be invalid.
+    // So we filter out such thin lines and holes and try to compute the Voronoi diagram again.
+    if (!m_vd.is_valid()) {
+        m_lines = to_lines(closing_ex({m_expolygon}, float(2. * SCALED_EPSILON)));
+        m_vd.construct_voronoi(m_lines.begin(), m_lines.end());
+
+        if (!m_vd.is_valid())
+            BOOST_LOG_TRIVIAL(error) << "MedialAxis - Invalid Voronoi diagram even after morphological closing.";
+    }
+
     Slic3r::Voronoi::annotate_inside_outside(m_vd, m_lines);
 //    static constexpr double threshold_alpha = M_PI / 12.; // 30 degrees
 //    std::vector<Vec2d> skeleton_edges = Slic3r::Voronoi::skeleton_edges_rough(vd, lines, threshold_alpha);

+ 56 - 0
tests/libslic3r/test_voronoi.cpp

@@ -2233,3 +2233,59 @@ TEST_CASE("Non-planar voronoi diagram", "[VoronoiNonPlanar]")
 
 //    REQUIRE(Geometry::VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(vd));
 }
+
+// This case is extracted from SPE-1729, where several ExPolygon with very thin lines
+// and holes formed by very close (1-5nm) vertices that are on the edge of our resolution.
+// Those thin lines and holes are both unprintable and cause the Voronoi diagram to be invalid.
+TEST_CASE("Invalid Voronoi diagram - Thin lines - SPE-1729", "[InvalidVoronoiDiagramThinLinesSPE1729]")
+{
+    Polygon contour = {
+        {32247689, -2405501},
+        {32247733, -2308514},
+        {32247692, -2405496},
+        {50484384,   332941},
+        {50374839,  1052546},
+        {32938040, -1637993},
+        {32938024, -1673788},
+        {32942107,  7220481},
+        {32252205,  7447599},
+        {32252476,  8037808},
+        {32555965,  8277599},
+        {17729260,  8904718},
+        {17729236,  8853233},
+        {17729259,  8904722},
+        {17039259,  8935481},
+        {17033440, -3880421},
+        {17204385, -3852156},
+        {17723645, -3441873},
+        {17723762, -3187210},
+        {17728957,  8240730},
+        {17728945,  8213866},
+        {31716233,  7614090},
+        {20801623, -1009882},
+        {21253963, -1580792},
+        {32252082,  7157187},
+        {32248022, -1673787},
+        {24245653, -2925506},
+        {18449246, -3809095},
+        {18728385, -4449246}
+    };
+
+    Polygon hole = {
+        {32247789, -2181284},
+        {32247870, -2003865},
+        {32247872, -2003866},
+        {32247752, -2267007}
+    };
+
+    Polygons polygons = {contour, hole};
+
+    VD    vd;
+    Lines lines = to_lines(polygons);
+    vd.construct_voronoi(lines.begin(), lines.end());
+#ifdef VORONOI_DEBUG_OUT
+    dump_voronoi_to_svg(debug_out_path("invalid-voronoi-diagram-thin-lines.svg").c_str(), vd, Points(), lines);
+#endif
+
+//    REQUIRE(vd.is_valid());
+}