ENH: slicing: add cache data load/export for slicing

Change-Id: I88b7c79b6f79ec6bed0f829316b67310cac99b44
(cherry picked from commit 67c1d2e8dd459cc4450ce580632f01e25db038ac)
This commit is contained in:
lane.wei 2022-11-22 15:22:47 +08:00 committed by Lane.Wei
parent 2ffa56633c
commit c3abc64b61
13 changed files with 1471 additions and 192 deletions

View file

@ -91,29 +91,6 @@ using namespace Slic3r;
std::string message; std::string message;
}error_message;*/ }error_message;*/
#define CLI_SUCCESS 0
#define CLI_ENVIRONMENT_ERROR -1
#define CLI_INVALID_PARAMS -2
#define CLI_FILE_NOTFOUND -3
#define CLI_FILELIST_INVALID_ORDER -4
#define CLI_CONFIG_FILE_ERROR -5
#define CLI_DATA_FILE_ERROR -6
#define CLI_INVALID_PRINTER_TECH -7
#define CLI_UNSUPPORTED_OPERATION -8
#define CLI_COPY_OBJECTS_ERROR -9
#define CLI_SCALE_TO_FIT_ERROR -10
#define CLI_EXPORT_STL_ERROR -11
#define CLI_EXPORT_OBJ_ERROR -12
#define CLI_EXPORT_3MF_ERROR -13
#define CLI_NO_SUITABLE_OBJECTS -50
#define CLI_VALIDATE_ERROR -51
#define CLI_OBJECTS_PARTLY_INSIDE -52
#define CLI_SLICING_ERROR -100
std::map<int, std::string> cli_errors = { std::map<int, std::string> cli_errors = {
{CLI_SUCCESS, "Success"}, {CLI_SUCCESS, "Success"},
@ -130,9 +107,15 @@ std::map<int, std::string> cli_errors = {
{CLI_EXPORT_STL_ERROR, "Export stl error"}, {CLI_EXPORT_STL_ERROR, "Export stl error"},
{CLI_EXPORT_OBJ_ERROR, "Export obj error"}, {CLI_EXPORT_OBJ_ERROR, "Export obj error"},
{CLI_EXPORT_3MF_ERROR, "Export 3mf error"}, {CLI_EXPORT_3MF_ERROR, "Export 3mf error"},
{CLI_OUT_OF_MEMORY, "Out of memory"},
{CLI_NO_SUITABLE_OBJECTS, "Found no objects in print volume to slice"}, {CLI_NO_SUITABLE_OBJECTS, "Found no objects in print volume to slice"},
{CLI_VALIDATE_ERROR, "Validate print error"}, {CLI_VALIDATE_ERROR, "Validate print error"},
{CLI_OBJECTS_PARTLY_INSIDE, "Objects partly inside"}, {CLI_OBJECTS_PARTLY_INSIDE, "Objects partly inside"},
{CLI_EXPORT_CACHE_DIRECTORY_CREATE_FAILED, "Objects partly inside"},
{CLI_EXPORT_CACHE_WRITE_FAILED, "export cached slicedata failed"},
{CLI_IMPORT_CACHE_NOT_FOUND, "cached slicedata can not be found"},
{CLI_IMPORT_CACHE_DATA_CAN_NOT_USE, "cached slicedata can not be used"},
{CLI_IMPORT_CACHE_LOAD_FAILED, "load cached slicedata failed"},
{CLI_SLICING_ERROR, "Slice error"} {CLI_SLICING_ERROR, "Slice error"}
}; };
@ -374,12 +357,12 @@ int CLI::run(int argc, char **argv)
int debug_argc = 7; int debug_argc = 7;
char *debug_argv[] = { char *debug_argv[] = {
"E:\work\projects\bambu_release\bamboo_slicer\build_debug\src\Debug\bambu-studio.exe", "E:\work\projects\bambu_release\bamboo_slicer\build_debug\src\Debug\bambu-studio.exe",
"--load-slicedata",
"cached_data",
"--slice", "--slice",
"2", "0",
"--export-3mf=output.3mf", "--export-3mf=output.3mf",
"--load-filaments", "test.3mf"
"GFSA05.json;GFSA04.json;;GFSA05.json;GFSL23.json",
"majiang.3mf"
}; };
if (! this->setup(debug_argc, debug_argv))*/ if (! this->setup(debug_argc, debug_argv))*/
if (!this->setup(argc, argv)) if (!this->setup(argc, argv))
@ -1345,8 +1328,8 @@ int CLI::run(int argc, char **argv)
o->ensure_on_bed(); o->ensure_on_bed();
// loop through action options // loop through action options
bool export_to_3mf = false; bool export_to_3mf = false, load_slicedata = false, export_slicedata = false, export_slicedata_error = false;
std::string export_3mf_file; std::string export_3mf_file, load_slice_data_dir, export_slice_data_dir;
std::string outfile_dir = m_config.opt_string("outputdir"); std::string outfile_dir = m_config.opt_string("outputdir");
std::vector<ThumbnailData*> calibration_thumbnails; std::vector<ThumbnailData*> calibration_thumbnails;
for (auto const &opt_key : m_actions) { for (auto const &opt_key : m_actions) {
@ -1361,6 +1344,13 @@ int CLI::run(int argc, char **argv)
std::string pipe_name = m_config.option<ConfigOptionString>("pipe")->value; std::string pipe_name = m_config.option<ConfigOptionString>("pipe")->value;
g_cli_callback_mgr.start(pipe_name); g_cli_callback_mgr.start(pipe_name);
#endif #endif
} else if (opt_key == "load_slicedata") {
load_slicedata = true;
load_slice_data_dir = m_config.opt_string(opt_key);
if (export_slicedata) {
BOOST_LOG_TRIVIAL(error) << "should not set load_slicedata and export_slicedata together." << std::endl;
flush_and_exit(CLI_INVALID_PARAMS);
}
} else if (opt_key == "export_settings") { } else if (opt_key == "export_settings") {
//FIXME check for mixing the FFF / SLA parameters. //FIXME check for mixing the FFF / SLA parameters.
// or better save fff_print_config vs. sla_print_config // or better save fff_print_config vs. sla_print_config
@ -1377,7 +1367,7 @@ int CLI::run(int argc, char **argv)
model.add_default_instances(); model.add_default_instances();
if (! this->export_models(IO::STL)) if (! this->export_models(IO::STL))
flush_and_exit(CLI_EXPORT_STL_ERROR); flush_and_exit(CLI_EXPORT_STL_ERROR);
} else if (opt_key == "expor1t_obj") { } else if (opt_key == "export_obj") {
for (auto &model : m_models) for (auto &model : m_models)
model.add_default_instances(); model.add_default_instances();
if (! this->export_models(IO::OBJ)) if (! this->export_models(IO::OBJ))
@ -1389,6 +1379,13 @@ int CLI::run(int argc, char **argv)
export_to_3mf = true; export_to_3mf = true;
export_3mf_file = m_config.opt_string(opt_key); export_3mf_file = m_config.opt_string(opt_key);
//} else if (opt_key == "export_gcode" || opt_key == "export_sla" || opt_key == "slice") { //} else if (opt_key == "export_gcode" || opt_key == "export_sla" || opt_key == "slice") {
} else if (opt_key == "export_slicedata") {
export_slicedata = true;
export_slice_data_dir = m_config.opt_string(opt_key);
if (load_slicedata) {
BOOST_LOG_TRIVIAL(error) << "should not set load_slicedata and export_slicedata together." << std::endl;
flush_and_exit(CLI_INVALID_PARAMS);
}
} else if (opt_key == "slice") { } else if (opt_key == "slice") {
//BBS: slice 0 means all plates, i means plate i; //BBS: slice 0 means all plates, i means plate i;
plate_to_slice = m_config.option<ConfigOptionInt>("slice")->value; plate_to_slice = m_config.option<ConfigOptionInt>("slice")->value;
@ -1530,7 +1527,23 @@ int CLI::run(int argc, char **argv)
} }
} }
#endif #endif
print->process(); if (load_slicedata) {
std::string plate_dir = load_slice_data_dir+"/"+std::to_string(index+1);
int ret = print->load_cached_data(plate_dir);
if (ret) {
BOOST_LOG_TRIVIAL(warning) << "plate "<< index+1<< ": load Slicing data error, ret=" << ret;
BOOST_LOG_TRIVIAL(warning) << "plate "<< index+1<< ": switch normal slicing";
print->process();
}
else {
BOOST_LOG_TRIVIAL(info) << "plate "<< index+1<< ": load cached data success, go on.";
print->process(true);
BOOST_LOG_TRIVIAL(info) << "plate "<< index+1<< ": finished print::process.";
}
}
else {
print->process();
}
if (printer_technology == ptFFF) { if (printer_technology == ptFFF) {
// The outfile is processed by a PlaceholderParser. // The outfile is processed by a PlaceholderParser.
//outfile = part_plate->get_tmp_gcode_path(); //outfile = part_plate->get_tmp_gcode_path();
@ -1569,6 +1582,18 @@ int CLI::run(int argc, char **argv)
cli_status_callback(slicing_status); cli_status_callback(slicing_status);
} }
#endif #endif
if (export_slicedata) {
BOOST_LOG_TRIVIAL(info) << "plate "<< index+1<< ":will export Slicing data to " << export_slice_data_dir;
std::string plate_dir = export_slice_data_dir+"/"+std::to_string(index+1);
bool with_space = (get_logging_level() >= 4)?true:false;
int ret = print->export_cached_data(plate_dir, with_space);
if (ret) {
BOOST_LOG_TRIVIAL(error) << "plate "<< index+1<< ": export Slicing data error, ret=" << ret;
export_slicedata_error = true;
if (fs::exists(plate_dir))
fs::remove_all(plate_dir);
}
}
} catch (const std::exception &ex) { } catch (const std::exception &ex) {
BOOST_LOG_TRIVIAL(info) << "found slicing or export error for partplate "<<index+1 << std::endl; BOOST_LOG_TRIVIAL(info) << "found slicing or export error for partplate "<<index+1 << std::endl;
boost::nowide::cerr << ex.what() << std::endl; boost::nowide::cerr << ex.what() << std::endl;
@ -2037,8 +2062,9 @@ bool CLI::setup(int argc, char **argv)
#if !BBL_RELEASE_TO_PUBLIC #if !BBL_RELEASE_TO_PUBLIC
{ {
const ConfigOptionInt *opt_loglevel = m_config.opt<ConfigOptionInt>("debug"); const ConfigOptionInt *opt_loglevel = m_config.opt<ConfigOptionInt>("debug");
if (opt_loglevel != 0) if (opt_loglevel != 0) {
set_logging_level(opt_loglevel->value); set_logging_level(opt_loglevel->value);
}
} }
#endif #endif

View file

@ -137,6 +137,7 @@ public:
// Height of the extrusion, used for visualization purposes. // Height of the extrusion, used for visualization purposes.
float height; float height;
ExtrusionPath() : mm3_per_mm(-1), width(-1), height(-1), m_role(erNone), m_no_extrusion(false) {}
ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), m_role(role), m_no_extrusion(false) {} ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), m_role(role), m_no_extrusion(false) {}
ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height, bool no_extrusion = false) : mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role), m_no_extrusion(no_extrusion) {} ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height, bool no_extrusion = false) : mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role), m_no_extrusion(no_extrusion) {}
ExtrusionPath(int overhang_degree, int curve_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) : overhang_degree(overhang_degree), curve_degree(curve_degree), mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role) {} ExtrusionPath(int overhang_degree, int curve_degree, ExtrusionRole role, double mm3_per_mm, float width, float height) : overhang_degree(overhang_degree), curve_degree(curve_degree), mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role) {}
@ -225,6 +226,8 @@ public:
void simplify_by_fitting_arc(double tolerance); void simplify_by_fitting_arc(double tolerance);
//BBS: //BBS:
bool is_force_no_extrusion() const { return m_no_extrusion; } bool is_force_no_extrusion() const { return m_no_extrusion; }
void set_force_no_extrusion(bool no_extrusion) { m_no_extrusion = no_extrusion; }
void set_extrusion_role(ExtrusionRole extrusion_role) { m_role = extrusion_role; }
private: private:
void _inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const; void _inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const;
@ -241,7 +244,7 @@ class ExtrusionMultiPath : public ExtrusionEntity
{ {
public: public:
ExtrusionPaths paths; ExtrusionPaths paths;
ExtrusionMultiPath() {} ExtrusionMultiPath() {}
ExtrusionMultiPath(const ExtrusionMultiPath &rhs) : paths(rhs.paths) {} ExtrusionMultiPath(const ExtrusionMultiPath &rhs) : paths(rhs.paths) {}
ExtrusionMultiPath(ExtrusionMultiPath &&rhs) : paths(std::move(rhs.paths)) {} ExtrusionMultiPath(ExtrusionMultiPath &&rhs) : paths(std::move(rhs.paths)) {}
@ -278,7 +281,7 @@ public:
double min_mm3_per_mm() const override; double min_mm3_per_mm() const override;
Polyline as_polyline() const override; Polyline as_polyline() const override;
void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); } void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); }
void collect_points(Points &dst) const override { void collect_points(Points &dst) const override {
size_t n = std::accumulate(paths.begin(), paths.end(), 0, [](const size_t n, const ExtrusionPath &p){ return n + p.polyline.size(); }); size_t n = std::accumulate(paths.begin(), paths.end(), 0, [](const size_t n, const ExtrusionPath &p){ return n + p.polyline.size(); });
dst.reserve(dst.size() + n); dst.reserve(dst.size() + n);
for (const ExtrusionPath &p : this->paths) for (const ExtrusionPath &p : this->paths)
@ -292,11 +295,11 @@ class ExtrusionLoop : public ExtrusionEntity
{ {
public: public:
ExtrusionPaths paths; ExtrusionPaths paths;
ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {} ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {}
ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {} ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {}
ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {} ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {}
ExtrusionLoop(const ExtrusionPath &path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role) ExtrusionLoop(const ExtrusionPath &path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
{ this->paths.push_back(path); } { this->paths.push_back(path); }
ExtrusionLoop(const ExtrusionPath &&path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role) ExtrusionLoop(const ExtrusionPath &&path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role)
{ this->paths.emplace_back(std::move(path)); } { this->paths.emplace_back(std::move(path)); }
@ -329,6 +332,7 @@ public:
bool has_overhang_point(const Point &point) const; bool has_overhang_point(const Point &point) const;
ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); } ExtrusionRole role() const override { return this->paths.empty() ? erNone : this->paths.front().role(); }
ExtrusionLoopRole loop_role() const { return m_loop_role; } ExtrusionLoopRole loop_role() const { return m_loop_role; }
void set_loop_role(ExtrusionLoopRole role) { m_loop_role = role; }
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width. // Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps. // Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override; void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;
@ -344,7 +348,7 @@ public:
double min_mm3_per_mm() const override; double min_mm3_per_mm() const override;
Polyline as_polyline() const override { return this->polygon().split_at_first_point(); } Polyline as_polyline() const override { return this->polygon().split_at_first_point(); }
void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); } void collect_polylines(Polylines &dst) const override { Polyline pl = this->as_polyline(); if (! pl.empty()) dst.emplace_back(std::move(pl)); }
void collect_points(Points &dst) const override { void collect_points(Points &dst) const override {
size_t n = std::accumulate(paths.begin(), paths.end(), 0, [](const size_t n, const ExtrusionPath &p){ return n + p.polyline.size(); }); size_t n = std::accumulate(paths.begin(), paths.end(), 0, [](const size_t n, const ExtrusionPath &p){ return n + p.polyline.size(); });
dst.reserve(dst.size() + n); dst.reserve(dst.size() + n);
for (const ExtrusionPath &p : this->paths) for (const ExtrusionPath &p : this->paths)

View file

@ -245,6 +245,7 @@ static constexpr const char* PATTERN_FILE_ATTR = "pattern_file";
static constexpr const char* PATTERN_BBOX_FILE_ATTR = "pattern_bbox_file"; static constexpr const char* PATTERN_BBOX_FILE_ATTR = "pattern_bbox_file";
static constexpr const char* OBJECT_ID_ATTR = "object_id"; static constexpr const char* OBJECT_ID_ATTR = "object_id";
static constexpr const char* INSTANCEID_ATTR = "instance_id"; static constexpr const char* INSTANCEID_ATTR = "instance_id";
static constexpr const char* ARRANGE_ORDER_ATTR = "arrange_order";
static constexpr const char* PLATERID_ATTR = "plater_id"; static constexpr const char* PLATERID_ATTR = "plater_id";
static constexpr const char* PLATE_IDX_ATTR = "index"; static constexpr const char* PLATE_IDX_ATTR = "index";
static constexpr const char* SLICE_PREDICTION_ATTR = "prediction"; static constexpr const char* SLICE_PREDICTION_ATTR = "prediction";
@ -604,6 +605,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
{ {
int object_id; int object_id;
int instance_id; int instance_id;
int arrange_order;
}; };
struct Instance struct Instance
@ -1123,6 +1125,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
m_plater_data.clear(); m_plater_data.clear();
m_curr_instance.object_id = -1; m_curr_instance.object_id = -1;
m_curr_instance.instance_id = -1; m_curr_instance.instance_id = -1;
m_curr_instance.arrange_order = 0;
clear_errors(); clear_errors();
// restore // restore
@ -1570,7 +1573,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
return false; return false;
} }
if (current_plate_data) { if (current_plate_data) {
std::map<int, int>::iterator it = current_plate_data->obj_inst_map.find(object.first.second); std::map<int, std::pair<int, int>>::iterator it = current_plate_data->obj_inst_map.find(object.first.second);
if (it == current_plate_data->obj_inst_map.end()) { if (it == current_plate_data->obj_inst_map.end()) {
//not in current plate, skip //not in current plate, skip
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", could not find object %1% in plate %2%, skip it\n")%object.first.second %plate_id; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", could not find object %1% in plate %2%, skip it\n")%object.first.second %plate_id;
@ -1769,8 +1772,46 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
plate_data_list[it->first-1]->pattern_file = (m_load_restore || it->second->pattern_file.empty()) ? it->second->pattern_file : m_backup_path + "/" + it->second->pattern_file; plate_data_list[it->first-1]->pattern_file = (m_load_restore || it->second->pattern_file.empty()) ? it->second->pattern_file : m_backup_path + "/" + it->second->pattern_file;
plate_data_list[it->first-1]->pattern_bbox_file = (m_load_restore || it->second->pattern_bbox_file.empty()) ? it->second->pattern_bbox_file : m_backup_path + "/" + it->second->pattern_bbox_file; plate_data_list[it->first-1]->pattern_bbox_file = (m_load_restore || it->second->pattern_bbox_file.empty()) ? it->second->pattern_bbox_file : m_backup_path + "/" + it->second->pattern_bbox_file;
plate_data_list[it->first-1]->config = it->second->config; plate_data_list[it->first-1]->config = it->second->config;
current_plate_data = plate_data_list[it->first - 1];
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", plate %1%, thumbnail_file=%2%")%it->first %plate_data_list[it->first-1]->thumbnail_file; BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" << __LINE__ << boost::format(", plate %1%, thumbnail_file=%2%")%it->first %plate_data_list[it->first-1]->thumbnail_file;
it++; it++;
//update the arrange order
std::map<int, std::pair<int, int>>::iterator map_it = current_plate_data->obj_inst_map.begin();
while (map_it != current_plate_data->obj_inst_map.end()) {
int obj_index, obj_id = map_it->first, inst_index = map_it->second.first;
IndexToPathMap::iterator index_iter = m_index_paths.find(obj_id);
if (index_iter == m_index_paths.end()) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ":" << __LINE__
<< boost::format(", can not find object from plate's obj_map, id=%1%, skip this object")%obj_id;
map_it++;
continue;
}
Id temp_id = std::make_pair(index_iter->second, index_iter->first);
IdToModelObjectMap::iterator object_item = m_objects.find(temp_id);
if (object_item == m_objects.end()) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ":" << __LINE__
<< boost::format(", can not find object from plate's obj_map, ID <%1%, %2%>, skip this object")%index_iter->second %index_iter->first;
map_it++;
continue;
}
obj_index = object_item->second;
if (obj_index >= m_model->objects.size()) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ":" << __LINE__ << boost::format("invalid object id %1%\n")%obj_index;
map_it++;
continue;
}
ModelObject* obj = m_model->objects[obj_index];
if (inst_index >= obj->instances.size()) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ":" << __LINE__ << boost::format("invalid instance id %1%\n")%inst_index;
map_it++;
continue;
}
ModelInstance* inst = obj->instances[inst_index];
inst->arrange_order = map_it->second.second;
map_it++;
}
} }
if ((plate_id > 0) && (plate_id <= m_plater_data.size())) { if ((plate_id > 0) && (plate_id <= m_plater_data.size())) {
@ -3417,6 +3458,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
{ {
m_curr_instance.instance_id = atoi(value.c_str()); m_curr_instance.instance_id = atoi(value.c_str());
} }
else if (key == ARRANGE_ORDER_ATTR)
{
m_curr_instance.arrange_order = atoi(value.c_str());
}
else if (key == OBJECT_ID_ATTR) else if (key == OBJECT_ID_ATTR)
{ {
m_curr_instance.object_id = atoi(value.c_str()); m_curr_instance.object_id = atoi(value.c_str());
@ -3570,11 +3615,13 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
//add_error("invalid object id/instance id"); //add_error("invalid object id/instance id");
//skip this instance //skip this instance
m_curr_instance.object_id = m_curr_instance.instance_id = -1; m_curr_instance.object_id = m_curr_instance.instance_id = -1;
m_curr_instance.arrange_order = 0;
return true; return true;
} }
m_curr_plater->obj_inst_map.emplace(m_curr_instance.object_id, m_curr_instance.instance_id); m_curr_plater->obj_inst_map.emplace(m_curr_instance.object_id, std::make_pair(m_curr_instance.instance_id, m_curr_instance.arrange_order));
m_curr_instance.object_id = m_curr_instance.instance_id = -1; m_curr_instance.object_id = m_curr_instance.instance_id = -1;
m_curr_instance.arrange_order = 0;
return true; return true;
} }
@ -6360,14 +6407,32 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
stream << " <" << INSTANCE_TAG << ">\n"; stream << " <" << INSTANCE_TAG << ">\n";
int obj_id = plate_data->objects_and_instances[j].first; int obj_id = plate_data->objects_and_instances[j].first;
int inst_id = plate_data->objects_and_instances[j].second; int inst_id = plate_data->objects_and_instances[j].second;
if (m_skip_static) { int arrange_o = 0;
obj_id = model.objects[obj_id]->get_backup_id(); ModelObject* obj = NULL;
ModelInstance* inst = NULL;
if (obj_id >= model.objects.size()) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ":" << __LINE__ << boost::format("invalid object id %1%\n")%obj_id;
}
else
obj = model.objects[obj_id];
if (obj && (inst_id >= obj->instances.size())) {
BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << ":" << __LINE__ << boost::format("invalid instance id %1%\n")%inst_id;
}
else if (obj){
inst = obj->instances[inst_id];
arrange_o = inst->arrange_order;
}
if (m_skip_static && obj) {
obj_id = obj->get_backup_id();
} else { } else {
//inst_id = convert_instance_id_to_resource_id(model, obj_id, inst_id); //inst_id = convert_instance_id_to_resource_id(model, obj_id, inst_id);
obj_id = convert_instance_id_to_resource_id(model, obj_id, 0); obj_id = convert_instance_id_to_resource_id(model, obj_id, 0);
} }
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << OBJECT_ID_ATTR << "\" " << VALUE_ATTR << "=\"" << obj_id << "\"/>\n"; stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << OBJECT_ID_ATTR << "\" " << VALUE_ATTR << "=\"" << obj_id << "\"/>\n";
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << INSTANCEID_ATTR << "\" " << VALUE_ATTR << "=\"" << inst_id << "\"/>\n"; stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << INSTANCEID_ATTR << "\" " << VALUE_ATTR << "=\"" << inst_id << "\"/>\n";
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << ARRANGE_ORDER_ATTR << "\" " << VALUE_ATTR << "=\"" << arrange_o << "\"/>\n";
stream << " </" << INSTANCE_TAG << ">\n"; stream << " </" << INSTANCE_TAG << ">\n";
} }
} }

