diff --git a/.github/workflows/gcodeanalyzer.yml b/.github/workflows/gcodeanalyzer.yml index 0b85fb75aa..aa45e74bc2 100644 --- a/.github/workflows/gcodeanalyzer.yml +++ b/.github/workflows/gcodeanalyzer.yml @@ -184,9 +184,13 @@ 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() + match = re.search(r"^real\s+(\d+)m(\d+\.\d+)s", content, re.MULTILINE) + if match: + timer = float(match.group(1)) * 60 + float(match.group(2)) + else: + timer = 0 + frame = GCodeAnalyzer.DataFrame(infilename) line_lengths = frame.gc.extrusions['length'].describe() diff --git a/include/infill.h b/include/infill.h index 081652d68f..89b9bba689 100644 --- a/include/infill.h +++ b/include/infill.h @@ -41,7 +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 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 @@ -219,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/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 }; // ("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; @@ -625,6 +624,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"); + 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; @@ -669,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, @@ -755,9 +755,13 @@ 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"); + 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"); + 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 @@ -825,7 +829,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, @@ -912,9 +916,13 @@ 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"); + 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"); + 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 @@ -988,7 +996,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, @@ -1899,7 +1907,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; @@ -2180,7 +2188,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( @@ -3356,6 +3364,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_initial_layer"); + } + 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"); @@ -3420,7 +3434,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") && layer_nr >= 0) + if (infill_extruder.settings_.get("support_z_seam_away_from_model") && (layer_nr >= 0)) { for (std::shared_ptr mesh_ptr : storage.meshes) { @@ -3482,10 +3496,15 @@ 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 + 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)) { diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp index 172389aaff..1b1e0f6b1c 100644 --- a/src/LayerPlan.cpp +++ b/src/LayerPlan.cpp @@ -265,7 +265,8 @@ bool LayerPlan::setExtruder(const size_t extruder_nr) } if (end_pos_absolute || last_planned_position_) { - addTravel(end_pos); // + extruder_offset cause it + GCodePath& path = addTravel(end_pos); // + extruder_offset cause it + path.retract_for_nozzle_switch = true; } } if (extruder_plans_.back().paths_.empty() && extruder_plans_.back().inserts_.empty()) @@ -2205,6 +2206,12 @@ void LayerPlan::writeGCode(GCodeExport& gcode) { retraction_config = path.mesh ? &path.mesh->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/infill.cpp b/src/infill.cpp index a2d931d262..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,9 +96,11 @@ 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(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 // that will be filled with the pattern. This split of regions is not needed if the 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(), 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() 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") } }) 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);