From 54eed41661b5aeb114f827b67328efcfac4bd07b Mon Sep 17 00:00:00 2001 From: tao wang Date: Thu, 23 Nov 2023 20:00:34 +0800 Subject: [PATCH] NEW:tracking stl model files jira:[STUDIO-5372] Change-Id: Idb1275b07441f0cd06c24588d5f7c20f81f1556c --- src/admesh/stl.h | 4 +- src/admesh/stlinit.cpp | 62 +++++++++++++++++++++------ src/libslic3r/Format/STL.cpp | 4 +- src/libslic3r/Model.cpp | 3 ++ src/libslic3r/Model.hpp | 1 + src/slic3r/GUI/Jobs/PrintJob.cpp | 13 +++++- src/slic3r/GUI/Plater.cpp | 62 ++++++++++++++++++++++++++- src/slic3r/Utils/bambu_networking.hpp | 1 + 8 files changed, 131 insertions(+), 19 deletions(-) diff --git a/src/admesh/stl.h b/src/admesh/stl.h index 65527e6f6..259377796 100644 --- a/src/admesh/stl.h +++ b/src/admesh/stl.h @@ -45,7 +45,7 @@ typedef Eigen::Matrix stl_triangle_vertex_indices static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect"); static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect"); -typedef std::function ImportstlProgressFn; +typedef std::function ImportstlProgressFn; typedef enum { eNormal, // normal face @@ -157,6 +157,7 @@ struct stl_file { return sizeof(*this) + sizeof(stl_facet) * facet_start.size() + sizeof(stl_neighbors) * neighbors_start.size(); } + char mw_data[256]; std::vector facet_start; std::vector neighbors_start; // Statistics @@ -275,7 +276,6 @@ extern void stl_mirror_yz(stl_file *stl); extern void stl_mirror_xz(stl_file *stl); extern float get_area(stl_facet* facet); - extern void stl_get_size(stl_file *stl); // the following function is not used diff --git a/src/admesh/stlinit.cpp b/src/admesh/stlinit.cpp index 095f7f715..ec044f87e 100644 --- a/src/admesh/stlinit.cpp +++ b/src/admesh/stlinit.cpp @@ -44,6 +44,7 @@ extern void stl_internal_reverse_quads(char *buf, size_t cnt); #endif /* BOOST_ENDIAN_BIG_BYTE */ const int LOAD_STL_UNIT_NUM = 5; +static std::string model_id = ""; static FILE* stl_open_count_facets(stl_file *stl, const char *file) { @@ -150,31 +151,66 @@ static FILE* stl_open_count_facets(stl_file *stl, const char *file) time running this for the stl and therefore we should reset our max and min stats. */ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, ImportstlProgressFn stlFn) { - if (stl->stats.type == binary) - fseek(fp, HEADER_SIZE, SEEK_SET); - else - rewind(fp); + if (stl->stats.type == binary) { + fseek(fp, HEADER_SIZE, SEEK_SET); + } + else { + rewind(fp); + try{ + char solid_name[256]; + int res_solid = fscanf(fp, " solid %[^\n]", solid_name); + if (res_solid == 1) { + char* mw_position = strstr(solid_name, "MW"); + if (mw_position != NULL) { + // Extract the value after "MW" + char version_str[16]; + char model_id_str[128]; + int num_values = sscanf(mw_position + 3, "%s %s", version_str, model_id_str); + if (num_values == 2) { + if (strcmp(version_str, "1.0") == 0) { + model_id = model_id_str; + } + } + else { + model_id = ""; + } + } + else { + model_id = ""; // No MW format found + } + } + } + catch (...){ + } + + rewind(fp); + } + char normal_buf[3][32]; uint32_t facets_num = stl->stats.number_of_facets; uint32_t unit = facets_num / LOAD_STL_UNIT_NUM + 1; for (uint32_t i = first_facet; i < facets_num; ++ i) { - if ((i % unit) == 0) { - bool cb_cancel = false; - if (stlFn) { - stlFn(i, facets_num, cb_cancel); - if (cb_cancel) - return false; - } - } + if ((i % unit) == 0) { + bool cb_cancel = false; + if (stlFn) { + stlFn(i, facets_num, cb_cancel, model_id); + if (cb_cancel) + return false; + } + } stl_facet facet; if (stl->stats.type == binary) { + + // Read a single facet from a binary .STL file. We assume little-endian architecture! if (fread(&facet, 1, SIZEOF_STL_FACET, fp) != SIZEOF_STL_FACET) return false; + + #if BOOST_ENDIAN_BIG_BYTE // Convert the loaded little endian data to big endian. stl_internal_reverse_quads((char*)&facet, 48); @@ -251,7 +287,7 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, Impor stl->facet_start[i] = facet; stl_facet_stats(stl, facet, first); } - + stl->stats.size = stl->stats.max - stl->stats.min; stl->stats.bounding_diameter = stl->stats.size.norm(); return true; diff --git a/src/libslic3r/Format/STL.cpp b/src/libslic3r/Format/STL.cpp index 3ba514dc9..133a7a505 100644 --- a/src/libslic3r/Format/STL.cpp +++ b/src/libslic3r/Format/STL.cpp @@ -17,6 +17,8 @@ namespace Slic3r { bool load_stl(const char *path, Model *model, const char *object_name_in, ImportstlProgressFn stlFn) { TriangleMesh mesh; + std::string design_id; + if (! mesh.ReadSTLFile(path, true, stlFn)) { // die "Failed to open $file\n" if !-e $path; return false; @@ -59,4 +61,4 @@ bool store_stl(const char *path, Model *model, bool binary) return store_stl(path, &mesh, binary); } -}; // namespace Slic3r +}; // namespace Slic3r \ No newline at end of file diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index d3b604a16..2ca36cd21 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -84,6 +84,7 @@ Model& Model::assign_copy(const Model &rhs) // BBS: for design info this->design_info = rhs.design_info; this->model_info = rhs.model_info; + this->stl_design_id = rhs.stl_design_id; this->profile_info = rhs.profile_info; return *this; @@ -113,6 +114,7 @@ Model& Model::assign_copy(Model &&rhs) //BBS: add auxiliary path logic // BBS: backup, all in one temp dir + this->stl_design_id = rhs.stl_design_id; this->backup_path = std::move(rhs.backup_path); this->object_backup_id_map = std::move(rhs.object_backup_id_map); this->next_object_backup_id = rhs.next_object_backup_id; @@ -910,6 +912,7 @@ void Model::load_from(Model& model) object_backup_id_map = model.object_backup_id_map; next_object_backup_id = model.next_object_backup_id; design_info = model.design_info; + stl_design_id = model.stl_design_id; model_info = model.model_info; profile_info = model.profile_info; model.design_info.reset(); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 948082f7a..e3010d9da 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -1508,6 +1508,7 @@ public: static GlobalSpeedMap printSpeedMap; // DesignInfo of Model + std::string stl_design_id; std::shared_ptr design_info = nullptr; std::shared_ptr model_info = nullptr; std::shared_ptr profile_info = nullptr; diff --git a/src/slic3r/GUI/Jobs/PrintJob.cpp b/src/slic3r/GUI/Jobs/PrintJob.cpp index 05cc0ddd3..186f031f5 100644 --- a/src/slic3r/GUI/Jobs/PrintJob.cpp +++ b/src/slic3r/GUI/Jobs/PrintJob.cpp @@ -245,7 +245,6 @@ void PrintJob::process() params.dst_file = m_dst_path; } - if (wxGetApp().model().model_info && wxGetApp().model().model_info.get()) { ModelInfo* model_info = wxGetApp().model().model_info.get(); auto origin_profile_id = model_info->metadata_items.find(BBL_DESIGNER_PROFILE_ID_TAG); @@ -279,7 +278,17 @@ void PrintJob::process() catch (...) {} } } - + + if (!wxGetApp().model().stl_design_id.empty()) { + int stl_design_id = 0; + try { + stl_design_id = std::stoi(wxGetApp().model().stl_design_id); + } + catch (const std::exception& e) { + stl_design_id = 0; + } + params.stl_design_id = stl_design_id; + } if (params.preset_name.empty() && m_print_type == "from_normal") { params.preset_name = wxString::Format("%s_plate_%d", m_project_name, curr_plate_idx).ToStdString(); } if (params.project_name.empty()) {params.project_name = m_project_name;} diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 8841d2195..8713d7da5 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3140,6 +3140,53 @@ BoundingBox Plater::priv::scaled_bed_shape_bb() const return printable_area.bounding_box(); } +std::string read_binary_stl(const std::string& filename) { + std::string model_id; + std::ifstream file(filename, std::ios::binary); + if (!file) { + return model_id; + } + + try{ + // Read the first 80 bytes + char data[80]; + file.read(data, 80); + if (!file) { + file.close(); + return model_id; + } + + if (data[0] == '\0' || data[0] == ' ') { + file.close(); + return model_id; + } + + char magic[2] = { data[0], data[1] }; + if (magic[0] != 'M' || magic[1] != 'W') { + file.close(); + return model_id; + } + + if (data[2] != ' ') { + file.close(); + return model_id; + } + + char protocol_version[3] = { data[3], data[4], data[5] }; + + //version + if (protocol_version[0] == '1' && protocol_version[1] == '.' && protocol_version[2] == '0') { + model_id = std::string(&data[7], &data[80]); + } + + file.close(); + } + catch (...){ + } + return model_id; +} + + // BBS: backup & restore std::vector Plater::priv::load_files(const std::vector& input_files, LoadStrategy strategy, bool ask_multi) { @@ -3177,6 +3224,8 @@ std::vector Plater::priv::load_files(const std::vector& input_ auto *new_model = (!load_model || one_by_one) ? nullptr : new Slic3r::Model(); std::vector obj_idxs; + std::string designer_model_id; + int answer_convert_from_meters = wxOK_DEFAULT; int answer_convert_from_imperial_units = wxOK_DEFAULT; int tolal_model_count = 0; @@ -3626,10 +3675,12 @@ std::vector Plater::priv::load_files(const std::vector& input_ std::vector project_presets; bool is_xxx; Semver file_version; + model = Slic3r::Model::read_from_file( path.string(), nullptr, nullptr, strategy, &plate_data, &project_presets, &is_xxx, &file_version, nullptr, - [this, &dlg, real_filename, &progress_percent, &file_percent, INPUT_FILES_RATIO, total_files, i](int current, int total, bool &cancel) + [this, &dlg, real_filename, &progress_percent, &file_percent, INPUT_FILES_RATIO, total_files, i, &designer_model_id](int current, int total, bool &cancel, std::string &mode_id) { + designer_model_id = mode_id; bool cont = true; float percent_float = (100.0f * (float)i / (float)total_files) + INPUT_FILES_RATIO * 100.0f * ((float)current / (float)total) / (float)total_files; BOOST_LOG_TRIVIAL(trace) << "load_stl_file: percent(float)=" << percent_float << ", curr = " << current << ", total = " << total; @@ -3654,6 +3705,11 @@ std::vector Plater::priv::load_files(const std::vector& input_ _L("Attention!")); }); + + if (designer_model_id.empty() && boost::algorithm::iends_with(path.string(), ".stl")) { + designer_model_id = read_binary_stl(path.string()); + } + if (type_any_amf && is_xxx) imperial_units = true; for (auto obj : model.objects) @@ -3947,6 +4003,10 @@ std::vector Plater::priv::load_files(const std::vector& input_ GLGizmoSimplify::add_simplify_suggestion_notification( obj_idxs, model.objects, *notification_manager); + //set designer_model_id + if (!designer_model_id.empty() && q->model().stl_design_id.empty()) { + q->model().stl_design_id = designer_model_id; + } if (tolal_model_count <= 0 && !q->m_exported_file) { dlg.Hide(); diff --git a/src/slic3r/Utils/bambu_networking.hpp b/src/slic3r/Utils/bambu_networking.hpp index e87540ec4..b91b4d382 100644 --- a/src/slic3r/Utils/bambu_networking.hpp +++ b/src/slic3r/Utils/bambu_networking.hpp @@ -202,6 +202,7 @@ struct PrintParams { std::string connection_type; std::string comments; int origin_profile_id = 0; + int stl_design_id = 0; std::string origin_model_id; std::string print_type; std::string dst_file;