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..5bc629b685 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. @@ -186,6 +175,8 @@ class ZigzagConnectorProcessor */ void addZagConnector(std::vector& points, bool is_endpiece); + 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 Polygons& result_; //!< The result of the computation diff --git a/src/infill.cpp b/src/infill.cpp index c085307622..7164da9741 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, 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/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..4e28dee774 100644 --- a/src/infill/ZigzagConnectorProcessor.cpp +++ b/src/infill/ZigzagConnectorProcessor.cpp @@ -83,8 +83,26 @@ bool ZigzagConnectorProcessor::shouldAddCurrentConnector(int start_scanline_idx, return should_add; } +bool ZigzagConnectorProcessor::handleConnectorTooCloseToSegment(const coord_t scanline_x, const coord_t min_distance_to_scanline) +{ + if (current_connector_.empty()) + { + 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(); + } +} -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_) { @@ -97,7 +115,7 @@ 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) && ! handleConnectorTooCloseToSegment(intersection.X, min_distance_to_scanline)) { const bool is_this_endpiece = scanline_index == last_connector_index_; current_connector_.push_back(intersection); diff --git a/src/skin.cpp b/src/skin.cpp index 842a6e576f..32469b2766 100644 --- a/src/skin.cpp +++ b/src/skin.cpp @@ -14,6 +14,7 @@ #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" @@ -465,9 +466,12 @@ 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"); + 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]; @@ -494,6 +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. 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 +531,16 @@ 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( + simplifier.polygon(more_dense_infill.difference(sum_more_dense).offset(-infill_wall_width).offset(infill_wall_width))); + 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(); - infill_area_per_combine_current_density.push_back(infill_area); + 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 7488c6832f..f5ad514faa 100644 --- a/src/support.cpp +++ b/src/support.cpp @@ -187,6 +187,8 @@ 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] double layer_skip_count{ 8.0 }; // skip every so many layers as to ignore small gaps in the model making computation more easy @@ -234,6 +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. 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 +295,16 @@ 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(simplifier.polygon(more_dense_support.difference(sum_more_dense))); + if (is_connected) + { + 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(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