Renamed FillBoundedRectilinear to FillEnsuring and moved to separated files.

This commit is contained in:
Lukáš Hejl 2023-01-05 15:59:28 +01:00
parent 634859e4a6
commit 1268856f6a
9 changed files with 137 additions and 112 deletions

View File

@ -72,6 +72,8 @@ set(SLIC3R_SOURCES
Fill/FillBase.hpp
Fill/FillConcentric.cpp
Fill/FillConcentric.hpp
Fill/FillEnsuring.cpp
Fill/FillEnsuring.hpp
Fill/FillHoneycomb.cpp
Fill/FillHoneycomb.hpp
Fill/FillGyroid.cpp

View File

@ -15,6 +15,7 @@
#include "FillRectilinear.hpp"
#include "FillLightning.hpp"
#include "FillConcentric.hpp"
#include "FillEnsuring.hpp"
namespace Slic3r {
@ -301,10 +302,10 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
}
}
// Detect narrow internal solid infill area and use ipBoundedRectilinear pattern instead.
// Detect narrow internal solid infill area and use ipEnsuring pattern instead.
{
std::vector<char> narrow_expolygons;
static constexpr const auto narrow_pattern = ipBoundedRectilinear;
static constexpr const auto narrow_pattern = ipEnsuring;
for (size_t surface_fill_id = 0, num_old_fills = surface_fills.size(); surface_fill_id < num_old_fills; ++ surface_fill_id)
if (SurfaceFill &fill = surface_fills[surface_fill_id]; fill.surface.surface_type == stInternalSolid) {
size_t num_expolygons = fill.expolygons.size();
@ -494,8 +495,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
if (surface_fill.params.pattern == ipLightning)
dynamic_cast<FillLightning::Filler*>(f.get())->generator = lightning_generator;
if (surface_fill.params.pattern == ipBoundedRectilinear) {
auto *fill_bounded_rectilinear = dynamic_cast<FillBoundedRectilinear *>(f.get());
if (surface_fill.params.pattern == ipEnsuring) {
auto *fill_bounded_rectilinear = dynamic_cast<FillEnsuring *>(f.get());
assert(fill_bounded_rectilinear != nullptr);
fill_bounded_rectilinear->print_region_config = &m_regions[surface_fill.region_id]->region().config();
}
@ -527,7 +528,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
params.anchor_length = surface_fill.params.anchor_length;
params.anchor_length_max = surface_fill.params.anchor_length_max;
params.resolution = resolution;
params.use_arachne = (perimeter_generator == PerimeterGeneratorType::Arachne && surface_fill.params.pattern == ipConcentric) || surface_fill.params.pattern == ipBoundedRectilinear;
params.use_arachne = (perimeter_generator == PerimeterGeneratorType::Arachne && surface_fill.params.pattern == ipConcentric) || surface_fill.params.pattern == ipEnsuring;
params.layer_height = layerm.layer()->height;
for (ExPolygon &expoly : surface_fill.expolygons) {

View File

@ -20,6 +20,7 @@
#include "FillRectilinear.hpp"
#include "FillAdaptive.hpp"
#include "FillLightning.hpp"
#include "FillEnsuring.hpp"
#include <boost/log/trivial.hpp>
@ -49,7 +50,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipSupportCubic: return new FillAdaptive::Filler();
case ipSupportBase: return new FillSupportBase();
case ipLightning: return new FillLightning::Filler();
case ipBoundedRectilinear: return new FillBoundedRectilinear();
case ipEnsuring: return new FillEnsuring();
default: throw Slic3r::InvalidArgument("unknown type");
}
}

View File

@ -91,7 +91,7 @@ public:
// Octree builds on mesh for usage in the adaptive cubic infill
FillAdaptive::Octree* adapt_fill_octree = nullptr;
// PrintConfig and PrintObjectConfig are used by infills that use Arachne (Concentric and FillBoundedRectilinear).
// PrintConfig and PrintObjectConfig are used by infills that use Arachne (Concentric and FillEnsuring).
const PrintConfig *print_config = nullptr;
const PrintObjectConfig *print_object_config = nullptr;

View File

@ -0,0 +1,95 @@
#include "../ClipperUtils.hpp"
#include "../ShortestPath.hpp"
#include "../Arachne/WallToolPaths.hpp"
#include "FillEnsuring.hpp"
#include <boost/log/trivial.hpp>
namespace Slic3r {
ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const FillParams &params)
{
// Perform offset.
Slic3r::ExPolygons expp = this->overlap != 0. ? offset_ex(surface->expolygon, scaled<float>(this->overlap)) : ExPolygons{surface->expolygon};
// Create the infills for each of the regions.
ThickPolylines thick_polylines_out;
for (ExPolygon &ex_poly : expp)
fill_surface_single_arachne(Surface(*surface, std::move(ex_poly)), params, thick_polylines_out);
return thick_polylines_out;
}
void FillEnsuring::fill_surface_single_arachne(const Surface &surface, const FillParams &params, ThickPolylines &thick_polylines_out)
{
assert(params.use_arachne);
assert(this->print_config != nullptr && this->print_object_config != nullptr && this->print_region_config != nullptr);
coord_t scaled_spacing = scaled<coord_t>(this->spacing);
Polygons polygons = to_polygons(surface.expolygon);
Arachne::WallToolPaths wall_tool_paths(polygons, scaled_spacing, scaled_spacing, 1, 0, params.layer_height, *this->print_object_config, *this->print_config);
if (std::vector<Arachne::VariableWidthLines> loop = wall_tool_paths.getToolPaths(); !loop.empty()) {
assert(loop.size() == 1);
size_t firts_poly_idx = thick_polylines_out.size();
Point last_pos(0, 0);
for (const Arachne::ExtrusionLine &extrusion : loop.front()) {
if (extrusion.empty())
continue;
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion);
if (thick_polyline.length() == 0.)
//FIXME this should not happen.
continue;
assert(thick_polyline.size() > 1);
assert(thick_polyline.length() > 0.);
//assert(thick_polyline.points.size() == thick_polyline.width.size());
if (extrusion.is_closed)
thick_polyline.start_at_index(nearest_point_index(thick_polyline.points, last_pos));
assert(thick_polyline.size() > 1);
//assert(thick_polyline.points.size() == thick_polyline.width.size());
thick_polylines_out.emplace_back(std::move(thick_polyline));
last_pos = thick_polylines_out.back().last_point();
}
// clip the paths to prevent the extruder from getting exactly on the first point of the loop
// Keep valid paths only.
size_t j = firts_poly_idx;
for (size_t i = firts_poly_idx; i < thick_polylines_out.size(); ++i) {
assert(thick_polylines_out[i].size() > 1);
assert(thick_polylines_out[i].length() > 0.);
//assert(thick_polylines_out[i].points.size() == thick_polylines_out[i].width.size());
thick_polylines_out[i].clip_end(this->loop_clipping);
assert(thick_polylines_out[i].size() > 1);
if (thick_polylines_out[i].is_valid()) {
if (j < i)
thick_polylines_out[j] = std::move(thick_polylines_out[i]);
++j;
}
}
if (j < thick_polylines_out.size())
thick_polylines_out.erase(thick_polylines_out.begin() + int(j), thick_polylines_out.end());
}
// Remaining infill area will be filled with classic Rectilinear infill.
ExPolygons infill_contour = union_ex(wall_tool_paths.getInnerContour());
if (offset_ex(infill_contour, -float(scaled_spacing / 2.)).empty())
infill_contour.clear(); // Infill region is too small, so let's filter it out.
Polygons pp;
for (ExPolygon &ex : infill_contour)
ex.simplify_p(scaled<double>(params.resolution), &pp);
// Collapse too narrow infill areas and append them to thick_polylines_out.
const auto min_perimeter_infill_spacing = coord_t(scaled_spacing * (1. - INSET_OVERLAP_TOLERANCE));
const auto infill_overlap = coord_t(scale_(this->print_region_config->get_abs_value("infill_overlap", this->spacing)));
for (ExPolygon &ex_poly : offset2_ex(union_ex(pp), float(-min_perimeter_infill_spacing / 2.), float(infill_overlap + min_perimeter_infill_spacing / 2.))) {
Polylines polylines;
if (Surface new_surface(surface, std::move(ex_poly)); !fill_surface_by_lines(&new_surface, params, 0.f, 0.f, polylines))
BOOST_LOG_TRIVIAL(error) << "FillEnsuring::fill_surface() failed to fill a region.";
append(thick_polylines_out, to_thick_polylines(std::move(polylines), scaled<coord_t>(this->spacing)));
}
}
} // namespace Slic3r

