diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index aca4c7a3c..a42619668 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -22,7 +22,7 @@ #include "libslic3r/Utils.hpp" -#define DEBUG_FILES +//#define DEBUG_FILES #ifdef DEBUG_FILES #include @@ -1217,9 +1217,8 @@ std::vector> SeamPlacer::find_seam_string(const PrintO while (next_layer < int(layers.size())) { std::optional> maybe_next_seam; float z_distance = float(po->get_layer(next_layer)->slice_z) - origin_position.z(); - float f = 2.71828f - logf(po->get_layer(next_layer)->height); - float max_distance = SeamPlacer::seam_align_tolerable_dist_factor * f * f; - if (fabs(next_layer - layer_idx) > 3){ + float max_distance = SeamPlacer::seam_align_tolerable_dist; + if (fabs(next_layer - layer_idx) >= SeamPlacer::seam_align_min_seams_for_linear_projection){ Vec3f projected_position = origin_position + z_distance * surface_line_dir; maybe_next_seam = find_next_seam_in_layer(layers, projected_position, next_layer, max_distance, comparator); @@ -1246,9 +1245,7 @@ std::vector> SeamPlacer::find_seam_string(const PrintO seam_string.push_back(maybe_next_seam.operator*()); prev_point_index = seam_string.back(); //String added, prev_point_index updated - Vec3f line_dir = next_seam.position - origin_position; - surface_line_dir += line_dir / line_dir.z(); - surface_line_dir /= surface_line_dir.z(); + surface_line_dir += (next_seam.position - origin_position).normalized(); } else { break; } @@ -1261,10 +1258,9 @@ std::vector> SeamPlacer::find_seam_string(const PrintO while (next_layer >= 0) { std::optional> maybe_next_seam; float z_distance = float(po->get_layer(next_layer)->slice_z) - origin_position.z(); - float f = 2.71828f - logf(po->get_layer(next_layer)->height); - float max_distance = SeamPlacer::seam_align_tolerable_dist_factor * f * f; - if (fabs(next_layer - layer_idx) > 3){ - Vec3f projected_position = origin_position + z_distance * surface_line_dir; + float max_distance = SeamPlacer::seam_align_tolerable_dist; + if (fabs(next_layer - layer_idx) >= SeamPlacer::seam_align_min_seams_for_linear_projection){ + Vec3f projected_position = origin_position + z_distance * (surface_line_dir / surface_line_dir.z()); maybe_next_seam = find_next_seam_in_layer(layers, projected_position, next_layer, max_distance, comparator); } @@ -1290,9 +1286,7 @@ std::vector> SeamPlacer::find_seam_string(const PrintO seam_string.push_back(maybe_next_seam.operator*()); prev_point_index = seam_string.back(); //String added, prev_point_index updated - Vec3f line_dir = next_seam.position - origin_position; - surface_line_dir += line_dir / line_dir.z(); - surface_line_dir /= surface_line_dir.z(); + surface_line_dir += (next_seam.position - origin_position).normalized(); } else { break; } @@ -1402,20 +1396,20 @@ void SeamPlacer::align_seam_points(const PrintObject *po, const SeamPlacerImpl:: weights.resize(seam_string.size()); //gather points positions and weights - // The algorithm uses only angle to compute penalty, to enforce snapping to sharp corners, if they are present - // after several experiments approach that gives best results is to snap the weight to one for sharp corners, and - // leave it small for others. However, this can result in non-smooth line over area with a lot of unaligned sharp corners. + float total_length = 0.0f; + Vec3f last_point_pos = layers[seam_string[0].first].points[seam_string[0].second].position; for (size_t index = 0; index < seam_string.size(); ++index) { Vec3f pos = layers[seam_string[index].first].points[seam_string[index].second].position; + total_length += (last_point_pos - pos).norm(); + last_point_pos = pos; observations[index] = pos.head<2>(); observation_points[index] = pos.z(); - weights[index] = std::min(1.0f, - comparator.weight(layers[seam_string[index].first].points[seam_string[index].second])); + weights[index] = comparator.weight(layers[seam_string[index].first].points[seam_string[index].second]); } // Curve Fitting size_t number_of_segments = std::max(size_t(1), - size_t(observations.size() / SeamPlacer::seam_align_seams_per_segment)); + size_t(total_length / SeamPlacer::seam_align_mm_per_segment)); auto curve = Geometry::fit_cubic_bspline(observations, observation_points, weights, number_of_segments); // Do alignment - compute fitted point for each point in the string from its Z coord, and store the position into diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp index 229e13731..50eebb78f 100644 --- a/src/libslic3r/GCode/SeamPlacer.hpp +++ b/src/libslic3r/GCode/SeamPlacer.hpp @@ -128,7 +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.25f * float(PI); + static constexpr float sharp_angle_snapping_threshold = 0.3f * float(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,13 +143,15 @@ public: static constexpr float enforcer_oversampling_distance = 0.2f; // When searching for seam clusters for alignment: + static constexpr size_t seam_align_min_seams_for_linear_projection = 1; // 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.3f; - static constexpr float seam_align_tolerable_dist_factor = 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 = 3.0f; // minimum number of seams needed in cluster to make alignment happen - 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 = 16; + static constexpr size_t seam_align_minimum_string_seams = 6; + // millimeters covered by spline; determines number of splines for the given string + static constexpr size_t seam_align_mm_per_segment = 8.0f; //The following data structures hold all perimeter points for all PrintObject. std::unordered_map m_seam_per_object; diff --git a/src/libslic3r/Geometry/Curves.hpp b/src/libslic3r/Geometry/Curves.hpp index 5a0d5481f..6ccdea366 100644 --- a/src/libslic3r/Geometry/Curves.hpp +++ b/src/libslic3r/Geometry/Curves.hpp @@ -15,8 +15,8 @@ template struct PolynomialCurve { Eigen::MatrixXf coefficients; - Vec3f get_fitted_value(const NumberType value) const { - auto result = Vec::Zero(); + Vec get_fitted_value(const NumberType& value) const { + Vec result = Vec::Zero(); size_t order = this->coefficients.rows() - 1; auto x = NumberType(1.); for (size_t index = 0; index < order + 1; ++index, x *= value)