From 3f771a788b92b9ce3a437d90e5207907ab0fe320 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 24 Oct 2024 10:28:12 +0200 Subject: [PATCH 01/13] Fix thin strips of infill missing. For a previous fix (see ticket CURA-11597 for the support issues fixed --doubling up lines of support-- and the related github discussion Cura/issues/18924 for the infill issues fixed --extra dots of infill at the edges--) we did some morpholigical operations to attempt to make the output more smooth. This caused more problems than its worth, and was in fact already removed in the original PR w.r.t. support (see commit eeec9636f7b3f749b790a1bea4c2901196cee027 ) -- seems we (read I) forgot to remove it for the infill case as well. part of CURA-12068 (or a belated contribution to CURA-11597). --- src/skin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skin.cpp b/src/skin.cpp index 351290be93..9d3f56db2c 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -530,7 +530,7 @@ void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh) std::vector& infill_area_per_combine_current_density = part.infill_area_per_combine_per_density.back(); const Shape more_dense_infill = infill_area.difference(less_dense_infill); infill_area_per_combine_current_density.push_back( - simplifier.polygon(more_dense_infill.difference(sum_more_dense).offset(-infill_wall_width).offset(infill_wall_width))); + simplifier.polygon(more_dense_infill.difference(sum_more_dense))); if (is_connected) { sum_more_dense = sum_more_dense.unionPolygons(more_dense_infill); @@ -538,7 +538,7 @@ void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh) } part.infill_area_per_combine_per_density.emplace_back(); std::vector& infill_area_per_combine_current_density = part.infill_area_per_combine_per_density.back(); - infill_area_per_combine_current_density.push_back(simplifier.polygon(infill_area.difference(sum_more_dense).offset(-infill_wall_width).offset(infill_wall_width))); + infill_area_per_combine_current_density.push_back(simplifier.polygon(infill_area.difference(sum_more_dense))); part.infill_area_own = std::nullopt; // clear infill_area_own, it's not needed any more. assert(! part.infill_area_per_combine_per_density.empty() && "infill_area_per_combine_per_density is now initialized"); } From c0d91c9a41c68487fca32d44184ca4b03838aca2 Mon Sep 17 00:00:00 2001 From: rburema Date: Thu, 24 Oct 2024 08:32:56 +0000 Subject: [PATCH 02/13] Applied clang-format. --- src/TreeSupport.cpp | 8 ++++---- src/skin.cpp | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/TreeSupport.cpp b/src/TreeSupport.cpp index 8268bc2e9c..77e7acdd19 100644 --- a/src/TreeSupport.cpp +++ b/src/TreeSupport.cpp @@ -2037,10 +2037,11 @@ void TreeSupport::filterFloatingLines(std::vector& support_layer_storage) { AABB hole_aabb = AABB(hole); hole_aabb.expand(EPSILON); - if(hole.size() > 1) + if (hole.size() > 1) { // The hole contains other branches! It can not be fully removed. - // This may not fully handle this case as there could be a situation where such a hole becomes invalid, but for now this is the best solution not requiring larger changes. + // This may not fully handle this case as there could be a situation where such a hole becomes invalid, but for now this is the best solution not requiring + // larger changes. holes_resting_outside[layer_idx].emplace(idx); } else if (! hole.intersection(PolygonUtils::clipPolygonWithAABB(outer_walls, hole_aabb)).empty()) @@ -2057,8 +2058,7 @@ void TreeSupport::filterFloatingLines(std::vector& support_layer_storage) for (auto [idx2, hole2] : holeparts[layer_idx - 1] | ranges::views::enumerate) { // TODO should technically be outline: Check if this is fine either way as it would save an offset - if (hole_aabb.hit(AABB(hole2)) - && ! hole.intersection(PolygonUtils::clipPolygonWithAABB(hole2, hole_aabb)).empty()) + if (hole_aabb.hit(AABB(hole2)) && ! hole.intersection(PolygonUtils::clipPolygonWithAABB(hole2, hole_aabb)).empty()) { hole_rest_map[layer_idx][idx].emplace_back(idx2); } diff --git a/src/skin.cpp b/src/skin.cpp index 9d3f56db2c..894692c815 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -529,8 +529,7 @@ void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh) part.infill_area_per_combine_per_density.emplace_back(); std::vector& infill_area_per_combine_current_density = part.infill_area_per_combine_per_density.back(); const Shape more_dense_infill = infill_area.difference(less_dense_infill); - infill_area_per_combine_current_density.push_back( - simplifier.polygon(more_dense_infill.difference(sum_more_dense))); + infill_area_per_combine_current_density.push_back(simplifier.polygon(more_dense_infill.difference(sum_more_dense))); if (is_connected) { sum_more_dense = sum_more_dense.unionPolygons(more_dense_infill); From 893ad91048c0cf43972d5c9c26798697b785dda9 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 28 Oct 2024 14:42:58 +0100 Subject: [PATCH 03/13] Apply scarf seam and speed gradient in surface mode CURA-12176 The addSplitWall method is now a template so that it can handle either ExtrusionLine or Polygon objects. It also takes a function as parameter because the way we add extrusion lines is not the same for surface mode and normal mode. In order to simplify this function, I added a PathAdapter class to work with different types of paths with more transparency. --- CMakeLists.txt | 1 + include/LayerPlan.h | 88 +++++++++++--- src/FffGcodeWriter.cpp | 46 +++++-- src/LayerPlan.cpp | 269 +++++++++++++++++++++++++++++------------ src/TopSurface.cpp | 2 +- 5 files changed, 297 insertions(+), 109 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index daf6022fbb..47581ceca4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,6 +63,7 @@ set(engine_SRCS # Except main.cpp. src/Mold.cpp src/multiVolumes.cpp src/path_ordering.cpp + src/PathAdapter.cpp src/Preheat.cpp src/PrimeTower/PrimeTower.cpp src/PrimeTower/PrimeTowerNormal.cpp diff --git a/include/LayerPlan.h b/include/LayerPlan.h index 0be204faf2..b2b207d3be 100644 --- a/include/LayerPlan.h +++ b/include/LayerPlan.h @@ -38,6 +38,9 @@ class Comb; class SliceDataStorage; class LayerPlanBuffer; +template +class PathAdapter; + /*! * The LayerPlan class stores multiple moves that are planned. * @@ -398,11 +401,15 @@ class LayerPlan : public NoCopy const Polygon& polygon, int startIdx, const bool reverse, + const Settings& settings, const GCodePathConfig& config, coord_t wall_0_wipe_dist = 0, bool spiralize = false, const Ratio& flow_ratio = 1.0_r, - bool always_retract = false); + bool always_retract = false, + bool scarf_seam = false, + bool smooth_speed = false, + bool is_candidate_small_feature = false); /*! * Add polygons to the gcode with optimized order. @@ -435,13 +442,16 @@ class LayerPlan : public NoCopy void addPolygonsByOptimizer( const Shape& polygons, const GCodePathConfig& config, + const Settings& settings, const ZSeamConfig& z_seam_config = ZSeamConfig(), coord_t wall_0_wipe_dist = 0, bool spiralize = false, const Ratio flow_ratio = 1.0_r, bool always_retract = false, bool reverse_order = false, - const std::optional start_near_location = std::optional()); + const std::optional start_near_location = std::optional(), + bool scarf_seam = false, + bool smooth_acceleration = false); /*! * Add a single line that is part of a wall to the gcode. @@ -836,18 +846,15 @@ class LayerPlan : public NoCopy /*! * \brief Add a wall to the gcode with optimized order, but split into pieces in order to facilitate the scarf seam and/or speed gradient. + * \tparam PathType The type of path to be processed, either ExtrusionLine or some subclass of Polyline * \param wall The full wall to be added * \param wall_length The pre-calculated full wall length * \param start_idx The index of the point where to start printing the wall * \param direction The direction along which to print the wall, which should be 1 or -1 * \param max_index The last index to be used when iterating over the wall segments - * \param settings The settings which should apply to this wall added to the layer plan * \param default_config The config with which to print the wall lines that are not spanning a bridge or are exposed to air - * \param roofing_config The config with which to print the wall lines that are exposed to air - * \param bridge_config The config with which to print the wall lines that are spanning a bridge * \param flow_ratio The ratio with which to multiply the extrusion amount - * \param line_width_ratio The line width ratio to be applied - * \param non_bridge_line_volume A pseudo-volume that is derived from the print speed and flow of the non-bridge lines that have preceded this lin + * \param nominal_line_width The nominal line width for the wall * \param min_bridge_line_len The minimum line width to allow an extrusion move to be processed as a bridge move * \param always_retract Whether to force a retraction when moving to the start of the polygon (used for outer walls) * \param is_small_feature Indicates whether the wall is so small that it should be processed differently @@ -864,26 +871,26 @@ class LayerPlan : public NoCopy * \param end_speed_ratio The ratio of the top speed to be applied when finishing a segment * \param decelerate_length The pre-calculated length of the deceleration phase * \param is_scarf_closure Indicates whether this function is called to make the scarf closure (overlap over the first scarf pass) or the normal first pass of the wall + * \param compute_distance_to_bridge_start Whether we should compute the distance to start of bridge. This is + * possible only if PathType is ExtrusionLine and will be ignored otherwise. + * \param func_add_segment The function to be called to actually add an extrusion segment with the given parameters */ + template void addSplitWall( - const ExtrusionLine& wall, + const PathAdapter& wall, const coord_t wall_length, - size_t start_idx, - const int direction, + const size_t start_idx, const size_t max_index, - const Settings& settings, + const int direction, const GCodePathConfig& default_config, - const GCodePathConfig& roofing_config, - const GCodePathConfig& bridge_config, - const double flow_ratio, - const Ratio line_width_ratio, - double& non_bridge_line_volume, - const coord_t min_bridge_line_len, const bool always_retract, const bool is_small_feature, Ratio small_feature_speed_factor, const coord_t max_area_deviation, const auto max_resolution, + const double flow_ratio, + const coord_t nominal_line_width, + const coord_t min_bridge_line_len, const auto scarf_seam_length, const auto scarf_seam_start_ratio, const auto scarf_split_distance, @@ -893,7 +900,52 @@ class LayerPlan : public NoCopy const coord_t accelerate_length, const Ratio end_speed_ratio, const coord_t decelerate_length, - const bool is_scarf_closure); + const bool is_scarf_closure, + const bool compute_distance_to_bridge_start, + const std::function& func_add_segment); + + /*! + * \brief Add a wall to the gcode with optimized order, possibly adding a scarf seam / speed gradient according to settings + * \tparam PathType The type of path to be processed, either ExtrusionLine or some subclass of Polyline + * \param wall The full wall to be added + * \param start_idx The index of the point where to start printing the wall + * \param settings The settings which should apply to this wall added to the layer plan + * \param default_config The config with which to print the wall lines that are not spanning a bridge or are exposed to air + * \param flow_ratio The ratio with which to multiply the extrusion amount + * \param always_retract Whether to force a retraction when moving to the start of the polygon (used for outer walls) + * \param is_closed Indicates whether the path is closed (or open) + * \param is_reversed Indicates if the path is to be processed backwards + * \param is_candidate_small_feature Indicates whether the path should be tested for being treated as a smell feature + * \param scarf_seam Indicates whether we may set a scraf seam to the path + * \param smooth_speed Indicates whether we may set a speed gradient to the path + * \param func_add_segment The function to be called to actually add an extrusion segment with the given parameters + */ + template + void addWallWithScarfSeam( + const PathAdapter& wall, + size_t start_idx, + const Settings& settings, + const GCodePathConfig& default_config, + const double flow_ratio, + bool always_retract, + const bool is_closed, + const bool is_reversed, + const bool is_candidate_small_feature, + const bool scarf_seam, + const bool smooth_speed, + const std::function& func_add_segment); /*! * \brief Helper function to calculate the distance from the start of the current wall line to the first bridge segment diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index fcba3b052b..a8642cf95c 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -735,6 +735,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) gcode_layer.addPolygonsByOptimizer( raft_polygons, gcode_layer.configs_storage_.raft_base_config, + mesh_group_settings, ZSeamConfig(), wipe_dist, spiralize, @@ -895,6 +896,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) gcode_layer.addPolygonsByOptimizer( raft_polygons, gcode_layer.configs_storage_.raft_interface_config, + mesh_group_settings, ZSeamConfig(), wipe_dist, spiralize, @@ -1073,6 +1075,7 @@ void FffGcodeWriter::processRaft(const SliceDataStorage& storage) gcode_layer.addPolygonsByOptimizer( raft_polygons, gcode_layer.configs_storage_.raft_surface_config, + mesh_group_settings, ZSeamConfig(), wipe_dist, spiralize, @@ -1477,13 +1480,14 @@ void FffGcodeWriter::processSkirtBrim(const SliceDataStorage& storage, LayerPlan void FffGcodeWriter::processOozeShield(const SliceDataStorage& storage, LayerPlan& gcode_layer) const { LayerIndex layer_nr = std::max(LayerIndex{ 0 }, gcode_layer.getLayerNr()); - if (layer_nr == 0 && Application::getInstance().current_slice_->scene.current_mesh_group->settings.get("adhesion_type") == EPlatformAdhesion::BRIM) + const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings; + if (layer_nr == 0 && mesh_group_settings.get("adhesion_type") == EPlatformAdhesion::BRIM) { return; // ooze shield already generated by brim } if (storage.ooze_shield.size() > 0 && layer_nr < storage.ooze_shield.size()) { - gcode_layer.addPolygonsByOptimizer(storage.ooze_shield[layer_nr], gcode_layer.configs_storage_.skirt_brim_config_per_extruder[0]); + gcode_layer.addPolygonsByOptimizer(storage.ooze_shield[layer_nr], gcode_layer.configs_storage_.skirt_brim_config_per_extruder[0], mesh_group_settings); } } @@ -1516,7 +1520,7 @@ void FffGcodeWriter::processDraftShield(const SliceDataStorage& storage, LayerPl } } - gcode_layer.addPolygonsByOptimizer(storage.draft_protection_shield, gcode_layer.configs_storage_.skirt_brim_config_per_extruder[0]); + gcode_layer.addPolygonsByOptimizer(storage.draft_protection_shield, gcode_layer.configs_storage_.skirt_brim_config_per_extruder[0], mesh_group_settings); } void FffGcodeWriter::calculateExtruderOrderPerLayer(const SliceDataStorage& storage) @@ -1723,7 +1727,26 @@ void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(const SliceMeshStorage& mesh.settings.get("z_seam_corner"), mesh.settings.get("wall_line_width_0") * 2); const bool spiralize = Application::getInstance().current_slice_->scene.current_mesh_group->settings.get("magic_spiralize"); - gcode_layer.addPolygonsByOptimizer(polygons, mesh_config.inset0_config, z_seam_config, mesh.settings.get("wall_0_wipe_dist"), spiralize); + constexpr Ratio flow_ratio = 1.0; + constexpr bool always_retract = false; + constexpr bool reverse_order = false; + constexpr std::optional start_near_location = std::nullopt; + constexpr bool scarf_seam = true; + constexpr bool smooth_speed = true; + + gcode_layer.addPolygonsByOptimizer( + polygons, + mesh_config.inset0_config, + mesh.settings, + z_seam_config, + mesh.settings.get("wall_0_wipe_dist"), + spiralize, + flow_ratio, + always_retract, + reverse_order, + start_near_location, + scarf_seam, + smooth_speed); addMeshOpenPolyLinesToGCode(mesh, mesh_config, gcode_layer); } @@ -1966,7 +1989,7 @@ bool FffGcodeWriter::processMultiLayerInfill( { constexpr bool force_comb_retract = false; gcode_layer.addTravel(infill_polygons[0][0], force_comb_retract); - gcode_layer.addPolygonsByOptimizer(infill_polygons, mesh_config.infill_config[combine_idx]); + gcode_layer.addPolygonsByOptimizer(infill_polygons, mesh_config.infill_config[combine_idx], mesh.settings); } if (! infill_lines.empty()) @@ -2723,7 +2746,7 @@ bool FffGcodeWriter::processSingleLayerInfill( constexpr bool force_comb_retract = false; // start the infill polygons at the nearest vertex to the current location gcode_layer.addTravel(PolygonUtils::findNearestVert(gcode_layer.getLastPlannedPositionOrStartingPosition(), infill_polygons).p(), force_comb_retract); - gcode_layer.addPolygonsByOptimizer(infill_polygons, mesh_config.infill_config[0], ZSeamConfig(), 0, false, 1.0_r, false, false, near_start_location); + gcode_layer.addPolygonsByOptimizer(infill_polygons, mesh_config.infill_config[0], mesh.settings, ZSeamConfig(), 0, false, 1.0_r, false, false, near_start_location); } const bool enable_travel_optimization = mesh.settings.get("infill_enable_travel_optimization"); if (pattern == EFillMethod::GRID || pattern == EFillMethod::LINES || pattern == EFillMethod::TRIANGLES || pattern == EFillMethod::CUBIC @@ -2965,7 +2988,7 @@ bool FffGcodeWriter::processInsets( gcode_layer.addTravel(spiral_inset[spiral_start_vertex]); } int wall_0_wipe_dist(0); - gcode_layer.addPolygonsByOptimizer(part.spiral_wall, mesh_config.inset0_config, ZSeamConfig(), wall_0_wipe_dist); + gcode_layer.addPolygonsByOptimizer(part.spiral_wall, mesh_config.inset0_config, mesh.settings, ZSeamConfig(), wall_0_wipe_dist); } } // for non-spiralized layers, determine the shape of the unsupported areas below this part @@ -3596,7 +3619,7 @@ void FffGcodeWriter::processSkinPrintFeature( { constexpr bool force_comb_retract = false; gcode_layer.addTravel(skin_polygons[0][0], force_comb_retract); - gcode_layer.addPolygonsByOptimizer(skin_polygons, config); + gcode_layer.addPolygonsByOptimizer(skin_polygons, config, mesh.settings); } if (monotonic) @@ -4001,6 +4024,7 @@ bool FffGcodeWriter::processSupportInfill(const SliceDataStorage& storage, Layer gcode_layer.addPolygonsByOptimizer( support_polygons, configs[combine_idx], + mesh_group_settings, z_seam_config, wall_0_wipe_dist, spiralize, @@ -4167,13 +4191,13 @@ bool FffGcodeWriter::addSupportRoofsToGCode(const SliceDataStorage& storage, con gcode_layer.setIsInside(false); // going to print stuff outside print object, i.e. support if (gcode_layer.getLayerNr() == 0) { - gcode_layer.addPolygonsByOptimizer(wall, current_roof_config); + gcode_layer.addPolygonsByOptimizer(wall, current_roof_config, roof_extruder.settings_); } if (! roof_polygons.empty()) { constexpr bool force_comb_retract = false; gcode_layer.addTravel(roof_polygons[0][0], force_comb_retract); - gcode_layer.addPolygonsByOptimizer(roof_polygons, current_roof_config); + gcode_layer.addPolygonsByOptimizer(roof_polygons, current_roof_config, roof_extruder.settings_); } if (! roof_paths.empty()) { @@ -4287,7 +4311,7 @@ bool FffGcodeWriter::addSupportBottomsToGCode(const SliceDataStorage& storage, L { constexpr bool force_comb_retract = false; gcode_layer.addTravel(bottom_polygons[0][0], force_comb_retract); - gcode_layer.addPolygonsByOptimizer(bottom_polygons, gcode_layer.configs_storage_.support_bottom_config); + gcode_layer.addPolygonsByOptimizer(bottom_polygons, gcode_layer.configs_storage_.support_bottom_config, bottom_extruder.settings_); } if (! bottom_paths.empty()) { diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp index 2b17229c36..c7467bf5fe 100644 --- a/src/LayerPlan.cpp +++ b/src/LayerPlan.cpp @@ -14,6 +14,7 @@ #include "Application.h" //To communicate layer view data. #include "ExtruderTrain.h" +#include "PathAdapter.h" #include "PathOrderMonotonic.h" //Monotonic ordering of skin lines. #include "Slice.h" #include "WipeScriptConfig.h" @@ -557,29 +558,54 @@ void LayerPlan::addPolygon( const Polygon& polygon, int start_idx, const bool backwards, + const Settings& settings, const GCodePathConfig& config, coord_t wall_0_wipe_dist, bool spiralize, const Ratio& flow_ratio, - bool always_retract) + bool always_retract, + bool scarf_seam, + bool smooth_speed, + bool is_candidate_small_feature) { - constexpr Ratio width_ratio = 1.0_r; // Not printed with variable line width. + constexpr bool is_closed = true; + Point2LL p0 = polygon[start_idx]; addTravel(p0, always_retract, config.z_offset); - const int direction = backwards ? -1 : 1; - for (size_t point_idx = 1; point_idx < polygon.size(); point_idx++) - { - Point2LL p1 = polygon[(start_idx + point_idx * direction + polygon.size()) % polygon.size()]; - addExtrusionMove(p1, config, SpaceFillType::Polygons, flow_ratio, width_ratio, spiralize); - p0 = p1; - } + + addWallWithScarfSeam( + PathAdapter(polygon, config.getLineWidth()), + start_idx, + settings, + config, + flow_ratio, + always_retract, + is_closed, + backwards, + is_candidate_small_feature, + scarf_seam, + smooth_speed, + [this, &config, &spiralize]( + const Point3LL& /*start*/, + const Point3LL& end, + const Ratio& speed_factor, + const Ratio& actual_flow_ratio, + const Ratio& line_width_ratio, + const coord_t /*distance_to_bridge_start*/) + { + constexpr double fan_speed = GCodePathConfig::FAN_SPEED_DEFAULT; + constexpr bool travel_to_z = false; + + addExtrusionMove(end, config, SpaceFillType::Polygons, actual_flow_ratio, line_width_ratio, spiralize, speed_factor, fan_speed, travel_to_z); + }); + + if (polygon.size() > 2) { - addExtrusionMove(polygon[start_idx], config, SpaceFillType::Polygons, flow_ratio, width_ratio, spiralize); - if (wall_0_wipe_dist > 0) { // apply outer wall wipe p0 = polygon[start_idx]; + const int direction = backwards ? -1 : 1; int distance_traversed = 0; for (size_t point_idx = 1;; point_idx++) { @@ -611,13 +637,16 @@ void LayerPlan::addPolygon( void LayerPlan::addPolygonsByOptimizer( const Shape& polygons, const GCodePathConfig& config, + const Settings& settings, const ZSeamConfig& z_seam_config, coord_t wall_0_wipe_dist, bool spiralize, const Ratio flow_ratio, bool always_retract, bool reverse_order, - const std::optional start_near_location) + const std::optional start_near_location, + bool scarf_seam, + bool smooth_speed) { if (polygons.empty()) { @@ -630,20 +659,33 @@ void LayerPlan::addPolygonsByOptimizer( } orderOptimizer.optimize(); - if (! reverse_order) + auto add_polygons + = [this, &config, &settings, &wall_0_wipe_dist, &spiralize, &flow_ratio, &always_retract, &scarf_seam, &smooth_speed](const auto& iterator_begin, const auto& iterator_end) { - for (const PathOrdering& path : orderOptimizer.paths_) + for (auto iterator = iterator_begin; iterator != iterator_end; ++iterator) { - addPolygon(*path.vertices_, path.start_vertex_, path.backwards_, config, wall_0_wipe_dist, spiralize, flow_ratio, always_retract); + addPolygon( + *iterator->vertices_, + iterator->start_vertex_, + iterator->backwards_, + settings, + config, + wall_0_wipe_dist, + spiralize, + flow_ratio, + always_retract, + scarf_seam, + smooth_speed); } + }; + + if (! reverse_order) + { + add_polygons(orderOptimizer.paths_.begin(), orderOptimizer.paths_.end()); } else { - for (int index = orderOptimizer.paths_.size() - 1; index >= 0; --index) - { - const PathOrdering& path = orderOptimizer.paths_[index]; - addPolygon(*path.vertices_, path.start_vertex_, path.backwards_, config, wall_0_wipe_dist, spiralize, flow_ratio, always_retract); - } + add_polygons(orderOptimizer.paths_.rbegin(), orderOptimizer.paths_.rend()); } } @@ -865,7 +907,7 @@ void LayerPlan::addWallLine( flow, width_factor, spiralize, - segmentIsOnOverhang(p0, p1) ? overhang_speed_factor : 1.0_r, + segmentIsOnOverhang(p0, p1) ? overhang_speed_factor : speed_factor, GCodePathConfig::FAN_SPEED_DEFAULT, travel_to_z); } @@ -996,25 +1038,22 @@ void LayerPlan::addWall( addWall(ewall, start_idx, settings, default_config, roofing_config, bridge_config, wall_0_wipe_dist, flow_ratio, always_retract, is_closed, is_reversed, is_linked_path); } +template void LayerPlan::addSplitWall( - const ExtrusionLine& wall, + const PathAdapter& wall, const coord_t wall_length, - size_t start_idx, - const int direction, + const size_t start_idx, const size_t max_index, - const Settings& settings, + const int direction, const GCodePathConfig& default_config, - const GCodePathConfig& roofing_config, - const GCodePathConfig& bridge_config, - const double flow_ratio, - const Ratio line_width_ratio, - double& non_bridge_line_volume, - const coord_t min_bridge_line_len, const bool always_retract, const bool is_small_feature, Ratio small_feature_speed_factor, const coord_t max_area_deviation, const auto max_resolution, + const double flow_ratio, + const coord_t nominal_line_width, + const coord_t min_bridge_line_len, const auto scarf_seam_length, const auto scarf_seam_start_ratio, const auto scarf_split_distance, @@ -1024,13 +1063,22 @@ void LayerPlan::addSplitWall( const coord_t accelerate_length, const Ratio end_speed_ratio, const coord_t decelerate_length, - const bool is_scarf_closure) + const bool is_scarf_closure, + const bool compute_distance_to_bridge_start, + const std::function& func_add_segment) { coord_t distance_to_bridge_start = 0; // will be updated before each line is processed - ExtrusionJunction p0 = wall[start_idx]; + Point2LL p0 = wall.pointAt(start_idx); + coord_t w0 = wall.lineWidthAt(start_idx); bool first_line = ! is_scarf_closure; bool first_split = ! is_scarf_closure; - Point3LL split_origin = p0.p_; + Point3LL split_origin = p0; if (! is_scarf_closure && scarf_seam_length > 0) { split_origin.z_ = scarf_max_z_offset; @@ -1044,16 +1092,21 @@ void LayerPlan::addSplitWall( for (size_t point_idx = 1; point_idx < max_index; point_idx++) { - const ExtrusionJunction& p1 = wall[(wall.size() + start_idx + point_idx * direction) % wall.size()]; + const size_t actual_point_index = (wall.size() + start_idx + point_idx * direction) % wall.size(); + const Point2LL& p1 = wall.pointAt(actual_point_index); + const coord_t w1 = wall.lineWidthAt(actual_point_index); - if (! bridge_wall_mask_.empty()) + if constexpr (std::is_same_v) { - distance_to_bridge_start = computeDistanceToBridgeStart(wall, (wall.size() + start_idx + point_idx * direction - 1) % wall.size(), min_bridge_line_len); + if (compute_distance_to_bridge_start && ! bridge_wall_mask_.empty()) + { + distance_to_bridge_start = computeDistanceToBridgeStart(wall.getPath(), (wall.size() + start_idx + point_idx * direction - 1) % wall.size(), min_bridge_line_len); + } } if (first_line) { - addTravel(p0.p_, always_retract); + addTravel(p0, always_retract); first_line = false; } @@ -1069,8 +1122,8 @@ void LayerPlan::addSplitWall( pieces we'd want to get low enough deviation, then check if each piece is not too short at the end. */ - const coord_t delta_line_width = p1.w_ - p0.w_; - const Point2LL line_vector = p1.p_ - p0.p_; + const coord_t delta_line_width = w1 - w0; + const Point2LL line_vector = p1 - p0; const coord_t line_length = vSize(line_vector); /* Calculate how much the line would deviate from the trapezoidal shape if printed at average width. @@ -1091,12 +1144,13 @@ void LayerPlan::addSplitWall( const double average_progress = (double(piece) + 0.5) / pieces; // How far along this line to sample the line width in the middle of this piece. // Round the line_width value to overcome floating point rounding issues, otherwise we may end up with slightly different values // and the generated GCodePath objects will not be merged together, which some subsequent algorithms rely on (e.g. coasting) - const coord_t line_width = std::lrint(static_cast(p0.w_) + average_progress * static_cast(delta_line_width)); - const Point2LL destination = p0.p_ + normal(line_vector, piece_length * (piece + 1)); + const coord_t line_width = std::lrint(static_cast(w0) + average_progress * static_cast(delta_line_width)); + const Ratio line_width_ratio = static_cast(line_width) / nominal_line_width; + const Point2LL destination = p0 + normal(line_vector, piece_length * (piece + 1)); if (is_small_feature && ! is_scarf_closure) { constexpr bool spiralize = false; - addExtrusionMove(destination, default_config, SpaceFillType::Polygons, flow_ratio, line_width * line_width_ratio, spiralize, small_feature_speed_factor); + addExtrusionMove(destination, default_config, SpaceFillType::Polygons, flow_ratio, line_width_ratio, spiralize, small_feature_speed_factor); } else { @@ -1170,7 +1224,7 @@ void LayerPlan::addSplitWall( if (first_split) { // Manually add a Z-only travel move to set the nozzle at the height of the first point - addTravel(p0.p_, always_retract, split_origin.z_); + addTravel(p0, always_retract, split_origin.z_); first_split = false; } } @@ -1198,20 +1252,13 @@ void LayerPlan::addSplitWall( } // now add the (sub-)segment - constexpr bool travel_to_z = false; - addWallLine( + func_add_segment( split_origin, split_destination, - settings, - default_config, - roofing_config, - bridge_config, - flow_ratio * scarf_segment_flow_ratio, - line_width * line_width_ratio, - non_bridge_line_volume, accelerate_speed_factor * decelerate_speed_factor, - distance_to_bridge_start, - travel_to_z); + flow_ratio * scarf_segment_flow_ratio, + line_width_ratio, + distance_to_bridge_start); wall_processed_distance = destination_position; piece_remaining_distance -= length_to_process; @@ -1308,39 +1355,41 @@ coord_t LayerPlan::computeDistanceToBridgeStart(const ExtrusionLine& wall, const return distance_to_bridge_start; } -void LayerPlan::addWall( - const ExtrusionLine& wall, +template +void LayerPlan::addWallWithScarfSeam( + const PathAdapter& wall, size_t start_idx, const Settings& settings, const GCodePathConfig& default_config, - const GCodePathConfig& roofing_config, - const GCodePathConfig& bridge_config, - coord_t wall_0_wipe_dist, const double flow_ratio, bool always_retract, const bool is_closed, const bool is_reversed, - const bool is_linked_path, + const bool is_candidate_small_feature, const bool scarf_seam, - const bool smooth_speed) + const bool smooth_speed, + const std::function& func_add_segment) { if (wall.empty()) { return; } - const bool actual_scarf_seam = scarf_seam && is_closed; - double non_bridge_line_volume = max_non_bridge_line_volume; // assume extruder is fully pressurised before first non-bridge line is output + const bool actual_scarf_seam = scarf_seam && is_closed; const coord_t min_bridge_line_len = settings.get("bridge_wall_min_length"); - const Ratio nominal_line_width_multiplier{ - 1.0 / Ratio{ static_cast(default_config.getLineWidth()) } - }; // we multiply the flow with the actual wanted line width (for that junction), and then multiply with this + const coord_t nominal_line_width = default_config.getLineWidth(); const coord_t wall_length = wall.length(); const coord_t small_feature_max_length = settings.get("small_feature_max_length"); - const bool is_small_feature = (small_feature_max_length > 0) && (layer_nr_ == 0 || wall.inset_idx_ == 0) && wall_length < small_feature_max_length; + const bool is_small_feature = (small_feature_max_length > 0) && (layer_nr_ == 0 || is_candidate_small_feature) && wall_length < small_feature_max_length; const Velocity min_speed = fan_speed_layer_time_settings_per_extruder_[getLastPlannedExtruderTrain()->extruder_nr_].cool_min_speed; Ratio small_feature_speed_factor = settings.get((layer_nr_ == 0) ? "small_feature_speed_factor_0" : "small_feature_speed_factor"); small_feature_speed_factor = std::max(static_cast(small_feature_speed_factor), static_cast(min_speed / default_config.getSpeed())); @@ -1368,25 +1417,23 @@ void LayerPlan::addWall( auto addSplitWallPass = [&](bool is_scarf_closure) { + constexpr bool compute_distance_to_bridge_start = true; + addSplitWall( - wall, + PathAdapter(wall), wall_length, start_idx, - direction, max_index, - settings, + direction, default_config, - roofing_config, - bridge_config, - flow_ratio, - nominal_line_width_multiplier, - non_bridge_line_volume, - min_bridge_line_len, always_retract, is_small_feature, small_feature_speed_factor, max_area_deviation, max_resolution, + flow_ratio, + nominal_line_width, + min_bridge_line_len, layer_nr_ > 0 ? scarf_seam_length : 0, scarf_seam_start_ratio, scarf_split_distance, @@ -1396,7 +1443,9 @@ void LayerPlan::addWall( accelerate_length, end_speed_ratio, decelerate_length, - is_scarf_closure); + is_scarf_closure, + compute_distance_to_bridge_start, + func_add_segment); }; // First pass to add the wall with the scarf beginning and acceleration @@ -1407,6 +1456,68 @@ void LayerPlan::addWall( // Second pass to add the scarf closure addSplitWallPass(true); } +} + +void LayerPlan::addWall( + const ExtrusionLine& wall, + size_t start_idx, + const Settings& settings, + const GCodePathConfig& default_config, + const GCodePathConfig& roofing_config, + const GCodePathConfig& bridge_config, + coord_t wall_0_wipe_dist, + const double flow_ratio, + bool always_retract, + const bool is_closed, + const bool is_reversed, + const bool is_linked_path, + const bool scarf_seam, + const bool smooth_speed) +{ + if (wall.empty()) + { + return; + } + + double non_bridge_line_volume = max_non_bridge_line_volume; // assume extruder is fully pressurised before first non-bridge line is output + const coord_t min_bridge_line_len = settings.get("bridge_wall_min_length"); + + addWallWithScarfSeam( + PathAdapter(wall), + start_idx, + settings, + default_config, + flow_ratio, + always_retract, + is_closed, + is_reversed, + wall.inset_idx_ == 0, + scarf_seam, + smooth_speed, + [this, &settings, &default_config, &roofing_config, &bridge_config, &non_bridge_line_volume]( + const Point3LL& start, + const Point3LL& end, + const Ratio& speed_factor, + const Ratio& actual_flow_ratio, + const Ratio& line_width_ratio, + const coord_t distance_to_bridge_start) + { + constexpr bool travel_to_z = false; + + addWallLine( + start, + end, + settings, + default_config, + roofing_config, + bridge_config, + actual_flow_ratio, + line_width_ratio, + non_bridge_line_volume, + speed_factor, + distance_to_bridge_start, + travel_to_z); + }); if (wall.size() >= 2) { @@ -2381,7 +2492,7 @@ void LayerPlan::writeGCode(GCodeExport& gcode) for (const auto& reversed_chunk : paths | ranges::views::enumerate | ranges::views::reverse | ranges::views::chunk_by( - [](const auto&path_a, const auto&path_b) + [](const auto& path_a, const auto& path_b) { return (! std::get<1>(path_a).isTravelPath()) || std::get<1>(path_b).isTravelPath(); })) diff --git a/src/TopSurface.cpp b/src/TopSurface.cpp index 15a6b03cf8..beb6154d3e 100644 --- a/src/TopSurface.cpp +++ b/src/TopSurface.cpp @@ -124,7 +124,7 @@ bool TopSurface::ironing(const SliceDataStorage& storage, const SliceMeshStorage { constexpr bool force_comb_retract = false; layer.addTravel(ironing_polygons[0][0], force_comb_retract); - layer.addPolygonsByOptimizer(ironing_polygons, line_config, ZSeamConfig()); + layer.addPolygonsByOptimizer(ironing_polygons, line_config, mesh.settings, ZSeamConfig()); added = true; } if (! ironing_lines.empty()) From ca5f958c9fec3a6394deb82429169b55fcf52c2c Mon Sep 17 00:00:00 2001 From: wawanbreton Date: Mon, 28 Oct 2024 13:43:26 +0000 Subject: [PATCH 04/13] Applied clang-format. --- src/LayerPlan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp index c7467bf5fe..66723a14bf 100644 --- a/src/LayerPlan.cpp +++ b/src/LayerPlan.cpp @@ -2492,7 +2492,7 @@ void LayerPlan::writeGCode(GCodeExport& gcode) for (const auto& reversed_chunk : paths | ranges::views::enumerate | ranges::views::reverse | ranges::views::chunk_by( - [](const auto& path_a, const auto& path_b) + [](const auto&path_a, const auto&path_b) { return (! std::get<1>(path_a).isTravelPath()) || std::get<1>(path_b).isTravelPath(); })) From d036c0bb08ddf0fe1c6e9c287ea321374d2a477a Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 28 Oct 2024 15:04:46 +0100 Subject: [PATCH 05/13] Add missing PathAdapter files CURA-12176 --- include/PathAdapter.h | 63 +++++++++++++++++++++++++++++++++++++++++++ src/PathAdapter.cpp | 35 ++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 include/PathAdapter.h create mode 100644 src/PathAdapter.cpp diff --git a/include/PathAdapter.h b/include/PathAdapter.h new file mode 100644 index 0000000000..21a71ee1da --- /dev/null +++ b/include/PathAdapter.h @@ -0,0 +1,63 @@ +// Copyright (c) 2024 Ultimaker B.V. +// CuraEngine is released under the terms of the AGPLv3 or higher. + +#ifndef PATH_ADAPTER_H +#define PATH_ADAPTER_H + +#include + +#include "geometry/Point2LL.h" +#include "utils/Coord_t.h" + +namespace cura +{ + +/* Adapter class to allow extrusion-related functions to work with either an ExtrusionLine or a Polygon */ +template +class PathAdapter +{ +public: + /*! + * \brief Base constructor + * \param path The actual stored path + * \param fixed_line_width The fixed line width in case the stored path doesn't handle information about a variable + * line width. Can be omitted otherwise. + */ + PathAdapter(const PathType& path, coord_t fixed_line_width = 0) + : path_(path) + , fixed_line_width_(fixed_line_width) + { + } + + bool empty() const + { + return path_.empty(); + } + + size_t size() const + { + return path_.size(); + } + + coord_t length() const + { + return path_.length(); + } + + const Point2LL& pointAt(size_t index) const; + + coord_t lineWidthAt(size_t index) const; + + const PathType& getPath() const + { + return path_; + } + +private: + const PathType& path_; + const coord_t fixed_line_width_; +}; + +} // namespace cura + +#endif // PATH_ADAPTER_H diff --git a/src/PathAdapter.cpp b/src/PathAdapter.cpp new file mode 100644 index 0000000000..09a5437493 --- /dev/null +++ b/src/PathAdapter.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2024 Ultimaker B.V. +// CuraEngine is released under the terms of the AGPLv3 or higher. + +#include "PathAdapter.h" + +#include "utils/ExtrusionLine.h" + +namespace cura +{ + +template<> +const Point2LL& PathAdapter::pointAt(size_t index) const +{ + return path_.junctions_.at(index).p_; +} + +template<> +coord_t PathAdapter::lineWidthAt(size_t index) const +{ + return path_.junctions_.at(index).w_; +} + +template<> +const Point2LL& PathAdapter::pointAt(size_t index) const +{ + return path_.at(index); +} + +template<> +coord_t PathAdapter::lineWidthAt(size_t /*index*/) const +{ + return fixed_line_width_; +} + +} // namespace cura From 04262454d1560b98ae1f04a0694c26ac220f3b0c Mon Sep 17 00:00:00 2001 From: saumyaj3 Date: Tue, 29 Oct 2024 10:57:26 +0100 Subject: [PATCH 06/13] Add writeGcodeFile function to GCodeExport Introduce a new method writeGcodeFile to the GCodeExport class, which ensures that the output stream is properly flushed. This function is also called at the end of the Gcode writing process to finalize the file. NP-470 --- include/gcodeExport.h | 2 ++ src/FffGcodeWriter.cpp | 1 + src/gcodeExport.cpp | 5 +++++ 3 files changed, 8 insertions(+) diff --git a/include/gcodeExport.h b/include/gcodeExport.h index 7b211f8516..ee18936e39 100644 --- a/include/gcodeExport.h +++ b/include/gcodeExport.h @@ -409,6 +409,8 @@ class GCodeExport : public NoCopy */ bool needPrimeBlob() const; + void writeGcodeFile(); + private: /*! * Coordinates are build plate coordinates, which might be offsetted when extruder offsets are encoded in the gcode. diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index fcba3b052b..bed6ad7176 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -4437,6 +4437,7 @@ void FffGcodeWriter::finalize() } gcode.writeComment("End of Gcode"); + gcode.writeGcodeFile(); /* the profile string below can be executed since the M25 doesn't end the gcode on an UMO and when printing via USB. gcode.writeCode("M25 ;Stop reading from this point on."); diff --git a/src/gcodeExport.cpp b/src/gcodeExport.cpp index e94c988b78..c93a068115 100644 --- a/src/gcodeExport.cpp +++ b/src/gcodeExport.cpp @@ -1726,9 +1726,14 @@ void GCodeExport::finalize(const char* endCode) for (int n = 1; n < MAX_EXTRUDERS; n++) if (getTotalFilamentUsed(n) > 0) spdlog::info("Filament {}: {}", n + 1, int(getTotalFilamentUsed(n))); +} + +void GCodeExport::writeGcodeFile() +{ output_stream_->flush(); } + double GCodeExport::getExtrudedVolumeAfterLastWipe(size_t extruder) { return eToMm3(extruder_attr_[extruder].last_e_value_after_wipe_, extruder); From b394b7bfcc9658045aaa18e5fcaa736e6d7efbae Mon Sep 17 00:00:00 2001 From: saumyaj3 Date: Tue, 29 Oct 2024 10:59:44 +0100 Subject: [PATCH 07/13] Remove unnecessary blank line NP-470 --- src/gcodeExport.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gcodeExport.cpp b/src/gcodeExport.cpp index c93a068115..b4ac8f1bdd 100644 --- a/src/gcodeExport.cpp +++ b/src/gcodeExport.cpp @@ -1733,7 +1733,6 @@ void GCodeExport::writeGcodeFile() output_stream_->flush(); } - double GCodeExport::getExtrudedVolumeAfterLastWipe(size_t extruder) { return eToMm3(extruder_attr_[extruder].last_e_value_after_wipe_, extruder); From 3bb6d32ec62ce7cd9b67dd607fd32ef25ac0968d Mon Sep 17 00:00:00 2001 From: saumyaj3 Date: Tue, 29 Oct 2024 11:51:02 +0100 Subject: [PATCH 08/13] Refactor writeGcodeFile to flushOutputStream Renamed the function writeGcodeFile to flushOutputStream for clarity. This change more accurately reflects the function's responsibility, which is to flush the output stream instead of managing file writing directly. Updated all references in the source files accordingly. NP-470 --- include/gcodeExport.h | 5 ++++- src/FffGcodeWriter.cpp | 2 +- src/gcodeExport.cpp | 3 ++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/gcodeExport.h b/include/gcodeExport.h index ee18936e39..0dd81541b8 100644 --- a/include/gcodeExport.h +++ b/include/gcodeExport.h @@ -409,7 +409,10 @@ class GCodeExport : public NoCopy */ bool needPrimeBlob() const; - void writeGcodeFile(); + /* + * Function is used to write the content of output_stream to the gcode file + */ + void flushOutputStream(); private: /*! diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index bed6ad7176..2417723014 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -4437,7 +4437,7 @@ void FffGcodeWriter::finalize() } gcode.writeComment("End of Gcode"); - gcode.writeGcodeFile(); + gcode.flushOutputStream(); /* the profile string below can be executed since the M25 doesn't end the gcode on an UMO and when printing via USB. gcode.writeCode("M25 ;Stop reading from this point on."); diff --git a/src/gcodeExport.cpp b/src/gcodeExport.cpp index b4ac8f1bdd..f9749b0d6e 100644 --- a/src/gcodeExport.cpp +++ b/src/gcodeExport.cpp @@ -1726,9 +1726,10 @@ void GCodeExport::finalize(const char* endCode) for (int n = 1; n < MAX_EXTRUDERS; n++) if (getTotalFilamentUsed(n) > 0) spdlog::info("Filament {}: {}", n + 1, int(getTotalFilamentUsed(n))); + flushOutputStream(); } -void GCodeExport::writeGcodeFile() +void GCodeExport::flushOutputStream() { output_stream_->flush(); } From 12491b406a5687fb961b556a8fdf61f1a14a261b Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 29 Oct 2024 15:48:41 +0100 Subject: [PATCH 09/13] Fix Mac build CURA-12176 --- src/FffGcodeWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index a8642cf95c..65eae9c2c2 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -1730,7 +1730,7 @@ void FffGcodeWriter::addMeshLayerToGCode_meshSurfaceMode(const SliceMeshStorage& constexpr Ratio flow_ratio = 1.0; constexpr bool always_retract = false; constexpr bool reverse_order = false; - constexpr std::optional start_near_location = std::nullopt; + const std::optional start_near_location = std::nullopt; constexpr bool scarf_seam = true; constexpr bool smooth_speed = true; From 43d5d2da84973e2d9af69f0a94fcbcaeb307a3ce Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 30 Oct 2024 11:46:41 +0100 Subject: [PATCH 10/13] Fix spiralize mode CURA-12245 This was broken when moving to 3D GCodePath points for the scarf seam --- src/LayerPlan.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp index 2b17229c36..9b07d2d22a 100644 --- a/src/LayerPlan.cpp +++ b/src/LayerPlan.cpp @@ -2381,7 +2381,7 @@ void LayerPlan::writeGCode(GCodeExport& gcode) for (const auto& reversed_chunk : paths | ranges::views::enumerate | ranges::views::reverse | ranges::views::chunk_by( - [](const auto&path_a, const auto&path_b) + [](const auto& path_a, const auto& path_b) { return (! std::get<1>(path_a).isTravelPath()) || std::get<1>(path_b).isTravelPath(); })) @@ -2664,14 +2664,14 @@ void LayerPlan::writeGCode(GCodeExport& gcode) const Point2LL p1 = spiral_path.points[point_idx].toPoint2LL(); length += vSizeMM(p0 - p1); p0 = p1; - gcode.setZ(std::round(z_ + layer_thickness_ * length / totalLength)); + const coord_t z_offset = std::round(layer_thickness_ * length / totalLength); const double extrude_speed = speed * spiral_path.speed_back_pressure_factor; writeExtrusionRelativeZ( gcode, spiral_path.points[point_idx], extrude_speed, - path.z_offset, + path.z_offset + z_offset, spiral_path.getExtrusionMM3perMM(), spiral_path.config.type, update_extrusion_offset); From 9a09cb29c051d328b3e50cba52467702de3b7cf6 Mon Sep 17 00:00:00 2001 From: wawanbreton Date: Wed, 30 Oct 2024 10:58:45 +0000 Subject: [PATCH 11/13] Applied clang-format. --- src/LayerPlan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp index 9b07d2d22a..7d7dc3a2d1 100644 --- a/src/LayerPlan.cpp +++ b/src/LayerPlan.cpp @@ -2381,7 +2381,7 @@ void LayerPlan::writeGCode(GCodeExport& gcode) for (const auto& reversed_chunk : paths | ranges::views::enumerate | ranges::views::reverse | ranges::views::chunk_by( - [](const auto& path_a, const auto& path_b) + [](const auto&path_a, const auto&path_b) { return (! std::get<1>(path_a).isTravelPath()) || std::get<1>(path_b).isTravelPath(); })) From 69c3e42cd04d3a57e2832dda18f9a2def41f9bd5 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Thu, 31 Oct 2024 10:10:16 +0100 Subject: [PATCH 12/13] Apply code cleaning suggestions CURA-12176 --- include/LayerPlan.h | 46 +++++++++++++++++++++++++++------------------ src/LayerPlan.cpp | 30 ++++++++++------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/include/LayerPlan.h b/include/LayerPlan.h index b2b207d3be..dd6ac02c83 100644 --- a/include/LayerPlan.h +++ b/include/LayerPlan.h @@ -396,6 +396,8 @@ class LayerPlan : public NoCopy * \param spiralize Whether to gradually increase the z height from the normal layer height to the height of the next layer over this polygon * \param flow_ratio The ratio with which to multiply the extrusion amount * \param always_retract Whether to force a retraction when moving to the start of the polygon (used for outer walls) + * \param scarf_seam Indicates whether we may use a scarf seam for the path + * \param smooth_speed Indicates whether we may use a speed gradient for the path */ void addPolygon( const Polygon& polygon, @@ -408,8 +410,7 @@ class LayerPlan : public NoCopy const Ratio& flow_ratio = 1.0_r, bool always_retract = false, bool scarf_seam = false, - bool smooth_speed = false, - bool is_candidate_small_feature = false); + bool smooth_speed = false); /*! * Add polygons to the gcode with optimized order. @@ -438,6 +439,8 @@ class LayerPlan : public NoCopy * \param reverse_order Adds polygons in reverse order. * \param start_near_location Start optimising the path near this location. * If unset, this causes it to start near the last planned location. + * \param scarf_seam Indicates whether we may use a scarf seam for the path + * \param smooth_speed Indicates whether we may use a speed gradient for the path */ void addPolygonsByOptimizer( const Shape& polygons, @@ -535,6 +538,8 @@ class LayerPlan : public NoCopy * polyline). * \param is_reversed Whether to print this wall in reverse direction. * \param is_linked_path Whether the path is a continuation off the previous path + * \param scarf_seam Indicates whether we may use a scarf seam for the path + * \param smooth_speed Indicates whether we may use a speed gradient for the path */ void addWall( const ExtrusionLine& wall, @@ -844,6 +849,23 @@ class LayerPlan : public NoCopy PrintFeatureType feature, bool update_extrusion_offset = false); + /*! + * \brief Alias for a function definition that adds an extrusion segment + * \param start The start position of the segment + * \param end The end position of the segment + * \param speed_factor The speed factor to be applied when extruding this specific segment (relative to nominal speed for the entire path) + * \param flow_ratio The flow ratio to be applied when extruding this specific segment (relative to nominal flow for the entire path) + * \param line_width_ratio The line width ratio to be applied when extruding this specific segment (relative to nominal line width for the entire path) + * \param distance_to_bridge_start The calculate distance to the next bridge start, which may be irrelevant in some cases + */ + using AddExtrusionSegmentFunction = std::function; + /*! * \brief Add a wall to the gcode with optimized order, but split into pieces in order to facilitate the scarf seam and/or speed gradient. * \tparam PathType The type of path to be processed, either ExtrusionLine or some subclass of Polyline @@ -902,13 +924,7 @@ class LayerPlan : public NoCopy const coord_t decelerate_length, const bool is_scarf_closure, const bool compute_distance_to_bridge_start, - const std::function& func_add_segment); + const AddExtrusionSegmentFunction& func_add_segment); /*! * \brief Add a wall to the gcode with optimized order, possibly adding a scarf seam / speed gradient according to settings @@ -922,8 +938,8 @@ class LayerPlan : public NoCopy * \param is_closed Indicates whether the path is closed (or open) * \param is_reversed Indicates if the path is to be processed backwards * \param is_candidate_small_feature Indicates whether the path should be tested for being treated as a smell feature - * \param scarf_seam Indicates whether we may set a scraf seam to the path - * \param smooth_speed Indicates whether we may set a speed gradient to the path + * \param scarf_seam Indicates whether we may use a scarf seam for the path + * \param smooth_speed Indicates whether we may use a speed gradient for the path * \param func_add_segment The function to be called to actually add an extrusion segment with the given parameters */ template @@ -939,13 +955,7 @@ class LayerPlan : public NoCopy const bool is_candidate_small_feature, const bool scarf_seam, const bool smooth_speed, - const std::function& func_add_segment); + const AddExtrusionSegmentFunction& func_add_segment); /*! * \brief Helper function to calculate the distance from the start of the current wall line to the first bridge segment diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp index 66723a14bf..7646fbbbee 100644 --- a/src/LayerPlan.cpp +++ b/src/LayerPlan.cpp @@ -565,10 +565,10 @@ void LayerPlan::addPolygon( const Ratio& flow_ratio, bool always_retract, bool scarf_seam, - bool smooth_speed, - bool is_candidate_small_feature) + bool smooth_speed) { constexpr bool is_closed = true; + constexpr bool is_candidate_small_feature = false; Point2LL p0 = polygon[start_idx]; addTravel(p0, always_retract, config.z_offset); @@ -659,7 +659,7 @@ void LayerPlan::addPolygonsByOptimizer( } orderOptimizer.optimize(); - auto add_polygons + const auto add_polygons = [this, &config, &settings, &wall_0_wipe_dist, &spiralize, &flow_ratio, &always_retract, &scarf_seam, &smooth_speed](const auto& iterator_begin, const auto& iterator_end) { for (auto iterator = iterator_begin; iterator != iterator_end; ++iterator) @@ -1065,13 +1065,7 @@ void LayerPlan::addSplitWall( const coord_t decelerate_length, const bool is_scarf_closure, const bool compute_distance_to_bridge_start, - const std::function& func_add_segment) + const AddExtrusionSegmentFunction& func_add_segment) { coord_t distance_to_bridge_start = 0; // will be updated before each line is processed Point2LL p0 = wall.pointAt(start_idx); @@ -1098,6 +1092,9 @@ void LayerPlan::addSplitWall( if constexpr (std::is_same_v) { + // The bridging functionality has not been designed to work with anything else than ExtrusionLine objects, + // and there is no need to do it otherwise yet. So the compute_distance_to_bridge_start argument will + // just be ignored if using an other PathType (e.g. Polygon) if (compute_distance_to_bridge_start && ! bridge_wall_mask_.empty()) { distance_to_bridge_start = computeDistanceToBridgeStart(wall.getPath(), (wall.size() + start_idx + point_idx * direction - 1) % wall.size(), min_bridge_line_len); @@ -1368,13 +1365,7 @@ void LayerPlan::addWallWithScarfSeam( const bool is_candidate_small_feature, const bool scarf_seam, const bool smooth_speed, - const std::function& func_add_segment) + const AddExtrusionSegmentFunction& func_add_segment) { if (wall.empty()) { @@ -1494,8 +1485,7 @@ void LayerPlan::addWall( wall.inset_idx_ == 0, scarf_seam, smooth_speed, - [this, &settings, &default_config, &roofing_config, &bridge_config, &non_bridge_line_volume]( - const Point3LL& start, + [&](const Point3LL& start, const Point3LL& end, const Ratio& speed_factor, const Ratio& actual_flow_ratio, @@ -2492,7 +2482,7 @@ void LayerPlan::writeGCode(GCodeExport& gcode) for (const auto& reversed_chunk : paths | ranges::views::enumerate | ranges::views::reverse | ranges::views::chunk_by( - [](const auto&path_a, const auto&path_b) + [](const auto& path_a, const auto& path_b) { return (! std::get<1>(path_a).isTravelPath()) || std::get<1>(path_b).isTravelPath(); })) From 34af646bd48edde42623cb22b21d3dba11e0d454 Mon Sep 17 00:00:00 2001 From: wawanbreton Date: Thu, 31 Oct 2024 09:10:50 +0000 Subject: [PATCH 13/13] Applied clang-format. --- src/LayerPlan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/LayerPlan.cpp b/src/LayerPlan.cpp index 7646fbbbee..0420da65e2 100644 --- a/src/LayerPlan.cpp +++ b/src/LayerPlan.cpp @@ -2482,7 +2482,7 @@ void LayerPlan::writeGCode(GCodeExport& gcode) for (const auto& reversed_chunk : paths | ranges::views::enumerate | ranges::views::reverse | ranges::views::chunk_by( - [](const auto& path_a, const auto& path_b) + [](const auto&path_a, const auto&path_b) { return (! std::get<1>(path_a).isTravelPath()) || std::get<1>(path_b).isTravelPath(); }))