From b04e3bc25e35e1efccb8c85d90d0475dcaa9e102 Mon Sep 17 00:00:00 2001 From: Pavel Mikus Date: Wed, 29 Mar 2023 17:14:03 +0200 Subject: [PATCH] Initial implementation, requieres both dynamic speed and avoid curled overhangs options to be enabled Also implements new, probably far better estimation of curled height of filament --- src/libslic3r/GCode/ExtrusionProcessor.hpp | 40 ++++++++++++++----- src/libslic3r/SupportSpotsGenerator.cpp | 45 ++++++++++++++++++---- src/libslic3r/SupportSpotsGenerator.hpp | 2 +- 3 files changed, 68 insertions(+), 19 deletions(-) diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 625ea695c..98febf609 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -246,6 +246,8 @@ class ExtrusionQualityEstimator { std::unordered_map> prev_layer_boundaries; std::unordered_map> next_layer_boundaries; + std::unordered_map> prev_curled_extrusions; + std::unordered_map> next_curled_extrusions; const PrintObject *current_object; public: @@ -253,18 +255,27 @@ public: void prepare_for_new_layer(const Layer *layer) { - if (layer == nullptr) return; - const PrintObject *object = layer->object(); - prev_layer_boundaries[object] = next_layer_boundaries[object]; - next_layer_boundaries[object] = AABBTreeLines::LinesDistancer{to_unscaled_linesf(layer->lslices)}; + if (layer == nullptr) + return; + const PrintObject *object = layer->object(); + prev_layer_boundaries[object] = next_layer_boundaries[object]; + next_layer_boundaries[object] = AABBTreeLines::LinesDistancer{to_unscaled_linesf(layer->lslices)}; + prev_curled_extrusions[object] = next_curled_extrusions[object]; + Linesf curled_lines; + curled_lines.reserve(layer->malformed_lines.size()); + for (const Line &l : layer->malformed_lines) { + curled_lines.push_back(Linef(unscaled(l.a), unscaled(l.b))); + } + next_curled_extrusions[object] = AABBTreeLines::LinesDistancer{curled_lines}; } - std::vector estimate_extrusion_quality(const ExtrusionPath &path, - const std::vector> overhangs_w_speeds, - const std::vector> overhangs_w_fan_speeds, - size_t extruder_id, - float ext_perimeter_speed, - float original_speed) + std::vector estimate_speed_from_extrusion_quality( + const ExtrusionPath &path, + const std::vector> overhangs_w_speeds, + const std::vector> overhangs_w_fan_speeds, + size_t extruder_id, + float ext_perimeter_speed, + float original_speed) { float speed_base = ext_perimeter_speed > 0 ? ext_perimeter_speed : original_speed; std::map speed_sections; @@ -285,6 +296,15 @@ public: std::vector extended_points = estimate_points_properties(path.polyline.points, prev_layer_boundaries[current_object], path.width); + + for (ExtendedPoint& ep : extended_points) { + // We are going to enforce slowdown by increasing the point distance. The overhang speed is based on signed distance from + // the prev layer, where 0 means fully overlapping extrusions and thus no slowdown, while extrusion_width and more means full overhang, thus full slowdown. + // However, for curling, we take unsinged distance from the curled lines and artifically modifiy the distance + float distance_from_curled = prev_curled_extrusions[current_object].distance_from_lines(ep.position); + ep.distance = std::max(ep.distance, path.width - distance_from_curled); + } + std::vector processed_points; processed_points.reserve(extended_points.size()); diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index 5062fe18a..bef3c0fc1 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,7 @@ #include "Geometry/ConvexHull.hpp" // #define DETAILED_DEBUG_LOGS -// #define DEBUG_FILES +#define DEBUG_FILES #ifdef DEBUG_FILES #include @@ -208,16 +209,44 @@ std::vector to_short_lines(const ExtrusionEntity *e, float length float estimate_curled_up_height( const ExtendedPoint &point, float layer_height, float flow_width, float prev_line_curled_height, Params params) { - float curled_up_height = 0.0f; + float curled_up_height = 0; if (fabs(point.distance) < 1.5 * flow_width) { - curled_up_height = 0.85 * prev_line_curled_height; + curled_up_height = 0.9 * prev_line_curled_height; } - if (point.distance > params.malformation_distance_factors.first * flow_width && - point.distance < params.malformation_distance_factors.second * flow_width && point.curvature > -0.1f) { - float dist_factor = std::max(point.distance - params.malformation_distance_factors.first * flow_width, 0.01f) / - ((params.malformation_distance_factors.second - params.malformation_distance_factors.first) * flow_width); - curled_up_height = layer_height * sqrt(sqrt(dist_factor)) * std::clamp(3.0f * point.curvature, 1.0f, 3.0f); + if (point.distance > params.malformation_distance_factors.first * flow_width && + point.distance < params.malformation_distance_factors.second * flow_width) { + // imagine the extrusion profile. The part that has been glued (melted) with the previous layer will be called anchored section + // and the rest will be called curling section + float anchored_section = flow_width - point.distance; + float curling_section = point.distance; + + // after extruding, the curling (floating) part of the extrusion starts to shrink back to the rounded shape of the nozzle + // The anchored part not, because the melted material holds to the previous layer well. + // We can assume for simplicity perfect equalization of layer height and raising part width, from which: + float swelling_radius = (layer_height + curling_section) / 2.0f; + curled_up_height += std::max(0.f, (swelling_radius - layer_height) / 2.0f); + + // There is one more effect. On convex turns, there is larger tension on the floating edge of the extrusion then on the middle section. + // The tension is caused by the shrinking tendency of the filament, and on outer edge of convex trun, the expansion is greater and thus shrinking force is greater. + // This tension will cause the curling section to curle up (Why not down? maybe the previous layer works as a heat block, releasing the heat + // faster or slower than thin air, thus the extrusion always curles up) + + if (point.curvature > 0.01){ + float radius = 1.0 / point.curvature; + // compute radius at the point where the extrusion stops touch previous layer and starts curling + float radius_anchored_section_end = radius - flow_width / 2.0 + anchored_section; + // target radius represents the radius of the extrusion curling end, after curling + // the layer_height term aproximates that the extrusion curling part, when raising to vertical position, will stop before reaching + // perpendicular position, due to various forces. + float target_radius = std::max(radius, radius_anchored_section_end) + layer_height; + + float b = target_radius - radius_anchored_section_end; + float a = (curling_section + swelling_radius) / 2.0; + float c = sqrt(a*a - b*b); + + curled_up_height += c; + } curled_up_height = std::min(curled_up_height, params.max_curled_height_factor * layer_height); } diff --git a/src/libslic3r/SupportSpotsGenerator.hpp b/src/libslic3r/SupportSpotsGenerator.hpp index 543b9c92b..c673fc21f 100644 --- a/src/libslic3r/SupportSpotsGenerator.hpp +++ b/src/libslic3r/SupportSpotsGenerator.hpp @@ -42,7 +42,7 @@ struct Params BrimType brim_type; const float brim_width; - const std::pair malformation_distance_factors = std::pair { 0.5, 1.1 }; + const std::pair malformation_distance_factors = std::pair { 0.3, 0.9 }; const float max_curled_height_factor = 10.0f; const float curling_tolerance_limit = 0.1f;