diff --git a/xs/MANIFEST b/xs/MANIFEST index 8dba51151..4d2015871 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -147,6 +147,8 @@ src/libslic3r/PrintGCode.cpp src/libslic3r/PrintGCode.hpp src/libslic3r/PrintObject.cpp src/libslic3r/PrintRegion.cpp +src/libslic3r/SimplePrint.cpp +src/libslic3r/SimplePrint.hpp src/libslic3r/SLAPrint.cpp src/libslic3r/SLAPrint.hpp src/libslic3r/SlicingAdaptive.cpp diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index d3cb341df..06a760f66 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -1,4 +1,3 @@ -#ifndef SLIC3RXS #include "Config.hpp" #include "Log.hpp" @@ -22,7 +21,7 @@ Config::new_from_defaults(std::initializer_list init) std::shared_ptr Config::new_from_defaults(t_config_option_keys init) { - auto my_config(std::make_shared()); + std::shared_ptr my_config(std::make_shared()); for (auto& opt_key : init) { if (print_config_def.has(opt_key)) { const std::string value { print_config_def.get(opt_key).default_value->serialize() }; @@ -33,30 +32,25 @@ Config::new_from_defaults(t_config_option_keys init) return my_config; } -std::shared_ptr -new_from_cli(const int& argc, const char* argv[]) -{ - return std::make_shared(); -} - std::shared_ptr Config::new_from_ini(const std::string& inifile) { - auto my_config(std::make_shared()); + std::shared_ptr my_config(std::make_shared()); my_config->read_ini(inifile); return my_config; } +// TODO: this should be merged into ConfigBase::validate() bool Config::validate() { // general validation for (auto k : this->_config.keys()) { if (print_config_def.options.count(k) == 0) continue; // skip over keys that aren't in the master list - const auto& opt {print_config_def.options.at(k)}; + const ConfigOptionDef& opt { print_config_def.options.at(k) }; if (opt.cli == "" || std::regex_search(opt.cli, _match_info, _cli_pattern) == false) continue; - auto type {_match_info.str(1)}; + std::string type { _match_info.str(1) }; std::vector values; if (std::regex_search(type, _match_info, std::regex("@$"))) { type = std::regex_replace(type, std::regex("@$"), std::string("")); // strip off the @ for later; @@ -66,7 +60,7 @@ Config::validate() } catch (std::bad_cast& e) { throw InvalidOptionType((std::string("(cast failure) Invalid value for ") + std::string(k)).c_str()); } - auto tmp_str {tmp_opt->vserialize()}; + const std::vector tmp_str { tmp_opt->vserialize() }; values.insert(values.end(), tmp_str.begin(), tmp_str.end()); } else { Slic3r::Log::debug("Config::validate", std::string("Not an array")); @@ -91,28 +85,28 @@ void Config::set(const t_config_option_key& opt_key, const std::string& value) { try { - const auto& def {print_config_def.options.at(opt_key)}; + const auto& def = print_config_def.options.at(opt_key); switch (def.type) { case coInt: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionInt* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->value = std::stoi(value); } break; case coInts: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionInts* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(value, true) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } } break; case coFloat: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloat* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(std::stod(value)); } break; case coFloatOrPercent: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloatOrPercent* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; const size_t perc = value.find("%"); ptr->percent = (perc != std::string::npos); if (ptr->percent) { @@ -125,21 +119,21 @@ Config::set(const t_config_option_key& opt_key, const std::string& value) } break; case coFloats: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloats* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(value, true) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } } break; case coString: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionString* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(value) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } } break; case coBool: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionBool* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(value); } break; default: @@ -156,42 +150,42 @@ void Config::set(const t_config_option_key& opt_key, const bool value) { try { - const auto& def {print_config_def.options.at(opt_key)}; + const auto& def = print_config_def.options.at(opt_key); switch (def.type) { case coBool: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionBool* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->value = value; } break; case coInt: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionInt* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setInt(value); } break; case coInts: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionInts* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(std::to_string(value), true); } break; case coFloat: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloat* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(value); } break; case coFloatOrPercent: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloatOrPercent* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(value); ptr->percent = false; } break; case coFloats: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloats* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(std::to_string(value), true); } break; case coString: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionString* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(std::to_string(value)) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } @@ -209,42 +203,42 @@ void Config::set(const t_config_option_key& opt_key, const int value) { try { - const auto& def {print_config_def.options.at(opt_key)}; + const auto& def = print_config_def.options.at(opt_key); switch (def.type) { case coBool: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionBool* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->value = (value != 0); } break; case coInt: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionInt* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setInt(value); } break; case coInts: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionInts* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(std::to_string(value), true); } break; case coFloat: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloat* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(value); } break; case coFloatOrPercent: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloatOrPercent* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(value); ptr->percent = false; } break; case coFloats: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloats* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(std::to_string(value), true); } break; case coString: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionString* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(std::to_string(value)) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } @@ -262,37 +256,37 @@ void Config::set(const t_config_option_key& opt_key, const double value) { try { - const auto& def {print_config_def.options.at(opt_key)}; + const auto& def = print_config_def.options.at(opt_key); switch (def.type) { case coInt: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionInt* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setInt(std::round(value)); } break; case coInts: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionInts* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(std::to_string(std::round(value)), true); } break; case coFloat: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloat* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(value); } break; case coFloatOrPercent: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloatOrPercent* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->setFloat(value); ptr->percent = false; } break; case coFloats: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionFloats* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; ptr->deserialize(std::to_string(value), true); } break; case coString: { - auto* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; + ConfigOptionString* ptr {dynamic_cast(this->_config.optptr(opt_key, true))}; if (!ptr->deserialize(std::to_string(value)) ) { throw InvalidOptionValue(std::string(opt_key) + std::string(" set with invalid value.")); } @@ -355,7 +349,3 @@ is_valid_float(const std::string& type, const ConfigOptionDef& opt, const std::s Config::Config() : _config(DynamicPrintConfig()) {}; } // namespace Slic3r - - - -#endif // SLIC3RXS diff --git a/xs/src/libslic3r/Config.hpp b/xs/src/libslic3r/Config.hpp index 703de8b49..5a01c3771 100644 --- a/xs/src/libslic3r/Config.hpp +++ b/xs/src/libslic3r/Config.hpp @@ -1,5 +1,3 @@ -#ifndef SLIC3RXS - #ifndef CONFIG_HPP #define CONFIG_HPP @@ -47,9 +45,6 @@ public: /// Factory method to construct a Config with specific default values loaded. static std::shared_ptr new_from_defaults(t_config_option_keys init); - /// Factory method to construct a Config from CLI options. - static std::shared_ptr new_from_cli(const int& argc, const char* argv[]); - /// Factory method to construct a Config from an ini file. static std::shared_ptr new_from_ini(const std::string& inifile); @@ -156,5 +151,3 @@ bool is_valid_float(const std::string& type, const ConfigOptionDef& opt, const s } // namespace Slic3r #endif // CONFIG_HPP - -#endif // SLIC3RXS diff --git a/xs/src/libslic3r/ConfigBase.cpp b/xs/src/libslic3r/ConfigBase.cpp index d28ebc243..091cd5361 100644 --- a/xs/src/libslic3r/ConfigBase.cpp +++ b/xs/src/libslic3r/ConfigBase.cpp @@ -378,7 +378,7 @@ ConfigBase::apply_only(const ConfigBase &other, const t_config_option_keys &opt_ continue; } if (default_nonexistent && !other.has(opt_key)) { - auto* def_opt = this->def->get(opt_key)->default_value->clone(); + auto* def_opt = this->def->get(opt_key).default_value->clone(); // not the most efficient way, but easier than casting pointers to subclasses bool res = my_opt->deserialize( def_opt->serialize() ); if (!res) { @@ -434,11 +434,11 @@ ConfigBase::set_deserialize(t_config_option_key opt_key, std::string str, bool a } } } - if (!this->def->has(opt_key)) { + if (!this->def->has(opt_key)) throw UnknownOptionException(opt_key); const ConfigOptionDef& optdef = this->def->options.at(opt_key); - if (!optdef.shortcut.empty()) + if (!optdef.shortcut.empty()) { for (const t_config_option_key& shortcut : optdef.shortcut) if (!this->set_deserialize(shortcut, str)) return false; diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 64dadeb2b..728b5dacb 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -103,8 +103,6 @@ Print::delete_object(size_t idx) // TODO: purge unused regions } -#ifndef SLIC3RXS - void Print::process() { @@ -176,11 +174,11 @@ Print::make_skirt() // $skirt_height_z in this case is the highest possible skirt height for safety. double skirt_height_z {-1.0}; for (const auto& object : this->objects) { - size_t skirt_height { + const size_t skirt_height { this->has_infinite_skirt() ? object->layer_count() : std::min(size_t(this->config.skirt_height()), object->layer_count()) }; - auto* highest_layer {object->get_layer(skirt_height - 1)}; + const Layer* highest_layer { object->get_layer(skirt_height - 1) }; skirt_height_z = std::max(skirt_height_z, highest_layer->print_z); } @@ -303,8 +301,6 @@ Print::make_skirt() this->state.set_done(psSkirt); } -#endif // SLIC3RXS - void Print::reload_object(size_t idx) { @@ -714,8 +710,6 @@ Print::add_model_object(ModelObject* model_object, int idx) } } -#ifndef SLIC3RXS - void Print::export_gcode(std::ostream& output, bool quiet) { @@ -724,9 +718,8 @@ Print::export_gcode(std::ostream& output, bool quiet) if (this->status_cb != nullptr) this->status_cb(90, "Exporting G-Code..."); - - auto export_handler {Slic3r::PrintGCode(*this, output)}; - export_handler.output(); + + Slic3r::PrintGCode(*this, output).output(); } void @@ -777,13 +770,12 @@ Print::export_gcode(std::string outfile, bool quiet) } } - +#ifndef SLIC3RXS bool Print::apply_config(config_ptr config) { // dereference the stored pointer and pass the resulting data to apply_config() return this->apply_config(config->config()); } - #endif bool @@ -934,12 +926,19 @@ Print::validate() const object->model_object()->instances.front()->transform_polygon(&convex_hull); // grow convex hull with the clearance margin - convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, 1, jtRound, scale_(0.1)).front(); + convex_hull = offset( + convex_hull, + // safety_offset in intersection() is not enough for preventing false positives + scale_(this->config.extruder_clearance_radius.value)/2 - scale_(0.01), + CLIPPER_OFFSET_SCALE, + jtRound, scale_(0.1) + ).front(); // now we check that no instance of convex_hull intersects any of the previously checked object instances for (Points::const_iterator copy = object->_shifted_copies.begin(); copy != object->_shifted_copies.end(); ++copy) { Polygon p = convex_hull; p.translate(*copy); + if (!intersection(a, p).empty()) throw InvalidPrintException{"Some objects are too close; your extruder will collide with them."}; diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index 98ce0816e..e8f65dd61 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -113,7 +113,7 @@ class PrintObject // TODO: Fill* fill_maker => (is => 'lazy'); PrintState state; - Print* print(); + Print* print() { return this->_print; }; ModelObject* model_object() { return this->_model_object; }; const ModelObject& model_object() const { return *(this->_model_object); }; @@ -167,8 +167,6 @@ class PrintObject void _make_perimeters(); void _infill(); -#ifndef SLIC3RXS - /// Initialize and generate support material. void generate_support_material(); @@ -200,7 +198,7 @@ class PrintObject /// Idempotence of this method is guaranteed by the fact that we don't remove things from /// fill_surfaces but we only turn them into VOID surfaces, thus preserving the boundaries. void clip_fill_surfaces(); -#endif // SLIC3RXS + private: Print* _print; ModelObject* _model_object; @@ -211,12 +209,10 @@ class PrintObject PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox); ~PrintObject(); -#ifndef SLIC3RXS /// Outer loop of logic for horizontal shell discovery void _discover_external_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id); /// Inner loop of logic for horizontal shell discovery - void _discover_neighbor_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id, const SurfaceType& type, Polygons& solid, const size_t& solid_layers); -#endif // SLIC3RXS + void _discover_neighbor_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id, const SurfaceType& type, Polygons& solid, const size_t& solid_layers); }; @@ -233,13 +229,13 @@ class Print PrintObjectPtrs objects; PrintRegionPtrs regions; PlaceholderParser placeholder_parser; - #ifndef SLIC3RXS + std::function status_cb {nullptr}; /// Function pointer for the UI side to call post-processing scripts. /// Vector is assumed to be the executable script and all arguments. std::function)> post_process_cb {nullptr}; - #endif + double total_used_filament, total_extruded_volume, total_cost, total_weight; std::map filament_stats; PrintState state; @@ -263,7 +259,6 @@ class Print const PrintRegion* get_region(size_t idx) const { return this->regions.at(idx); }; PrintRegion* add_region(); - #ifndef SLIC3RXS /// Triggers the rest of the print process void process(); @@ -275,8 +270,6 @@ class Print /// commands a gcode export to a temporary file and return its name std::string export_gcode(bool quiet = false); - - #endif // SLIC3RXS // methods for handling state bool invalidate_state_by_config(const PrintConfigBase &config); @@ -301,14 +294,12 @@ class Print Flow skirt_flow() const; void _make_brim(); - #ifndef SLIC3RXS /// Generates a skirt around the union of all of /// the objects in the print. void make_skirt(); /// Generates a brim around all of the objects in the print. void make_brim(); - #endif // SLIC3RXS std::set object_extruders() const; diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 9796f35b1..b72547ddd 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -2029,7 +2029,7 @@ CLITransformConfigDef::CLITransformConfigDef() def = this->add("repair", coBool); def->label = __TRANS("Repair"); - def->tooltip = __TRANS("Try to repair any non-manifold meshes (this option is implicitly added whenever we need to slice the model to perform the requested action."); + def->tooltip = __TRANS("Try to repair any non-manifold meshes (this option is implicitly added whenever we need to slice the model to perform the requested action)."); def->cli = "repair"; def = this->add("rotate", coFloat); diff --git a/xs/src/libslic3r/PrintGCode.cpp b/xs/src/libslic3r/PrintGCode.cpp index 724679d0e..79a5f7636 100644 --- a/xs/src/libslic3r/PrintGCode.cpp +++ b/xs/src/libslic3r/PrintGCode.cpp @@ -1,4 +1,3 @@ -#ifndef SLIC3RXS #include "PrintGCode.hpp" #include "PrintConfig.hpp" @@ -9,12 +8,6 @@ namespace Slic3r { void PrintGCode::output() { - auto& gcodegen {this->_gcodegen}; - auto& fh {this->fh}; - auto& print {this->_print}; - const auto& config {this->config}; - const auto extruders {print.extruders()}; - // Write information about the generator. time_t rawtime; tm * timeinfo; time(&rawtime); @@ -25,16 +18,16 @@ PrintGCode::output() fh << "; Git Commit: " << BUILD_COMMIT << "\n\n"; // Writes notes (content of all Settings tabs -> Notes) - fh << gcodegen.notes(); + fh << _gcodegen.notes(); // Write some terse information on the slicing parameters. - auto& first_object {*(this->objects.at(0))}; - auto layer_height {first_object.config.layer_height.getFloat()}; + PrintObject& first_object { *this->objects.at(0) }; + const auto layer_height = first_object.config.layer_height.getFloat(); - for (auto* region : print.regions) { + for (auto* region : _print.regions) { { - auto flow {region->flow(frExternalPerimeter, layer_height, false, false, -1, first_object)}; - auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("external_perimeter_speed")}; + const Flow flow { region->flow(frExternalPerimeter, layer_height, false, false, -1, first_object) }; + auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("external_perimeter_speed"); if (config.max_volumetric_speed.getInt() > 0) vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat()); fh << "; external perimeters extrusion width = "; @@ -42,8 +35,8 @@ PrintGCode::output() fh << "(" << vol_speed << "mm^3/s)\n"; } { - auto flow {region->flow(frPerimeter, layer_height, false, false, -1, first_object)}; - auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("perimeter_speed")}; + const Flow flow { region->flow(frPerimeter, layer_height, false, false, -1, first_object) }; + auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("perimeter_speed"); if (config.max_volumetric_speed.getInt() > 0) vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat()); fh << "; perimeters extrusion width = "; @@ -51,8 +44,8 @@ PrintGCode::output() fh << "(" << vol_speed << "mm^3/s)\n"; } { - auto flow {region->flow(frInfill, layer_height, false, false, -1, first_object)}; - auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("infill_speed")}; + const Flow flow { region->flow(frInfill, layer_height, false, false, -1, first_object) }; + auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("infill_speed"); if (config.max_volumetric_speed.getInt() > 0) vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat()); fh << "; infill extrusion width = "; @@ -60,8 +53,8 @@ PrintGCode::output() fh << "(" << vol_speed << "mm^3/s)\n"; } { - auto flow {region->flow(frSolidInfill, layer_height, false, false, -1, first_object)}; - auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("solid_infill_speed")}; + const Flow flow { region->flow(frSolidInfill, layer_height, false, false, -1, first_object) }; + auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("solid_infill_speed"); if (config.max_volumetric_speed.getInt() > 0) vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat()); fh << "; solid infill extrusion width = "; @@ -69,26 +62,26 @@ PrintGCode::output() fh << "(" << vol_speed << "mm^3/s)\n"; } { - auto flow {region->flow(frTopSolidInfill, layer_height, false, false, -1, first_object)}; - auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("top_solid_infill_speed")}; + const Flow flow { region->flow(frTopSolidInfill, layer_height, false, false, -1, first_object) }; + auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("top_solid_infill_speed"); if (config.max_volumetric_speed.getInt() > 0) vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat()); fh << "; top solid infill extrusion width = "; fh << std::fixed << std::setprecision(2) << flow.width << "mm "; fh << "(" << vol_speed << "mm^3/s)\n"; } - if (print.has_support_material()) { - auto flow {first_object._support_material_flow()}; - auto vol_speed {flow.mm3_per_mm() * first_object.config.get_abs_value("support_material_speed")}; + if (_print.has_support_material()) { + const Flow flow { first_object._support_material_flow() }; + auto vol_speed = flow.mm3_per_mm() * first_object.config.get_abs_value("support_material_speed"); if (config.max_volumetric_speed.getInt() > 0) vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat()); fh << "; support material extrusion width = "; fh << std::fixed << std::setprecision(2) << flow.width << "mm "; fh << "(" << vol_speed << "mm^3/s)\n"; } - if (print.config.first_layer_extrusion_width.getFloat() > 0) { - auto flow {region->flow(frPerimeter, layer_height, false, false, -1, first_object)}; -// auto vol_speed {flow.mm3_per_mm() * print.config.get_abs_value("first_layer_speed")}; + if (_print.config.first_layer_extrusion_width.getFloat() > 0) { + const Flow flow { region->flow(frPerimeter, layer_height, false, false, -1, first_object) }; +// auto vol_speed = flow.mm3_per_mm() * _print.config.get_abs_value("first_layer_speed"); // if (config.max_volumetric_speed.getInt() > 0) // vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat()); fh << "; first layer extrusion width = "; @@ -99,29 +92,29 @@ PrintGCode::output() fh << std::endl; } // Prepare the helper object for replacing placeholders in custom G-Code and output filename - print.placeholder_parser.update_timestamp(); + _print.placeholder_parser.update_timestamp(); // GCode sets this automatically when change_layer() is called, but needed for skirt/brim as well - gcodegen.first_layer = true; + _gcodegen.first_layer = true; // disable fan if (config.cooling.getBool() && config.disable_fan_first_layers.getInt() > 0) { - fh << gcodegen.writer.set_fan(0,1) << "\n"; + fh << _gcodegen.writer.set_fan(0,1) << "\n"; } // set bed temperature - auto temp{config.first_layer_bed_temperature.getFloat()}; + const auto temp = config.first_layer_bed_temperature.getFloat(); if (config.has_heatbed && temp > 0 && std::regex_search(config.start_gcode.getString(), bed_temp_regex)) { - fh << gcodegen.writer.set_bed_temperature(temp, 1); + fh << _gcodegen.writer.set_bed_temperature(temp, 1); } // Set extruder(s) temperature before and after start gcode. - auto include_start_extruder_temp {!std::regex_search(config.start_gcode.getString(), ex_temp_regex)}; + auto include_start_extruder_temp = !std::regex_search(config.start_gcode.getString(), ex_temp_regex); for(const auto& start_gcode : config.start_filament_gcode.values) { include_start_extruder_temp = include_start_extruder_temp && !std::regex_search(start_gcode, ex_temp_regex); } - auto include_end_extruder_temp {!std::regex_search(config.end_gcode.getString(), ex_temp_regex)}; + auto include_end_extruder_temp = !std::regex_search(config.end_gcode.getString(), ex_temp_regex); for(const auto& end_gcode : config.end_filament_gcode.values) { include_end_extruder_temp = include_end_extruder_temp && !std::regex_search(end_gcode, ex_temp_regex); } @@ -129,12 +122,12 @@ PrintGCode::output() if (include_start_extruder_temp) this->_print_first_layer_temperature(0); // Apply gcode math to start gcode - fh << apply_math(gcodegen.placeholder_parser->process(config.start_gcode.value)); + fh << apply_math(_gcodegen.placeholder_parser->process(config.start_gcode.value)); { - auto filament_extruder {0U}; + auto filament_extruder = 0U; for(const auto& start_gcode : config.start_filament_gcode.values) { - gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++); - fh << apply_math(gcodegen.placeholder_parser->process(start_gcode)); + _gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++); + fh << apply_math(_gcodegen.placeholder_parser->process(start_gcode)); } } @@ -142,7 +135,7 @@ PrintGCode::output() // Set other general things (preamble) - fh << gcodegen.preamble(); + fh << _gcodegen.preamble(); // initialize motion planner for object-to-object travel moves if (config.avoid_crossing_perimeters.getBool()) { @@ -153,7 +146,7 @@ PrintGCode::output() Polygons polygons {}; // Add polygons that aren't just thin walls. for (auto layer : object->layers) { - const auto& slice {ExPolygons(layer->slices)}; + const ExPolygons& slice { layer->slices }; std::for_each(slice.cbegin(), slice.cend(), [&polygons] (const ExPolygon& a) { polygons.emplace_back(a.contour); }); } @@ -166,39 +159,70 @@ PrintGCode::output() } } - gcodegen.avoid_crossing_perimeters.init_external_mp(union_ex(islands_p)); + _gcodegen.avoid_crossing_perimeters.init_external_mp(union_ex(islands_p)); } + + const auto extruders = _print.extruders(); // Calculate wiping points if needed. if (config.ooze_prevention && extruders.size() > 1) { + /* + TODO: PORT THIS! + my @skirt_points = map @$_, map @$_, @{$self->print->skirt}; + if (@skirt_points) { + my $outer_skirt = convex_hull(\@skirt_points); + my @skirts = (); + foreach my $extruder_id (@extruders) { + my $extruder_offset = $self->config->get_at('extruder_offset', $extruder_id); + push @skirts, my $s = $outer_skirt->clone; + $s->translate(-scale($extruder_offset->x), -scale($extruder_offset->y)); #) + } + my $convex_hull = convex_hull([ map @$_, @skirts ]); + + $gcodegen->ooze_prevention->set_enable(1); + $gcodegen->ooze_prevention->set_standby_points( + [ map @{$_->equally_spaced_points(scale 10)}, @{offset([$convex_hull], scale 3)} ] + ); + + if (0) { + require "Slic3r/SVG.pm"; + Slic3r::SVG::output( + "ooze_prevention.svg", + red_polygons => \@skirts, + polygons => [$outer_skirt], + points => $gcodegen->ooze_prevention->standby_points, + ); + } + } + */ } // Set initial extruder only after custom start gcode - fh << gcodegen.set_extruder(*(extruders.begin())); + fh << _gcodegen.set_extruder( *(extruders.begin()) ); // Do all objects for each layer. if (config.complete_objects) { // print objects from the smallest to the tallest to avoid collisions // when moving onto next object starting point - std::sort(print.objects.begin(), print.objects.end(), [] (const PrintObject* a, const PrintObject* b) { + std::sort(_print.objects.begin(), _print.objects.end(), [] (const PrintObject* a, const PrintObject* b) { return (a->config.sequential_print_priority < a->config.sequential_print_priority) || (a->size.z < b->size.z); }); size_t finished_objects {0}; - for (size_t obj_idx {0}; obj_idx < print.objects.size(); ++obj_idx) { + for (size_t obj_idx {0}; obj_idx < _print.objects.size(); ++obj_idx) { PrintObject& object {*(this->objects.at(obj_idx))}; for (const Point& copy : object._shifted_copies) { if (finished_objects > 0) { - gcodegen.set_origin(Pointf::new_unscale(copy)); - gcodegen.enable_cooling_markers = false; - gcodegen.avoid_crossing_perimeters.use_external_mp_once = true; - fh << gcodegen.retract(); - fh << gcodegen.travel_to(Point(0,0), erNone, "move to origin position for next object"); + _gcodegen.set_origin(Pointf::new_unscale(copy)); + _gcodegen.enable_cooling_markers = false; + _gcodegen.avoid_crossing_perimeters.use_external_mp_once = true; + fh << _gcodegen.retract(); + fh << _gcodegen.travel_to(Point(0,0), erNone, "move to origin position for next object"); - gcodegen.enable_cooling_markers = true; + _gcodegen.enable_cooling_markers = true; // disable motion planner when traveling to first object point - gcodegen.avoid_crossing_perimeters.disable_once = true; + _gcodegen.avoid_crossing_perimeters.disable_once = true; } std::vector layers; layers.reserve(object.layers.size() + object.support_layers.size()); @@ -218,7 +242,7 @@ PrintGCode::output() config.has_heatbed && std::regex_search(config.between_objects_gcode.getString(), bed_temp_regex)) { - fh << gcodegen.writer.set_bed_temperature(config.first_layer_bed_temperature); + fh << _gcodegen.writer.set_bed_temperature(config.first_layer_bed_temperature); } if (std::regex_search(config.between_objects_gcode.getString(), ex_temp_regex)) { _print_first_layer_temperature(false); @@ -242,8 +266,8 @@ PrintGCode::output() std::vector z; z.reserve(100); // preallocate with 100 layers std::map > layers {}; - for (size_t idx = 0U; idx < print.objects.size(); ++idx) { - const auto& object {*(objects.at(idx))}; + for (size_t idx = 0U; idx < _print.objects.size(); ++idx) { + const PrintObject& object { *objects.at(idx) }; // sort layers by Z into buckets for (Layer* layer : object.layers) { if (layers.count(scale_(layer->print_z)) == 0) { // initialize bucket if empty @@ -272,47 +296,47 @@ PrintGCode::output() this->process_layer(idx, layer, layer->object()->_shifted_copies); } } - gcodegen.placeholder_parser->set("layer_z", unscale(print_z)); - gcodegen.placeholder_parser->set("layer_num", gcodegen.layer_index); + _gcodegen.placeholder_parser->set("layer_z", unscale(print_z)); + _gcodegen.placeholder_parser->set("layer_num", _gcodegen.layer_index); } this->flush_filters(); } // Write end commands to file. - fh << gcodegen.retract(); // TODO: process this retract through PressureRegulator in order to discharge fully + fh << _gcodegen.retract(); // TODO: process this retract through PressureRegulator in order to discharge fully { - auto filament_extruder {0U}; + auto filament_extruder = 0U; for(const auto& end_gcode : config.end_filament_gcode.values) { - gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++); - fh << apply_math(gcodegen.placeholder_parser->process(end_gcode)); + _gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++); + fh << apply_math(_gcodegen.placeholder_parser->process(end_gcode)); } } - fh << apply_math(gcodegen.placeholder_parser->process(config.end_gcode)); + fh << apply_math(_gcodegen.placeholder_parser->process(config.end_gcode)); // set bed temperature if (config.has_heatbed && temp > 0 && std::regex_search(config.end_gcode.getString(), bed_temp_regex)) { - fh << gcodegen.writer.set_bed_temperature(0, 0); + fh << _gcodegen.writer.set_bed_temperature(0, 0); } // Get filament stats - print.filament_stats.clear(); - print.total_used_filament = 0.0; - print.total_extruded_volume = 0.0; - print.total_weight = 0.0; - print.total_cost = 0.0; + _print.filament_stats.clear(); + _print.total_used_filament = 0.0; + _print.total_extruded_volume = 0.0; + _print.total_weight = 0.0; + _print.total_cost = 0.0; - for (auto extruder_pair : gcodegen.writer.extruders) { - const auto& extruder {extruder_pair.second}; - auto used_material {extruder.used_filament()}; - auto extruded_volume {extruder.extruded_volume()}; - auto material_weight {extruded_volume * extruder.filament_density() / 1000.0}; - auto material_cost { material_weight * (extruder.filament_cost() / 1000.0)}; + for (auto extruder_pair : _gcodegen.writer.extruders) { + const Extruder& extruder { extruder_pair.second }; + const auto used_material = extruder.used_filament(); + const auto extruded_volume = extruder.extruded_volume(); + const auto material_weight = extruded_volume * extruder.filament_density() / 1000.0; + const auto material_cost = material_weight * (extruder.filament_cost() / 1000.0); - print.filament_stats[extruder.id] = used_material; + _print.filament_stats[extruder.id] = used_material; fh << "; material used = "; fh << std::fixed << std::setprecision(2) << used_material << "mm "; @@ -321,28 +345,28 @@ PrintGCode::output() << used_material << "cm3)\n"; if (material_weight > 0) { - print.total_weight += material_weight; + _print.total_weight += material_weight; fh << "; material used = " << std::fixed << std::setprecision(2) << material_weight << "g\n"; if (material_cost > 0) { - print.total_cost += material_cost; + _print.total_cost += material_cost; fh << "; material cost = " << std::fixed << std::setprecision(2) << material_weight << "g\n"; } } - print.total_used_filament += used_material; - print.total_extruded_volume += extruded_volume; + _print.total_used_filament += used_material; + _print.total_extruded_volume += extruded_volume; } fh << "; total filament cost = " - << std::fixed << std::setprecision(2) << print.total_cost << "\n"; + << std::fixed << std::setprecision(2) << _print.total_cost << "\n"; // Append full config fh << std::endl; // print config - _print_config(print.config); - _print_config(print.default_object_config); - _print_config(print.default_region_config); + _print_config(_print.config); + _print_config(_print.default_object_config); + _print_config(_print.default_region_config); } std::string @@ -355,17 +379,14 @@ void PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) { std::string gcode {""}; - auto& gcodegen {this->_gcodegen}; - const auto& print {this->_print}; - const auto& config {this->config}; - const auto& obj {*(layer->object())}; - gcodegen.config.apply(obj.config, true); + const PrintObject& obj { *layer->object() }; + _gcodegen.config.apply(obj.config, true); // check for usage of spiralvase logic. this->_spiral_vase.enable = ( layer->id() > 0 - && (print.config.skirts == 0 || (layer->id() >= print.config.skirt_height && !print.has_infinite_skirt())) + && (_print.config.skirts == 0 || (layer->id() >= _print.config.skirt_height && !_print.has_infinite_skirt())) && std::find_if(layer->regions.cbegin(), layer->regions.cend(), [layer] (const LayerRegion* l) { return l->region()->config.bottom_solid_layers > layer->id() || l->perimeters.items_count() > 1 @@ -382,9 +403,9 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) { // get the minimum cross-section used in the layer. std::vector mm3_per_mm; - for (auto region_id = 0U; region_id < print.regions.size(); ++region_id) { - const auto& region {print.regions.at(region_id)}; - const auto& layerm {layer->get_region(region_id)}; + for (auto region_id = 0U; region_id < _print.regions.size(); ++region_id) { + const PrintRegion* region = _print.get_region(region_id); + const LayerRegion* layerm = layer->get_region(region_id); if (!(region->config.get_abs_value("perimeter_speed") > 0 && region->config.get_abs_value("small_perimeter_speed") > 0 && @@ -417,53 +438,53 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) // TODO make the definition of "too thin" based on a config somewhere mm3_per_mm.erase(std::remove_if(mm3_per_mm.begin(), mm3_per_mm.end(), [] (const double& vol) { return vol <= 0.01;} ), mm3_per_mm.end()); if (mm3_per_mm.size() > 0) { - const auto min_mm3_per_mm {*(std::min_element(mm3_per_mm.begin(), mm3_per_mm.end()))}; + const double min_mm3_per_mm { *(std::min_element(mm3_per_mm.begin(), mm3_per_mm.end())) }; // In order to honor max_print_speed we need to find a target volumetric - // speed that we can use throughout the print. So we define this target + // speed that we can use throughout the _print. So we define this target // volumetric speed as the volumetric speed produced by printing the // smallest cross-section at the maximum speed: any larger cross-section // will need slower feedrates. - auto volumetric_speed {min_mm3_per_mm * config.max_print_speed}; + double volumetric_speed { min_mm3_per_mm * config.max_print_speed }; if (config.max_volumetric_speed > 0) { volumetric_speed = std::min(volumetric_speed, config.max_volumetric_speed.getFloat()); } - gcodegen.volumetric_speed = volumetric_speed; + _gcodegen.volumetric_speed = volumetric_speed; } } // set the second layer + temp if (!this->_second_layer_things_done && layer->id() == 1) { - for (const auto& extruder_ref : gcodegen.writer.extruders) { - const auto& extruder { extruder_ref.second }; - auto temp { config.temperature.get_at(extruder.id) }; + for (const auto& extruder_ref : _gcodegen.writer.extruders) { + const Extruder& extruder { extruder_ref.second }; + auto temp = config.temperature.get_at(extruder.id); if (temp > 0 && temp != config.first_layer_temperature.get_at(extruder.id) ) - gcode += gcodegen.writer.set_temperature(temp, 0, extruder.id); + gcode += _gcodegen.writer.set_temperature(temp, 0, extruder.id); } - if (config.has_heatbed && print.config.first_layer_bed_temperature > 0 && print.config.bed_temperature != print.config.first_layer_bed_temperature) { - gcode += gcodegen.writer.set_bed_temperature(print.config.bed_temperature); + if (config.has_heatbed && _print.config.first_layer_bed_temperature > 0 && _print.config.bed_temperature != _print.config.first_layer_bed_temperature) { + gcode += _gcodegen.writer.set_bed_temperature(_print.config.bed_temperature); } this->_second_layer_things_done = true; } // set new layer - this will change Z and force a retraction if retract_layer_change is enabled - if (print.config.before_layer_gcode.getString().size() > 0) { - auto pp {*(gcodegen.placeholder_parser)}; - pp.set("layer_num", gcodegen.layer_index); + if (_print.config.before_layer_gcode.getString().size() > 0) { + PlaceholderParser pp { *_gcodegen.placeholder_parser }; + pp.set("layer_num", _gcodegen.layer_index); pp.set("layer_z", layer->print_z); - pp.set("current_retraction", gcodegen.writer.extruder()->retracted); + pp.set("current_retraction", _gcodegen.writer.extruder()->retracted); - gcode += apply_math(pp.process(print.config.before_layer_gcode.getString())); + gcode += apply_math(pp.process(_print.config.before_layer_gcode.getString())); gcode += "\n"; } - gcode += gcodegen.change_layer(*layer); - if (print.config.layer_gcode.getString().size() > 0) { - auto pp {*(gcodegen.placeholder_parser)}; - pp.set("layer_num", gcodegen.layer_index); + gcode += _gcodegen.change_layer(*layer); + if (_print.config.layer_gcode.getString().size() > 0) { + PlaceholderParser pp { *_gcodegen.placeholder_parser }; + pp.set("layer_num", _gcodegen.layer_index); pp.set("layer_z", layer->print_z); - pp.set("current_retraction", gcodegen.writer.extruder()->retracted); + pp.set("current_retraction", _gcodegen.writer.extruder()->retracted); - gcode += apply_math(pp.process(print.config.layer_gcode.getString())); + gcode += apply_math(pp.process(_print.config.layer_gcode.getString())); gcode += "\n"; } @@ -471,73 +492,73 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) // extrude skirt along raft layers and normal obj layers // (not along interlaced support material layers) if (layer->id() < static_cast(obj.config.raft_layers) - || ((print.has_infinite_skirt() || _skirt_done.size() == 0 || (_skirt_done.rbegin())->first < print.config.skirt_height) + || ((_print.has_infinite_skirt() || _skirt_done.size() == 0 || (_skirt_done.rbegin())->first < _print.config.skirt_height) && _skirt_done.count(scale_(layer->print_z)) == 0 && typeid(layer) != typeid(SupportLayer*)) ) { - gcodegen.set_origin(Pointf(0,0)); - gcodegen.avoid_crossing_perimeters.use_external_mp = true; + _gcodegen.set_origin(Pointf(0,0)); + _gcodegen.avoid_crossing_perimeters.use_external_mp = true; /// data load std::vector extruder_ids; - extruder_ids.reserve(gcodegen.writer.extruders.size()); - std::transform(gcodegen.writer.extruders.cbegin(), gcodegen.writer.extruders.cend(), std::back_inserter(extruder_ids), + extruder_ids.reserve(_gcodegen.writer.extruders.size()); + std::transform(_gcodegen.writer.extruders.cbegin(), _gcodegen.writer.extruders.cend(), std::back_inserter(extruder_ids), [] (const std::pair& z) -> std::size_t { return z.second.id; } ); - gcode += gcodegen.set_extruder(extruder_ids.at(0)); + gcode += _gcodegen.set_extruder(extruder_ids.at(0)); // skip skirt if a large brim - if (print.has_infinite_skirt() || layer->id() < static_cast(print.config.skirt_height)) { - const auto& skirt_flow {print.skirt_flow()}; + if (_print.has_infinite_skirt() || layer->id() < static_cast(_print.config.skirt_height)) { + const Flow skirt_flow { _print.skirt_flow() }; // distribute skirt loops across all extruders in layer 0 - auto skirt_loops {print.skirt.flatten().entities}; + const auto skirt_loops = _print.skirt.flatten().entities; for (size_t i = 0; i < skirt_loops.size(); ++i) { // when printing layers > 0 ignore 'min_skirt_length' and // just use the 'skirts' setting; also just use the current extruder - if (layer->id() > 0 && i >= static_cast(print.config.skirts)) break; - const auto extruder_id { extruder_ids.at((i / extruder_ids.size()) % extruder_ids.size()) }; + if (layer->id() > 0 && i >= static_cast(_print.config.skirts)) break; + const size_t extruder_id { extruder_ids.at((i / extruder_ids.size()) % extruder_ids.size()) }; if (layer->id() == 0) - gcode += gcodegen.set_extruder(extruder_id); + gcode += _gcodegen.set_extruder(extruder_id); // adjust flow according to layer height - auto& loop {*(dynamic_cast(skirt_loops.at(i)))}; + auto& loop = *dynamic_cast(skirt_loops.at(i)); { Flow layer_skirt_flow(skirt_flow); layer_skirt_flow.height = layer->height; - auto mm3_per_mm {layer_skirt_flow.mm3_per_mm()}; + const auto mm3_per_mm = layer_skirt_flow.mm3_per_mm(); for (auto& path : loop.paths) { path.height = layer->height; path.mm3_per_mm = mm3_per_mm; } } - gcode += gcodegen.extrude(loop, "skirt", obj.config.support_material_speed); + gcode += _gcodegen.extrude(loop, "skirt", obj.config.support_material_speed); } } this->_skirt_done[scale_(layer->print_z)] = true; - gcodegen.avoid_crossing_perimeters.use_external_mp = false; + _gcodegen.avoid_crossing_perimeters.use_external_mp = false; - if (layer->id() == 0) gcodegen.avoid_crossing_perimeters.disable_once = true; + if (layer->id() == 0) _gcodegen.avoid_crossing_perimeters.disable_once = true; } // extrude brim if (this->_brim_done) { - gcode += gcodegen.set_extruder(print.brim_extruder() - 1); - gcodegen.set_origin(Pointf(0,0)); - gcodegen.avoid_crossing_perimeters.use_external_mp = true; - for (const auto& b : print.brim.entities) { - gcode += gcodegen.extrude(*b, "brim", obj.config.get_abs_value("support_material_speed")); + gcode += _gcodegen.set_extruder(_print.brim_extruder() - 1); + _gcodegen.set_origin(Pointf(0,0)); + _gcodegen.avoid_crossing_perimeters.use_external_mp = true; + for (const auto& b : _print.brim.entities) { + gcode += _gcodegen.extrude(*b, "brim", obj.config.get_abs_value("support_material_speed")); } this->_brim_done = true; - gcodegen.avoid_crossing_perimeters.use_external_mp = false; + _gcodegen.avoid_crossing_perimeters.use_external_mp = false; // allow a straight travel move to the first object point - gcodegen.avoid_crossing_perimeters.disable_once = true; + _gcodegen.avoid_crossing_perimeters.disable_once = true; } auto copy_idx = 0U; @@ -548,10 +569,10 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) // when starting a new object, use the external motion planner for the first travel move if (this->_last_obj_copy.first != copy && this->_last_obj_copy.second ) - gcodegen.avoid_crossing_perimeters.use_external_mp = true; + _gcodegen.avoid_crossing_perimeters.use_external_mp = true; this->_last_obj_copy.first = copy; this->_last_obj_copy.second = true; - gcodegen.set_origin(Pointf::new_unscale(copy)); + _gcodegen.set_origin(Pointf::new_unscale(copy)); // extrude support material before other things because it might use a lower Z // and also because we avoid travelling on other things when printing it @@ -559,17 +580,17 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) const SupportLayer* slayer = dynamic_cast(layer); ExtrusionEntityCollection paths; if (slayer->support_interface_fills.size() > 0) { - gcode += gcodegen.set_extruder(obj.config.support_material_interface_extruder - 1); - slayer->support_interface_fills.chained_path_from(gcodegen.last_pos(), &paths, false); + gcode += _gcodegen.set_extruder(obj.config.support_material_interface_extruder - 1); + slayer->support_interface_fills.chained_path_from(_gcodegen.last_pos(), &paths, false); for (const auto& path : paths) { - gcode += gcodegen.extrude(*path, "support material interface", obj.config.get_abs_value("support_material_interface_speed")); + gcode += _gcodegen.extrude(*path, "support material interface", obj.config.get_abs_value("support_material_interface_speed")); } } if (slayer->support_fills.size() > 0) { - gcode += gcodegen.set_extruder(obj.config.support_material_extruder - 1); - slayer->support_fills.chained_path_from(gcodegen.last_pos(), &paths, false); + gcode += _gcodegen.set_extruder(obj.config.support_material_extruder - 1); + slayer->support_fills.chained_path_from(_gcodegen.last_pos(), &paths, false); for (const auto& path : paths) { - gcode += gcodegen.extrude(*path, "support material", obj.config.get_abs_value("support_material_speed")); + gcode += _gcodegen.extrude(*path, "support material", obj.config.get_abs_value("support_material_speed")); } } } @@ -594,25 +615,25 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) // cache bounding boxes of layer slices std::vector layer_slices_bb; std::transform(layer->slices.cbegin(), layer->slices.cend(), std::back_inserter(layer_slices_bb), [] (const ExPolygon& s)-> BoundingBox { return s.bounding_box(); }); - auto point_inside_surface { [&layer_slices_bb, &layer] (size_t i, Point point) -> bool { - const auto& bbox {layer_slices_bb.at(i)}; + auto point_inside_surface = [&layer_slices_bb, &layer] (size_t i, Point point) -> bool { + const BoundingBox& bbox { layer_slices_bb.at(i) }; return bbox.contains(point) && layer->slices.at(i).contour.contains(point); - }}; - const auto n_slices {layer->slices.size()}; + }; + const size_t n_slices { layer->slices.size() }; - for (auto region_id = 0U; region_id < print.regions.size(); ++region_id) { + for (auto region_id = 0U; region_id < _print.regions.size(); ++region_id) { const LayerRegion* layerm; try { layerm = layer->get_region(region_id); // we promise to be good and not give this to anyone who will modify it } catch (std::out_of_range &e) { continue; // if no regions, bail; } - auto* region {print.get_region(region_id)}; + const PrintRegion* region { _print.get_region(region_id) }; // process perimeters { auto extruder_id = region->config.perimeter_extruder-1; // Casting away const just to avoid double dereferences - for(auto* perimeter_coll : layerm->perimeters.flatten().entities) { + for(const auto* perimeter_coll : layerm->perimeters.flatten().entities) { if(perimeter_coll->length() == 0) continue; // this shouldn't happen but first_point() would fail @@ -654,10 +675,10 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) // tweak extruder ordering to save toolchanges - auto last_extruder = gcodegen.writer.extruder()->id; + auto last_extruder = _gcodegen.writer.extruder()->id; if (by_extruder.count(last_extruder)) { for(auto &island : by_extruder[last_extruder]) { - if (print.config.infill_first()) { + if (_print.config.infill_first()) { gcode += this->_extrude_infill(std::get<1>(island.second)); gcode += this->_extrude_perimeters(std::get<0>(island.second)); } else { @@ -668,9 +689,9 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies) } for(auto &pair : by_extruder) { if(pair.first == last_extruder)continue; - gcode += gcodegen.set_extruder(pair.first); + gcode += _gcodegen.set_extruder(pair.first); for(auto &island : pair.second) { - if (print.config.infill_first()) { + if (_print.config.infill_first()) { gcode += this->_extrude_infill(std::get<1>(island.second)); gcode += this->_extrude_perimeters(std::get<0>(island.second)); } else { @@ -733,16 +754,10 @@ PrintGCode::_extrude_infill(std::map &by_regio void PrintGCode::_print_first_layer_temperature(bool wait) { - auto& gcodegen {this->_gcodegen}; - auto& fh {this->fh}; - const auto& print {this->_print}; - const auto& config {this->config}; - const auto extruders {print.extruders()}; - - for (auto& t : extruders) { - auto temp { config.first_layer_temperature.get_at(t) }; + for (auto& t : _print.extruders()) { + auto temp = config.first_layer_temperature.get_at(t); if (config.ooze_prevention.value) temp += config.standby_temperature_delta.value; - if (temp > 0) fh << gcodegen.writer.set_temperature(temp, wait, t); + if (temp > 0) fh << _gcodegen.writer.set_temperature(temp, wait, t); } } @@ -758,9 +773,9 @@ PrintGCode::_print_config(const ConfigBase& config) PrintGCode::PrintGCode(Slic3r::Print& print, std::ostream& _fh) : _print(print), - config(print.config), + config(_print.config), _gcodegen(Slic3r::GCode()), - objects(print.objects), + objects(_print.objects), fh(_fh), _cooling_buffer(Slic3r::CoolingBuffer(this->_gcodegen)), _spiral_vase(Slic3r::SpiralVase(this->config)) @@ -771,16 +786,16 @@ PrintGCode::PrintGCode(Slic3r::Print& print, std::ostream& _fh) : } else { layer_count = std::accumulate(objects.cbegin(), objects.cend(), layer_count, [](const size_t& ret, const PrintObject* obj){ return ret + obj->total_layer_count(); }); } - _gcodegen.placeholder_parser = &(print.placeholder_parser); // initialize + _gcodegen.placeholder_parser = &(_print.placeholder_parser); // initialize _gcodegen.layer_count = layer_count; _gcodegen.enable_cooling_markers = true; _gcodegen.apply_print_config(config); if (config.spiral_vase) _spiral_vase.enable = true; - auto extruders {print.extruders()}; + const auto extruders = _print.extruders(); _gcodegen.set_extruders(extruders.cbegin(), extruders.cend()); } } // namespace Slic3r -#endif //SLIC3RXS + diff --git a/xs/src/libslic3r/PrintGCode.hpp b/xs/src/libslic3r/PrintGCode.hpp index 0001c8b70..9f0b4006f 100644 --- a/xs/src/libslic3r/PrintGCode.hpp +++ b/xs/src/libslic3r/PrintGCode.hpp @@ -1,4 +1,3 @@ -#ifndef SLIC3RXS #ifndef slic3r_PrintGCode_hpp #define slic3r_PrintGCode_hpp @@ -77,4 +76,3 @@ private: } // namespace Slic3r #endif // slic3r_PrintGCode_hpp -#endif // SLIC3RXS diff --git a/xs/src/libslic3r/PrintObject.cpp b/xs/src/libslic3r/PrintObject.cpp index d8e8fad2d..c0f476f8e 100644 --- a/xs/src/libslic3r/PrintObject.cpp +++ b/xs/src/libslic3r/PrintObject.cpp @@ -38,12 +38,6 @@ PrintObject::~PrintObject() { } -Print* -PrintObject::print() -{ - return this->_print; -} - Points PrintObject::copies() const { @@ -952,7 +946,6 @@ PrintObject::_slice_region(size_t region_id, std::vector z, bool modifier return layers; } -#ifndef SLIC3RXS void PrintObject::make_perimeters() { @@ -966,28 +959,22 @@ PrintObject::make_perimeters() void PrintObject::slice() { - auto* print {this->print()}; if (this->state.is_done(posSlice)) return; this->state.set_started(posSlice); - if (print->status_cb != nullptr) { - print->status_cb(10, "Processing triangulated mesh"); + if (_print->status_cb != nullptr) { + _print->status_cb(10, "Processing triangulated mesh"); } this->_slice(); // detect slicing errors - bool warning_thrown = false; - for (size_t i = 0U; i < this->layer_count(); ++i) { - auto* layer {this->get_layer(i)}; - if (!layer->slicing_errors) continue; - if (!warning_thrown) { - Slic3r::Log::warn("PrintObject") << "The model has overlapping or self-intersecting facets. " - << "I tried to repair it, however you might want to check " - << "the results or repair the input file and retry.\n"; - warning_thrown = true; - } - } + if (std::any_of(this->layers.cbegin(), this->layers.cend(), + [](const Layer* l){ return l->slicing_errors; })) + Slic3r::Log::warn("PrintObject") << "The model has overlapping or self-intersecting facets. " + << "I tried to repair it, however you might want to check " + << "the results or repair the input file and retry.\n"; + if (this->layers.size() == 0) { Slic3r::Log::error("PrintObject") << "slice(): " << "No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n"; return; // make this throw an exception instead? @@ -998,7 +985,6 @@ PrintObject::slice() this->state.set_done(posSlice); } -#endif // SLIC3RXS void PrintObject::_make_perimeters() { @@ -1142,7 +1128,6 @@ PrintObject::_infill() this->state.set_done(posInfill); } -#ifndef SLIC3RXS void PrintObject::prepare_infill() { @@ -1304,8 +1289,6 @@ PrintObject::infill() this->_infill(); } -#endif //SLIC3RXS - SupportMaterial * PrintObject::_support_material() { @@ -1357,12 +1340,10 @@ PrintObject::_support_material_flow(FlowRole role) return support_flow; } -#ifndef SLIC3RXS + void PrintObject::generate_support_material() { - auto* print { this->_print }; - const auto& config { this->config }; //prereqs this->slice(); if (this->state.is_done(posSupportMaterial)) { return; } @@ -1379,8 +1360,8 @@ PrintObject::generate_support_material() this->state.set_done(posSupportMaterial); return; } - if (print->status_cb != nullptr) - print->status_cb(85, "Generating support material"); + if (_print->status_cb != nullptr) + _print->status_cb(85, "Generating support material"); this->_support_material()->generate(this); @@ -1388,8 +1369,8 @@ PrintObject::generate_support_material() std::stringstream stats {""}; - if (print->status_cb != nullptr) - print->status_cb(85, stats.str().c_str()); + if (_print->status_cb != nullptr) + _print->status_cb(85, stats.str().c_str()); } @@ -1397,15 +1378,14 @@ PrintObject::generate_support_material() void PrintObject::discover_horizontal_shells() { - auto* print {this->print()}; - for (size_t region_id = 0U; region_id < print->regions.size(); ++region_id) { + for (size_t region_id = 0U; region_id < _print->regions.size(); ++region_id) { for (size_t i = 0; i < this->layer_count(); ++i) { - auto* layerm {this->get_layer(i)->regions.at(region_id)}; - const auto& region_config {layerm->region()->config}; + auto* layerm = this->get_layer(i)->get_region(region_id); + const auto& region_config = layerm->region()->config; if (region_config.solid_infill_every_layers() > 0 && region_config.fill_density() > 0 && (i % region_config.solid_infill_every_layers()) == 0) { - const auto type {region_config.fill_density() == 100 ? stInternalSolid : stInternalBridge }; + const auto type = region_config.fill_density() == 100 ? stInternalSolid : stInternalBridge; // set the surface type to internal for the types std::for_each(layerm->fill_surfaces.begin(), layerm->fill_surfaces.end(), [type] (Surface& s) { s.surface_type = (s.surface_type == type ? stInternal : s.surface_type); }); } @@ -1417,7 +1397,7 @@ PrintObject::discover_horizontal_shells() void PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id) { - const auto& region_config {layerm->region()->config}; + const auto& region_config = layerm->region()->config; for (auto& type : { stTop, stBottom, stBottomBridge }) { // find slices of current type for current layer // use slices instead of fill_surfaces because they also include the perimeter area @@ -1430,7 +1410,7 @@ PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const siz // too much solid infill inside nearly-vertical slopes. Polygons solid; - auto tmp {layerm->slices.filter_by_type(type)}; + auto tmp = layerm->slices.filter_by_type(type); polygons_append(solid, tmp); tmp.clear(); tmp = layerm->fill_surfaces.filter_by_type(type); @@ -1438,11 +1418,11 @@ PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const siz if (solid.size() == 0) continue; - auto solid_layers { type == stTop ? region_config.top_solid_layers() : region_config.bottom_solid_layers() }; + auto solid_layers = type == stTop ? region_config.top_solid_layers() : region_config.bottom_solid_layers(); if (region_config.min_top_bottom_shell_thickness() > 0) { - auto current_shell_thick { static_cast(solid_layers) * this->get_layer(i)->height }; - const auto& min_shell_thick { region_config.min_top_bottom_shell_thickness() }; + auto current_shell_thick = static_cast(solid_layers) * this->get_layer(i)->height; + const auto min_shell_thick = region_config.min_top_bottom_shell_thickness(); while (std::abs(min_shell_thick - current_shell_thick) > Slic3r::Geometry::epsilon) { solid_layers++; current_shell_thick = static_cast(solid_layers) * this->get_layer(i)->height; @@ -1455,19 +1435,19 @@ PrintObject::_discover_external_horizontal_shells(LayerRegion* layerm, const siz void PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const size_t& i, const size_t& region_id, const SurfaceType& type, Polygons& solid, const size_t& solid_layers) { - const auto& region_config {layerm->region()->config}; + const auto& region_config = layerm->region()->config; for (int n = (type == stTop ? i-1 : i+1); std::abs(n-int(i)) < solid_layers; (type == stTop ? n-- : n++)) { if (n < 0 || static_cast(n) >= this->layer_count()) continue; - auto* neighbor_layerm { this->get_layer(n)->regions.at(region_id) }; + LayerRegion* neighbor_layerm { this->get_layer(n)->get_region(region_id) }; // make a copy so we can use them even after clearing the original collection - auto neighbor_fill_surfaces{ SurfaceCollection(neighbor_layerm->fill_surfaces) }; + SurfaceCollection neighbor_fill_surfaces{ neighbor_layerm->fill_surfaces }; // find intersection between neighbor and current layer's surfaces // intersections have contours and holes Polygons filtered_poly; polygons_append(filtered_poly, neighbor_fill_surfaces.filter_by_type({stInternal, stInternalSolid})); - auto new_internal_solid { intersection(solid, filtered_poly , 1 ) }; + auto new_internal_solid = intersection(solid, filtered_poly , 1 ); if (new_internal_solid.size() == 0) { // No internal solid needed on this layer. In order to decide whether to continue // searching on the next neighbor (thus enforcing the configured number of solid @@ -1490,8 +1470,8 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz // than a perimeter width, since it's probably just crossing a sloping wall // and it's not wanted in a hollow print even if it would make sense when // obeying the solid shell count option strictly (DWIM!) - auto margin { neighbor_layerm->flow(frExternalPerimeter).scaled_width()}; - auto too_narrow { diff(new_internal_solid, offset2(new_internal_solid, -margin, +margin, CLIPPER_OFFSET_SCALE, ClipperLib::jtMiter, 5), 1)}; + const auto margin = neighbor_layerm->flow(frExternalPerimeter).scaled_width(); + const auto too_narrow = diff(new_internal_solid, offset2(new_internal_solid, -margin, +margin, CLIPPER_OFFSET_SCALE, ClipperLib::jtMiter, 5), 1); if (too_narrow.size() > 0) new_internal_solid = solid = diff(new_internal_solid, too_narrow); } @@ -1499,16 +1479,16 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz // make sure the new internal solid is wide enough, as it might get collapsed // when spacing is added in Slic3r::Fill { - auto margin {3 * layerm->flow(frSolidInfill).scaled_width()}; + const auto margin = 3 * layerm->flow(frSolidInfill).scaled_width(); // we use a higher miterLimit here to handle areas with acute angles // in those cases, the default miterLimit would cut the corner and we'd // get a triangle in $too_narrow; if we grow it below then the shell // would have a different shape from the external surface and we'd still // have the same angle, so the next shell would be grown even more and so on. - auto too_narrow { diff(new_internal_solid, offset2(new_internal_solid, -margin, +margin, CLIPPER_OFFSET_SCALE, ClipperLib::jtMiter, 5), 1) }; + const auto too_narrow = diff(new_internal_solid, offset2(new_internal_solid, -margin, +margin, CLIPPER_OFFSET_SCALE, ClipperLib::jtMiter, 5), 1); - if (too_narrow.size() > 0) { + if (!too_narrow.empty()) { // grow the collapsing parts and add the extra area to the neighbor layer // as well as to our original surfaces so that we support this // additional area in the next shell too @@ -1518,16 +1498,16 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz for (auto& s : neighbor_fill_surfaces) { if (s.is_internal() && !s.is_bridge()) tmp_internal.emplace_back(Polygon(s.expolygon)); } - auto grown {intersection( - offset(too_narrow, +margin), - // Discard bridges as they are grown for anchoring and we cant - // remove such anchors. (This may happen when a bridge is being - // anchored onto a wall where little space remains after the bridge - // is grown, and that little space is an internal solid shell so - // it triggers this too_narrow logic.) - tmp_internal) - }; - new_internal_solid = solid = diff(new_internal_solid, too_narrow); + const auto grown = intersection( + offset(too_narrow, +margin), + // Discard bridges as they are grown for anchoring and we cant + // remove such anchors. (This may happen when a bridge is being + // anchored onto a wall where little space remains after the bridge + // is grown, and that little space is an internal solid shell so + // it triggers this too_narrow logic.) + tmp_internal + ); + new_internal_solid = solid = diff(grown, new_internal_solid); } } // internal-solid are the union of the existing internal-solid surfaces @@ -1535,11 +1515,11 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz Polygons tmp_internal { to_polygons(neighbor_fill_surfaces.filter_by_type(stInternalSolid)) }; polygons_append(tmp_internal, neighbor_fill_surfaces.surfaces); - auto internal_solid {union_ex(tmp_internal)}; + const auto internal_solid = union_ex(tmp_internal); // subtract intersections from layer surfaces to get resulting internal surfaces tmp_internal = to_polygons(neighbor_fill_surfaces.filter_by_type(stInternal)); - auto internal { diff_ex(tmp_internal, to_polygons(internal_solid), 1) }; + const auto internal = diff_ex(tmp_internal, to_polygons(internal_solid), 1); // assign resulting internal surfaces to layer neighbor_fill_surfaces.clear(); @@ -1563,7 +1543,7 @@ PrintObject::_discover_neighbor_horizontal_shells(LayerRegion* layerm, const siz both_solids.insert(both_solids.end(), internal_solid.begin(), internal_solid.end()); both_solids.insert(both_solids.end(), internal.begin(), internal.end()); - auto solid_surfaces { diff_ex(pp, to_polygons(both_solids), 1) }; + const auto solid_surfaces = diff_ex(pp, to_polygons(both_solids), 1); for (auto exp : solid_surfaces) neighbor_fill_surfaces.surfaces.emplace_back(Surface(s.surface_type, exp)); } @@ -1645,5 +1625,4 @@ PrintObject::clip_fill_surfaces() } } -#endif // SLIC3RXS } diff --git a/xs/src/libslic3r/SimplePrint.hpp b/xs/src/libslic3r/SimplePrint.hpp index 313718da9..8691d69c1 100644 --- a/xs/src/libslic3r/SimplePrint.hpp +++ b/xs/src/libslic3r/SimplePrint.hpp @@ -12,7 +12,6 @@ class SimplePrint { bool center{true}; std::function status_cb {nullptr}; - bool apply_config(config_ptr config) { return this->_print.apply_config(config); } bool apply_config(DynamicPrintConfig config) { return this->_print.apply_config(config); } double total_used_filament() const { return this->_print.total_used_filament; } double total_extruded_volume() const { return this->_print.total_extruded_volume; } diff --git a/xs/src/libslic3r/TriangleMesh.cpp b/xs/src/libslic3r/TriangleMesh.cpp index 5950c5382..874b01b3a 100644 --- a/xs/src/libslic3r/TriangleMesh.cpp +++ b/xs/src/libslic3r/TriangleMesh.cpp @@ -108,7 +108,6 @@ void TriangleMesh::clone(const TriangleMesh& other) { } } -#ifndef SLIC3RXS TriangleMesh::TriangleMesh(TriangleMesh&& other) { this->repaired = std::move(other.repaired); this->stl = std::move(other.stl); @@ -123,7 +122,6 @@ TriangleMesh& TriangleMesh::operator= (TriangleMesh&& other) return *this; } -#endif void TriangleMesh::swap(TriangleMesh &other) @@ -399,8 +397,6 @@ void TriangleMesh::rotate(double angle, const Point& center) this->translate(+center.x, +center.y, 0); } -#ifndef SLIC3RXS - Pointf3s TriangleMesh::vertices() { Pointf3s tmp {}; @@ -408,7 +404,7 @@ Pointf3s TriangleMesh::vertices() if (this->stl.v_shared == nullptr) stl_generate_shared_vertices(&stl); // build the list of vertices for (auto i = 0; i < this->stl.stats.shared_vertices; i++) { - const auto& v {this->stl.v_shared[i]}; + const stl_vertex& v { this->stl.v_shared[i] }; tmp.emplace_back(Pointf3(v.x, v.y, v.z)); } } else { @@ -424,7 +420,7 @@ Point3s TriangleMesh::facets() if (this->stl.v_shared == nullptr) stl_generate_shared_vertices(&stl); // build the list of vertices for (auto i = 0; i < stl.stats.number_of_facets; i++) { - const auto& v {stl.v_indices[i]}; + const v_indices_struct& v { stl.v_indices[i] }; tmp.emplace_back(Point3(v.vertex[0], v.vertex[1], v.vertex[2])); } } else { @@ -438,7 +434,7 @@ Pointf3s TriangleMesh::normals() const Pointf3s tmp {}; if (this->repaired) { for (auto i = 0; i < stl.stats.number_of_facets; i++) { - const auto& n {stl.facet_start[i].normal}; + const auto& n = stl.facet_start[i].normal; tmp.emplace_back(Pointf3(n.x, n.y, n.z)); } } else { @@ -449,7 +445,7 @@ Pointf3s TriangleMesh::normals() const Pointf3 TriangleMesh::size() const { - const auto& sz {stl.stats.size}; + const auto& sz = stl.stats.size; return Pointf3(sz.x, sz.y, sz.z); } @@ -513,10 +509,6 @@ void TriangleMesh::cut(Axis axis, double z, TriangleMesh* upper, TriangleMesh* l } } - - -#endif // SLIC3RXS - TriangleMeshPtrs TriangleMesh::split() const { diff --git a/xs/src/libslic3r/TriangleMesh.hpp b/xs/src/libslic3r/TriangleMesh.hpp index 96728911c..8118b12d2 100644 --- a/xs/src/libslic3r/TriangleMesh.hpp +++ b/xs/src/libslic3r/TriangleMesh.hpp @@ -47,11 +47,10 @@ class TriangleMesh /// copy assignment TriangleMesh& operator= (const TriangleMesh& other); -#ifndef SLIC3RXS /// Move assignment TriangleMesh& operator= (TriangleMesh&& other); TriangleMesh(TriangleMesh&& other); -#endif + void swap(TriangleMesh &other); ~TriangleMesh(); void ReadSTLFile(const std::string &input_file); @@ -99,9 +98,7 @@ class TriangleMesh void extrude_tin(float offset); void require_shared_vertices(); void reverse_normals(); - -#ifndef SLIC3RXS // Don't build these functions when also building the Perl interface. - + /// Return a copy of the vertex array defining this mesh. Pointf3s vertices(); @@ -127,8 +124,6 @@ class TriangleMesh /// Perform a cut of the mesh and put the output in upper and lower void cut(Axis axis, double z, TriangleMesh* upper, TriangleMesh* lower); - -#endif // SLIC3RXS /// Generate a mesh representing a cube with dimensions (x, y, z), with one corner at (0,0,0). static TriangleMesh make_cube(double x, double y, double z); diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index ebff92e0d..76a65d3d6 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -79,8 +79,8 @@ ConfigBase__get(ConfigBase* THIS, const t_config_option_key &opt_key) { ConfigOption* opt = THIS->option(opt_key); if (opt == NULL) return &PL_sv_undef; - const ConfigOptionDef* def = THIS->def->get(opt_key); - return ConfigOption_to_SV(*opt, *def); + const ConfigOptionDef& def = THIS->def->get(opt_key); + return ConfigOption_to_SV(*opt, def); } SV* @@ -153,22 +153,22 @@ ConfigBase__get_at(ConfigBase* THIS, const t_config_option_key &opt_key, size_t ConfigOption* opt = THIS->option(opt_key); if (opt == NULL) return &PL_sv_undef; - const ConfigOptionDef* def = THIS->def->get(opt_key); - if (def->type == coFloats) { + const ConfigOptionDef& def = THIS->def->get(opt_key); + if (def.type == coFloats) { ConfigOptionFloats* optv = dynamic_cast(opt); return newSVnv(optv->get_at(i)); - } else if (def->type == coInts) { + } else if (def.type == coInts) { ConfigOptionInts* optv = dynamic_cast(opt); return newSViv(optv->get_at(i)); - } else if (def->type == coStrings) { + } else if (def.type == coStrings) { ConfigOptionStrings* optv = dynamic_cast(opt); // we don't serialize() because that would escape newlines std::string val = optv->get_at(i); return newSVpvn_utf8(val.c_str(), val.length(), true); - } else if (def->type == coPoints) { + } else if (def.type == coPoints) { ConfigOptionPoints* optv = dynamic_cast(opt); return perl_to_SV_clone_ref(optv->get_at(i)); - } else if (def->type == coBools) { + } else if (def.type == coBools) { ConfigOptionBools* optv = dynamic_cast(opt); return newSViv(optv->get_at(i) ? 1 : 0); } else { @@ -181,12 +181,12 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) ConfigOption* opt = THIS->option(opt_key, true); if (opt == NULL) CONFESS("Trying to set non-existing option"); - const ConfigOptionDef* def = THIS->def->get(opt_key); - if (def->type == coFloat) { + const ConfigOptionDef& def = THIS->def->get(opt_key); + if (def.type == coFloat) { if (!looks_like_number(value)) return false; ConfigOptionFloat* optv = dynamic_cast(opt); optv->value = SvNV(value); - } else if (def->type == coFloats) { + } else if (def.type == coFloats) { ConfigOptionFloats* optv = dynamic_cast(opt); std::vector values; AV* av = (AV*)SvRV(value); @@ -197,11 +197,11 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) values.push_back(SvNV(*elem)); } optv->values = values; - } else if (def->type == coInt) { + } else if (def.type == coInt) { if (!looks_like_number(value)) return false; ConfigOptionInt* optv = dynamic_cast(opt); optv->value = SvIV(value); - } else if (def->type == coInts) { + } else if (def.type == coInts) { ConfigOptionInts* optv = dynamic_cast(opt); std::vector values; AV* av = (AV*)SvRV(value); @@ -212,10 +212,10 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) values.push_back(SvIV(*elem)); } optv->values = values; - } else if (def->type == coString) { + } else if (def.type == coString) { ConfigOptionString* optv = dynamic_cast(opt); optv->value = std::string(SvPV_nolen(value), SvCUR(value)); - } else if (def->type == coStrings) { + } else if (def.type == coStrings) { ConfigOptionStrings* optv = dynamic_cast(opt); optv->values.clear(); AV* av = (AV*)SvRV(value); @@ -225,13 +225,13 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) if (elem == NULL) return false; optv->values.push_back(std::string(SvPV_nolen(*elem), SvCUR(*elem))); } - } else if (def->type == coPoint) { + } else if (def.type == coPoint) { ConfigOptionPoint* optv = dynamic_cast(opt); return from_SV_check(value, &optv->value); - } else if(def->type == coPoint3){ + } else if(def.type == coPoint3){ ConfigOptionPoint3* optv = dynamic_cast(opt); return from_SV_check(value, &optv->value); - } else if (def->type == coPoints) { + } else if (def.type == coPoints) { ConfigOptionPoints* optv = dynamic_cast(opt); std::vector values; AV* av = (AV*)SvRV(value); @@ -243,10 +243,10 @@ ConfigBase__set(ConfigBase* THIS, const t_config_option_key &opt_key, SV* value) values.push_back(point); } optv->values = values; - } else if (def->type == coBool) { + } else if (def.type == coBool) { ConfigOptionBool* optv = dynamic_cast(opt); optv->value = SvTRUE(value); - } else if (def->type == coBools) { + } else if (def.type == coBools) { ConfigOptionBools* optv = dynamic_cast(opt); optv->values.clear(); AV* av = (AV*)SvRV(value); @@ -287,9 +287,9 @@ ConfigBase__set_ifndef(ConfigBase* THIS, const t_config_option_key &opt_key, SV* bool StaticConfig__set(StaticConfig* THIS, const t_config_option_key &opt_key, SV* value) { - const ConfigOptionDef* optdef = THIS->def->get(opt_key); - if (!optdef->shortcut.empty()) { - for (std::vector::const_iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it) { + const ConfigOptionDef& optdef = THIS->def->get(opt_key); + if (!optdef.shortcut.empty()) { + for (std::vector::const_iterator it = optdef.shortcut.begin(); it != optdef.shortcut.end(); ++it) { if (!StaticConfig__set(THIS, *it, value)) return false; } return true; diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index 9397961dd..fc0da994a 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -269,7 +269,13 @@ _constant() bool has_infinite_skirt(); bool has_skirt(); std::string _validate() - %code%{ RETVAL = THIS->validate(); %}; + %code%{ + try { + THIS->validate(); + } catch (std::exception &e) { + RETVAL = e.what(); + } + %}; Clone bounding_box(); Clone total_bounding_box(); double skirt_first_layer_height();