diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 660bd78491..8e7c04d4ce 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -4252,49 +4252,53 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp return false; } + //BBS: input travel polyline must be in current plate coordinate system auto is_through_overhang = [this](const Polyline& travel) { + BoundingBox travel_bbox = get_extents(travel); + travel_bbox.inflated(1); + const float protect_z_scaled = scale_(0.4); std::pair z_range; z_range.second = m_layer ? m_layer->print_z : 0.f; z_range.first = std::max(0.f, z_range.second - protect_z_scaled); std::vector layers_of_objects; std::vector boundingBox_for_objects; - std::vector idx_of_object_sorted = m_curr_print->layers_sorted_for_object(z_range.first, z_range.second, layers_of_objects, boundingBox_for_objects); + std::vector objects_instances_shift; + std::vector idx_of_object_sorted = m_curr_print->layers_sorted_for_object(z_range.first, z_range.second, layers_of_objects, boundingBox_for_objects, objects_instances_shift); - for (size_t i = 0; i < idx_of_object_sorted.size();i++) { - size_t idx = idx_of_object_sorted[i]; + std::vector is_layers_of_objects_sorted(layers_of_objects.size(), false); - BoundingBox obj_bbox = boundingBox_for_objects[idx]; - BoundingBox travel_bbox = get_extents(travel); - obj_bbox.offset(scale_(EPSILON)); + for (size_t idx : idx_of_object_sorted) { + for (const Point & instance_shift : objects_instances_shift[idx]) { + BoundingBox instance_bbox = boundingBox_for_objects[idx]; + instance_bbox.offset(scale_(EPSILON)); + instance_bbox.translate(instance_shift.x(), instance_shift.y()); + if (!instance_bbox.overlap(travel_bbox)) + continue; - if (!obj_bbox.overlap(travel_bbox)) - continue; + Polygons temp; + temp.emplace_back(std::move(instance_bbox.polygon())); + if (intersection_pl(travel, temp).empty()) + continue; - Polygon object_box; - Polygons temp; - object_box.points.push_back(Point(obj_bbox.min(0), obj_bbox.min(1))); - object_box.points.push_back(Point(obj_bbox.max(0), obj_bbox.min(1))); - object_box.points.push_back(Point(obj_bbox.max(0), obj_bbox.max(1))); - object_box.points.push_back(Point(obj_bbox.min(0), obj_bbox.max(1))); - temp.push_back(object_box); - if (intersection_pl(travel, temp).empty()) - continue; + if (!is_layers_of_objects_sorted[idx]) { + std::sort(layers_of_objects[idx].begin(), layers_of_objects[idx].end(), [](auto left, auto right) { return left->loverhangs_bbox.area() > right->loverhangs_bbox.area();}); + is_layers_of_objects_sorted[idx] = true; + } - std::sort(layers_of_objects[idx].begin(), layers_of_objects[idx].end(), [](auto left, auto right) { return left->loverhangs_bbox.area() > right->loverhangs_bbox.area(); - }); + for (const auto& layer : layers_of_objects[idx]) { + for (ExPolygon overhang : layer->loverhangs) { + overhang.translate(instance_shift); + BoundingBox bbox1 = get_extents(overhang); - for (const auto &layer : layers_of_objects[idx]) { - for (const ExPolygon &overhang : layer->loverhangs) { - BoundingBox bbox1 = get_extents(overhang); - travel_bbox.inflated(1); - if (!bbox1.overlap(travel_bbox)) - continue; + if (!bbox1.overlap(travel_bbox)) + continue; - if (intersection_pl(travel, overhang).empty()) - continue; + if (intersection_pl(travel, overhang).empty()) + continue; - return true; + return true; + } } } } @@ -4312,6 +4316,8 @@ bool GCode::needs_retraction(const Polyline &travel, ExtrusionRole role, LiftTyp clipped_travel.append(Polyline(travel.points[0], travel.points[1])); if (clipped_travel.length() > travel_len_thresh) clipped_travel.points.back() = clipped_travel.points.front()+(clipped_travel.points.back() - clipped_travel.points.front()) * (travel_len_thresh / clipped_travel.length()); + //BBS: translate to current plate coordinate system + clipped_travel.translate(Point::new_scale(double(m_origin.x() - m_writer.get_xy_offset().x()), double(m_origin.y() - m_writer.get_xy_offset().y()))); //BBS: force to retract when leave from external perimeter for a long travel //Better way is judging whether the travel move direction is same with last extrusion move. diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index c5df65fb93..b696da529f 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -437,7 +437,7 @@ bool Print::has_brim() const } //BBS -std::vector Print::layers_sorted_for_object(float start, float end, std::vector &layers_of_objects, std::vector &boundingBox_for_objects) +std::vector Print::layers_sorted_for_object(float start, float end, std::vector &layers_of_objects, std::vector &boundingBox_for_objects, std::vector &objects_instances_shift) { std::vector idx_of_object_sorted; size_t idx = 0; @@ -448,6 +448,11 @@ std::vector Print::layers_sorted_for_object(float start, float end, std: std::sort(idx_of_object_sorted.begin(), idx_of_object_sorted.end(), [boundingBox_for_objects](auto left, auto right) { return boundingBox_for_objects[left].area() > boundingBox_for_objects[right].area(); }); + objects_instances_shift.clear(); + objects_instances_shift.reserve(m_objects.size()); + for (const auto& object : m_objects) + objects_instances_shift.emplace_back(object->get_instances_shift_without_plate_offset()); + return idx_of_object_sorted; }; diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index ccd5c10685..d9a1681b67 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -424,6 +424,7 @@ public: //BBS BoundingBox get_first_layer_bbox(float& area, float& layer_height, std::string& name); void get_certain_layers(float start, float end, std::vector &out, std::vector &boundingbox_objects); + std::vector get_instances_shift_without_plate_offset(); PrintObject* get_shared_object() const { return m_shared_object; } void set_shared_object(PrintObject *object); void clear_shared_object(); @@ -758,7 +759,7 @@ public: // For Perl bindings. PrintObjectPtrs& objects_mutable() { return m_objects; } PrintRegionPtrs& print_regions_mutable() { return m_print_regions; } - std::vector layers_sorted_for_object(float start, float end, std::vector &layers_of_objects, std::vector &boundingBox_for_objects); + std::vector layers_sorted_for_object(float start, float end, std::vector &layers_of_objects, std::vector &boundingBox_for_objects, std::vector& objects_instances_shift); const ExtrusionEntityCollection& skirt() const { return m_skirt; } // Convex hull of the 1st layer extrusions, for bed leveling and placing the initial purge line. // It encompasses the object extrusions, support extrusions, skirt, brim, wipe tower. diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index df104bc535..f10532843b 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -2045,6 +2045,17 @@ void PrintObject::get_certain_layers(float start, float end, std::vector PrintObject::get_instances_shift_without_plate_offset() +{ + std::vector out; + out.reserve(m_instances.size()); + for (const auto& instance : m_instances) + out.push_back(instance.shift_without_plate_offset()); + + return out; +} + // Only active if config->infill_only_where_needed. This step trims the sparse infill, // so it acts as an internal support. It maintains all other infill types intact. // Here the internal surfaces and perimeters have to be supported by the sparse infill.