diff options
author | Lukáš Hejl <hejl.lukas@gmail.com> | 2022-08-29 16:58:57 +0300 |
---|---|---|
committer | supermerill <merill@free.fr> | 2022-09-13 21:39:03 +0300 |
commit | d81e39185acb8f66ae4ab546a1d46625cb96eb09 (patch) | |
tree | 193248bcb0c2706679e61282203c0564afe28a48 | |
parent | 0f0b4d1c200cff25c751c91ba33e897c71c65eaa (diff) |
Fix of #8724, #8747, and #8753: Crash when Voronoi vertexes of a finite edge have some coordinate NaN or infinite.
-rw-r--r-- | src/libslic3r/Arachne/SkeletalTrapezoidation.cpp | 18 | ||||
-rw-r--r-- | src/libslic3r/Arachne/utils/VoronoiUtils.cpp | 1 | ||||
-rw-r--r-- | src/libslic3r/Arachne/utils/VoronoiUtils.hpp | 5 | ||||
-rw-r--r-- | src/libslic3r/Geometry/VoronoiUtilsCgal.cpp | 7 |
4 files changed, 28 insertions, 3 deletions
diff --git a/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp b/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp index 7bd37df11..e9afa0305 100644 --- a/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp +++ b/src/libslic3r/Arachne/SkeletalTrapezoidation.cpp @@ -451,8 +451,23 @@ SkeletalTrapezoidation::SkeletalTrapezoidation(const Polygons& polys, const Bead constructFromPolygons(polys); } +static bool has_finite_edge_with_non_finite_vertex(const Geometry::VoronoiDiagram &voronoi_diagram) +{ + for (const VoronoiUtils::vd_t::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 false; +} static bool detect_missing_voronoi_vertex(const Geometry::VoronoiDiagram &voronoi_diagram, const std::vector<SkeletalTrapezoidation::Segment> &segments) { + if (has_finite_edge_with_non_finite_vertex(voronoi_diagram)) + return true; + for (VoronoiUtils::vd_t::cell_type cell : voronoi_diagram.cells()) { if (!cell.incident_edge()) continue; // There is no spoon @@ -471,7 +486,8 @@ static bool detect_missing_voronoi_vertex(const Geometry::VoronoiDiagram &vorono VoronoiUtils::vd_t::edge_type *ending_vd_edge = nullptr; VoronoiUtils::vd_t::edge_type *edge = cell.incident_edge(); do { - if (edge->is_infinite()) continue; + if (edge->is_infinite() || edge->vertex0() == nullptr || edge->vertex1() == nullptr || !VoronoiUtils::is_finite(*edge->vertex0()) || !VoronoiUtils::is_finite(*edge->vertex1())) + continue; Vec2i64 v0 = VoronoiUtils::p(edge->vertex0()); Vec2i64 v1 = VoronoiUtils::p(edge->vertex1()); diff --git a/src/libslic3r/Arachne/utils/VoronoiUtils.cpp b/src/libslic3r/Arachne/utils/VoronoiUtils.cpp index 3da556b47..82bd79523 100644 --- a/src/libslic3r/Arachne/utils/VoronoiUtils.cpp +++ b/src/libslic3r/Arachne/utils/VoronoiUtils.cpp @@ -15,6 +15,7 @@ Vec2i64 VoronoiUtils::p(const vd_t::vertex_type *node) { const double x = node->x(); const double y = node->y(); + assert(std::isfinite(x) && std::isfinite(y)); assert(x <= double(std::numeric_limits<int64_t>::max()) && x >= std::numeric_limits<int64_t>::lowest()); assert(y <= double(std::numeric_limits<int64_t>::max()) && y >= std::numeric_limits<int64_t>::lowest()); return {int64_t(x + 0.5 - (x < 0)), int64_t(y + 0.5 - (y < 0))}; // Round to the nearest integer coordinates. diff --git a/src/libslic3r/Arachne/utils/VoronoiUtils.hpp b/src/libslic3r/Arachne/utils/VoronoiUtils.hpp index e736f98bc..aa4693643 100644 --- a/src/libslic3r/Arachne/utils/VoronoiUtils.hpp +++ b/src/libslic3r/Arachne/utils/VoronoiUtils.hpp @@ -35,6 +35,11 @@ public: * The \p approximate_step_size is measured parallel to the \p source_segment, not along the parabola. */ static std::vector<Point> discretizeParabola(const Point &source_point, const Segment &source_segment, Point start, Point end, coord_t approximate_step_size, float transitioning_angle); + + static inline bool is_finite(const VoronoiUtils::vd_t::vertex_type &vertex) + { + return std::isfinite(vertex.x()) && std::isfinite(vertex.y()); + } }; } // namespace Slic3r::Arachne diff --git a/src/libslic3r/Geometry/VoronoiUtilsCgal.cpp b/src/libslic3r/Geometry/VoronoiUtilsCgal.cpp index caaf1ee9c..062a3b397 100644 --- a/src/libslic3r/Geometry/VoronoiUtilsCgal.cpp +++ b/src/libslic3r/Geometry/VoronoiUtilsCgal.cpp @@ -3,6 +3,7 @@ #include <CGAL/Surface_sweep_2_algorithms.h> #include "libslic3r/Geometry/Voronoi.hpp" +#include "libslic3r/Arachne/utils/VoronoiUtils.hpp" #include "VoronoiUtilsCgal.hpp" @@ -28,7 +29,8 @@ bool VoronoiUtilsCgal::is_voronoi_diagram_planar_intersection(const VD &voronoi_ if (edge.color() != 0) continue; - if (edge.is_finite() && edge.is_linear()) { + if (edge.is_finite() && edge.is_linear() && edge.vertex0() != nullptr && edge.vertex1() != nullptr && + Arachne::VoronoiUtils::is_finite(*edge.vertex0()) && Arachne::VoronoiUtils::is_finite(*edge.vertex1())) { segments.emplace_back(to_cgal_point(*edge.vertex0()), to_cgal_point(*edge.vertex1())); edge.color(1); assert(edge.twin() != nullptr); @@ -73,7 +75,8 @@ bool VoronoiUtilsCgal::is_voronoi_diagram_planar_angle(const VoronoiDiagram &vor do { // FIXME Lukas H.: Also process parabolic segments. - if (edge->is_finite() && edge->is_linear()) + if (edge->is_finite() && edge->is_linear() && edge->vertex0() != nullptr && edge->vertex1() != nullptr && + Arachne::VoronoiUtils::is_finite(*edge->vertex0()) && Arachne::VoronoiUtils::is_finite(*edge->vertex1())) edges.emplace_back(edge); edge = edge->rot_next(); |