NEW:support makerlab info tracking

jira:[makerlab info]

Change-Id: I9b35df5357cd5b00028a7e5ac65b1ca4fe7d6959
This commit is contained in:
tao wang 2024-09-11 19:27:19 +08:00 committed by Lane.Wei
parent b47342178e
commit 2483257cfb
10 changed files with 215 additions and 58 deletions

View File

@ -45,7 +45,8 @@ typedef Eigen::Matrix<int, 3, 1, Eigen::DontAlign> 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<void(int current, int total, bool& cancel, std::string& model_id, std::string& code)> ImportstlProgressFn;
typedef std::function<void(int current, int total, bool& cancel, std::string& model_id, std::string& code,
std::string& ml_region, std::string& ml_name, std::string& ml_id)> ImportstlProgressFn;
typedef enum {
eNormal, // normal face

View File

@ -46,6 +46,9 @@ extern void stl_internal_reverse_quads(char *buf, size_t cnt);
const int LOAD_STL_UNIT_NUM = 5;
static std::string model_id = "";
static std::string country_code = "";
static std::string ml_name = "";
static std::string ml_id = "";
static std::string ml_region = "";
static FILE *stl_open_count_facets(stl_file *stl, const char *file, unsigned int custom_header_length)
{
@ -162,30 +165,61 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, Impor
else {
rewind(fp);
try{
char solid_name[256];
int res_solid = fscanf(fp, " solid %[^\n]", solid_name);
char solid_content[256];
int res_solid = fscanf(fp, " solid %[^\n]", solid_content);
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];
char country_code_str[16];
int num_values = sscanf(mw_position + 3, "%s %s %s", version_str, model_id_str, country_code_str);
if (num_values == 3) {
if (strcmp(version_str, "1.0") == 0) {
model_id = model_id_str;
country_code = country_code_str;
/*include ml info*/
std::string ext_content(solid_content);
std::string ml_content;
std::string mw_content;
size_t pos = ext_content.find('&');
if (pos != std::string::npos) {
mw_content = ext_content.substr(0, pos);
ml_content = ext_content.substr(pos + 1);
}
if (ml_content.empty() && ext_content.find("ML") != std::string::npos) {
ml_content = ext_content;
}
if (mw_content.empty() && ext_content.find("MW") != std::string::npos) {
mw_content = ext_content;
}
/*parse ml info*/
if (!ml_content.empty()) {
std::istringstream iss(ml_content);
std::string token;
std::vector<std::string> result;
while (iss >> token) {
if (token.find(' ') == std::string::npos) {
result.push_back(token);
}
}
else {
model_id = "";
country_code = "";
if (result.size() == 4 && result[0] == "ML") {
ml_region = result[1];
ml_name = result[2];
ml_id = result[3];
}
}
else {
model_id = ""; // No MW format found
country_code = "";
/*parse mw info*/
if (!mw_content.empty()) {
std::istringstream iss(mw_content);
std::string token;
std::vector<std::string> result;
while (iss >> token) {
if (token.find(' ') == std::string::npos) {
result.push_back(token);
}
}
if (result.size() == 4 && result[0] == "MW") {
model_id = result[2];
country_code = result[3];
}
}
}
}
@ -204,7 +238,7 @@ static bool stl_read(stl_file *stl, FILE *fp, int first_facet, bool first, Impor
if ((i % unit) == 0) {
bool cb_cancel = false;
if (stlFn) {
stlFn(i, facets_num, cb_cancel, model_id, country_code);
stlFn(i, facets_num, cb_cancel, model_id, country_code, ml_region, ml_name, ml_id);
if (cb_cancel)
return false;
}

View File

@ -33,6 +33,11 @@ bool load_obj(const char *path, TriangleMesh *meshptr, ObjInfo& obj_info, std::s
message = _L("load_obj: failed to parse");
return false;
}
obj_info.ml_region = data.ml_region;
obj_info.ml_name = data.ml_name;
obj_info.ml_id = data.ml_id;
bool exist_mtl = false;
if (data.mtllibs.size() > 0) { // read mtl
for (auto mtl_name : data.mtllibs) {

View File

@ -1,13 +1,15 @@
#ifndef slic3r_Format_OBJ_hpp_
#define slic3r_Format_OBJ_hpp_
#include "libslic3r/Color.hpp"
#include "objparser.hpp"
#include <unordered_map>
namespace Slic3r {
class TriangleMesh;
class Model;
class ModelObject;
typedef std::function<void(std::vector<RGBA> &input_colors, bool is_single_color, std::vector<unsigned char> &filament_ids, unsigned char &first_extruder_id)> ObjImportColorFn;
typedef std::function<void(std::vector<RGBA> &input_colors, bool is_single_color, std::vector<unsigned char> &filament_ids, unsigned char &first_extruder_id,
std::string& ml_region, std::string& ml_name, std::string& ml_id)> ObjImportColorFn;
// Load an OBJ file into a provided model.
struct ObjInfo {
std::vector<RGBA> vertex_colors;
@ -19,6 +21,9 @@ struct ObjInfo {
std::unordered_map<int, std::string> uv_map_pngs;
bool has_uv_png{false};
std::string ml_region;
std::string ml_name;
std::string ml_id;
};
extern bool load_obj(const char *path, TriangleMesh *mesh, ObjInfo &vertex_colors, std::string &message);
extern bool load_obj(const char *path, Model *model, ObjInfo &vertex_colors, std::string &message, const char *object_name = nullptr);

View File

@ -137,6 +137,10 @@ const std::string BBL_APPLICATION_TAG = "Application";
const std::string BBL_MAKERLAB_TAG = "MakerLab";
const std::string BBL_MAKERLAB_VERSION_TAG = "MakerLabVersion";
const std::string BBL_MAKERLAB_NAME = "MakerLab";
const std::string BBL_MAKERLAB_REGION = "MakerLabRegion";
const std::string BBL_MAKERLAB_ID = "MakerLabFileId";
const std::string BBL_PROFILE_TITLE_TAG = "ProfileTitle";
const std::string BBL_PROFILE_COVER_TAG = "ProfileCover";
@ -6459,6 +6463,15 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
metadata_item_map[BBL_MAKERLAB_VERSION_TAG] = xml_escape(model.mk_version);
BOOST_LOG_TRIVIAL(info) << "saved mk_version " << model.mk_version;
}
/*for ml*/
if (model.mk_name.empty() && !model.makerlab_name.empty()) {
metadata_item_map[BBL_MAKERLAB_NAME] = model.makerlab_name;
metadata_item_map[BBL_MAKERLAB_REGION] = model.makerlab_region;
metadata_item_map[BBL_MAKERLAB_ID] = model.makerlab_id;
}
if (!model.md_name.empty()) {
for (unsigned int i = 0; i < model.md_name.size(); i++)
{

View File

@ -577,6 +577,8 @@ bool objparse(const char *path, ObjData &data)
char buf[65536 * 2];
size_t len = 0;
size_t lenPrev = 0;
size_t lineCount = 0;
while ((len = ::fread(buf + lenPrev, 1, 65536, pFile)) != 0) {
len += lenPrev;
size_t lastLine = 0;
@ -589,6 +591,13 @@ bool objparse(const char *path, ObjData &data)
//FIXME check the return value and exit on error?
// Will it break parsing of some obj files?
obj_parseline(c, data);
/*for ml*/
if (lineCount == 0) { data.ml_region = parsemlinfo(c, "region:");}
if (lineCount == 1) { data.ml_name = parsemlinfo(c, "ml_name:"); }
if (lineCount == 2) { data.ml_id = parsemlinfo(c, "ml_file_id:");}
++lineCount;
lastLine = i + 1;
}
lenPrev = len - lastLine;
@ -607,6 +616,28 @@ bool objparse(const char *path, ObjData &data)
return true;
}
std::string parsemlinfo(const char* input, const char* condition) {
const char* regionPtr = std::strstr(input, condition);
std::string regionContent = "";
if (regionPtr != nullptr) {
regionPtr += std::strlen(condition);
while (*regionPtr == ' ' || *regionPtr == '\t') {
++regionPtr;
}
const char* endPtr = std::strchr(regionPtr, '\n');
size_t length = (endPtr != nullptr) ? (endPtr - regionPtr) : std::strlen(regionPtr);
regionContent = std::string(regionPtr, length);
}
return regionContent;
}
bool mtlparse(const char *path, MtlData &data)
{
Slic3r::CNumericLocalesSetter locales_setter;
@ -664,6 +695,14 @@ bool objparse(std::istream &stream, ObjData &data)
while (*c == ' ' || *c == '\t')
++ c;
obj_parseline(c, data);
/*for ml*/
if (lastLine < 3) {
data.ml_region = parsemlinfo(c, "region");
data.ml_name = parsemlinfo(c, "ml_name");
data.ml_id = parsemlinfo(c, "ml_file_id");
}
lastLine = i + 1;
}
lenPrev = len - lastLine;

View File

@ -115,6 +115,10 @@ struct ObjData {
// List of faces, delimited by an ObjVertex with all members set to -1.
std::vector<ObjVertex> vertices;
std::string ml_region;
std::string ml_name;
std::string ml_id;
};
struct MtlData
@ -127,6 +131,8 @@ extern bool objparse(const char *path, ObjData &data);
extern bool mtlparse(const char *path, MtlData &data);
extern bool objparse(std::istream &stream, ObjData &data);
extern std::string parsemlinfo(const char* input, const char* condition);
extern bool objbinsave(const char *path, const ObjData &data);
extern bool objbinload(const char *path, ObjData &data);

View File

@ -90,8 +90,15 @@ Model& Model::assign_copy(const Model &rhs)
this->design_id = rhs.design_id;
this->stl_design_id = rhs.stl_design_id;
this->stl_design_country = rhs.stl_design_country;
this->makerlab_region = rhs.makerlab_region;
this->makerlab_name = rhs.makerlab_name;
this->makerlab_id = rhs.makerlab_id;
this->profile_info = rhs.profile_info;
this->makerlab_region = rhs.makerlab_region;
this->makerlab_name = rhs.makerlab_name;
this->makerlab_id = rhs.makerlab_id;
this->mk_name = rhs.mk_name;
this->mk_version = rhs.mk_version;
this->md_name = rhs.md_name;
@ -127,6 +134,9 @@ Model& Model::assign_copy(Model &&rhs)
this->design_id = rhs.design_id;
this->stl_design_id = rhs.stl_design_id;
this->stl_design_country = rhs.stl_design_country;
this->makerlab_region = rhs.makerlab_region;
this->makerlab_name = rhs.makerlab_name;
this->makerlab_id = rhs.makerlab_id;
this->mk_name = rhs.mk_name;
this->mk_version = rhs.mk_version;
this->md_name = rhs.md_name;
@ -234,7 +244,7 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
if (obj_info.vertex_colors.size() > 0) {
std::vector<unsigned char> vertex_filament_ids;
if (objFn) { // 1.result is ok and pop up a dialog
objFn(obj_info.vertex_colors, false, vertex_filament_ids, first_extruder_id);
objFn(obj_info.vertex_colors, false, vertex_filament_ids, first_extruder_id, obj_info.ml_region, obj_info.ml_name, obj_info.ml_id);
if (vertex_filament_ids.size() > 0) {
result = obj_import_vertex_color_deal(vertex_filament_ids, first_extruder_id, & model);
}
@ -242,7 +252,7 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
} else if (obj_info.face_colors.size() > 0 && obj_info.has_uv_png == false) { // mtl file
std::vector<unsigned char> face_filament_ids;
if (objFn) { // 1.result is ok and pop up a dialog
objFn(obj_info.face_colors, obj_info.is_single_mtl, face_filament_ids, first_extruder_id);
objFn(obj_info.face_colors, obj_info.is_single_mtl, face_filament_ids, first_extruder_id, obj_info.ml_region, obj_info.ml_name, obj_info.ml_id);
if (face_filament_ids.size() > 0) {
result = obj_import_face_color_deal(face_filament_ids, first_extruder_id, &model);
}
@ -999,6 +1009,9 @@ void Model::load_from(Model& model)
design_id = model.design_id;
stl_design_id = model.stl_design_id;
stl_design_country = model.stl_design_country;
makerlab_region = model.makerlab_region;
makerlab_name = model.makerlab_name;
makerlab_id = model.makerlab_id;
model_info = model.model_info;
profile_info = model.profile_info;
mk_name = model.mk_name;

View File

@ -1531,6 +1531,11 @@ public:
std::string stl_design_id;
std::string design_id;
std::string stl_design_country;
std::string makerlab_region;
std::string makerlab_name;
std::string makerlab_id;
std::shared_ptr<ModelDesignInfo> design_info = nullptr;
std::shared_ptr<ModelInfo> model_info = nullptr;
std::shared_ptr<ModelProfileInfo> profile_info = nullptr;

View File

@ -3411,7 +3411,8 @@ BoundingBox Plater::priv::scaled_bed_shape_bb() const
}
void read_binary_stl(const std::string& filename, std::string& model_id, std::string& code) {
void read_binary_stl(const std::string& filename, std::string& model_id, std::string& code,
std::string& ml_name, std::string& ml_region, std::string& ml_id) {
std::ifstream file( encode_path(filename.c_str()), std::ios::binary);
if (!file) {
return;
@ -3431,42 +3432,60 @@ void read_binary_stl(const std::string& filename, std::string& model_id, std::st
return;
}
char magic[2] = { data[0], data[1] };
if (magic[0] != 'M' || magic[1] != 'W') {
file.close();
return;
/*include ml info*/
std::string ext_content(data);
std::string ml_content;
std::string mw_content;
size_t pos = ext_content.find('&');
if (pos != std::string::npos) {
ml_content = ext_content.substr(0, pos);
mw_content = ext_content.substr(pos + 1);
}
if (data[2] != ' ') {
file.close();
return;
if (ml_content.empty() && ext_content.find("ML") != std::string::npos) {
ml_content = ext_content;
}
char protocol_version[3] = { data[3], data[4], data[5] };
//version
if (protocol_version[0] != '1' || protocol_version[1] != '.' || protocol_version[2] != '0') {
file.close();
return;
if (mw_content.empty() && ext_content.find("MW") != std::string::npos) {
mw_content = ext_content;
}
std::vector<char*> tokens;
std::istringstream iss(data);
std::string token;
while (std::getline(iss, token, ' ')) {
char* tokenPtr = new char[token.length() + 1];
std::strcpy(tokenPtr, token.c_str());
tokens.push_back(tokenPtr);
/*parse ml info*/
if (!ml_content.empty()) {
std::istringstream iss(ml_content);
std::string token;
std::vector<std::string> result;
while (iss >> token) {
if (token.find(' ') == std::string::npos) {
result.push_back(token);
}
}
if (result.size() == 4 && result[0] == "ML") {
ml_region = result[1];
ml_name = result[2];
ml_id = result[3];
}
}
//model id
if (tokens.size() < 4) {
file.close();
return;
/*parse mw info*/
if (!mw_content.empty()) {
std::istringstream iss(mw_content);
std::string token;
std::vector<std::string> result;
while (iss >> token) {
if (token.find(' ') == std::string::npos) {
result.push_back(token);
}
}
if (result.size() == 4 && result[0] == "MW") {
model_id = result[2];
code = result[3];
}
}
model_id = tokens[2];
code = tokens[3];
file.close();
}
catch (...) {
@ -3513,6 +3532,9 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
std::string designer_model_id;
std::string designer_country_code;
std::string makerlab_region;
std::string makerlab_name;
std::string makerlab_id;
int answer_convert_from_meters = wxOK_DEFAULT;
int answer_convert_from_imperial_units = wxOK_DEFAULT;
@ -3975,8 +3997,13 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
bool is_xxx;
Semver file_version;
//ObjImportColorFn obj_color_fun=nullptr;
auto obj_color_fun = [this, &path](std::vector<RGBA> &input_colors, bool is_single_color, std::vector<unsigned char> &filament_ids,
unsigned char &first_extruder_id) {
auto obj_color_fun = [this, &path, &makerlab_region, &makerlab_name, &makerlab_id](std::vector<RGBA> &input_colors, bool is_single_color, std::vector<unsigned char> &filament_ids,
unsigned char& first_extruder_id, std::string ml_origin, std::string ml_name, std::string ml_id) {
makerlab_region = ml_origin;
makerlab_name = ml_name;
makerlab_id = ml_id;
if (!boost::iends_with(path.string(), ".obj")) { return; }
const std::vector<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
ObjColorDialog color_dlg(nullptr, input_colors, is_single_color, extruder_colours, filament_ids, first_extruder_id);
@ -3999,10 +4026,14 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
};
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, &designer_model_id, &designer_country_code](int current, int total, bool &cancel, std::string &mode_id, std::string &code)
[this, &dlg, real_filename, &progress_percent, &file_percent, INPUT_FILES_RATIO, total_files, i, &designer_model_id, &designer_country_code, &makerlab_region, &makerlab_name, &makerlab_id](int current, int total, bool &cancel,
std::string &mode_id, std::string &code, std::string &ml_region, std::string &ml_name, std::string &ml_id)
{
designer_model_id = mode_id;
designer_country_code = code;
designer_model_id = mode_id;
designer_country_code = code;
makerlab_region = ml_region;
makerlab_name = ml_name;
makerlab_id = ml_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;
@ -4031,7 +4062,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
if (designer_model_id.empty() && boost::algorithm::iends_with(path.string(), ".stl")) {
read_binary_stl(path.string(), designer_model_id, designer_country_code);
read_binary_stl(path.string(), designer_model_id, designer_country_code, makerlab_name, makerlab_region, makerlab_id);
}
if (type_any_amf && is_xxx) imperial_units = true;
@ -4342,6 +4373,10 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
//set designer_model_id
q->model().stl_design_id = designer_model_id;
q->model().stl_design_country = designer_country_code;
q->model().makerlab_region = makerlab_region;
q->model().makerlab_name = makerlab_name;
q->model().makerlab_id = makerlab_id;
//if (!designer_model_id.empty() && q->model().stl_design_id.empty() && !designer_country_code.empty()) {
// q->model().stl_design_id = designer_model_id;
// q->model().stl_design_country = designer_country_code;
@ -5772,7 +5807,8 @@ void Plater::priv::reload_from_disk()
// load one file at a time
for (size_t i = 0; i < input_paths.size(); ++i) {
const auto& path = input_paths[i].string();
auto obj_color_fun = [this, &path](std::vector<RGBA> &input_colors, bool is_single_color, std::vector<unsigned char> &filament_ids, unsigned char &first_extruder_id) {
auto obj_color_fun = [this, &path](std::vector<RGBA> &input_colors, bool is_single_color, std::vector<unsigned char> &filament_ids, unsigned char &first_extruder_id,
std::string ml_origin, std::string ml_name, std::string ml_id) {
if (!boost::iends_with(path, ".obj")) { return; }
const std::vector<std::string> extruder_colours = wxGetApp().plater()->get_extruder_colors_from_plater_config();
ObjColorDialog color_dlg(nullptr, input_colors, is_single_color, extruder_colours, filament_ids, first_extruder_id);