SPE-2484: Fix "Infill failed" during interlocking generation.

This commit is contained in:
Lukáš Hejl 2025-02-13 10:16:17 +01:00 committed by Lukas Matena
parent 6e5aa4b2e2
commit 3017ea0051
2 changed files with 20 additions and 66 deletions

View File

@ -1,6 +1,8 @@
// Copyright (c) 2022 Ultimaker B.V.
// CuraEngine is released under the terms of the AGPLv3 or higher.
#include <boost/log/trivial.hpp>
#include "VoxelUtils.hpp"
#include "libslic3r/Geometry.hpp"
#include "libslic3r/Fill/FillRectilinear.hpp"
@ -9,9 +11,7 @@
namespace Slic3r
{
DilationKernel::DilationKernel(GridPoint3 kernel_size, DilationKernel::Type type)
: kernel_size_(kernel_size)
, type_(type)
DilationKernel::DilationKernel(GridPoint3 kernel_size, DilationKernel::Type type) : kernel_size_(kernel_size)
{
coord_t mult = kernel_size.x() * kernel_size.y() * kernel_size.z(); // multiplier for division to avoid rounding and to avoid use of floating point numbers
relative_cells_.reserve(mult);
@ -129,61 +129,23 @@ bool VoxelUtils::walkDilatedPolygons(const ExPolygon& polys, coord_t z, const Di
return walkPolygons(translated, z + translation.z(), dilate(kernel, process_cell_func));
}
bool VoxelUtils::walkAreas(const ExPolygon& polys, coord_t z, const std::function<bool(GridPoint3)>& process_cell_func) const
bool VoxelUtils::_walkAreas(const ExPolygon &ex_polygon, coord_t z, const std::function<bool(GridPoint3)> &process_cell_func) const
{
ExPolygon translated = polys;
const Vec3crd translation = -cell_size_ / 2; // offset half a cell so that the dots of spreadDotsArea are centered on the middle of the cell isntead of the lower corners.
if (translation.x() && translation.y())
{
translated.translate(Point(translation.x(), translation.y()));
}
return _walkAreas(translated, z, process_cell_func);
}
static Points spreadDotsArea(const ExPolygon& polygons, Point grid_size)
{
std::unique_ptr<Fill> filler(Fill::new_from_type(ipAlignedRectilinear));
filler->angle = Geometry::deg2rad(90.f);
filler->spacing = unscaled(grid_size.x());
filler->bounding_box = get_extents(polygons);
FillParams params;
params.density = 1.f;
params.anchor_length_max = 0;
Surface surface(stInternal, polygons);
auto polylines = filler->fill_surface(&surface, params);
Points result;
for (const Polyline& line : polylines) {
assert(line.size() == 2);
Point a = line[0];
Point b = line[1];
assert(a.x() == b.x());
if (a.y() > b.y()) {
std::swap(a, b);
}
for (coord_t y = a.y() - (a.y() % grid_size.y()) - grid_size.y(); y < b.y(); y += grid_size.y()) {
if (y < a.y())
continue;
result.emplace_back(a.x(), y);
}
Points grid_points;
try {
const BoundingBox ex_polygon_bbox = get_extents(ex_polygon);
grid_points = sample_grid_pattern(ex_polygon, cell_size_.x(), ex_polygon_bbox);
} catch (InfillFailedException &) {
BOOST_LOG_TRIVIAL(warning) << "Sampling ExPolygon failed.";
}
return result;
}
bool VoxelUtils::_walkAreas(const ExPolygon& polys, coord_t z, const std::function<bool(GridPoint3)>& process_cell_func) const
{
Points skin_points = spreadDotsArea(polys, Point(cell_size_.x(), cell_size_.y()));
for (Point p : skin_points)
{
bool continue_ = process_cell_func(toGridPoint(Vec3crd(p.x() + cell_size_.x() / 2, p.y() + cell_size_.y() / 2, z)));
if (! continue_)
{
const Vec3crd grid_point_offset(cell_size_.x() / 2, cell_size_.y() / 2, z);
for (const Point &grid_point : grid_points) {
if (const bool continue_ = process_cell_func(toGridPoint(grid_point, grid_point_offset)); !continue_) {
return false;
}
}
return true;
}

View File

@ -48,7 +48,6 @@ struct DilationKernel
PRISM
};
GridPoint3 kernel_size_; //!< Size of the kernel in number of voxel cells
Type type_;
std::vector<GridPoint3> relative_cells_; //!< All offset positions relative to some reference cell which is to be dilated
DilationKernel(GridPoint3 kernel_size, Type type);
@ -120,21 +119,9 @@ private:
/*!
* \warning the \p polys is assumed to be translated by half the cell_size in xy already
*/
bool _walkAreas(const ExPolygon& polys, coord_t z, const std::function<bool(GridPoint3)>& process_cell_func) const;
bool _walkAreas(const ExPolygon &ex_polygon, coord_t z, const std::function<bool(GridPoint3)> &process_cell_func) const;
public:
/*!
* Process all voxels inside the area of a polygons object.
*
* \warning The voxels along the area are not processed. Thin areas might not process any voxels at all.
*
* \param polys The area to fill
* \param z The height at which the polygons occur
* \param process_cell_func Function to perform on each voxel cell
* \return Whether executing was stopped short as indicated by the \p cell_processing_function
*/
bool walkAreas(const ExPolygon& polys, coord_t z, const std::function<bool(GridPoint3)>& process_cell_func) const;
/*!
* Process all voxels inside the area of a polygons object.
* For each voxel inside the polygon we process each of the offset voxels according to the kernel.
@ -170,6 +157,11 @@ public:
*/
std::function<bool(GridPoint3)> dilate(const DilationKernel& kernel, const std::function<bool(GridPoint3)>& process_cell_func) const;
GridPoint3 toGridPoint(const Point &point, const Vec3crd &offset) const
{
return toGridPoint(Vec3crd(point.x(), point.y(), 0) + offset);
}
GridPoint3 toGridPoint(const Vec3crd& point) const
{
return GridPoint3(toGridCoord(point.x(), 0), toGridCoord(point.y(), 1), toGridCoord(point.z(), 2));