From ba6ebd66e4e864246b44004d89fd7b9918cf8ade Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 29 Mar 2024 14:06:28 +0100 Subject: [PATCH 01/15] Make prime tower only prime the used extruders CURA-11717 --- include/FffGcodeWriter.h | 4 ++- include/PrimeTower.h | 8 +++-- src/FffGcodeWriter.cpp | 13 ++++++--- src/FffPolygonGenerator.cpp | 2 ++ src/PrimeTower.cpp | 58 ++++++++++++++++++++----------------- 5 files changed, 50 insertions(+), 35 deletions(-) diff --git a/include/FffGcodeWriter.h b/include/FffGcodeWriter.h index 4c4061c37b..251712c8fc 100644 --- a/include/FffGcodeWriter.h +++ b/include/FffGcodeWriter.h @@ -295,9 +295,11 @@ class FffGcodeWriter : public NoCopy * * \param[in] storage where the slice data is stored. * \param current_extruder The current extruder with which we last printed + * \param global_extruders_used The extruders that are at some point used for the print job * \return The order of extruders for a layer beginning with \p current_extruder */ - std::vector getUsedExtrudersOnLayer(const SliceDataStorage& storage, const size_t start_extruder, const LayerIndex& layer_nr) const; + std::vector + getUsedExtrudersOnLayer(const SliceDataStorage& storage, const size_t start_extruder, const LayerIndex& layer_nr, const std::vector& global_extruders_used) const; /*! * Calculate in which order to plan the meshes of a specific extruder diff --git a/include/PrimeTower.h b/include/PrimeTower.h index 61a0beb901..b11522643d 100644 --- a/include/PrimeTower.h +++ b/include/PrimeTower.h @@ -28,8 +28,8 @@ class LayerPlan; class PrimeTower { private: - using MovesByExtruder = std::vector; - using MovesByLayer = std::vector; + using MovesByExtruder = std::map; + using MovesByLayer = std::map>; size_t extruder_count_; //!< Number of extruders @@ -79,10 +79,12 @@ class PrimeTower */ PrimeTower(); + void initializeExtruders(const std::vector& used_extruders); + /*! * Check whether we actually use the prime tower. */ - void checkUsed(const SliceDataStorage& storage); + void checkUsed(); /*! * Generate the prime tower area to be used on each layer diff --git a/src/FffGcodeWriter.cpp b/src/FffGcodeWriter.cpp index c71c925ea0..74343ea99b 100644 --- a/src/FffGcodeWriter.cpp +++ b/src/FffGcodeWriter.cpp @@ -1543,12 +1543,13 @@ void FffGcodeWriter::calculateExtruderOrderPerLayer(const SliceDataStorage& stor } size_t extruder_count = Application::getInstance().current_slice_->scene.extruders.size(); + const std::vector extruders_used = storage.getExtrudersUsed(); const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings; PrimeTowerMethod prime_tower_mode = mesh_group_settings.get("prime_tower_mode"); for (LayerIndex layer_nr = -Raft::getTotalExtraLayers(); layer_nr < static_cast(storage.print_layer_count); layer_nr++) { std::vector>& extruder_order_per_layer_here = (layer_nr < 0) ? extruder_order_per_layer_negative_layers : extruder_order_per_layer; - std::vector extruder_order = getUsedExtrudersOnLayer(storage, last_extruder, layer_nr); + std::vector extruder_order = getUsedExtrudersOnLayer(storage, last_extruder, layer_nr, extruders_used); extruder_order_per_layer_here.push_back(extruder_order); if (! extruder_order.empty()) @@ -1573,10 +1574,14 @@ void FffGcodeWriter::calculatePrimeLayerPerExtruder(const SliceDataStorage& stor } } -std::vector FffGcodeWriter::getUsedExtrudersOnLayer(const SliceDataStorage& storage, const size_t start_extruder, const LayerIndex& layer_nr) const +std::vector FffGcodeWriter::getUsedExtrudersOnLayer( + const SliceDataStorage& storage, + const size_t start_extruder, + const LayerIndex& layer_nr, + const std::vector& global_extruders_used) const { const Settings& mesh_group_settings = Application::getInstance().current_slice_->scene.current_mesh_group->settings; - size_t extruder_count = Application::getInstance().current_slice_->scene.extruders.size(); + size_t extruder_count = global_extruders_used.size(); assert(static_cast(extruder_count) > 0); std::vector ret; std::vector extruder_is_used_on_this_layer = storage.getExtrudersUsed(layer_nr); @@ -1601,7 +1606,7 @@ std::vector FffGcodeWriter::getUsedExtrudersOnLayer(const SliceData ordered_extruders.push_back(start_extruder); for (size_t extruder_nr = 0; extruder_nr < extruder_count; extruder_nr++) { - if (extruder_nr != start_extruder) + if (extruder_nr != start_extruder && global_extruders_used[extruder_nr]) { ordered_extruders.push_back(extruder_nr); } diff --git a/src/FffPolygonGenerator.cpp b/src/FffPolygonGenerator.cpp index b0d5ff5ff2..24e23b547a 100644 --- a/src/FffPolygonGenerator.cpp +++ b/src/FffPolygonGenerator.cpp @@ -404,6 +404,8 @@ void FffPolygonGenerator::slices2polygons(SliceDataStorage& storage, TimeKeeper& Progress::messageProgressStage(Progress::Stage::SUPPORT, &time_keeper); + storage.primeTower.initializeExtruders(storage.getExtrudersUsed()); + AreaSupport::generateOverhangAreas(storage); AreaSupport::generateSupportAreas(storage); TreeSupport tree_support_generator(storage); diff --git a/src/PrimeTower.cpp b/src/PrimeTower.cpp index 57dc4d9853..f9ebcb4f4c 100644 --- a/src/PrimeTower.cpp +++ b/src/PrimeTower.cpp @@ -52,35 +52,37 @@ PrimeTower::PrimeTower() && scene.current_mesh_group->settings.get("prime_tower_size") > 10; would_have_actual_tower_ = enabled_; // Assume so for now. +} - extruder_count_ = scene.extruders.size(); - extruder_order_.resize(extruder_count_); - for (unsigned int extruder_nr = 0; extruder_nr < extruder_count_; extruder_nr++) +void PrimeTower::initializeExtruders(const std::vector& used_extruders) +{ + // Add used extruders in default order, then sort. + for (unsigned int extruder_nr = 0; extruder_nr < used_extruders.size(); extruder_nr++) { - extruder_order_[extruder_nr] = extruder_nr; // Start with default order, then sort. + if (used_extruders[extruder_nr]) + { + extruder_order_.push_back(extruder_nr); + } } + + extruder_count_ = extruder_order_.size(); + // Sort from high adhesion to low adhesion. - const Scene* scene_pointer = &scene; // Communicate to lambda via pointer to prevent copy. + const Scene& scene = Application::getInstance().current_slice_->scene; std::stable_sort( extruder_order_.begin(), extruder_order_.end(), - [scene_pointer](const unsigned int& extruder_nr_a, const unsigned int& extruder_nr_b) -> bool + [&scene](const unsigned int& extruder_nr_a, const unsigned int& extruder_nr_b) -> bool { - const Ratio adhesion_a = scene_pointer->extruders[extruder_nr_a].settings_.get("material_adhesion_tendency"); - const Ratio adhesion_b = scene_pointer->extruders[extruder_nr_b].settings_.get("material_adhesion_tendency"); + const Ratio adhesion_a = scene.extruders[extruder_nr_a].settings_.get("material_adhesion_tendency"); + const Ratio adhesion_b = scene.extruders[extruder_nr_b].settings_.get("material_adhesion_tendency"); return adhesion_a < adhesion_b; }); } -void PrimeTower::checkUsed(const SliceDataStorage& storage) +void PrimeTower::checkUsed() { - std::vector extruder_is_used = storage.getExtrudersUsed(); - size_t used_extruder_count = 0; - for (bool is_used : extruder_is_used) - { - used_extruder_count += is_used; - } - if (used_extruder_count <= 1) + if (extruder_count_ <= 1) { enabled_ = false; } @@ -108,7 +110,7 @@ void PrimeTower::generateGroundpoly() void PrimeTower::generatePaths(const SliceDataStorage& storage) { - checkUsed(storage); + checkUsed(); const int raft_total_extra_layers = Raft::getTotalExtraLayers(); would_have_actual_tower_ = storage.max_print_height_second_to_last_extruder @@ -138,9 +140,13 @@ void PrimeTower::generatePaths_denseInfill(std::vector& cumulative_inse const coord_t base_height = std::max(scene.settings.get("prime_tower_base_height"), has_raft ? layer_height : 0); const double base_curve_magnitude = mesh_group_settings.get("prime_tower_base_curve_magnitude"); - prime_moves_.resize(extruder_count_); - base_extra_moves_.resize(extruder_count_); - inset_extra_moves_.resize(extruder_count_); + for (size_t extruder_nr : extruder_order_) + { + // By default, add empty moves for every extruder + prime_moves_[extruder_nr]; + base_extra_moves_[extruder_nr]; + inset_extra_moves_[extruder_nr]; + } coord_t cumulative_inset = 0; // Each tower shape is going to be printed inside the other. This is the inset we're doing for each extruder. for (size_t extruder_nr : extruder_order_) @@ -226,8 +232,6 @@ void PrimeTower::generatePaths_sparseInfill(const std::vector& cumulati if (method == PrimeTowerMethod::INTERLEAVED || method == PrimeTowerMethod::NORMAL) { - const size_t nb_extruders = scene.extruders.size(); - // Pre-compute radiuses of each extruder ring std::vector rings_radii; const coord_t tower_size = mesh_group_settings.get("prime_tower_size"); @@ -242,9 +246,9 @@ void PrimeTower::generatePaths_sparseInfill(const std::vector& cumulati // Generate all possible extruders combinations, e.g. if there are 4 extruders, we have combinations // 0 / 0-1 / 0-1-2 / 0-1-2-3 / 1 / 1-2 / 1-2-3 / 2 / 2-3 / 3 // A combination is represented by a bitmask - for (size_t first_extruder_idx = 0; first_extruder_idx < nb_extruders; ++first_extruder_idx) + for (size_t first_extruder_idx = 0; first_extruder_idx < extruder_count_; ++first_extruder_idx) { - size_t nb_extruders_sparse = method == PrimeTowerMethod::NORMAL ? first_extruder_idx + 1 : nb_extruders; + size_t nb_extruders_sparse = method == PrimeTowerMethod::NORMAL ? first_extruder_idx + 1 : extruder_count_; for (size_t last_extruder_idx = first_extruder_idx; last_extruder_idx < nb_extruders_sparse; ++last_extruder_idx) { @@ -444,7 +448,7 @@ void PrimeTower::addToGcode_denseInfill(LayerPlan& gcode_layer, const size_t ext { // Actual prime pattern const GCodePathConfig& config = gcode_layer.configs_storage_.prime_tower_config_per_extruder[extruder_nr]; - const Polygons& pattern = prime_moves_[extruder_nr]; + const Polygons& pattern = prime_moves_.at(extruder_nr); gcode_layer.addPolygonsByOptimizer(pattern, config); } } @@ -454,7 +458,7 @@ bool PrimeTower::addToGcode_base(LayerPlan& gcode_layer, const size_t extruder_n const size_t raft_total_extra_layers = Raft::getTotalExtraLayers(); LayerIndex absolute_layer_number = gcode_layer.getLayerNr() + raft_total_extra_layers; - const std::vector& pattern_extra_brim = base_extra_moves_[extruder_nr]; + const std::vector& pattern_extra_brim = base_extra_moves_.at(extruder_nr); if (absolute_layer_number < pattern_extra_brim.size()) { // Extra rings for stronger base @@ -477,7 +481,7 @@ bool PrimeTower::addToGcode_inset(LayerPlan& gcode_layer, const size_t extruder_ if (absolute_layer_number == 0) // Extra-adhesion on very first layer only { - const Polygons& pattern_extra_inset = inset_extra_moves_[extruder_nr]; + const Polygons& pattern_extra_inset = inset_extra_moves_.at(extruder_nr); if (! pattern_extra_inset.empty()) { const GCodePathConfig& config = gcode_layer.configs_storage_.prime_tower_config_per_extruder[extruder_nr]; From 1ee8726e9a149ee1c52ed1ba81fa152f04dfe449 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 2 Apr 2024 10:12:02 +0200 Subject: [PATCH 02/15] Fix unit tests Possible crash when finializing a layer plan and prime tower not initialized. Although not possible in normal execution (prime tower is always initialized first), it is still a healthy fix. CURA-11717 --- src/sliceDataStorage.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/sliceDataStorage.cpp b/src/sliceDataStorage.cpp index b369dbb082..cfc4d32c08 100644 --- a/src/sliceDataStorage.cpp +++ b/src/sliceDataStorage.cpp @@ -362,13 +362,9 @@ Polygons SliceDataStorage::getLayerOutlines( total.add(support_layer.support_roof); } } - int prime_tower_outer_extruder_nr = primeTower.extruder_order_[0]; - if (include_prime_tower && (extruder_nr == -1 || extruder_nr == prime_tower_outer_extruder_nr)) + if (include_prime_tower && primeTower.enabled_ && (extruder_nr == -1 || (! primeTower.extruder_order_.empty() && extruder_nr == primeTower.extruder_order_[0]))) { - if (primeTower.enabled_) - { - total.add(primeTower.getOuterPoly(layer_nr)); - } + total.add(primeTower.getOuterPoly(layer_nr)); } return total; } From 2efbdd2b11f208be0a1bc4a2a646f4c7f7236cf3 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Tue, 2 Apr 2024 14:23:40 +0200 Subject: [PATCH 03/15] Pin version 5.7.0 --- conandata.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conandata.yml b/conandata.yml index a5527b0e01..e6c16b939b 100644 --- a/conandata.yml +++ b/conandata.yml @@ -1,4 +1,4 @@ -version: "5.7.0-beta.1" +version: "5.7.0" requirements: - "scripta/0.1.0@ultimaker/testing" requirements_arcus: From 928ebe1c3c3c85e0a65be94aa92626b68220622e Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 2 Apr 2024 15:58:41 +0200 Subject: [PATCH 04/15] Fix overlapping lines with gradual (support) infill. Separate out the areas, since overlapping lines will become a big problem when 'connect infill lines' or 'zig zag' is enabled. This does mean that lines are less well-connected when the pattern _isn't_ already connected in and of itself, like lines. However, such patterns aren't recommended anyway. Also some compensation for the extra density which we _may_ now lose in some cases might need to be done. It should still allow us to to the combine (though I can't see that this happens in practice, either before or after this fix, so we'll may have to look at that in more detail later). part of CURA-11597 --- src/skin.cpp | 6 ++++-- src/support.cpp | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/skin.cpp b/src/skin.cpp index 842a6e576f..797fc6b679 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -494,6 +494,7 @@ void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh) continue; } Polygons less_dense_infill = infill_area; // one step less dense with each infill_step + Polygons sum_more_dense; for (size_t infill_step = 0; infill_step < max_infill_steps; infill_step++) { LayerIndex min_layer = layer_idx + infill_step * gradual_infill_step_layer_count + static_cast(layer_skip_count); @@ -526,11 +527,12 @@ 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 Polygons more_dense_infill = infill_area.difference(less_dense_infill); - infill_area_per_combine_current_density.push_back(more_dense_infill); + infill_area_per_combine_current_density.push_back(more_dense_infill.difference(sum_more_dense)); + sum_more_dense = sum_more_dense.unionPolygons(more_dense_infill); } 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(infill_area); + infill_area_per_combine_current_density.push_back(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"); } diff --git a/src/support.cpp b/src/support.cpp index 7488c6832f..82b9f22e06 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -234,6 +234,7 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) // calculate density areas for this island Polygons less_dense_support = infill_area; // one step less dense with each density_step + Polygons sum_more_dense; for (unsigned int density_step = 0; density_step < max_density_steps; ++density_step) { LayerIndex actual_min_layer{ layer_nr + density_step * gradual_support_step_layer_count + static_cast(layer_skip_count) }; @@ -292,12 +293,13 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) support_infill_part.infill_area_per_combine_per_density_.emplace_back(); std::vector& support_area_current_density = support_infill_part.infill_area_per_combine_per_density_.back(); const Polygons more_dense_support = infill_area.difference(less_dense_support); - support_area_current_density.push_back(more_dense_support); + support_area_current_density.push_back(more_dense_support.difference(sum_more_dense)); + sum_more_dense = sum_more_dense.unionPolygons(more_dense_support); } support_infill_part.infill_area_per_combine_per_density_.emplace_back(); std::vector& support_area_current_density = support_infill_part.infill_area_per_combine_per_density_.back(); - support_area_current_density.push_back(infill_area); + support_area_current_density.push_back(infill_area.difference(sum_more_dense)); assert(support_infill_part.infill_area_per_combine_per_density_.size() != 0 && "support_infill_part.infill_area_per_combine_per_density should now be initialized"); #ifdef DEBUG From 51daa75a08b4bbed37ebec25137b49ed13d26466 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 3 Apr 2024 13:38:31 +0200 Subject: [PATCH 05/15] Only add zig-zag connector when not 'too close' to scanline. This can in some cases lead to (nearly) doubly printed extrusion-paths (or close enough), especially in support, where it might also present the biggest problems. part of CURA-11597 --- include/infill/NoZigZagConnectorProcessor.h | 2 +- include/infill/ZigzagConnectorProcessor.h | 13 +------------ src/infill.cpp | 6 +++--- src/infill/NoZigZagConnectorProcessor.cpp | 2 +- src/infill/ZigzagConnectorProcessor.cpp | 15 ++++++++++++--- 5 files changed, 18 insertions(+), 20 deletions(-) diff --git a/include/infill/NoZigZagConnectorProcessor.h b/include/infill/NoZigZagConnectorProcessor.h index 002fb0fb7b..6e59dcdaa5 100644 --- a/include/infill/NoZigZagConnectorProcessor.h +++ b/include/infill/NoZigZagConnectorProcessor.h @@ -29,7 +29,7 @@ class NoZigZagConnectorProcessor : public ZigzagConnectorProcessor } void registerVertex(const Point2LL& vertex); - void registerScanlineSegmentIntersection(const Point2LL& intersection, int scanline_index); + void registerScanlineSegmentIntersection(const Point2LL& intersection, int scanline_index, coord_t min_distance_to_scanline); void registerPolyFinished(); }; diff --git a/include/infill/ZigzagConnectorProcessor.h b/include/infill/ZigzagConnectorProcessor.h index 513ad9d8f1..9adb751430 100644 --- a/include/infill/ZigzagConnectorProcessor.h +++ b/include/infill/ZigzagConnectorProcessor.h @@ -137,7 +137,7 @@ class ZigzagConnectorProcessor * \param intersection The intersection * \param scanline_index Index of the current scanline */ - virtual void registerScanlineSegmentIntersection(const Point2LL& intersection, int scanline_index); + virtual void registerScanlineSegmentIntersection(const Point2LL& intersection, int scanline_index, coord_t min_distance_to_scanline); /*! * Handle the end of a polygon and prepare for the next. @@ -166,17 +166,6 @@ class ZigzagConnectorProcessor */ bool shouldAddCurrentConnector(int start_scanline_idx, int end_scanline_idx) const; - /*! - * Checks whether two points are separated at least by "threshold" microns. - * If they are far away from each other enough, the line represented by the two points - * will be added; In case they are close, the second point will be set to be the same - * as the first and this line won't be added. - * - * \param first_point The first of the points - * \param second_point The second of the points - */ - void checkAndAddZagConnectorLine(Point2LL* first_point, Point2LL* second_point); - /*! * Adds a Zag connector represented by the given points. The last line of the connector will not be * added if the given connector is an end piece and "connected_endpieces" is not enabled. diff --git a/src/infill.cpp b/src/infill.cpp index c085307622..ff51356267 100644 --- a/src/infill.cpp +++ b/src/infill.cpp @@ -746,12 +746,12 @@ void Infill::generateLinearBasedInfill( for (int scanline_idx = scanline_idx0; scanline_idx != scanline_idx1 + direction; scanline_idx += direction) { - int x = scanline_idx * line_distance + shift; - int y = p1.Y + (p0.Y - p1.Y) * (x - p1.X) / (p0.X - p1.X); + const int x = scanline_idx * line_distance + shift; + const int y = p1.Y + (p0.Y - p1.Y) * (x - p1.X) / (p0.X - p1.X); assert(scanline_idx - scanline_min_idx >= 0 && scanline_idx - scanline_min_idx < int(cut_list.size()) && "reading infill cutlist index out of bounds!"); cut_list[scanline_idx - scanline_min_idx].push_back(y); Point2LL scanline_linesegment_intersection(x, y); - zigzag_connector_processor.registerScanlineSegmentIntersection(scanline_linesegment_intersection, scanline_idx); + zigzag_connector_processor.registerScanlineSegmentIntersection(scanline_linesegment_intersection, scanline_idx, infill_line_width_); crossings_per_scanline[scanline_idx - min_scanline_index].emplace_back(scanline_linesegment_intersection, poly_idx, point_idx); } zigzag_connector_processor.registerVertex(p1); diff --git a/src/infill/NoZigZagConnectorProcessor.cpp b/src/infill/NoZigZagConnectorProcessor.cpp index 1ffa6532f4..25cb0fa48e 100644 --- a/src/infill/NoZigZagConnectorProcessor.cpp +++ b/src/infill/NoZigZagConnectorProcessor.cpp @@ -14,7 +14,7 @@ void NoZigZagConnectorProcessor::registerVertex(const Point2LL&) // No need to add anything. } -void NoZigZagConnectorProcessor::registerScanlineSegmentIntersection(const Point2LL&, int) +void NoZigZagConnectorProcessor::registerScanlineSegmentIntersection(const Point2LL&, int, coord_t) { // No need to add anything. } diff --git a/src/infill/ZigzagConnectorProcessor.cpp b/src/infill/ZigzagConnectorProcessor.cpp index 7f75b608ff..bb7c1bbbac 100644 --- a/src/infill/ZigzagConnectorProcessor.cpp +++ b/src/infill/ZigzagConnectorProcessor.cpp @@ -84,7 +84,7 @@ bool ZigzagConnectorProcessor::shouldAddCurrentConnector(int start_scanline_idx, } -void ZigzagConnectorProcessor::registerScanlineSegmentIntersection(const Point2LL& intersection, int scanline_index) +void ZigzagConnectorProcessor::registerScanlineSegmentIntersection(const Point2LL& intersection, int scanline_index, coord_t min_distance_to_scanline) { if (is_first_connector_) { @@ -100,8 +100,17 @@ void ZigzagConnectorProcessor::registerScanlineSegmentIntersection(const Point2L if (shouldAddCurrentConnector(last_connector_index_, scanline_index)) { const bool is_this_endpiece = scanline_index == last_connector_index_; - current_connector_.push_back(intersection); - addZagConnector(current_connector_, is_this_endpiece); + bool close_to_line_except_intersect = false; + const coord_t min_dist2 = min_distance_to_scanline * min_distance_to_scanline; + for (const auto& point : current_connector_) + { + close_to_line_except_intersect |= (std::abs(point.X - intersection.X) < min_distance_to_scanline) && (vSize2(point - intersection) > min_dist2); + } + if (! close_to_line_except_intersect) + { + current_connector_.push_back(intersection); + addZagConnector(current_connector_, is_this_endpiece); + } } } From 042745ed7055446f493482c65d58c0b75582df4e Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 3 Apr 2024 14:28:20 +0200 Subject: [PATCH 06/15] Remove narrow areas from --and simplify-- gradual infill areas. Narrow or small areas can lead to double printing of lines, as a polygon is filled out that can be narrower than the line-width. Also observed what might be micro-segments in the connecting zags (if there are any), so simplify those out as well. part of CURA-11597 --- src/skin.cpp | 7 +++++-- src/support.cpp | 5 +++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/skin.cpp b/src/skin.cpp index 797fc6b679..7dc2993a82 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -16,6 +16,7 @@ #include "sliceDataStorage.h" #include "utils/math.h" #include "utils/polygonUtils.h" +#include "utils/Simplify.h" #define MIN_AREA_SIZE (0.4 * 0.4) @@ -465,6 +466,8 @@ void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh) const LayerIndex mesh_min_layer = mesh.settings.get("initial_bottom_layers"); const LayerIndex mesh_max_layer = mesh.layers.size() - 1 - mesh.settings.get("top_layers"); + const Simplify simplifier(mesh.settings.get("infill_extruder_nr").settings_); + 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"); @@ -527,12 +530,12 @@ 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 Polygons more_dense_infill = infill_area.difference(less_dense_infill); - infill_area_per_combine_current_density.push_back(more_dense_infill.difference(sum_more_dense)); + 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))); sum_more_dense = sum_more_dense.unionPolygons(more_dense_infill); } 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(infill_area.difference(sum_more_dense)); + infill_area_per_combine_current_density.push_back(simplifier.polygon(infill_area.difference(sum_more_dense).offset(-infill_wall_width).offset(infill_wall_width))); 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"); } diff --git a/src/support.cpp b/src/support.cpp index 82b9f22e06..e8546c55f0 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -187,6 +187,7 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) const size_t max_density_steps = infill_extruder.settings_.get("gradual_support_infill_steps"); const coord_t wall_width = infill_extruder.settings_.get("support_line_width"); + const Simplify simplifier(infill_extruder.settings_); // no early-out for this function; it needs to initialize the [infill_area_per_combine_per_density] double layer_skip_count{ 8.0 }; // skip every so many layers as to ignore small gaps in the model making computation more easy @@ -293,13 +294,13 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) support_infill_part.infill_area_per_combine_per_density_.emplace_back(); std::vector& support_area_current_density = support_infill_part.infill_area_per_combine_per_density_.back(); const Polygons more_dense_support = infill_area.difference(less_dense_support); - support_area_current_density.push_back(more_dense_support.difference(sum_more_dense)); + support_area_current_density.push_back(simplifier.polygon(more_dense_support.difference(sum_more_dense).offset(-wall_width).offset(wall_width))); sum_more_dense = sum_more_dense.unionPolygons(more_dense_support); } support_infill_part.infill_area_per_combine_per_density_.emplace_back(); std::vector& support_area_current_density = support_infill_part.infill_area_per_combine_per_density_.back(); - support_area_current_density.push_back(infill_area.difference(sum_more_dense)); + support_area_current_density.push_back(simplifier.polygon(infill_area.difference(sum_more_dense).offset(-wall_width).offset(wall_width))); assert(support_infill_part.infill_area_per_combine_per_density_.size() != 0 && "support_infill_part.infill_area_per_combine_per_density should now be initialized"); #ifdef DEBUG From 659aa52b08b1b611ad53c87b4946c82ffeb53615 Mon Sep 17 00:00:00 2001 From: rburema Date: Wed, 3 Apr 2024 19:15:52 +0000 Subject: [PATCH 07/15] Applied clang-format. --- src/skin.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/skin.cpp b/src/skin.cpp index 7dc2993a82..e342b58554 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -14,9 +14,9 @@ #include "settings/types/Angle.h" //For the infill support angle. #include "settings/types/Ratio.h" #include "sliceDataStorage.h" +#include "utils/Simplify.h" #include "utils/math.h" #include "utils/polygonUtils.h" -#include "utils/Simplify.h" #define MIN_AREA_SIZE (0.4 * 0.4) @@ -530,7 +530,8 @@ 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 Polygons 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))); + 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))); sum_more_dense = sum_more_dense.unionPolygons(more_dense_infill); } part.infill_area_per_combine_per_density.emplace_back(); From ead0ddeb135b271d6d58ec0dbd4923ae96119fc8 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 10 Apr 2024 09:08:14 +0200 Subject: [PATCH 08/15] Better metric for when a connection is too close to the scanline. Instead of one point within a very small distance, all points need to be within a slightly larger distance to be ignored. part of CURA-11597 --- src/infill.cpp | 2 +- src/infill/ZigzagConnectorProcessor.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/infill.cpp b/src/infill.cpp index ff51356267..ce5189973e 100644 --- a/src/infill.cpp +++ b/src/infill.cpp @@ -751,7 +751,7 @@ void Infill::generateLinearBasedInfill( assert(scanline_idx - scanline_min_idx >= 0 && scanline_idx - scanline_min_idx < int(cut_list.size()) && "reading infill cutlist index out of bounds!"); cut_list[scanline_idx - scanline_min_idx].push_back(y); Point2LL scanline_linesegment_intersection(x, y); - zigzag_connector_processor.registerScanlineSegmentIntersection(scanline_linesegment_intersection, scanline_idx, infill_line_width_); + zigzag_connector_processor.registerScanlineSegmentIntersection(scanline_linesegment_intersection, scanline_idx, infill_line_width_ * 2); crossings_per_scanline[scanline_idx - min_scanline_index].emplace_back(scanline_linesegment_intersection, poly_idx, point_idx); } zigzag_connector_processor.registerVertex(p1); diff --git a/src/infill/ZigzagConnectorProcessor.cpp b/src/infill/ZigzagConnectorProcessor.cpp index bb7c1bbbac..315735bb9a 100644 --- a/src/infill/ZigzagConnectorProcessor.cpp +++ b/src/infill/ZigzagConnectorProcessor.cpp @@ -100,13 +100,13 @@ void ZigzagConnectorProcessor::registerScanlineSegmentIntersection(const Point2L if (shouldAddCurrentConnector(last_connector_index_, scanline_index)) { const bool is_this_endpiece = scanline_index == last_connector_index_; - bool close_to_line_except_intersect = false; + bool close_to_line_except_intersect = true; const coord_t min_dist2 = min_distance_to_scanline * min_distance_to_scanline; for (const auto& point : current_connector_) { - close_to_line_except_intersect |= (std::abs(point.X - intersection.X) < min_distance_to_scanline) && (vSize2(point - intersection) > min_dist2); + close_to_line_except_intersect &= std::abs(point.X - intersection.X) < min_distance_to_scanline; } - if (! close_to_line_except_intersect) + if (current_connector_.empty() || ! close_to_line_except_intersect) { current_connector_.push_back(intersection); addZagConnector(current_connector_, is_this_endpiece); From 7206bc92130bb2012df427fcd74758f929447119 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Wed, 10 Apr 2024 10:59:37 +0200 Subject: [PATCH 09/15] Make min-distance to connecting piece dependant on line-distance. This fixes the issue that (near) 100% fill zig-zags had if you just make it anywhere near larger than a single line-distance. part of CURA-11597 --- src/infill.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/infill.cpp b/src/infill.cpp index ce5189973e..715cce1c61 100644 --- a/src/infill.cpp +++ b/src/infill.cpp @@ -751,7 +751,7 @@ void Infill::generateLinearBasedInfill( assert(scanline_idx - scanline_min_idx >= 0 && scanline_idx - scanline_min_idx < int(cut_list.size()) && "reading infill cutlist index out of bounds!"); cut_list[scanline_idx - scanline_min_idx].push_back(y); Point2LL scanline_linesegment_intersection(x, y); - zigzag_connector_processor.registerScanlineSegmentIntersection(scanline_linesegment_intersection, scanline_idx, infill_line_width_ * 2); + zigzag_connector_processor.registerScanlineSegmentIntersection(scanline_linesegment_intersection, scanline_idx, line_distance / 2); crossings_per_scanline[scanline_idx - min_scanline_index].emplace_back(scanline_linesegment_intersection, poly_idx, point_idx); } zigzag_connector_processor.registerVertex(p1); From f05f5386c7fb2226d3630cebc429ee35f1850eb4 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 11 Apr 2024 11:01:19 +0200 Subject: [PATCH 10/15] Make line-overlap detection more conservative. (Tried a lot of other things as well, which makes it less predictable.) Clean up experiments, bring it back to basics, be quite conservative as this is only a patch and solving the whole 'scan-segments can be too close to the connector paths' probably requires properly rewriting the zig-zag algorithm -- which is way more like a feature. part of CURA-11597 --- include/infill/ZigzagConnectorProcessor.h | 2 ++ src/infill.cpp | 2 +- src/infill/ZigzagConnectorProcessor.cpp | 24 +++++++++++------------ 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/include/infill/ZigzagConnectorProcessor.h b/include/infill/ZigzagConnectorProcessor.h index 9adb751430..9b1b979cf6 100644 --- a/include/infill/ZigzagConnectorProcessor.h +++ b/include/infill/ZigzagConnectorProcessor.h @@ -175,6 +175,8 @@ class ZigzagConnectorProcessor */ void addZagConnector(std::vector& points, bool is_endpiece); + bool handleConnectorToCloseToSegment(const coord_t scanline_x, const coord_t min_distance_to_scanline); + protected: const PointMatrix& rotation_matrix_; //!< The rotation matrix used to enforce the infill angle Polygons& result_; //!< The result of the computation diff --git a/src/infill.cpp b/src/infill.cpp index 715cce1c61..7164da9741 100644 --- a/src/infill.cpp +++ b/src/infill.cpp @@ -751,7 +751,7 @@ void Infill::generateLinearBasedInfill( assert(scanline_idx - scanline_min_idx >= 0 && scanline_idx - scanline_min_idx < int(cut_list.size()) && "reading infill cutlist index out of bounds!"); cut_list[scanline_idx - scanline_min_idx].push_back(y); Point2LL scanline_linesegment_intersection(x, y); - zigzag_connector_processor.registerScanlineSegmentIntersection(scanline_linesegment_intersection, scanline_idx, line_distance / 2); + zigzag_connector_processor.registerScanlineSegmentIntersection(scanline_linesegment_intersection, scanline_idx, line_distance / 4); crossings_per_scanline[scanline_idx - min_scanline_index].emplace_back(scanline_linesegment_intersection, poly_idx, point_idx); } zigzag_connector_processor.registerVertex(p1); diff --git a/src/infill/ZigzagConnectorProcessor.cpp b/src/infill/ZigzagConnectorProcessor.cpp index 315735bb9a..c19cd46b4e 100644 --- a/src/infill/ZigzagConnectorProcessor.cpp +++ b/src/infill/ZigzagConnectorProcessor.cpp @@ -83,6 +83,15 @@ bool ZigzagConnectorProcessor::shouldAddCurrentConnector(int start_scanline_idx, return should_add; } +bool ZigzagConnectorProcessor::handleConnectorToCloseToSegment(const coord_t scanline_x, const coord_t min_distance_to_scanline) +{ + bool all_within_min_dist = ! current_connector_.empty(); + for (const auto& point : current_connector_) + { + all_within_min_dist &= std::abs(point.X - scanline_x) < min_distance_to_scanline; + } + return all_within_min_dist; +} void ZigzagConnectorProcessor::registerScanlineSegmentIntersection(const Point2LL& intersection, int scanline_index, coord_t min_distance_to_scanline) { @@ -97,20 +106,11 @@ void ZigzagConnectorProcessor::registerScanlineSegmentIntersection(const Point2L else { // add the current connector if needed - if (shouldAddCurrentConnector(last_connector_index_, scanline_index)) + if (shouldAddCurrentConnector(last_connector_index_, scanline_index) && ! handleConnectorToCloseToSegment(intersection.X, min_distance_to_scanline)) { const bool is_this_endpiece = scanline_index == last_connector_index_; - bool close_to_line_except_intersect = true; - const coord_t min_dist2 = min_distance_to_scanline * min_distance_to_scanline; - for (const auto& point : current_connector_) - { - close_to_line_except_intersect &= std::abs(point.X - intersection.X) < min_distance_to_scanline; - } - if (current_connector_.empty() || ! close_to_line_except_intersect) - { - current_connector_.push_back(intersection); - addZagConnector(current_connector_, is_this_endpiece); - } + current_connector_.push_back(intersection); + addZagConnector(current_connector_, is_this_endpiece); } } From 449c209cda975a42c37f104286dc3b0443e97db9 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 11 Apr 2024 11:28:24 +0200 Subject: [PATCH 11/15] Only split up densities _completely_ when we zig-zaggify infill. Only do the new split-up in the rare cases where stuff goes wrong for now (= gradual fills + connected fill lines). We're not adjusting the percentages for not doubling/tripling/etc over an area anymore, since that would change too much at this juncture, make it less predicatble which lines in the layer below match up, and we have more walls anyway because of the zig-zagging. part of CURA-11597 --- src/skin.cpp | 8 ++++++-- src/support.cpp | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/skin.cpp b/src/skin.cpp index e342b58554..1bd59d165a 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -471,6 +471,7 @@ 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 SliceLayer& layer = mesh.layers[layer_idx]; @@ -497,7 +498,7 @@ void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh) continue; } Polygons less_dense_infill = infill_area; // one step less dense with each infill_step - Polygons sum_more_dense; + Polygons sum_more_dense; // NOTE: Only used for zig-zag or connected fills. for (size_t infill_step = 0; infill_step < max_infill_steps; infill_step++) { LayerIndex min_layer = layer_idx + infill_step * gradual_infill_step_layer_count + static_cast(layer_skip_count); @@ -532,7 +533,10 @@ void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh) const Polygons 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))); - sum_more_dense = sum_more_dense.unionPolygons(more_dense_infill); + if (is_connected) + { + sum_more_dense = sum_more_dense.unionPolygons(more_dense_infill); + } } 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(); diff --git a/src/support.cpp b/src/support.cpp index e8546c55f0..4954501e0a 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -187,6 +187,7 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) const size_t max_density_steps = infill_extruder.settings_.get("gradual_support_infill_steps"); const coord_t wall_width = infill_extruder.settings_.get("support_line_width"); + const bool is_connected = infill_extruder.settings_.get("zig_zaggify_infill") || infill_extruder.settings_.get("infill_pattern") == EFillMethod::ZIG_ZAG; const Simplify simplifier(infill_extruder.settings_); // no early-out for this function; it needs to initialize the [infill_area_per_combine_per_density] @@ -235,7 +236,7 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) // calculate density areas for this island Polygons less_dense_support = infill_area; // one step less dense with each density_step - Polygons sum_more_dense; + Polygons sum_more_dense; // NOTE: Only used for zig-zag or connected fills. for (unsigned int density_step = 0; density_step < max_density_steps; ++density_step) { LayerIndex actual_min_layer{ layer_nr + density_step * gradual_support_step_layer_count + static_cast(layer_skip_count) }; @@ -295,7 +296,10 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) std::vector& support_area_current_density = support_infill_part.infill_area_per_combine_per_density_.back(); const Polygons more_dense_support = infill_area.difference(less_dense_support); support_area_current_density.push_back(simplifier.polygon(more_dense_support.difference(sum_more_dense).offset(-wall_width).offset(wall_width))); - sum_more_dense = sum_more_dense.unionPolygons(more_dense_support); + if (is_connected) + { + sum_more_dense = sum_more_dense.unionPolygons(more_dense_support); + } } support_infill_part.infill_area_per_combine_per_density_.emplace_back(); From 6592e502ead8022d6906d2643213706f54c3c880 Mon Sep 17 00:00:00 2001 From: rburema Date: Thu, 11 Apr 2024 09:29:36 +0000 Subject: [PATCH 12/15] Applied clang-format. --- src/skin.cpp | 2 +- src/support.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/skin.cpp b/src/skin.cpp index 1bd59d165a..32469b2766 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -498,7 +498,7 @@ void SkinInfillAreaComputation::generateGradualInfill(SliceMeshStorage& mesh) continue; } Polygons less_dense_infill = infill_area; // one step less dense with each infill_step - Polygons sum_more_dense; // NOTE: Only used for zig-zag or connected fills. + Polygons sum_more_dense; // NOTE: Only used for zig-zag or connected fills. for (size_t infill_step = 0; infill_step < max_infill_steps; infill_step++) { LayerIndex min_layer = layer_idx + infill_step * gradual_infill_step_layer_count + static_cast(layer_skip_count); diff --git a/src/support.cpp b/src/support.cpp index 4954501e0a..bafce3e6f2 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -236,7 +236,7 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) // calculate density areas for this island Polygons less_dense_support = infill_area; // one step less dense with each density_step - Polygons sum_more_dense; // NOTE: Only used for zig-zag or connected fills. + Polygons sum_more_dense; // NOTE: Only used for zig-zag or connected fills. for (unsigned int density_step = 0; density_step < max_density_steps; ++density_step) { LayerIndex actual_min_layer{ layer_nr + density_step * gradual_support_step_layer_count + static_cast(layer_skip_count) }; From eeec9636f7b3f749b790a1bea4c2901196cee027 Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Thu, 11 Apr 2024 11:34:17 +0200 Subject: [PATCH 13/15] Morphologic opening operation was causing floating areas. Introduced earlier in this PR to solve some edge cases, but more trouble than it's worth it seems, at the very least when it's for support. part of CURA-11597 --- src/support.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/support.cpp b/src/support.cpp index bafce3e6f2..f5ad514faa 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -295,7 +295,7 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) support_infill_part.infill_area_per_combine_per_density_.emplace_back(); std::vector& support_area_current_density = support_infill_part.infill_area_per_combine_per_density_.back(); const Polygons more_dense_support = infill_area.difference(less_dense_support); - support_area_current_density.push_back(simplifier.polygon(more_dense_support.difference(sum_more_dense).offset(-wall_width).offset(wall_width))); + support_area_current_density.push_back(simplifier.polygon(more_dense_support.difference(sum_more_dense))); if (is_connected) { sum_more_dense = sum_more_dense.unionPolygons(more_dense_support); @@ -304,7 +304,7 @@ void AreaSupport::generateGradualSupport(SliceDataStorage& storage) support_infill_part.infill_area_per_combine_per_density_.emplace_back(); std::vector& support_area_current_density = support_infill_part.infill_area_per_combine_per_density_.back(); - support_area_current_density.push_back(simplifier.polygon(infill_area.difference(sum_more_dense).offset(-wall_width).offset(wall_width))); + support_area_current_density.push_back(simplifier.polygon(infill_area.difference(sum_more_dense))); assert(support_infill_part.infill_area_per_combine_per_density_.size() != 0 && "support_infill_part.infill_area_per_combine_per_density should now be initialized"); #ifdef DEBUG From 513927496c23425e27539088598d4ee6ae67b008 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Wed, 17 Apr 2024 14:53:53 +0200 Subject: [PATCH 14/15] Minor code cleaning and optimization CURA-11597 --- include/infill/ZigzagConnectorProcessor.h | 2 +- src/infill/ZigzagConnectorProcessor.cpp | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/include/infill/ZigzagConnectorProcessor.h b/include/infill/ZigzagConnectorProcessor.h index 9b1b979cf6..5bc629b685 100644 --- a/include/infill/ZigzagConnectorProcessor.h +++ b/include/infill/ZigzagConnectorProcessor.h @@ -175,7 +175,7 @@ class ZigzagConnectorProcessor */ void addZagConnector(std::vector& points, bool is_endpiece); - bool handleConnectorToCloseToSegment(const coord_t scanline_x, const coord_t min_distance_to_scanline); + bool handleConnectorTooCloseToSegment(const coord_t scanline_x, const coord_t min_distance_to_scanline); protected: const PointMatrix& rotation_matrix_; //!< The rotation matrix used to enforce the infill angle diff --git a/src/infill/ZigzagConnectorProcessor.cpp b/src/infill/ZigzagConnectorProcessor.cpp index c19cd46b4e..4e28dee774 100644 --- a/src/infill/ZigzagConnectorProcessor.cpp +++ b/src/infill/ZigzagConnectorProcessor.cpp @@ -83,14 +83,23 @@ bool ZigzagConnectorProcessor::shouldAddCurrentConnector(int start_scanline_idx, return should_add; } -bool ZigzagConnectorProcessor::handleConnectorToCloseToSegment(const coord_t scanline_x, const coord_t min_distance_to_scanline) +bool ZigzagConnectorProcessor::handleConnectorTooCloseToSegment(const coord_t scanline_x, const coord_t min_distance_to_scanline) { - bool all_within_min_dist = ! current_connector_.empty(); - for (const auto& point : current_connector_) + if (current_connector_.empty()) { - all_within_min_dist &= std::abs(point.X - scanline_x) < min_distance_to_scanline; + return false; + } + else + { + return std::find_if( + current_connector_.begin(), + current_connector_.end(), + [scanline_x, min_distance_to_scanline](const Point2LL& point) + { + return std::abs(point.X - scanline_x) >= min_distance_to_scanline; + }) + == current_connector_.end(); } - return all_within_min_dist; } void ZigzagConnectorProcessor::registerScanlineSegmentIntersection(const Point2LL& intersection, int scanline_index, coord_t min_distance_to_scanline) @@ -106,7 +115,7 @@ void ZigzagConnectorProcessor::registerScanlineSegmentIntersection(const Point2L else { // add the current connector if needed - if (shouldAddCurrentConnector(last_connector_index_, scanline_index) && ! handleConnectorToCloseToSegment(intersection.X, min_distance_to_scanline)) + if (shouldAddCurrentConnector(last_connector_index_, scanline_index) && ! handleConnectorTooCloseToSegment(intersection.X, min_distance_to_scanline)) { const bool is_this_endpiece = scanline_index == last_connector_index_; current_connector_.push_back(intersection); From fe02797035a248840e1cc16c89a723aa7f4ac037 Mon Sep 17 00:00:00 2001 From: Jelle Spijker Date: Mon, 22 Apr 2024 12:39:43 +0200 Subject: [PATCH 15/15] pin version 5.7.1 --- conandata.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conandata.yml b/conandata.yml index e6c16b939b..25ea096dd3 100644 --- a/conandata.yml +++ b/conandata.yml @@ -1,4 +1,4 @@ -version: "5.7.0" +version: "5.7.1" requirements: - "scripta/0.1.0@ultimaker/testing" requirements_arcus: