Skip to content

Commit

Permalink
Fix of prusa3d#8724, prusa3d#8747, and prusa3d#8753: Crash when Voron…
Browse files Browse the repository at this point in the history
…oi vertexes of a finite edge have some coordinate NaN or infinite.
  • Loading branch information
hejllukas authored and supermerill committed Sep 13, 2022
1 parent 0f0b4d1 commit d81e391
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 3 deletions.
18 changes: 17 additions & 1 deletion src/libslic3r/Arachne/SkeletalTrapezoidation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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());
Expand Down
1 change: 1 addition & 0 deletions src/libslic3r/Arachne/utils/VoronoiUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions src/libslic3r/Arachne/utils/VoronoiUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ class VoronoiUtils
* 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
Expand Down
7 changes: 5 additions & 2 deletions src/libslic3r/Geometry/VoronoiUtilsCgal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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);
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit d81e391

Please sign in to comment.