From acd6016fc834c749307205448e05bffee954c71e Mon Sep 17 00:00:00 2001 From: "zhimin.zeng" Date: Wed, 16 Oct 2024 10:38:52 +0800 Subject: [PATCH] FIX: add object id for gcode check and display plater limit error individually jira: none Change-Id: Ie6105642667530901be494b344ce853e728ae5fa --- src/libslic3r/GCode/GCodeProcessor.cpp | 92 +++++++++++++++++--------- src/libslic3r/GCode/GCodeProcessor.hpp | 5 +- src/slic3r/GUI/GLCanvas3D.cpp | 21 ++++-- src/slic3r/GUI/NotificationManager.cpp | 16 +++++ src/slic3r/GUI/NotificationManager.hpp | 5 ++ 5 files changed, 100 insertions(+), 39 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 1c7bb58b1..1418ee64e 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -137,6 +137,19 @@ static float acceleration_time_from_distance(float initial_feedrate, float dista return (acceleration != 0.0f) ? (speed_from_distance(initial_feedrate, distance, acceleration) - initial_feedrate) / acceleration : 0.0f; } +static int get_object_label_id(const std::string_view comment_1) +{ + std::string comment(comment_1); + auto pos = comment.find(":"); + std::string num_str = comment.substr(pos + 1); + int id = -1; + try { + id = stoi(num_str); + } + catch (const std::exception &) {} + return id; +} + void GCodeProcessor::CachedPosition::reset() { std::fill(position.begin(), position.end(), FLT_MAX); @@ -1084,54 +1097,54 @@ bool GCodeProcessor::check_multi_extruder_gcode_valid(const std::vector gcode_path_pos; + + std::map> gcode_path_pos; // object_id, filament_id, pos for (const GCodeProcessorResult::MoveVertex &move : m_result.moves) { if (move.type == EMoveType::Extrude/* || move.type == EMoveType::Travel*/) { if (move.is_arc_move_with_interpolation_points()) { for (int i = 0; i < move.interpolation_points.size(); i++) { - gcode_path_pos[int(move.extruder_id)].emplace_back(to_2d(move.interpolation_points[i].cast())); + gcode_path_pos[move.object_label_id][int(move.extruder_id)].emplace_back(to_2d(move.interpolation_points[i].cast())); } } else { - gcode_path_pos[int(move.extruder_id)].emplace_back(to_2d(move.position.cast())); + gcode_path_pos[move.object_label_id][int(move.extruder_id)].emplace_back(to_2d(move.position.cast())); } } } bool valid = true; - for (auto iter = gcode_path_pos.begin(); iter != gcode_path_pos.end(); ++iter) { - int extruder_id = filament_map[iter->first] - 1; - Polygon path_poly(iter->second); - BoundingBox bbox = path_poly.bounding_box(); + Point plate_offset = Point(scale_(m_x_offset), scale_(m_y_offset)); + for (auto obj_iter = gcode_path_pos.begin(); obj_iter != gcode_path_pos.end(); ++obj_iter) { + int object_label_id = obj_iter->first; + const std::map& path_pos = obj_iter->second; + for (auto iter = path_pos.begin(); iter != path_pos.end(); ++iter) { + int extruder_id = filament_map[iter->first] - 1; + Polygon path_poly(iter->second); + BoundingBox bbox = path_poly.bounding_box(); - // Simplified use bounding_box, Accurate calculation is not efficient - for (const Polygon &poly : unprintable_areas[extruder_id]) { - if (poly.bounding_box().overlap(bbox)) { - m_result.gcode_check_result.error_code = 1; - m_result.gcode_check_result.error_infos[extruder_id].push_back(iter->first); - valid = false; + // Simplified use bounding_box, Accurate calculation is not efficient + for (Polygon poly : unprintable_areas[extruder_id]) { + poly.translate(plate_offset); + if (poly.bounding_box().overlap(bbox)) { + m_result.gcode_check_result.error_code = 1; + std::pair filament_to_object_id; + filament_to_object_id.first = iter->first; + filament_to_object_id.second = object_label_id; + m_result.gcode_check_result.error_infos[extruder_id].push_back(filament_to_object_id); + valid = false; + } + } + + for (int i = 0; i < unprintable_areas.size(); ++i) { + for (Polygon poly : unprintable_areas[i]) { + poly.translate(plate_offset); + if (!poly.bounding_box().overlap(bbox)) + continue; + + m_result.limit_filament_maps[iter->first] |= (1 << i); + } } } - - for (int i = 0; i < unprintable_areas.size(); ++i) { - for (const Polygon &poly : unprintable_areas[i]) { - if (!poly.bounding_box().overlap(bbox)) - continue; - - m_result.limit_filament_maps[iter->first] |= (1 << i); - } - } - - /* - // Accurate calculation is not efficient - for (const Polygon& poly : unprintable_areas[extruder_id]) { - if (poly.overlaps({path_poly})) { - m_result.gcode_check_result.error_code = 1; - valid = false; - break; - } - } - */ } return valid; @@ -2360,6 +2373,18 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers return; } + // ; OBJECT_ID start + if (boost::starts_with(comment, " start printing object")) { + m_object_label_id = get_object_label_id(comment); + return; + } + + // ; OBJECT_ID end + if (boost::starts_with(comment, " stop printing object")) { + m_object_label_id = -1; + return; + } + // wipe start tag if (boost::starts_with(comment, reserved_tag(ETags::Wipe_Start))) { m_wiping = true; @@ -4861,6 +4886,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type, EMovePathType path_type) path_type, Vec3f(m_arc_center(0, 0) + m_x_offset, m_arc_center(1, 0) + m_y_offset, m_arc_center(2, 0)) + m_extruder_offsets[filament_id], m_interpolation_points, + m_object_label_id }); if (type == EMoveType::Seam) { diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index 699fb5abf..8af2e4fe5 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -137,8 +137,7 @@ namespace Slic3r { struct GCodeCheckResult { int error_code = 0; // 0 means succeed - std::map> error_infos; // extruder_id to filament_ids - + std::map>> error_infos; // extruder_id to which cannot printed in this extruder void reset() { error_code = 0; error_infos.clear(); @@ -187,6 +186,7 @@ namespace Slic3r { EMovePathType move_path_type{ EMovePathType::Noop_move }; Vec3f arc_center_position{ Vec3f::Zero() }; // mm std::vector interpolation_points; // interpolation points of arc for drawing + int object_label_id{-1}; float volumetric_rate() const { return feedrate * mm3_per_mm; } //BBS: new function to support arc move @@ -732,6 +732,7 @@ namespace Slic3r { bool m_flushing; // mark a section with real flush bool m_virtual_flushing; // mark a section with virtual flush, only for statistics bool m_wipe_tower; + int m_object_label_id{-1}; std::vector m_remaining_volume; std::vector m_filament_lists; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 4b71c663f..52d2d2344 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -9604,6 +9604,7 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) PLATER_ERROR, SLICING_SERIOUS_WARNING, SLICING_ERROR, + SLICING_LIMIT_ERROR }; std::string text; ErrorType error = ErrorType::PLATER_WARNING; @@ -9644,7 +9645,11 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) if (i > 0) { filaments += ", "; } - filaments += std::to_string(error_iter->second[i] + 1); + int filament_id = error_iter->second[i].first; + int object_label_id = error_iter->second[i].second; + // todo: display the conflict objects + //ModelObject* object->instances[0]->get_labeled_id(); + filaments += std::to_string(filament_id); } std::string extruder_name = extruder_id == master_extruder_id ? "Left extruder" : "Right extruder"; if (error_iter->second.size() == 1) { @@ -9654,9 +9659,11 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) text += (boost::format(_u8L("Filaments %d is placed in the %s, but the generated G-code path exceeds the printable range of the %s.")) %filaments %extruder_name %extruder_name).str(); } } - text += "\n"; - text += _u8L("Open wiki for more information."); - error = ErrorType::SLICING_ERROR; + if (!text.empty()) { + text += "\n"; + text += _u8L("Open wiki for more information."); + } + error = ErrorType::SLICING_LIMIT_ERROR; break; } // BBS: remove _u8L() for SLA @@ -9723,6 +9730,12 @@ void GLCanvas3D::_set_warning_notification(EWarning warning, bool state) notification_manager.close_slicing_error_notification(text); } break; + case SLICING_LIMIT_ERROR: + if (state) + notification_manager.push_slicing_limit_error_notification(text); + else + notification_manager.close_slicing_limit_error_notification(text); + break; default: break; } diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 458c6c3be..08185ff12 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -1731,6 +1731,22 @@ void NotificationManager::close_plater_error_notification(const std::string& tex } } +void NotificationManager::push_slicing_limit_error_notification(const std::string &text) +{ + set_all_slicing_errors_gray(false); + push_notification_data({NotificationType::BBLSliceLimitError, NotificationLevel::ErrorNotificationLevel, 0, _u8L("Error:") + "\n" + text}, 0); + set_slicing_progress_hidden(); +} + +void NotificationManager::close_slicing_limit_error_notification(const std::string &text) +{ + for (std::unique_ptr ¬ification : m_pop_notifications) { + if (notification->get_type() == NotificationType::BBLSliceLimitError) { + notification->close(); + } + } +} + void NotificationManager::push_plater_warning_notification(const std::string& text) { // Find if was not hidden diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 83abd2982..9b7881214 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -227,6 +227,11 @@ public: // Closes error or warning of the same text void close_plater_error_notification(const std::string& text); void close_plater_warning_notification(const std::string& text); + + // GCode exceeds the printing range of the extruder + void push_slicing_limit_error_notification(const std::string &text); + void close_slicing_limit_error_notification(const std::string &text); + // Object warning with ObjectID, closes when object is deleted. ID used is of object not print like in slicing warning. void push_simplify_suggestion_notification(const std::string& text, ObjectID object_id, const std::string& hypertext = "", std::function callback = std::function());