From 3b35abb5568eae985e0aac81bc89ff9126be16f5 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 13 Jun 2024 10:53:56 +0200 Subject: [PATCH 01/14] Apply raft flow settings CURA-11947 --- src/settings/PathConfigStorage.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/settings/PathConfigStorage.cpp b/src/settings/PathConfigStorage.cpp index c0edd6d0e8..d4944f1e8d 100644 --- a/src/settings/PathConfigStorage.cpp +++ b/src/settings/PathConfigStorage.cpp @@ -46,21 +46,21 @@ PathConfigStorage::PathConfigStorage(const SliceDataStorage& storage, const Laye , raft_base_config(GCodePathConfig{ .type = PrintFeatureType::SupportInterface, .line_width = raft_base_train.settings_.get("raft_base_line_width"), .layer_thickness = raft_base_train.settings_.get("raft_base_thickness"), - .flow = Ratio(1.0), + .flow = raft_base_train.settings_.get("raft_base_flow"), .speed_derivatives = SpeedDerivatives{ .speed = raft_base_train.settings_.get("raft_base_speed"), .acceleration = raft_base_train.settings_.get("raft_base_acceleration"), .jerk = raft_base_train.settings_.get("raft_base_jerk") } }) , raft_interface_config(GCodePathConfig{ .type = PrintFeatureType::Support, .line_width = raft_interface_train.settings_.get("raft_interface_line_width"), .layer_thickness = raft_interface_train.settings_.get("raft_interface_thickness"), - .flow = Ratio(1.0), + .flow = raft_base_train.settings_.get("raft_interface_flow"), .speed_derivatives = SpeedDerivatives{ .speed = raft_interface_train.settings_.get("raft_interface_speed"), .acceleration = raft_interface_train.settings_.get("raft_interface_acceleration"), .jerk = raft_interface_train.settings_.get("raft_interface_jerk") } }) , raft_surface_config(GCodePathConfig{ .type = PrintFeatureType::SupportInterface, .line_width = raft_surface_train.settings_.get("raft_surface_line_width"), .layer_thickness = raft_surface_train.settings_.get("raft_surface_thickness"), - .flow = Ratio(1.0), + .flow = raft_base_train.settings_.get("raft_surface_flow"), .speed_derivatives = SpeedDerivatives{ .speed = raft_surface_train.settings_.get("raft_surface_speed"), .acceleration = raft_surface_train.settings_.get("raft_surface_acceleration"), .jerk = raft_surface_train.settings_.get("raft_surface_jerk") } }) From 16507e070ff7f47c3456f604d660e12cc8d516ce Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 13 Jun 2024 11:05:25 +0200 Subject: [PATCH 02/14] Fix possible crash when using raft and supports --- src/FffGcodeWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 79a97b2e7e..ee1d1a19a4 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -3462,7 +3462,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer ZSeamConfig z_seam_config = ZSeamConfig(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); Shape disallowed_area_for_seams{}; - if (infill_extruder.settings_.get("support_z_seam_away_from_model")) + if (infill_extruder.settings_.get("support_z_seam_away_from_model") && gcode_layer.getLayerNr() >= 0) { for (std::shared_ptr mesh_ptr : storage.meshes) { From 3c1a4423eb840b38ce45b8daed81bf3f490038b1 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 13 Jun 2024 13:02:46 +0200 Subject: [PATCH 03/14] Apply setting to customize support first layer CURA-11947 --- src/FffGcodeWriter.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index ee1d1a19a4..2d479ed2fa 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -3399,6 +3399,12 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer const AngleDegrees support_infill_angle = get_support_infill_angle(storage.support, gcode_layer.getLayerNr()); constexpr size_t infill_multiplier = 1; // there is no frontend setting for this (yet) + size_t infill_density_multiplier = 1; + if (gcode_layer.getLayerNr() <= 0) + { + infill_density_multiplier = infill_extruder.settings_.get("support_infill_density_multiplier_layer_0"); + } + const size_t wall_line_count = infill_extruder.settings_.get("support_wall_count"); const coord_t max_resolution = infill_extruder.settings_.get("meshfix_maximum_resolution"); const coord_t max_deviation = infill_extruder.settings_.get("meshfix_maximum_deviation"); @@ -3523,10 +3529,12 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer } const unsigned int density_factor = 2 << density_idx; // == pow(2, density_idx + 1) - int support_line_distance_here + coord_t support_line_distance_here = (part.custom_line_distance_ > 0 ? part.custom_line_distance_ : default_support_line_distance * density_factor); // the highest density infill combines with the next to create a grid with density_factor 1 + support_line_distance_here /= (1 << (infill_density_multiplier - 1)); + support_line_distance_here = std::max(support_line_distance_here, support_line_width); const int support_shift = support_line_distance_here / 2; if (part.custom_line_distance_ == 0 && (density_idx == max_density_idx || support_pattern == EFillMethod::CROSS || support_pattern == EFillMethod::CROSS_3D)) { From e6bb061bd4c7b962c1fcd9a3d7419676acce574e Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 13 Jun 2024 13:41:00 +0200 Subject: [PATCH 04/14] Apply setting to offset raft layers CURA-11947 --- src/FffGcodeWriter.cpp | 6 ++++++ src/raft.cpp | 12 ++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 2d479ed2fa..c9651d0624 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -756,6 +756,9 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) const coord_t interface_avoid_distance = interface_settings.get("travel_avoid_distance"); const coord_t interface_max_resolution = interface_settings.get("meshfix_maximum_resolution"); const coord_t interface_max_deviation = interface_settings.get("meshfix_maximum_deviation"); + const coord_t raft_interface_z_offset = interface_settings.get("raft_interface_z_offset"); + + z += raft_interface_z_offset; for (LayerIndex raft_interface_layer = 1; static_cast(raft_interface_layer) <= num_interface_layers; ++raft_interface_layer) { // raft interface layer @@ -912,6 +915,9 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) const coord_t surface_avoid_distance = surface_settings.get("travel_avoid_distance"); const Ratio surface_fan_speed = surface_settings.get("raft_surface_fan_speed"); const bool surface_monotonic = surface_settings.get("raft_surface_monotonic"); + const coord_t raft_surface_z_offset = interface_settings.get("raft_surface_z_offset"); + + z += raft_surface_z_offset; for (LayerIndex raft_surface_layer = 1; static_cast(raft_surface_layer) <= num_surface_layers; raft_surface_layer++) { // raft surface layers diff --git a/src/raft.cpp b/src/raft.cpp index ef08c19d6d..edaff83509 100644 --- a/src/raft.cpp +++ b/src/raft.cpp @@ -130,12 +130,12 @@ void Raft::generate(SliceDataStorage& storage) coord_t Raft::getTotalThickness() { const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings; - const ExtruderTrain& base_train = mesh_group_settings.get("raft_base_extruder_nr"); - const ExtruderTrain& interface_train = mesh_group_settings.get("raft_interface_extruder_nr"); - const ExtruderTrain& surface_train = mesh_group_settings.get("raft_surface_extruder_nr"); - return base_train.settings_.get("raft_base_thickness") - + interface_train.settings_.get("raft_interface_layers") * interface_train.settings_.get("raft_interface_thickness") - + surface_train.settings_.get("raft_surface_layers") * surface_train.settings_.get("raft_surface_thickness"); + const Settings& base_train = mesh_group_settings.get("raft_base_extruder_nr").settings_; + const Settings& interface_train = mesh_group_settings.get("raft_interface_extruder_nr").settings_; + const Settings& surface_train = mesh_group_settings.get("raft_surface_extruder_nr").settings_; + return base_train.get("raft_base_thickness") + interface_train.get("raft_interface_layers") * interface_train.get("raft_interface_thickness") + + interface_train.get("raft_interface_z_offset") + surface_train.get("raft_surface_layers") * surface_train.get("raft_surface_thickness") + + interface_train.get("raft_surface_z_offset"); } coord_t Raft::getZdiffBetweenRaftAndLayer0() From cfdf0b40eefbbaa5158f0feffd8d5afa5864561b Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 19 Jun 2024 13:52:45 +0200 Subject: [PATCH 05/14] Apply the raft infill overlap --- include/infill.h | 5 ++++- src/FffGcodeWriter.cpp | 22 +++++++++++++++------- src/infill.cpp | 2 ++ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/include/infill.h b/include/infill.h index 081652d68f..53994fb122 100644 --- a/include/infill.h +++ b/include/infill.h @@ -42,6 +42,7 @@ class Infill coord_t infill_line_width_{}; //!< The line width of the infill lines to generate coord_t line_distance_{}; //!< The distance between two infill lines / polygons coord_t infill_overlap_{}; //!< the distance by which to overlap with the actual area within which to generate infill + coord_t pattern_overlap_{ 0 }; //!< The distance by which to overlap the inner infill pattern with the walls size_t infill_multiplier_{}; //!< the number of infill lines next to each other AngleDegrees fill_angle_{}; //!< for linear infill types: the angle of the infill lines (or the angle of the grid) coord_t z_{}; //!< height of the layer for which we generate infill @@ -163,7 +164,8 @@ class Infill bool use_endpieces, bool skip_some_zags, size_t zag_skip_count, - coord_t pocket_size) noexcept + coord_t pocket_size, + coord_t pattern_overlap = 0) noexcept : pattern_{ pattern } , zig_zaggify_{ zig_zaggify } , connect_polygons_{ connect_polygons } @@ -188,6 +190,7 @@ class Infill , zag_skip_count_{ zag_skip_count } , pocket_size_{ pocket_size } , mirror_offset_{ zig_zaggify } + , pattern_overlap_{ pattern_overlap } { } diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index c9651d0624..2411f3d02a 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -580,7 +580,6 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) const size_t num_surface_layers = surface_settings.get("raft_surface_layers"); // some infill config for all lines infill generation below - constexpr double fill_overlap = 0; // raft line shouldn't be expanded - there is no boundary polygon printed constexpr int infill_multiplier = 1; // rafts use single lines constexpr int extra_infill_shift = 0; constexpr bool fill_gaps = true; @@ -624,6 +623,8 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) const size_t wall_line_count = base_settings.get("raft_base_wall_count"); const coord_t small_area_width = 0; // A raft never has a small region due to the large horizontal expansion. const coord_t line_spacing = base_settings.get("raft_base_line_spacing"); + constexpr coord_t infill_overlap = 0; + const coord_t pattern_overlap = base_settings.get("raft_base_infill_overlap_mm"); const coord_t line_spacing_prime_tower = base_settings.get("prime_tower_raft_base_line_spacing"); const Point2LL& infill_origin = Point2LL(); constexpr bool skip_stitching = false; @@ -668,7 +669,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) raft_outline_path.outline, gcode_layer.configs_storage_.raft_base_config.getLineWidth(), raft_outline_path.line_spacing, - fill_overlap, + infill_overlap, infill_multiplier, fill_angle, z, @@ -684,7 +685,8 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) use_endpieces, skip_some_zags, zag_skip_count, - pocket_size); + pocket_size, + pattern_overlap); std::vector raft_paths; infill_comp.generate(raft_paths, raft_polygons, raft_lines, base_settings, layer_nr, SectionType::ADHESION); if (! raft_paths.empty()) @@ -753,6 +755,8 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) const coord_t interface_line_spacing = interface_settings.get("raft_interface_line_spacing"); const Ratio interface_fan_speed = interface_settings.get("raft_interface_fan_speed"); const coord_t interface_line_width = interface_settings.get("raft_interface_line_width"); + constexpr coord_t interface_infill_overlap = 0; + const coord_t interface_pattern_overlap = interface_settings.get("raft_interface_infill_overlap_mm"); const coord_t interface_avoid_distance = interface_settings.get("travel_avoid_distance"); const coord_t interface_max_resolution = interface_settings.get("meshfix_maximum_resolution"); const coord_t interface_max_deviation = interface_settings.get("meshfix_maximum_deviation"); @@ -826,7 +830,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) raft_outline_path, infill_outline_width, interface_line_spacing, - fill_overlap, + interface_infill_overlap, infill_multiplier, fill_angle, z, @@ -842,7 +846,8 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) use_endpieces, skip_some_zags, zag_skip_count, - pocket_size); + pocket_size, + interface_pattern_overlap); std::vector raft_paths; infill_comp.generate(raft_paths, raft_polygons, raft_lines, interface_settings, layer_nr, SectionType::ADHESION); if (! raft_paths.empty()) @@ -912,6 +917,8 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) const coord_t surface_max_resolution = surface_settings.get("meshfix_maximum_resolution"); const coord_t surface_max_deviation = surface_settings.get("meshfix_maximum_deviation"); const coord_t surface_line_width = surface_settings.get("raft_surface_line_width"); + constexpr coord_t surface_infill_overlap = 0; + const coord_t surface_pattern_overlap = surface_settings.get("raft_surface_infill_overlap_mm"); const coord_t surface_avoid_distance = surface_settings.get("travel_avoid_distance"); const Ratio surface_fan_speed = surface_settings.get("raft_surface_fan_speed"); const bool surface_monotonic = surface_settings.get("raft_surface_monotonic"); @@ -991,7 +998,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) raft_island, infill_outline_width, surface_line_spacing, - fill_overlap, + surface_infill_overlap, infill_multiplier, fill_angle, z, @@ -1007,7 +1014,8 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) use_endpieces, skip_some_zags, zag_skip_count, - pocket_size); + pocket_size, + surface_pattern_overlap); std::vector raft_paths; infill_comp.generate(raft_paths, raft_polygons, raft_lines, surface_settings, layer_nr, SectionType::ADHESION); diff --git a/src/infill.cpp b/src/infill.cpp index a2d931d262..86f72c646c 100644 --- a/src/infill.cpp +++ b/src/infill.cpp @@ -103,6 +103,8 @@ void Infill::generate( inner_contour_ = generateWallToolPaths(toolpaths, outer_contour_, wall_line_count_, infill_line_width_, infill_overlap_, settings, layer_idx, section_type); scripta::log("infill_inner_contour_0", inner_contour_, section_type, layer_idx); + inner_contour_ = inner_contour_.offset(pattern_overlap_); + // It does not make sense to print a pattern in a small region. So the infill region // is split into a small region that will be filled with walls and the normal region // that will be filled with the pattern. This split of regions is not needed if the From 3f65f4444ac02ed5ce79ed22f52f9f69faab385c Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 21 Jun 2024 10:35:44 +0200 Subject: [PATCH 06/14] Make documentation more explicit --- include/infill.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/infill.h b/include/infill.h index 53994fb122..3a644c6418 100644 --- a/include/infill.h +++ b/include/infill.h @@ -42,7 +42,7 @@ class Infill coord_t infill_line_width_{}; //!< The line width of the infill lines to generate coord_t line_distance_{}; //!< The distance between two infill lines / polygons coord_t infill_overlap_{}; //!< the distance by which to overlap with the actual area within which to generate infill - coord_t pattern_overlap_{ 0 }; //!< The distance by which to overlap the inner infill pattern with the walls + coord_t pattern_overlap_{ 0 }; //!< The distance by which to overlap the inner infill pattern with the infill walls size_t infill_multiplier_{}; //!< the number of infill lines next to each other AngleDegrees fill_angle_{}; //!< for linear infill types: the angle of the infill lines (or the angle of the grid) coord_t z_{}; //!< height of the layer for which we generate infill From 91635416d2cb614ad96e7c58c1c3cb5d6c80a078 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 21 Jun 2024 13:42:08 +0200 Subject: [PATCH 07/14] Change behavior of infill overlap to match expected behavior The infill overlap previously worked by extending the whole infill area and filling it. However, infill areas sometimes have inner walls, and in this case we would expand the walls, but the pattern generated inside would not overlap the walls, which is actually what we want to achieve in order to ensure that the sparser inner pattern properly sticks to what is outside it, whenever this is an infill wall or a skin wall. --- include/infill.h | 13 ++++--------- src/FffGcodeWriter.cpp | 22 ++++++++-------------- src/infill.cpp | 10 +++------- src/skin.cpp | 2 -- src/support.cpp | 1 - 5 files changed, 15 insertions(+), 33 deletions(-) diff --git a/include/infill.h b/include/infill.h index 3a644c6418..89b9bba689 100644 --- a/include/infill.h +++ b/include/infill.h @@ -41,8 +41,7 @@ class Infill Shape inner_contour_{}; //!< The part of the contour that will get filled with an infill pattern. Equals outer_contour minus the extra infill walls. coord_t infill_line_width_{}; //!< The line width of the infill lines to generate coord_t line_distance_{}; //!< The distance between two infill lines / polygons - coord_t infill_overlap_{}; //!< the distance by which to overlap with the actual area within which to generate infill - coord_t pattern_overlap_{ 0 }; //!< The distance by which to overlap the inner infill pattern with the infill walls + coord_t infill_overlap_{}; //!< The distance by which to overlap the inner infill pattern with the infill walls size_t infill_multiplier_{}; //!< the number of infill lines next to each other AngleDegrees fill_angle_{}; //!< for linear infill types: the angle of the infill lines (or the angle of the grid) coord_t z_{}; //!< height of the layer for which we generate infill @@ -164,8 +163,7 @@ class Infill bool use_endpieces, bool skip_some_zags, size_t zag_skip_count, - coord_t pocket_size, - coord_t pattern_overlap = 0) noexcept + coord_t pocket_size) noexcept : pattern_{ pattern } , zig_zaggify_{ zig_zaggify } , connect_polygons_{ connect_polygons } @@ -190,7 +188,6 @@ class Infill , zag_skip_count_{ zag_skip_count } , pocket_size_{ pocket_size } , mirror_offset_{ zig_zaggify } - , pattern_overlap_{ pattern_overlap } { } @@ -222,19 +219,17 @@ class Infill * This function is called within the generate() function but can also be called stand-alone * * \param toolpaths [out] The generated toolpaths. Binned by inset_idx. - * \param outer_contour [in,out] the outer contour, this is offsetted with the infill overlap + * \param outer_contour [in] the outer contour * \param wall_line_count [in] The number of walls that needs to be generated * \param line_width [in] The optimum wall line width of the walls - * \param infill_overlap [in] The overlap of the infill * \param settings [in] A settings storage to use for generating variable-width walls. * \return The inner contour of the wall toolpaths */ static Shape generateWallToolPaths( std::vector& toolpaths, - Shape& outer_contour, + const Shape& outer_contour, const size_t wall_line_count, const coord_t line_width, - const coord_t infill_overlap, const Settings& settings, int layer_idx, SectionType section_type); diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 0d664918ac..43bb607980 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -623,8 +623,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) const size_t wall_line_count = base_settings.get("raft_base_wall_count"); const coord_t small_area_width = 0; // A raft never has a small region due to the large horizontal expansion. const coord_t line_spacing = base_settings.get("raft_base_line_spacing"); - constexpr coord_t infill_overlap = 0; - const coord_t pattern_overlap = base_settings.get("raft_base_infill_overlap_mm"); + const coord_t infill_overlap = base_settings.get("raft_base_infill_overlap_mm"); const coord_t line_spacing_prime_tower = base_settings.get("prime_tower_raft_base_line_spacing"); const Point2LL& infill_origin = Point2LL(); constexpr bool skip_stitching = false; @@ -685,8 +684,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) use_endpieces, skip_some_zags, zag_skip_count, - pocket_size, - pattern_overlap); + pocket_size); std::vector raft_paths; infill_comp.generate(raft_paths, raft_polygons, raft_lines, base_settings, layer_nr, SectionType::ADHESION); if (! raft_paths.empty()) @@ -755,8 +753,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) const coord_t interface_line_spacing = interface_settings.get("raft_interface_line_spacing"); const Ratio interface_fan_speed = interface_settings.get("raft_interface_fan_speed"); const coord_t interface_line_width = interface_settings.get("raft_interface_line_width"); - constexpr coord_t interface_infill_overlap = 0; - const coord_t interface_pattern_overlap = interface_settings.get("raft_interface_infill_overlap_mm"); + const coord_t interface_infill_overlap = interface_settings.get("raft_interface_infill_overlap_mm"); const coord_t interface_avoid_distance = interface_settings.get("travel_avoid_distance"); const coord_t interface_max_resolution = interface_settings.get("meshfix_maximum_resolution"); const coord_t interface_max_deviation = interface_settings.get("meshfix_maximum_deviation"); @@ -846,8 +843,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) use_endpieces, skip_some_zags, zag_skip_count, - pocket_size, - interface_pattern_overlap); + pocket_size); std::vector raft_paths; infill_comp.generate(raft_paths, raft_polygons, raft_lines, interface_settings, layer_nr, SectionType::ADHESION); if (! raft_paths.empty()) @@ -917,8 +913,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) const coord_t surface_max_resolution = surface_settings.get("meshfix_maximum_resolution"); const coord_t surface_max_deviation = surface_settings.get("meshfix_maximum_deviation"); const coord_t surface_line_width = surface_settings.get("raft_surface_line_width"); - constexpr coord_t surface_infill_overlap = 0; - const coord_t surface_pattern_overlap = surface_settings.get("raft_surface_infill_overlap_mm"); + const coord_t surface_infill_overlap = surface_settings.get("raft_surface_infill_overlap_mm"); const coord_t surface_avoid_distance = surface_settings.get("travel_avoid_distance"); const Ratio surface_fan_speed = surface_settings.get("raft_surface_fan_speed"); const bool surface_monotonic = surface_settings.get("raft_surface_monotonic"); @@ -1014,8 +1009,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) use_endpieces, skip_some_zags, zag_skip_count, - pocket_size, - surface_pattern_overlap); + pocket_size); std::vector raft_paths; infill_comp.generate(raft_paths, raft_polygons, raft_lines, surface_settings, layer_nr, SectionType::ADHESION); @@ -1933,7 +1927,7 @@ bool FffGcodeWriter::processMultiLayerInfill( constexpr size_t wall_line_count = 0; // wall toolpaths are when gradual infill areas are determined const coord_t small_area_width = 0; - constexpr coord_t infill_overlap = 0; // Overlap is handled when the wall toolpaths are generated + const coord_t infill_overlap = mesh.settings.get("infill_overlap_mm"); constexpr bool skip_stitching = false; constexpr bool connected_zigzags = false; constexpr bool use_endpieces = true; @@ -2214,7 +2208,7 @@ bool FffGcodeWriter::processSingleLayerInfill( constexpr size_t wall_line_count_here = 0; // Wall toolpaths were generated in generateGradualInfill for the sparsest density, denser parts don't have walls by default const coord_t small_area_width = 0; - constexpr coord_t overlap = 0; // overlap is already applied for the sparsest density in the generateGradualInfill + const coord_t overlap = mesh.settings.get("infill_overlap_mm"); wall_tool_paths.emplace_back(); Infill infill_comp( diff --git a/src/infill.cpp b/src/infill.cpp index 86f72c646c..6067fa625b 100644 --- a/src/infill.cpp +++ b/src/infill.cpp @@ -57,17 +57,13 @@ namespace cura Shape Infill::generateWallToolPaths( std::vector& toolpaths, - Shape& outer_contour, + const Shape& outer_contour, const size_t wall_line_count, const coord_t line_width, - const coord_t infill_overlap, const Settings& settings, int layer_idx, SectionType section_type) { - outer_contour = outer_contour.offset(infill_overlap); - scripta::log("infill_outer_contour", outer_contour, section_type, layer_idx, scripta::CellVDI{ "infill_overlap", infill_overlap }); - Shape inner_contour; if (wall_line_count > 0) { @@ -100,10 +96,10 @@ void Infill::generate( return; } - inner_contour_ = generateWallToolPaths(toolpaths, outer_contour_, wall_line_count_, infill_line_width_, infill_overlap_, settings, layer_idx, section_type); + inner_contour_ = generateWallToolPaths(toolpaths, outer_contour_, wall_line_count_, infill_line_width_, settings, layer_idx, section_type); scripta::log("infill_inner_contour_0", inner_contour_, section_type, layer_idx); - inner_contour_ = inner_contour_.offset(pattern_overlap_); + inner_contour_ = inner_contour_.offset(infill_overlap_); // It does not make sense to print a pattern in a small region. So the infill region // is split into a small region that will be filled with walls and the normal region diff --git a/src/skin.cpp b/src/skin.cpp index c0dcadd3d8..351290be93 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -470,7 +470,6 @@ void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh) const auto infill_wall_count = mesh.settings.get("infill_wall_line_count"); const auto infill_wall_width = mesh.settings.get("infill_line_width"); - const auto infill_overlap = mesh.settings.get("infill_overlap_mm"); const auto is_connected = mesh.settings.get("zig_zaggify_infill") || mesh.settings.get("infill_pattern") == EFillMethod::ZIG_ZAG; for (LayerIndex layer_idx = 0; layer_idx < static_cast(mesh.layers.size()); layer_idx++) { // loop also over layers which don't contain infill cause of bottom_ and top_layer to initialize their infill_area_per_combine_per_density @@ -485,7 +484,6 @@ void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh) part.getOwnInfillArea(), infill_wall_count, infill_wall_width, - infill_overlap, mesh.settings, layer_idx, SectionType::SKIN); diff --git a/src/support.cpp b/src/support.cpp index a432da3d58..ea7f4164ef 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -226,7 +226,6 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) original_area, support_infill_part.inset_count_to_generate_, wall_width, - 0, infill_extruder.settings_, layer_nr, SectionType::SUPPORT); From 5b5c1bf48ad00fc3bf5fbe5357d68ae909f02bd5 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 24 Jun 2024 12:58:53 +0200 Subject: [PATCH 08/14] Add possibility to do the nozzle switch retract earlier We now try to insert the nozzle switch retract at the same time as the travel move to the nozzle switch position, to avoid oozing during this (long) move. If there is no such move, it will fallback to the old behavior, but this should quite never happen. CURA-11796 --- include/pathPlanning/GCodePath.h | 1 + src/LayerPlan.cpp | 9 ++++++++- src/plugins/converters.cpp | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/pathPlanning/GCodePath.h b/include/pathPlanning/GCodePath.h index 09160202d9..577cd8efcc 100644 --- a/include/pathPlanning/GCodePath.h +++ b/include/pathPlanning/GCodePath.h @@ -40,6 +40,7 @@ struct GCodePath Ratio speed_factor{ 1.0 }; //!< A speed factor that is multiplied with the travel speed. This factor can be used to change the travel speed. Ratio speed_back_pressure_factor{ 1.0 }; // retraction_wipe_config : retraction_config; gcode.writeRetraction(retraction_config->retraction_config); + if (path.retract_for_nozzle_switch) + { + constexpr bool force = true; + constexpr bool extruder_switch = true; + gcode.writeRetraction(retraction_config->extruder_switch_retraction_config, force, extruder_switch); + } insertTempOnTime(extruder_plan.getRetractTime(path), path_idx); if (path.perform_z_hop) { diff --git a/src/plugins/converters.cpp b/src/plugins/converters.cpp index f53d2cbc7c..964a50007d 100644 --- a/src/plugins/converters.cpp +++ b/src/plugins/converters.cpp @@ -347,6 +347,7 @@ gcode_paths_modify_request::value_type gcode_path->set_speed_factor(path.speed_factor); gcode_path->set_speed_back_pressure_factor(path.speed_back_pressure_factor); gcode_path->set_retract(path.retract); + gcode_path->set_retract_for_nozzle_switch(path.retract_for_nozzle_switch); gcode_path->set_unretract_before_last_travel_move(path.unretract_before_last_travel_move); gcode_path->set_perform_z_hop(path.perform_z_hop); gcode_path->set_perform_prime(path.perform_prime); @@ -464,6 +465,7 @@ gcode_paths_modify_response::native_value_type .speed_factor = gcode_path_msg.speed_factor(), .speed_back_pressure_factor = gcode_path_msg.speed_back_pressure_factor(), .retract = gcode_path_msg.retract(), + .retract_for_nozzle_switch = gcode_path_msg.retract_for_nozzle_switch(), .unretract_before_last_travel_move = gcode_path_msg.unretract_before_last_travel_move(), .perform_z_hop = gcode_path_msg.perform_z_hop(), .perform_prime = gcode_path_msg.perform_prime(), From 469686736ddd8acca92a1bfb4f8697c37ce2fd2f Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 25 Jun 2024 13:36:21 +0200 Subject: [PATCH 09/14] Add modifications to script, include a debug line --- .github/workflows/gcodeanalyzer.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/gcodeanalyzer.yml b/.github/workflows/gcodeanalyzer.yml index 0b85fb75aa..8aa0f7d316 100644 --- a/.github/workflows/gcodeanalyzer.yml +++ b/.github/workflows/gcodeanalyzer.yml @@ -184,9 +184,16 @@ jobs: continue infilename = os.path.join(folder_path, filename) with open(infilename.rsplit(".", 1)[0] + ".time", "r") as f: - match = re.match(r"^.*?real\s+(\d+)m(\d+\.\d+)s", f.read()) - timer = 0 if not match else float(match[1]) - + content = f.read() + print("File content:", content) # Debug + match = re.match(r"^real\s+(\d+)m(\d+\.\d+)s", content, re.MULTILINE) + if match: + print("Match groups:", match.groups()) # Debugging line + timer = float(match.group(1)) * 60 + float(match.group(2)) + else: + print("No match found") # Debugging line + timer = 0 + frame = GCodeAnalyzer.DataFrame(infilename) line_lengths = frame.gc.extrusions['length'].describe() From fe774c506501ec508d180eabe9527e41d5986172 Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 25 Jun 2024 14:58:51 +0200 Subject: [PATCH 10/14] User search instead of match :shrug: --- .github/workflows/gcodeanalyzer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gcodeanalyzer.yml b/.github/workflows/gcodeanalyzer.yml index 8aa0f7d316..22095303b5 100644 --- a/.github/workflows/gcodeanalyzer.yml +++ b/.github/workflows/gcodeanalyzer.yml @@ -186,7 +186,7 @@ jobs: with open(infilename.rsplit(".", 1)[0] + ".time", "r") as f: content = f.read() print("File content:", content) # Debug - match = re.match(r"^real\s+(\d+)m(\d+\.\d+)s", content, re.MULTILINE) + match = re.search(r"^real\s+(\d+)m(\d+\.\d+)s", content, re.MULTILINE) if match: print("Match groups:", match.groups()) # Debugging line timer = float(match.group(1)) * 60 + float(match.group(2)) From de5cbc5550fabe63d1d7052f7f367e66cf1581b8 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 25 Jun 2024 15:09:41 +0200 Subject: [PATCH 11/14] Prevent negative (= raft) layers from messing up z-seam calculation. Not part of a ticket (yet?), done as a quick-fix. --- src/FffGcodeWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index 0b3d71df86..61899373d3 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -3469,7 +3469,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer ZSeamConfig z_seam_config = ZSeamConfig(EZSeamType::SHORTEST, gcode_layer.getLastPlannedPositionOrStartingPosition(), EZSeamCornerPrefType::Z_SEAM_CORNER_PREF_NONE, false); Shape disallowed_area_for_seams{}; - if (infill_extruder.settings_.get("support_z_seam_away_from_model")) + if (infill_extruder.settings_.get("support_z_seam_away_from_model") && (gcode_layer.getLayerNr() >= 0)) { for (std::shared_ptr mesh_ptr : storage.meshes) { From 0169a41cb84e29d90b9973936b94646a8569b06d Mon Sep 17 00:00:00 2001 From: HellAholic Date: Tue, 25 Jun 2024 16:06:57 +0200 Subject: [PATCH 12/14] Remove debug comments --- .github/workflows/gcodeanalyzer.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/gcodeanalyzer.yml b/.github/workflows/gcodeanalyzer.yml index 22095303b5..aa45e74bc2 100644 --- a/.github/workflows/gcodeanalyzer.yml +++ b/.github/workflows/gcodeanalyzer.yml @@ -185,13 +185,10 @@ jobs: infilename = os.path.join(folder_path, filename) with open(infilename.rsplit(".", 1)[0] + ".time", "r") as f: content = f.read() - print("File content:", content) # Debug match = re.search(r"^real\s+(\d+)m(\d+\.\d+)s", content, re.MULTILINE) if match: - print("Match groups:", match.groups()) # Debugging line timer = float(match.group(1)) * 60 + float(match.group(2)) else: - print("No match found") # Debugging line timer = 0 frame = GCodeAnalyzer.DataFrame(infilename) From e09e5b4fb2ecfd172533f018228591e1e18f8a10 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 25 Jun 2024 16:56:22 +0200 Subject: [PATCH 13/14] Apply setting renaming CURA-11947 --- src/FffGcodeWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index de322d3679..ae03dfb305 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -3417,7 +3417,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer size_t infill_density_multiplier = 1; if (gcode_layer.getLayerNr() <= 0) { - infill_density_multiplier = infill_extruder.settings_.get("support_infill_density_multiplier_layer_0"); + infill_density_multiplier = infill_extruder.settings_.get("support_infill_density_multiplier_initial_layer"); } const size_t wall_line_count = infill_extruder.settings_.get("support_wall_count"); From 1fdb9f72f0fa7c1e4398de2a3b96ade5fb35793b Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 26 Jun 2024 08:51:21 +0200 Subject: [PATCH 14/14] Fix wrong support infill in some cases support_line_distance with a value of 0 actually means no infill, which was currently interpreted with infinitely dense infill. CURA-11947 --- src/FffGcodeWriter.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index ae03dfb305..ae7c7c2b07 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -3549,8 +3549,11 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer = (part.custom_line_distance_ > 0 ? part.custom_line_distance_ : default_support_line_distance * density_factor); // the highest density infill combines with the next to create a grid with density_factor 1 - support_line_distance_here /= (1 << (infill_density_multiplier - 1)); - support_line_distance_here = std::max(support_line_distance_here, support_line_width); + if (support_line_distance_here != 0 && infill_density_multiplier > 1) + { + support_line_distance_here /= (1 << (infill_density_multiplier - 1)); + support_line_distance_here = std::max(support_line_distance_here, support_line_width); + } const int support_shift = support_line_distance_here / 2; if (part.custom_line_distance_ == 0 && (density_idx == max_density_idx || support_pattern == EFillMethod::CROSS || support_pattern == EFillMethod::CROSS_3D)) {