diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 81a1c018a..6e441a4c6 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -27,78 +27,6 @@ namespace Slic3r { -class SlidingWindowCurvatureAccumulator -{ - float window_size; - float total_distance = 0; // accumulated distance - float total_curvature = 0; // accumulated signed ccw angles - deque distances; - deque angles; - -public: - SlidingWindowCurvatureAccumulator(float window_size) : window_size(window_size) {} - - void add_point(float distance, float angle) - { - total_distance += distance; - total_curvature += angle; - distances.push_back(distance); - angles.push_back(angle); - - while (distances.size() > 1 && total_distance > window_size) { - total_distance -= distances.front(); - total_curvature -= angles.front(); - distances.pop_front(); - angles.pop_front(); - } - } - - float get_curvature() const - { - return total_curvature / window_size; - } - - void reset() - { - total_curvature = 0; - total_distance = 0; - distances.clear(); - angles.clear(); - } -}; - -class CurvatureEstimator -{ - static const size_t sliders_count = 3; - SlidingWindowCurvatureAccumulator sliders[sliders_count] = {{1.0},{4.0}, {10.0}}; - -public: - void add_point(float distance, float angle) - { - if (distance < EPSILON) - return; - for (SlidingWindowCurvatureAccumulator &slider : sliders) { - slider.add_point(distance, angle); - } - } - float get_curvature() - { - float max_curvature = 0.0f; - for (const SlidingWindowCurvatureAccumulator &slider : sliders) { - if (abs(slider.get_curvature()) > abs(max_curvature)) { - max_curvature = slider.get_curvature(); - } - } - return max_curvature; - } - void reset() - { - for (SlidingWindowCurvatureAccumulator &slider : sliders) { - slider.reset(); - } - } -}; - struct ExtendedPoint { Vec2d position; @@ -118,7 +46,6 @@ std::vector estimate_points_properties(const std::vector

if (input_points.empty()) return {}; float boundary_offset = PREV_LAYER_BOUNDARY_OFFSET ? 0.5 * flow_width : 0.0f; - CurvatureEstimator cestim; auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast(); }; std::vector points; @@ -227,6 +154,9 @@ std::vector estimate_points_properties(const std::vector

points = new_points; } + std::vector angles_for_curvature(points.size()); + std::vector distances_for_curvature(points.size()); + for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) { ExtendedPoint &a = points[point_idx]; ExtendedPoint &prev = points[point_idx > 0 ? point_idx - 1 : point_idx]; @@ -234,22 +164,59 @@ std::vector estimate_points_properties(const std::vector

int prev_point_idx = point_idx; while (prev_point_idx > 0) { prev_point_idx--; - if ((a.position - points[prev_point_idx].position).squaredNorm() > EPSILON) { break; } + if ((a.position - points[prev_point_idx].position).squaredNorm() > EPSILON) { + break; + } } int next_point_index = point_idx; while (next_point_index < int(points.size()) - 1) { next_point_index++; - if ((a.position - points[next_point_index].position).squaredNorm() > EPSILON) { break; } + if ((a.position - points[next_point_index].position).squaredNorm() > EPSILON) { + break; + } } + distances_for_curvature[point_idx] = (prev.position - a.position).norm(); if (prev_point_idx != point_idx && next_point_index != point_idx) { - float distance = (prev.position - a.position).norm(); - float alfa = angle(a.position - points[prev_point_idx].position, points[next_point_index].position - a.position); - cestim.add_point(distance, alfa); - } + float alfa = angle(a.position - points[prev_point_idx].position, points[next_point_index].position - a.position); + angles_for_curvature[point_idx] = alfa; + } // else keep zero + } - a.curvature = cestim.get_curvature(); + for (float window_size : {3.0f, 9.0f, 16.0f}) { + size_t tail_point = 0; + float tail_window_acc = 0; + float tail_angle_acc = 0; + + size_t head_point = 0; + float head_window_acc = 0; + float head_angle_acc = 0; + + for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) { + if (point_idx > 0) { + tail_window_acc += distances_for_curvature[point_idx - 1]; + tail_angle_acc += angles_for_curvature[point_idx - 1]; + head_window_acc -= distances_for_curvature[point_idx - 1]; + head_angle_acc -= angles_for_curvature[point_idx - 1]; + } + while (tail_window_acc > window_size * 0.5 && tail_point < point_idx) { + tail_window_acc -= distances_for_curvature[tail_point]; + tail_angle_acc -= angles_for_curvature[tail_point]; + tail_point++; + } + + while (head_window_acc < window_size * 0.5 && head_point < int(points.size()) - 1) { + head_window_acc += distances_for_curvature[head_point]; + head_angle_acc += angles_for_curvature[head_point]; + head_point++; + } + + float curvature = (tail_angle_acc + head_angle_acc) / (tail_window_acc + head_window_acc); + if (std::abs(curvature) > std::abs(points[point_idx].curvature)) { + points[point_idx].curvature = curvature; + } + } } return points; diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index 15a4aa535..0ad76d8b1 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -234,7 +234,7 @@ float estimate_curled_up_height( // faster or slower than thin air, thus the extrusion always curles up) if (point.curvature > 0.01){ - float radius = std::max(1.0 / point.curvature - flow_width / 2.0, 0.001); + float radius = (1.0 / point.curvature); float curling_t = sqrt(radius / 100); float b = curling_t * flow_width; float a = curling_section; @@ -397,8 +397,8 @@ std::vector check_extrusion_entity_stability(const ExtrusionEntit bridged_distance = 0.0f; } - line_out.curled_up_height = estimate_curled_up_height(curr_point, layer_region->layer()->height, flow_width, - prev_layer_curling, params); + line_out.curled_up_height = estimate_curled_up_height(layer_region->layer()->id() % 2 == 0 ? curr_point : prev_point, + layer_region->layer()->height, flow_width, prev_layer_curling, params); lines_out.push_back(line_out); } @@ -1102,25 +1102,25 @@ void estimate_supports_malformations(SupportLayerPtrs &layers, float flow_width, auto annotated_points = estimate_points_properties(pol.points, prev_layer_lines, flow_width); for (size_t i = 0; i < annotated_points.size(); ++i) { - ExtendedPoint &curr_point = annotated_points[i]; - float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f; - ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast() : curr_point.position.cast(), - curr_point.position.cast(), line_len, extrusion}; + ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i]; + ExtendedPoint &b = annotated_points[i]; + ExtrusionLine line_out{a.position.cast(), b.position.cast(), float((a.position - b.position).norm()), + extrusion}; - auto [prev_layer_quality, prev_layer_curling] = get_bottom_extrusions_quality_and_curling(prev_layer_lines, curr_point); - const ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ? - prev_layer_lines.get_line(curr_point.nearest_prev_layer_line) : - ExtrusionLine{}; + ExtendedPoint &pivot = l->id() % 2 == 0 ? a : b; + auto [prev_layer_quality, prev_layer_curling] = get_bottom_extrusions_quality_and_curling(prev_layer_lines, pivot); + const ExtrusionLine nearest_prev_layer_line = prev_layer_lines.get_lines().size() > 0 ? + prev_layer_lines.get_line(pivot.nearest_prev_layer_line) : + ExtrusionLine{}; Vec2f v1 = (nearest_prev_layer_line.b - nearest_prev_layer_line.a); - Vec2f v2 = (curr_point.position.cast() - nearest_prev_layer_line.a); + Vec2f v2 = (pivot.position.cast() - nearest_prev_layer_line.a); auto d = (v1.x() * v2.y()) - (v1.y() * v2.x()); if (d > 0) { - curr_point.distance *= -1.0f; + pivot.distance *= -1.0f; } - line_out.curled_up_height = estimate_curled_up_height(curr_point, l->height, flow_width, - prev_layer_curling, params); + line_out.curled_up_height = estimate_curled_up_height(pivot, l->height, flow_width, prev_layer_curling, params); current_layer_lines.push_back(line_out); } @@ -1158,7 +1158,7 @@ void estimate_malformations(LayerPtrs &layers, const Params ¶ms) { #ifdef DEBUG_FILES FILE *debug_file = boost::nowide::fopen(debug_out_path("object_malformations.obj").c_str(), "w"); - FILE *full_file = boost::nowide::fopen(debug_out_path("object_full.obj").c_str(), "w"); + FILE *full_file = boost::nowide::fopen(debug_out_path("object_full.obj").c_str(), "w"); #endif LD prev_layer_lines{}; @@ -1170,8 +1170,8 @@ void estimate_malformations(LayerPtrs &layers, const Params ¶ms) std::vector current_layer_lines; for (const LayerRegion *layer_region : l->regions()) { for (const ExtrusionEntity *extrusion : layer_region->perimeters().flatten().entities) { - - if (!extrusion->role().is_external_perimeter()) continue; + if (!extrusion->role().is_external_perimeter()) + continue; Points extrusion_pts; extrusion->collect_points(extrusion_pts); @@ -1179,18 +1179,18 @@ void estimate_malformations(LayerPtrs &layers, const Params ¶ms) auto annotated_points = estimate_points_properties(extrusion_pts, prev_layer_lines, flow_width, params.bridge_distance); for (size_t i = 0; i < annotated_points.size(); ++i) { - ExtendedPoint &curr_point = annotated_points[i]; - float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f; - ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast() : curr_point.position.cast(), - curr_point.position.cast(), line_len, extrusion}; + ExtendedPoint &a = i > 0 ? annotated_points[i - 1] : annotated_points[i]; + ExtendedPoint &b = annotated_points[i]; + ExtrusionLine line_out{a.position.cast(), b.position.cast(), float((a.position - b.position).norm()), + extrusion}; - auto [prev_layer_quality, prev_layer_curling] = get_bottom_extrusions_quality_and_curling(prev_layer_lines, curr_point); + ExtendedPoint &pivot = l->id() % 2 == 0 ? a : b; + auto [prev_layer_quality, prev_layer_curling] = get_bottom_extrusions_quality_and_curling(prev_layer_lines, pivot); - float sign = (prev_layer_boundary.distance_from_lines(curr_point.position) + 0.5f * flow_width) < 0.0f ? -1.0f : - 1.0f; - curr_point.distance *= sign; + float sign = (prev_layer_boundary.distance_from_lines(pivot.position) + 0.5f * flow_width) < 0.0f ? -1.0f : 1.0f; + pivot.distance *= sign; - line_out.curled_up_height = estimate_curled_up_height(curr_point, layer_region->layer()->height, flow_width, + line_out.curled_up_height = estimate_curled_up_height(pivot, layer_region->layer()->height, flow_width, prev_layer_curling, params); current_layer_lines.push_back(line_out); @@ -1211,9 +1211,9 @@ void estimate_malformations(LayerPtrs &layers, const Params ¶ms) fprintf(debug_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]); } } - for (const ExtrusionLine &line : current_layer_lines) { - Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_curled_height_factor, line.curled_up_height); - fprintf(full_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]); + for (const ExtrusionLine &line : current_layer_lines) { + Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_curled_height_factor, line.curled_up_height); + fprintf(full_file, "v %f %f %f %f %f %f\n", line.b[0], line.b[1], l->print_z, color[0], color[1], color[2]); } #endif