From c44ffed475f55f5203142c20005568b497e6362d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Fri, 17 May 2024 15:15:34 +0200 Subject: [PATCH] SPE-2298: Add detection of Voronoi diagram with parabolic edge without a focus point. --- src/libslic3r/Geometry/Voronoi.cpp | 18 ++++++--- src/libslic3r/Geometry/Voronoi.hpp | 8 +++- tests/libslic3r/test_voronoi.cpp | 65 ++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 7 deletions(-) diff --git a/src/libslic3r/Geometry/Voronoi.cpp b/src/libslic3r/Geometry/Voronoi.cpp index 947c56a707..71c67b9cc1 100644 --- a/src/libslic3r/Geometry/Voronoi.cpp +++ b/src/libslic3r/Geometry/Voronoi.cpp @@ -35,6 +35,8 @@ VoronoiDiagram::construct_voronoi(const SegmentIterator segment_begin, const Seg BOOST_LOG_TRIVIAL(warning) << "Detected Voronoi edge intersecting input segment, input polygons will be rotated back and forth."; } else if (m_issue_type == IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX) { BOOST_LOG_TRIVIAL(warning) << "Detected finite Voronoi vertex with non finite vertex, input polygons will be rotated back and forth."; + } else if (m_issue_type == IssueType::PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT) { + BOOST_LOG_TRIVIAL(warning) << "Detected parabolic Voronoi edges without focus point, input polygons will be rotated back and forth."; } else { BOOST_LOG_TRIVIAL(error) << "Detected unknown Voronoi diagram issue, input polygons will be rotated back and forth."; } @@ -48,6 +50,8 @@ VoronoiDiagram::construct_voronoi(const SegmentIterator segment_begin, const Seg BOOST_LOG_TRIVIAL(error) << "Detected Voronoi edge intersecting input segment even after the rotation of input."; } else if (m_issue_type == IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX) { BOOST_LOG_TRIVIAL(error) << "Detected finite Voronoi vertex with non finite vertex even after the rotation of input."; + } else if (m_issue_type == IssueType::PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT) { + BOOST_LOG_TRIVIAL(error) << "Detected parabolic Voronoi edges without focus point even after the rotation of input."; } else { BOOST_LOG_TRIVIAL(error) << "Detected unknown Voronoi diagram issue even after the rotation of input."; } @@ -159,8 +163,8 @@ typename boost::polygon::enable_if< VoronoiDiagram::IssueType>::type VoronoiDiagram::detect_known_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end) { - if (has_finite_edge_with_non_finite_vertex(voronoi_diagram)) { - return IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX; + if (const IssueType edge_issue_type = detect_known_voronoi_edge_issues(voronoi_diagram); edge_issue_type != IssueType::NO_ISSUE_DETECTED) { + return edge_issue_type; } else if (const IssueType cell_issue_type = detect_known_voronoi_cell_issues(voronoi_diagram, segment_begin, segment_end); cell_issue_type != IssueType::NO_ISSUE_DETECTED) { return cell_issue_type; } else if (!VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(voronoi_diagram, segment_begin, segment_end)) { @@ -218,16 +222,20 @@ VoronoiDiagram::detect_known_voronoi_cell_issues(const VoronoiDiagram &voronoi_d return IssueType::NO_ISSUE_DETECTED; } -bool VoronoiDiagram::has_finite_edge_with_non_finite_vertex(const VoronoiDiagram &voronoi_diagram) +VoronoiDiagram::IssueType VoronoiDiagram::detect_known_voronoi_edge_issues(const VoronoiDiagram &voronoi_diagram) { for (const voronoi_diagram_type::edge_type &edge : voronoi_diagram.edges()) { if (edge.is_finite()) { assert(edge.vertex0() != nullptr && edge.vertex1() != nullptr); if (edge.vertex0() == nullptr || edge.vertex1() == nullptr || !VoronoiUtils::is_finite(*edge.vertex0()) || !VoronoiUtils::is_finite(*edge.vertex1())) - return true; + return IssueType::FINITE_EDGE_WITH_NON_FINITE_VERTEX; + + if (edge.is_curved() && !edge.cell()->contains_point() && !edge.twin()->cell()->contains_point()) + return IssueType::PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT; } } - return false; + + return IssueType::NO_ISSUE_DETECTED; } template diff --git a/src/libslic3r/Geometry/Voronoi.hpp b/src/libslic3r/Geometry/Voronoi.hpp index 1c5d68acd0..72fa387e18 100644 --- a/src/libslic3r/Geometry/Voronoi.hpp +++ b/src/libslic3r/Geometry/Voronoi.hpp @@ -48,7 +48,8 @@ public: MISSING_VORONOI_VERTEX, NON_PLANAR_VORONOI_DIAGRAM, VORONOI_EDGE_INTERSECTING_INPUT_SEGMENT, - UNKNOWN // Repairs are disabled in the constructor. + PARABOLIC_VORONOI_EDGE_WITHOUT_FOCUS_POINT, + UNKNOWN // Repairs are disabled in the constructor. }; enum class State { @@ -162,7 +163,10 @@ private: IssueType>::type detect_known_voronoi_cell_issues(const VoronoiDiagram &voronoi_diagram, SegmentIterator segment_begin, SegmentIterator segment_end); - static bool has_finite_edge_with_non_finite_vertex(const VoronoiDiagram &voronoi_diagram); + // Detect issues related to Voronoi edges, or that can be detected by iterating over Voronoi edges. + // The first type of issue that can be detected is a finite Voronoi edge with a non-finite vertex. + // The second type of issue that can be detected is a parabolic Voronoi edge without a focus point (produced by two segments). + static IssueType detect_known_voronoi_edge_issues(const VoronoiDiagram &voronoi_diagram); voronoi_diagram_type m_voronoi_diagram; vertex_container_type m_vertices; diff --git a/tests/libslic3r/test_voronoi.cpp b/tests/libslic3r/test_voronoi.cpp index 71ef1588e7..f415dc74c0 100644 --- a/tests/libslic3r/test_voronoi.cpp +++ b/tests/libslic3r/test_voronoi.cpp @@ -2217,3 +2217,68 @@ TEST_CASE("Invalid Voronoi diagram - Thin lines - SPE-1729", "[InvalidVoronoiDia // REQUIRE(vd.is_valid()); } + +TEST_CASE("Voronoi cell doesn't contain a source point - SPE-2298", "[VoronoiCellSourcePointSPE2298]") +{ + Polygon polygon = { + { 9854534, -39739718}, {- 4154002, -34864557}, {-13073118, -31802214}, + {-21265508, -29026626}, {-31388055, -25645073}, {-32409943, -25279942}, + {-33418087, -24864987}, {-34400568, -24404312}, {-35354754, -23899358}, + {-36278795, -23351325}, {-37170015, -22762146}, {-38025776, -22134628}, + {-38845825, -21468175}, {-39627905, -20764801}, {-40370549, -20026061}, + {-41072075, -19253859}, {-41731000, -18450032}, {-42345940, -17616466}, + {-42915530, -16755283}, {-43438684, -15868338}, {-43914245, -14957822}, + {-44341235, -14025879}, {-44718686, -13074712}, {-45045890, -12106566}, + {-45322386, -11123499}, {-45547674, -10127656}, {-45721021, - 9121581}, + {-45842174, - 8107658}, {-45910990, - 7088089}, {-45927405, - 6065217}, + {-45891432, - 5041288}, {-45803222, - 4018728}, {-45663042, - 2999801}, + {-45471245, - 1986784}, {-45230690, - 991761}, {-38655400, 23513180}, + {-38366034, 24494742}, {-38025334, 25467666}, {-37636844, 26420074}, + {-37200678, 27349843}, {-36718169, 28254419}, {-36191104, 29131704}, + {-35620587, 29979748}, {-35007621, 30796895}, {-34353751, 31580950}, + {-33660293, 32330182}, {-32928806, 33042775}, {-32160862, 33717057}, + {-31358104, 34351432}, {-30522331, 34944323}, {-29655434, 35494277}, + {-28759338, 35999922}, {-27835963, 36460011}, {-26921721, 36858494}, + {-25914008, 37239556}, {-24919466, 37557049}, {-24204878, 37746930}, + {-22880526, 38041931}, {-21833362, 38209050}, {-21449204, 38252031}, + {-20775657, 38324377}, {-19711119, 38387480}, {-18638667, 38398812}, + {-17762260, 38366962}, {-16480321, 38266321}, {-15396213, 38120856}, + {-14327987, 37925343}, {- 5801522, 36175494}, { 7791637, 33457589}, + { 15887399, 31878986}, { 28428609, 29478881}, { 28438392, 29512722}, + { 27850323, 29743358}, { 27058729, 29970066}, { 14135560, 32452875}, + { 6101685, 34019760}, {- 5352362, 36305237}, {-14423391, 38160442}, + {-15528705, 38361745}, {-16625379, 38507834}, {-17721787, 38600631}, + {-18812787, 38641330}, {-19563804, 38633844}, {-20975692, 38563412}, + {-22036069, 38446419}, {-23087710, 38277136}, {-24123993, 38056689}, + {-25141240, 37786307}, {-26138324, 37466465}, {-26851801, 37197652}, + {-28067514, 36680229}, {-28988984, 36219404}, {-29886302, 35711371}, + {-30754551, 35158840}, {-31124518, 34896643}, {-31589528, 34564743}, + {-32392776, 33928220}, {-33161225, 33251721}, {-33454722, 32966117}, + {-33891684, 32538320}, {-34585318, 31787066}, {-35239508, 31000793}, + {-35527715, 30616853}, {-35851756, 30182731}, {-36422833, 29331982}, + {-36950377, 28452000}, {-37265788, 27860633}, {-37432874, 27545549}, + {-37870512, 26612217}, {-38261423, 25655915}, {-38581885, 24744387}, + {-38902507, 23671594}, {-45523689, - 1006672}, {-45770290, - 2026713}, + {-45963584, - 3043930}, {-46104330, - 4066310}, {-46192377, - 5092635}, + {-46228310, - 6120019}, {-46211987, - 7145807}, {-46143426, - 8167812}, + {-46022719, - 9183674}, {-45850055, -10191399}, {-45625772, -11188531}, + {-45350245, -12172975}, {-45023965, -13142600}, {-44647538, -14095222}, + {-44221691, -15028602}, {-43747176, -15940794}, {-43224933, -16829570}, + {-42655872, -17693052}, {-42041183, -18529065}, {-41381752, -19335983}, + {-40677899, -20112975}, {-39932077, -20856972}, {-39145730, -21566171}, + {-38320552, -22238686}, {-37458030, -22872953}, {-36560036, -23467217}, + {-35627745, -24020614}, {-34662272, -24532977}, {-33667551, -25000722}, + {-32645434, -25422669}, {-31588226, -25801077}, {-24380013, -28208306}, + {-24380013, -28208306}, {-13354262, -31942517}, {-13354261, -31942515}, + {-2032305, -35842454}, { 8025116, -39348505}, { 8820397, -39587703}, + { 9636283, -39751794}, { 9847092, -39773278}}; + + VD vd; + Lines lines = to_lines(polygon); + vd.construct_voronoi(lines.begin(), lines.end()); +#ifdef VORONOI_DEBUG_OUT +// dump_voronoi_to_svg(debug_out_path("voronoi-cell-source-point-spe2298.svg").c_str(), vd, Points(), lines); +#endif + + REQUIRE(vd.is_valid()); +}