From 928ebe1c3c3c85e0a65be94aa92626b68220622e Mon Sep 17 00:00:00 2001 From: Remco Burema Date: Tue, 2 Apr 2024 15:58:41 +0200 Subject: [PATCH 01/11] 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 02/11] 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 03/11] 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 04/11] 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 05/11] 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 06/11] 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 07/11] 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 08/11] 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 09/11] 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 10/11] 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 11/11] 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);