diff --git a/src/libslic3r/GCode/SeamPlacerNG.cpp b/src/libslic3r/GCode/SeamPlacerNG.cpp index fad3911c6..6dab7ac41 100644 --- a/src/libslic3r/GCode/SeamPlacerNG.cpp +++ b/src/libslic3r/GCode/SeamPlacerNG.cpp @@ -6,6 +6,7 @@ #include #include #include +#include //For polynomial fitting #include @@ -299,14 +300,18 @@ struct GlobalModelInfo { raycast_hits_tree(HitInfoCoordinateFunctor { &geometry_raycast_hits }) { } - bool is_enforced(const Vec3f &position) const { - float radius = SeamPlacer::enforcer_blocker_sqr_distance_tolerance; + bool is_enforced(const Vec3f &position, float radius) const { + if (enforcers.empty()) { + return false; + } return AABBTreeIndirect::is_any_triangle_in_radius(enforcers.vertices, enforcers.indices, enforcers_tree, position, radius); } - bool is_blocked(const Vec3f &position) const { - float radius = SeamPlacer::enforcer_blocker_sqr_distance_tolerance; + bool is_blocked(const Vec3f &position, float radius) const { + if (blockers.empty()) { + return false; + } return AABBTreeIndirect::is_any_triangle_in_radius(blockers.vertices, blockers.indices, blockers_tree, position, radius); } @@ -431,6 +436,7 @@ Polygons extract_perimeter_polygons(const Layer *layer) { // Insert SeamCandidates created from perimeter polygons in to the result vector. // Compute its type (Enfrocer,Blocker), angle, and position //each SeamCandidate also contains pointer to shared Perimeter structure representing the polygon +// if Custom Seam modifiers are present, oversamples the polygon if necessary to better fit user intentions void process_perimeter_polygon(const Polygon &orig_polygon, float z_coord, std::vector &result_vec, const GlobalModelInfo &global_model_info) { if (orig_polygon.size() == 0) { @@ -450,26 +456,59 @@ void process_perimeter_polygon(const Polygon &orig_polygon, float z_coord, std:: SeamPlacer::polygon_local_angles_arm_distance); std::shared_ptr perimeter = std::make_shared(); - perimeter->start_index = result_vec.size(); - perimeter->end_index = result_vec.size() + polygon.size() - 1; - + std::queue orig_polygon_points { }; for (size_t index = 0; index < polygon.size(); ++index) { Vec2f unscaled_p = unscale(polygon[index]).cast(); - Vec3f unscaled_position = Vec3f { unscaled_p.x(), unscaled_p.y(), z_coord }; + orig_polygon_points.emplace(unscaled_p.x(), unscaled_p.y(), z_coord); + } + Vec3f first = orig_polygon_points.front(); + std::queue oversampled_points { }; + size_t orig_angle_index = 0; + perimeter->start_index = result_vec.size(); + while (!orig_polygon_points.empty() || !oversampled_points.empty()) { EnforcedBlockedSeamPoint type = EnforcedBlockedSeamPoint::Neutral; + Vec3f position; + float local_ccw_angle = 0; + bool orig_point = false; + if (!oversampled_points.empty()) { + position = oversampled_points.front(); + oversampled_points.pop(); + } else { + position = orig_polygon_points.front(); + orig_polygon_points.pop(); + local_ccw_angle = was_clockwise ? -local_angles[orig_angle_index] : local_angles[orig_angle_index]; + orig_angle_index++; + orig_point = true; + } - if (global_model_info.is_enforced(unscaled_position)) { + if (global_model_info.is_enforced(position, SeamPlacer::enforcer_blocker_sqr_distance_tolerance)) { type = EnforcedBlockedSeamPoint::Enforced; } - if (global_model_info.is_blocked(unscaled_position)) { + if (global_model_info.is_blocked(position, SeamPlacer::enforcer_blocker_sqr_distance_tolerance)) { type = EnforcedBlockedSeamPoint::Blocked; } - float local_ccw_angle = was_clockwise ? -local_angles[index] : local_angles[index]; + if (orig_point) { + Vec3f pos_of_next = orig_polygon_points.empty() ? first : orig_polygon_points.front(); + float distance_to_next = (position - pos_of_next).norm(); + if (global_model_info.is_enforced(position, distance_to_next) + || global_model_info.is_blocked(position, distance_to_next)) { + Vec3f vec_to_next = (pos_of_next - position).normalized(); + float step_size = SeamPlacer::enforcer_blocker_sqr_distance_tolerance; + float step = step_size; + while (step < distance_to_next) { + oversampled_points.push(position + vec_to_next * step); + step += step_size; + } + } + } + + result_vec.emplace_back(position, perimeter, local_ccw_angle, type); - result_vec.emplace_back(unscaled_position, perimeter, local_ccw_angle, type); } + + perimeter->end_index = result_vec.size() - 1; } // Get index of previous and next perimeter point of the layer. Because SeamCandidates of all polygons of the given layer @@ -963,6 +1002,8 @@ void SeamPlacer::init(const Print &print) { for (const PrintObject *po : print.objects()) { + SeamPosition configured_seam_preference = po->config().seam_position.value; + GlobalModelInfo global_model_info { }; gather_global_model_info(global_model_info, po); @@ -972,11 +1013,13 @@ void SeamPlacer::init(const Print &print) { BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: gather_seam_candidates: end"; - BOOST_LOG_TRIVIAL(debug) - << "SeamPlacer: calculate_candidates_visibility : start"; - calculate_candidates_visibility(po, global_model_info); - BOOST_LOG_TRIVIAL(debug) - << "SeamPlacer: calculate_candidates_visibility : end"; + if (configured_seam_preference != spAligned) { + BOOST_LOG_TRIVIAL(debug) + << "SeamPlacer: calculate_candidates_visibility : start"; + calculate_candidates_visibility(po, global_model_info); + BOOST_LOG_TRIVIAL(debug) + << "SeamPlacer: calculate_candidates_visibility : end"; + } BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: calculate_overhangs : start"; @@ -1002,12 +1045,13 @@ void SeamPlacer::init(const Print &print) { BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: pick_seam_point : end"; - BOOST_LOG_TRIVIAL(debug) - << "SeamPlacer: align_seam_points : start"; - align_seam_points(po, DefaultSeamComparator { }); - BOOST_LOG_TRIVIAL(debug) - << "SeamPlacer: align_seam_points : end"; - + if (configured_seam_preference != spRandom) { + BOOST_LOG_TRIVIAL(debug) + << "SeamPlacer: align_seam_points : start"; + align_seam_points(po, DefaultSeamComparator { }); + BOOST_LOG_TRIVIAL(debug) + << "SeamPlacer: align_seam_points : end"; + } } }