diff --git a/src/libslic3r/GCode/ExtrusionProcessor.hpp b/src/libslic3r/GCode/ExtrusionProcessor.hpp index 5a13e5484..7d8cc4c73 100644 --- a/src/libslic3r/GCode/ExtrusionProcessor.hpp +++ b/src/libslic3r/GCode/ExtrusionProcessor.hpp @@ -122,39 +122,18 @@ std::vector estimate_points_properties(const std::vector

CurvatureEstimator cestim; 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)); + points.reserve(input_points.size() * (ADD_INTERSECTIONS ? 1.5 : 1)); { - ExtendedPoint start_point{maybe_unscale(extrusion_points.front())}; + ExtendedPoint start_point{maybe_unscale(input_points.front())}; 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])}; + for (size_t i = 1; i < input_points.size(); i++) { + ExtendedPoint next_point{maybe_unscale(input_points[i])}; 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; @@ -172,7 +151,7 @@ std::vector estimate_points_properties(const std::vector

if (PREV_LAYER_BOUNDARY_OFFSET && ADD_INTERSECTIONS) { std::vector new_points; - new_points.reserve(points.size() * 2); + new_points.reserve(points.size()*2); new_points.push_back(points.front()); for (int point_idx = 0; point_idx < int(points.size()) - 1; ++point_idx) { const ExtendedPoint &curr = points[point_idx]; @@ -201,7 +180,30 @@ std::vector estimate_points_properties(const std::vector

} new_points.push_back(next); } - points = std::move(new_points); + points = new_points; + } + + if (max_line_length > 0) { + std::vector new_points; + new_points.reserve(points.size()*2); + { + for (size_t i = 0; i + 1 < points.size(); i++) { + const ExtendedPoint &curr = points[i]; + const ExtendedPoint &next = points[i + 1]; + new_points.push_back(curr); + double len = (next.position - curr.position).squaredNorm(); + double t = sqrt((max_line_length * max_line_length) / len); + size_t new_point_count = 1.0 / t; + for (size_t j = 1; j < new_point_count + 1; j++) { + Vec2d pos = curr.position * (1.0 - j * t) + next.position * (j * t); + auto [p_dist, p_near_l, + p_x] = unscaled_prev_layer.template distance_from_lines_extra(pos.cast()); + new_points.push_back(ExtendedPoint{pos, float(p_dist + boundary_offset), p_near_l}); + } + } + new_points.push_back(new_points.back()); + } + points = new_points; } for (int point_idx = 0; point_idx < int(points.size()); ++point_idx) { diff --git a/src/libslic3r/SupportSpotsGenerator.cpp b/src/libslic3r/SupportSpotsGenerator.cpp index ecc03e3db..73eae069f 100644 --- a/src/libslic3r/SupportSpotsGenerator.cpp +++ b/src/libslic3r/SupportSpotsGenerator.cpp @@ -237,13 +237,66 @@ std::vector check_extrusion_entity_stability(const ExtrusionEntit checked_lines_out.insert(checked_lines_out.end(), tmp.begin(), tmp.end()); } return checked_lines_out; + } else if (entity->role().is_bridge() && !entity->role().is_perimeter()) { + // pure bridges are handled separately, beacuse we need to align the forward and backward direction support points + if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) { + return {}; + } + const float flow_width = get_flow_width(layer_region, entity->role()); + std::vector annotated_points = estimate_points_properties(entity->as_polyline().points, + prev_layer_boundary, flow_width, + params.bridge_distance); + + std::vector lines_out; + lines_out.reserve(annotated_points.size()); + float bridged_distance = 0.0f; + + std::optional bridging_dir{}; + + for (size_t i = 0; i < annotated_points.size(); ++i) { + ExtendedPoint &curr_point = annotated_points[i]; + ExtendedPoint &prev_point = i > 0 ? annotated_points[i - 1] : annotated_points[i - 1]; + + SupportPointCause potential_cause = std::abs(curr_point.curvature) > 0.1 ? SupportPointCause::FloatingBridgeAnchor : + SupportPointCause::LongBridge; + float line_len = i > 0 ? ((annotated_points[i - 1].position - curr_point.position).norm()) : 0.0f; + Vec2d line_dir = (curr_point.position - prev_point.position).normalized(); + + ExtrusionLine line_out{i > 0 ? annotated_points[i - 1].position.cast() : curr_point.position.cast(), + curr_point.position.cast(), line_len, entity}; + + float max_bridge_len = std::max(params.support_points_interface_radius * 2.0f, + params.bridge_distance / + ((1.0f + std::abs(curr_point.curvature)) * (1.0f + std::abs(curr_point.curvature)) * + (1.0f + std::abs(curr_point.curvature)))); + + if (!bridging_dir.has_value() && curr_point.distance > flow_width && line_len > params.bridge_distance * 0.6) { + bridging_dir = (prev_point.position - curr_point.position).normalized(); + } + + if (curr_point.distance > flow_width && potential_cause == SupportPointCause::LongBridge && bridging_dir.has_value() && + bridging_dir->dot(line_dir) < 0.8) { // skip backward direction of bridge - supported by forward points enough + bridged_distance += line_len; + } else if (curr_point.distance > flow_width) { + bridged_distance += line_len; + if (bridged_distance > max_bridge_len) { + bridged_distance = 0.0f; + line_out.support_point_generated = potential_cause; + } + } else { + bridged_distance = 0.0f; + } + + lines_out.push_back(line_out); + } + return lines_out; + } else { // single extrusion path, with possible varying parameters if (entity->length() < scale_(params.min_distance_to_allow_local_supports)) { return {}; } const float flow_width = get_flow_width(layer_region, entity->role()); - // Compute only unsigned distance - prev_layer_lines can contain unconnected paths, thus the sign of the distance is unreliable std::vector annotated_points = estimate_points_properties(entity->as_polyline().points, prev_layer_lines, flow_width, @@ -268,13 +321,11 @@ std::vector check_extrusion_entity_stability(const ExtrusionEntit curr_point.distance *= sign; SupportPointCause potential_cause = SupportPointCause::FloatingExtrusion; - if (entity->role().is_bridge() && !entity->role().is_perimeter()) { - potential_cause = std::abs(curr_point.curvature) > 0.1 ? SupportPointCause::FloatingBridgeAnchor : SupportPointCause::LongBridge; - } - float max_bridge_len = params.bridge_distance / - ((1.0f + std::abs(curr_point.curvature)) * (1.0f + std::abs(curr_point.curvature)) * - (1.0f + std::abs(curr_point.curvature))); + float max_bridge_len = std::max(params.support_points_interface_radius * 2.0f, + params.bridge_distance / + ((1.0f + std::abs(curr_point.curvature)) * (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; diff --git a/src/libslic3r/SupportSpotsGenerator.hpp b/src/libslic3r/SupportSpotsGenerator.hpp index b36566b04..9ef3b8637 100644 --- a/src/libslic3r/SupportSpotsGenerator.hpp +++ b/src/libslic3r/SupportSpotsGenerator.hpp @@ -68,7 +68,7 @@ enum class SupportPointCause { LongBridge, // point generated on bridge extrusion longer than the allowed length FloatingBridgeAnchor, // point generated on unsupported bridge endpoint FloatingExtrusion, // point generated on extrusion that does not hold on its own - huge overhangs - SeparationFromBed, // point generated for object parts that are connected to the bed, but the area is too low and there is risk of separation (brim may help) + SeparationFromBed, // point generated for object parts that are connected to the bed, but the area is too small and there is a risk of separation (brim may help) UnstableFloatingPart, // point generated for object parts not connected to the bed, holded only by the other support points (brim will not help here) WeakObjectPart // point generated when some part of the object is too weak to hold the upper part and may break (imagine hourglass) };