diff --git a/src/libslic3r/GCode/SeamAligned.cpp b/src/libslic3r/GCode/SeamAligned.cpp index a2e22c6b33..209a5a85d2 100644 --- a/src/libslic3r/GCode/SeamAligned.cpp +++ b/src/libslic3r/GCode/SeamAligned.cpp @@ -420,7 +420,9 @@ std::vector get_shells_seam_candidates( std::vector get_shell_seam( const Shells::Shell<> &shell, - std::vector seam_candidates + std::vector seam_candidates, + const Perimeters::Perimeter::OptionalPointTree &previous_points, + const Params ¶ms ) { std::vector seam; double visibility{std::numeric_limits::infinity()}; @@ -429,8 +431,27 @@ std::vector get_shell_seam( using Perimeters::Perimeter, Perimeters::AngleType; SeamCandidate seam_candidate{seam_candidates[i]}; + const Vec2d first_point{seam_candidate.choices.front().position}; - double seam_candidate_visibility{0.0}; + std::optional closest_point; + if (previous_points) { + std::size_t closest_point_index{find_closest_point(*previous_points, first_point)}; + Vec2d point; + point.x() = previous_points->coordinate(closest_point_index, 0); + point.y() = previous_points->coordinate(closest_point_index, 1); + closest_point = point; + } + + std::optional previous_distance; + if (closest_point) { + previous_distance = (*closest_point - first_point).norm(); + } + const bool is_near_previous{closest_point && *previous_distance < params.max_detour}; + + double seam_candidate_visibility{ + is_near_previous ? -params.continuity_modifier * + (params.max_detour - *previous_distance) / params.max_detour : + 0.0}; for (std::size_t slice_index{}; slice_index < shell.size(); ++slice_index) { seam_candidate_visibility += seam_candidate.visibilities[slice_index]; } @@ -476,8 +497,29 @@ std::vector> get_object_seams( for (std::size_t shell_index{0}; shell_index < shells.size(); ++shell_index) { Shells::Shell<> &shell{shells[shell_index]}; + if (shell.empty()) { + continue; + } + + const std::size_t layer_index{shell.front().layer_index}; + tcb::span previous_seams{ + layer_index == 0 ? tcb::span{} : layer_seams[layer_index - 1]}; + std::vector previous_seams_positions; + std::transform( + previous_seams.begin(), previous_seams.end(), + std::back_inserter(previous_seams_positions), + [](const SeamPerimeterChoice &seam) { return seam.choice.position; } + ); + + Perimeters::Perimeter::OptionalPointTree previous_seams_positions_tree; + const Perimeters::Perimeter::IndexToCoord index_to_coord{previous_seams_positions}; + if (!previous_seams_positions.empty()) { + previous_seams_positions_tree = + Perimeters::Perimeter::PointTree{index_to_coord, index_to_coord.positions.size()}; + } + std::vector seam{ - Aligned::get_shell_seam(shell, seam_candidates[shell_index])}; + Aligned::get_shell_seam(shell, seam_candidates[shell_index], previous_seams_positions_tree, params)}; for (std::size_t perimeter_id{}; perimeter_id < shell.size(); ++perimeter_id) { const SeamChoice &choice{seam[perimeter_id]}; diff --git a/src/libslic3r/GCode/SeamAligned.hpp b/src/libslic3r/GCode/SeamAligned.hpp index d3fbebab6c..ee3b581ec1 100644 --- a/src/libslic3r/GCode/SeamAligned.hpp +++ b/src/libslic3r/GCode/SeamAligned.hpp @@ -83,6 +83,7 @@ private: struct Params { double max_detour{}; double jump_visibility_threshold{}; + double continuity_modifier{}; }; std::vector> get_object_seams( diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index d1fd54e069..3c93ed4f07 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -100,6 +100,7 @@ Params Placer::get_params(const DynamicPrintConfig &config) { params.random_seed = 1653710332u; params.aligned.max_detour = 1.0; + params.aligned.continuity_modifier = 2.0; params.convex_visibility_modifier = 1.1; params.concave_visibility_modifier = 0.9; params.perimeter.overhang_threshold = Slic3r::Geometry::deg2rad(55.0);