diff options
-rw-r--r-- | resources/ui_layout/print.ui | 1 | ||||
-rw-r--r-- | src/libslic3r/Brim.cpp | 4 | ||||
-rw-r--r-- | src/libslic3r/ExtrusionEntityCollection.hpp | 17 | ||||
-rw-r--r-- | src/libslic3r/Fill/FillBase.cpp | 89 | ||||
-rw-r--r-- | src/libslic3r/Fill/FillBase.hpp | 22 | ||||
-rw-r--r-- | src/libslic3r/Fill/FillRectilinear.cpp | 83 | ||||
-rw-r--r-- | src/libslic3r/Fill/FillRectilinear.hpp | 11 | ||||
-rw-r--r-- | src/libslic3r/Preset.cpp | 1 | ||||
-rw-r--r-- | src/libslic3r/PrintConfig.cpp | 13 | ||||
-rw-r--r-- | src/libslic3r/PrintConfig.hpp | 1 | ||||
-rw-r--r-- | src/libslic3r/PrintObject.cpp | 3 | ||||
-rw-r--r-- | src/libslic3r/SupportMaterial.cpp | 203 |
12 files changed, 231 insertions, 217 deletions
diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index 6ed8eaabc..22ff7a78b 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -214,7 +214,6 @@ group:Support material setting:support_material_threshold setting:support_material_enforce_layers group:Raft - setting:support_material_solid_first_layer setting:raft_layers line:First layer setting:raft_first_layer_density diff --git a/src/libslic3r/Brim.cpp b/src/libslic3r/Brim.cpp index 2f265fc4e..2208af917 100644 --- a/src/libslic3r/Brim.cpp +++ b/src/libslic3r/Brim.cpp @@ -988,8 +988,8 @@ void make_brim_ears(const Print& print, const Flow& flow, const PrintObjectPtrs& if (!object->support_layers().empty()) { Polygons polys = object->support_layers().front()->support_fills.polygons_covered_by_spacing(flow.spacing_ratio(), float(SCALED_EPSILON)); - //put ears over supports unless it's 100% fill - if (object->config().support_material_solid_first_layer) { + //put ears over supports unless it's more than 30% fill + if (object->config().raft_first_layer_density.get_abs_value(1.) > 0.3) { for (Polygon poly : polys) { object_islands.push_back(brim_offset == 0 ? ExPolygon{ poly } : offset_ex(Polygons{ poly }, brim_offset)[0]); } diff --git a/src/libslic3r/ExtrusionEntityCollection.hpp b/src/libslic3r/ExtrusionEntityCollection.hpp index ac21bba48..b84f035d1 100644 --- a/src/libslic3r/ExtrusionEntityCollection.hpp +++ b/src/libslic3r/ExtrusionEntityCollection.hpp @@ -175,6 +175,23 @@ public: virtual void use(const ExtrusionEntityCollection &coll) override; }; +#ifdef _DEBUG +class TestCollection : public ExtrusionVisitorRecursiveConst { +public: + virtual void default_use(const ExtrusionEntity& entity) override { + assert(entity.as_polyline().size() > 0); + } + virtual void use(const ExtrusionEntityCollection& coll) override { + for (const ExtrusionEntity* entity : coll.entities()) { + assert(entity); + std::cout << "entity at " << ((uint64_t)(void*)entity) << "\n"; + entity->visit(*this); + } + + } +}; +#endif + } // namespace Slic3r #endif diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index a3e237135..e0d838650 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -53,7 +53,7 @@ Fill* Fill::new_from_type(const InfillPattern type) case ipSmooth: return new FillSmooth(); case ipSmoothTriple: return new FillSmoothTriple(); case ipSmoothHilbert: return new FillSmoothHilbert(); - case ipRectiWithPerimeter: return new FillRectilinearPeri(); + case ipRectiWithPerimeter: return new FillWithPerimeter(new FillRectilinear()); case ipSawtooth: return new FillRectilinearSawtooth(); case ipAdaptiveCubic: return new FillAdaptive::Filler(); case ipSupportCubic: return new FillAdaptive::Filler(); @@ -3565,4 +3565,91 @@ void Fill::connect_infill(Polylines&& infill_ordered, const ExPolygon& boundary, } } + +void +FillWithPerimeter::fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out) const +{ + ExtrusionEntityCollection* eecroot = new ExtrusionEntityCollection(); + //you don't want to sort the extrusions: big infill first, small second + eecroot->set_can_sort_reverse(true, true); + + //set Fill params + *infill = *this; + + // === extrude perimeter & associated surface at the same time, in the right order === + //generate perimeter: + ExPolygons path_perimeter = offset2_ex(ExPolygons{ surface->expolygon }, + scale_d(-this->get_spacing()), scale_d(this->get_spacing() / 2), + ClipperLib::jtMiter, scale_d(this->get_spacing()) * 10); + //fix a bug that can happens when (positive) offsetting with a big miter limit and two island merge. See https://github.com/supermerill/SuperSlicer/issues/609 + path_perimeter = intersection_ex(path_perimeter, offset_ex(surface->expolygon, scale_d(-this->get_spacing() / 2))); + for (ExPolygon& expolygon : path_perimeter) { + ExtrusionEntityCollection* eec_expoly = path_perimeter.size() == 1 ? eecroot : new ExtrusionEntityCollection(); + if (path_perimeter.size() > 1) eecroot->append(ExtrusionEntitiesPtr{ eec_expoly }); + eec_expoly->set_can_sort_reverse(false, false); + + //create perimeter + expolygon.contour.make_counter_clockwise(); + Polylines polylines_peri = { expolygon.contour.split_at_index(0) }; + for (Polygon hole : expolygon.holes) { + hole.make_clockwise(); + polylines_peri.push_back(hole.split_at_index(0)); + } + if (!polylines_peri.empty()) { + // Save into layer. + ExtrusionEntityCollection* eec_peri = new ExtrusionEntityCollection(); + /// pass the no_sort attribute to the extrusion path + eec_peri->set_can_sort_reverse(!this->no_sort(), !this->no_sort()); + /// add it into the collection + eec_expoly->append(ExtrusionEntitiesPtr{ eec_peri }); + //get the role + ExtrusionRole good_role = getRoleFromSurfaceType(params, surface); + /// push the path + extrusion_entities_append_paths( + eec_peri->set_entities(), + polylines_peri, + good_role, + params.flow.mm3_per_mm() * params.flow_mult, + params.flow.width() * params.flow_mult, + params.flow.height()); + + // === extrude infill === + //50% overlap with the new perimeter + ExPolygons path_inner = offset2_ex(ExPolygons{ expolygon }, scale_d(-this->get_spacing() * (ratio_fill_inside+0.5)), scale_d(this->get_spacing()/2)); + for (ExPolygon& expolygon : path_inner) { + Surface surfInner(*surface, expolygon); + Polylines polys_infill = infill->fill_surface(&surfInner, params); + if (!polys_infill.empty()) { + // Save into layer. + ExtrusionEntityCollection* eec_infill = new ExtrusionEntityCollection(); + /// pass the no_sort attribute to the extrusion path + eec_infill->set_can_sort_reverse(!this->no_sort(), !this->no_sort()); + /// add it into the collection + eec_expoly->append(ExtrusionEntitiesPtr{ eec_infill }); + //get the role + ExtrusionRole good_role = getRoleFromSurfaceType(params, surface); + /// push the path + extrusion_entities_append_paths( + eec_infill->set_entities(), + polys_infill, + good_role, + params.flow.mm3_per_mm() * params.flow_mult, + params.flow.width() * params.flow_mult, + params.flow.height()); + } + } + } + + } + + // === end === + if (!eecroot->empty()) { + out.push_back(eecroot); + } else { + delete eecroot; + } + +} + + } // namespace Slic3r diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index fe1ea4c7c..76ca17de0 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -209,6 +209,28 @@ namespace NaiveConnect { void connect_infill(Polylines&& infill_ordered, const ExPolygon& boundary, Polylines& polylines_out, const double spacing, const FillParams& params); } +// composite filler +class FillWithPerimeter : public Fill +{ +public: + std::unique_ptr<Fill> infill{ nullptr }; + float ratio_fill_inside = 0.f; + FillWithPerimeter() : Fill() {} + FillWithPerimeter(Fill* parent) : infill(parent), Fill() {} + FillWithPerimeter(const FillWithPerimeter& o) : infill(o.infill.get() ? o.infill->clone() : nullptr), ratio_fill_inside(o.ratio_fill_inside), Fill(o) {} + Fill* clone() const override { + FillWithPerimeter* n = new FillWithPerimeter(*this); + if (infill != nullptr) { + n->infill.reset(infill->clone()); + } + return n; + }; + ~FillWithPerimeter() override = default; + //Polylines fill_surface(const Surface *surface, const FillParams ¶ms); + void fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out) const override; + +}; + class ExtrusionSetRole : public ExtrusionVisitor { ExtrusionRole new_role; public: diff --git a/src/libslic3r/Fill/FillRectilinear.cpp b/src/libslic3r/Fill/FillRectilinear.cpp index e04c63d8c..72d86a73b 100644 --- a/src/libslic3r/Fill/FillRectilinear.cpp +++ b/src/libslic3r/Fill/FillRectilinear.cpp @@ -3247,89 +3247,6 @@ Polylines FillSupportBase::fill_surface(const Surface *surface, const FillParams return polylines_out; } -void -FillRectilinearPeri::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, ExtrusionEntitiesPtr &out) const -{ - ExtrusionEntityCollection *eecroot = new ExtrusionEntityCollection(); - //you don't want to sort the extrusions: big infill first, small second - eecroot->set_can_sort_reverse(false, false); - - // === extrude perimeter === - Polylines polylines_1; - //generate perimeter: - ExPolygons path_perimeter = offset2_ex(ExPolygons{ surface->expolygon }, - scale_d(-this->get_spacing()), scale_d(this->get_spacing() / 2), - ClipperLib::jtMiter, scale_d(this->get_spacing()) * 10); - //fix a bug that can happens when (positive) offsetting with a big miter limit and two island merge. See https://github.com/supermerill/SuperSlicer/issues/609 - path_perimeter = intersection_ex(path_perimeter, offset_ex(surface->expolygon, scale_d(-this->get_spacing() / 2))); - for (ExPolygon &expolygon : path_perimeter) { - expolygon.contour.make_counter_clockwise(); - polylines_1.push_back(expolygon.contour.split_at_index(0)); - for (Polygon hole : expolygon.holes) { - hole.make_clockwise(); - polylines_1.push_back(hole.split_at_index(0)); - } - } - - if (!polylines_1.empty()) { - // Save into layer. - ExtrusionEntityCollection *eec = new ExtrusionEntityCollection(); - /// pass the no_sort attribute to the extrusion path - eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort()); - /// add it into the collection - eecroot->append(ExtrusionEntitiesPtr{ eec }); - //get the role - ExtrusionRole good_role = getRoleFromSurfaceType(params, surface); - /// push the path - extrusion_entities_append_paths( - eec->set_entities(), - polylines_1, - good_role, - params.flow.mm3_per_mm() * params.flow_mult, - params.flow.width() * params.flow_mult, - params.flow.height()); - } - - - // === extrude dense infill === - Polylines polylines_2; - bool canFill = true; - //50% overlap with the new perimeter - ExPolygons path_inner = offset2_ex(ExPolygons{ surface->expolygon }, scale_d(-this->get_spacing() * 1.5), scale_d(this->get_spacing())); - for (ExPolygon &expolygon : path_inner) { - Surface surfInner(*surface, expolygon); - if (!fill_surface_by_lines(&surfInner, params, 0.f, 0.f, polylines_2)) { - printf("FillRectilinear2::fill_surface() failed to fill a region.\n"); - canFill = false; - } - } - if (canFill && !polylines_2.empty()) { - // Save into layer. - ExtrusionEntityCollection *eec = new ExtrusionEntityCollection(); - /// pass the no_sort attribute to the extrusion path - eec->set_can_sort_reverse(!this->no_sort(), !this->no_sort()); - /// add it into the collection - eecroot->append(ExtrusionEntitiesPtr{ eec }); - //get the role - ExtrusionRole good_role = getRoleFromSurfaceType(params, surface); - /// push the path - extrusion_entities_append_paths( - eec->set_entities(), - polylines_2, - good_role, - params.flow.mm3_per_mm() * params.flow_mult, - params.flow.width() * params.flow_mult, - params.flow.height()); - } - - // === end === - if (!eecroot->empty()) { - out.push_back(eecroot); - } else { - delete eecroot; - } - -} /* Returns a float uniformly distributed in the range [0..1.0) using the given integer as the seed * diff --git a/src/libslic3r/Fill/FillRectilinear.hpp b/src/libslic3r/Fill/FillRectilinear.hpp index 483a7e5a0..0c7eee3c8 100644 --- a/src/libslic3r/Fill/FillRectilinear.hpp +++ b/src/libslic3r/Fill/FillRectilinear.hpp @@ -113,17 +113,6 @@ protected: float _layer_angle(size_t idx) const override { return 0.f; } }; -class FillRectilinearPeri : public FillRectilinear -{ -public: - Fill* clone() const override { return new FillRectilinearPeri(*this); }; - ~FillRectilinearPeri() override = default; - //Polylines fill_surface(const Surface *surface, const FillParams ¶ms); - void fill_surface_extrusion(const Surface* surface, const FillParams& params, ExtrusionEntitiesPtr& out) const override; - -}; - - class FillScatteredRectilinear : public FillRectilinear { public: diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 14261db65..f5778501d 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -652,7 +652,6 @@ static std::vector<std::string> s_Preset_print_options { "compatible_printers", "compatible_printers_condition", "inherits", "infill_dense", "infill_dense_algo", "no_perimeter_unsupported_algo", - "support_material_solid_first_layer", "exact_last_layer_height", "perimeter_loop", "perimeter_loop_seam", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 6626cefa6..d52c00c20 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3963,13 +3963,6 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(3.)); - def = this->add("support_material_solid_first_layer", coBool); - def->label = L("Solid first layer"); - def->category = OptionCategory::support; - def->tooltip = L("Use a solid layer instead of a raft for the layer that touches the build plate."); - def->mode = comAdvanced; - def->set_default_value(new ConfigOptionBool(false)); - def = this->add("raft_layers", coInt); def->label = L("Raft layers"); def->category = OptionCategory::support; @@ -6808,6 +6801,11 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va opt_key = ""; return; } + //in ps 2.4, the raft_first_layer_density is now more powerful than the support_material_solid_first_layer, also it always does the perimeter. + if ("support_material_solid_first_layer" == opt_key) { + opt_key = "raft_first_layer_density"; + value = "100"; + } //prusa if ("gcode_flavor" == opt_key) { @@ -7033,7 +7031,6 @@ std::unordered_set<std::string> prusa_export_to_remove_keys = { "support_material_contact_distance_type", "support_material_interface_acceleration", "support_material_interface_pattern", -"support_material_solid_first_layer", "thin_perimeters_all", "thin_perimeters", "thin_walls_acceleration", diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 30d1b0423..04624a731 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -728,7 +728,6 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, support_material_spacing)) ((ConfigOptionFloatOrPercent, support_material_speed)) ((ConfigOptionEnum<SupportMaterialStyle>, support_material_style)) - ((ConfigOptionBool, support_material_solid_first_layer)) ((ConfigOptionBool, support_material_synchronize_layers)) // Overhang angle threshold. ((ConfigOptionInt, support_material_threshold)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 698bf4677..cd3c9f4b9 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -818,8 +818,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "support_material_closing_radius" || opt_key == "support_material_synchronize_layers" || opt_key == "support_material_threshold" - || opt_key == "support_material_with_sheath" - || opt_key == "support_material_solid_first_layer") { + || opt_key == "support_material_with_sheath") { steps.emplace_back(posSupportMaterial); } else if (opt_key == "bottom_solid_layers") { steps.emplace_back(posPrepareInfill); diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index 87d99e278..b64663f63 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -334,7 +334,7 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object m_support_params.support_material_flow = support_material_flow(object, float(slicing_params.layer_height)); m_support_params.support_material_interface_flow = support_material_interface_flow(object, float(slicing_params.layer_height)); m_support_params.support_layer_height_min = 0.01; - m_support_params.raft_bridge_flow_ratio = object->print()->default_region_config().bridge_flow_ratio.value; + m_support_params.raft_bridge_flow_ratio = object->print()->default_region_config().bridge_flow_ratio.get_abs_value(1.); // Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um. m_support_params.support_layer_height_min = 1000000.; @@ -3303,59 +3303,59 @@ static inline void fill_expolygons_generate_paths( fill_params.config = ®ion_config; fill_expolygons_generate_paths(dst, std::move(expolygons), filler, fill_params, density, role, flow, spacing); } - -static inline void fill_expolygons_with_sheath_generate_paths( - ExtrusionEntitiesPtr &dst, - const Polygons &polygons, - Fill *filler, - float density, - ExtrusionRole role, - const Flow &flow, - coordf_t spacing, - bool with_sheath, - bool no_sort, - const PrintRegionConfig& region_config) -{ - if (polygons.empty()) - return; - - if (! with_sheath) { - fill_expolygons_generate_paths(dst, closing_ex(polygons, float(SCALED_EPSILON)), filler, density, role, flow, spacing, region_config); - return; - } - - FillParams fill_params; - fill_params.density = density; - fill_params.dont_adjust = true; - fill_params.config = ®ion_config; - - // Clip the sheath path to avoid the extruder to get exactly on the first point of the loop. - double clip_length = spacing * 0.15; - - for (ExPolygon &expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5*flow.scaled_width()))) { - // Don't reorder the skirt and its infills. - std::unique_ptr<ExtrusionEntityCollection> eec; - if (no_sort) { - eec = std::make_unique<ExtrusionEntityCollection>(); - eec->set_can_sort_reverse(false, true); - } - ExtrusionEntitiesPtr &out = no_sort ? eec->set_entities() : dst; - // Draw the perimeters. - Polylines polylines; - polylines.reserve(expoly.holes.size() + 1); - for (size_t i = 0; i <= expoly.holes.size(); ++ i) { - Polyline pl(i == 0 ? expoly.contour.points : expoly.holes[i - 1].points); - pl.points.emplace_back(pl.points.front()); - pl.clip_end(clip_length); - polylines.emplace_back(std::move(pl)); - } - extrusion_entities_append_paths(out, polylines, erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height()); - // Fill in the rest. - fill_expolygons_generate_paths(out, offset_ex(expoly, float(-0.4 * spacing)), filler, fill_params, density, role, flow, spacing); - if (no_sort && ! eec->empty()) - dst.emplace_back(eec.release()); - } -} +// now use FillWithPerimeter +//static inline void fill_expolygons_with_sheath_generate_paths( +// ExtrusionEntitiesPtr &dst, +// const Polygons &polygons, +// Fill *filler, +// float density, +// ExtrusionRole role, +// const Flow &flow, +// coordf_t spacing, +// bool with_sheath, +// bool no_sort, +// const PrintRegionConfig& region_config) +//{ +// if (polygons.empty()) +// return; +// +// if (! with_sheath) { +// fill_expolygons_generate_paths(dst, closing_ex(polygons, float(SCALED_EPSILON)), filler, density, role, flow, spacing, region_config); +// return; +// } +// +// FillParams fill_params; +// fill_params.density = density; +// fill_params.dont_adjust = true; +// fill_params.config = ®ion_config; +// +// // Clip the sheath path to avoid the extruder to get exactly on the first point of the loop. +// double clip_length = spacing * 0.15; +// +// for (ExPolygon &expoly : closing_ex(polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5*flow.scaled_width()))) { +// // Don't reorder the skirt and its infills. +// std::unique_ptr<ExtrusionEntityCollection> eec; +// if (no_sort) { +// eec = std::make_unique<ExtrusionEntityCollection>(); +// eec->set_can_sort_reverse(false, true); +// } +// ExtrusionEntitiesPtr &out = no_sort ? eec->set_entities() : dst; +// // Draw the perimeters. +// Polylines polylines; +// polylines.reserve(expoly.holes.size() + 1); +// for (size_t i = 0; i <= expoly.holes.size(); ++ i) { +// Polyline pl(i == 0 ? expoly.contour.points : expoly.holes[i - 1].points); +// pl.points.emplace_back(pl.points.front()); +// pl.clip_end(clip_length); +// polylines.emplace_back(std::move(pl)); +// } +// extrusion_entities_append_paths(out, polylines, erSupportMaterial, flow.mm3_per_mm(), flow.width(), flow.height()); +// // Fill in the rest. +// fill_expolygons_generate_paths(out, offset_ex(expoly, float(-0.4 * spacing)), filler, fill_params, density, role, flow, spacing); +// if (no_sort && ! eec->empty()) +// dst.emplace_back(eec.release()); +// } +//} // Support layers, partially processed. struct MyLayerExtruded @@ -4015,7 +4015,10 @@ void PrintObjectSupportMaterial::generate_toolpaths( std::unique_ptr<Fill> filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(m_support_params.contact_fill_pattern)); //m_support_params.interface_fill_pattern)); FIXME choose std::unique_ptr<Fill> filler_support = std::unique_ptr<Fill>(Fill::new_from_type(m_support_params.base_fill_pattern)); - std::unique_ptr<Fill> filler_dense = std::unique_ptr<Fill>(Fill::new_from_type(ipRectiWithPerimeter)); + std::unique_ptr<FillWithPerimeter> filler_support_with_sheath = std::make_unique<FillWithPerimeter>((Fill::new_from_type(m_support_params.base_fill_pattern))); + filler_support_with_sheath->ratio_fill_inside = 0.2f; + std::unique_ptr<FillWithPerimeter> filler_dense = std::make_unique<FillWithPerimeter>((Fill::new_from_type(ipRectilinear))); + filler_dense->ratio_fill_inside = 0.2f; filler_interface->set_bounding_box(bbox_object); filler_support->set_bounding_box(bbox_object); @@ -4028,19 +4031,18 @@ void PrintObjectSupportMaterial::generate_toolpaths( if (! to_infill_polygons.empty()) { assert(! raft_layer.bridging); Flow flow(float(m_support_params.support_material_flow.width()), float(raft_layer.height), m_support_params.support_material_flow.nozzle_diameter(), m_support_params.support_material_flow.spacing_ratio()); - Fill * filler = filler_support.get(); + Fill * filler = m_support_params.with_sheath ? filler_support_with_sheath.get() : filler_support.get(); filler->angle = raft_angle_base; filler->link_max_length = scale_t(m_support_params.support_material_flow.spacing() * link_max_length_factor / m_support_params.support_density); - fill_expolygons_with_sheath_generate_paths( + fill_expolygons_generate_paths( // Destination support_layer.support_fills.set_entities(), // Regions to fill - to_infill_polygons, + closing_ex(to_infill_polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5 * flow.scaled_width())), // Filler and its parameters filler, float(m_support_params.support_density), // Extrusion parameters erSupportMaterial, flow, m_support_params.support_material_flow.spacing(), - m_support_params.with_sheath, false, m_object->print()->default_region_config()); } } @@ -4048,17 +4050,12 @@ void PrintObjectSupportMaterial::generate_toolpaths( Fill *filler = filler_interface.get(); Flow flow = m_support_params.first_layer_flow; float density = 0.f; - coordf_t spacing = 0.f; + double spacing = 0.f; if (support_layer_id == 0) { // Base flange. - if (this->m_object_config->support_material_solid_first_layer.value) { - filler = filler_dense.get(); - density = 1.f; - filler->angle = 0; - } else { - filler->angle = raft_angle_1st_layer; - density = float(m_object_config->raft_first_layer_density.value * 0.01); - } + filler = filler_dense.get(); + filler->angle = raft_angle_1st_layer; + density = float(m_object_config->raft_first_layer_density.value * 0.01); spacing = m_support_params.first_layer_flow.spacing(); } else if (support_layer_id >= m_slicing_params.base_raft_layers) { filler->angle = raft_angle_interface; @@ -4073,18 +4070,16 @@ void PrintObjectSupportMaterial::generate_toolpaths( density = float(m_support_params.interface_density); } else continue; - filler->link_max_length = coord_t(scale_(spacing * link_max_length_factor / density)); - fill_expolygons_with_sheath_generate_paths( + filler->link_max_length = scale_t(spacing * link_max_length_factor / density); + fill_expolygons_generate_paths( // Destination support_layer.support_fills.set_entities(), // Regions to fill - raft_layer.polygons, + closing_ex(raft_layer.polygons, float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5 * flow.scaled_width())), // Filler and its parameters filler, density, // Extrusion parameters (support_layer_id < m_slicing_params.base_raft_layers) ? erSupportMaterial : erSupportMaterialInterface, flow, spacing, - // sheath at first layer - support_layer_id == 0, support_layer_id == 0, m_object->print()->default_region_config()); } }); @@ -4112,9 +4107,12 @@ void PrintObjectSupportMaterial::generate_toolpaths( }; std::vector<LayerCache> layer_caches(support_layers.size()); + // Filler for the 1st layer interface. + std::unique_ptr<FillWithPerimeter> filler_first_layer_ptr = std::make_unique<FillWithPerimeter>(Fill::new_from_type(ipRectilinear)); + filler_first_layer_ptr->ratio_fill_inside = 0.2f; tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, support_layers.size()), [this, &support_layers, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &base_interface_layers, &layer_caches, &loop_interface_processor, - &bbox_object, &angles, link_max_length_factor] + &bbox_object, &angles, link_max_length_factor, &filler_first_layer_ptr] (const tbb::blocked_range<size_t>& range) { // Indices of the 1st layer in their respective container at the support layer height. size_t idx_layer_bottom_contact = size_t(-1); @@ -4122,26 +4120,27 @@ void PrintObjectSupportMaterial::generate_toolpaths( size_t idx_layer_intermediate = size_t(-1); size_t idx_layer_interface = size_t(-1); size_t idx_layer_base_interface = size_t(-1); - const InfillPattern fill_type_first_layer = ipRectilinear; + const InfillPattern fill_type_first_layer = ipRectiWithPerimeter; std::unique_ptr<Fill> filler_interface = std::unique_ptr<Fill>(Fill::new_from_type(m_support_params.contact_fill_pattern)); std::unique_ptr<Fill> filler_intermediate_interface = std::unique_ptr<Fill>(Fill::new_from_type(ipRectilinear)); - // Filler for the 1st layer interface, if different from filler_interface. - std::unique_ptr<Fill> filler_first_layer_ptr = std::unique_ptr<Fill>(range.begin() == 0 && m_support_params.contact_fill_pattern != fill_type_first_layer ? Fill::new_from_type(fill_type_first_layer) : nullptr); - // Pointer to the 1st layer interface filler. - Fill* filler_first_layer = filler_first_layer_ptr ? filler_first_layer_ptr.get() : filler_interface.get(); // Filler for the base interface (to be used for soluble interface / non soluble base, to produce non soluble interface layer below soluble interface layer). std::unique_ptr<Fill> filler_base_interface = std::unique_ptr<Fill>(base_interface_layers.empty() ? nullptr : Fill::new_from_type(m_support_params.interface_density > 0.95 || m_support_params.with_sheath ? ipRectilinear : ipSupportBase)); - std::unique_ptr<Fill> filler_support = std::unique_ptr<Fill>(Fill::new_from_type(m_support_params.base_fill_pattern)); - std::unique_ptr<Fill> filler_solid = std::unique_ptr<Fill>(Fill::new_from_type(ipRectiWithPerimeter)); + std::unique_ptr<Fill> filler_support; + if (m_support_params.with_sheath) { + FillWithPerimeter *ptr = new FillWithPerimeter(Fill::new_from_type(m_support_params.base_fill_pattern)); + ptr->ratio_fill_inside = 0.2f; + filler_support.reset(ptr); + } else { + filler_support.reset(Fill::new_from_type(m_support_params.base_fill_pattern)); + } filler_interface->set_bounding_box(bbox_object); filler_intermediate_interface->set_bounding_box(bbox_object); - if (filler_first_layer_ptr) + if (range.begin() == 0) filler_first_layer_ptr->set_bounding_box(bbox_object); if (filler_base_interface) filler_base_interface->set_bounding_box(bbox_object); filler_support->set_bounding_box(bbox_object); - filler_solid->set_bounding_box(bbox_object); for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id) { SupportLayer &support_layer = *support_layers[support_layer_id]; @@ -4233,9 +4232,9 @@ void PrintObjectSupportMaterial::generate_toolpaths( float supp_density = m_support_params.interface_density; coordf_t filler_spacing; //if first layer and solid first layer : draw concentric with 100% density - if (support_layer.id() == 0 && this->m_object_config->support_material_solid_first_layer.value) { - filler = filler_solid.get(); - supp_density = 1.f; + if (support_layer.id() == 0) { + filler = filler_first_layer_ptr.get(); + supp_density = float(this->m_object_config->raft_first_layer_density.get_abs_value(1.)); interface_flow = m_support_params.first_layer_flow; filler->angle = 0; filler_spacing = interface_flow.spacing(); @@ -4289,45 +4288,35 @@ void PrintObjectSupportMaterial::generate_toolpaths( // Base support or flange. if (! base_layer.empty() && ! base_layer.polygons_to_extrude().empty()) { Fill *filler = filler_support.get(); - coordf_t filler_spacing = filler->get_spacing(); - filler->angle = angles[support_layer_id % angles.size()]; + coordf_t filler_spacing = m_support_params.support_material_flow.spacing(); // We don't use $base_flow->spacing because we need a constant spacing // value that guarantees that all layers are correctly aligned. assert(! base_layer.layer->bridging); auto flow = m_support_params.support_material_flow.with_height(float(base_layer.layer->height)); - filler_spacing = m_support_params.support_material_flow.spacing(); - filler->link_max_length = coord_t(scale_(filler_spacing * link_max_length_factor / m_support_params.support_density)); float density = float(m_support_params.support_density); bool sheath = m_support_params.with_sheath; - bool no_sort = false; if (base_layer.layer->bottom_z < EPSILON) { - if (this->m_object_config->support_material_solid_first_layer.value) { - // Base flange (the 1st layer). - filler = filler_solid.get(); //FIXME use filler_first_layer, just set it to the right value - filler->angle = 0; - density = 1.f; - } else { - filler = filler_first_layer_ptr.get() == nullptr ? filler_interface.get() : filler_first_layer_ptr.get(); - filler->angle = Geometry::deg2rad(float(m_object_config->support_material_angle.value + 90.)); - density = float(m_object_config->raft_first_layer_density.value * 0.01); - filler->link_max_length = scale_t(filler_spacing * link_max_length_factor / density); - } + filler = filler_first_layer_ptr.get(); + filler->angle = Geometry::deg2rad(float(m_object_config->support_material_angle.value + 90.)); + density = float(m_object_config->raft_first_layer_density.get_abs_value(1.)); + filler->link_max_length = scale_t(filler_spacing * link_max_length_factor / density); flow = m_support_params.first_layer_flow; // use the proper spacing for first layer as we don't need to align // its pattern to the other layers - sheath = true; - no_sort = true; + filler_spacing = flow.spacing(); + } else{ + filler->angle = angles[support_layer_id % angles.size()]; + filler->link_max_length = coord_t(scale_(filler_spacing * link_max_length_factor / m_support_params.support_density)); } - fill_expolygons_with_sheath_generate_paths( + fill_expolygons_generate_paths( // Destination base_layer.extrusions.set_entities(), // Regions to fill - base_layer.polygons_to_extrude(), + closing_ex(base_layer.polygons_to_extrude(), float(SCALED_EPSILON), float(SCALED_EPSILON + 0.5 * flow.scaled_width())), // Filler and its parameters filler, density, // Extrusion parameters erSupportMaterial, flow, filler_spacing, - sheath, no_sort, m_object->print()->default_region_config()); } |