View file

@ -57,7 +57,7 @@ struct PlateData
int plate_index; int plate_index;
std::vector<std::pair<int, int>> objects_and_instances; std::vector<std::pair<int, int>> objects_and_instances;
std::map<int, int> obj_inst_map; std::map<int, std::pair<int, int>> obj_inst_map;
std::string gcode_file; std::string gcode_file;
std::string gcode_file_md5; std::string gcode_file_md5;
std::string thumbnail_file; std::string thumbnail_file;

View file

@ -65,7 +65,7 @@ public:
// ordered collection of extrusion paths to fill surfaces // ordered collection of extrusion paths to fill surfaces
// (this collection contains only ExtrusionEntityCollection objects) // (this collection contains only ExtrusionEntityCollection objects)
ExtrusionEntityCollection fills; ExtrusionEntityCollection fills;
Flow flow(FlowRole role) const; Flow flow(FlowRole role) const;
Flow flow(FlowRole role, double layer_height) const; Flow flow(FlowRole role, double layer_height) const;
Flow bridging_flow(FlowRole role, bool thick_bridge = false) const; Flow bridging_flow(FlowRole role, bool thick_bridge = false) const;
@ -110,7 +110,7 @@ private:
const PrintRegion *m_region; const PrintRegion *m_region;
}; };
class Layer class Layer
{ {
public: public:
// Sequential index of this layer in PrintObject::m_layers, offsetted by the number of raft layers. // Sequential index of this layer in PrintObject::m_layers, offsetted by the number of raft layers.
@ -132,7 +132,7 @@ public:
mutable ExPolygons cantilevers; mutable ExPolygons cantilevers;
mutable std::map<const ExPolygon*, float> sharp_tails_height; mutable std::map<const ExPolygon*, float> sharp_tails_height;
// Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry // Collection of expolygons generated by slicing the possibly multiple meshes of the source geometry
// (with possibly differing extruder ID and slicing parameters) and merged. // (with possibly differing extruder ID and slicing parameters) and merged.
// For the first layer, if the Elephant foot compensation is applied, this lslice is uncompensated, therefore // For the first layer, if the Elephant foot compensation is applied, this lslice is uncompensated, therefore
// it includes the Elephant foot effect, thus it corresponds to the shape of the printed 1st layer. // it includes the Elephant foot effect, thus it corresponds to the shape of the printed 1st layer.
@ -149,7 +149,7 @@ public:
LayerRegion* add_region(const PrintRegion *print_region); LayerRegion* add_region(const PrintRegion *print_region);
const LayerRegionPtrs& regions() const { return m_regions; } const LayerRegionPtrs& regions() const { return m_regions; }
// Test whether whether there are any slices assigned to this layer. // Test whether whether there are any slices assigned to this layer.
bool empty() const; bool empty() const;
void make_slices(); void make_slices();
// Backup and restore raw sliced regions if needed. // Backup and restore raw sliced regions if needed.
//FIXME Review whether not to simplify the code by keeping the raw_slices all the time. //FIXME Review whether not to simplify the code by keeping the raw_slices all the time.
@ -209,7 +209,7 @@ private:
LayerRegionPtrs m_regions; LayerRegionPtrs m_regions;
}; };
class SupportLayer : public Layer class SupportLayer : public Layer
{ {
public: public:
// Polygons covered by the supports: base, interface and contact areas. // Polygons covered by the supports: base, interface and contact areas.

File diff suppressed because it is too large Load diff

View file

@ -628,10 +628,13 @@ public:
ApplyStatus apply(const Model &model, DynamicPrintConfig config) override; ApplyStatus apply(const Model &model, DynamicPrintConfig config) override;
void process() override; void process(bool use_cache = false) override;
// Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file. // Exports G-code into a file name based on the path_template, returns the file path of the generated G-code file.
// If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r). // If preview_data is not null, the preview_data is filled in for the G-code visualization (not used by the command line Slic3r).
std::string export_gcode(const std::string& path_template, GCodeProcessorResult* result, ThumbnailsGeneratorCallback thumbnail_cb = nullptr); std::string export_gcode(const std::string& path_template, GCodeProcessorResult* result, ThumbnailsGeneratorCallback thumbnail_cb = nullptr);
//return 0 means successful
int export_cached_data(const std::string& dir_path, bool with_space=false);
int load_cached_data(const std::string& directory);
// methods for handling state // methods for handling state
bool is_step_done(PrintStep step) const { return Inherited::is_step_done(step); } bool is_step_done(PrintStep step) const { return Inherited::is_step_done(step); }
@ -788,6 +791,7 @@ public:
static float min_skirt_length; static float min_skirt_length;
}; };
} /* slic3r_Print_hpp_ */ } /* slic3r_Print_hpp_ */
#endif #endif

