From 1268856f6a90c1c1b0e5d82fe26da714ab78f548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Thu, 5 Jan 2023 15:59:28 +0100 Subject: [PATCH] Renamed FillBoundedRectilinear to FillEnsuring and moved to separated files. --- src/libslic3r/CMakeLists.txt | 2 + src/libslic3r/Fill/Fill.cpp | 11 +-- src/libslic3r/Fill/FillBase.cpp | 3 +- src/libslic3r/Fill/FillBase.hpp | 2 +- src/libslic3r/Fill/FillEnsuring.cpp | 95 ++++++++++++++++++++++++++ src/libslic3r/Fill/FillEnsuring.hpp | 30 ++++++++ src/libslic3r/Fill/FillRectilinear.cpp | 85 ----------------------- src/libslic3r/Fill/FillRectilinear.hpp | 19 ------ src/libslic3r/PrintConfig.hpp | 2 +- 9 files changed, 137 insertions(+), 112 deletions(-) create mode 100644 src/libslic3r/Fill/FillEnsuring.cpp create mode 100644 src/libslic3r/Fill/FillEnsuring.hpp diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index bdf057f585..92983a34d4 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -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 diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 1093de1f35..5eee8706ff 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -15,6 +15,7 @@ #include "FillRectilinear.hpp" #include "FillLightning.hpp" #include "FillConcentric.hpp" +#include "FillEnsuring.hpp" namespace Slic3r { @@ -301,10 +302,10 @@ std::vector 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 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(f.get())->generator = lightning_generator; - if (surface_fill.params.pattern == ipBoundedRectilinear) { - auto *fill_bounded_rectilinear = dynamic_cast(f.get()); + if (surface_fill.params.pattern == ipEnsuring) { + auto *fill_bounded_rectilinear = dynamic_cast(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) { diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index 0bf3c4dde6..c92462148b 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -20,6 +20,7 @@ #include "FillRectilinear.hpp" #include "FillAdaptive.hpp" #include "FillLightning.hpp" +#include "FillEnsuring.hpp" #include @@ -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"); } } diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 2a9091d354..cf37667587 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -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; diff --git a/src/libslic3r/Fill/FillEnsuring.cpp b/src/libslic3r/Fill/FillEnsuring.cpp new file mode 100644 index 0000000000..60b92d16ff --- /dev/null +++ b/src/libslic3r/Fill/FillEnsuring.cpp @@ -0,0 +1,95 @@ +#include "../ClipperUtils.hpp" +#include "../ShortestPath.hpp" +#include "../Arachne/WallToolPaths.hpp" + +#include "FillEnsuring.hpp" + +#include + +namespace Slic3r { + +ThickPolylines FillEnsuring::fill_surface_arachne(const Surface *surface, const FillParams ¶ms) +{ + // Perform offset. + Slic3r::ExPolygons expp = this->overlap != 0. ? offset_ex(surface->expolygon, scaled(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 ¶ms, 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(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 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(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(this->spacing))); + } +} + +} // namespace Slic3r diff --git a/src/libslic3r/Fill/FillEnsuring.hpp b/src/libslic3r/Fill/FillEnsuring.hpp new file mode 100644 index 0000000000..faa0801535 --- /dev/null +++ b/src/libslic3r/Fill/FillEnsuring.hpp @@ -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 ¶ms) override { return {}; }; + ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams ¶ms) override; + +protected: + void fill_surface_single_arachne(const Surface &surface, const FillParams ¶ms, 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_ diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index b0c1e50966..bb93d824be 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -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 ¶ms) -{ - // Perform offset. - Slic3r::ExPolygons expp = this->overlap != 0. ? offset_ex(surface->expolygon, scaled(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 ¶ms, 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(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 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(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(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. diff --git a/src/libslic3r/Fill/FillRectilinear.hpp b/src/libslic3r/Fill/FillRectilinear.hpp index 9a022873f7..3ba5823046 100644 --- a/src/libslic3r/Fill/FillRectilinear.hpp +++ b/src/libslic3r/Fill/FillRectilinear.hpp @@ -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 ¶ms) override { return {}; }; - ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams ¶ms) override; - -protected: - void fill_surface_single_arachne(const Surface &surface, const FillParams ¶ms, 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); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index edfac5f4fa..a253b95a5f 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -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, };