diff --git a/src/libslic3r/AABBTreeLines.hpp b/src/libslic3r/AABBTreeLines.hpp index 55ce9a0c8..21678bfcd 100644 --- a/src/libslic3r/AABBTreeLines.hpp +++ b/src/libslic3r/AABBTreeLines.hpp @@ -117,18 +117,18 @@ inline std::tuple coordinate_aligned_ray_hit_count(size_t } template -inline std::vector get_intersections_with_line(size_t node_idx, - const TreeType &tree, - const std::vector &lines, - const LineType &line, - const typename TreeType::BoundingBox &line_bb) +inline std::vector> get_intersections_with_line(size_t node_idx, + const TreeType &tree, + const std::vector &lines, + const LineType &line, + const typename TreeType::BoundingBox &line_bb) { const auto &node = tree.node(node_idx); assert(node.is_valid()); if (node.is_leaf()) { VectorType intersection_pt; if (line_alg::intersection(line, lines[node.idx], &intersection_pt)) { - return {intersection_pt}; + return {std::pair(intersection_pt, node.idx)}; } else { return {}; } @@ -140,17 +140,17 @@ inline std::vector get_intersections_with_line(size_t assert(node_left.is_valid()); assert(node_right.is_valid()); - std::vector result; + std::vector> result; if (node_left.bbox.intersects(line_bb)) { - std::vector intersections = get_intersections_with_line(left_node_idx, tree, lines, - line, line_bb); + std::vector> intersections = + get_intersections_with_line(left_node_idx, tree, lines, line, line_bb); result.insert(result.end(), intersections.begin(), intersections.end()); } if (node_right.bbox.intersects(line_bb)) { - std::vector intersections = get_intersections_with_line(right_node_idx, tree, lines, - line, line_bb); + std::vector> intersections = + get_intersections_with_line(right_node_idx, tree, lines, line, line_bb); result.insert(result.end(), intersections.begin(), intersections.end()); } @@ -263,9 +263,13 @@ inline int point_outside_closed_contours(const std::vector &lines, con } template -inline std::vector get_intersections_with_line(const std::vector &lines, const TreeType &tree, const LineType &line) +inline std::vector> get_intersections_with_line(const std::vector &lines, + const TreeType &tree, + const LineType &line) { - if (tree.empty()) { return {}; } + if (tree.empty()) { + return {}; + } auto line_bb = typename TreeType::BoundingBox(line.a, line.a); line_bb.extend(line.b); @@ -274,15 +278,16 @@ inline std::vector get_intersections_with_line(const std::vector::value, typename LineType::Scalar, double>::type; - std::vector> points_with_sq_distance{}; - for (const VectorType &p : intersections) { - points_with_sq_distance.emplace_back((p - line.a).template cast().squaredNorm(), p); + std::vector>> points_with_sq_distance{}; + for (const auto &p : intersections) { + points_with_sq_distance.emplace_back((p.first - line.a).template cast().squaredNorm(), p); } std::sort(points_with_sq_distance.begin(), points_with_sq_distance.end(), - [](const std::pair &left, std::pair &right) { - return left.first < right.first; - }); - for (size_t i = 0; i < points_with_sq_distance.size(); i++) { intersections[i] = points_with_sq_distance[i].second; } + [](const std::pair> &left, + std::pair> &right) { return left.first < right.first; }); + for (size_t i = 0; i < points_with_sq_distance.size(); i++) { + intersections[i] = points_with_sq_distance[i].second; + } } return intersections; @@ -290,10 +295,11 @@ inline std::vector get_intersections_with_line(const std::vector class LinesDistancer { -private: - std::vector lines; +public: using Scalar = typename LineType::Scalar; using Floating = typename std::conditional::value, Scalar, double>::type; +private: + std::vector lines; AABBTreeIndirect::Tree<2, Scalar> tree; public: @@ -313,23 +319,29 @@ public: int outside(const Vec<2, Scalar> &point) const { return point_outside_closed_contours(lines, tree, point); } // negative sign means inside - std::tuple> signed_distance_from_lines_extra(const Vec<2, Scalar> &point) const + template + std::tuple> distance_from_lines_extra(const Vec<2, Scalar> &point) const { size_t nearest_line_index_out = size_t(-1); Vec<2, Floating> nearest_point_out = Vec<2, Floating>::Zero(); Vec<2, Floating> p = point.template cast(); auto distance = AABBTreeLines::squared_distance_to_indexed_lines(lines, tree, p, nearest_line_index_out, nearest_point_out); - if (distance < 0) { return {std::numeric_limits::infinity(), nearest_line_index_out, nearest_point_out}; } + if (distance < 0) { + return {std::numeric_limits::infinity(), nearest_line_index_out, nearest_point_out}; + } distance = sqrt(distance); - distance *= outside(point); + + if (SIGNED_DISTANCE) { + distance *= outside(point); + } return {distance, nearest_line_index_out, nearest_point_out}; } - Floating signed_distance_from_lines(const Vec<2, typename LineType::Scalar> &point) const + template Floating distance_from_lines(const Vec<2, typename LineType::Scalar> &point) const { - auto [dist, idx, np] = signed_distance_from_lines_extra(point); + auto [dist, idx, np] = distance_from_lines_extra(point); return dist; } @@ -338,7 +350,7 @@ public: return all_lines_in_radius(this->lines, this->tree, point, radius * radius); } - template std::vector> intersections_with_line(const LineType &line) const + template std::vector, size_t>> intersections_with_line(const LineType &line) const { return get_intersections_with_line>(lines, tree, line); } diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 8cb95ea6c..b9817776f 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2161,11 +2161,11 @@ LayerResult GCode::process_layer( Skirt::make_skirt_loops_per_extruder_1st_layer(print, layer_tools, m_skirt_done) : Skirt::make_skirt_loops_per_extruder_other_layers(print, layer_tools, m_skirt_done); - if (this->config().avoid_curled_filament_during_travels) { - m_avoid_curled_filaments.clear(); + if (this->config().avoid_crossing_curled_overhangs) { + m_avoid_crossing_curled_overhangs.clear(); for (const ObjectLayerToPrint &layer_to_print : layers) { - m_avoid_curled_filaments.add_obstacles(layer_to_print.object_layer, Point(scaled(this->origin()))); - m_avoid_curled_filaments.add_obstacles(layer_to_print.support_layer, Point(scaled(this->origin()))); + m_avoid_crossing_curled_overhangs.add_obstacles(layer_to_print.object_layer, Point(scaled(this->origin()))); + m_avoid_crossing_curled_overhangs.add_obstacles(layer_to_print.support_layer, Point(scaled(this->origin()))); } } @@ -2916,7 +2916,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de bool variable_speed = false; std::vector new_points{}; if (this->m_config.enable_dynamic_overhang_speeds && !this->on_first_layer() && is_perimeter(path.role())) { - new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, m_config.overhang_steepness_levels, + new_points = m_extrusion_quality_estimator.estimate_extrusion_quality(path, m_config.overhang_overlap_levels, m_config.dynamic_overhang_speeds, m_config.get_abs_value("external_perimeter_speed"), speed); variable_speed = std::any_of(new_points.begin(), new_points.end(), [speed](const ProcessedPoint &p) { return p.speed != speed; }); @@ -3040,13 +3040,13 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string this->origin in order to get G-code coordinates. */ Polyline travel { this->last_pos(), point }; - if (this->config().avoid_curled_filament_during_travels) { + if (this->config().avoid_crossing_curled_overhangs) { if (m_config.avoid_crossing_perimeters) { BOOST_LOG_TRIVIAL(warning) - << "Option >avoid curled filament during travels< is not compatible with avoid crossing perimeters and it will be ignored!"; + << "Option >avoid crossing curled overhangs< is not compatible with avoid crossing perimeters and it will be ignored!"; } else { Point scaled_origin = Point(scaled(this->origin())); - travel = m_avoid_curled_filaments.find_path(this->last_pos() + scaled_origin, point + scaled_origin); + travel = m_avoid_crossing_curled_overhangs.find_path(this->last_pos() + scaled_origin, point + scaled_origin); travel.translate(-scaled_origin); } } diff --git a/src/libslic3r/GCode.hpp b/src/libslic3r/GCode.hpp index 9d1a2449b..09442cf0f 100644 --- a/src/libslic3r/GCode.hpp +++ b/src/libslic3r/GCode.hpp @@ -352,7 +352,7 @@ private: OozePrevention m_ooze_prevention; Wipe m_wipe; AvoidCrossingPerimeters m_avoid_crossing_perimeters; - JPSPathFinder m_avoid_curled_filaments; + JPSPathFinder m_avoid_crossing_curled_overhangs; RetractWhenCrossingPerimeters m_retract_when_crossing_perimeters; bool m_enable_loop_clipping; // If enabled, the G-code generator will put following comments at the ends diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index a0495dd58..5a13e5484 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -39,9 +39,9 @@ public: void add_point(float distance, float angle) { total_distance += distance; - total_curvature += std::abs(angle); + total_curvature += angle; distances.push_back(distance); - angles.push_back(std::abs(angle)); + angles.push_back(angle); while (distances.size() > 1 && total_distance > window_size) { total_distance -= distances.front(); @@ -53,8 +53,6 @@ public: float get_curvature() const { - if (total_distance < EPSILON) { return 0.0; } - return total_curvature / window_size; } @@ -69,24 +67,33 @@ public: class CurvatureEstimator { - static const size_t sliders_count = 2; - SlidingWindowCurvatureAccumulator sliders[sliders_count] = {{1.5}, {3.0}}; + 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); } + if (distance < EPSILON) + return; + for (SlidingWindowCurvatureAccumulator &slider : sliders) { + slider.add_point(distance, angle); + } } float get_curvature() { - float max_curvature = std::numeric_limits::min(); - for (const SlidingWindowCurvatureAccumulator &slider : sliders) { max_curvature = std::max(max_curvature, slider.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(); } + for (SlidingWindowCurvatureAccumulator &slider : sliders) { + slider.reset(); + } } }; @@ -102,45 +109,68 @@ struct ExtendedPoint float curvature; }; -template -std::vector estimate_points_properties(const std::vector

&extrusion_points, +template +std::vector estimate_points_properties(const std::vector

&input_points, const AABBTreeLines::LinesDistancer &unscaled_prev_layer, - float flow_width) + float flow_width, + float max_line_length = -1.0f) { - if (extrusion_points.empty()) return {}; - float boundary_offset = PREV_LAYER_BOUNDARY_ONLY ? 0.5 * flow_width : 0.0f; + using AABBScalar = typename AABBTreeLines::LinesDistancer::Scalar; + if (input_points.empty()) + return {}; + float boundary_offset = PREV_LAYER_BOUNDARY_OFFSET ? 0.5 * flow_width : 0.0f; CurvatureEstimator cestim; - float min_malformation_dist = 0.55 * flow_width; + auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast(); }; + + std::vector

extrusion_points; + { + if (max_line_length <= 0) { + extrusion_points = input_points; + } else { + extrusion_points.reserve(input_points.size() * 2); + for (size_t i = 0; i + 1 < input_points.size(); i++) { + const P &curr = input_points[i]; + const P &next = input_points[i + 1]; + extrusion_points.push_back(curr); + auto len = maybe_unscale(next - curr).squaredNorm(); + double t = sqrt((max_line_length * max_line_length) / len); + size_t new_point_count = 1.0 / (t + EPSILON); + for (size_t j = 1; j < new_point_count + 1; j++) { + extrusion_points.push_back(curr * (1.0 - j * t) + next * (j * t)); + } + } + extrusion_points.push_back(input_points.back()); + } + } std::vector points; points.reserve(extrusion_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1)); - auto maybe_unscale = [](const P &p) { return SCALED_INPUT ? unscaled(p) : p.template cast(); }; { ExtendedPoint start_point{maybe_unscale(extrusion_points.front())}; - auto [distance, nearest_line, x] = unscaled_prev_layer.signed_distance_from_lines_extra(start_point.position); + auto [distance, nearest_line, x] = unscaled_prev_layer.template distance_from_lines_extra(start_point.position.cast()); start_point.distance = distance + boundary_offset; start_point.nearest_prev_layer_line = nearest_line; points.push_back(start_point); } for (size_t i = 1; i < extrusion_points.size(); i++) { ExtendedPoint next_point{maybe_unscale(extrusion_points[i])}; - auto [distance, nearest_line, x] = unscaled_prev_layer.signed_distance_from_lines_extra(next_point.position); + auto [distance, nearest_line, x] = unscaled_prev_layer.template distance_from_lines_extra(next_point.position.cast()); next_point.distance = distance + boundary_offset; next_point.nearest_prev_layer_line = nearest_line; if (ADD_INTERSECTIONS && ((points.back().distance > boundary_offset + EPSILON) != (next_point.distance > boundary_offset + EPSILON))) { const ExtendedPoint &prev_point = points.back(); - auto intersections = unscaled_prev_layer.template intersections_with_line(L{prev_point.position, next_point.position}); + auto intersections = unscaled_prev_layer.template intersections_with_line(L{prev_point.position.cast(), next_point.position.cast()}); for (const auto &intersection : intersections) { - points.emplace_back(intersection, boundary_offset); + points.emplace_back(intersection.first.template cast(), boundary_offset, intersection.second); } } points.push_back(next_point); } - if (PREV_LAYER_BOUNDARY_ONLY && ADD_INTERSECTIONS) { + if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) { std::vector new_points; new_points.reserve(points.size() * 2); new_points.push_back(points.front()); @@ -159,12 +189,12 @@ std::vector estimate_points_properties(const std::vector

if (t0 < 1.0) { auto p0 = curr.position + t0 * (next.position - curr.position); - auto [p0_dist, p0_near_l, p0_x] = unscaled_prev_layer.signed_distance_from_lines_extra(p0); + auto [p0_dist, p0_near_l, p0_x] = unscaled_prev_layer.template distance_from_lines_extra(p0.cast()); new_points.push_back(ExtendedPoint{p0, float(p0_dist + boundary_offset), p0_near_l}); } if (t1 > 0.0) { auto p1 = curr.position + t1 * (next.position - curr.position); - auto [p1_dist, p1_near_l, p1_x] = unscaled_prev_layer.signed_distance_from_lines_extra(p1); + auto [p1_dist, p1_near_l, p1_x] = unscaled_prev_layer.template distance_from_lines_extra(p1.cast()); new_points.push_back(ExtendedPoint{p1, float(p1_dist + boundary_offset), p1_near_l}); } } @@ -194,10 +224,8 @@ std::vector estimate_points_properties(const std::vector

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); - if (CONCAVITY_RESETS_CURVATURE && alfa < 0.0) { cestim.reset(); } } - if (a.distance < min_malformation_dist) { cestim.reset(); } a.curvature = cestim.get_curvature(); } @@ -241,10 +269,23 @@ public: speed_sections.push_back({distance, speed}); } std::sort(speed_sections.begin(), speed_sections.end(), - [](const std::pair &a, const std::pair &b) { return a.first < b.first; }); + [](const std::pair &a, const std::pair &b) { + if (a.first == b.first) { + return a.second > b.second; + } + return a.first < b.first; }); + + std::pair last_section{INFINITY, 0}; + for (auto §ion : speed_sections) { + if (section.first == last_section.first) { + section.second = last_section.second; + } else { + last_section = section; + } + } std::vector extended_points = - estimate_points_properties(path.polyline.points, prev_layer_boundaries[current_object], path.width); + estimate_points_properties(path.polyline.points, prev_layer_boundaries[current_object], path.width); std::vector processed_points; processed_points.reserve(extended_points.size()); diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index c92ff8212..685855721 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -1071,7 +1071,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) for (SeamCandidate &perimeter_point : layers[layer_idx].points) { Vec2f point = Vec2f { perimeter_point.position.head<2>() }; if (prev_layer_distancer.get() != nullptr) { - perimeter_point.overhang = prev_layer_distancer->signed_distance_from_lines(point.cast()) + perimeter_point.overhang = prev_layer_distancer->distance_from_lines(point.cast()) + 0.6f * perimeter_point.perimeter.flow_width - tan(SeamPlacer::overhang_angle_threshold) * po->layers()[layer_idx]->height; @@ -1080,7 +1080,7 @@ void SeamPlacer::calculate_overhangs_and_layer_embedding(const PrintObject *po) } if (should_compute_layer_embedding) { // search for embedded perimeter points (points hidden inside the print ,e.g. multimaterial join, best position for seam) - perimeter_point.embedded_distance = current_layer_distancer->signed_distance_from_lines(point.cast()) + perimeter_point.embedded_distance = current_layer_distancer->distance_from_lines(point.cast()) + 0.6f * perimeter_point.perimeter.flow_width; } } diff --git a/src/libslic3r/Layer.hpp b/src/libslic3r/Layer.hpp index 024ed41a4..cfeace67b 100644 --- a/src/libslic3r/Layer.hpp +++ b/src/libslic3r/Layer.hpp @@ -324,7 +324,7 @@ public: coordf_t height; // layer height in unscaled coordinates coordf_t bottom_z() const { return this->print_z - this->height; } - //Lines estimated to be seriously malformed, info from the IssueSearch algorithm. These lines should probably be avoided during fast travels. + //Extrusions estimated to be seriously malformed, estimated during "Estimating curled extrusions" step. These lines should be avoided during fast travels. Lines malformed_lines; // Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index c700c45f8..15210b641 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -664,11 +664,11 @@ bool paths_touch(const ExtrusionPath &path_one, const ExtrusionPath &path_two, d AABBTreeLines::LinesDistancer lines_two{path_two.as_polyline().lines()}; for (size_t pt_idx = 0; pt_idx < path_one.polyline.size(); pt_idx++) { - if (std::abs(lines_two.signed_distance_from_lines(path_one.polyline.points[pt_idx])) < limit_distance) { return true; } + if (lines_two.distance_from_lines(path_one.polyline.points[pt_idx]) < limit_distance) { return true; } } for (size_t pt_idx = 0; pt_idx < path_two.polyline.size(); pt_idx++) { - if (std::abs(lines_one.signed_distance_from_lines(path_two.polyline.points[pt_idx])) < limit_distance) { return true; } + if (lines_one.distance_from_lines(path_two.polyline.points[pt_idx]) < limit_distance) { return true; } } return false; } @@ -831,23 +831,21 @@ std::tuple, Polygons> generate_extra_perimeters_over std::vector anchor_areas_w_delta_anchor_size{}; for (double delta : deltas) { + // for each delta, store anchors without the delta region around overhangs anchor_areas_w_delta_anchor_size.push_back(diff(anchors, expand(overhangs, delta, EXTRA_PERIMETER_OFFSET_PARAMETERS))); } for (size_t i = 0; i < anchor_areas_w_delta_anchor_size.size() - 1; i++) { - Polygons clipped = diff(anchor_areas_w_delta_anchor_size[i], expand(anchor_areas_w_delta_anchor_size[i + 1], + // Then, clip off each anchor area by the next area expanded back to original size, so that this smaller anchor region is only where larger wouldnt fit + anchor_areas_w_delta_anchor_size[i] = diff(anchor_areas_w_delta_anchor_size[i], expand(anchor_areas_w_delta_anchor_size[i + 1], deltas[i + 1], EXTRA_PERIMETER_OFFSET_PARAMETERS)); - anchor_areas_w_delta_anchor_size[i] = intersection(anchor_areas_w_delta_anchor_size[i], - expand(clipped, deltas[i+1] + 0.1*overhang_flow.scaled_spacing(), - EXTRA_PERIMETER_OFFSET_PARAMETERS)); } for (size_t i = 0; i < anchor_areas_w_delta_anchor_size.size(); i++) { inset_anchors = union_(inset_anchors, anchor_areas_w_delta_anchor_size[i]); } - inset_anchors = opening(inset_anchors, 0.8 * deltas[0], EXTRA_PERIMETER_OFFSET_PARAMETERS); - inset_anchors = closing(inset_anchors, 0.8 * deltas[0], EXTRA_PERIMETER_OFFSET_PARAMETERS); + inset_anchors = expand(inset_anchors, 0.1*overhang_flow.scaled_width()); #ifdef EXTRA_PERIM_DEBUG_FILES { @@ -901,12 +899,6 @@ std::tuple, Polygons> generate_extra_perimeters_over Polygon anchoring_convex_hull = Geometry::convex_hull(anchoring); double unbridgeable_area = area(diff(real_overhang, {anchoring_convex_hull})); - // penalize also holes - for (const Polygon &poly : perimeter_polygon) { - if (poly.is_clockwise()) { // hole, penalize bridges. - unbridgeable_area += std::abs(area(poly)); - } - } auto [dir, unsupp_dist] = detect_bridging_direction(real_overhang, anchors); @@ -920,16 +912,19 @@ std::tuple, Polygons> generate_extra_perimeters_over for (const Line &line : to_lines(anchoring_convex_hull)) svg.draw(line, "green", scale_(0.15)); for (const Line &line : to_lines(anchoring)) svg.draw(line, "yellow", scale_(0.10)); for (const Line &line : to_lines(diff_ex(perimeter_polygon, {anchoring_convex_hull}))) svg.draw(line, "black", scale_(0.10)); + for (const Line &line : to_lines(diff_pl(to_polylines(diff(real_overhang, anchors)), expand(anchors, float(SCALED_EPSILON))))) + svg.draw(line, "blue", scale_(0.30)); svg.Close(); } #endif - if (unbridgeable_area < 0.2 * area(real_overhang) && unsupp_dist < total_length(real_overhang) * 0.125) { + + if (unbridgeable_area < 0.2 * area(real_overhang) && unsupp_dist < total_length(real_overhang) * 0.2) { inset_overhang_area_left_unfilled.insert(inset_overhang_area_left_unfilled.end(),overhang_to_cover.begin(),overhang_to_cover.end()); perimeter_polygon.clear(); } else { // fill the overhang with perimeters int continuation_loops = 2; - while (continuation_loops > 0) { + while (continuation_loops >= 0) { auto prev = perimeter_polygon; // prepare next perimeter lines Polylines perimeter = intersection_pl(to_polylines(perimeter_polygon), shrinked_overhang_to_cover); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 842638efc..206844b7b 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -420,7 +420,7 @@ void Preset::set_visible_from_appconfig(const AppConfig &app_config) static std::vector s_Preset_print_options { "layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "slicing_mode", "top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness", - "extra_perimeters", "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "avoid_curled_filament_during_travels", "avoid_crossing_perimeters", "thin_walls", "overhangs", + "extra_perimeters", "extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "avoid_crossing_curled_overhangs", "avoid_crossing_perimeters", "thin_walls", "overhangs", "seam_position","staggered_inner_seams", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern", "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", @@ -429,7 +429,7 @@ static std::vector s_Preset_print_options { "fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_dist", "max_volumetric_extrusion_rate_slope_positive", "max_volumetric_extrusion_rate_slope_negative", "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "infill_speed", "solid_infill_speed", - "enable_dynamic_overhang_speeds", "dynamic_overhang_speeds", "overhang_steepness_levels", + "enable_dynamic_overhang_speeds", "dynamic_overhang_speeds", "overhang_overlap_levels", "top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed", "bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "first_layer_speed_over_raft", "perimeter_acceleration", "infill_acceleration", "bridge_acceleration", "first_layer_acceleration", "first_layer_acceleration_over_raft", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield", diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 4e230dc6d..79fee4672 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -222,7 +222,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n osteps.emplace_back(posInfill); osteps.emplace_back(posSupportMaterial); steps.emplace_back(psSkirtBrim); - } else if (opt_key == "avoid_curled_filament_during_travels") { + } else if (opt_key == "avoid_crossing_curled_overhangs") { osteps.emplace_back(posEstimateCurledExtrusions); } else { // for legacy, if we can't handle this option let's invalidate all steps diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 2f5c4e96b..31e78d714 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -222,7 +222,6 @@ public: all_regions.clear(); layer_ranges.clear(); cached_volume_ids.clear(); - generated_support_points.reset(); } private: diff --git a/src/libslic3r/PrintBase.cpp b/src/libslic3r/PrintBase.cpp index b0aa7bd1e..d9b3e9cda 100644 --- a/src/libslic3r/PrintBase.cpp +++ b/src/libslic3r/PrintBase.cpp @@ -13,7 +13,7 @@ namespace Slic3r { -void PrintTryCancel::operator()() +void PrintTryCancel::operator()() const { m_print->throw_if_canceled(); } diff --git a/src/libslic3r/PrintBase.hpp b/src/libslic3r/PrintBase.hpp index 6aac560a3..d218146ac 100644 --- a/src/libslic3r/PrintBase.hpp +++ b/src/libslic3r/PrintBase.hpp @@ -340,7 +340,7 @@ class PrintTryCancel { public: // calls print.throw_if_canceled(). - void operator()(); + void operator()() const; private: friend PrintBase; PrintTryCancel() = delete; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index af2ce3b66..1c2947099 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -400,10 +400,10 @@ void PrintConfigDef::init_fff_params() // Maximum extruder temperature, bumped to 1500 to support printing of glass. const int max_temp = 1500; - def = this->add("avoid_curled_filament_during_travels", coBool); - def->label = L("Avoid curled filament during travels"); - def->tooltip = L("Plan travel moves such that the extruder avoids areas where filament may be curled up. " - "This is mostly happening on steeper rounded overhangs and may cause crash or borken print. " + def = this->add("avoid_crossing_curled_overhangs", coBool); + def->label = L("Avoid crossing curled overhangs (Experimental)"); + def->tooltip = L("Plan travel moves such that the extruder avoids areas where the filament may be curled up. " + "This is mostly happening on steeper rounded overhangs and may cause a crash with the nozzle. " "This feature slows down both the print and the G-code generation."); def->mode = comExpert; def->set_default_value(new ConfigOptionBool(false)); @@ -536,11 +536,15 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(true)); - def = this->add("overhang_steepness_levels", coPercents); - def->full_label = L("Steepness levels of overhangs"); + def = this->add("overhang_overlap_levels", coPercents); + def->full_label = L("Overhang overlap levels"); def->category = L("Speed"); - def->tooltip = L("Controls overhang steepness, expressed as percentage of overlap of the extrusion with the previous layer. " - "Each overhang level then corresponds with the overhang speed below."); + def->tooltip = L("Controls overhang levels, expressed as a percentage of overlap of the extrusion with the previous layer - " + "100% represents full overlap - no overhang is present, while 0% represents full overhang (floating extrusion). " + "Each overhang level then corresponds with the overhang speed below. Speeds for overhang levels in between are " + "calculated via linear interpolation." + "If you set multiple different speeds for the same overhang level, only the largest speed is used. " + ); def->sidetext = L("%"); def->min = 0; def->max = 100; @@ -550,7 +554,8 @@ void PrintConfigDef::init_fff_params() def = this->add("dynamic_overhang_speeds", coFloatsOrPercents); def->full_label = L("Dynamic speed on overhangs"); def->category = L("Speed"); - def->tooltip = L("This setting controls the speed on the overhang with steepness value above. " + def->tooltip = L("This setting controls the speed on the overhang with the overlap value set above. " + "The speed of the extrusion is calculated as a linear interpolation of the speeds for higher and lower overlap. " "If set as percentage, the speed is calculated over the external perimeter speed." ); def->sidetext = L("mm/s or %"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 7f8d5df12..a36125a07 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -565,7 +565,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloatOrPercent, external_perimeter_extrusion_width)) ((ConfigOptionFloatOrPercent, external_perimeter_speed)) ((ConfigOptionBool, enable_dynamic_overhang_speeds)) - ((ConfigOptionPercents, overhang_steepness_levels)) + ((ConfigOptionPercents, overhang_overlap_levels)) ((ConfigOptionFloatsOrPercents, dynamic_overhang_speeds)) ((ConfigOptionBool, external_perimeters_first)) ((ConfigOptionBool, extra_perimeters)) @@ -732,7 +732,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( PrintConfig, (MachineEnvelopeConfig, GCodeConfig), - ((ConfigOptionBool, avoid_curled_filament_during_travels)) + ((ConfigOptionBool, avoid_crossing_curled_overhangs)) ((ConfigOptionBool, avoid_crossing_perimeters)) ((ConfigOptionFloatOrPercent, avoid_crossing_perimeters_max_detour)) ((ConfigOptionPoints, bed_shape)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 24a4191c1..5423a3ad1 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -7,6 +7,7 @@ #include "I18N.hpp" #include "Layer.hpp" #include "MutablePolygon.hpp" +#include "PrintBase.hpp" #include "SupportMaterial.hpp" #include "TreeSupport.hpp" #include "Surface.hpp" @@ -420,8 +421,9 @@ void PrintObject::generate_support_spots() BOOST_LOG_TRIVIAL(debug) << "Searching support spots - start"; m_print->set_status(75, L("Searching support spots")); if (!this->shared_regions()->generated_support_points.has_value()) { + PrintTryCancel cancel_func = m_print->make_try_cancel(); SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values}; - SupportSpotsGenerator::SupportPoints supp_points = SupportSpotsGenerator::full_search(this, params); + SupportSpotsGenerator::SupportPoints supp_points = SupportSpotsGenerator::full_search(this, cancel_func, params); this->m_shared_regions->generated_support_points = {this->trafo_centered(), supp_points}; m_print->throw_if_canceled(); } @@ -454,7 +456,7 @@ void PrintObject::generate_support_material() void PrintObject::estimate_curled_extrusions() { if (this->set_started(posEstimateCurledExtrusions)) { - if (this->print()->config().avoid_curled_filament_during_travels) { + if (this->print()->config().avoid_crossing_curled_overhangs) { BOOST_LOG_TRIVIAL(debug) << "Estimating areas with curled extrusions - start"; m_print->set_status(88, L("Estimating curled extrusions")); @@ -463,7 +465,6 @@ void PrintObject::estimate_curled_extrusions() SupportSpotsGenerator::Params params{this->print()->m_config.filament_type.values}; SupportSpotsGenerator::estimate_supports_malformations(this->support_layers(), support_flow_width, params); SupportSpotsGenerator::estimate_malformations(this->layers(), params); - m_print->throw_if_canceled(); BOOST_LOG_TRIVIAL(debug) << "Estimating areas with curled extrusions - end"; } @@ -749,7 +750,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "support_material_interface_speed" || opt_key == "bridge_speed" || opt_key == "enable_dynamic_overhang_speeds" - || opt_key == "overhang_steepness_levels" + || opt_key == "overhang_overlap_levels" || opt_key == "dynamic_overhang_speeds" || opt_key == "external_perimeter_speed" || opt_key == "infill_speed" @@ -787,10 +788,10 @@ bool PrintObject::invalidate_step(PrintObjectStep step) } else if (step == posPrepareInfill) { invalidated |= this->invalidate_steps({ posInfill, posIroning }); } else if (step == posInfill) { - invalidated |= this->invalidate_steps({ posIroning }); + invalidated |= this->invalidate_steps({ posIroning, posSupportSpotsSearch }); invalidated |= m_print->invalidate_steps({ psSkirtBrim }); } else if (step == posSlice) { - invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportMaterial, posEstimateCurledExtrusions }); + invalidated |= this->invalidate_steps({ posPerimeters, posPrepareInfill, posInfill, posIroning, posSupportSpotsSearch, posSupportMaterial, posEstimateCurledExtrusions }); invalidated |= m_print->invalidate_steps({ psSkirtBrim }); m_slicing_params.valid = false; } else if (step == posSupportMaterial) { diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index 3d061269a..68a8a4011 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -3,23 +3,28 @@ #include "ExPolygon.hpp" #include "ExtrusionEntity.hpp" #include "ExtrusionEntityCollection.hpp" +#include "GCode/ExtrusionProcessor.hpp" #include "Line.hpp" #include "Point.hpp" #include "Polygon.hpp" #include "Print.hpp" +#include "PrintBase.hpp" #include "Tesselate.hpp" #include "libslic3r.h" #include "tbb/parallel_for.h" #include "tbb/blocked_range.h" #include "tbb/blocked_range2d.h" #include "tbb/parallel_reduce.h" +#include #include #include +#include #include #include #include #include #include +#include #include #include "AABBTreeLines.hpp" @@ -41,12 +46,14 @@ namespace Slic3r { class ExtrusionLine { public: - ExtrusionLine() : a(Vec2f::Zero()), b(Vec2f::Zero()), len(0.0f), origin_entity(nullptr) {} - ExtrusionLine(const Vec2f &a, const Vec2f &b, const ExtrusionEntity *origin_entity) - : a(a), b(b), len((a - b).norm()), origin_entity(origin_entity) + ExtrusionLine() : a(Vec2f::Zero()), b(Vec2f::Zero()), len(0.0), origin_entity(nullptr) {} + ExtrusionLine(const Vec2f &a, const Vec2f &b, float len, const ExtrusionEntity *origin_entity) + : a(a), b(b), len(len), origin_entity(origin_entity) {} - float length() { return (a - b).norm(); } + ExtrusionLine(const Vec2f &a, const Vec2f &b) + : a(a), b(b), len((a-b).norm()), origin_entity(nullptr) + {} bool is_external_perimeter() const { @@ -60,7 +67,8 @@ public: const ExtrusionEntity *origin_entity; bool support_point_generated = false; - float malformation = 0.0f; + float form_quality = 1.0f; + float curled_up_height = 0.0f; static const constexpr int Dim = 2; using Scalar = Vec2f::Scalar; @@ -174,38 +182,12 @@ float get_flow_width(const LayerRegion *region, ExtrusionRole role) } } -// Accumulator of current extrusion path properties -// It remembers unsuported distance and maximum accumulated curvature over that distance. -// Used to determine local stability issues (too long bridges, extrusion curves into air) -struct ExtrusionPropertiesAccumulator -{ - float distance = 0; // accumulated distance - float curvature = 0; // accumulated signed ccw angles - float max_curvature = 0; // max absolute accumulated value - - void add_distance(float dist) { distance += dist; } - - void add_angle(float ccw_angle) - { - curvature += ccw_angle; - max_curvature = std::max(max_curvature, std::abs(curvature)); - } - - void reset() - { - distance = 0; - curvature = 0; - max_curvature = 0; - } -}; - std::vector to_short_lines(const ExtrusionEntity *e, float length_limit) { assert(!e->is_collection()); Polyline pl = e->as_polyline(); std::vector lines; lines.reserve(pl.points.size() * 1.5f); - lines.emplace_back(unscaled(pl.points[0]).cast(), unscaled(pl.points[0]).cast(), e); for (int point_idx = 0; point_idx < int(pl.points.size()) - 1; ++point_idx) { Vec2f start = unscaled(pl.points[point_idx]).cast(); Vec2f next = unscaled(pl.points[point_idx + 1]).cast(); @@ -217,87 +199,102 @@ std::vector to_short_lines(const ExtrusionEntity *e, float length for (int i = 0; i < lines_count; ++i) { Vec2f a(start + v * (i * step_size)); Vec2f b(start + v * ((i + 1) * step_size)); - lines.emplace_back(a, b, e); + lines.emplace_back(a, b, (a-b).norm(), e); } } return lines; } -std::vector check_extrusion_entity_stability(const ExtrusionEntity *entity, - const LayerRegion *layer_region, - const LD &prev_layer_lines, - const Params ¶ms) +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; + if (fabs(point.distance) < 1.5 * flow_width) { + curled_up_height = 0.85 * 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 * 2.0f * sqrt(sqrt(dist_factor)) * std::clamp(6.0f * point.curvature, 1.0f, 6.0f); + curled_up_height = std::min(curled_up_height, params.max_curled_height_factor * layer_height); + } + + return curled_up_height; +} + +std::vector check_extrusion_entity_stability(const ExtrusionEntity *entity, + const LayerRegion *layer_region, + const LD &prev_layer_lines, + const AABBTreeLines::LinesDistancer &prev_layer_boundary, + const Params ¶ms) { if (entity->is_collection()) { std::vector checked_lines_out; checked_lines_out.reserve(prev_layer_lines.get_lines().size() / 3); for (const auto *e : static_cast(entity)->entities) { - auto tmp = check_extrusion_entity_stability(e, layer_region, prev_layer_lines, params); + auto tmp = check_extrusion_entity_stability(e, layer_region, prev_layer_lines, prev_layer_boundary, params); checked_lines_out.insert(checked_lines_out.end(), tmp.begin(), tmp.end()); } return checked_lines_out; } else { // single extrusion path, with possible varying parameters - if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) { return {}; } - - std::vector lines = to_short_lines(entity, params.bridge_distance); - - ExtrusionPropertiesAccumulator bridging_acc{}; - ExtrusionPropertiesAccumulator malformation_acc{}; - bridging_acc.add_distance(params.bridge_distance + 1.0f); - const float flow_width = get_flow_width(layer_region, entity->role()); - float min_malformation_dist = flow_width - params.malformation_overlap_factor.first * flow_width; - float max_malformation_dist = flow_width - params.malformation_overlap_factor.second * flow_width; - - for (size_t line_idx = 0; line_idx < lines.size(); ++line_idx) { - ExtrusionLine ¤t_line = lines[line_idx]; - if (line_idx + 1 == lines.size() && current_line.b != lines.begin()->a) { - bridging_acc.add_distance(params.bridge_distance + 1.0f); - } - float curr_angle = 0; - if (line_idx + 1 < lines.size()) { - const Vec2f v1 = current_line.b - current_line.a; - const Vec2f v2 = lines[line_idx + 1].b - lines[line_idx + 1].a; - curr_angle = angle(v1, v2); - } - bridging_acc.add_angle(curr_angle); - // malformation in concave angles does not happen - malformation_acc.add_angle(std::max(0.0f, curr_angle)); - if (curr_angle < -20.0 * PI / 180.0) { malformation_acc.reset(); } - - auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.signed_distance_from_lines_extra(current_line.b); - if (dist_from_prev_layer < flow_width) { - bridging_acc.reset(); - } else { - bridging_acc.add_distance(current_line.len); - // if unsupported distance is larger than bridge distance linearly decreased by curvature, enforce supports. - bool in_layer_dist_condition = bridging_acc.distance > - params.bridge_distance / (1.0f + (bridging_acc.max_curvature * - params.bridge_distance_decrease_by_curvature_factor / PI)); - bool between_layers_condition = dist_from_prev_layer > max_malformation_dist; - if (in_layer_dist_condition && between_layers_condition) { - current_line.support_point_generated = true; - bridging_acc.reset(); - } - } - - // malformation propagation from below - if (fabs(dist_from_prev_layer) < 2.0f * flow_width) { - const ExtrusionLine &nearest_line = prev_layer_lines.get_line(nearest_line_idx); - current_line.malformation += 0.85 * nearest_line.malformation; - } - // current line maformation - if (dist_from_prev_layer > min_malformation_dist && dist_from_prev_layer < max_malformation_dist) { - float factor = std::abs(dist_from_prev_layer - (max_malformation_dist + min_malformation_dist) * 0.5) / - (max_malformation_dist - min_malformation_dist); - malformation_acc.add_distance(current_line.len); - current_line.malformation += layer_region->layer()->height * factor * (2.0f + 3.0f * (malformation_acc.max_curvature / PI)); - current_line.malformation = std::min(current_line.malformation, - float(layer_region->layer()->height * params.max_malformation_factor)); - } else { - malformation_acc.reset(); - } + if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) { + return {}; } - return lines; + + const float flow_width = get_flow_width(layer_region, entity->role()); + + std::vector annotated_points = estimate_points_properties(entity->as_polyline().points, + prev_layer_lines, flow_width, + params.bridge_distance); + + std::vector lines_out; + lines_out.reserve(annotated_points.size()); + float bridged_distance = annotated_points.front().position != annotated_points.back().position ? (params.bridge_distance + 1.0f) : + 0.0f; + 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, entity}; + + 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{}; + + 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 max_bridge_len = params.bridge_distance / + ((1.0f + std::abs(curr_point.curvature)) * (1.0f + std::abs(curr_point.curvature))); + + if (curr_point.distance > 2.0f * flow_width) { + line_out.form_quality = 0.8f; + bridged_distance += line_len; + if (bridged_distance > max_bridge_len) { + line_out.support_point_generated = true; + bridged_distance = 0.0f; + } + } else if (curr_point.distance > flow_width * (1.0 + std::clamp(curr_point.curvature, -0.30f, 0.20f))) { + bridged_distance += line_len; + line_out.form_quality = nearest_prev_layer_line.form_quality - 0.3f; + if (line_out.form_quality < 0 && bridged_distance > max_bridge_len) { + line_out.support_point_generated = true; + line_out.form_quality = 0.5f; + bridged_distance = 0.0f; + } + } else { + bridged_distance = 0.0f; + } + + line_out.curled_up_height = estimate_curled_up_height(curr_point, layer_region->layer()->height, flow_width, + nearest_prev_layer_line.curled_up_height, params); + + lines_out.push_back(line_out); + } + + return lines_out; } } @@ -474,7 +471,7 @@ public: float movement_force = params.max_acceleration * mass; float extruder_conflict_force = params.standard_extruder_conflict_force + - std::min(extruded_line.malformation, 1.0f) * params.malformations_additive_conflict_extruder_force; + std::min(extruded_line.curled_up_height, 1.0f) * params.malformations_additive_conflict_extruder_force; // section for bed calculations { @@ -512,7 +509,8 @@ public: BOOST_LOG_TRIVIAL(debug) << "SSG: bed_movement_arm: " << bed_movement_arm; BOOST_LOG_TRIVIAL(debug) << "SSG: bed_movement_torque: " << bed_movement_torque; BOOST_LOG_TRIVIAL(debug) << "SSG: bed_conflict_torque_arm: " << bed_conflict_torque_arm; - BOOST_LOG_TRIVIAL(debug) << "SSG: extruded_line.malformation: " << extruded_line.malformation; + BOOST_LOG_TRIVIAL(debug) << "SSG: extruded_line.curled_up_height: " << extruded_line.curled_up_height; + BOOST_LOG_TRIVIAL(debug) << "SSG: extruded_line.form_quality: " << extruded_line.form_quality; BOOST_LOG_TRIVIAL(debug) << "SSG: extruder_conflict_force: " << extruder_conflict_force; BOOST_LOG_TRIVIAL(debug) << "SSG: bed_extruder_conflict_torque: " << bed_extruder_conflict_torque; BOOST_LOG_TRIVIAL(debug) << "SSG: total_torque: " << bed_total_torque << " layer_z: " << layer_z; @@ -546,7 +544,7 @@ public: float conn_total_torque = conn_movement_torque + conn_extruder_conflict_torque + conn_weight_torque - conn_yield_torque; #ifdef DETAILED_DEBUG_LOGS - BOOST_LOG_TRIVIAL(debug) << "bed_centroid: " << conn_centroid.x() << " " << conn_centroid.y() << " " << conn_centroid.z(); + BOOST_LOG_TRIVIAL(debug) << "conn_centroid: " << conn_centroid.x() << " " << conn_centroid.y() << " " << conn_centroid.z(); BOOST_LOG_TRIVIAL(debug) << "SSG: conn_yield_torque: " << conn_yield_torque; BOOST_LOG_TRIVIAL(debug) << "SSG: conn_weight_arm: " << conn_weight_arm; BOOST_LOG_TRIVIAL(debug) << "SSG: conn_weight_torque: " << conn_weight_torque; @@ -580,7 +578,7 @@ std::tuple build_object_part_from_slice(const LayerSlice &sli new_object_part.volume += volume; new_object_part.volume_centroid_accumulator += to_3d(Vec2f((line.a + line.b) / 2.0f), slice_z) * volume; - if (l->id() == 0) { // first layer + if (l->bottom_z() < EPSILON) { // layer attached on bed float sticking_area = line.len * flow_width; new_object_part.sticking_area += sticking_area; Vec2f middle = Vec2f((line.a + line.b) / 2.0f); @@ -664,7 +662,7 @@ public: } }; -SupportPoints check_stability(const PrintObject *po, const Params ¶ms) +SupportPoints check_stability(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms) { SupportPoints supp_points{}; SupportGridFilter supports_presence_grid(po, params.min_distance_between_support_points); @@ -677,6 +675,7 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) std::unordered_map next_slice_idx_to_weakest_connection; for (size_t layer_idx = 0; layer_idx < po->layer_count(); ++layer_idx) { + cancel_func(); const Layer *layer = po->get_layer(layer_idx); float bottom_z = layer->bottom_z(); auto create_support_point_position = [bottom_z](const Vec2f &layer_pos) { return Vec3f{layer_pos.x(), layer_pos.y(), bottom_z}; }; @@ -756,6 +755,15 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) const LayerSlice &slice = layer->lslices_ex.at(slice_idx); ObjectPart &part = active_object_parts.access(prev_slice_idx_to_object_part_mapping[slice_idx]); SliceConnection &weakest_conn = prev_slice_idx_to_weakest_connection[slice_idx]; + + std::vector boundary_lines; + for (const auto &link : slice.overlaps_below) { + auto ls = to_unscaled_linesf({layer->lower_layer->lslices[link.slice_idx]}); + boundary_lines.insert(boundary_lines.end(), ls.begin(), ls.end()); + } + AABBTreeLines::LinesDistancer prev_layer_boundary{std::move(boundary_lines)}; + + std::vector current_slice_ext_perims_lines{}; current_slice_ext_perims_lines.reserve(prev_layer_ext_perim_lines.get_lines().size() / layer->lslices_ex.size()); #ifdef DETAILED_DEBUG_LOGS @@ -765,14 +773,17 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) // and the support presence grid and add the point to the issues. auto reckon_new_support_point = [&part, &weakest_conn, &supp_points, &supports_presence_grid, ¶ms, &layer_idx](const Vec3f &support_point, float force, const Vec2f &dir) { - if (supports_presence_grid.position_taken(support_point) || layer_idx <= 1) { return; } + if ((supports_presence_grid.position_taken(support_point) && force > 0) || layer_idx <= 1) { + return; + } float area = params.support_points_interface_radius * params.support_points_interface_radius * float(PI); part.add_support_point(support_point, area); float radius = params.support_points_interface_radius; supp_points.emplace_back(support_point, force, radius, dir); - supports_presence_grid.take_position(support_point); - + if (force > 0) { + supports_presence_grid.take_position(support_point); + } if (weakest_conn.area > EPSILON) { // Do not add it to the weakest connection if it is not valid - does not exist weakest_conn.area += area; weakest_conn.centroid_accumulator += support_point * area; @@ -791,7 +802,7 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) const ExtrusionEntity *entity = fill_region->fills().entities[fill_idx]; if (entity->role() == erBridgeInfill) { for (const ExtrusionLine &bridge : - check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines, params)) { + check_extrusion_entity_stability(entity, fill_region, prev_layer_ext_perim_lines,prev_layer_boundary, params)) { if (bridge.support_point_generated) { reckon_new_support_point(create_support_point_position(bridge.b), -EPSILON, Vec2f::Zero()); } @@ -804,7 +815,7 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) for (const auto &perimeter_idx : island.perimeters) { const ExtrusionEntity *entity = perimeter_region->perimeters().entities[perimeter_idx]; std::vector perims = check_extrusion_entity_stability(entity, perimeter_region, - prev_layer_ext_perim_lines, params); + prev_layer_ext_perim_lines,prev_layer_boundary, params); for (const ExtrusionLine &perim : perims) { if (perim.support_point_generated) { reckon_new_support_point(create_support_point_position(perim.b), -EPSILON, Vec2f::Zero()); @@ -818,13 +829,13 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) float unchecked_dist = params.min_distance_between_support_points + 1.0f; for (const ExtrusionLine &line : current_slice_ext_perims_lines) { - if ((unchecked_dist + line.len < params.min_distance_between_support_points && line.malformation < 0.3f) || line.len == 0) { + if ((unchecked_dist + line.len < params.min_distance_between_support_points && line.curled_up_height < 0.3f) || line.len < EPSILON) { unchecked_dist += line.len; } else { unchecked_dist = line.len; Vec2f pivot_site_search_point = Vec2f(line.b + (line.b - line.a).normalized() * 300.0f); auto [dist, nidx, - nearest_point] = current_slice_lines_distancer.signed_distance_from_lines_extra(pivot_site_search_point); + nearest_point] = current_slice_lines_distancer.distance_from_lines_extra(pivot_site_search_point); Vec3f support_point = create_support_point_position(nearest_point); auto force = part.is_stable_while_extruding(weakest_conn, line, support_point, bottom_z, params); if (force > 0) { reckon_new_support_point(support_point, force, (line.b - line.a).normalized()); } @@ -839,7 +850,7 @@ SupportPoints check_stability(const PrintObject *po, const Params ¶ms) } #ifdef DEBUG_FILES -void debug_export(Issues issues, std::string file_name) +void debug_export(SupportPoints support_points, std::string file_name) { Slic3r::CNumericLocalesSetter locales_setter; { @@ -849,13 +860,13 @@ void debug_export(Issues issues, std::string file_name) return; } - for (size_t i = 0; i < issues.support_points.size(); ++i) { - if (issues.support_points[i].force <= 0) { - fprintf(fp, "v %f %f %f %f %f %f\n", issues.support_points[i].position(0), issues.support_points[i].position(1), - issues.support_points[i].position(2), 0.0, 1.0, 0.0); + for (size_t i = 0; i < support_points.size(); ++i) { + if (support_points[i].force <= 0) { + fprintf(fp, "v %f %f %f %f %f %f\n", support_points[i].position(0), support_points[i].position(1), + support_points[i].position(2), 0.0, 1.0, 0.0); } else { - fprintf(fp, "v %f %f %f %f %f %f\n", issues.support_points[i].position(0), issues.support_points[i].position(1), - issues.support_points[i].position(2), 1.0, 0.0, 0.0); + fprintf(fp, "v %f %f %f %f %f %f\n", support_points[i].position(0), support_points[i].position(1), + support_points[i].position(2), 1.0, 0.0, 0.0); } } @@ -867,113 +878,84 @@ void debug_export(Issues issues, std::string file_name) // std::vector quick_search(const PrintObject *po, const Params ¶ms) { // return {}; // } -SupportPoints full_search(const PrintObject *po, const Params ¶ms) +SupportPoints full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms) { - SupportPoints supp_points = check_stability(po, params); + SupportPoints supp_points = check_stability(po, cancel_func, params); #ifdef DEBUG_FILES - debug_export(issues, "issues"); + debug_export(supp_points, "issues"); #endif return supp_points; } - -struct LayerCurlingEstimator -{ - LD prev_layer_lines; - Params params; - std::function flow_width_getter; - - LayerCurlingEstimator(std::function flow_width_getter, const Params ¶ms) - : flow_width_getter(flow_width_getter), params(params) - {} - - void estimate_curling(std::vector &extrusion_lines, Layer *l) - { - ExtrusionPropertiesAccumulator malformation_acc{}; - for (size_t line_idx = 0; line_idx < extrusion_lines.size(); ++line_idx) { - ExtrusionLine ¤t_line = extrusion_lines[line_idx]; - - float flow_width = flow_width_getter(current_line); - - float min_malformation_dist = flow_width - params.malformation_overlap_factor.first * flow_width; - float max_malformation_dist = flow_width - params.malformation_overlap_factor.second * flow_width; - - float curr_angle = 0; - if (line_idx + 1 < extrusion_lines.size()) { - const Vec2f v1 = current_line.b - current_line.a; - const Vec2f v2 = extrusion_lines[line_idx + 1].b - extrusion_lines[line_idx + 1].a; - curr_angle = angle(v1, v2); - } - // malformation in concave angles does not happen - malformation_acc.add_angle(std::max(0.0f, curr_angle)); - if (curr_angle < -20.0 * PI / 180.0) { malformation_acc.reset(); } - - auto [dist_from_prev_layer, nearest_line_idx, nearest_point] = prev_layer_lines.signed_distance_from_lines_extra(current_line.b); - - if (fabs(dist_from_prev_layer) < 2.0f * flow_width) { - const ExtrusionLine &nearest_line = prev_layer_lines.get_line(nearest_line_idx); - current_line.malformation += 0.9 * nearest_line.malformation; - } - if (dist_from_prev_layer > min_malformation_dist && dist_from_prev_layer < max_malformation_dist) { - float factor = 0.5f + 0.5f * std::abs(dist_from_prev_layer - (max_malformation_dist + min_malformation_dist) * 0.5) / - (max_malformation_dist - min_malformation_dist); - malformation_acc.add_distance(current_line.len); - current_line.malformation += l->height * factor * (1.5f + 3.0f * (malformation_acc.max_curvature / PI)); - current_line.malformation = std::min(current_line.malformation, float(l->height * params.max_malformation_factor)); - } else { - malformation_acc.reset(); - } - } - - for (const ExtrusionLine &line : extrusion_lines) { - if (line.malformation > 0.3f) { l->malformed_lines.push_back(Line{Point::new_scale(line.a), Point::new_scale(line.b)}); } - } - prev_layer_lines = LD(extrusion_lines); - } -}; - - -void estimate_supports_malformations(SupportLayerPtrs &layers, float supports_flow_width, const Params ¶ms) +void estimate_supports_malformations(SupportLayerPtrs &layers, float flow_width, const Params ¶ms) { #ifdef DEBUG_FILES FILE *debug_file = boost::nowide::fopen(debug_out_path("supports_malformations.obj").c_str(), "w"); + FILE *full_file = boost::nowide::fopen(debug_out_path("supports_full.obj").c_str(), "w"); #endif - auto flow_width_getter = [=](const ExtrusionLine& l) { - return supports_flow_width; - }; - LayerCurlingEstimator lce{flow_width_getter, params}; + AABBTreeLines::LinesDistancer prev_layer_lines{}; for (SupportLayer *l : layers) { - std::vector extrusion_lines; + std::vector current_layer_lines; + for (const ExtrusionEntity *extrusion : l->support_fills.flatten().entities) { Polyline pl = extrusion->as_polyline(); - Polygon pol(pl.points); + Polygon pol(pl.points); pol.make_counter_clockwise(); - pl = pol.split_at_first_point(); - for (int point_idx = 0; point_idx < int(pl.points.size() - 1); ++point_idx) { - Vec2f start = unscaled(pl.points[point_idx]).cast(); - Vec2f next = unscaled(pl.points[point_idx + 1]).cast(); - ExtrusionLine line{start, next, extrusion}; - extrusion_lines.push_back(line); + + 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}; + + 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{}; + + Vec2f v1 = (nearest_prev_layer_line.b - nearest_prev_layer_line.a); + Vec2f v2 = (curr_point.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; + } + + line_out.curled_up_height = estimate_curled_up_height(curr_point, l->height, flow_width, + nearest_prev_layer_line.curled_up_height, params); + + current_layer_lines.push_back(line_out); } } - lce.estimate_curling(extrusion_lines, l); + for (const ExtrusionLine &line : current_layer_lines) { + if (line.curled_up_height > 0.3f) { + l->malformed_lines.push_back(Line{Point::new_scale(line.a), Point::new_scale(line.b)}); + } + } #ifdef DEBUG_FILES - for (const ExtrusionLine &line : extrusion_lines) { - if (line.malformation > 0.3f) { - Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_malformation_factor, line.malformation); + for (const ExtrusionLine &line : current_layer_lines) { + if (line.curled_up_height > 0.3f) { + Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_curled_height_factor, line.curled_up_height); 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]); + } #endif + + prev_layer_lines = LD{current_layer_lines}; } #ifdef DEBUG_FILES fclose(debug_file); + fclose(full_file); #endif } @@ -981,52 +963,71 @@ 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"); #endif - auto flow_width_getter = [](const ExtrusionLine &l) { return 0.0; }; - LayerCurlingEstimator lce{flow_width_getter, params}; + + LD prev_layer_lines{}; for (Layer *l : layers) { - if (l->regions().empty()) { - continue; - } - struct Visitor { - Visitor(const Params ¶ms) : params(params) {} - void recursive_do(const ExtrusionEntityCollection &collection, const LayerRegion *region) { - for (const ExtrusionEntity* entity : collection.entities) - if (entity->is_collection()) - this->recursive_do(*static_cast(entity), region); - else { - append(extrusion_lines, to_short_lines(entity, params.bridge_distance)); - extrusions_widths.emplace(entity, get_flow_width(region, entity->role())); - } + std::vector boundary_lines = l->lower_layer != nullptr ? to_unscaled_linesf(l->lower_layer->lslices) : std::vector(); + AABBTreeLines::LinesDistancer prev_layer_boundary{std::move(boundary_lines)}; + std::vector current_layer_lines; + for (const LayerRegion *layer_region : l->regions()) { + for (const ExtrusionEntity *extrusion : layer_region->perimeters().flatten().entities) { + Points extrusion_pts; + extrusion->collect_points(extrusion_pts); + float flow_width = get_flow_width(layer_region, extrusion->role()); + 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}; + + 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{}; + + 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; + + line_out.curled_up_height = estimate_curled_up_height(curr_point, layer_region->layer()->height, flow_width, + nearest_prev_layer_line.curled_up_height, params); + + current_layer_lines.push_back(line_out); + } } - const Params ¶ms; - std::unordered_map extrusions_widths; - std::vector extrusion_lines; - } visitor(params); + } - for (const LayerRegion *region : l->regions()) - visitor.recursive_do(region->perimeters(), region); - - lce.flow_width_getter = [&](const ExtrusionLine &l) { return visitor.extrusions_widths[l.origin_entity]; }; - - lce.estimate_curling(visitor.extrusion_lines, l); + for (const ExtrusionLine &line : current_layer_lines) { + if (line.curled_up_height > 0.3f) { + l->malformed_lines.push_back(Line{Point::new_scale(line.a), Point::new_scale(line.b)}); + } + } #ifdef DEBUG_FILES - for (const ExtrusionLine &line : extrusion_lines) { - if (line.malformation > 0.3f) { - Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_malformation_factor, line.malformation); + for (const ExtrusionLine &line : current_layer_lines) { + if (line.curled_up_height > 0.3f) { + Vec3f color = value_to_rgbf(-EPSILON, l->height * params.max_curled_height_factor, line.curled_up_height); 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]); + } #endif + + prev_layer_lines = LD{current_layer_lines}; } #ifdef DEBUG_FILES fclose(debug_file); + fclose(full_file); #endif } -} //SupportableIssues End -} - +} // namespace SupportSpotsGenerator +} // namespace Slic3r diff --git a/src/libslic3r/SupportSpotsGenerator.hpp b/src/libslic3r/SupportSpotsGenerator.hpp index fa6761d34..1c07c1381 100644 --- a/src/libslic3r/SupportSpotsGenerator.hpp +++ b/src/libslic3r/SupportSpotsGenerator.hpp @@ -3,6 +3,7 @@ #include "Layer.hpp" #include "Line.hpp" +#include "PrintBase.hpp" #include #include @@ -22,19 +23,20 @@ struct Params { filament_type = std::string("PLA"); } else { filament_type = filament_types[0]; + BOOST_LOG_TRIVIAL(debug) + << "SupportSpotsGenerator: applying filament type: " << filament_type; } } // the algorithm should use the following units for all computations: distance [mm], mass [g], time [s], force [g*mm/s^2] const float bridge_distance = 12.0f; //mm - const float bridge_distance_decrease_by_curvature_factor = 5.0f; // allowed bridge distance = bridge_distance / (1 + this factor * (curvature / PI) ) - const std::pair malformation_overlap_factor = std::pair { 0.50, -0.1 }; - const float max_malformation_factor = 10.0f; + const std::pair malformation_distance_factors = std::pair { 0.4, 1.2 }; + const float max_curled_height_factor = 10.0f; const float min_distance_between_support_points = 3.0f; //mm const float support_points_interface_radius = 1.5f; // mm const float connections_min_considerable_area = 1.5f; //mm^2 - const float min_distance_to_allow_local_supports = 2.0f; //mm + const float min_distance_to_allow_local_supports = 1.0f; //mm std::string filament_type; const float gravity_constant = 9806.65f; // mm/s^2; gravity acceleration on Earth's surface, algorithm assumes that printer is in upwards position. @@ -42,7 +44,7 @@ struct Params { const double filament_density = 1.25e-3f; // g/mm^3 ; Common filaments are very lightweight, so precise number is not that important const double material_yield_strength = 33.0f * 1e6f; // (g*mm/s^2)/mm^2; 33 MPa is yield strength of ABS, which has the lowest yield strength from common materials. const float standard_extruder_conflict_force = 20.0f * gravity_constant; // force that can occasionally push the model due to various factors (filament leaks, small curling, ... ); - const float malformations_additive_conflict_extruder_force = 300.0f * gravity_constant; // for areas with possible high layered curled filaments + const float malformations_additive_conflict_extruder_force = 100.0f * gravity_constant; // for areas with possible high layered curled filaments // MPa * 1e^6 = (g*mm/s^2)/mm^2 = g/(mm*s^2); yield strength of the bed surface double get_bed_adhesion_yield_strength() const { @@ -76,7 +78,7 @@ struct Malformations { }; // std::vector quick_search(const PrintObject *po, const Params ¶ms); -SupportPoints full_search(const PrintObject *po, const Params ¶ms); +SupportPoints full_search(const PrintObject *po, const PrintTryCancel& cancel_func, const Params ¶ms); void estimate_supports_malformations(std::vector &layers, float supports_flow_width, const Params ¶ms); void estimate_malformations(std::vector &layers, const Params ¶ms); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 482f000f0..7f8e70e6c 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -221,11 +221,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) bool have_perimeters = config->opt_int("perimeters") > 0; for (auto el : { "extra_perimeters","extra_perimeters_on_overhangs", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", "seam_position","staggered_inner_seams", "external_perimeters_first", "external_perimeter_extrusion_width", - "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "enable_dynamic_overhang_speeds", "overhang_steepness_levels", "dynamic_overhang_speeds" }) + "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "enable_dynamic_overhang_speeds", "overhang_overlap_levels", "dynamic_overhang_speeds" }) toggle_field(el, have_perimeters); for (size_t i = 0; i < 4; i++) { - toggle_field("overhang_steepness_levels#" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); + toggle_field("overhang_overlap_levels#" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); toggle_field("dynamic_overhang_speeds#" + std::to_string(i), config->opt_bool("enable_dynamic_overhang_speeds")); } @@ -321,8 +321,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) "wipe_tower_bridging", "wipe_tower_no_sparse_layers", "single_extruder_multi_material_priming" }) toggle_field(el, have_wipe_tower); - toggle_field("avoid_curled_filament_during_travels", !config->opt_bool("avoid_crossing_perimeters")); - toggle_field("avoid_crossing_perimeters", !config->opt_bool("avoid_curled_filament_during_travels")); + toggle_field("avoid_crossing_curled_overhangs", !config->opt_bool("avoid_crossing_perimeters")); + toggle_field("avoid_crossing_perimeters", !config->opt_bool("avoid_crossing_curled_overhangs")); bool have_avoid_crossing_perimeters = config->opt_bool("avoid_crossing_perimeters"); toggle_field("avoid_crossing_perimeters_max_detour", have_avoid_crossing_perimeters); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp index f13914715..3827cd331 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoFdmSupports.cpp @@ -497,18 +497,24 @@ void GLGizmoFdmSupports::update_from_model_object() bool GLGizmoFdmSupports::has_backend_supports() { - const ModelObject* mo = m_c->selection_info()->model_object(); - if (! mo) { + const ModelObject *mo = m_c->selection_info()->model_object(); + if (!mo) { waiting_for_autogenerated_supports = false; return false; } // find PrintObject with this ID - for (const PrintObject* po : m_parent.fff_print()->objects()) { + bool done = false; + for (const PrintObject *po : m_parent.fff_print()->objects()) { if (po->model_object()->id() == mo->id()) - return po->is_step_done(posSupportSpotsSearch); + done = po->is_step_done(posSupportSpotsSearch); } - return false; + + if (!done && !wxGetApp().plater()->is_background_process_update_scheduled()) { + waiting_for_autogenerated_supports = false; + } + + return done; } void GLGizmoFdmSupports::reslice_FDM_supports(bool postpone_error_messages) const { diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 796ce622b..0b0cfc8ae 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1425,7 +1425,7 @@ void TabPrint::build() optgroup->append_single_option_line("extra_perimeters", category_path + "extra-perimeters-if-needed"); optgroup->append_single_option_line("extra_perimeters_on_overhangs", category_path + "extra-perimeters-on-overhangs"); optgroup->append_single_option_line("ensure_vertical_shell_thickness", category_path + "ensure-vertical-shell-thickness"); - optgroup->append_single_option_line("avoid_curled_filament_during_travels", category_path + "avoid-curled-filament-during-travels"); + optgroup->append_single_option_line("avoid_crossing_curled_overhangs", category_path + "avoid-crossing-curled-overhangs"); optgroup->append_single_option_line("avoid_crossing_perimeters", category_path + "avoid-crossing-perimeters"); optgroup->append_single_option_line("avoid_crossing_perimeters_max_detour", category_path + "avoid_crossing_perimeters_max_detour"); optgroup->append_single_option_line("thin_walls", category_path + "detect-thin-walls"); @@ -1548,7 +1548,7 @@ void TabPrint::build() optgroup->append_line(line); }; optgroup->append_single_option_line("enable_dynamic_overhang_speeds"); - append_option_line(optgroup,"overhang_steepness_levels"); + append_option_line(optgroup,"overhang_overlap_levels"); append_option_line(optgroup,"dynamic_overhang_speeds"); optgroup = page->new_optgroup(L("Speed for non-print moves"));