Complete the C++ CLI; remove the #ifndef SLIC3RXS guards and fix CI by removing std::initializer_lists

This commit is contained in:
Alessandro Ranellucci 2018-11-21 09:17:32 +01:00 committed by Joseph Lenox
parent 11a6601c4a
commit f0f36cb935
15 changed files with 325 additions and 366 deletions

View File

@ -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

View File

@ -1,4 +1,3 @@
#ifndef SLIC3RXS
#include "Config.hpp"
#include "Log.hpp"
@ -22,7 +21,7 @@ Config::new_from_defaults(std::initializer_list<std::string> init)
std::shared_ptr<Config>
Config::new_from_defaults(t_config_option_keys init)
{
auto my_config(std::make_shared<Config>());
std::shared_ptr<Config> my_config(std::make_shared<Config>());
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<Config>
new_from_cli(const int& argc, const char* argv[])
{
return std::make_shared<Config>();
}
std::shared_ptr<Config>
Config::new_from_ini(const std::string& inifile)
{
auto my_config(std::make_shared<Config>());
std::shared_ptr<Config> my_config(std::make_shared<Config>());
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<std::string> 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<std::string> 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<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
ConfigOptionInt* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
ptr->value = std::stoi(value);
} break;
case coInts:
{
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
ConfigOptionInts* ptr {dynamic_cast<ConfigOptionInts*>(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<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloat* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
ptr->setFloat(std::stod(value));
} break;
case coFloatOrPercent:
{
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloatOrPercent* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(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<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloats* ptr {dynamic_cast<ConfigOptionFloats*>(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<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
ConfigOptionString* ptr {dynamic_cast<ConfigOptionString*>(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<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
ConfigOptionBool* ptr {dynamic_cast<ConfigOptionBool*>(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<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
ConfigOptionBool* ptr {dynamic_cast<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
ptr->value = value;
} break;
case coInt:
{
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
ConfigOptionInt* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
ptr->setInt(value);
} break;
case coInts:
{
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
ConfigOptionInts* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
ptr->deserialize(std::to_string(value), true);
} break;
case coFloat:
{
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloat* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
ptr->setFloat(value);
} break;
case coFloatOrPercent:
{
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloatOrPercent* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
ptr->setFloat(value);
ptr->percent = false;
} break;
case coFloats:
{
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloats* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
ptr->deserialize(std::to_string(value), true);
} break;
case coString:
{
auto* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
ConfigOptionString* ptr {dynamic_cast<ConfigOptionString*>(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<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
ConfigOptionBool* ptr {dynamic_cast<ConfigOptionBool*>(this->_config.optptr(opt_key, true))};
ptr->value = (value != 0);
} break;
case coInt:
{
auto* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
ConfigOptionInt* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
ptr->setInt(value);
} break;
case coInts:
{
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
ConfigOptionInts* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
ptr->deserialize(std::to_string(value), true);
} break;
case coFloat:
{
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloat* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
ptr->setFloat(value);
} break;
case coFloatOrPercent:
{
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloatOrPercent* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
ptr->setFloat(value);
ptr->percent = false;
} break;
case coFloats:
{
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloats* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
ptr->deserialize(std::to_string(value), true);
} break;
case coString:
{
auto* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
ConfigOptionString* ptr {dynamic_cast<ConfigOptionString*>(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<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
ConfigOptionInt* ptr {dynamic_cast<ConfigOptionInt*>(this->_config.optptr(opt_key, true))};
ptr->setInt(std::round(value));
} break;
case coInts:
{
auto* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
ConfigOptionInts* ptr {dynamic_cast<ConfigOptionInts*>(this->_config.optptr(opt_key, true))};
ptr->deserialize(std::to_string(std::round(value)), true);
} break;
case coFloat:
{
auto* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloat* ptr {dynamic_cast<ConfigOptionFloat*>(this->_config.optptr(opt_key, true))};
ptr->setFloat(value);
} break;
case coFloatOrPercent:
{
auto* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloatOrPercent* ptr {dynamic_cast<ConfigOptionFloatOrPercent*>(this->_config.optptr(opt_key, true))};
ptr->setFloat(value);
ptr->percent = false;
} break;
case coFloats:
{
auto* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
ConfigOptionFloats* ptr {dynamic_cast<ConfigOptionFloats*>(this->_config.optptr(opt_key, true))};
ptr->deserialize(std::to_string(value), true);
} break;
case coString:
{
auto* ptr {dynamic_cast<ConfigOptionString*>(this->_config.optptr(opt_key, true))};
ConfigOptionString* ptr {dynamic_cast<ConfigOptionString*>(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

View File

@ -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<Config> new_from_defaults(t_config_option_keys init);
/// Factory method to construct a Config from CLI options.
static std::shared_ptr<Config> new_from_cli(const int& argc, const char* argv[]);
/// Factory method to construct a Config from an ini file.
static std::shared_ptr<Config> 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

View File

@ -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;

View File

@ -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."};

View File

@ -113,7 +113,7 @@ class PrintObject
// TODO: Fill* fill_maker => (is => 'lazy');
PrintState<PrintObjectStep> 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<void(int, const std::string&)> 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<void(std::vector<std::string>)> post_process_cb {nullptr};
#endif
double total_used_filament, total_extruded_volume, total_cost, total_weight;
std::map<size_t,float> filament_stats;
PrintState<PrintStep> 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<size_t> object_extruders() const;

View File

@ -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);

View File

@ -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<Layer*> 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<size_t> z;
z.reserve(100); // preallocate with 100 layers
std::map<coord_t, std::map<size_t, LayerPtrs > > 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<double> 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<size_t>(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<size_t> 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<unsigned int, Extruder>& 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<size_t>(print.config.skirt_height)) {
const auto& skirt_flow {print.skirt_flow()};
if (_print.has_infinite_skirt() || layer->id() < static_cast<size_t>(_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<size_t>(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<size_t>(_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<ExtrusionLoop*>(skirt_loops.at(i)))};
auto& loop = *dynamic_cast<ExtrusionLoop*>(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<const SupportLayer*>(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<BoundingBox> 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<size_t,ExtrusionEntityCollection> &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

View File

@ -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

View File

@ -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<float> 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<coordf_t>(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<coordf_t>(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<coordf_t>(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<size_t>(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
}

View File

@ -12,7 +12,6 @@ class SimplePrint {
bool center{true};
std::function<void(int, const std::string&)> 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; }

View File

@ -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
{

View File

@ -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);

View File

@ -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<ConfigOptionFloats*>(opt);
return newSVnv(optv->get_at(i));
} else if (def->type == coInts) {
} else if (def.type == coInts) {
ConfigOptionInts* optv = dynamic_cast<ConfigOptionInts*>(opt);
return newSViv(optv->get_at(i));
} else if (def->type == coStrings) {
} else if (def.type == coStrings) {
ConfigOptionStrings* optv = dynamic_cast<ConfigOptionStrings*>(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<ConfigOptionPoints*>(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<ConfigOptionBools*>(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<ConfigOptionFloat*>(opt);
optv->value = SvNV(value);
} else if (def->type == coFloats) {
} else if (def.type == coFloats) {
ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt);
std::vector<double> 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<ConfigOptionInt*>(opt);
optv->value = SvIV(value);
} else if (def->type == coInts) {
} else if (def.type == coInts) {
ConfigOptionInts* optv = dynamic_cast<ConfigOptionInts*>(opt);
std::vector<int> 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<ConfigOptionString*>(opt);
optv->value = std::string(SvPV_nolen(value), SvCUR(value));
} else if (def->type == coStrings) {
} else if (def.type == coStrings) {
ConfigOptionStrings* optv = dynamic_cast<ConfigOptionStrings*>(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<ConfigOptionPoint*>(opt);
return from_SV_check(value, &optv->value);
} else if(def->type == coPoint3){
} else if(def.type == coPoint3){
ConfigOptionPoint3* optv = dynamic_cast<ConfigOptionPoint3*>(opt);
return from_SV_check(value, &optv->value);
} else if (def->type == coPoints) {
} else if (def.type == coPoints) {
ConfigOptionPoints* optv = dynamic_cast<ConfigOptionPoints*>(opt);
std::vector<Pointf> 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<ConfigOptionBool*>(opt);
optv->value = SvTRUE(value);
} else if (def->type == coBools) {
} else if (def.type == coBools) {
ConfigOptionBools* optv = dynamic_cast<ConfigOptionBools*>(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<t_config_option_key>::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<t_config_option_key>::const_iterator it = optdef.shortcut.begin(); it != optdef.shortcut.end(); ++it) {
if (!StaticConfig__set(THIS, *it, value)) return false;
}
return true;

View File

@ -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<BoundingBox> bounding_box();
Clone<BoundingBox> total_bounding_box();
double skirt_first_layer_height();