SPE-2298: Add detection of Voronoi diagram with parabolic edge without a focus point.

Cherry-picked from prusa3d/PrusaSlicer@c44ffed475

Co-authored-by: Lukáš Hejl <hejl.lukas@gmail.com>
This commit is contained in:
Noisyfox 2024-12-22 17:01:54 +08:00
parent 44e53c90f0
commit 4b739539a4
2 changed files with 19 additions and 7 deletions

View file

@ -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;
}
@ -220,16 +224,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<typename SegmentIterator>

View file

@ -44,7 +44,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 {
@ -158,7 +159,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;