View file

@ -419,7 +419,9 @@ public:
// After calling the apply() function, call set_task() to limit the task to be processed by process(). // After calling the apply() function, call set_task() to limit the task to be processed by process().
virtual void set_task(const TaskParams &params) {} virtual void set_task(const TaskParams &params) {}
// Perform the calculation. This is the only method that is to be called at a worker thread. // Perform the calculation. This is the only method that is to be called at a worker thread.
virtual void process() = 0; virtual void process(bool use_cache = false) = 0;
virtual int export_cached_data(const std::string& dir_path, bool with_space=false) { return 0;}
virtual int load_cached_data(const std::string& directory) { return 0;}
// Clean up after process() finished, either with success, error or if canceled. // Clean up after process() finished, either with success, error or if canceled.
// The adjustments on the Print / PrintObject data due to set_task() are to be reverted here. // The adjustments on the Print / PrintObject data due to set_task() are to be reverted here.
virtual void finalize() {} virtual void finalize() {}

View file

@ -4333,6 +4333,18 @@ CLIActionsConfigDef::CLIActionsConfigDef()
def->cli_params = "filename.3mf"; def->cli_params = "filename.3mf";
def->set_default_value(new ConfigOptionString("output.3mf")); def->set_default_value(new ConfigOptionString("output.3mf"));
def = this->add("export_slicedata", coString);
def->label = L("Export slicing data");
def->tooltip = L("Export slicing data to a folder.");
def->cli_params = "slicing_data_directory";
def->set_default_value(new ConfigOptionString("cached_data"));
def = this->add("load_slicedata", coStrings);
def->label = L("Load slicing data");
def->tooltip = L("Load cached slicing data from directory");
def->cli_params = "slicing_data_directory";
def->set_default_value(new ConfigOptionString("cached_data"));
/*def = this->add("export_amf", coBool); /*def = this->add("export_amf", coBool);
def->label = L("Export AMF"); def->label = L("Export AMF");
def->tooltip = L("Export the model(s) as AMF."); def->tooltip = L("Export the model(s) as AMF.");

View file

@ -37,7 +37,7 @@ bool is_zero_elevation(const SLAPrintObjectConfig &c)
sla::SupportTreeConfig make_support_cfg(const SLAPrintObjectConfig& c) sla::SupportTreeConfig make_support_cfg(const SLAPrintObjectConfig& c)
{ {
sla::SupportTreeConfig scfg; sla::SupportTreeConfig scfg;
scfg.enabled = c.supports_enable.getBool(); scfg.enabled = c.supports_enable.getBool();
scfg.head_front_radius_mm = 0.5*c.support_head_front_diameter.getFloat(); scfg.head_front_radius_mm = 0.5*c.support_head_front_diameter.getFloat();
double pillar_r = 0.5 * c.support_pillar_diameter.getFloat(); double pillar_r = 0.5 * c.support_pillar_diameter.getFloat();
@ -66,18 +66,18 @@ sla::SupportTreeConfig make_support_cfg(const SLAPrintObjectConfig& c)
scfg.pillar_base_safety_distance_mm = scfg.pillar_base_safety_distance_mm =
c.support_base_safety_distance.getFloat() < EPSILON ? c.support_base_safety_distance.getFloat() < EPSILON ?
scfg.safety_distance_mm : c.support_base_safety_distance.getFloat(); scfg.safety_distance_mm : c.support_base_safety_distance.getFloat();
scfg.max_bridges_on_pillar = unsigned(c.support_max_bridges_on_pillar.getInt()); scfg.max_bridges_on_pillar = unsigned(c.support_max_bridges_on_pillar.getInt());
return scfg; return scfg;
} }
sla::PadConfig::EmbedObject builtin_pad_cfg(const SLAPrintObjectConfig& c) sla::PadConfig::EmbedObject builtin_pad_cfg(const SLAPrintObjectConfig& c)
{ {
sla::PadConfig::EmbedObject ret; sla::PadConfig::EmbedObject ret;
ret.enabled = is_zero_elevation(c); ret.enabled = is_zero_elevation(c);
if(ret.enabled) { if(ret.enabled) {
ret.everywhere = c.pad_around_object_everywhere.getBool(); ret.everywhere = c.pad_around_object_everywhere.getBool();
ret.object_gap_mm = c.pad_object_gap.getFloat(); ret.object_gap_mm = c.pad_object_gap.getFloat();
@ -86,24 +86,24 @@ sla::PadConfig::EmbedObject builtin_pad_cfg(const SLAPrintObjectConfig& c)
ret.stick_penetration_mm = c.pad_object_connector_penetration ret.stick_penetration_mm = c.pad_object_connector_penetration
.getFloat(); .getFloat();
} }
return ret; return ret;
} }
sla::PadConfig make_pad_cfg(const SLAPrintObjectConfig& c) sla::PadConfig make_pad_cfg(const SLAPrintObjectConfig& c)
{ {
sla::PadConfig pcfg; sla::PadConfig pcfg;
pcfg.wall_thickness_mm = c.pad_wall_thickness.getFloat(); pcfg.wall_thickness_mm = c.pad_wall_thickness.getFloat();
pcfg.wall_slope = c.pad_wall_slope.getFloat() * PI / 180.0; pcfg.wall_slope = c.pad_wall_slope.getFloat() * PI / 180.0;
pcfg.max_merge_dist_mm = c.pad_max_merge_distance.getFloat(); pcfg.max_merge_dist_mm = c.pad_max_merge_distance.getFloat();
pcfg.wall_height_mm = c.pad_wall_height.getFloat(); pcfg.wall_height_mm = c.pad_wall_height.getFloat();
pcfg.brim_size_mm = c.pad_brim_size.getFloat(); pcfg.brim_size_mm = c.pad_brim_size.getFloat();
// set builtin pad implicitly ON // set builtin pad implicitly ON
pcfg.embed_object = builtin_pad_cfg(c); pcfg.embed_object = builtin_pad_cfg(c);
return pcfg; return pcfg;
} }
@ -174,8 +174,8 @@ static std::vector<SLAPrintObject::Instance> sla_instances(const ModelObject &mo
return instances; return instances;
} }
std::vector<ObjectID> SLAPrint::print_object_ids() const std::vector<ObjectID> SLAPrint::print_object_ids() const
{ {
std::vector<ObjectID> out; std::vector<ObjectID> out;
// Reserve one more for the caller to append the ID of the Print itself. // Reserve one more for the caller to append the ID of the Print itself.
out.reserve(m_objects.size() + 1); out.reserve(m_objects.size() + 1);
@ -238,7 +238,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
m_material_config.apply_only(config, material_diff, true); m_material_config.apply_only(config, material_diff, true);
// Handle changes to object config defaults // Handle changes to object config defaults
m_default_object_config.apply_only(config, object_diff, true); m_default_object_config.apply_only(config, object_diff, true);
if (m_printer) m_printer->apply(m_printer_config); if (m_printer) m_printer->apply(m_printer_config);
struct ModelObjectStatus { struct ModelObjectStatus {
@ -429,7 +429,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
model_object.sla_support_points = model_object_new.sla_support_points; model_object.sla_support_points = model_object_new.sla_support_points;
} }
model_object.sla_points_status = model_object_new.sla_points_status; model_object.sla_points_status = model_object_new.sla_points_status;
// Invalidate hollowing if drain holes have changed // Invalidate hollowing if drain holes have changed
if (model_object.sla_drain_holes != model_object_new.sla_drain_holes) if (model_object.sla_drain_holes != model_object_new.sla_drain_holes)
{ {
@ -629,15 +629,15 @@ StringObjectException SLAPrint::validate(StringObjectException *exception, Polyg
sla::SupportTreeConfig cfg = make_support_cfg(po->config()); sla::SupportTreeConfig cfg = make_support_cfg(po->config());
double elv = cfg.object_elevation_mm; double elv = cfg.object_elevation_mm;
sla::PadConfig padcfg = make_pad_cfg(po->config()); sla::PadConfig padcfg = make_pad_cfg(po->config());
sla::PadConfig::EmbedObject &builtinpad = padcfg.embed_object; sla::PadConfig::EmbedObject &builtinpad = padcfg.embed_object;
if(supports_en && !builtinpad.enabled && elv < cfg.head_fullwidth()) if(supports_en && !builtinpad.enabled && elv < cfg.head_fullwidth())
return {L( return {L(
"Elevation is too low for object. Use the \"Pad around " "Elevation is too low for object. Use the \"Pad around "
"object\" feature to print the object without elevation."), po}; "object\" feature to print the object without elevation."), po};
if(supports_en && builtinpad.enabled && if(supports_en && builtinpad.enabled &&
cfg.pillar_base_safety_distance_mm < builtinpad.object_gap_mm) { cfg.pillar_base_safety_distance_mm < builtinpad.object_gap_mm) {
return {L( return {L(
@ -646,7 +646,7 @@ StringObjectException SLAPrint::validate(StringObjectException *exception, Polyg
"distance' has to be greater than the 'Pad object gap' " "distance' has to be greater than the 'Pad object gap' "
"parameter to avoid this."), po}; "parameter to avoid this."), po};
} }
std::string pval = padcfg.validate(); std::string pval = padcfg.validate();
if (!pval.empty()) return {pval, po}; if (!pval.empty()) return {pval, po};
} }
@ -686,7 +686,7 @@ bool SLAPrint::invalidate_step(SLAPrintStep step)
return invalidated; return invalidated;
} }
void SLAPrint::process() void SLAPrint::process(bool use_cache)
{ {
if (m_objects.empty()) if (m_objects.empty())
return; return;
@ -695,7 +695,7 @@ void SLAPrint::process()
// Assumption: at this point the print objects should be populated only with // Assumption: at this point the print objects should be populated only with
// the model objects we have to process and the instances are also filtered // the model objects we have to process and the instances are also filtered
Steps printsteps(this); Steps printsteps(this);
// We want to first process all objects... // We want to first process all objects...
@ -709,7 +709,7 @@ void SLAPrint::process()
}; };
SLAPrintStep print_steps[] = { slapsMergeSlicesAndEval, slapsRasterize }; SLAPrintStep print_steps[] = { slapsMergeSlicesAndEval, slapsRasterize };
double st = Steps::min_objstatus; double st = Steps::min_objstatus;
BOOST_LOG_TRIVIAL(info) << "Start slicing process."; BOOST_LOG_TRIVIAL(info) << "Start slicing process.";
@ -749,7 +749,7 @@ void SLAPrint::process()
throw_if_canceled(); throw_if_canceled();
po->set_done(step); po->set_done(step);
} }
incr = printsteps.progressrange(step); incr = printsteps.progressrange(step);
} }
} }
@ -760,7 +760,7 @@ void SLAPrint::process()
// this would disable the rasterization step // this would disable the rasterization step
// std::fill(m_stepmask.begin(), m_stepmask.end(), false); // std::fill(m_stepmask.begin(), m_stepmask.end(), false);
st = Steps::max_objstatus; st = Steps::max_objstatus;
for(SLAPrintStep currentstep : print_steps) { for(SLAPrintStep currentstep : print_steps) {
throw_if_canceled(); throw_if_canceled();
@ -774,7 +774,7 @@ void SLAPrint::process()
throw_if_canceled(); throw_if_canceled();
set_done(currentstep); set_done(currentstep);
} }
st += printsteps.progressrange(currentstep); st += printsteps.progressrange(currentstep);
} }
@ -1132,7 +1132,7 @@ const TriangleMesh& SLAPrintObject::support_mesh() const
{ {
if(m_config.supports_enable.getBool() && m_supportdata) if(m_config.supports_enable.getBool() && m_supportdata)
return m_supportdata->tree_mesh; return m_supportdata->tree_mesh;
return EMPTY_MESH; return EMPTY_MESH;
} }
@ -1149,7 +1149,7 @@ const indexed_triangle_set &SLAPrintObject::hollowed_interior_mesh() const
if (m_hollowing_data && m_hollowing_data->interior && if (m_hollowing_data && m_hollowing_data->interior &&
m_config.hollowing_enable.getBool()) m_config.hollowing_enable.getBool())
return sla::get_mesh(*m_hollowing_data->interior); return sla::get_mesh(*m_hollowing_data->interior);
return EMPTY_TRIANGLE_SET; return EMPTY_TRIANGLE_SET;
} }
@ -1174,7 +1174,7 @@ sla::SupportPoints SLAPrintObject::transformed_support_points() const
for (sla::SupportPoint& suppt : spts) { for (sla::SupportPoint& suppt : spts) {
suppt.pos = tr * suppt.pos; suppt.pos = tr * suppt.pos;
} }
return spts; return spts;
} }

View file

@ -77,7 +77,7 @@ public:
// Get a pad mesh centered around origin in XY, and with zero rotation around Z applied. // Get a pad mesh centered around origin in XY, and with zero rotation around Z applied.
// Support mesh is only valid if this->is_step_done(slaposPad) is true. // Support mesh is only valid if this->is_step_done(slaposPad) is true.
const TriangleMesh& pad_mesh() const; const TriangleMesh& pad_mesh() const;
// Ready after this->is_step_done(slaposDrillHoles) is true // Ready after this->is_step_done(slaposDrillHoles) is true
const indexed_triangle_set &hollowed_interior_mesh() const; const indexed_triangle_set &hollowed_interior_mesh() const;
@ -201,7 +201,7 @@ private:
{ {
return level<T>(r1) < level<T>(r2); return level<T>(r1) < level<T>(r2);
}); });
if(it == cont.end()) return it; if(it == cont.end()) return it;
T diff = std::abs(level<T>(*it) - lvl); T diff = std::abs(level<T>(*it) - lvl);
@ -307,18 +307,18 @@ private:
// Caching the transformed (m_trafo) raw mesh of the object // Caching the transformed (m_trafo) raw mesh of the object
mutable CachedObject<TriangleMesh> m_transformed_rmesh; mutable CachedObject<TriangleMesh> m_transformed_rmesh;
class SupportData : public sla::SupportableMesh class SupportData : public sla::SupportableMesh
{ {
public: public:
sla::SupportTree::UPtr support_tree_ptr; // the supports sla::SupportTree::UPtr support_tree_ptr; // the supports
std::vector<ExPolygons> support_slices; // sliced supports std::vector<ExPolygons> support_slices; // sliced supports
TriangleMesh tree_mesh, pad_mesh, full_mesh; TriangleMesh tree_mesh, pad_mesh, full_mesh;
inline SupportData(const TriangleMesh &t) inline SupportData(const TriangleMesh &t)
: sla::SupportableMesh{t.its, {}, {}} : sla::SupportableMesh{t.its, {}, {}}
{} {}
sla::SupportTree::UPtr &create_support_tree(const sla::JobController &ctl) sla::SupportTree::UPtr &create_support_tree(const sla::JobController &ctl)
{ {
support_tree_ptr = sla::SupportTree::create(*this, ctl); support_tree_ptr = sla::SupportTree::create(*this, ctl);
@ -335,9 +335,9 @@ private:
pad_mesh = TriangleMesh{support_tree_ptr->retrieve_mesh(sla::MeshType::Pad)}; pad_mesh = TriangleMesh{support_tree_ptr->retrieve_mesh(sla::MeshType::Pad)};
} }
}; };
std::unique_ptr<SupportData> m_supportdata; std::unique_ptr<SupportData> m_supportdata;
class HollowingData class HollowingData
{ {
public: public:
@ -346,7 +346,7 @@ private:
mutable TriangleMesh hollow_mesh_with_holes; // caching the complete hollowed mesh mutable TriangleMesh hollow_mesh_with_holes; // caching the complete hollowed mesh
mutable TriangleMesh hollow_mesh_with_holes_trimmed; mutable TriangleMesh hollow_mesh_with_holes_trimmed;
}; };
std::unique_ptr<HollowingData> m_hollowing_data; std::unique_ptr<HollowingData> m_hollowing_data;
}; };
@ -390,15 +390,15 @@ struct SLAPrintStatistics
class SLAArchive { class SLAArchive {
protected: protected:
std::vector<sla::EncodedRaster> m_layers; std::vector<sla::EncodedRaster> m_layers;
virtual std::unique_ptr<sla::RasterBase> create_raster() const = 0; virtual std::unique_ptr<sla::RasterBase> create_raster() const = 0;
virtual sla::RasterEncoder get_encoder() const = 0; virtual sla::RasterEncoder get_encoder() const = 0;
public: public:
virtual ~SLAArchive() = default; virtual ~SLAArchive() = default;
virtual void apply(const SLAPrinterConfig &cfg) = 0; virtual void apply(const SLAPrinterConfig &cfg) = 0;
// Fn have to be thread safe: void(sla::RasterBase& raster, size_t lyrid); // Fn have to be thread safe: void(sla::RasterBase& raster, size_t lyrid);
template<class Fn, class CancelFn, class EP = ExecutionTBB> template<class Fn, class CancelFn, class EP = ExecutionTBB>
void draw_layers( void draw_layers(
@ -434,9 +434,9 @@ class SLAPrint : public PrintBaseWithState<SLAPrintStep, slapsCount>
{ {
private: // Prevents erroneous use by other classes. private: // Prevents erroneous use by other classes.
typedef PrintBaseWithState<SLAPrintStep, slapsCount> Inherited; typedef PrintBaseWithState<SLAPrintStep, slapsCount> Inherited;
class Steps; // See SLAPrintSteps.cpp class Steps; // See SLAPrintSteps.cpp
public: public:
SLAPrint(): m_stepmask(slapsCount, true) {} SLAPrint(): m_stepmask(slapsCount, true) {}
@ -451,7 +451,7 @@ public:
std::vector<ObjectID> print_object_ids() const override; std::vector<ObjectID> print_object_ids() const override;
ApplyStatus apply(const Model &model, DynamicPrintConfig config) override; ApplyStatus apply(const Model &model, DynamicPrintConfig config) override;
void set_task(const TaskParams &params) override; void set_task(const TaskParams &params) override;
void process() override; void process(bool use_cache = false) override;
void finalize() override; void finalize() override;
// Returns true if an object step is done on all objects and there's at least one object. // Returns true if an object step is done on all objects and there's at least one object.
bool is_step_done(SLAPrintObjectStep step) const; bool is_step_done(SLAPrintObjectStep step) const;
@ -501,11 +501,11 @@ public:
{ {
m_transformed_slices = std::forward<Container>(c); m_transformed_slices = std::forward<Container>(c);
} }
friend class SLAPrint::Steps; friend class SLAPrint::Steps;
public: public:
explicit PrintLayer(coord_t lvl) : m_level(lvl) {} explicit PrintLayer(coord_t lvl) : m_level(lvl) {}
// for being sorted in their container (see m_printer_input) // for being sorted in their container (see m_printer_input)
@ -527,11 +527,11 @@ public:
// The aggregated and leveled print records from various objects. // The aggregated and leveled print records from various objects.
// TODO: use this structure for the preview in the future. // TODO: use this structure for the preview in the future.
const std::vector<PrintLayer>& print_layers() const { return m_printer_input; } const std::vector<PrintLayer>& print_layers() const { return m_printer_input; }
void set_printer(SLAArchive *archiver); void set_printer(SLAArchive *archiver);
private: private:
// Implement same logic as in SLAPrintObject // Implement same logic as in SLAPrintObject
bool invalidate_step(SLAPrintStep st); bool invalidate_step(SLAPrintStep st);
@ -548,24 +548,24 @@ private:
// Ready-made data for rasterization. // Ready-made data for rasterization.
std::vector<PrintLayer> m_printer_input; std::vector<PrintLayer> m_printer_input;
// The archive object which collects the raster images after slicing // The archive object which collects the raster images after slicing
SLAArchive *m_printer = nullptr; SLAArchive *m_printer = nullptr;
// Estimated print time, material consumed. // Estimated print time, material consumed.
SLAPrintStatistics m_print_statistics; SLAPrintStatistics m_print_statistics;
class StatusReporter class StatusReporter
{ {
double m_st = 0; double m_st = 0;
public: public:
void operator()(SLAPrint & p, void operator()(SLAPrint & p,
double st, double st,
const std::string &msg, const std::string &msg,
unsigned flags = SlicingStatus::DEFAULT, unsigned flags = SlicingStatus::DEFAULT,
const std::string &logmsg = ""); const std::string &logmsg = "");
double status() const { return m_st; } double status() const { return m_st; }
} m_report_status; } m_report_status;

View file

@ -6,7 +6,7 @@
namespace Slic3r { namespace Slic3r {
enum SurfaceType { enum SurfaceType {
// Top horizontal surface, visible from the top. // Top horizontal surface, visible from the top.
stTop, stTop,
// Bottom horizontal surface, visible from the bottom, printed with a normal extrusion flow. // Bottom horizontal surface, visible from the bottom, printed with a normal extrusion flow.
@ -39,10 +39,14 @@ public:
unsigned short thickness_layers; // in layers unsigned short thickness_layers; // in layers
double bridge_angle; // in radians, ccw, 0 = East, only 0+ (negative means undefined) double bridge_angle; // in radians, ccw, 0 = East, only 0+ (negative means undefined)
unsigned short extra_perimeters; unsigned short extra_perimeters;
Surface(SurfaceType _surface_type = stInternal)
: surface_type(_surface_type),
thickness(-1), thickness_layers(1), bridge_angle(-1), extra_perimeters(0)
{};
Surface(const Slic3r::Surface &rhs) Surface(const Slic3r::Surface &rhs)
: surface_type(rhs.surface_type), expolygon(rhs.expolygon), : surface_type(rhs.surface_type), expolygon(rhs.expolygon),
thickness(rhs.thickness), thickness_layers(rhs.thickness_layers), thickness(rhs.thickness), thickness_layers(rhs.thickness_layers),
bridge_angle(rhs.bridge_angle), extra_perimeters(rhs.extra_perimeters) bridge_angle(rhs.bridge_angle), extra_perimeters(rhs.extra_perimeters)
{}; {};
@ -52,12 +56,12 @@ public:
{}; {};
Surface(const Surface &other, const ExPolygon &_expolygon) Surface(const Surface &other, const ExPolygon &_expolygon)
: surface_type(other.surface_type), expolygon(_expolygon), : surface_type(other.surface_type), expolygon(_expolygon),
thickness(other.thickness), thickness_layers(other.thickness_layers), thickness(other.thickness), thickness_layers(other.thickness_layers),
bridge_angle(other.bridge_angle), extra_perimeters(other.extra_perimeters) bridge_angle(other.bridge_angle), extra_perimeters(other.extra_perimeters)
{}; {};
Surface(Surface &&rhs) Surface(Surface &&rhs)
: surface_type(rhs.surface_type), expolygon(std::move(rhs.expolygon)), : surface_type(rhs.surface_type), expolygon(std::move(rhs.expolygon)),
thickness(rhs.thickness), thickness_layers(rhs.thickness_layers), thickness(rhs.thickness), thickness_layers(rhs.thickness_layers),
bridge_angle(rhs.bridge_angle), extra_perimeters(rhs.extra_perimeters) bridge_angle(rhs.bridge_angle), extra_perimeters(rhs.extra_perimeters)
{}; {};
Surface(SurfaceType _surface_type, const ExPolygon &&_expolygon) Surface(SurfaceType _surface_type, const ExPolygon &&_expolygon)
@ -66,7 +70,7 @@ public:
{}; {};
Surface(const Surface &other, const ExPolygon &&_expolygon) Surface(const Surface &other, const ExPolygon &&_expolygon)
: surface_type(other.surface_type), expolygon(std::move(_expolygon)), : surface_type(other.surface_type), expolygon(std::move(_expolygon)),
thickness(other.thickness), thickness_layers(other.thickness_layers), thickness(other.thickness), thickness_layers(other.thickness_layers),
bridge_angle(other.bridge_angle), extra_perimeters(other.extra_perimeters) bridge_angle(other.bridge_angle), extra_perimeters(other.extra_perimeters)
{}; {};
@ -194,8 +198,8 @@ inline size_t number_polygons(const SurfacesPtr &surfaces)
} }
// Append a vector of Surfaces at the end of another vector of polygons. // Append a vector of Surfaces at the end of another vector of polygons.
inline void polygons_append(Polygons &dst, const Surfaces &src) inline void polygons_append(Polygons &dst, const Surfaces &src)
{ {
dst.reserve(dst.size() + number_polygons(src)); dst.reserve(dst.size() + number_polygons(src));
for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++ it) { for (Surfaces::const_iterator it = src.begin(); it != src.end(); ++ it) {
dst.emplace_back(it->expolygon.contour); dst.emplace_back(it->expolygon.contour);
@ -203,8 +207,8 @@ inline void polygons_append(Polygons &dst, const Surfaces &src)
} }
} }
inline void polygons_append(Polygons &dst, Surfaces &&src) inline void polygons_append(Polygons &dst, Surfaces &&src)
{ {
dst.reserve(dst.size() + number_polygons(src)); dst.reserve(dst.size() + number_polygons(src));
for (Surfaces::iterator it = src.begin(); it != src.end(); ++ it) { for (Surfaces::iterator it = src.begin(); it != src.end(); ++ it) {
dst.emplace_back(std::move(it->expolygon.contour)); dst.emplace_back(std::move(it->expolygon.contour));
@ -214,8 +218,8 @@ inline void polygons_append(Polygons &dst, Surfaces &&src)
} }
// Append a vector of Surfaces at the end of another vector of polygons. // Append a vector of Surfaces at the end of another vector of polygons.
inline void polygons_append(Polygons &dst, const SurfacesPtr &src) inline void polygons_append(Polygons &dst, const SurfacesPtr &src)
{ {
dst.reserve(dst.size() + number_polygons(src)); dst.reserve(dst.size() + number_polygons(src));
for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++ it) { for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++ it) {
dst.emplace_back((*it)->expolygon.contour); dst.emplace_back((*it)->expolygon.contour);
@ -223,8 +227,8 @@ inline void polygons_append(Polygons &dst, const SurfacesPtr &src)
} }
} }
inline void polygons_append(Polygons &dst, SurfacesPtr &&src) inline void polygons_append(Polygons &dst, SurfacesPtr &&src)
{ {
dst.reserve(dst.size() + number_polygons(src)); dst.reserve(dst.size() + number_polygons(src));
for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++ it) { for (SurfacesPtr::const_iterator it = src.begin(); it != src.end(); ++ it) {
dst.emplace_back(std::move((*it)->expolygon.contour)); dst.emplace_back(std::move((*it)->expolygon.contour));
@ -234,41 +238,41 @@ inline void polygons_append(Polygons &dst, SurfacesPtr &&src)
} }
// Append a vector of Surfaces at the end of another vector of polygons. // Append a vector of Surfaces at the end of another vector of polygons.
inline void surfaces_append(Surfaces &dst, const ExPolygons &src, SurfaceType surfaceType) inline void surfaces_append(Surfaces &dst, const ExPolygons &src, SurfaceType surfaceType)
{ {
dst.reserve(dst.size() + src.size()); dst.reserve(dst.size() + src.size());
for (const ExPolygon &expoly : src) for (const ExPolygon &expoly : src)
dst.emplace_back(Surface(surfaceType, expoly)); dst.emplace_back(Surface(surfaceType, expoly));
} }
inline void surfaces_append(Surfaces &dst, const ExPolygons &src, const Surface &surfaceTempl) inline void surfaces_append(Surfaces &dst, const ExPolygons &src, const Surface &surfaceTempl)
{ {
dst.reserve(dst.size() + number_polygons(src)); dst.reserve(dst.size() + number_polygons(src));
for (const ExPolygon &expoly : src) for (const ExPolygon &expoly : src)
dst.emplace_back(Surface(surfaceTempl, expoly)); dst.emplace_back(Surface(surfaceTempl, expoly));
} }
inline void surfaces_append(Surfaces &dst, const Surfaces &src) inline void surfaces_append(Surfaces &dst, const Surfaces &src)
{ {
dst.insert(dst.end(), src.begin(), src.end()); dst.insert(dst.end(), src.begin(), src.end());
} }
inline void surfaces_append(Surfaces &dst, ExPolygons &&src, SurfaceType surfaceType) inline void surfaces_append(Surfaces &dst, ExPolygons &&src, SurfaceType surfaceType)
{ {
dst.reserve(dst.size() + src.size()); dst.reserve(dst.size() + src.size());
for (ExPolygon &expoly : src) for (ExPolygon &expoly : src)
dst.emplace_back(Surface(surfaceType, std::move(expoly))); dst.emplace_back(Surface(surfaceType, std::move(expoly)));
src.clear(); src.clear();
} }
inline void surfaces_append(Surfaces &dst, ExPolygons &&src, const Surface &surfaceTempl) inline void surfaces_append(Surfaces &dst, ExPolygons &&src, const Surface &surfaceTempl)
{ {
dst.reserve(dst.size() + number_polygons(src)); dst.reserve(dst.size() + number_polygons(src));
for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++ it) for (ExPolygons::const_iterator it = src.begin(); it != src.end(); ++ it)
dst.emplace_back(Surface(surfaceTempl, std::move(*it))); dst.emplace_back(Surface(surfaceTempl, std::move(*it)));
src.clear(); src.clear();
} }
inline void surfaces_append(Surfaces &dst, Surfaces &&src) inline void surfaces_append(Surfaces &dst, Surfaces &&src)
{ {
if (dst.empty()) { if (dst.empty()) {
dst = std::move(src); dst = std::move(src);
} else { } else {
@ -283,7 +287,7 @@ extern BoundingBox get_extents(const SurfacesPtr &surfaces);
inline bool surfaces_could_merge(const Surface &s1, const Surface &s2) inline bool surfaces_could_merge(const Surface &s1, const Surface &s2)
{ {
return return
s1.surface_type == s2.surface_type && s1.surface_type == s2.surface_type &&
s1.thickness == s2.thickness && s1.thickness == s2.thickness &&
s1.thickness_layers == s2.thickness_layers && s1.thickness_layers == s2.thickness_layers &&

View file

@ -13,6 +13,38 @@
#include "libslic3r.h" #include "libslic3r.h"
//define CLI errors
#define CLI_SUCCESS 0
#define CLI_ENVIRONMENT_ERROR -1
#define CLI_INVALID_PARAMS -2
#define CLI_FILE_NOTFOUND -3
#define CLI_FILELIST_INVALID_ORDER -4
#define CLI_CONFIG_FILE_ERROR -5
#define CLI_DATA_FILE_ERROR -6
#define CLI_INVALID_PRINTER_TECH -7
#define CLI_UNSUPPORTED_OPERATION -8
#define CLI_COPY_OBJECTS_ERROR -9
#define CLI_SCALE_TO_FIT_ERROR -10
#define CLI_EXPORT_STL_ERROR -11
#define CLI_EXPORT_OBJ_ERROR -12
#define CLI_EXPORT_3MF_ERROR -13
#define CLI_OUT_OF_MEMORY -14
#define CLI_NO_SUITABLE_OBJECTS -50
#define CLI_VALIDATE_ERROR -51
#define CLI_OBJECTS_PARTLY_INSIDE -52
#define CLI_EXPORT_CACHE_DIRECTORY_CREATE_FAILED -53
#define CLI_EXPORT_CACHE_WRITE_FAILED -54
#define CLI_IMPORT_CACHE_NOT_FOUND -55
#define CLI_IMPORT_CACHE_DATA_CAN_NOT_USE -56
#define CLI_IMPORT_CACHE_LOAD_FAILED -57
#define CLI_SLICING_ERROR -100
namespace boost { namespace filesystem { class directory_entry; }} namespace boost { namespace filesystem { class directory_entry; }}
namespace Slic3r { namespace Slic3r {
@ -161,11 +193,11 @@ namespace PerlUtils {
std::string string_printf(const char *format, ...); std::string string_printf(const char *format, ...);
// Standard "generated by Slic3r version xxx timestamp xxx" header string, // Standard "generated by Slic3r version xxx timestamp xxx" header string,
// to be placed at the top of Slic3r generated files. // to be placed at the top of Slic3r generated files.
std::string header_slic3r_generated(); std::string header_slic3r_generated();
// Standard "generated by PrusaGCodeViewer version xxx timestamp xxx" header string, // Standard "generated by PrusaGCodeViewer version xxx timestamp xxx" header string,
// to be placed at the top of Slic3r generated files. // to be placed at the top of Slic3r generated files.
std::string header_gcodeviewer_generated(); std::string header_gcodeviewer_generated();
@ -247,38 +279,38 @@ inline INDEX_TYPE next_idx_modulo(INDEX_TYPE idx, const INDEX_TYPE count)
} }
template<typename CONTAINER_TYPE> template<typename CONTAINER_TYPE>
inline typename CONTAINER_TYPE::size_type prev_idx_modulo(typename CONTAINER_TYPE::size_type idx, const CONTAINER_TYPE &container) inline typename CONTAINER_TYPE::size_type prev_idx_modulo(typename CONTAINER_TYPE::size_type idx, const CONTAINER_TYPE &container)
{ {
return prev_idx_modulo(idx, container.size()); return prev_idx_modulo(idx, container.size());
} }
template<typename CONTAINER_TYPE> template<typename CONTAINER_TYPE>
inline typename CONTAINER_TYPE::size_type next_idx_modulo(typename CONTAINER_TYPE::size_type idx, const CONTAINER_TYPE &container) inline typename CONTAINER_TYPE::size_type next_idx_modulo(typename CONTAINER_TYPE::size_type idx, const CONTAINER_TYPE &container)
{ {
return next_idx_modulo(idx, container.size()); return next_idx_modulo(idx, container.size());
} }
template<typename CONTAINER_TYPE> template<typename CONTAINER_TYPE>
inline const typename CONTAINER_TYPE::value_type& prev_value_modulo(typename CONTAINER_TYPE::size_type idx, const CONTAINER_TYPE &container) inline const typename CONTAINER_TYPE::value_type& prev_value_modulo(typename CONTAINER_TYPE::size_type idx, const CONTAINER_TYPE &container)
{ {
return container[prev_idx_modulo(idx, container.size())]; return container[prev_idx_modulo(idx, container.size())];
} }
template<typename CONTAINER_TYPE> template<typename CONTAINER_TYPE>
inline typename CONTAINER_TYPE::value_type& prev_value_modulo(typename CONTAINER_TYPE::size_type idx, CONTAINER_TYPE &container) inline typename CONTAINER_TYPE::value_type& prev_value_modulo(typename CONTAINER_TYPE::size_type idx, CONTAINER_TYPE &container)
{ {
return container[prev_idx_modulo(idx, container.size())]; return container[prev_idx_modulo(idx, container.size())];
} }
template<typename CONTAINER_TYPE> template<typename CONTAINER_TYPE>
inline const typename CONTAINER_TYPE::value_type& next_value_modulo(typename CONTAINER_TYPE::size_type idx, const CONTAINER_TYPE &container) inline const typename CONTAINER_TYPE::value_type& next_value_modulo(typename CONTAINER_TYPE::size_type idx, const CONTAINER_TYPE &container)
{ {
return container[next_idx_modulo(idx, container.size())]; return container[next_idx_modulo(idx, container.size())];
} }
template<typename CONTAINER_TYPE> template<typename CONTAINER_TYPE>
inline typename CONTAINER_TYPE::value_type& next_value_modulo(typename CONTAINER_TYPE::size_type idx, CONTAINER_TYPE &container) inline typename CONTAINER_TYPE::value_type& next_value_modulo(typename CONTAINER_TYPE::size_type idx, CONTAINER_TYPE &container)
{ {
return container[next_idx_modulo(idx, container.size())]; return container[next_idx_modulo(idx, container.size())];
} }
@ -300,7 +332,7 @@ template<typename T> struct IsTriviallyCopyable : public std::is_trivially_copya
struct FilePtr { struct FilePtr {
FilePtr(FILE *f) : f(f) {} FilePtr(FILE *f) : f(f) {}
~FilePtr() { this->close(); } ~FilePtr() { this->close(); }
void close() { void close() {
if (this->f) { if (this->f) {
::fclose(this->f); ::fclose(this->f);
this->f = nullptr; this->f = nullptr;