diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 43c9f2e5ec..53edc04006 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -332,7 +332,6 @@ struct GlobalModelInfo { return std::abs(orig_to_point.dot(plane_normal)); }; - float total_weight = 0; float total_visibility = 0; for (size_t i = 0; i < points.size(); ++i) { @@ -561,7 +560,7 @@ void process_perimeter_polygon(const Polygon &orig_polygon, float z_coord, const break; } viable_points_indices.push_back(last_enforced_idx); - if (abs(result.points[last_enforced_idx].local_ccw_angle) > 0.3 * PI) { + if (abs(result.points[last_enforced_idx].local_ccw_angle) > SeamPlacer::sharp_angle_snapping_threshold) { orig_large_angle_points_indices.push_back(last_enforced_idx); } last_enforced_idx = next_index(last_enforced_idx); @@ -654,7 +653,7 @@ void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po, // to compute ideal search radius (area), we use exponential distribution (complementary distr to poisson) // parameters of exponential distribution to compute area that will have with probability="probability" more than given number of samples="samples" float probability = 0.9f; - float samples = 3; + float samples = 4; float density = SeamPlacer::raycasting_visibility_samples_count / result.mesh_samples.total_area; // exponential probability distrubtion function is : f(x) = P(X > x) = e^(l*x) where l is the rate parameter (computed as 1/u where u is mean value) // probability that sampled area A with S samples contains more than samples count: @@ -718,7 +717,7 @@ void gather_enforcers_blockers(GlobalModelInfo &result, const PrintObject *po) { struct SeamComparator { SeamPosition setup; float angle_importance; - SeamComparator(SeamPosition setup) : + explicit SeamComparator(SeamPosition setup) : setup(setup) { angle_importance = setup == spNearest ? SeamPlacer::angle_importance_nearest : SeamPlacer::angle_importance_aligned; } @@ -750,10 +749,7 @@ struct SeamComparator { return false; } - if (setup == SeamPosition::spRear) { - if (a.position.y() == b.position.y()) { - return a.position.x() > b.position.x(); - } + if (setup == SeamPosition::spRear && a.position.y() != b.position.y()) { return a.position.y() > b.position.y(); } @@ -816,10 +812,7 @@ struct SeamComparator { } if (setup == SeamPosition::spRear) { - if (a.position.y() == b.position.y()) { - return a.position.x() > b.position.x(); - } - return a.position.y() > b.position.y(); + return a.position.y() + SeamPlacer::seam_align_score_tolerance * 5.0f > b.position.y(); } float penalty_a = a.visibility @@ -843,6 +836,10 @@ struct SeamComparator { return gauss(ccw_angle, 0.0f, 1.0f, 3.0f) + 1.0f / (2 + std::exp(-ccw_angle)); } + + float weight(const SeamCandidate &a) const { + return a.visibility + angle_importance * compute_angle_penalty(a.local_ccw_angle) / (1.0f + angle_importance); + } }; #ifdef DEBUG_FILES @@ -1214,13 +1211,12 @@ std::vector> SeamPlacer::find_seam_string(const PrintO int seam_index = start_seam.second; //initialize searching for seam string - cluster of nearby seams on previous and next layers - int skips = SeamPlacer::seam_align_tolerable_skips / 2; int next_layer = layer_idx + 1; std::pair prev_point_index = start_seam; std::vector> seam_string { start_seam }; //find seams or potential seams in forward direction; there is a budget of skips allowed - while (skips >= 0 && next_layer < int(layers.size())) { + while (next_layer < int(layers.size())) { auto maybe_next_seam = find_next_seam_in_layer(layers, prev_point_index, next_layer, float(po->get_layer(next_layer)->slice_z), comparator); if (maybe_next_seam.has_value()) { @@ -1240,17 +1236,15 @@ std::vector> SeamPlacer::find_seam_string(const PrintO prev_point_index = seam_string.back(); //String added, prev_point_index updated } else { - // Layer skipped, reduce number of available skips - skips--; + break; } next_layer++; } //do additional check in back direction next_layer = layer_idx - 1; - skips = SeamPlacer::seam_align_tolerable_skips / 2; prev_point_index = std::pair(layer_idx, seam_index); - while (skips >= 0 && next_layer >= 0) { + while (next_layer >= 0) { auto maybe_next_seam = find_next_seam_in_layer(layers, prev_point_index, next_layer, float(po->get_layer(next_layer)->slice_z), comparator); if (maybe_next_seam.has_value()) { @@ -1269,8 +1263,7 @@ std::vector> SeamPlacer::find_seam_string(const PrintO prev_point_index = seam_string.back(); //String added, prev_point_index updated } else { - // Layer skipped, reduce number of available skips - skips--; + break; } next_layer--; } @@ -1385,10 +1378,8 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl:: Vec3f pos = layers[seam_string[index].first].points[seam_string[index].second].position; observations[index] = pos.head<2>(); observation_points[index] = pos.z(); - weights[index] = - (comparator.compute_angle_penalty( - layers[seam_string[index].first].points[seam_string[index].second].local_ccw_angle) - < comparator.compute_angle_penalty(0.4f * float(PI))) ? 1.0f : 0.1f; + weights[index] = std::min(1.0f, + comparator.weight(layers[seam_string[index].first].points[seam_string[index].second])); } // Curve Fitting @@ -1400,7 +1391,10 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl:: // Perimeter structure of the point; also set flag aligned to true for (size_t index = 0; index < seam_string.size(); ++index) { const auto &pair = seam_string[index]; - const float t = weights[index]; + const float t = + abs(layers[pair.first].points[pair.second].local_ccw_angle) + > SeamPlacer::sharp_angle_snapping_threshold + ? 1.0 : 0.0f; Vec3f current_pos = layers[pair.first].points[pair.second].position; Vec2f fitted_pos = curve.get_fitted_value(current_pos.z()); @@ -1504,7 +1498,7 @@ void SeamPlacer::init(const Print &print, std::function throw_if_can << "SeamPlacer: pick_seam_point : end"; } throw_if_canceled_func(); - if (configured_seam_preference == spAligned) { + if (configured_seam_preference == spAligned || configured_seam_preference == spRear) { BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: align_seam_points : start"; align_seam_points(po, comparator); diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp index 181dd5bb8c..740fb33bc1 100644 --- a/src/libslic3r/GCode/SeamPlacer.hpp +++ b/src/libslic3r/GCode/SeamPlacer.hpp @@ -128,6 +128,7 @@ public: // arm length used during angles computation static constexpr float polygon_local_angles_arm_distance = 0.3f; + static constexpr float sharp_angle_snapping_threshold = 0.3 * PI; // max tolerable distance from the previous layer is overhang_distance_tolerance_factor * flow_width static constexpr float overhang_distance_tolerance_factor = 0.5f; @@ -143,16 +144,13 @@ public: // When searching for seam clusters for alignment: // following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer - static constexpr float seam_align_score_tolerance = 0.27f; - // seam_align_tolerable_dist - if next layer closest point is too far away, skip layer - static constexpr float seam_align_tolerable_dist = 0.4f; - // if the seam of the current layer is too far away, and the closest seam candidate is not very good, layer is skipped. - // this param limits the number of allowed skips - static constexpr size_t seam_align_tolerable_skips = 4; + static constexpr float seam_align_score_tolerance = 0.3f; + // seam_align_tolerable_dist - if next layer closest point is too far away, break aligned string + static constexpr float seam_align_tolerable_dist = 1.0f; // minimum number of seams needed in cluster to make alignment happen - static constexpr size_t seam_align_minimum_string_seams = 6; + static constexpr size_t seam_align_minimum_string_seams = 10; // points covered by spline; determines number of splines for the given string - static constexpr size_t seam_align_seams_per_segment = 8; + static constexpr size_t seam_align_seams_per_segment = 16; //The following data structures hold all perimeter points for all PrintObject. std::unordered_map m_seam_per_object;