Fixed an issue when the Lightning infill stuck in an infinite loop on some models.
Cased by two sampled points closer than chosen spacing.
This commit is contained in:
parent
3fba411d17
commit
bd4b63e67d
@ -3043,14 +3043,18 @@ Polylines FillSupportBase::fill_surface(const Surface *surface, const FillParams
|
|||||||
return polylines_out;
|
return polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing)
|
// Lightning infill assumes that the distance between any two sampled points is always
|
||||||
|
// at least equal to the value of spacing. To meet this assumption, we need to use
|
||||||
|
// BoundingBox for whole layers instead of bounding box just around processing ExPolygon.
|
||||||
|
// Using just BoundingBox around processing ExPolygon could produce two points closer
|
||||||
|
// than spacing (in cases where two ExPolygon are closer than spacing).
|
||||||
|
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing, const BoundingBox &global_bounding_box)
|
||||||
{
|
{
|
||||||
ExPolygonWithOffset poly_with_offset(expolygon, 0, 0, 0);
|
ExPolygonWithOffset poly_with_offset(expolygon, 0, 0, 0);
|
||||||
BoundingBox bounding_box = poly_with_offset.bounding_box_src();
|
|
||||||
std::vector<SegmentedIntersectionLine> segs = slice_region_by_vertical_lines(
|
std::vector<SegmentedIntersectionLine> segs = slice_region_by_vertical_lines(
|
||||||
poly_with_offset,
|
poly_with_offset,
|
||||||
(bounding_box.max.x() - bounding_box.min.x() + spacing - 1) / spacing,
|
(global_bounding_box.max.x() - global_bounding_box.min.x() + spacing - 1) / spacing,
|
||||||
bounding_box.min.x(),
|
global_bounding_box.min.x(),
|
||||||
spacing);
|
spacing);
|
||||||
|
|
||||||
Points out;
|
Points out;
|
||||||
@ -3066,17 +3070,17 @@ Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Points sample_grid_pattern(const ExPolygons &expolygons, coord_t spacing)
|
Points sample_grid_pattern(const ExPolygons &expolygons, coord_t spacing, const BoundingBox &global_bounding_box)
|
||||||
{
|
{
|
||||||
Points out;
|
Points out;
|
||||||
for (const ExPolygon &expoly : expolygons)
|
for (const ExPolygon &expoly : expolygons)
|
||||||
append(out, sample_grid_pattern(expoly, spacing));
|
append(out, sample_grid_pattern(expoly, spacing, global_bounding_box));
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing)
|
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing, const BoundingBox &global_bounding_box)
|
||||||
{
|
{
|
||||||
return sample_grid_pattern(union_ex(polygons), spacing);
|
return sample_grid_pattern(union_ex(polygons), spacing, global_bounding_box);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -109,9 +109,9 @@ protected:
|
|||||||
float _layer_angle(size_t idx) const override { return 0.f; }
|
float _layer_angle(size_t idx) const override { return 0.f; }
|
||||||
};
|
};
|
||||||
|
|
||||||
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing);
|
Points sample_grid_pattern(const ExPolygon &expolygon, coord_t spacing, const BoundingBox &global_bounding_box);
|
||||||
Points sample_grid_pattern(const ExPolygons &expolygons, coord_t spacing);
|
Points sample_grid_pattern(const ExPolygons &expolygons, coord_t spacing, const BoundingBox &global_bounding_box);
|
||||||
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing);
|
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing, const BoundingBox &global_bounding_box);
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
@ -7,11 +7,34 @@
|
|||||||
|
|
||||||
#include <tbb/parallel_for.h>
|
#include <tbb/parallel_for.h>
|
||||||
|
|
||||||
|
#ifdef LIGHTNING_DISTANCE_FIELD_DEBUG_OUTPUT
|
||||||
|
#include "../../SVG.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Slic3r::FillLightning
|
namespace Slic3r::FillLightning
|
||||||
{
|
{
|
||||||
|
|
||||||
constexpr coord_t radius_per_cell_size = 6; // The cell-size should be small compared to the radius, but not so small as to be inefficient.
|
constexpr coord_t radius_per_cell_size = 6; // The cell-size should be small compared to the radius, but not so small as to be inefficient.
|
||||||
|
|
||||||
|
#ifdef LIGHTNING_DISTANCE_FIELD_DEBUG_OUTPUT
|
||||||
|
void export_distance_field_to_svg(const std::string &path, const Polygons &outline, const Polygons &overhang, const std::list<DistanceField::UnsupportedCell> &unsupported_points, const Points &points = {})
|
||||||
|
{
|
||||||
|
coordf_t stroke_width = scaled<coordf_t>(0.01);
|
||||||
|
BoundingBox bbox = get_extents(outline);
|
||||||
|
|
||||||
|
bbox.offset(SCALED_EPSILON);
|
||||||
|
SVG svg(path, bbox);
|
||||||
|
svg.draw_outline(outline, "green", stroke_width);
|
||||||
|
svg.draw_outline(overhang, "blue", stroke_width);
|
||||||
|
|
||||||
|
for (const DistanceField::UnsupportedCell &cell : unsupported_points)
|
||||||
|
svg.draw(cell.loc, "cyan", coord_t(stroke_width));
|
||||||
|
|
||||||
|
for (const Point &pt : points)
|
||||||
|
svg.draw(pt, "red", coord_t(stroke_width));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outline, const BoundingBox& current_outlines_bbox, const Polygons& current_overhang) :
|
DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outline, const BoundingBox& current_outlines_bbox, const Polygons& current_overhang) :
|
||||||
m_cell_size(radius / radius_per_cell_size),
|
m_cell_size(radius / radius_per_cell_size),
|
||||||
m_supporting_radius(radius),
|
m_supporting_radius(radius),
|
||||||
@ -19,8 +42,9 @@ DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outl
|
|||||||
{
|
{
|
||||||
m_supporting_radius2 = Slic3r::sqr(int64_t(radius));
|
m_supporting_radius2 = Slic3r::sqr(int64_t(radius));
|
||||||
// Sample source polygons with a regular grid sampling pattern.
|
// Sample source polygons with a regular grid sampling pattern.
|
||||||
|
const BoundingBox overhang_bbox = get_extents(current_overhang);
|
||||||
for (const ExPolygon &expoly : union_ex(current_overhang)) {
|
for (const ExPolygon &expoly : union_ex(current_overhang)) {
|
||||||
const Points sampled_points = sample_grid_pattern(expoly, m_cell_size);
|
const Points sampled_points = sample_grid_pattern(expoly, m_cell_size, overhang_bbox);
|
||||||
const size_t unsupported_points_prev_size = m_unsupported_points.size();
|
const size_t unsupported_points_prev_size = m_unsupported_points.size();
|
||||||
m_unsupported_points.resize(unsupported_points_prev_size + sampled_points.size());
|
m_unsupported_points.resize(unsupported_points_prev_size + sampled_points.size());
|
||||||
|
|
||||||
@ -59,6 +83,13 @@ DistanceField::DistanceField(const coord_t& radius, const Polygons& current_outl
|
|||||||
// Because the distance between two points is at least one axis equal to m_cell_size, every cell
|
// Because the distance between two points is at least one axis equal to m_cell_size, every cell
|
||||||
// in m_unsupported_points_grid contains exactly one point.
|
// in m_unsupported_points_grid contains exactly one point.
|
||||||
assert(m_unsupported_points.size() == m_unsupported_points_grid.size());
|
assert(m_unsupported_points.size() == m_unsupported_points_grid.size());
|
||||||
|
|
||||||
|
#ifdef LIGHTNING_DISTANCE_FIELD_DEBUG_OUTPUT
|
||||||
|
{
|
||||||
|
static int iRun = 0;
|
||||||
|
export_distance_field_to_svg(debug_out_path("FillLightning-DistanceField-%d.svg", iRun++), current_outline, current_overhang, m_unsupported_points);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void DistanceField::update(const Point& to_node, const Point& added_leaf)
|
void DistanceField::update(const Point& to_node, const Point& added_leaf)
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "../../Point.hpp"
|
#include "../../Point.hpp"
|
||||||
#include "../../Polygon.hpp"
|
#include "../../Polygon.hpp"
|
||||||
|
|
||||||
|
//#define LIGHTNING_DISTANCE_FIELD_DEBUG_OUTPUT
|
||||||
|
|
||||||
namespace Slic3r::FillLightning
|
namespace Slic3r::FillLightning
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -196,6 +198,10 @@ protected:
|
|||||||
Point from_grid_point(const Point &point) const {
|
Point from_grid_point(const Point &point) const {
|
||||||
return point * m_cell_size + m_unsupported_points_bbox.min;
|
return point * m_cell_size + m_unsupported_points_bbox.min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LIGHTNING_DISTANCE_FIELD_DEBUG_OUTPUT
|
||||||
|
friend void export_distance_field_to_svg(const std::string &path, const Polygons &outline, const Polygons &overhang, const std::list<DistanceField::UnsupportedCell> &unsupported_points, const Points &points);
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Slic3r::FillLightning
|
} // namespace Slic3r::FillLightning
|
||||||
|
Loading…
Reference in New Issue
Block a user