View File

@ -0,0 +1,30 @@
#ifndef slic3r_FillEnsuring_hpp_
#define slic3r_FillEnsuring_hpp_
#include "FillBase.hpp"
#include "FillRectilinear.hpp"
namespace Slic3r {
class FillEnsuring : public FillRectilinear
{
public:
Fill *clone() const override { return new FillEnsuring(*this); }
~FillEnsuring() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override { return {}; };
ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams &params) override;
protected:
void fill_surface_single_arachne(const Surface &surface, const FillParams &params, ThickPolylines &thick_polylines_out);
bool no_sort() const override { return true; }
// PrintRegionConfig is used for computing overlap between boundary contour and inner Rectilinear infill.
const PrintRegionConfig *print_region_config = nullptr;
friend class Layer;
};
} // namespace Slic3r
#endif // slic3r_FillEnsuring_hpp_

View File

@ -15,7 +15,6 @@
#include "../Geometry.hpp"
#include "../Surface.hpp"
#include "../ShortestPath.hpp"
#include "../Arachne/WallToolPaths.hpp"
#include "FillRectilinear.hpp"
@ -3044,90 +3043,6 @@ Polylines FillSupportBase::fill_surface(const Surface *surface, const FillParams
return polylines_out;
}
ThickPolylines FillBoundedRectilinear::fill_surface_arachne(const Surface *surface, const FillParams &params)
{
// Perform offset.
Slic3r::ExPolygons expp = this->overlap != 0. ? offset_ex(surface->expolygon, scaled<float>(this->overlap)) : ExPolygons{surface->expolygon};
// Create the infills for each of the regions.
ThickPolylines thick_polylines_out;
for (ExPolygon &ex_poly : expp)
fill_surface_single_arachne(Surface(*surface, std::move(ex_poly)), params, thick_polylines_out);
return thick_polylines_out;
}
void FillBoundedRectilinear::fill_surface_single_arachne(const Surface &surface, const FillParams &params, ThickPolylines &thick_polylines_out)
{
assert(params.use_arachne);
assert(this->print_config != nullptr && this->print_object_config != nullptr && this->print_region_config != nullptr);
coord_t scaled_spacing = scaled<coord_t>(this->spacing);
Polygons polygons = to_polygons(surface.expolygon);
Arachne::WallToolPaths wall_tool_paths(polygons, scaled_spacing, scaled_spacing, 1, 0, params.layer_height, *this->print_object_config, *this->print_config);
if (std::vector<Arachne::VariableWidthLines> loop = wall_tool_paths.getToolPaths(); !loop.empty()) {
assert(loop.size() == 1);
size_t firts_poly_idx = thick_polylines_out.size();
Point last_pos(0, 0);
for (const Arachne::ExtrusionLine &extrusion : loop.front()) {
if (extrusion.empty())
continue;
ThickPolyline thick_polyline = Arachne::to_thick_polyline(extrusion);
if (thick_polyline.length() == 0.)
//FIXME this should not happen.
continue;
assert(thick_polyline.size() > 1);
assert(thick_polyline.length() > 0.);
//assert(thick_polyline.points.size() == thick_polyline.width.size());
if (extrusion.is_closed)
thick_polyline.start_at_index(nearest_point_index(thick_polyline.points, last_pos));
assert(thick_polyline.size() > 1);
//assert(thick_polyline.points.size() == thick_polyline.width.size());
thick_polylines_out.emplace_back(std::move(thick_polyline));
last_pos = thick_polylines_out.back().last_point();
}
// clip the paths to prevent the extruder from getting exactly on the first point of the loop
// Keep valid paths only.
size_t j = firts_poly_idx;
for (size_t i = firts_poly_idx; i < thick_polylines_out.size(); ++i) {
assert(thick_polylines_out[i].size() > 1);
assert(thick_polylines_out[i].length() > 0.);
//assert(thick_polylines_out[i].points.size() == thick_polylines_out[i].width.size());
thick_polylines_out[i].clip_end(this->loop_clipping);
assert(thick_polylines_out[i].size() > 1);
if (thick_polylines_out[i].is_valid()) {
if (j < i)
thick_polylines_out[j] = std::move(thick_polylines_out[i]);
++j;
}
}
if (j < thick_polylines_out.size())
thick_polylines_out.erase(thick_polylines_out.begin() + int(j), thick_polylines_out.end());
}
// Remaining infill area will be filled with classic Rectilinear infill.
ExPolygons infill_contour = union_ex(wall_tool_paths.getInnerContour());
if (offset_ex(infill_contour, -float(scaled_spacing / 2.)).empty())
infill_contour.clear(); // Infill region is too small, so let's filter it out.
Polygons pp;
for (ExPolygon &ex : infill_contour)
ex.simplify_p(scaled<double>(params.resolution), &pp);
// Collapse too narrow infill areas and append them to thick_polylines_out.
const auto min_perimeter_infill_spacing = coord_t(scaled_spacing * (1. - INSET_OVERLAP_TOLERANCE));
const auto infill_overlap = coord_t(scale_(this->print_region_config->get_abs_value("infill_overlap", this->spacing)));
for (ExPolygon &ex_poly : offset2_ex(union_ex(pp), float(-min_perimeter_infill_spacing / 2.), float(infill_overlap + min_perimeter_infill_spacing / 2.))) {
Polylines polylines;
if (Surface new_surface(surface, std::move(ex_poly)); !fill_surface_by_lines(&new_surface, params, 0.f, 0.f, polylines))
BOOST_LOG_TRIVIAL(error) << "FillBoundedRectilinear::fill_surface() failed to fill a region.";
append(thick_polylines_out, to_thick_polylines(std::move(polylines), scaled<coord_t>(this->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.

View File

@ -110,25 +110,6 @@ protected:
float _layer_angle(size_t idx) const override { return 0.f; }
};
class FillBoundedRectilinear : public FillRectilinear
{
public:
Fill *clone() const override { return new FillBoundedRectilinear(*this); }
~FillBoundedRectilinear() override = default;
Polylines fill_surface(const Surface *surface, const FillParams &params) override { return {}; };
ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams &params) override;
protected:
void fill_surface_single_arachne(const Surface &surface, const FillParams &params, ThickPolylines &thick_polylines_out);
bool no_sort() const override { return true; }
// PrintRegionConfig is used for computing overlap between boundary contour and inner Rectilinear infill.
const PrintRegionConfig *print_region_config = nullptr;
friend class Layer;
};
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, const BoundingBox &global_bounding_box);
Points sample_grid_pattern(const Polygons &polygons, coord_t spacing, const BoundingBox &global_bounding_box);

View File

@ -60,7 +60,7 @@ enum InfillPattern : int {
ipRectilinear, ipMonotonic, ipAlignedRectilinear, ipGrid, ipTriangles, ipStars, ipCubic, ipLine, ipConcentric, ipHoneycomb, ip3DHoneycomb,
ipGyroid, ipHilbertCurve, ipArchimedeanChords, ipOctagramSpiral, ipAdaptiveCubic, ipSupportCubic, ipSupportBase,
ipLightning,
ipBoundedRectilinear,
ipEnsuring,
ipCount,
};