Improved constness of the Print / PrintObject / Layer ...
Split the wipe tower and time statistics data into separate objects. Initial work in synchronizing the Model with the Print.
This commit is contained in:
parent
49697ed6aa
commit
41ce69f327
21 changed files with 1197 additions and 1101 deletions
|
@ -34,7 +34,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||||
{
|
{
|
||||||
// Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id;
|
// Slic3r::debugf "Filling layer %d:\n", $layerm->layer->id;
|
||||||
|
|
||||||
double fill_density = layerm.region()->config.fill_density;
|
double fill_density = layerm.region()->config().fill_density;
|
||||||
Flow infill_flow = layerm.flow(frInfill);
|
Flow infill_flow = layerm.flow(frInfill);
|
||||||
Flow solid_infill_flow = layerm.flow(frSolidInfill);
|
Flow solid_infill_flow = layerm.flow(frSolidInfill);
|
||||||
Flow top_solid_infill_flow = layerm.flow(frTopSolidInfill);
|
Flow top_solid_infill_flow = layerm.flow(frTopSolidInfill);
|
||||||
|
@ -69,7 +69,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||||
if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0)) {
|
if (surface.is_solid() && (!surface.is_bridge() || layerm.layer()->id() == 0)) {
|
||||||
group_attrib[i].is_solid = true;
|
group_attrib[i].is_solid = true;
|
||||||
group_attrib[i].flow_width = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width;
|
group_attrib[i].flow_width = (surface.surface_type == stTop) ? top_solid_infill_flow.width : solid_infill_flow.width;
|
||||||
group_attrib[i].pattern = surface.is_external() ? layerm.region()->config.external_fill_pattern.value : ipRectilinear;
|
group_attrib[i].pattern = surface.is_external() ? layerm.region()->config().external_fill_pattern.value : ipRectilinear;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Loop through solid groups, find compatible groups and append them to this one.
|
// Loop through solid groups, find compatible groups and append them to this one.
|
||||||
|
@ -152,7 +152,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||||
for (const Surface &surface : surfaces) {
|
for (const Surface &surface : surfaces) {
|
||||||
if (surface.surface_type == stInternalVoid)
|
if (surface.surface_type == stInternalVoid)
|
||||||
continue;
|
continue;
|
||||||
InfillPattern fill_pattern = layerm.region()->config.fill_pattern.value;
|
InfillPattern fill_pattern = layerm.region()->config().fill_pattern.value;
|
||||||
double density = fill_density;
|
double density = fill_density;
|
||||||
FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill :
|
FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill :
|
||||||
(surface.is_solid() ? frSolidInfill : frInfill);
|
(surface.is_solid() ? frSolidInfill : frInfill);
|
||||||
|
@ -161,7 +161,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||||
if (surface.is_solid()) {
|
if (surface.is_solid()) {
|
||||||
density = 100.;
|
density = 100.;
|
||||||
fill_pattern = (surface.is_external() && ! is_bridge) ?
|
fill_pattern = (surface.is_external() && ! is_bridge) ?
|
||||||
layerm.region()->config.external_fill_pattern.value :
|
layerm.region()->config().external_fill_pattern.value :
|
||||||
ipRectilinear;
|
ipRectilinear;
|
||||||
} else if (density <= 0)
|
} else if (density <= 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -190,7 +190,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||||
// layer height
|
// layer height
|
||||||
Flow internal_flow = layerm.region()->flow(
|
Flow internal_flow = layerm.region()->flow(
|
||||||
frInfill,
|
frInfill,
|
||||||
layerm.layer()->object()->config.layer_height.value, // TODO: handle infill_every_layers?
|
layerm.layer()->object()->config().layer_height.value, // TODO: handle infill_every_layers?
|
||||||
false, // no bridge
|
false, // no bridge
|
||||||
false, // no first layer
|
false, // no first layer
|
||||||
-1, // auto width
|
-1, // auto width
|
||||||
|
@ -205,7 +205,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||||
double link_max_length = 0.;
|
double link_max_length = 0.;
|
||||||
if (! is_bridge) {
|
if (! is_bridge) {
|
||||||
#if 0
|
#if 0
|
||||||
link_max_length = layerm.region()->config.get_abs_value(surface.is_external() ? "external_fill_link_max_length" : "fill_link_max_length", flow.spacing());
|
link_max_length = layerm.region()->config().get_abs_value(surface.is_external() ? "external_fill_link_max_length" : "fill_link_max_length", flow.spacing());
|
||||||
// printf("flow spacing: %f, is_external: %d, link_max_length: %lf\n", flow.spacing(), int(surface.is_external()), link_max_length);
|
// printf("flow spacing: %f, is_external: %d, link_max_length: %lf\n", flow.spacing(), int(surface.is_external()), link_max_length);
|
||||||
#else
|
#else
|
||||||
if (density > 80.) // 80%
|
if (density > 80.) // 80%
|
||||||
|
@ -215,7 +215,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
||||||
|
|
||||||
f->layer_id = layerm.layer()->id();
|
f->layer_id = layerm.layer()->id();
|
||||||
f->z = layerm.layer()->print_z;
|
f->z = layerm.layer()->print_z;
|
||||||
f->angle = float(Geometry::deg2rad(layerm.region()->config.fill_angle.value));
|
f->angle = float(Geometry::deg2rad(layerm.region()->config().fill_angle.value));
|
||||||
// Maximum length of the perimeter segment linking two infill lines.
|
// Maximum length of the perimeter segment linking two infill lines.
|
||||||
f->link_max_length = scale_(link_max_length);
|
f->link_max_length = scale_(link_max_length);
|
||||||
// Used by the concentric infill pattern to clip the loops to create extrusion paths.
|
// Used by the concentric infill pattern to clip the loops to create extrusion paths.
|
||||||
|
|
|
@ -111,22 +111,22 @@ Flow support_material_flow(const PrintObject *object, float layer_height)
|
||||||
return Flow::new_from_config_width(
|
return Flow::new_from_config_width(
|
||||||
frSupportMaterial,
|
frSupportMaterial,
|
||||||
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
||||||
(object->config.support_material_extrusion_width.value > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
|
(object->config().support_material_extrusion_width.value > 0) ? object->config().support_material_extrusion_width : object->config().extrusion_width,
|
||||||
// if object->config.support_material_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
|
// if object->config().support_material_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
|
||||||
float(object->print()->config.nozzle_diameter.get_at(object->config.support_material_extruder-1)),
|
float(object->print()->config().nozzle_diameter.get_at(object->config().support_material_extruder-1)),
|
||||||
(layer_height > 0.f) ? layer_height : float(object->config.layer_height.value),
|
(layer_height > 0.f) ? layer_height : float(object->config().layer_height.value),
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Flow support_material_1st_layer_flow(const PrintObject *object, float layer_height)
|
Flow support_material_1st_layer_flow(const PrintObject *object, float layer_height)
|
||||||
{
|
{
|
||||||
const auto &width = (object->print()->config.first_layer_extrusion_width.value > 0) ? object->print()->config.first_layer_extrusion_width : object->config.support_material_extrusion_width;
|
const auto &width = (object->print()->config().first_layer_extrusion_width.value > 0) ? object->print()->config().first_layer_extrusion_width : object->config().support_material_extrusion_width;
|
||||||
return Flow::new_from_config_width(
|
return Flow::new_from_config_width(
|
||||||
frSupportMaterial,
|
frSupportMaterial,
|
||||||
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
||||||
(width.value > 0) ? width : object->config.extrusion_width,
|
(width.value > 0) ? width : object->config().extrusion_width,
|
||||||
float(object->print()->config.nozzle_diameter.get_at(object->config.support_material_extruder-1)),
|
float(object->print()->config().nozzle_diameter.get_at(object->config().support_material_extruder-1)),
|
||||||
(layer_height > 0.f) ? layer_height : float(object->config.first_layer_height.get_abs_value(object->config.layer_height.value)),
|
(layer_height > 0.f) ? layer_height : float(object->config().first_layer_height.get_abs_value(object->config().layer_height.value)),
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,10 +135,10 @@ Flow support_material_interface_flow(const PrintObject *object, float layer_heig
|
||||||
return Flow::new_from_config_width(
|
return Flow::new_from_config_width(
|
||||||
frSupportMaterialInterface,
|
frSupportMaterialInterface,
|
||||||
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
// The width parameter accepted by new_from_config_width is of type ConfigOptionFloatOrPercent, the Flow class takes care of the percent to value substitution.
|
||||||
(object->config.support_material_extrusion_width > 0) ? object->config.support_material_extrusion_width : object->config.extrusion_width,
|
(object->config().support_material_extrusion_width > 0) ? object->config().support_material_extrusion_width : object->config().extrusion_width,
|
||||||
// if object->config.support_material_interface_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
|
// if object->config().support_material_interface_extruder == 0 (which means to not trigger tool change, but use the current extruder instead), get_at will return the 0th component.
|
||||||
float(object->print()->config.nozzle_diameter.get_at(object->config.support_material_interface_extruder-1)),
|
float(object->print()->config().nozzle_diameter.get_at(object->config().support_material_interface_extruder-1)),
|
||||||
(layer_height > 0.f) ? layer_height : float(object->config.layer_height.value),
|
(layer_height > 0.f) ? layer_height : float(object->config().layer_height.value),
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -275,15 +275,15 @@ std::string WipeTowerIntegration::finalize(GCode &gcodegen)
|
||||||
std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObject &object)
|
std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObject &object)
|
||||||
{
|
{
|
||||||
std::vector<GCode::LayerToPrint> layers_to_print;
|
std::vector<GCode::LayerToPrint> layers_to_print;
|
||||||
layers_to_print.reserve(object.layers.size() + object.support_layers.size());
|
layers_to_print.reserve(object.layers().size() + object.support_layers().size());
|
||||||
|
|
||||||
// Pair the object layers with the support layers by z.
|
// Pair the object layers with the support layers by z.
|
||||||
size_t idx_object_layer = 0;
|
size_t idx_object_layer = 0;
|
||||||
size_t idx_support_layer = 0;
|
size_t idx_support_layer = 0;
|
||||||
while (idx_object_layer < object.layers.size() || idx_support_layer < object.support_layers.size()) {
|
while (idx_object_layer < object.layers().size() || idx_support_layer < object.support_layers().size()) {
|
||||||
LayerToPrint layer_to_print;
|
LayerToPrint layer_to_print;
|
||||||
layer_to_print.object_layer = (idx_object_layer < object.layers.size()) ? object.layers[idx_object_layer ++] : nullptr;
|
layer_to_print.object_layer = (idx_object_layer < object.layers().size()) ? object.layers()[idx_object_layer ++] : nullptr;
|
||||||
layer_to_print.support_layer = (idx_support_layer < object.support_layers.size()) ? object.support_layers[idx_support_layer ++] : nullptr;
|
layer_to_print.support_layer = (idx_support_layer < object.support_layers().size()) ? object.support_layers()[idx_support_layer ++] : nullptr;
|
||||||
if (layer_to_print.object_layer && layer_to_print.support_layer) {
|
if (layer_to_print.object_layer && layer_to_print.support_layer) {
|
||||||
if (layer_to_print.object_layer->print_z < layer_to_print.support_layer->print_z - EPSILON) {
|
if (layer_to_print.object_layer->print_z < layer_to_print.support_layer->print_z - EPSILON) {
|
||||||
layer_to_print.support_layer = nullptr;
|
layer_to_print.support_layer = nullptr;
|
||||||
|
@ -309,10 +309,10 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
|
||||||
size_t object_idx;
|
size_t object_idx;
|
||||||
size_t layer_idx;
|
size_t layer_idx;
|
||||||
};
|
};
|
||||||
std::vector<std::vector<LayerToPrint>> per_object(print.objects.size(), std::vector<LayerToPrint>());
|
std::vector<std::vector<LayerToPrint>> per_object(print.objects().size(), std::vector<LayerToPrint>());
|
||||||
std::vector<OrderingItem> ordering;
|
std::vector<OrderingItem> ordering;
|
||||||
for (size_t i = 0; i < print.objects.size(); ++ i) {
|
for (size_t i = 0; i < print.objects().size(); ++ i) {
|
||||||
per_object[i] = collect_layers_to_print(*print.objects[i]);
|
per_object[i] = collect_layers_to_print(*print.objects()[i]);
|
||||||
OrderingItem ordering_item;
|
OrderingItem ordering_item;
|
||||||
ordering_item.object_idx = i;
|
ordering_item.object_idx = i;
|
||||||
ordering.reserve(ordering.size() + per_object[i].size());
|
ordering.reserve(ordering.size() + per_object[i].size());
|
||||||
|
@ -337,7 +337,7 @@ std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collec
|
||||||
std::pair<coordf_t, std::vector<LayerToPrint>> merged;
|
std::pair<coordf_t, std::vector<LayerToPrint>> merged;
|
||||||
// Assign an average print_z to the set of layers with nearly equal print_z.
|
// Assign an average print_z to the set of layers with nearly equal print_z.
|
||||||
merged.first = 0.5 * (ordering[i].print_z + ordering[j-1].print_z);
|
merged.first = 0.5 * (ordering[i].print_z + ordering[j-1].print_z);
|
||||||
merged.second.assign(print.objects.size(), LayerToPrint());
|
merged.second.assign(print.objects().size(), LayerToPrint());
|
||||||
for (; i < j; ++ i) {
|
for (; i < j; ++ i) {
|
||||||
const OrderingItem &oi = ordering[i];
|
const OrderingItem &oi = ordering[i];
|
||||||
assert(merged.second[oi.object_idx].layer() == nullptr);
|
assert(merged.second[oi.object_idx].layer() == nullptr);
|
||||||
|
@ -366,7 +366,7 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||||
throw std::runtime_error(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n");
|
throw std::runtime_error(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this->m_placeholder_parser_failed_templates.clear();
|
m_placeholder_parser_failed_templates.clear();
|
||||||
this->_do_export(*print, file, preview_data);
|
this->_do_export(*print, file, preview_data);
|
||||||
fflush(file);
|
fflush(file);
|
||||||
if (ferror(file)) {
|
if (ferror(file)) {
|
||||||
|
@ -382,10 +382,10 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
if (! this->m_placeholder_parser_failed_templates.empty()) {
|
if (! m_placeholder_parser_failed_templates.empty()) {
|
||||||
// G-code export proceeded, but some of the PlaceholderParser substitutions failed.
|
// G-code export proceeded, but some of the PlaceholderParser substitutions failed.
|
||||||
std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n";
|
std::string msg = std::string("G-code export to ") + path + " failed due to invalid custom G-code sections:\n\n";
|
||||||
for (const std::string &name : this->m_placeholder_parser_failed_templates)
|
for (const std::string &name : m_placeholder_parser_failed_templates)
|
||||||
msg += std::string("\t") + name + "\n";
|
msg += std::string("\t") + name + "\n";
|
||||||
msg += "\nPlease inspect the file ";
|
msg += "\nPlease inspect the file ";
|
||||||
msg += path_tmp + " for error messages enclosed between\n";
|
msg += path_tmp + " for error messages enclosed between\n";
|
||||||
|
@ -415,7 +415,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
|
|
||||||
// resets time estimator
|
// resets time estimator
|
||||||
m_time_estimator.reset();
|
m_time_estimator.reset();
|
||||||
m_time_estimator.set_dialect(print.config.gcode_flavor);
|
m_time_estimator.set_dialect(print.config().gcode_flavor);
|
||||||
|
|
||||||
// resets analyzer
|
// resets analyzer
|
||||||
m_analyzer.reset();
|
m_analyzer.reset();
|
||||||
|
@ -429,14 +429,14 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
// How many times will be change_layer() called?
|
// How many times will be change_layer() called?
|
||||||
// change_layer() in turn increments the progress bar status.
|
// change_layer() in turn increments the progress bar status.
|
||||||
m_layer_count = 0;
|
m_layer_count = 0;
|
||||||
if (print.config.complete_objects.value) {
|
if (print.config().complete_objects.value) {
|
||||||
// Add each of the object's layers separately.
|
// Add each of the object's layers separately.
|
||||||
for (auto object : print.objects) {
|
for (auto object : print.objects()) {
|
||||||
std::vector<coordf_t> zs;
|
std::vector<coordf_t> zs;
|
||||||
zs.reserve(object->layers.size() + object->support_layers.size());
|
zs.reserve(object->layers().size() + object->support_layers().size());
|
||||||
for (auto layer : object->layers)
|
for (auto layer : object->layers())
|
||||||
zs.push_back(layer->print_z);
|
zs.push_back(layer->print_z);
|
||||||
for (auto layer : object->support_layers)
|
for (auto layer : object->support_layers())
|
||||||
zs.push_back(layer->print_z);
|
zs.push_back(layer->print_z);
|
||||||
std::sort(zs.begin(), zs.end());
|
std::sort(zs.begin(), zs.end());
|
||||||
m_layer_count += (unsigned int)(object->copies().size() * (std::unique(zs.begin(), zs.end()) - zs.begin()));
|
m_layer_count += (unsigned int)(object->copies().size() * (std::unique(zs.begin(), zs.end()) - zs.begin()));
|
||||||
|
@ -444,11 +444,11 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
} else {
|
} else {
|
||||||
// Print all objects with the same print_z together.
|
// Print all objects with the same print_z together.
|
||||||
std::vector<coordf_t> zs;
|
std::vector<coordf_t> zs;
|
||||||
for (auto object : print.objects) {
|
for (auto object : print.objects()) {
|
||||||
zs.reserve(zs.size() + object->layers.size() + object->support_layers.size());
|
zs.reserve(zs.size() + object->layers().size() + object->support_layers().size());
|
||||||
for (auto layer : object->layers)
|
for (auto layer : object->layers())
|
||||||
zs.push_back(layer->print_z);
|
zs.push_back(layer->print_z);
|
||||||
for (auto layer : object->support_layers)
|
for (auto layer : object->support_layers())
|
||||||
zs.push_back(layer->print_z);
|
zs.push_back(layer->print_z);
|
||||||
}
|
}
|
||||||
std::sort(zs.begin(), zs.end());
|
std::sort(zs.begin(), zs.end());
|
||||||
|
@ -457,33 +457,33 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
print.throw_if_canceled();
|
print.throw_if_canceled();
|
||||||
|
|
||||||
m_enable_cooling_markers = true;
|
m_enable_cooling_markers = true;
|
||||||
this->apply_print_config(print.config);
|
this->apply_print_config(print.config());
|
||||||
this->set_extruders(print.extruders());
|
this->set_extruders(print.extruders());
|
||||||
|
|
||||||
// Initialize autospeed.
|
// Initialize autospeed.
|
||||||
{
|
{
|
||||||
// get the minimum cross-section used in the print
|
// get the minimum cross-section used in the print
|
||||||
std::vector<double> mm3_per_mm;
|
std::vector<double> mm3_per_mm;
|
||||||
for (auto object : print.objects) {
|
for (auto object : print.objects()) {
|
||||||
for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) {
|
for (size_t region_id = 0; region_id < print.regions().size(); ++ region_id) {
|
||||||
auto region = print.regions[region_id];
|
auto region = print.regions()[region_id];
|
||||||
for (auto layer : object->layers) {
|
for (auto layer : object->layers()) {
|
||||||
auto layerm = layer->regions[region_id];
|
auto layerm = layer->regions()[region_id];
|
||||||
if (region->config.get_abs_value("perimeter_speed" ) == 0 ||
|
if (region->config().get_abs_value("perimeter_speed" ) == 0 ||
|
||||||
region->config.get_abs_value("small_perimeter_speed" ) == 0 ||
|
region->config().get_abs_value("small_perimeter_speed" ) == 0 ||
|
||||||
region->config.get_abs_value("external_perimeter_speed" ) == 0 ||
|
region->config().get_abs_value("external_perimeter_speed" ) == 0 ||
|
||||||
region->config.get_abs_value("bridge_speed" ) == 0)
|
region->config().get_abs_value("bridge_speed" ) == 0)
|
||||||
mm3_per_mm.push_back(layerm->perimeters.min_mm3_per_mm());
|
mm3_per_mm.push_back(layerm->perimeters.min_mm3_per_mm());
|
||||||
if (region->config.get_abs_value("infill_speed" ) == 0 ||
|
if (region->config().get_abs_value("infill_speed" ) == 0 ||
|
||||||
region->config.get_abs_value("solid_infill_speed" ) == 0 ||
|
region->config().get_abs_value("solid_infill_speed" ) == 0 ||
|
||||||
region->config.get_abs_value("top_solid_infill_speed" ) == 0 ||
|
region->config().get_abs_value("top_solid_infill_speed" ) == 0 ||
|
||||||
region->config.get_abs_value("bridge_speed" ) == 0)
|
region->config().get_abs_value("bridge_speed" ) == 0)
|
||||||
mm3_per_mm.push_back(layerm->fills.min_mm3_per_mm());
|
mm3_per_mm.push_back(layerm->fills.min_mm3_per_mm());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (object->config.get_abs_value("support_material_speed" ) == 0 ||
|
if (object->config().get_abs_value("support_material_speed" ) == 0 ||
|
||||||
object->config.get_abs_value("support_material_interface_speed" ) == 0)
|
object->config().get_abs_value("support_material_interface_speed" ) == 0)
|
||||||
for (auto layer : object->support_layers)
|
for (auto layer : object->support_layers())
|
||||||
mm3_per_mm.push_back(layer->support_fills.min_mm3_per_mm());
|
mm3_per_mm.push_back(layer->support_fills.min_mm3_per_mm());
|
||||||
}
|
}
|
||||||
print.throw_if_canceled();
|
print.throw_if_canceled();
|
||||||
|
@ -495,20 +495,20 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
// volumetric speed as the volumetric speed produced by printing the
|
// volumetric speed as the volumetric speed produced by printing the
|
||||||
// smallest cross-section at the maximum speed: any larger cross-section
|
// smallest cross-section at the maximum speed: any larger cross-section
|
||||||
// will need slower feedrates.
|
// will need slower feedrates.
|
||||||
m_volumetric_speed = *std::min_element(mm3_per_mm.begin(), mm3_per_mm.end()) * print.config.max_print_speed.value;
|
m_volumetric_speed = *std::min_element(mm3_per_mm.begin(), mm3_per_mm.end()) * print.config().max_print_speed.value;
|
||||||
// limit such volumetric speed with max_volumetric_speed if set
|
// limit such volumetric speed with max_volumetric_speed if set
|
||||||
if (print.config.max_volumetric_speed.value > 0)
|
if (print.config().max_volumetric_speed.value > 0)
|
||||||
m_volumetric_speed = std::min(m_volumetric_speed, print.config.max_volumetric_speed.value);
|
m_volumetric_speed = std::min(m_volumetric_speed, print.config().max_volumetric_speed.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print.throw_if_canceled();
|
print.throw_if_canceled();
|
||||||
|
|
||||||
m_cooling_buffer = make_unique<CoolingBuffer>(*this);
|
m_cooling_buffer = make_unique<CoolingBuffer>(*this);
|
||||||
if (print.config.spiral_vase.value)
|
if (print.config().spiral_vase.value)
|
||||||
m_spiral_vase = make_unique<SpiralVase>(print.config);
|
m_spiral_vase = make_unique<SpiralVase>(print.config());
|
||||||
if (print.config.max_volumetric_extrusion_rate_slope_positive.value > 0 ||
|
if (print.config().max_volumetric_extrusion_rate_slope_positive.value > 0 ||
|
||||||
print.config.max_volumetric_extrusion_rate_slope_negative.value > 0)
|
print.config().max_volumetric_extrusion_rate_slope_negative.value > 0)
|
||||||
m_pressure_equalizer = make_unique<PressureEqualizer>(&print.config);
|
m_pressure_equalizer = make_unique<PressureEqualizer>(&print.config());
|
||||||
m_enable_extrusion_role_markers = (bool)m_pressure_equalizer;
|
m_enable_extrusion_role_markers = (bool)m_pressure_equalizer;
|
||||||
|
|
||||||
// Write information on the generator.
|
// Write information on the generator.
|
||||||
|
@ -516,7 +516,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
// Write notes (content of the Print Settings tab -> Notes)
|
// Write notes (content of the Print Settings tab -> Notes)
|
||||||
{
|
{
|
||||||
std::list<std::string> lines;
|
std::list<std::string> lines;
|
||||||
boost::split(lines, print.config.notes.value, boost::is_any_of("\n"), boost::token_compress_off);
|
boost::split(lines, print.config().notes.value, boost::is_any_of("\n"), boost::token_compress_off);
|
||||||
for (auto line : lines) {
|
for (auto line : lines) {
|
||||||
// Remove the trailing '\r' from the '\r\n' sequence.
|
// Remove the trailing '\r' from the '\r\n' sequence.
|
||||||
if (! line.empty() && line.back() == '\r')
|
if (! line.empty() && line.back() == '\r')
|
||||||
|
@ -529,11 +529,11 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
print.throw_if_canceled();
|
print.throw_if_canceled();
|
||||||
|
|
||||||
// Write some terse information on the slicing parameters.
|
// Write some terse information on the slicing parameters.
|
||||||
const PrintObject *first_object = print.objects.front();
|
const PrintObject *first_object = print.objects().front();
|
||||||
const double layer_height = first_object->config.layer_height.value;
|
const double layer_height = first_object->config().layer_height.value;
|
||||||
const double first_layer_height = first_object->config.first_layer_height.get_abs_value(layer_height);
|
const double first_layer_height = first_object->config().first_layer_height.get_abs_value(layer_height);
|
||||||
for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) {
|
for (size_t region_id = 0; region_id < print.regions().size(); ++ region_id) {
|
||||||
auto region = print.regions[region_id];
|
auto region = print.regions()[region_id];
|
||||||
_write_format(file, "; external perimeters extrusion width = %.2fmm\n", region->flow(frExternalPerimeter, layer_height, false, false, -1., *first_object).width);
|
_write_format(file, "; external perimeters extrusion width = %.2fmm\n", region->flow(frExternalPerimeter, layer_height, false, false, -1., *first_object).width);
|
||||||
_write_format(file, "; perimeters extrusion width = %.2fmm\n", region->flow(frPerimeter, layer_height, false, false, -1., *first_object).width);
|
_write_format(file, "; perimeters extrusion width = %.2fmm\n", region->flow(frPerimeter, layer_height, false, false, -1., *first_object).width);
|
||||||
_write_format(file, "; infill extrusion width = %.2fmm\n", region->flow(frInfill, layer_height, false, false, -1., *first_object).width);
|
_write_format(file, "; infill extrusion width = %.2fmm\n", region->flow(frInfill, layer_height, false, false, -1., *first_object).width);
|
||||||
|
@ -541,14 +541,14 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
_write_format(file, "; top infill extrusion width = %.2fmm\n", region->flow(frTopSolidInfill, layer_height, false, false, -1., *first_object).width);
|
_write_format(file, "; top infill extrusion width = %.2fmm\n", region->flow(frTopSolidInfill, layer_height, false, false, -1., *first_object).width);
|
||||||
if (print.has_support_material())
|
if (print.has_support_material())
|
||||||
_write_format(file, "; support material extrusion width = %.2fmm\n", support_material_flow(first_object).width);
|
_write_format(file, "; support material extrusion width = %.2fmm\n", support_material_flow(first_object).width);
|
||||||
if (print.config.first_layer_extrusion_width.value > 0)
|
if (print.config().first_layer_extrusion_width.value > 0)
|
||||||
_write_format(file, "; first layer extrusion width = %.2fmm\n", region->flow(frPerimeter, first_layer_height, false, true, -1., *first_object).width);
|
_write_format(file, "; first layer extrusion width = %.2fmm\n", region->flow(frPerimeter, first_layer_height, false, true, -1., *first_object).width);
|
||||||
_write_format(file, "\n");
|
_write_format(file, "\n");
|
||||||
}
|
}
|
||||||
print.throw_if_canceled();
|
print.throw_if_canceled();
|
||||||
|
|
||||||
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
|
// Prepare the helper object for replacing placeholders in custom G-code and output filename.
|
||||||
m_placeholder_parser = print.placeholder_parser;
|
m_placeholder_parser = print.placeholder_parser();
|
||||||
m_placeholder_parser.update_timestamp();
|
m_placeholder_parser.update_timestamp();
|
||||||
|
|
||||||
// Get optimal tool ordering to minimize tool switches of a multi-exruder print.
|
// Get optimal tool ordering to minimize tool switches of a multi-exruder print.
|
||||||
|
@ -558,19 +558,19 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
unsigned int final_extruder_id = (unsigned int)-1;
|
unsigned int final_extruder_id = (unsigned int)-1;
|
||||||
size_t initial_print_object_id = 0;
|
size_t initial_print_object_id = 0;
|
||||||
bool has_wipe_tower = false;
|
bool has_wipe_tower = false;
|
||||||
if (print.config.complete_objects.value) {
|
if (print.config().complete_objects.value) {
|
||||||
// Find the 1st printing object, find its tool ordering and the initial extruder ID.
|
// Find the 1st printing object, find its tool ordering and the initial extruder ID.
|
||||||
for (; initial_print_object_id < print.objects.size(); ++initial_print_object_id) {
|
for (; initial_print_object_id < print.objects().size(); ++initial_print_object_id) {
|
||||||
tool_ordering = ToolOrdering(*print.objects[initial_print_object_id], initial_extruder_id);
|
tool_ordering = ToolOrdering(*print.objects()[initial_print_object_id], initial_extruder_id);
|
||||||
if ((initial_extruder_id = tool_ordering.first_extruder()) != (unsigned int)-1)
|
if ((initial_extruder_id = tool_ordering.first_extruder()) != (unsigned int)-1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Find tool ordering for all the objects at once, and the initial extruder ID.
|
// Find tool ordering for all the objects at once, and the initial extruder ID.
|
||||||
// If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it.
|
// If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it.
|
||||||
tool_ordering = print.m_tool_ordering.empty() ?
|
tool_ordering = print.wipe_tower_data().tool_ordering.empty() ?
|
||||||
ToolOrdering(print, initial_extruder_id) :
|
ToolOrdering(print, initial_extruder_id) :
|
||||||
print.m_tool_ordering;
|
print.wipe_tower_data().tool_ordering;
|
||||||
initial_extruder_id = tool_ordering.first_extruder();
|
initial_extruder_id = tool_ordering.first_extruder();
|
||||||
has_wipe_tower = print.has_wipe_tower() && tool_ordering.has_wipe_tower();
|
has_wipe_tower = print.has_wipe_tower() && tool_ordering.has_wipe_tower();
|
||||||
}
|
}
|
||||||
|
@ -587,7 +587,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
m_cooling_buffer->set_current_extruder(initial_extruder_id);
|
m_cooling_buffer->set_current_extruder(initial_extruder_id);
|
||||||
|
|
||||||
// Disable fan.
|
// Disable fan.
|
||||||
if (! print.config.cooling.get_at(initial_extruder_id) || print.config.disable_fan_first_layers.get_at(initial_extruder_id))
|
if (! print.config().cooling.get_at(initial_extruder_id) || print.config().disable_fan_first_layers.get_at(initial_extruder_id))
|
||||||
_write(file, m_writer.set_fan(0, true));
|
_write(file, m_writer.set_fan(0, true));
|
||||||
|
|
||||||
// Let the start-up script prime the 1st printing tool.
|
// Let the start-up script prime the 1st printing tool.
|
||||||
|
@ -598,7 +598,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
m_placeholder_parser.set("current_object_idx", 0);
|
m_placeholder_parser.set("current_object_idx", 0);
|
||||||
// For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided.
|
// For the start / end G-code to do the priming and final filament pull in case there is no wipe tower provided.
|
||||||
m_placeholder_parser.set("has_wipe_tower", has_wipe_tower);
|
m_placeholder_parser.set("has_wipe_tower", has_wipe_tower);
|
||||||
std::string start_gcode = this->placeholder_parser_process("start_gcode", print.config.start_gcode.value, initial_extruder_id);
|
std::string start_gcode = this->placeholder_parser_process("start_gcode", print.config().start_gcode.value, initial_extruder_id);
|
||||||
|
|
||||||
// Set bed temperature if the start G-code does not contain any bed temp control G-codes.
|
// Set bed temperature if the start G-code does not contain any bed temp control G-codes.
|
||||||
this->_print_first_layer_bed_temperature(file, print, start_gcode, initial_extruder_id, true);
|
this->_print_first_layer_bed_temperature(file, print, start_gcode, initial_extruder_id, true);
|
||||||
|
@ -616,16 +616,16 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
// Write the custom start G-code
|
// Write the custom start G-code
|
||||||
_writeln(file, start_gcode);
|
_writeln(file, start_gcode);
|
||||||
// Process filament-specific gcode in extruder order.
|
// Process filament-specific gcode in extruder order.
|
||||||
if (print.config.single_extruder_multi_material) {
|
if (print.config().single_extruder_multi_material) {
|
||||||
if (has_wipe_tower) {
|
if (has_wipe_tower) {
|
||||||
// Wipe tower will control the extruder switching, it will call the start_filament_gcode.
|
// Wipe tower will control the extruder switching, it will call the start_filament_gcode.
|
||||||
} else {
|
} else {
|
||||||
// Only initialize the initial extruder.
|
// Only initialize the initial extruder.
|
||||||
_writeln(file, this->placeholder_parser_process("start_filament_gcode", print.config.start_filament_gcode.values[initial_extruder_id], initial_extruder_id));
|
_writeln(file, this->placeholder_parser_process("start_filament_gcode", print.config().start_filament_gcode.values[initial_extruder_id], initial_extruder_id));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (const std::string &start_gcode : print.config.start_filament_gcode.values)
|
for (const std::string &start_gcode : print.config().start_filament_gcode.values)
|
||||||
_writeln(file, this->placeholder_parser_process("start_gcode", start_gcode, (unsigned int)(&start_gcode - &print.config.start_filament_gcode.values.front())));
|
_writeln(file, this->placeholder_parser_process("start_gcode", start_gcode, (unsigned int)(&start_gcode - &print.config().start_filament_gcode.values.front())));
|
||||||
}
|
}
|
||||||
this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, true);
|
this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, true);
|
||||||
print.throw_if_canceled();
|
print.throw_if_canceled();
|
||||||
|
@ -634,12 +634,12 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
_write(file, this->preamble());
|
_write(file, this->preamble());
|
||||||
|
|
||||||
// Initialize a motion planner for object-to-object travel moves.
|
// Initialize a motion planner for object-to-object travel moves.
|
||||||
if (print.config.avoid_crossing_perimeters.value) {
|
if (print.config().avoid_crossing_perimeters.value) {
|
||||||
// Collect outer contours of all objects over all layers.
|
// Collect outer contours of all objects over all layers.
|
||||||
// Discard objects only containing thin walls (offset would fail on an empty polygon).
|
// Discard objects only containing thin walls (offset would fail on an empty polygon).
|
||||||
Polygons islands;
|
Polygons islands;
|
||||||
for (const PrintObject *object : print.objects)
|
for (const PrintObject *object : print.objects())
|
||||||
for (const Layer *layer : object->layers)
|
for (const Layer *layer : object->layers())
|
||||||
for (const ExPolygon &expoly : layer->slices.expolygons)
|
for (const ExPolygon &expoly : layer->slices.expolygons)
|
||||||
for (const Point © : object->_shifted_copies) {
|
for (const Point © : object->_shifted_copies) {
|
||||||
islands.emplace_back(expoly.contour);
|
islands.emplace_back(expoly.contour);
|
||||||
|
@ -651,16 +651,16 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate wiping points if needed
|
// Calculate wiping points if needed
|
||||||
if (print.config.ooze_prevention.value && ! print.config.single_extruder_multi_material) {
|
if (print.config().ooze_prevention.value && ! print.config().single_extruder_multi_material) {
|
||||||
Points skirt_points;
|
Points skirt_points;
|
||||||
for (const ExtrusionEntity *ee : print.skirt.entities)
|
for (const ExtrusionEntity *ee : print.skirt().entities)
|
||||||
for (const ExtrusionPath &path : dynamic_cast<const ExtrusionLoop*>(ee)->paths)
|
for (const ExtrusionPath &path : dynamic_cast<const ExtrusionLoop*>(ee)->paths)
|
||||||
append(skirt_points, path.polyline.points);
|
append(skirt_points, path.polyline.points);
|
||||||
if (! skirt_points.empty()) {
|
if (! skirt_points.empty()) {
|
||||||
Polygon outer_skirt = Slic3r::Geometry::convex_hull(skirt_points);
|
Polygon outer_skirt = Slic3r::Geometry::convex_hull(skirt_points);
|
||||||
Polygons skirts;
|
Polygons skirts;
|
||||||
for (unsigned int extruder_id : print.extruders()) {
|
for (unsigned int extruder_id : print.extruders()) {
|
||||||
const Pointf &extruder_offset = print.config.extruder_offset.get_at(extruder_id);
|
const Pointf &extruder_offset = print.config().extruder_offset.get_at(extruder_id);
|
||||||
Polygon s(outer_skirt);
|
Polygon s(outer_skirt);
|
||||||
s.translate(-scale_(extruder_offset.x), -scale_(extruder_offset.y));
|
s.translate(-scale_(extruder_offset.x), -scale_(extruder_offset.y));
|
||||||
skirts.emplace_back(std::move(s));
|
skirts.emplace_back(std::move(s));
|
||||||
|
@ -685,10 +685,10 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
_write(file, this->set_extruder(initial_extruder_id));
|
_write(file, this->set_extruder(initial_extruder_id));
|
||||||
|
|
||||||
// Do all objects for each layer.
|
// Do all objects for each layer.
|
||||||
if (print.config.complete_objects.value) {
|
if (print.config().complete_objects.value) {
|
||||||
// Print objects from the smallest to the tallest to avoid collisions
|
// Print objects from the smallest to the tallest to avoid collisions
|
||||||
// when moving onto next object starting point.
|
// when moving onto next object starting point.
|
||||||
std::vector<PrintObject*> objects(print.objects);
|
std::vector<PrintObject*> objects(print.objects());
|
||||||
std::sort(objects.begin(), objects.end(), [](const PrintObject* po1, const PrintObject* po2) { return po1->size.z < po2->size.z; });
|
std::sort(objects.begin(), objects.end(), [](const PrintObject* po1, const PrintObject* po2) { return po1->size.z < po2->size.z; });
|
||||||
size_t finished_objects = 0;
|
size_t finished_objects = 0;
|
||||||
for (size_t object_id = initial_print_object_id; object_id < objects.size(); ++ object_id) {
|
for (size_t object_id = initial_print_object_id; object_id < objects.size(); ++ object_id) {
|
||||||
|
@ -722,7 +722,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
// another one, set first layer temperatures. This happens before the Z move
|
// another one, set first layer temperatures. This happens before the Z move
|
||||||
// is triggered, so machine has more time to reach such temperatures.
|
// is triggered, so machine has more time to reach such temperatures.
|
||||||
m_placeholder_parser.set("current_object_idx", int(finished_objects));
|
m_placeholder_parser.set("current_object_idx", int(finished_objects));
|
||||||
std::string between_objects_gcode = this->placeholder_parser_process("between_objects_gcode", print.config.between_objects_gcode.value, initial_extruder_id);
|
std::string between_objects_gcode = this->placeholder_parser_process("between_objects_gcode", print.config().between_objects_gcode.value, initial_extruder_id);
|
||||||
// Set first layer bed and extruder temperatures, don't wait for it to reach the temperature.
|
// Set first layer bed and extruder temperatures, don't wait for it to reach the temperature.
|
||||||
this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false);
|
this->_print_first_layer_bed_temperature(file, print, between_objects_gcode, initial_extruder_id, false);
|
||||||
this->_print_first_layer_extruder_temperatures(file, print, between_objects_gcode, initial_extruder_id, false);
|
this->_print_first_layer_extruder_temperatures(file, print, between_objects_gcode, initial_extruder_id, false);
|
||||||
|
@ -751,7 +751,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
// Order objects using a nearest neighbor search.
|
// Order objects using a nearest neighbor search.
|
||||||
std::vector<size_t> object_indices;
|
std::vector<size_t> object_indices;
|
||||||
Points object_reference_points;
|
Points object_reference_points;
|
||||||
for (PrintObject *object : print.objects)
|
for (PrintObject *object : print.objects())
|
||||||
object_reference_points.push_back(object->_shifted_copies.front());
|
object_reference_points.push_back(object->_shifted_copies.front());
|
||||||
Slic3r::Geometry::chained_path(object_reference_points, object_indices);
|
Slic3r::Geometry::chained_path(object_reference_points, object_indices);
|
||||||
// Sort layers by Z.
|
// Sort layers by Z.
|
||||||
|
@ -759,13 +759,13 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);
|
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);
|
||||||
// Prusa Multi-Material wipe tower.
|
// Prusa Multi-Material wipe tower.
|
||||||
if (has_wipe_tower && ! layers_to_print.empty()) {
|
if (has_wipe_tower && ! layers_to_print.empty()) {
|
||||||
m_wipe_tower.reset(new WipeTowerIntegration(print.config, *print.m_wipe_tower_priming.get(), print.m_wipe_tower_tool_changes, *print.m_wipe_tower_final_purge.get()));
|
m_wipe_tower.reset(new WipeTowerIntegration(print.config(), *print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()));
|
||||||
_write(file, m_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height"));
|
_write(file, m_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height"));
|
||||||
_write(file, m_wipe_tower->prime(*this));
|
_write(file, m_wipe_tower->prime(*this));
|
||||||
// Verify, whether the print overaps the priming extrusions.
|
// Verify, whether the print overaps the priming extrusions.
|
||||||
BoundingBoxf bbox_print(get_print_extrusions_extents(print));
|
BoundingBoxf bbox_print(get_print_extrusions_extents(print));
|
||||||
coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON;
|
coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON;
|
||||||
for (const PrintObject *print_object : print.objects)
|
for (const PrintObject *print_object : print.objects())
|
||||||
bbox_print.merge(get_print_object_extrusions_extents(*print_object, twolayers_printz));
|
bbox_print.merge(get_print_object_extrusions_extents(*print_object, twolayers_printz));
|
||||||
bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz));
|
bbox_print.merge(get_wipe_tower_extrusions_extents(print, twolayers_printz));
|
||||||
BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print));
|
BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print));
|
||||||
|
@ -813,14 +813,14 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process filament-specific gcode in extruder order.
|
// Process filament-specific gcode in extruder order.
|
||||||
if (print.config.single_extruder_multi_material) {
|
if (print.config().single_extruder_multi_material) {
|
||||||
// Process the end_filament_gcode for the active filament only.
|
// Process the end_filament_gcode for the active filament only.
|
||||||
_writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config.end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id()));
|
_writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(m_writer.extruder()->id()), m_writer.extruder()->id()));
|
||||||
} else {
|
} else {
|
||||||
for (const std::string &end_gcode : print.config.end_filament_gcode.values)
|
for (const std::string &end_gcode : print.config().end_filament_gcode.values)
|
||||||
_writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config.end_filament_gcode.values.front())));
|
_writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, (unsigned int)(&end_gcode - &print.config().end_filament_gcode.values.front())));
|
||||||
}
|
}
|
||||||
_writeln(file, this->placeholder_parser_process("end_gcode", print.config.end_gcode, m_writer.extruder()->id()));
|
_writeln(file, this->placeholder_parser_process("end_gcode", print.config().end_gcode, m_writer.extruder()->id()));
|
||||||
_write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
|
_write(file, m_writer.update_progress(m_layer_count, m_layer_count, true)); // 100%
|
||||||
_write(file, m_writer.postamble());
|
_write(file, m_writer.postamble());
|
||||||
print.throw_if_canceled();
|
print.throw_if_canceled();
|
||||||
|
@ -829,31 +829,27 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
||||||
m_time_estimator.calculate_time();
|
m_time_estimator.calculate_time();
|
||||||
|
|
||||||
// Get filament stats.
|
// Get filament stats.
|
||||||
print.filament_stats.clear();
|
print.m_print_statistics.clear();
|
||||||
print.total_used_filament = 0.;
|
print.m_print_statistics.estimated_print_time = m_time_estimator.get_time_hms();
|
||||||
print.total_extruded_volume = 0.;
|
|
||||||
print.total_weight = 0.;
|
|
||||||
print.total_cost = 0.;
|
|
||||||
print.estimated_print_time = m_time_estimator.get_time_hms();
|
|
||||||
for (const Extruder &extruder : m_writer.extruders()) {
|
for (const Extruder &extruder : m_writer.extruders()) {
|
||||||
double used_filament = extruder.used_filament();
|
double used_filament = extruder.used_filament();
|
||||||
double extruded_volume = extruder.extruded_volume();
|
double extruded_volume = extruder.extruded_volume();
|
||||||
double filament_weight = extruded_volume * extruder.filament_density() * 0.001;
|
double filament_weight = extruded_volume * extruder.filament_density() * 0.001;
|
||||||
double filament_cost = filament_weight * extruder.filament_cost() * 0.001;
|
double filament_cost = filament_weight * extruder.filament_cost() * 0.001;
|
||||||
print.filament_stats.insert(std::pair<size_t,float>(extruder.id(), used_filament));
|
print.m_print_statistics.filament_stats.insert(std::pair<size_t,float>(extruder.id(), used_filament));
|
||||||
_write_format(file, "; filament used = %.1lfmm (%.1lfcm3)\n", used_filament, extruded_volume * 0.001);
|
_write_format(file, "; filament used = %.1lfmm (%.1lfcm3)\n", used_filament, extruded_volume * 0.001);
|
||||||
if (filament_weight > 0.) {
|
if (filament_weight > 0.) {
|
||||||
print.total_weight = print.total_weight + filament_weight;
|
print.m_print_statistics.total_weight = print.m_print_statistics.total_weight + filament_weight;
|
||||||
_write_format(file, "; filament used = %.1lf\n", filament_weight);
|
_write_format(file, "; filament used = %.1lf\n", filament_weight);
|
||||||
if (filament_cost > 0.) {
|
if (filament_cost > 0.) {
|
||||||
print.total_cost = print.total_cost + filament_cost;
|
print.m_print_statistics.total_cost = print.m_print_statistics.total_cost + filament_cost;
|
||||||
_write_format(file, "; filament cost = %.1lf\n", filament_cost);
|
_write_format(file, "; filament cost = %.1lf\n", filament_cost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print.total_used_filament = print.total_used_filament + used_filament;
|
print.m_print_statistics.total_used_filament = print.m_print_statistics.total_used_filament + used_filament;
|
||||||
print.total_extruded_volume = print.total_extruded_volume + extruded_volume;
|
print.m_print_statistics.total_extruded_volume = print.m_print_statistics.total_extruded_volume + extruded_volume;
|
||||||
}
|
}
|
||||||
_write_format(file, "; total filament cost = %.1lf\n", print.total_cost);
|
_write_format(file, "; total filament cost = %.1lf\n", print.m_print_statistics.total_cost);
|
||||||
_write_format(file, "; estimated printing time = %s\n", m_time_estimator.get_time_hms().c_str());
|
_write_format(file, "; estimated printing time = %s\n", m_time_estimator.get_time_hms().c_str());
|
||||||
|
|
||||||
// Append full config.
|
// Append full config.
|
||||||
|
@ -879,7 +875,7 @@ std::string GCode::placeholder_parser_process(const std::string &name, const std
|
||||||
return m_placeholder_parser.process(templ, current_extruder_id, config_override);
|
return m_placeholder_parser.process(templ, current_extruder_id, config_override);
|
||||||
} catch (std::runtime_error &err) {
|
} catch (std::runtime_error &err) {
|
||||||
// Collect the names of failed template substitutions for error reporting.
|
// Collect the names of failed template substitutions for error reporting.
|
||||||
this->m_placeholder_parser_failed_templates.insert(name);
|
m_placeholder_parser_failed_templates.insert(name);
|
||||||
// Insert the macro error message into the G-code.
|
// Insert the macro error message into the G-code.
|
||||||
return
|
return
|
||||||
std::string("\n!!!!! Failed to process the custom G-code template ") + name + "\n" +
|
std::string("\n!!!!! Failed to process the custom G-code template ") + name + "\n" +
|
||||||
|
@ -949,7 +945,7 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc
|
||||||
void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait)
|
void GCode::_print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait)
|
||||||
{
|
{
|
||||||
// Initial bed temperature based on the first extruder.
|
// Initial bed temperature based on the first extruder.
|
||||||
int temp = print.config.first_layer_bed_temperature.get_at(first_printing_extruder_id);
|
int temp = print.config().first_layer_bed_temperature.get_at(first_printing_extruder_id);
|
||||||
// Is the bed temperature set by the provided custom G-code?
|
// Is the bed temperature set by the provided custom G-code?
|
||||||
int temp_by_gcode = -1;
|
int temp_by_gcode = -1;
|
||||||
bool temp_set_by_gcode = custom_gcode_sets_temperature(gcode, 140, 190, temp_by_gcode);
|
bool temp_set_by_gcode = custom_gcode_sets_temperature(gcode, 140, 190, temp_by_gcode);
|
||||||
|
@ -972,23 +968,23 @@ void GCode::_print_first_layer_extruder_temperatures(FILE *file, Print &print, c
|
||||||
int temp_by_gcode = -1;
|
int temp_by_gcode = -1;
|
||||||
if (custom_gcode_sets_temperature(gcode, 104, 109, temp_by_gcode)) {
|
if (custom_gcode_sets_temperature(gcode, 104, 109, temp_by_gcode)) {
|
||||||
// Set the extruder temperature at m_writer, but throw away the generated G-code as it will be written with the custom G-code.
|
// Set the extruder temperature at m_writer, but throw away the generated G-code as it will be written with the custom G-code.
|
||||||
int temp = print.config.first_layer_temperature.get_at(first_printing_extruder_id);
|
int temp = print.config().first_layer_temperature.get_at(first_printing_extruder_id);
|
||||||
if (temp_by_gcode >= 0 && temp_by_gcode < 1000)
|
if (temp_by_gcode >= 0 && temp_by_gcode < 1000)
|
||||||
temp = temp_by_gcode;
|
temp = temp_by_gcode;
|
||||||
m_writer.set_temperature(temp_by_gcode, wait, first_printing_extruder_id);
|
m_writer.set_temperature(temp_by_gcode, wait, first_printing_extruder_id);
|
||||||
} else {
|
} else {
|
||||||
// Custom G-code does not set the extruder temperature. Do it now.
|
// Custom G-code does not set the extruder temperature. Do it now.
|
||||||
if (print.config.single_extruder_multi_material.value) {
|
if (print.config().single_extruder_multi_material.value) {
|
||||||
// Set temperature of the first printing extruder only.
|
// Set temperature of the first printing extruder only.
|
||||||
int temp = print.config.first_layer_temperature.get_at(first_printing_extruder_id);
|
int temp = print.config().first_layer_temperature.get_at(first_printing_extruder_id);
|
||||||
if (temp > 0)
|
if (temp > 0)
|
||||||
_write(file, m_writer.set_temperature(temp, wait, first_printing_extruder_id));
|
_write(file, m_writer.set_temperature(temp, wait, first_printing_extruder_id));
|
||||||
} else {
|
} else {
|
||||||
// Set temperatures of all the printing extruders.
|
// Set temperatures of all the printing extruders.
|
||||||
for (unsigned int tool_id : print.extruders()) {
|
for (unsigned int tool_id : print.extruders()) {
|
||||||
int temp = print.config.first_layer_temperature.get_at(tool_id);
|
int temp = print.config().first_layer_temperature.get_at(tool_id);
|
||||||
if (print.config.ooze_prevention.value)
|
if (print.config().ooze_prevention.value)
|
||||||
temp += print.config.standby_temperature_delta.value;
|
temp += print.config().standby_temperature_delta.value;
|
||||||
if (temp > 0)
|
if (temp > 0)
|
||||||
_write(file, m_writer.set_temperature(temp, wait, tool_id));
|
_write(file, m_writer.set_temperature(temp, wait, tool_id));
|
||||||
}
|
}
|
||||||
|
@ -1061,15 +1057,15 @@ void GCode::process_layer(
|
||||||
unsigned int first_extruder_id = layer_tools.extruders.front();
|
unsigned int first_extruder_id = layer_tools.extruders.front();
|
||||||
|
|
||||||
// Initialize config with the 1st object to be printed at this layer.
|
// Initialize config with the 1st object to be printed at this layer.
|
||||||
m_config.apply(layer.object()->config, true);
|
m_config.apply(layer.object()->config(), true);
|
||||||
|
|
||||||
// Check whether it is possible to apply the spiral vase logic for this layer.
|
// Check whether it is possible to apply the spiral vase logic for this layer.
|
||||||
// Just a reminder: A spiral vase mode is allowed for a single object, single material print only.
|
// Just a reminder: A spiral vase mode is allowed for a single object, single material print only.
|
||||||
if (m_spiral_vase && layers.size() == 1 && support_layer == nullptr) {
|
if (m_spiral_vase && layers.size() == 1 && support_layer == nullptr) {
|
||||||
bool enable = (layer.id() > 0 || print.config.brim_width.value == 0.) && (layer.id() >= print.config.skirt_height.value && ! print.has_infinite_skirt());
|
bool enable = (layer.id() > 0 || print.config().brim_width.value == 0.) && (layer.id() >= print.config().skirt_height.value && ! print.has_infinite_skirt());
|
||||||
if (enable) {
|
if (enable) {
|
||||||
for (const LayerRegion *layer_region : layer.regions)
|
for (const LayerRegion *layer_region : layer.regions())
|
||||||
if (layer_region->region()->config.bottom_solid_layers.value > layer.id() ||
|
if (layer_region->region()->config().bottom_solid_layers.value > layer.id() ||
|
||||||
layer_region->perimeters.items_count() > 1 ||
|
layer_region->perimeters.items_count() > 1 ||
|
||||||
layer_region->fills.items_count() > 0) {
|
layer_region->fills.items_count() > 0) {
|
||||||
enable = false;
|
enable = false;
|
||||||
|
@ -1084,22 +1080,22 @@ void GCode::process_layer(
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
|
|
||||||
// Set new layer - this will change Z and force a retraction if retract_layer_change is enabled.
|
// Set new layer - this will change Z and force a retraction if retract_layer_change is enabled.
|
||||||
if (! print.config.before_layer_gcode.value.empty()) {
|
if (! print.config().before_layer_gcode.value.empty()) {
|
||||||
DynamicConfig config;
|
DynamicConfig config;
|
||||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1));
|
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1));
|
||||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||||
gcode += this->placeholder_parser_process("before_layer_gcode",
|
gcode += this->placeholder_parser_process("before_layer_gcode",
|
||||||
print.config.before_layer_gcode.value, m_writer.extruder()->id(), &config)
|
print.config().before_layer_gcode.value, m_writer.extruder()->id(), &config)
|
||||||
+ "\n";
|
+ "\n";
|
||||||
}
|
}
|
||||||
gcode += this->change_layer(print_z); // this will increase m_layer_index
|
gcode += this->change_layer(print_z); // this will increase m_layer_index
|
||||||
m_layer = &layer;
|
m_layer = &layer;
|
||||||
if (! print.config.layer_gcode.value.empty()) {
|
if (! print.config().layer_gcode.value.empty()) {
|
||||||
DynamicConfig config;
|
DynamicConfig config;
|
||||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||||
gcode += this->placeholder_parser_process("layer_gcode",
|
gcode += this->placeholder_parser_process("layer_gcode",
|
||||||
print.config.layer_gcode.value, m_writer.extruder()->id(), &config)
|
print.config().layer_gcode.value, m_writer.extruder()->id(), &config)
|
||||||
+ "\n";
|
+ "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1107,14 +1103,14 @@ void GCode::process_layer(
|
||||||
// Transition from 1st to 2nd layer. Adjust nozzle temperatures as prescribed by the nozzle dependent
|
// Transition from 1st to 2nd layer. Adjust nozzle temperatures as prescribed by the nozzle dependent
|
||||||
// first_layer_temperature vs. temperature settings.
|
// first_layer_temperature vs. temperature settings.
|
||||||
for (const Extruder &extruder : m_writer.extruders()) {
|
for (const Extruder &extruder : m_writer.extruders()) {
|
||||||
if (print.config.single_extruder_multi_material.value && extruder.id() != m_writer.extruder()->id())
|
if (print.config().single_extruder_multi_material.value && extruder.id() != m_writer.extruder()->id())
|
||||||
// In single extruder multi material mode, set the temperature for the current extruder only.
|
// In single extruder multi material mode, set the temperature for the current extruder only.
|
||||||
continue;
|
continue;
|
||||||
int temperature = print.config.temperature.get_at(extruder.id());
|
int temperature = print.config().temperature.get_at(extruder.id());
|
||||||
if (temperature > 0 && temperature != print.config.first_layer_temperature.get_at(extruder.id()))
|
if (temperature > 0 && temperature != print.config().first_layer_temperature.get_at(extruder.id()))
|
||||||
gcode += m_writer.set_temperature(temperature, false, extruder.id());
|
gcode += m_writer.set_temperature(temperature, false, extruder.id());
|
||||||
}
|
}
|
||||||
gcode += m_writer.set_bed_temperature(print.config.bed_temperature.get_at(first_extruder_id));
|
gcode += m_writer.set_bed_temperature(print.config().bed_temperature.get_at(first_extruder_id));
|
||||||
// Mark the temperature transition from 1st to 2nd layer to be finished.
|
// Mark the temperature transition from 1st to 2nd layer to be finished.
|
||||||
m_second_layer_things_done = true;
|
m_second_layer_things_done = true;
|
||||||
}
|
}
|
||||||
|
@ -1122,9 +1118,9 @@ void GCode::process_layer(
|
||||||
// Extrude skirt at the print_z of the raft layers and normal object layers
|
// Extrude skirt at the print_z of the raft layers and normal object layers
|
||||||
// not at the print_z of the interlaced support material layers.
|
// not at the print_z of the interlaced support material layers.
|
||||||
bool extrude_skirt =
|
bool extrude_skirt =
|
||||||
! print.skirt.entities.empty() &&
|
! print.skirt().entities.empty() &&
|
||||||
// Not enough skirt layers printed yet.
|
// Not enough skirt layers printed yet.
|
||||||
(m_skirt_done.size() < print.config.skirt_height.value || print.has_infinite_skirt()) &&
|
(m_skirt_done.size() < print.config().skirt_height.value || print.has_infinite_skirt()) &&
|
||||||
// This print_z has not been extruded yet
|
// This print_z has not been extruded yet
|
||||||
(m_skirt_done.empty() ? 0. : m_skirt_done.back()) < print_z - EPSILON &&
|
(m_skirt_done.empty() ? 0. : m_skirt_done.back()) < print_z - EPSILON &&
|
||||||
// and this layer is the 1st layer, or it is an object layer, or it is a raft layer.
|
// and this layer is the 1st layer, or it is an object layer, or it is a raft layer.
|
||||||
|
@ -1146,7 +1142,7 @@ void GCode::process_layer(
|
||||||
extruder_ids.front() = first_extruder_id;
|
extruder_ids.front() = first_extruder_id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
size_t n_loops = print.skirt.entities.size();
|
size_t n_loops = print.skirt().entities.size();
|
||||||
if (n_loops <= extruder_ids.size()) {
|
if (n_loops <= extruder_ids.size()) {
|
||||||
for (size_t i = 0; i < n_loops; ++i)
|
for (size_t i = 0; i < n_loops; ++i)
|
||||||
skirt_loops_per_extruder[extruder_ids[i]] = std::pair<size_t, size_t>(i, i + 1);
|
skirt_loops_per_extruder[extruder_ids[i]] = std::pair<size_t, size_t>(i, i + 1);
|
||||||
|
@ -1165,7 +1161,7 @@ void GCode::process_layer(
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
// Extrude all skirts with the current extruder.
|
// Extrude all skirts with the current extruder.
|
||||||
skirt_loops_per_extruder[first_extruder_id] = std::pair<size_t, size_t>(0, print.config.skirts.value);
|
skirt_loops_per_extruder[first_extruder_id] = std::pair<size_t, size_t>(0, print.config().skirts.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group extrusions by an extruder, then by an object, an island and a region.
|
// Group extrusions by an extruder, then by an object, an island and a region.
|
||||||
|
@ -1180,22 +1176,22 @@ void GCode::process_layer(
|
||||||
bool has_support = role == erMixed || role == erSupportMaterial;
|
bool has_support = role == erMixed || role == erSupportMaterial;
|
||||||
bool has_interface = role == erMixed || role == erSupportMaterialInterface;
|
bool has_interface = role == erMixed || role == erSupportMaterialInterface;
|
||||||
// Extruder ID of the support base. -1 if "don't care".
|
// Extruder ID of the support base. -1 if "don't care".
|
||||||
unsigned int support_extruder = object.config.support_material_extruder.value - 1;
|
unsigned int support_extruder = object.config().support_material_extruder.value - 1;
|
||||||
// Shall the support be printed with the active extruder, preferably with non-soluble, to avoid tool changes?
|
// Shall the support be printed with the active extruder, preferably with non-soluble, to avoid tool changes?
|
||||||
bool support_dontcare = object.config.support_material_extruder.value == 0;
|
bool support_dontcare = object.config().support_material_extruder.value == 0;
|
||||||
// Extruder ID of the support interface. -1 if "don't care".
|
// Extruder ID of the support interface. -1 if "don't care".
|
||||||
unsigned int interface_extruder = object.config.support_material_interface_extruder.value - 1;
|
unsigned int interface_extruder = object.config().support_material_interface_extruder.value - 1;
|
||||||
// Shall the support interface be printed with the active extruder, preferably with non-soluble, to avoid tool changes?
|
// Shall the support interface be printed with the active extruder, preferably with non-soluble, to avoid tool changes?
|
||||||
bool interface_dontcare = object.config.support_material_interface_extruder.value == 0;
|
bool interface_dontcare = object.config().support_material_interface_extruder.value == 0;
|
||||||
if (support_dontcare || interface_dontcare) {
|
if (support_dontcare || interface_dontcare) {
|
||||||
// Some support will be printed with "don't care" material, preferably non-soluble.
|
// Some support will be printed with "don't care" material, preferably non-soluble.
|
||||||
// Is the current extruder assigned a soluble filament?
|
// Is the current extruder assigned a soluble filament?
|
||||||
unsigned int dontcare_extruder = first_extruder_id;
|
unsigned int dontcare_extruder = first_extruder_id;
|
||||||
if (print.config.filament_soluble.get_at(dontcare_extruder)) {
|
if (print.config().filament_soluble.get_at(dontcare_extruder)) {
|
||||||
// The last extruder printed on the previous layer extrudes soluble filament.
|
// The last extruder printed on the previous layer extrudes soluble filament.
|
||||||
// Try to find a non-soluble extruder on the same layer.
|
// Try to find a non-soluble extruder on the same layer.
|
||||||
for (unsigned int extruder_id : layer_tools.extruders)
|
for (unsigned int extruder_id : layer_tools.extruders)
|
||||||
if (! print.config.filament_soluble.get_at(extruder_id)) {
|
if (! print.config().filament_soluble.get_at(extruder_id)) {
|
||||||
dontcare_extruder = extruder_id;
|
dontcare_extruder = extruder_id;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1242,11 +1238,11 @@ void GCode::process_layer(
|
||||||
layer.slices.expolygons[i].contour.contains(point);
|
layer.slices.expolygons[i].contour.contains(point);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) {
|
for (size_t region_id = 0; region_id < print.regions().size(); ++ region_id) {
|
||||||
const LayerRegion *layerm = layer.regions[region_id];
|
const LayerRegion *layerm = layer.regions()[region_id];
|
||||||
if (layerm == nullptr)
|
if (layerm == nullptr)
|
||||||
continue;
|
continue;
|
||||||
const PrintRegion ®ion = *print.regions[region_id];
|
const PrintRegion ®ion = *print.regions()[region_id];
|
||||||
|
|
||||||
// process perimeters
|
// process perimeters
|
||||||
for (const ExtrusionEntity *ee : layerm->perimeters.entities) {
|
for (const ExtrusionEntity *ee : layerm->perimeters.entities) {
|
||||||
|
@ -1258,7 +1254,7 @@ void GCode::process_layer(
|
||||||
// Init by_extruder item only if we actually use the extruder.
|
// Init by_extruder item only if we actually use the extruder.
|
||||||
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
|
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
|
||||||
by_extruder,
|
by_extruder,
|
||||||
std::max<int>(region.config.perimeter_extruder.value - 1, 0),
|
std::max<int>(region.config().perimeter_extruder.value - 1, 0),
|
||||||
&layer_to_print - layers.data(),
|
&layer_to_print - layers.data(),
|
||||||
layers.size(), n_slices+1);
|
layers.size(), n_slices+1);
|
||||||
for (size_t i = 0; i <= n_slices; ++ i)
|
for (size_t i = 0; i <= n_slices; ++ i)
|
||||||
|
@ -1267,7 +1263,7 @@ void GCode::process_layer(
|
||||||
// perimeter_coll->first_point fits inside ith slice
|
// perimeter_coll->first_point fits inside ith slice
|
||||||
point_inside_surface(i, perimeter_coll->first_point())) {
|
point_inside_surface(i, perimeter_coll->first_point())) {
|
||||||
if (islands[i].by_region.empty())
|
if (islands[i].by_region.empty())
|
||||||
islands[i].by_region.assign(print.regions.size(), ObjectByExtruder::Island::Region());
|
islands[i].by_region.assign(print.regions().size(), ObjectByExtruder::Island::Region());
|
||||||
islands[i].by_region[region_id].perimeters.append(perimeter_coll->entities);
|
islands[i].by_region[region_id].perimeters.append(perimeter_coll->entities);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1285,7 +1281,7 @@ void GCode::process_layer(
|
||||||
// This shouldn't happen but first_point() would fail.
|
// This shouldn't happen but first_point() would fail.
|
||||||
continue;
|
continue;
|
||||||
// init by_extruder item only if we actually use the extruder
|
// init by_extruder item only if we actually use the extruder
|
||||||
int extruder_id = std::max<int>(0, (is_solid_infill(fill->entities.front()->role()) ? region.config.solid_infill_extruder : region.config.infill_extruder) - 1);
|
int extruder_id = std::max<int>(0, (is_solid_infill(fill->entities.front()->role()) ? region.config().solid_infill_extruder : region.config().infill_extruder) - 1);
|
||||||
// Init by_extruder item only if we actually use the extruder.
|
// Init by_extruder item only if we actually use the extruder.
|
||||||
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
|
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
|
||||||
by_extruder,
|
by_extruder,
|
||||||
|
@ -1298,7 +1294,7 @@ void GCode::process_layer(
|
||||||
// fill->first_point fits inside ith slice
|
// fill->first_point fits inside ith slice
|
||||||
point_inside_surface(i, fill->first_point())) {
|
point_inside_surface(i, fill->first_point())) {
|
||||||
if (islands[i].by_region.empty())
|
if (islands[i].by_region.empty())
|
||||||
islands[i].by_region.assign(print.regions.size(), ObjectByExtruder::Island::Region());
|
islands[i].by_region.assign(print.regions().size(), ObjectByExtruder::Island::Region());
|
||||||
islands[i].by_region[region_id].infills.append(fill->entities);
|
islands[i].by_region[region_id].infills.append(fill->entities);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1324,7 +1320,7 @@ void GCode::process_layer(
|
||||||
Flow skirt_flow = print.skirt_flow();
|
Flow skirt_flow = print.skirt_flow();
|
||||||
for (size_t i = loops.first; i < loops.second; ++ i) {
|
for (size_t i = loops.first; i < loops.second; ++ i) {
|
||||||
// Adjust flow according to this layer's layer height.
|
// Adjust flow according to this layer's layer height.
|
||||||
ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(print.skirt.entities[i]);
|
ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(print.skirt().entities[i]);
|
||||||
Flow layer_skirt_flow(skirt_flow);
|
Flow layer_skirt_flow(skirt_flow);
|
||||||
layer_skirt_flow.height = (float)skirt_height;
|
layer_skirt_flow.height = (float)skirt_height;
|
||||||
double mm3_per_mm = layer_skirt_flow.mm3_per_mm();
|
double mm3_per_mm = layer_skirt_flow.mm3_per_mm();
|
||||||
|
@ -1345,7 +1341,7 @@ void GCode::process_layer(
|
||||||
if (! m_brim_done) {
|
if (! m_brim_done) {
|
||||||
this->set_origin(0., 0.);
|
this->set_origin(0., 0.);
|
||||||
m_avoid_crossing_perimeters.use_external_mp = true;
|
m_avoid_crossing_perimeters.use_external_mp = true;
|
||||||
for (const ExtrusionEntity *ee : print.brim.entities)
|
for (const ExtrusionEntity *ee : print.brim().entities)
|
||||||
gcode += this->extrude_loop(*dynamic_cast<const ExtrusionLoop*>(ee), "brim", m_config.support_material_speed.value);
|
gcode += this->extrude_loop(*dynamic_cast<const ExtrusionLoop*>(ee), "brim", m_config.support_material_speed.value);
|
||||||
m_brim_done = true;
|
m_brim_done = true;
|
||||||
m_avoid_crossing_perimeters.use_external_mp = false;
|
m_avoid_crossing_perimeters.use_external_mp = false;
|
||||||
|
@ -1363,7 +1359,7 @@ void GCode::process_layer(
|
||||||
// This layer is empty for this particular object, it has neither object extrusions nor support extrusions at this print_z.
|
// This layer is empty for this particular object, it has neither object extrusions nor support extrusions at this print_z.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
m_config.apply(print_object->config, true);
|
m_config.apply(print_object->config(), true);
|
||||||
m_layer = layers[layer_id].layer();
|
m_layer = layers[layer_id].layer();
|
||||||
if (m_config.avoid_crossing_perimeters)
|
if (m_config.avoid_crossing_perimeters)
|
||||||
m_avoid_crossing_perimeters.init_layer_mp(union_ex(m_layer->slices, true));
|
m_avoid_crossing_perimeters.init_layer_mp(union_ex(m_layer->slices, true));
|
||||||
|
@ -1389,7 +1385,7 @@ void GCode::process_layer(
|
||||||
m_layer = layers[layer_id].layer();
|
m_layer = layers[layer_id].layer();
|
||||||
}
|
}
|
||||||
for (const ObjectByExtruder::Island &island : object_by_extruder.islands) {
|
for (const ObjectByExtruder::Island &island : object_by_extruder.islands) {
|
||||||
if (print.config.infill_first) {
|
if (print.config().infill_first) {
|
||||||
gcode += this->extrude_infill(print, island.by_region);
|
gcode += this->extrude_infill(print, island.by_region);
|
||||||
gcode += this->extrude_perimeters(print, island.by_region, lower_layer_edge_grids[layer_id]);
|
gcode += this->extrude_perimeters(print, island.by_region, lower_layer_edge_grids[layer_id]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1430,7 +1426,7 @@ void GCode::apply_print_config(const PrintConfig &print_config)
|
||||||
|
|
||||||
void GCode::append_full_config(const Print& print, std::string& str)
|
void GCode::append_full_config(const Print& print, std::string& str)
|
||||||
{
|
{
|
||||||
const StaticPrintConfig *configs[] = { &print.config, &print.default_object_config, &print.default_region_config };
|
const StaticPrintConfig *configs[] = { &print.config(), &print.default_object_config(), &print.default_region_config() };
|
||||||
for (size_t i = 0; i < sizeof(configs) / sizeof(configs[0]); ++i) {
|
for (size_t i = 0; i < sizeof(configs) / sizeof(configs[0]); ++i) {
|
||||||
const StaticPrintConfig *cfg = configs[i];
|
const StaticPrintConfig *cfg = configs[i];
|
||||||
for (const std::string &key : cfg->keys())
|
for (const std::string &key : cfg->keys())
|
||||||
|
@ -2015,7 +2011,7 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector<Obje
|
||||||
{
|
{
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
for (const ObjectByExtruder::Island::Region ®ion : by_region) {
|
for (const ObjectByExtruder::Island::Region ®ion : by_region) {
|
||||||
m_config.apply(print.regions[®ion - &by_region.front()]->config);
|
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||||
for (ExtrusionEntity *ee : region.perimeters.entities)
|
for (ExtrusionEntity *ee : region.perimeters.entities)
|
||||||
gcode += this->extrude_entity(*ee, "perimeter", -1., &lower_layer_edge_grid);
|
gcode += this->extrude_entity(*ee, "perimeter", -1., &lower_layer_edge_grid);
|
||||||
}
|
}
|
||||||
|
@ -2027,7 +2023,7 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
|
||||||
{
|
{
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
for (const ObjectByExtruder::Island::Region ®ion : by_region) {
|
for (const ObjectByExtruder::Island::Region ®ion : by_region) {
|
||||||
m_config.apply(print.regions[®ion - &by_region.front()]->config);
|
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||||
ExtrusionEntityCollection chained = region.infills.chained_path_from(m_last_pos, false);
|
ExtrusionEntityCollection chained = region.infills.chained_path_from(m_last_pos, false);
|
||||||
for (ExtrusionEntity *fill : chained.entities) {
|
for (ExtrusionEntity *fill : chained.entities) {
|
||||||
auto *eec = dynamic_cast<ExtrusionEntityCollection*>(fill);
|
auto *eec = dynamic_cast<ExtrusionEntityCollection*>(fill);
|
||||||
|
|
|
@ -99,19 +99,19 @@ static BoundingBoxf extrusionentity_extents(const ExtrusionEntity *extrusion_ent
|
||||||
|
|
||||||
BoundingBoxf get_print_extrusions_extents(const Print &print)
|
BoundingBoxf get_print_extrusions_extents(const Print &print)
|
||||||
{
|
{
|
||||||
BoundingBoxf bbox(extrusionentity_extents(print.brim));
|
BoundingBoxf bbox(extrusionentity_extents(print.brim()));
|
||||||
bbox.merge(extrusionentity_extents(print.skirt));
|
bbox.merge(extrusionentity_extents(print.skirt()));
|
||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coordf_t max_print_z)
|
BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coordf_t max_print_z)
|
||||||
{
|
{
|
||||||
BoundingBoxf bbox;
|
BoundingBoxf bbox;
|
||||||
for (const Layer *layer : print_object.layers) {
|
for (const Layer *layer : print_object.layers()) {
|
||||||
if (layer->print_z > max_print_z)
|
if (layer->print_z > max_print_z)
|
||||||
break;
|
break;
|
||||||
BoundingBoxf bbox_this;
|
BoundingBoxf bbox_this;
|
||||||
for (const LayerRegion *layerm : layer->regions) {
|
for (const LayerRegion *layerm : layer->regions()) {
|
||||||
bbox_this.merge(extrusionentity_extents(layerm->perimeters));
|
bbox_this.merge(extrusionentity_extents(layerm->perimeters));
|
||||||
for (const ExtrusionEntity *ee : layerm->fills.entities)
|
for (const ExtrusionEntity *ee : layerm->fills.entities)
|
||||||
// fill represents infill extrusions of a single island.
|
// fill represents infill extrusions of a single island.
|
||||||
|
@ -135,7 +135,7 @@ BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object
|
||||||
BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_t max_print_z)
|
BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_t max_print_z)
|
||||||
{
|
{
|
||||||
BoundingBoxf bbox;
|
BoundingBoxf bbox;
|
||||||
for (const std::vector<WipeTower::ToolChangeResult> &tool_changes : print.m_wipe_tower_tool_changes) {
|
for (const std::vector<WipeTower::ToolChangeResult> &tool_changes : print.wipe_tower_data().tool_changes) {
|
||||||
if (! tool_changes.empty() && tool_changes.front().print_z > max_print_z)
|
if (! tool_changes.empty() && tool_changes.front().print_z > max_print_z)
|
||||||
break;
|
break;
|
||||||
for (const WipeTower::ToolChangeResult &tcr : tool_changes) {
|
for (const WipeTower::ToolChangeResult &tcr : tool_changes) {
|
||||||
|
@ -161,8 +161,8 @@ BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_
|
||||||
BoundingBoxf get_wipe_tower_priming_extrusions_extents(const Print &print)
|
BoundingBoxf get_wipe_tower_priming_extrusions_extents(const Print &print)
|
||||||
{
|
{
|
||||||
BoundingBoxf bbox;
|
BoundingBoxf bbox;
|
||||||
if (print.m_wipe_tower_priming) {
|
if (print.wipe_tower_data().priming != nullptr) {
|
||||||
const WipeTower::ToolChangeResult &tcr = *print.m_wipe_tower_priming.get();
|
const WipeTower::ToolChangeResult &tcr = *print.wipe_tower_data().priming;
|
||||||
for (size_t i = 1; i < tcr.extrusions.size(); ++ i) {
|
for (size_t i = 1; i < tcr.extrusions.size(); ++ i) {
|
||||||
const WipeTower::Extrusion &e = tcr.extrusions[i];
|
const WipeTower::Extrusion &e = tcr.extrusions[i];
|
||||||
if (e.width > 0) {
|
if (e.width > 0) {
|
||||||
|
|
|
@ -16,19 +16,19 @@
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
// For the use case when each object is printed separately
|
// For the use case when each object is printed separately
|
||||||
// (print.config.complete_objects is true).
|
// (print.config().complete_objects is true).
|
||||||
ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material)
|
ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material)
|
||||||
{
|
{
|
||||||
if (object.layers.empty())
|
if (object.layers().empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Initialize the print layers for just a single object.
|
// Initialize the print layers for just a single object.
|
||||||
{
|
{
|
||||||
std::vector<coordf_t> zs;
|
std::vector<coordf_t> zs;
|
||||||
zs.reserve(zs.size() + object.layers.size() + object.support_layers.size());
|
zs.reserve(zs.size() + object.layers().size() + object.support_layers().size());
|
||||||
for (auto layer : object.layers)
|
for (auto layer : object.layers())
|
||||||
zs.emplace_back(layer->print_z);
|
zs.emplace_back(layer->print_z);
|
||||||
for (auto layer : object.support_layers)
|
for (auto layer : object.support_layers())
|
||||||
zs.emplace_back(layer->print_z);
|
zs.emplace_back(layer->print_z);
|
||||||
this->initialize_layers(zs);
|
this->initialize_layers(zs);
|
||||||
}
|
}
|
||||||
|
@ -39,39 +39,39 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
|
||||||
// Reorder the extruders to minimize tool switches.
|
// Reorder the extruders to minimize tool switches.
|
||||||
this->reorder_extruders(first_extruder);
|
this->reorder_extruders(first_extruder);
|
||||||
|
|
||||||
this->fill_wipe_tower_partitions(object.print()->config, object.layers.front()->print_z - object.layers.front()->height);
|
this->fill_wipe_tower_partitions(object.print()->config(), object.layers().front()->print_z - object.layers().front()->height);
|
||||||
|
|
||||||
this->collect_extruder_statistics(prime_multi_material);
|
this->collect_extruder_statistics(prime_multi_material);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For the use case when all objects are printed at once.
|
// For the use case when all objects are printed at once.
|
||||||
// (print.config.complete_objects is false).
|
// (print.config().complete_objects is false).
|
||||||
ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material)
|
ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool prime_multi_material)
|
||||||
{
|
{
|
||||||
// Initialize the print layers for all objects and all layers.
|
// Initialize the print layers for all objects and all layers.
|
||||||
coordf_t object_bottom_z = 0.;
|
coordf_t object_bottom_z = 0.;
|
||||||
{
|
{
|
||||||
std::vector<coordf_t> zs;
|
std::vector<coordf_t> zs;
|
||||||
for (auto object : print.objects) {
|
for (auto object : print.objects()) {
|
||||||
zs.reserve(zs.size() + object->layers.size() + object->support_layers.size());
|
zs.reserve(zs.size() + object->layers().size() + object->support_layers().size());
|
||||||
for (auto layer : object->layers)
|
for (auto layer : object->layers())
|
||||||
zs.emplace_back(layer->print_z);
|
zs.emplace_back(layer->print_z);
|
||||||
for (auto layer : object->support_layers)
|
for (auto layer : object->support_layers())
|
||||||
zs.emplace_back(layer->print_z);
|
zs.emplace_back(layer->print_z);
|
||||||
if (! object->layers.empty())
|
if (! object->layers().empty())
|
||||||
object_bottom_z = object->layers.front()->print_z - object->layers.front()->height;
|
object_bottom_z = object->layers().front()->print_z - object->layers().front()->height;
|
||||||
}
|
}
|
||||||
this->initialize_layers(zs);
|
this->initialize_layers(zs);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect extruders reuqired to print the layers.
|
// Collect extruders reuqired to print the layers.
|
||||||
for (auto object : print.objects)
|
for (auto object : print.objects())
|
||||||
this->collect_extruders(*object);
|
this->collect_extruders(*object);
|
||||||
|
|
||||||
// Reorder the extruders to minimize tool switches.
|
// Reorder the extruders to minimize tool switches.
|
||||||
this->reorder_extruders(first_extruder);
|
this->reorder_extruders(first_extruder);
|
||||||
|
|
||||||
this->fill_wipe_tower_partitions(print.config, object_bottom_z);
|
this->fill_wipe_tower_partitions(print.config(), object_bottom_z);
|
||||||
|
|
||||||
this->collect_extruder_statistics(prime_multi_material);
|
this->collect_extruder_statistics(prime_multi_material);
|
||||||
}
|
}
|
||||||
|
@ -111,13 +111,13 @@ void ToolOrdering::initialize_layers(std::vector<coordf_t> &zs)
|
||||||
void ToolOrdering::collect_extruders(const PrintObject &object)
|
void ToolOrdering::collect_extruders(const PrintObject &object)
|
||||||
{
|
{
|
||||||
// Collect the support extruders.
|
// Collect the support extruders.
|
||||||
for (auto support_layer : object.support_layers) {
|
for (auto support_layer : object.support_layers()) {
|
||||||
LayerTools &layer_tools = this->tools_for_layer(support_layer->print_z);
|
LayerTools &layer_tools = this->tools_for_layer(support_layer->print_z);
|
||||||
ExtrusionRole role = support_layer->support_fills.role();
|
ExtrusionRole role = support_layer->support_fills.role();
|
||||||
bool has_support = role == erMixed || role == erSupportMaterial;
|
bool has_support = role == erMixed || role == erSupportMaterial;
|
||||||
bool has_interface = role == erMixed || role == erSupportMaterialInterface;
|
bool has_interface = role == erMixed || role == erSupportMaterialInterface;
|
||||||
unsigned int extruder_support = object.config.support_material_extruder.value;
|
unsigned int extruder_support = object.config().support_material_extruder.value;
|
||||||
unsigned int extruder_interface = object.config.support_material_interface_extruder.value;
|
unsigned int extruder_interface = object.config().support_material_interface_extruder.value;
|
||||||
if (has_support)
|
if (has_support)
|
||||||
layer_tools.extruders.push_back(extruder_support);
|
layer_tools.extruders.push_back(extruder_support);
|
||||||
if (has_interface)
|
if (has_interface)
|
||||||
|
@ -126,16 +126,16 @@ void ToolOrdering::collect_extruders(const PrintObject &object)
|
||||||
layer_tools.has_support = true;
|
layer_tools.has_support = true;
|
||||||
}
|
}
|
||||||
// Collect the object extruders.
|
// Collect the object extruders.
|
||||||
for (auto layer : object.layers) {
|
for (auto layer : object.layers()) {
|
||||||
LayerTools &layer_tools = this->tools_for_layer(layer->print_z);
|
LayerTools &layer_tools = this->tools_for_layer(layer->print_z);
|
||||||
// What extruders are required to print this object layer?
|
// What extruders are required to print this object layer?
|
||||||
for (size_t region_id = 0; region_id < object.print()->regions.size(); ++ region_id) {
|
for (size_t region_id = 0; region_id < object.print()->regions().size(); ++ region_id) {
|
||||||
const LayerRegion *layerm = (region_id < layer->regions.size()) ? layer->regions[region_id] : nullptr;
|
const LayerRegion *layerm = (region_id < layer->regions().size()) ? layer->regions()[region_id] : nullptr;
|
||||||
if (layerm == nullptr)
|
if (layerm == nullptr)
|
||||||
continue;
|
continue;
|
||||||
const PrintRegion ®ion = *object.print()->regions[region_id];
|
const PrintRegion ®ion = *object.print()->regions()[region_id];
|
||||||
if (! layerm->perimeters.entities.empty()) {
|
if (! layerm->perimeters.entities.empty()) {
|
||||||
layer_tools.extruders.push_back(region.config.perimeter_extruder.value);
|
layer_tools.extruders.push_back(region.config().perimeter_extruder.value);
|
||||||
layer_tools.has_object = true;
|
layer_tools.has_object = true;
|
||||||
}
|
}
|
||||||
bool has_infill = false;
|
bool has_infill = false;
|
||||||
|
@ -150,9 +150,9 @@ void ToolOrdering::collect_extruders(const PrintObject &object)
|
||||||
has_infill = true;
|
has_infill = true;
|
||||||
}
|
}
|
||||||
if (has_solid_infill)
|
if (has_solid_infill)
|
||||||
layer_tools.extruders.push_back(region.config.solid_infill_extruder);
|
layer_tools.extruders.push_back(region.config().solid_infill_extruder);
|
||||||
if (has_infill)
|
if (has_infill)
|
||||||
layer_tools.extruders.push_back(region.config.infill_extruder);
|
layer_tools.extruders.push_back(region.config().infill_extruder);
|
||||||
if (has_solid_infill || has_infill)
|
if (has_solid_infill || has_infill)
|
||||||
layer_tools.has_object = true;
|
layer_tools.has_object = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -396,8 +396,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
|
||||||
}
|
}
|
||||||
|
|
||||||
this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false);
|
this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false);
|
||||||
this->m_num_layer_changes = 0;
|
m_num_layer_changes = 0;
|
||||||
this->m_current_tool = tools.front();
|
m_current_tool = tools.front();
|
||||||
|
|
||||||
// The Prusa i3 MK2 has a working space of [0, -2.2] to [250, 210].
|
// The Prusa i3 MK2 has a working space of [0, -2.2] to [250, 210].
|
||||||
// Due to the XYZ calibration, this working space may shrink slightly from all directions,
|
// Due to the XYZ calibration, this working space may shrink slightly from all directions,
|
||||||
|
@ -439,9 +439,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
|
||||||
if (last_wipe_inside_wipe_tower) {
|
if (last_wipe_inside_wipe_tower) {
|
||||||
// Shrink the last wipe area to the area of the other purge areas,
|
// Shrink the last wipe area to the area of the other purge areas,
|
||||||
// remember the last initial wipe width to be purged into the 1st layer of the wipe tower.
|
// remember the last initial wipe width to be purged into the 1st layer of the wipe tower.
|
||||||
this->m_initial_extra_wipe = std::max(0.f, wipe_area - (y_end + 0.5f * 0.85f * m_perimeter_width - cleaning_box.ld.y));
|
m_initial_extra_wipe = std::max(0.f, wipe_area - (y_end + 0.5f * 0.85f * m_perimeter_width - cleaning_box.ld.y));
|
||||||
cleaning_box.lu.y -= this->m_initial_extra_wipe;
|
cleaning_box.lu.y -= m_initial_extra_wipe;
|
||||||
cleaning_box.ru.y -= this->m_initial_extra_wipe;
|
cleaning_box.ru.y -= m_initial_extra_wipe;
|
||||||
}
|
}
|
||||||
toolchange_Wipe(writer, cleaning_box, false);
|
toolchange_Wipe(writer, cleaning_box, false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -471,8 +471,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
|
||||||
m_idx_tool_change_in_layer = (unsigned int)(-1);
|
m_idx_tool_change_in_layer = (unsigned int)(-1);
|
||||||
|
|
||||||
ToolChangeResult result;
|
ToolChangeResult result;
|
||||||
result.print_z = this->m_z_pos;
|
result.print_z = m_z_pos;
|
||||||
result.layer_height = this->m_layer_height;
|
result.layer_height = m_layer_height;
|
||||||
result.gcode = writer.gcode();
|
result.gcode = writer.gcode();
|
||||||
result.elapsed_time = writer.elapsed_time();
|
result.elapsed_time = writer.elapsed_time();
|
||||||
result.extrusions = writer.extrusions();
|
result.extrusions = writer.extrusions();
|
||||||
|
@ -612,8 +612,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolChangeResult result;
|
ToolChangeResult result;
|
||||||
result.print_z = this->m_z_pos;
|
result.print_z = m_z_pos;
|
||||||
result.layer_height = this->m_layer_height;
|
result.layer_height = m_layer_height;
|
||||||
result.gcode = writer.gcode();
|
result.gcode = writer.gcode();
|
||||||
result.elapsed_time = writer.elapsed_time();
|
result.elapsed_time = writer.elapsed_time();
|
||||||
result.extrusions = writer.extrusions();
|
result.extrusions = writer.extrusions();
|
||||||
|
@ -718,8 +718,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolChangeResult result;
|
ToolChangeResult result;
|
||||||
result.print_z = this->m_z_pos;
|
result.print_z = m_z_pos;
|
||||||
result.layer_height = this->m_layer_height;
|
result.layer_height = m_layer_height;
|
||||||
result.gcode = writer.gcode();
|
result.gcode = writer.gcode();
|
||||||
result.elapsed_time = writer.elapsed_time();
|
result.elapsed_time = writer.elapsed_time();
|
||||||
result.extrusions = writer.extrusions();
|
result.extrusions = writer.extrusions();
|
||||||
|
@ -1040,8 +1040,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose)
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolChangeResult result;
|
ToolChangeResult result;
|
||||||
result.print_z = this->m_z_pos;
|
result.print_z = m_z_pos;
|
||||||
result.layer_height = this->m_layer_height;
|
result.layer_height = m_layer_height;
|
||||||
result.gcode = writer.gcode();
|
result.gcode = writer.gcode();
|
||||||
result.elapsed_time = writer.elapsed_time();
|
result.elapsed_time = writer.elapsed_time();
|
||||||
result.extrusions = writer.extrusions();
|
result.extrusions = writer.extrusions();
|
||||||
|
|
|
@ -12,24 +12,24 @@ namespace Slic3r {
|
||||||
Layer::~Layer()
|
Layer::~Layer()
|
||||||
{
|
{
|
||||||
this->lower_layer = this->upper_layer = nullptr;
|
this->lower_layer = this->upper_layer = nullptr;
|
||||||
for (LayerRegion *region : this->regions)
|
for (LayerRegion *region : m_regions)
|
||||||
delete region;
|
delete region;
|
||||||
this->regions.clear();
|
m_regions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerRegion* Layer::add_region(PrintRegion* print_region)
|
LayerRegion* Layer::add_region(PrintRegion* print_region)
|
||||||
{
|
{
|
||||||
this->regions.emplace_back(new LayerRegion(this, print_region));
|
m_regions.emplace_back(new LayerRegion(this, print_region));
|
||||||
return this->regions.back();
|
return m_regions.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
// merge all regions' slices to get islands
|
// merge all regions' slices to get islands
|
||||||
void Layer::make_slices()
|
void Layer::make_slices()
|
||||||
{
|
{
|
||||||
ExPolygons slices;
|
ExPolygons slices;
|
||||||
if (this->regions.size() == 1) {
|
if (m_regions.size() == 1) {
|
||||||
// optimization: if we only have one region, take its slices
|
// optimization: if we only have one region, take its slices
|
||||||
slices = this->regions.front()->slices;
|
slices = m_regions.front()->slices;
|
||||||
} else {
|
} else {
|
||||||
Polygons slices_p;
|
Polygons slices_p;
|
||||||
FOREACH_LAYERREGION(this, layerm) {
|
FOREACH_LAYERREGION(this, layerm) {
|
||||||
|
@ -58,10 +58,10 @@ void Layer::make_slices()
|
||||||
|
|
||||||
void Layer::merge_slices()
|
void Layer::merge_slices()
|
||||||
{
|
{
|
||||||
if (this->regions.size() == 1) {
|
if (m_regions.size() == 1) {
|
||||||
// Optimization, also more robust. Don't merge classified pieces of layerm->slices,
|
// Optimization, also more robust. Don't merge classified pieces of layerm->slices,
|
||||||
// but use the non-split islands of a layer. For a single region print, these shall be equal.
|
// but use the non-split islands of a layer. For a single region print, these shall be equal.
|
||||||
this->regions.front()->slices.set(this->slices.expolygons, stInternal);
|
m_regions.front()->slices.set(this->slices.expolygons, stInternal);
|
||||||
} else {
|
} else {
|
||||||
FOREACH_LAYERREGION(this, layerm) {
|
FOREACH_LAYERREGION(this, layerm) {
|
||||||
// without safety offset, artifacts are generated (GH #2494)
|
// without safety offset, artifacts are generated (GH #2494)
|
||||||
|
@ -81,18 +81,18 @@ void Layer::make_perimeters()
|
||||||
std::set<size_t> done;
|
std::set<size_t> done;
|
||||||
|
|
||||||
FOREACH_LAYERREGION(this, layerm) {
|
FOREACH_LAYERREGION(this, layerm) {
|
||||||
size_t region_id = layerm - this->regions.begin();
|
size_t region_id = layerm - m_regions.begin();
|
||||||
if (done.find(region_id) != done.end()) continue;
|
if (done.find(region_id) != done.end()) continue;
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
|
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
|
||||||
done.insert(region_id);
|
done.insert(region_id);
|
||||||
const PrintRegionConfig &config = (*layerm)->region()->config;
|
const PrintRegionConfig &config = (*layerm)->region()->config();
|
||||||
|
|
||||||
// find compatible regions
|
// find compatible regions
|
||||||
LayerRegionPtrs layerms;
|
LayerRegionPtrs layerms;
|
||||||
layerms.push_back(*layerm);
|
layerms.push_back(*layerm);
|
||||||
for (LayerRegionPtrs::const_iterator it = layerm + 1; it != this->regions.end(); ++it) {
|
for (LayerRegionPtrs::const_iterator it = layerm + 1; it != m_regions.end(); ++it) {
|
||||||
LayerRegion* other_layerm = *it;
|
LayerRegion* other_layerm = *it;
|
||||||
const PrintRegionConfig &other_config = other_layerm->region()->config;
|
const PrintRegionConfig &other_config = other_layerm->region()->config();
|
||||||
|
|
||||||
if (config.perimeter_extruder == other_config.perimeter_extruder
|
if (config.perimeter_extruder == other_config.perimeter_extruder
|
||||||
&& config.perimeters == other_config.perimeters
|
&& config.perimeters == other_config.perimeters
|
||||||
|
@ -104,7 +104,7 @@ void Layer::make_perimeters()
|
||||||
&& config.thin_walls == other_config.thin_walls
|
&& config.thin_walls == other_config.thin_walls
|
||||||
&& config.external_perimeters_first == other_config.external_perimeters_first) {
|
&& config.external_perimeters_first == other_config.external_perimeters_first) {
|
||||||
layerms.push_back(other_layerm);
|
layerms.push_back(other_layerm);
|
||||||
done.insert(it - this->regions.begin());
|
done.insert(it - m_regions.begin());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ void Layer::make_fills()
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
printf("Making fills for layer " PRINTF_ZU "\n", this->id());
|
printf("Making fills for layer " PRINTF_ZU "\n", this->id());
|
||||||
#endif
|
#endif
|
||||||
for (LayerRegion *layerm : regions) {
|
for (LayerRegion *layerm : m_regions) {
|
||||||
layerm->fills.clear();
|
layerm->fills.clear();
|
||||||
make_fill(*layerm, layerm->fills);
|
make_fill(*layerm, layerm->fills);
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
@ -163,18 +163,18 @@ void Layer::make_fills()
|
||||||
void Layer::export_region_slices_to_svg(const char *path) const
|
void Layer::export_region_slices_to_svg(const char *path) const
|
||||||
{
|
{
|
||||||
BoundingBox bbox;
|
BoundingBox bbox;
|
||||||
for (LayerRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region)
|
for (const auto *region : m_regions)
|
||||||
for (Surfaces::const_iterator surface = (*region)->slices.surfaces.begin(); surface != (*region)->slices.surfaces.end(); ++surface)
|
for (const auto &surface : region->slices.surfaces)
|
||||||
bbox.merge(get_extents(surface->expolygon));
|
bbox.merge(get_extents(surface.expolygon));
|
||||||
Point legend_size = export_surface_type_legend_to_svg_box_size();
|
Point legend_size = export_surface_type_legend_to_svg_box_size();
|
||||||
Point legend_pos(bbox.min.x, bbox.max.y);
|
Point legend_pos(bbox.min.x, bbox.max.y);
|
||||||
bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y));
|
bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y));
|
||||||
|
|
||||||
SVG svg(path, bbox);
|
SVG svg(path, bbox);
|
||||||
const float transparency = 0.5f;
|
const float transparency = 0.5f;
|
||||||
for (LayerRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region)
|
for (const auto *region : m_regions)
|
||||||
for (Surfaces::const_iterator surface = (*region)->slices.surfaces.begin(); surface != (*region)->slices.surfaces.end(); ++surface)
|
for (const auto &surface : region->slices.surfaces)
|
||||||
svg.draw(surface->expolygon, surface_type_to_color_name(surface->surface_type), transparency);
|
svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency);
|
||||||
export_surface_type_legend_to_svg(svg, legend_pos);
|
export_surface_type_legend_to_svg(svg, legend_pos);
|
||||||
svg.Close();
|
svg.Close();
|
||||||
}
|
}
|
||||||
|
@ -189,18 +189,18 @@ void Layer::export_region_slices_to_svg_debug(const char *name) const
|
||||||
void Layer::export_region_fill_surfaces_to_svg(const char *path) const
|
void Layer::export_region_fill_surfaces_to_svg(const char *path) const
|
||||||
{
|
{
|
||||||
BoundingBox bbox;
|
BoundingBox bbox;
|
||||||
for (LayerRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region)
|
for (const auto *region : m_regions)
|
||||||
for (Surfaces::const_iterator surface = (*region)->fill_surfaces.surfaces.begin(); surface != (*region)->fill_surfaces.surfaces.end(); ++surface)
|
for (const auto &surface : region->slices.surfaces)
|
||||||
bbox.merge(get_extents(surface->expolygon));
|
bbox.merge(get_extents(surface.expolygon));
|
||||||
Point legend_size = export_surface_type_legend_to_svg_box_size();
|
Point legend_size = export_surface_type_legend_to_svg_box_size();
|
||||||
Point legend_pos(bbox.min.x, bbox.max.y);
|
Point legend_pos(bbox.min.x, bbox.max.y);
|
||||||
bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y));
|
bbox.merge(Point(std::max(bbox.min.x + legend_size.x, bbox.max.x), bbox.max.y + legend_size.y));
|
||||||
|
|
||||||
SVG svg(path, bbox);
|
SVG svg(path, bbox);
|
||||||
const float transparency = 0.5f;
|
const float transparency = 0.5f;
|
||||||
for (LayerRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region)
|
for (const auto *region : m_regions)
|
||||||
for (Surfaces::const_iterator surface = (*region)->fill_surfaces.surfaces.begin(); surface != (*region)->fill_surfaces.surfaces.end(); ++surface)
|
for (const auto &surface : region->slices.surfaces)
|
||||||
svg.draw(surface->expolygon, surface_type_to_color_name(surface->surface_type), transparency);
|
svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency);
|
||||||
export_surface_type_legend_to_svg(svg, legend_pos);
|
export_surface_type_legend_to_svg(svg, legend_pos);
|
||||||
svg.Close();
|
svg.Close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,13 @@ class Layer;
|
||||||
class PrintRegion;
|
class PrintRegion;
|
||||||
class PrintObject;
|
class PrintObject;
|
||||||
|
|
||||||
// TODO: make stuff private
|
|
||||||
class LayerRegion
|
class LayerRegion
|
||||||
{
|
{
|
||||||
friend class Layer;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Layer* layer() { return this->_layer; }
|
Layer* layer() { return m_layer; }
|
||||||
const Layer* layer() const { return this->_layer; }
|
const Layer* layer() const { return m_layer; }
|
||||||
PrintRegion* region() { return this->_region; }
|
PrintRegion* region() { return m_region; }
|
||||||
const PrintRegion* region() const { return this->_region; }
|
const PrintRegion* region() const { return m_region; }
|
||||||
|
|
||||||
// collection of surfaces generated by slicing the original geometry
|
// collection of surfaces generated by slicing the original geometry
|
||||||
// divided by type top/bottom/internal
|
// divided by type top/bottom/internal
|
||||||
|
@ -77,29 +74,30 @@ public:
|
||||||
// Is there any valid extrusion assigned to this LayerRegion?
|
// Is there any valid extrusion assigned to this LayerRegion?
|
||||||
bool has_extrusions() const { return ! this->perimeters.entities.empty() || ! this->fills.entities.empty(); }
|
bool has_extrusions() const { return ! this->perimeters.entities.empty() || ! this->fills.entities.empty(); }
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
Layer *_layer;
|
friend class Layer;
|
||||||
PrintRegion *_region;
|
|
||||||
|
|
||||||
LayerRegion(Layer *layer, PrintRegion *region) : _layer(layer), _region(region) {}
|
LayerRegion(Layer *layer, PrintRegion *region) : m_layer(layer), m_region(region) {}
|
||||||
~LayerRegion() {}
|
~LayerRegion() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Layer *m_layer;
|
||||||
|
PrintRegion *m_region;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef std::vector<LayerRegion*> LayerRegionPtrs;
|
typedef std::vector<LayerRegion*> LayerRegionPtrs;
|
||||||
|
|
||||||
class Layer {
|
class Layer
|
||||||
friend class PrintObject;
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
size_t id() const { return this->_id; }
|
size_t id() const { return m_id; }
|
||||||
void set_id(size_t id) { this->_id = id; }
|
void set_id(size_t id) { m_id = id; }
|
||||||
PrintObject* object() { return this->_object; }
|
PrintObject* object() { return m_object; }
|
||||||
const PrintObject* object() const { return this->_object; }
|
const PrintObject* object() const { return m_object; }
|
||||||
|
|
||||||
Layer *upper_layer;
|
Layer *upper_layer;
|
||||||
Layer *lower_layer;
|
Layer *lower_layer;
|
||||||
LayerRegionPtrs regions;
|
|
||||||
bool slicing_errors;
|
bool slicing_errors;
|
||||||
coordf_t slice_z; // Z used for slicing in unscaled coordinates
|
coordf_t slice_z; // Z used for slicing in unscaled coordinates
|
||||||
coordf_t print_z; // Z used for printing in unscaled coordinates
|
coordf_t print_z; // Z used for printing in unscaled coordinates
|
||||||
|
@ -111,19 +109,20 @@ public:
|
||||||
// order will be recovered by the G-code generator.
|
// order will be recovered by the G-code generator.
|
||||||
ExPolygonCollection slices;
|
ExPolygonCollection slices;
|
||||||
|
|
||||||
size_t region_count() const { return this->regions.size(); }
|
size_t region_count() const { return m_regions.size(); }
|
||||||
const LayerRegion* get_region(int idx) const { return this->regions.at(idx); }
|
const LayerRegion* get_region(int idx) const { return m_regions.at(idx); }
|
||||||
LayerRegion* get_region(int idx) { return this->regions.at(idx); }
|
LayerRegion* get_region(int idx) { return m_regions[idx]; }
|
||||||
LayerRegion* add_region(PrintRegion* print_region);
|
LayerRegion* add_region(PrintRegion* print_region);
|
||||||
|
const LayerRegionPtrs& regions() const { return m_regions; }
|
||||||
|
|
||||||
void make_slices();
|
void make_slices();
|
||||||
void merge_slices();
|
void merge_slices();
|
||||||
template <class T> bool any_internal_region_slice_contains(const T &item) const {
|
template <class T> bool any_internal_region_slice_contains(const T &item) const {
|
||||||
for (const LayerRegion *layerm : this->regions) if (layerm->slices.any_internal_contains(item)) return true;
|
for (const LayerRegion *layerm : m_regions) if (layerm->slices.any_internal_contains(item)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
template <class T> bool any_bottom_region_slice_contains(const T &item) const {
|
template <class T> bool any_bottom_region_slice_contains(const T &item) const {
|
||||||
for (const LayerRegion *layerm : this->regions) if (layerm->slices.any_bottom_contains(item)) return true;
|
for (const LayerRegion *layerm : m_regions) if (layerm->slices.any_bottom_contains(item)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
void make_perimeters();
|
void make_perimeters();
|
||||||
|
@ -136,22 +135,26 @@ public:
|
||||||
void export_region_fill_surfaces_to_svg_debug(const char *name) const;
|
void export_region_fill_surfaces_to_svg_debug(const char *name) const;
|
||||||
|
|
||||||
// Is there any valid extrusion assigned to this LayerRegion?
|
// Is there any valid extrusion assigned to this LayerRegion?
|
||||||
virtual bool has_extrusions() const { for (auto layerm : this->regions) if (layerm->has_extrusions()) return true; return false; }
|
virtual bool has_extrusions() const { for (auto layerm : m_regions) if (layerm->has_extrusions()) return true; return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t _id; // sequential number of layer, 0-based
|
friend class PrintObject;
|
||||||
PrintObject *_object;
|
|
||||||
|
|
||||||
Layer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) :
|
Layer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) :
|
||||||
upper_layer(nullptr), lower_layer(nullptr), slicing_errors(false),
|
upper_layer(nullptr), lower_layer(nullptr), slicing_errors(false),
|
||||||
slice_z(slice_z), print_z(print_z), height(height),
|
slice_z(slice_z), print_z(print_z), height(height),
|
||||||
_id(id), _object(object) {}
|
m_id(id), m_object(object) {}
|
||||||
virtual ~Layer();
|
virtual ~Layer();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// sequential number of layer, 0-based
|
||||||
|
size_t m_id;
|
||||||
|
PrintObject *m_object;
|
||||||
|
LayerRegionPtrs m_regions;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SupportLayer : public Layer {
|
class SupportLayer : public Layer
|
||||||
friend class PrintObject;
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Polygons covered by the supports: base, interface and contact areas.
|
// Polygons covered by the supports: base, interface and contact areas.
|
||||||
ExPolygonCollection support_islands;
|
ExPolygonCollection support_islands;
|
||||||
|
@ -161,7 +164,9 @@ public:
|
||||||
// Is there any valid extrusion assigned to this LayerRegion?
|
// Is there any valid extrusion assigned to this LayerRegion?
|
||||||
virtual bool has_extrusions() const { return ! support_fills.empty(); }
|
virtual bool has_extrusions() const { return ! support_fills.empty(); }
|
||||||
|
|
||||||
//protected:
|
protected:
|
||||||
|
friend class PrintObject;
|
||||||
|
|
||||||
// The constructor has been made public to be able to insert additional support layers for the skirt or a wipe tower
|
// The constructor has been made public to be able to insert additional support layers for the skirt or a wipe tower
|
||||||
// between the raft and the object first layer.
|
// between the raft and the object first layer.
|
||||||
SupportLayer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) :
|
SupportLayer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z, coordf_t slice_z) :
|
||||||
|
|
|
@ -18,13 +18,13 @@ namespace Slic3r {
|
||||||
Flow
|
Flow
|
||||||
LayerRegion::flow(FlowRole role, bool bridge, double width) const
|
LayerRegion::flow(FlowRole role, bool bridge, double width) const
|
||||||
{
|
{
|
||||||
return this->_region->flow(
|
return m_region->flow(
|
||||||
role,
|
role,
|
||||||
this->_layer->height,
|
m_layer->height,
|
||||||
bridge,
|
bridge,
|
||||||
this->_layer->id() == 0,
|
m_layer->id() == 0,
|
||||||
width,
|
width,
|
||||||
*this->_layer->object()
|
*m_layer->object()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,9 +61,9 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
||||||
&slices,
|
&slices,
|
||||||
this->layer()->height,
|
this->layer()->height,
|
||||||
this->flow(frPerimeter),
|
this->flow(frPerimeter),
|
||||||
&this->region()->config,
|
&this->region()->config(),
|
||||||
&this->layer()->object()->config,
|
&this->layer()->object()->config(),
|
||||||
&this->layer()->object()->print()->config,
|
&this->layer()->object()->print()->config(),
|
||||||
|
|
||||||
// output:
|
// output:
|
||||||
&this->perimeters,
|
&this->perimeters,
|
||||||
|
@ -116,7 +116,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||||
{
|
{
|
||||||
// bottom_polygons are used to trim inflated top surfaces.
|
// bottom_polygons are used to trim inflated top surfaces.
|
||||||
fill_boundaries.reserve(number_polygons(surfaces));
|
fill_boundaries.reserve(number_polygons(surfaces));
|
||||||
bool has_infill = this->region()->config.fill_density.value > 0.;
|
bool has_infill = this->region()->config().fill_density.value > 0.;
|
||||||
for (const Surface &surface : this->fill_surfaces.surfaces) {
|
for (const Surface &surface : this->fill_surfaces.surfaces) {
|
||||||
if (surface.surface_type == stTop) {
|
if (surface.surface_type == stTop) {
|
||||||
// Collect the top surfaces, inflate them and trim them by the bottom surfaces.
|
// Collect the top surfaces, inflate them and trim them by the bottom surfaces.
|
||||||
|
@ -259,9 +259,9 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
printf("Processing bridge at layer " PRINTF_ZU ":\n", this->layer()->id());
|
printf("Processing bridge at layer " PRINTF_ZU ":\n", this->layer()->id());
|
||||||
#endif
|
#endif
|
||||||
if (bd.detect_angle(Geometry::deg2rad(this->region()->config.bridge_angle.value))) {
|
if (bd.detect_angle(Geometry::deg2rad(this->region()->config().bridge_angle.value))) {
|
||||||
bridges[idx_last].bridge_angle = bd.angle;
|
bridges[idx_last].bridge_angle = bd.angle;
|
||||||
if (this->layer()->object()->config.support_material) {
|
if (this->layer()->object()->config().support_material) {
|
||||||
polygons_append(this->bridged, bd.coverage());
|
polygons_append(this->bridged, bd.coverage());
|
||||||
this->unsupported_bridge_edges.append(bd.unsupported_edges());
|
this->unsupported_bridge_edges.append(bd.unsupported_edges());
|
||||||
}
|
}
|
||||||
|
@ -351,13 +351,13 @@ void LayerRegion::prepare_fill_surfaces()
|
||||||
the only meaningful information returned by psPerimeters. */
|
the only meaningful information returned by psPerimeters. */
|
||||||
|
|
||||||
// if no solid layers are requested, turn top/bottom surfaces to internal
|
// if no solid layers are requested, turn top/bottom surfaces to internal
|
||||||
if (this->region()->config.top_solid_layers == 0) {
|
if (this->region()->config().top_solid_layers == 0) {
|
||||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
|
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface)
|
||||||
if (surface->surface_type == stTop)
|
if (surface->surface_type == stTop)
|
||||||
surface->surface_type = (this->layer()->object()->config.infill_only_where_needed) ?
|
surface->surface_type = (this->layer()->object()->config().infill_only_where_needed) ?
|
||||||
stInternalVoid : stInternal;
|
stInternalVoid : stInternal;
|
||||||
}
|
}
|
||||||
if (this->region()->config.bottom_solid_layers == 0) {
|
if (this->region()->config().bottom_solid_layers == 0) {
|
||||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
||||||
if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge)
|
if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge)
|
||||||
surface->surface_type = stInternal;
|
surface->surface_type = stInternal;
|
||||||
|
@ -365,9 +365,9 @@ void LayerRegion::prepare_fill_surfaces()
|
||||||
}
|
}
|
||||||
|
|
||||||
// turn too small internal regions into solid regions according to the user setting
|
// turn too small internal regions into solid regions according to the user setting
|
||||||
if (this->region()->config.fill_density.value > 0) {
|
if (this->region()->config().fill_density.value > 0) {
|
||||||
// scaling an area requires two calls!
|
// scaling an area requires two calls!
|
||||||
double min_area = scale_(scale_(this->region()->config.solid_infill_below_area.value));
|
double min_area = scale_(scale_(this->region()->config().solid_infill_below_area.value));
|
||||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
||||||
if (surface->surface_type == stInternal && surface->area() <= min_area)
|
if (surface->surface_type == stInternal && surface->area() <= min_area)
|
||||||
surface->surface_type = stInternalSolid;
|
surface->surface_type = stInternalSolid;
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
void
|
void PerimeterGenerator::process()
|
||||||
PerimeterGenerator::process()
|
|
||||||
{
|
{
|
||||||
// other perimeters
|
// other perimeters
|
||||||
this->_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
|
this->_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
|
||||||
|
|
|
@ -38,30 +38,30 @@ typedef std::vector<PerimeterGeneratorLoop> PerimeterGeneratorLoops;
|
||||||
class PerimeterGenerator {
|
class PerimeterGenerator {
|
||||||
public:
|
public:
|
||||||
// Inputs:
|
// Inputs:
|
||||||
const SurfaceCollection* slices;
|
const SurfaceCollection *slices;
|
||||||
const ExPolygonCollection* lower_slices;
|
const ExPolygonCollection *lower_slices;
|
||||||
double layer_height;
|
double layer_height;
|
||||||
int layer_id;
|
int layer_id;
|
||||||
Flow perimeter_flow;
|
Flow perimeter_flow;
|
||||||
Flow ext_perimeter_flow;
|
Flow ext_perimeter_flow;
|
||||||
Flow overhang_flow;
|
Flow overhang_flow;
|
||||||
Flow solid_infill_flow;
|
Flow solid_infill_flow;
|
||||||
PrintRegionConfig* config;
|
const PrintRegionConfig *config;
|
||||||
PrintObjectConfig* object_config;
|
const PrintObjectConfig *object_config;
|
||||||
PrintConfig* print_config;
|
const PrintConfig *print_config;
|
||||||
// Outputs:
|
// Outputs:
|
||||||
ExtrusionEntityCollection* loops;
|
ExtrusionEntityCollection *loops;
|
||||||
ExtrusionEntityCollection* gap_fill;
|
ExtrusionEntityCollection *gap_fill;
|
||||||
SurfaceCollection* fill_surfaces;
|
SurfaceCollection *fill_surfaces;
|
||||||
|
|
||||||
PerimeterGenerator(
|
PerimeterGenerator(
|
||||||
// Input:
|
// Input:
|
||||||
const SurfaceCollection* slices,
|
const SurfaceCollection* slices,
|
||||||
double layer_height,
|
double layer_height,
|
||||||
Flow flow,
|
Flow flow,
|
||||||
PrintRegionConfig* config,
|
const PrintRegionConfig* config,
|
||||||
PrintObjectConfig* object_config,
|
const PrintObjectConfig* object_config,
|
||||||
PrintConfig* print_config,
|
const PrintConfig* print_config,
|
||||||
// Output:
|
// Output:
|
||||||
// Loops with the external thin walls
|
// Loops with the external thin walls
|
||||||
ExtrusionEntityCollection* loops,
|
ExtrusionEntityCollection* loops,
|
||||||
|
@ -84,10 +84,8 @@ private:
|
||||||
double _mm3_per_mm_overhang;
|
double _mm3_per_mm_overhang;
|
||||||
Polygons _lower_slices_p;
|
Polygons _lower_slices_p;
|
||||||
|
|
||||||
ExtrusionEntityCollection _traverse_loops(const PerimeterGeneratorLoops &loops,
|
ExtrusionEntityCollection _traverse_loops(const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) const;
|
||||||
ThickPolylines &thin_walls) const;
|
ExtrusionEntityCollection _variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const;
|
||||||
ExtrusionEntityCollection _variable_width
|
|
||||||
(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,7 +69,7 @@ PlaceholderParser::PlaceholderParser()
|
||||||
this->update_timestamp();
|
this->update_timestamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaceholderParser::update_timestamp()
|
void PlaceholderParser::update_timestamp(DynamicConfig &config)
|
||||||
{
|
{
|
||||||
time_t rawtime;
|
time_t rawtime;
|
||||||
time(&rawtime);
|
time(&rawtime);
|
||||||
|
@ -84,14 +84,14 @@ void PlaceholderParser::update_timestamp()
|
||||||
ss << std::setw(2) << std::setfill('0') << timeinfo->tm_hour;
|
ss << std::setw(2) << std::setfill('0') << timeinfo->tm_hour;
|
||||||
ss << std::setw(2) << std::setfill('0') << timeinfo->tm_min;
|
ss << std::setw(2) << std::setfill('0') << timeinfo->tm_min;
|
||||||
ss << std::setw(2) << std::setfill('0') << timeinfo->tm_sec;
|
ss << std::setw(2) << std::setfill('0') << timeinfo->tm_sec;
|
||||||
this->set("timestamp", ss.str());
|
config.set_key_value("timestamp", new ConfigOptionString(ss.str()));
|
||||||
}
|
}
|
||||||
this->set("year", 1900 + timeinfo->tm_year);
|
config.set_key_value("year", new ConfigOptionInt(1900 + timeinfo->tm_year));
|
||||||
this->set("month", 1 + timeinfo->tm_mon);
|
config.set_key_value("month", new ConfigOptionInt(1 + timeinfo->tm_mon));
|
||||||
this->set("day", timeinfo->tm_mday);
|
config.set_key_value("day", new ConfigOptionInt(timeinfo->tm_mday));
|
||||||
this->set("hour", timeinfo->tm_hour);
|
config.set_key_value("hour", new ConfigOptionInt(timeinfo->tm_hour));
|
||||||
this->set("minute", timeinfo->tm_min);
|
config.set_key_value("minute", new ConfigOptionInt(timeinfo->tm_min));
|
||||||
this->set("second", timeinfo->tm_sec);
|
config.set_key_value("second", new ConfigOptionInt(timeinfo->tm_sec));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scalar configuration values are stored into m_single,
|
// Scalar configuration values are stored into m_single,
|
||||||
|
|
|
@ -14,7 +14,6 @@ class PlaceholderParser
|
||||||
public:
|
public:
|
||||||
PlaceholderParser();
|
PlaceholderParser();
|
||||||
|
|
||||||
void update_timestamp();
|
|
||||||
void apply_config(const DynamicPrintConfig &config);
|
void apply_config(const DynamicPrintConfig &config);
|
||||||
void apply_env_variables();
|
void apply_env_variables();
|
||||||
|
|
||||||
|
@ -37,6 +36,11 @@ public:
|
||||||
// Throws std::runtime_error on syntax or runtime error.
|
// Throws std::runtime_error on syntax or runtime error.
|
||||||
static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override = nullptr);
|
static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override = nullptr);
|
||||||
|
|
||||||
|
// Update timestamp, year, month, day, hour, minute, second variables at the provided config.
|
||||||
|
static void update_timestamp(DynamicConfig &config);
|
||||||
|
// Update timestamp, year, month, day, hour, minute, second variables at m_config.
|
||||||
|
void update_timestamp() { update_timestamp(m_config); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DynamicConfig m_config;
|
DynamicConfig m_config;
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,24 +20,27 @@ template class PrintState<PrintObjectStep, posCount>;
|
||||||
|
|
||||||
void Print::clear_objects()
|
void Print::clear_objects()
|
||||||
{
|
{
|
||||||
for (int i = int(this->objects.size())-1; i >= 0; --i)
|
tbb::mutex::scoped_lock lock(m_mutex);
|
||||||
|
for (int i = int(m_objects.size())-1; i >= 0; --i)
|
||||||
this->delete_object(i);
|
this->delete_object(i);
|
||||||
for (PrintRegion *region : this->regions)
|
for (PrintRegion *region : m_regions)
|
||||||
delete region;
|
delete region;
|
||||||
this->regions.clear();
|
m_regions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Print::delete_object(size_t idx)
|
void Print::delete_object(size_t idx)
|
||||||
{
|
{
|
||||||
|
tbb::mutex::scoped_lock lock(m_mutex);
|
||||||
// destroy object and remove it from our container
|
// destroy object and remove it from our container
|
||||||
delete this->objects[idx];
|
delete m_objects[idx];
|
||||||
this->objects.erase(this->objects.begin() + idx);
|
m_objects.erase(m_objects.begin() + idx);
|
||||||
this->invalidate_all_steps();
|
this->invalidate_all_steps();
|
||||||
// TODO: purge unused regions
|
// TODO: purge unused regions
|
||||||
}
|
}
|
||||||
|
|
||||||
void Print::reload_object(size_t /* idx */)
|
void Print::reload_object(size_t /* idx */)
|
||||||
{
|
{
|
||||||
|
tbb::mutex::scoped_lock lock(m_mutex);
|
||||||
/* TODO: this method should check whether the per-object config and per-material configs
|
/* TODO: this method should check whether the per-object config and per-material configs
|
||||||
have changed in such a way that regions need to be rearranged or we can just apply
|
have changed in such a way that regions need to be rearranged or we can just apply
|
||||||
the diff and invalidate something. Same logic as apply_config()
|
the diff and invalidate something. Same logic as apply_config()
|
||||||
|
@ -46,8 +49,8 @@ void Print::reload_object(size_t /* idx */)
|
||||||
|
|
||||||
// collect all current model objects
|
// collect all current model objects
|
||||||
ModelObjectPtrs model_objects;
|
ModelObjectPtrs model_objects;
|
||||||
model_objects.reserve(this->objects.size());
|
model_objects.reserve(m_objects.size());
|
||||||
for (PrintObject *object : this->objects)
|
for (PrintObject *object : m_objects)
|
||||||
model_objects.push_back(object->model_object());
|
model_objects.push_back(object->model_object());
|
||||||
// remove our print objects
|
// remove our print objects
|
||||||
this->clear_objects();
|
this->clear_objects();
|
||||||
|
@ -63,15 +66,21 @@ void Print::reload_object(size_t /* idx */)
|
||||||
bool Print::reload_model_instances()
|
bool Print::reload_model_instances()
|
||||||
{
|
{
|
||||||
bool invalidated = false;
|
bool invalidated = false;
|
||||||
for (PrintObject *object : this->objects)
|
for (PrintObject *object : m_objects)
|
||||||
invalidated |= object->reload_model_instances();
|
invalidated |= object->reload_model_instances();
|
||||||
return invalidated;
|
return invalidated;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintRegion* Print::add_region()
|
PrintRegion* Print::add_region()
|
||||||
{
|
{
|
||||||
regions.push_back(new PrintRegion(this));
|
m_regions.emplace_back(new PrintRegion(this));
|
||||||
return regions.back();
|
return m_regions.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintRegion* Print::add_region(const PrintRegionConfig &config)
|
||||||
|
{
|
||||||
|
m_regions.emplace_back(new PrintRegion(this, config));
|
||||||
|
return m_regions.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by Print::apply_config().
|
// Called by Print::apply_config().
|
||||||
|
@ -224,18 +233,18 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
||||||
invalidated |= this->invalidate_step(step);
|
invalidated |= this->invalidate_step(step);
|
||||||
sort_remove_duplicates(osteps);
|
sort_remove_duplicates(osteps);
|
||||||
for (PrintObjectStep ostep : osteps)
|
for (PrintObjectStep ostep : osteps)
|
||||||
for (PrintObject *object : this->objects)
|
for (PrintObject *object : m_objects)
|
||||||
invalidated |= object->invalidate_step(ostep);
|
invalidated |= object->invalidate_step(ostep);
|
||||||
return invalidated;
|
return invalidated;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Print::invalidate_step(PrintStep step)
|
bool Print::invalidate_step(PrintStep step)
|
||||||
{
|
{
|
||||||
bool invalidated = m_state.invalidate(step);
|
bool invalidated = m_state.invalidate(step, m_mutex, m_cancel_callback);
|
||||||
// Propagate to dependent steps.
|
// Propagate to dependent steps.
|
||||||
//FIXME Why should skirt invalidate brim? Shouldn't it be vice versa?
|
//FIXME Why should skirt invalidate brim? Shouldn't it be vice versa?
|
||||||
if (step == psSkirt)
|
if (step == psSkirt)
|
||||||
invalidated |= m_state.invalidate(psBrim);
|
invalidated |= m_state.invalidate(psBrim, m_mutex, m_cancel_callback);
|
||||||
return invalidated;
|
return invalidated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,9 +252,9 @@ bool Print::invalidate_step(PrintStep step)
|
||||||
// and there's at least one object
|
// and there's at least one object
|
||||||
bool Print::is_step_done(PrintObjectStep step) const
|
bool Print::is_step_done(PrintObjectStep step) const
|
||||||
{
|
{
|
||||||
if (this->objects.empty())
|
if (m_objects.empty())
|
||||||
return false;
|
return false;
|
||||||
for (const PrintObject *object : this->objects)
|
for (const PrintObject *object : m_objects)
|
||||||
if (!object->m_state.is_done(step))
|
if (!object->m_state.is_done(step))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
|
@ -256,15 +265,15 @@ std::vector<unsigned int> Print::object_extruders() const
|
||||||
{
|
{
|
||||||
std::vector<unsigned int> extruders;
|
std::vector<unsigned int> extruders;
|
||||||
|
|
||||||
for (PrintRegion* region : this->regions) {
|
for (PrintRegion* region : m_regions) {
|
||||||
// these checks reflect the same logic used in the GUI for enabling/disabling
|
// these checks reflect the same logic used in the GUI for enabling/disabling
|
||||||
// extruder selection fields
|
// extruder selection fields
|
||||||
if (region->config.perimeters.value > 0 || this->config.brim_width.value > 0)
|
if (region->config().perimeters.value > 0 || m_config.brim_width.value > 0)
|
||||||
extruders.push_back(region->config.perimeter_extruder - 1);
|
extruders.push_back(region->config().perimeter_extruder - 1);
|
||||||
if (region->config.fill_density.value > 0)
|
if (region->config().fill_density.value > 0)
|
||||||
extruders.push_back(region->config.infill_extruder - 1);
|
extruders.push_back(region->config().infill_extruder - 1);
|
||||||
if (region->config.top_solid_layers.value > 0 || region->config.bottom_solid_layers.value > 0)
|
if (region->config().top_solid_layers.value > 0 || region->config().bottom_solid_layers.value > 0)
|
||||||
extruders.push_back(region->config.solid_infill_extruder - 1);
|
extruders.push_back(region->config().solid_infill_extruder - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sort_remove_duplicates(extruders);
|
sort_remove_duplicates(extruders);
|
||||||
|
@ -277,16 +286,16 @@ std::vector<unsigned int> Print::support_material_extruders() const
|
||||||
std::vector<unsigned int> extruders;
|
std::vector<unsigned int> extruders;
|
||||||
bool support_uses_current_extruder = false;
|
bool support_uses_current_extruder = false;
|
||||||
|
|
||||||
for (PrintObject *object : this->objects) {
|
for (PrintObject *object : m_objects) {
|
||||||
if (object->has_support_material()) {
|
if (object->has_support_material()) {
|
||||||
if (object->config.support_material_extruder == 0)
|
if (object->config().support_material_extruder == 0)
|
||||||
support_uses_current_extruder = true;
|
support_uses_current_extruder = true;
|
||||||
else
|
else
|
||||||
extruders.push_back(object->config.support_material_extruder - 1);
|
extruders.push_back(object->config().support_material_extruder - 1);
|
||||||
if (object->config.support_material_interface_extruder == 0)
|
if (object->config().support_material_interface_extruder == 0)
|
||||||
support_uses_current_extruder = true;
|
support_uses_current_extruder = true;
|
||||||
else
|
else
|
||||||
extruders.push_back(object->config.support_material_interface_extruder - 1);
|
extruders.push_back(object->config().support_material_interface_extruder - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,10 +318,10 @@ std::vector<unsigned int> Print::extruders() const
|
||||||
|
|
||||||
void Print::_simplify_slices(double distance)
|
void Print::_simplify_slices(double distance)
|
||||||
{
|
{
|
||||||
for (PrintObject *object : this->objects) {
|
for (PrintObject *object : m_objects) {
|
||||||
for (Layer *layer : object->layers) {
|
for (Layer *layer : object->m_layers) {
|
||||||
layer->slices.simplify(distance);
|
layer->slices.simplify(distance);
|
||||||
for (LayerRegion *layerm : layer->regions)
|
for (LayerRegion *layerm : layer->regions())
|
||||||
layerm->slices.simplify(distance);
|
layerm->slices.simplify(distance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,7 +331,7 @@ double Print::max_allowed_layer_height() const
|
||||||
{
|
{
|
||||||
double nozzle_diameter_max = 0.;
|
double nozzle_diameter_max = 0.;
|
||||||
for (unsigned int extruder_id : this->extruders())
|
for (unsigned int extruder_id : this->extruders())
|
||||||
nozzle_diameter_max = std::max(nozzle_diameter_max, this->config.nozzle_diameter.get_at(extruder_id));
|
nozzle_diameter_max = std::max(nozzle_diameter_max, m_config.nozzle_diameter.get_at(extruder_id));
|
||||||
return nozzle_diameter_max;
|
return nozzle_diameter_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -333,10 +342,10 @@ void Print::add_model_object(ModelObject* model_object, int idx)
|
||||||
// Initialize a new print object and store it at the given position.
|
// Initialize a new print object and store it at the given position.
|
||||||
PrintObject *object = new PrintObject(this, model_object, model_object->raw_bounding_box());
|
PrintObject *object = new PrintObject(this, model_object, model_object->raw_bounding_box());
|
||||||
if (idx != -1) {
|
if (idx != -1) {
|
||||||
delete this->objects[idx];
|
delete m_objects[idx];
|
||||||
this->objects[idx] = object;
|
m_objects[idx] = object;
|
||||||
} else
|
} else
|
||||||
this->objects.emplace_back(object);
|
m_objects.emplace_back(object);
|
||||||
// Invalidate all print steps.
|
// Invalidate all print steps.
|
||||||
this->invalidate_all_steps();
|
this->invalidate_all_steps();
|
||||||
|
|
||||||
|
@ -345,37 +354,42 @@ void Print::add_model_object(ModelObject* model_object, int idx)
|
||||||
PrintRegionConfig config = this->_region_config_from_model_volume(*model_object->volumes[volume_id]);
|
PrintRegionConfig config = this->_region_config_from_model_volume(*model_object->volumes[volume_id]);
|
||||||
// Find an existing print region with the same config.
|
// Find an existing print region with the same config.
|
||||||
size_t region_id = size_t(-1);
|
size_t region_id = size_t(-1);
|
||||||
for (size_t i = 0; i < this->regions.size(); ++ i)
|
for (size_t i = 0; i < m_regions.size(); ++ i)
|
||||||
if (config.equals(this->regions[i]->config)) {
|
if (config.equals(m_regions[i]->config())) {
|
||||||
region_id = i;
|
region_id = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// If no region exists with the same config, create a new one.
|
// If no region exists with the same config, create a new one.
|
||||||
if (region_id == size_t(-1)) {
|
if (region_id == size_t(-1)) {
|
||||||
region_id = this->regions.size();
|
region_id = this->regions().size();
|
||||||
this->add_region()->config.apply(config);
|
this->add_region(config);
|
||||||
}
|
}
|
||||||
// Assign volume to a region.
|
// Assign volume to a region.
|
||||||
object->add_region_volume(region_id, volume_id);
|
object->add_region_volume(region_id, volume_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply config to print object.
|
// Apply config to print object.
|
||||||
object->config.apply(this->default_object_config);
|
object->config_apply(this->default_object_config());
|
||||||
normalize_and_apply_config(object->config, model_object->config);
|
{
|
||||||
|
//normalize_and_apply_config(object->config(), model_object->config);
|
||||||
|
DynamicPrintConfig src_normalized(model_object->config);
|
||||||
|
src_normalized.normalize();
|
||||||
|
object->config_apply(src_normalized, true);
|
||||||
|
}
|
||||||
|
|
||||||
// update placeholders
|
// update placeholders
|
||||||
{
|
{
|
||||||
// get the first input file name
|
// get the first input file name
|
||||||
std::string input_file;
|
std::string input_file;
|
||||||
std::vector<std::string> v_scale;
|
std::vector<std::string> v_scale;
|
||||||
for (const PrintObject *object : this->objects) {
|
for (const PrintObject *object : m_objects) {
|
||||||
const ModelObject &mobj = *object->model_object();
|
const ModelObject &mobj = *object->model_object();
|
||||||
v_scale.push_back(boost::lexical_cast<std::string>(mobj.instances[0]->scaling_factor*100) + "%");
|
v_scale.push_back(boost::lexical_cast<std::string>(mobj.instances[0]->scaling_factor*100) + "%");
|
||||||
if (input_file.empty())
|
if (input_file.empty())
|
||||||
input_file = mobj.input_file;
|
input_file = mobj.input_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaceholderParser &pp = this->placeholder_parser;
|
PlaceholderParser &pp = m_placeholder_parser;
|
||||||
pp.set("scale", v_scale);
|
pp.set("scale", v_scale);
|
||||||
if (! input_file.empty()) {
|
if (! input_file.empty()) {
|
||||||
// get basename with and without suffix
|
// get basename with and without suffix
|
||||||
|
@ -393,19 +407,19 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||||
config.normalize();
|
config.normalize();
|
||||||
|
|
||||||
// apply variables to placeholder parser
|
// apply variables to placeholder parser
|
||||||
this->placeholder_parser.apply_config(config);
|
m_placeholder_parser.apply_config(config);
|
||||||
|
|
||||||
// handle changes to print config
|
// handle changes to print config
|
||||||
t_config_option_keys print_diff = this->config.diff(config);
|
t_config_option_keys print_diff = m_config.diff(config);
|
||||||
this->config.apply_only(config, print_diff, true);
|
m_config.apply_only(config, print_diff, true);
|
||||||
bool invalidated = this->invalidate_state_by_config_options(print_diff);
|
bool invalidated = this->invalidate_state_by_config_options(print_diff);
|
||||||
|
|
||||||
// handle changes to object config defaults
|
// handle changes to object config defaults
|
||||||
this->default_object_config.apply(config, true);
|
m_default_object_config.apply(config, true);
|
||||||
for (PrintObject *object : this->objects) {
|
for (PrintObject *object : m_objects) {
|
||||||
// we don't assume that config contains a full ObjectConfig,
|
// we don't assume that config contains a full ObjectConfig,
|
||||||
// so we base it on the current print-wise default
|
// so we base it on the current print-wise default
|
||||||
PrintObjectConfig new_config = this->default_object_config;
|
PrintObjectConfig new_config = this->default_object_config();
|
||||||
// we override the new config with object-specific options
|
// we override the new config with object-specific options
|
||||||
normalize_and_apply_config(new_config, object->model_object()->config);
|
normalize_and_apply_config(new_config, object->model_object()->config);
|
||||||
// Force a refresh of a variable layer height profile at the PrintObject if it is not valid.
|
// Force a refresh of a variable layer height profile at the PrintObject if it is not valid.
|
||||||
|
@ -417,13 +431,13 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||||
invalidated = true;
|
invalidated = true;
|
||||||
}
|
}
|
||||||
// check whether the new config is different from the current one
|
// check whether the new config is different from the current one
|
||||||
t_config_option_keys diff = object->config.diff(new_config);
|
t_config_option_keys diff = object->config().diff(new_config);
|
||||||
object->config.apply_only(new_config, diff, true);
|
object->config_apply_only(new_config, diff, true);
|
||||||
invalidated |= object->invalidate_state_by_config_options(diff);
|
invalidated |= object->invalidate_state_by_config_options(diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle changes to regions config defaults
|
// handle changes to regions config defaults
|
||||||
this->default_region_config.apply(config, true);
|
m_default_region_config.apply(config, true);
|
||||||
|
|
||||||
// All regions now have distinct settings.
|
// All regions now have distinct settings.
|
||||||
// Check whether applying the new region config defaults we'd get different regions.
|
// Check whether applying the new region config defaults we'd get different regions.
|
||||||
|
@ -432,11 +446,11 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||||
// Collect the already visited region configs into other_region_configs,
|
// Collect the already visited region configs into other_region_configs,
|
||||||
// so one may check for duplicates.
|
// so one may check for duplicates.
|
||||||
std::vector<PrintRegionConfig> other_region_configs;
|
std::vector<PrintRegionConfig> other_region_configs;
|
||||||
for (size_t region_id = 0; region_id < this->regions.size(); ++ region_id) {
|
for (size_t region_id = 0; region_id < m_regions.size(); ++ region_id) {
|
||||||
PrintRegion ®ion = *this->regions[region_id];
|
PrintRegion ®ion = *m_regions[region_id];
|
||||||
PrintRegionConfig this_region_config;
|
PrintRegionConfig this_region_config;
|
||||||
bool this_region_config_set = false;
|
bool this_region_config_set = false;
|
||||||
for (PrintObject *object : this->objects) {
|
for (PrintObject *object : m_objects) {
|
||||||
if (region_id < object->region_volumes.size()) {
|
if (region_id < object->region_volumes.size()) {
|
||||||
for (int volume_id : object->region_volumes[region_id]) {
|
for (int volume_id : object->region_volumes[region_id]) {
|
||||||
const ModelVolume &volume = *object->model_object()->volumes[volume_id];
|
const ModelVolume &volume = *object->model_object()->volumes[volume_id];
|
||||||
|
@ -466,10 +480,10 @@ bool Print::apply_config(DynamicPrintConfig config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this_region_config_set) {
|
if (this_region_config_set) {
|
||||||
t_config_option_keys diff = region.config.diff(this_region_config);
|
t_config_option_keys diff = region.config().diff(this_region_config);
|
||||||
if (! diff.empty()) {
|
if (! diff.empty()) {
|
||||||
region.config.apply_only(this_region_config, diff);
|
region.config_apply_only(this_region_config, diff, false);
|
||||||
for (PrintObject *object : this->objects)
|
for (PrintObject *object : m_objects)
|
||||||
if (region_id < object->region_volumes.size() && ! object->region_volumes[region_id].empty())
|
if (region_id < object->region_volumes.size() && ! object->region_volumes[region_id].empty())
|
||||||
invalidated |= object->invalidate_state_by_config_options(diff);
|
invalidated |= object->invalidate_state_by_config_options(diff);
|
||||||
}
|
}
|
||||||
|
@ -484,8 +498,8 @@ exit_for_rearrange_regions:
|
||||||
// The current subdivision of regions does not make sense anymore.
|
// The current subdivision of regions does not make sense anymore.
|
||||||
// We need to remove all objects and re-add them.
|
// We need to remove all objects and re-add them.
|
||||||
ModelObjectPtrs model_objects;
|
ModelObjectPtrs model_objects;
|
||||||
model_objects.reserve(this->objects.size());
|
model_objects.reserve(m_objects.size());
|
||||||
for (PrintObject *object : this->objects)
|
for (PrintObject *object : m_objects)
|
||||||
model_objects.push_back(object->model_object());
|
model_objects.push_back(object->model_object());
|
||||||
this->clear_objects();
|
this->clear_objects();
|
||||||
for (ModelObject *mo : model_objects)
|
for (ModelObject *mo : model_objects)
|
||||||
|
@ -494,7 +508,7 @@ exit_for_rearrange_regions:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always make sure that the layer_height_profiles are set, as they should not be modified from the worker threads.
|
// Always make sure that the layer_height_profiles are set, as they should not be modified from the worker threads.
|
||||||
for (PrintObject *object : this->objects)
|
for (PrintObject *object : m_objects)
|
||||||
if (! object->layer_height_profile_valid)
|
if (! object->layer_height_profile_valid)
|
||||||
object->update_layer_height_profile();
|
object->update_layer_height_profile();
|
||||||
|
|
||||||
|
@ -503,32 +517,32 @@ exit_for_rearrange_regions:
|
||||||
|
|
||||||
bool Print::has_infinite_skirt() const
|
bool Print::has_infinite_skirt() const
|
||||||
{
|
{
|
||||||
return (this->config.skirt_height == -1 && this->config.skirts > 0)
|
return (m_config.skirt_height == -1 && m_config.skirts > 0)
|
||||||
|| (this->config.ooze_prevention && this->extruders().size() > 1);
|
|| (m_config.ooze_prevention && this->extruders().size() > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Print::has_skirt() const
|
bool Print::has_skirt() const
|
||||||
{
|
{
|
||||||
return (this->config.skirt_height > 0 && this->config.skirts > 0)
|
return (m_config.skirt_height > 0 && m_config.skirts > 0)
|
||||||
|| this->has_infinite_skirt();
|
|| this->has_infinite_skirt();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Print::validate() const
|
std::string Print::validate() const
|
||||||
{
|
{
|
||||||
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(config.bed_shape.values));
|
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(m_config.bed_shape.values));
|
||||||
BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), config.max_print_height));
|
BoundingBoxf3 print_volume(Pointf3(unscale(bed_box_2D.min.x), unscale(bed_box_2D.min.y), 0.0), Pointf3(unscale(bed_box_2D.max.x), unscale(bed_box_2D.max.y), m_config.max_print_height));
|
||||||
// Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced.
|
// Allow the objects to protrude below the print bed, only the part of the object above the print bed will be sliced.
|
||||||
print_volume.min.z = -1e10;
|
print_volume.min.z = -1e10;
|
||||||
for (PrintObject *po : this->objects) {
|
for (PrintObject *po : m_objects) {
|
||||||
if (! print_volume.contains(po->model_object()->tight_bounding_box(false)))
|
if (! print_volume.contains(po->model_object()->tight_bounding_box(false)))
|
||||||
return "Some objects are outside of the print volume.";
|
return "Some objects are outside of the print volume.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->config.complete_objects) {
|
if (m_config.complete_objects) {
|
||||||
// Check horizontal clearance.
|
// Check horizontal clearance.
|
||||||
{
|
{
|
||||||
Polygons convex_hulls_other;
|
Polygons convex_hulls_other;
|
||||||
for (PrintObject *object : this->objects) {
|
for (PrintObject *object : m_objects) {
|
||||||
// Get convex hull of all meshes assigned to this print object.
|
// Get convex hull of all meshes assigned to this print object.
|
||||||
Polygon convex_hull;
|
Polygon convex_hull;
|
||||||
{
|
{
|
||||||
|
@ -542,7 +556,7 @@ std::string Print::validate() const
|
||||||
// Apply the same transformations we apply to the actual meshes when slicing them.
|
// Apply the same transformations we apply to the actual meshes when slicing them.
|
||||||
object->model_object()->instances.front()->transform_polygon(&convex_hull);
|
object->model_object()->instances.front()->transform_polygon(&convex_hull);
|
||||||
// Grow convex hull with the clearance margin.
|
// Grow convex hull with the clearance margin.
|
||||||
convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front();
|
convex_hull = offset(convex_hull, scale_(m_config.extruder_clearance_radius.value)/2, jtRound, scale_(0.1)).front();
|
||||||
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
// Now we check that no instance of convex_hull intersects any of the previously checked object instances.
|
||||||
for (const Point © : object->_shifted_copies) {
|
for (const Point © : object->_shifted_copies) {
|
||||||
Polygon p = convex_hull;
|
Polygon p = convex_hull;
|
||||||
|
@ -556,47 +570,47 @@ std::string Print::validate() const
|
||||||
// Check vertical clearance.
|
// Check vertical clearance.
|
||||||
{
|
{
|
||||||
std::vector<coord_t> object_height;
|
std::vector<coord_t> object_height;
|
||||||
for (const PrintObject *object : this->objects)
|
for (const PrintObject *object : m_objects)
|
||||||
object_height.insert(object_height.end(), object->copies().size(), object->size.z);
|
object_height.insert(object_height.end(), object->copies().size(), object->size.z);
|
||||||
std::sort(object_height.begin(), object_height.end());
|
std::sort(object_height.begin(), object_height.end());
|
||||||
// Ignore the tallest *copy* (this is why we repeat height for all of them):
|
// Ignore the tallest *copy* (this is why we repeat height for all of them):
|
||||||
// it will be printed as last one so its height doesn't matter.
|
// it will be printed as last one so its height doesn't matter.
|
||||||
object_height.pop_back();
|
object_height.pop_back();
|
||||||
if (! object_height.empty() && object_height.back() > scale_(this->config.extruder_clearance_height.value))
|
if (! object_height.empty() && object_height.back() > scale_(m_config.extruder_clearance_height.value))
|
||||||
return "Some objects are too tall and cannot be printed without extruder collisions.";
|
return "Some objects are too tall and cannot be printed without extruder collisions.";
|
||||||
}
|
}
|
||||||
} // end if (this->config.complete_objects)
|
} // end if (m_config.complete_objects)
|
||||||
|
|
||||||
if (this->config.spiral_vase) {
|
if (m_config.spiral_vase) {
|
||||||
size_t total_copies_count = 0;
|
size_t total_copies_count = 0;
|
||||||
for (const PrintObject *object : this->objects)
|
for (const PrintObject *object : m_objects)
|
||||||
total_copies_count += object->copies().size();
|
total_copies_count += object->copies().size();
|
||||||
// #4043
|
// #4043
|
||||||
if (total_copies_count > 1 && ! this->config.complete_objects.value)
|
if (total_copies_count > 1 && ! m_config.complete_objects.value)
|
||||||
return "The Spiral Vase option can only be used when printing a single object.";
|
return "The Spiral Vase option can only be used when printing a single object.";
|
||||||
if (this->regions.size() > 1)
|
if (m_regions.size() > 1)
|
||||||
return "The Spiral Vase option can only be used when printing single material objects.";
|
return "The Spiral Vase option can only be used when printing single material objects.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->has_wipe_tower() && ! this->objects.empty()) {
|
if (this->has_wipe_tower() && ! m_objects.empty()) {
|
||||||
#if 0
|
#if 0
|
||||||
for (auto dmr : this->config.nozzle_diameter.values)
|
for (auto dmr : m_config.nozzle_diameter.values)
|
||||||
if (std::abs(dmr - 0.4) > EPSILON)
|
if (std::abs(dmr - 0.4) > EPSILON)
|
||||||
return "The Wipe Tower is currently only supported for the 0.4mm nozzle diameter.";
|
return "The Wipe Tower is currently only supported for the 0.4mm nozzle diameter.";
|
||||||
#endif
|
#endif
|
||||||
if (this->config.gcode_flavor != gcfRepRap && this->config.gcode_flavor != gcfMarlin)
|
if (m_config.gcode_flavor != gcfRepRap && m_config.gcode_flavor != gcfMarlin)
|
||||||
return "The Wipe Tower is currently only supported for the Marlin and RepRap/Sprinter G-code flavors.";
|
return "The Wipe Tower is currently only supported for the Marlin and RepRap/Sprinter G-code flavors.";
|
||||||
if (! this->config.use_relative_e_distances)
|
if (! m_config.use_relative_e_distances)
|
||||||
return "The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).";
|
return "The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).";
|
||||||
SlicingParameters slicing_params0 = this->objects.front()->slicing_parameters();
|
SlicingParameters slicing_params0 = m_objects.front()->slicing_parameters();
|
||||||
for (PrintObject *object : this->objects) {
|
for (PrintObject *object : m_objects) {
|
||||||
SlicingParameters slicing_params = object->slicing_parameters();
|
SlicingParameters slicing_params = object->slicing_parameters();
|
||||||
if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
|
if (std::abs(slicing_params.first_print_layer_height - slicing_params0.first_print_layer_height) > EPSILON ||
|
||||||
std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
|
std::abs(slicing_params.layer_height - slicing_params0.layer_height ) > EPSILON)
|
||||||
return "The Wipe Tower is only supported for multiple objects if they have equal layer heigths";
|
return "The Wipe Tower is only supported for multiple objects if they have equal layer heigths";
|
||||||
if (slicing_params.raft_layers() != slicing_params0.raft_layers())
|
if (slicing_params.raft_layers() != slicing_params0.raft_layers())
|
||||||
return "The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers";
|
return "The Wipe Tower is only supported for multiple objects if they are printed over an equal number of raft layers";
|
||||||
if (object->config.support_material_contact_distance != this->objects.front()->config.support_material_contact_distance)
|
if (object->config().support_material_contact_distance != m_objects.front()->config().support_material_contact_distance)
|
||||||
return "The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance";
|
return "The Wipe Tower is only supported for multiple objects if they are printed with the same support_material_contact_distance";
|
||||||
if (! equal_layering(slicing_params, slicing_params0))
|
if (! equal_layering(slicing_params, slicing_params0))
|
||||||
return "The Wipe Tower is only supported for multiple objects if they are sliced equally.";
|
return "The Wipe Tower is only supported for multiple objects if they are sliced equally.";
|
||||||
|
@ -605,7 +619,7 @@ std::string Print::validate() const
|
||||||
object->layer_height_profile_valid = was_layer_height_profile_valid;
|
object->layer_height_profile_valid = was_layer_height_profile_valid;
|
||||||
for (size_t i = 5; i < object->layer_height_profile.size(); i += 2)
|
for (size_t i = 5; i < object->layer_height_profile.size(); i += 2)
|
||||||
if (object->layer_height_profile[i-1] > slicing_params.object_print_z_min + EPSILON &&
|
if (object->layer_height_profile[i-1] > slicing_params.object_print_z_min + EPSILON &&
|
||||||
std::abs(object->layer_height_profile[i] - object->config.layer_height) > EPSILON)
|
std::abs(object->layer_height_profile[i] - object->config().layer_height) > EPSILON)
|
||||||
return "The Wipe Tower is currently only supported with constant Z layer spacing. Layer editing is not allowed.";
|
return "The Wipe Tower is currently only supported with constant Z layer spacing. Layer editing is not allowed.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -618,12 +632,12 @@ std::string Print::validate() const
|
||||||
|
|
||||||
std::vector<double> nozzle_diameters;
|
std::vector<double> nozzle_diameters;
|
||||||
for (unsigned int extruder_id : extruders)
|
for (unsigned int extruder_id : extruders)
|
||||||
nozzle_diameters.push_back(this->config.nozzle_diameter.get_at(extruder_id));
|
nozzle_diameters.push_back(m_config.nozzle_diameter.get_at(extruder_id));
|
||||||
double min_nozzle_diameter = *std::min_element(nozzle_diameters.begin(), nozzle_diameters.end());
|
double min_nozzle_diameter = *std::min_element(nozzle_diameters.begin(), nozzle_diameters.end());
|
||||||
|
|
||||||
for (PrintObject *object : this->objects) {
|
for (PrintObject *object : m_objects) {
|
||||||
if ((object->config.support_material_extruder == -1 || object->config.support_material_interface_extruder == -1) &&
|
if ((object->config().support_material_extruder == -1 || object->config().support_material_interface_extruder == -1) &&
|
||||||
(object->config.raft_layers > 0 || object->config.support_material.value)) {
|
(object->config().raft_layers > 0 || object->config().support_material.value)) {
|
||||||
// The object has some form of support and either support_material_extruder or support_material_interface_extruder
|
// The object has some form of support and either support_material_extruder or support_material_interface_extruder
|
||||||
// will be printed with the current tool without a forced tool change. Play safe, assert that all object nozzles
|
// will be printed with the current tool without a forced tool change. Play safe, assert that all object nozzles
|
||||||
// are of the same diameter.
|
// are of the same diameter.
|
||||||
|
@ -634,16 +648,16 @@ std::string Print::validate() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate first_layer_height
|
// validate first_layer_height
|
||||||
double first_layer_height = object->config.get_abs_value("first_layer_height");
|
double first_layer_height = object->config().get_abs_value("first_layer_height");
|
||||||
double first_layer_min_nozzle_diameter;
|
double first_layer_min_nozzle_diameter;
|
||||||
if (object->config.raft_layers > 0) {
|
if (object->config().raft_layers > 0) {
|
||||||
// if we have raft layers, only support material extruder is used on first layer
|
// if we have raft layers, only support material extruder is used on first layer
|
||||||
size_t first_layer_extruder = object->config.raft_layers == 1
|
size_t first_layer_extruder = object->config().raft_layers == 1
|
||||||
? object->config.support_material_interface_extruder-1
|
? object->config().support_material_interface_extruder-1
|
||||||
: object->config.support_material_extruder-1;
|
: object->config().support_material_extruder-1;
|
||||||
first_layer_min_nozzle_diameter = (first_layer_extruder == size_t(-1)) ?
|
first_layer_min_nozzle_diameter = (first_layer_extruder == size_t(-1)) ?
|
||||||
min_nozzle_diameter :
|
min_nozzle_diameter :
|
||||||
this->config.nozzle_diameter.get_at(first_layer_extruder);
|
m_config.nozzle_diameter.get_at(first_layer_extruder);
|
||||||
} else {
|
} else {
|
||||||
// if we don't have raft layers, any nozzle diameter is potentially used in first layer
|
// if we don't have raft layers, any nozzle diameter is potentially used in first layer
|
||||||
first_layer_min_nozzle_diameter = min_nozzle_diameter;
|
first_layer_min_nozzle_diameter = min_nozzle_diameter;
|
||||||
|
@ -652,7 +666,7 @@ std::string Print::validate() const
|
||||||
return "First layer height can't be greater than nozzle diameter";
|
return "First layer height can't be greater than nozzle diameter";
|
||||||
|
|
||||||
// validate layer_height
|
// validate layer_height
|
||||||
if (object->config.layer_height.value > min_nozzle_diameter)
|
if (object->config().layer_height.value > min_nozzle_diameter)
|
||||||
return "Layer height can't be greater than nozzle diameter";
|
return "Layer height can't be greater than nozzle diameter";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -665,7 +679,7 @@ std::string Print::validate() const
|
||||||
BoundingBox Print::bounding_box() const
|
BoundingBox Print::bounding_box() const
|
||||||
{
|
{
|
||||||
BoundingBox bb;
|
BoundingBox bb;
|
||||||
for (const PrintObject *object : this->objects)
|
for (const PrintObject *object : m_objects)
|
||||||
for (Point copy : object->_shifted_copies) {
|
for (Point copy : object->_shifted_copies) {
|
||||||
bb.merge(copy);
|
bb.merge(copy);
|
||||||
copy.translate(object->size);
|
copy.translate(object->size);
|
||||||
|
@ -683,7 +697,7 @@ BoundingBox Print::total_bounding_box() const
|
||||||
BoundingBox bb = this->bounding_box();
|
BoundingBox bb = this->bounding_box();
|
||||||
|
|
||||||
// we need to offset the objects bounding box by at least half the perimeters extrusion width
|
// we need to offset the objects bounding box by at least half the perimeters extrusion width
|
||||||
Flow perimeter_flow = this->objects.front()->get_layer(0)->get_region(0)->flow(frPerimeter);
|
Flow perimeter_flow = m_objects.front()->get_layer(0)->get_region(0)->flow(frPerimeter);
|
||||||
double extra = perimeter_flow.width/2;
|
double extra = perimeter_flow.width/2;
|
||||||
|
|
||||||
// consider support material
|
// consider support material
|
||||||
|
@ -692,18 +706,18 @@ BoundingBox Print::total_bounding_box() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// consider brim and skirt
|
// consider brim and skirt
|
||||||
if (this->config.brim_width.value > 0) {
|
if (m_config.brim_width.value > 0) {
|
||||||
Flow brim_flow = this->brim_flow();
|
Flow brim_flow = this->brim_flow();
|
||||||
extra = std::max(extra, this->config.brim_width.value + brim_flow.width/2);
|
extra = std::max(extra, m_config.brim_width.value + brim_flow.width/2);
|
||||||
}
|
}
|
||||||
if (this->has_skirt()) {
|
if (this->has_skirt()) {
|
||||||
int skirts = this->config.skirts.value;
|
int skirts = m_config.skirts.value;
|
||||||
if (skirts == 0 && this->has_infinite_skirt()) skirts = 1;
|
if (skirts == 0 && this->has_infinite_skirt()) skirts = 1;
|
||||||
Flow skirt_flow = this->skirt_flow();
|
Flow skirt_flow = this->skirt_flow();
|
||||||
extra = std::max(
|
extra = std::max(
|
||||||
extra,
|
extra,
|
||||||
this->config.brim_width.value
|
m_config.brim_width.value
|
||||||
+ this->config.skirt_distance.value
|
+ m_config.skirt_distance.value
|
||||||
+ skirts * skirt_flow.spacing()
|
+ skirts * skirt_flow.spacing()
|
||||||
+ skirt_flow.width/2
|
+ skirt_flow.width/2
|
||||||
);
|
);
|
||||||
|
@ -717,17 +731,17 @@ BoundingBox Print::total_bounding_box() const
|
||||||
|
|
||||||
double Print::skirt_first_layer_height() const
|
double Print::skirt_first_layer_height() const
|
||||||
{
|
{
|
||||||
if (this->objects.empty()) CONFESS("skirt_first_layer_height() can't be called without PrintObjects");
|
if (m_objects.empty()) CONFESS("skirt_first_layer_height() can't be called without PrintObjects");
|
||||||
return this->objects.front()->config.get_abs_value("first_layer_height");
|
return m_objects.front()->config().get_abs_value("first_layer_height");
|
||||||
}
|
}
|
||||||
|
|
||||||
Flow Print::brim_flow() const
|
Flow Print::brim_flow() const
|
||||||
{
|
{
|
||||||
ConfigOptionFloatOrPercent width = this->config.first_layer_extrusion_width;
|
ConfigOptionFloatOrPercent width = m_config.first_layer_extrusion_width;
|
||||||
if (width.value == 0)
|
if (width.value == 0)
|
||||||
width = this->regions.front()->config.perimeter_extrusion_width;
|
width = m_regions.front()->config().perimeter_extrusion_width;
|
||||||
if (width.value == 0)
|
if (width.value == 0)
|
||||||
width = this->objects.front()->config.extrusion_width;
|
width = m_objects.front()->config().extrusion_width;
|
||||||
|
|
||||||
/* We currently use a random region's perimeter extruder.
|
/* We currently use a random region's perimeter extruder.
|
||||||
While this works for most cases, we should probably consider all of the perimeter
|
While this works for most cases, we should probably consider all of the perimeter
|
||||||
|
@ -737,7 +751,7 @@ Flow Print::brim_flow() const
|
||||||
return Flow::new_from_config_width(
|
return Flow::new_from_config_width(
|
||||||
frPerimeter,
|
frPerimeter,
|
||||||
width,
|
width,
|
||||||
this->config.nozzle_diameter.get_at(this->regions.front()->config.perimeter_extruder-1),
|
m_config.nozzle_diameter.get_at(m_regions.front()->config().perimeter_extruder-1),
|
||||||
this->skirt_first_layer_height(),
|
this->skirt_first_layer_height(),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
@ -745,11 +759,11 @@ Flow Print::brim_flow() const
|
||||||
|
|
||||||
Flow Print::skirt_flow() const
|
Flow Print::skirt_flow() const
|
||||||
{
|
{
|
||||||
ConfigOptionFloatOrPercent width = this->config.first_layer_extrusion_width;
|
ConfigOptionFloatOrPercent width = m_config.first_layer_extrusion_width;
|
||||||
if (width.value == 0)
|
if (width.value == 0)
|
||||||
width = this->regions.front()->config.perimeter_extrusion_width;
|
width = m_regions.front()->config().perimeter_extrusion_width;
|
||||||
if (width.value == 0)
|
if (width.value == 0)
|
||||||
width = this->objects.front()->config.extrusion_width;
|
width = m_objects.front()->config().extrusion_width;
|
||||||
|
|
||||||
/* We currently use a random object's support material extruder.
|
/* We currently use a random object's support material extruder.
|
||||||
While this works for most cases, we should probably consider all of the support material
|
While this works for most cases, we should probably consider all of the support material
|
||||||
|
@ -759,7 +773,7 @@ Flow Print::skirt_flow() const
|
||||||
return Flow::new_from_config_width(
|
return Flow::new_from_config_width(
|
||||||
frPerimeter,
|
frPerimeter,
|
||||||
width,
|
width,
|
||||||
this->config.nozzle_diameter.get_at(this->objects.front()->config.support_material_extruder-1),
|
m_config.nozzle_diameter.get_at(m_objects.front()->config().support_material_extruder-1),
|
||||||
this->skirt_first_layer_height(),
|
this->skirt_first_layer_height(),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
@ -767,7 +781,7 @@ Flow Print::skirt_flow() const
|
||||||
|
|
||||||
PrintRegionConfig Print::_region_config_from_model_volume(const ModelVolume &volume)
|
PrintRegionConfig Print::_region_config_from_model_volume(const ModelVolume &volume)
|
||||||
{
|
{
|
||||||
PrintRegionConfig config = this->default_region_config;
|
PrintRegionConfig config = this->default_region_config();
|
||||||
normalize_and_apply_config(config, volume.get_object()->config);
|
normalize_and_apply_config(config, volume.get_object()->config);
|
||||||
normalize_and_apply_config(config, volume.config);
|
normalize_and_apply_config(config, volume.config);
|
||||||
if (! volume.material_id().empty())
|
if (! volume.material_id().empty())
|
||||||
|
@ -777,7 +791,7 @@ PrintRegionConfig Print::_region_config_from_model_volume(const ModelVolume &vol
|
||||||
|
|
||||||
bool Print::has_support_material() const
|
bool Print::has_support_material() const
|
||||||
{
|
{
|
||||||
for (const PrintObject *object : this->objects)
|
for (const PrintObject *object : m_objects)
|
||||||
if (object->has_support_material())
|
if (object->has_support_material())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -791,7 +805,7 @@ void Print::auto_assign_extruders(ModelObject* model_object) const
|
||||||
if (model_object->volumes.size() < 2)
|
if (model_object->volumes.size() < 2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// size_t extruders = this->config.nozzle_diameter.values.size();
|
// size_t extruders = m_config.nozzle_diameter.values.size();
|
||||||
for (size_t volume_id = 0; volume_id < model_object->volumes.size(); ++ volume_id) {
|
for (size_t volume_id = 0; volume_id < model_object->volumes.size(); ++ volume_id) {
|
||||||
ModelVolume *volume = model_object->volumes[volume_id];
|
ModelVolume *volume = model_object->volumes[volume_id];
|
||||||
//FIXME Vojtech: This assigns an extruder ID even to a modifier volume, if it has a material assigned.
|
//FIXME Vojtech: This assigns an extruder ID even to a modifier volume, if it has a material assigned.
|
||||||
|
@ -804,44 +818,44 @@ void Print::auto_assign_extruders(ModelObject* model_object) const
|
||||||
void Print::process()
|
void Print::process()
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "Staring the slicing process.";
|
BOOST_LOG_TRIVIAL(info) << "Staring the slicing process.";
|
||||||
for (PrintObject *obj : this->objects)
|
for (PrintObject *obj : m_objects)
|
||||||
obj->make_perimeters();
|
obj->make_perimeters();
|
||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
this->set_status(70, "Infilling layers");
|
this->set_status(70, "Infilling layers");
|
||||||
for (PrintObject *obj : this->objects)
|
for (PrintObject *obj : m_objects)
|
||||||
obj->infill();
|
obj->infill();
|
||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
for (PrintObject *obj : this->objects)
|
for (PrintObject *obj : m_objects)
|
||||||
obj->generate_support_material();
|
obj->generate_support_material();
|
||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
if (! m_state.is_done(psSkirt)) {
|
if (! m_state.is_done(psSkirt)) {
|
||||||
this->set_started(psSkirt);
|
this->set_started(psSkirt);
|
||||||
this->skirt.clear();
|
m_skirt.clear();
|
||||||
if (this->has_skirt()) {
|
if (this->has_skirt()) {
|
||||||
this->set_status(88, "Generating skirt");
|
this->set_status(88, "Generating skirt");
|
||||||
this->_make_skirt();
|
this->_make_skirt();
|
||||||
}
|
}
|
||||||
m_state.set_done(psSkirt);
|
this->set_done(psSkirt);
|
||||||
}
|
}
|
||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
if (! m_state.is_done(psBrim)) {
|
if (! m_state.is_done(psBrim)) {
|
||||||
this->set_started(psBrim);
|
this->set_started(psBrim);
|
||||||
this->brim.clear();
|
m_brim.clear();
|
||||||
if (this->config.brim_width > 0) {
|
if (m_config.brim_width > 0) {
|
||||||
this->set_status(88, "Generating brim");
|
this->set_status(88, "Generating brim");
|
||||||
this->_make_brim();
|
this->_make_brim();
|
||||||
}
|
}
|
||||||
m_state.set_done(psBrim);
|
this->set_done(psBrim);
|
||||||
}
|
}
|
||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
if (! m_state.is_done(psWipeTower)) {
|
if (! m_state.is_done(psWipeTower)) {
|
||||||
this->set_started(psWipeTower);
|
this->set_started(psWipeTower);
|
||||||
this->_clear_wipe_tower();
|
m_wipe_tower_data.clear();
|
||||||
if (this->has_wipe_tower()) {
|
if (this->has_wipe_tower()) {
|
||||||
//this->set_status(95, "Generating wipe tower");
|
//this->set_status(95, "Generating wipe tower");
|
||||||
this->_make_wipe_tower();
|
this->_make_wipe_tower();
|
||||||
}
|
}
|
||||||
m_state.set_done(psWipeTower);
|
this->set_done(psWipeTower);
|
||||||
}
|
}
|
||||||
BOOST_LOG_TRIVIAL(info) << "Slicing process finished.";
|
BOOST_LOG_TRIVIAL(info) << "Slicing process finished.";
|
||||||
}
|
}
|
||||||
|
@ -883,20 +897,20 @@ void Print::_make_skirt()
|
||||||
// prepended to the first 'n' layers (with 'n' = skirt_height).
|
// prepended to the first 'n' layers (with 'n' = skirt_height).
|
||||||
// $skirt_height_z in this case is the highest possible skirt height for safety.
|
// $skirt_height_z in this case is the highest possible skirt height for safety.
|
||||||
coordf_t skirt_height_z = 0.;
|
coordf_t skirt_height_z = 0.;
|
||||||
for (const PrintObject *object : this->objects) {
|
for (const PrintObject *object : m_objects) {
|
||||||
size_t skirt_layers = this->has_infinite_skirt() ?
|
size_t skirt_layers = this->has_infinite_skirt() ?
|
||||||
object->layer_count() :
|
object->layer_count() :
|
||||||
std::min(size_t(this->config.skirt_height.value), object->layer_count());
|
std::min(size_t(m_config.skirt_height.value), object->layer_count());
|
||||||
skirt_height_z = std::max(skirt_height_z, object->layers[skirt_layers-1]->print_z);
|
skirt_height_z = std::max(skirt_height_z, object->m_layers[skirt_layers-1]->print_z);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect points from all layers contained in skirt height.
|
// Collect points from all layers contained in skirt height.
|
||||||
Points points;
|
Points points;
|
||||||
for (const PrintObject *object : this->objects) {
|
for (const PrintObject *object : m_objects) {
|
||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
Points object_points;
|
Points object_points;
|
||||||
// Get object layers up to skirt_height_z.
|
// Get object layers up to skirt_height_z.
|
||||||
for (const Layer *layer : object->layers) {
|
for (const Layer *layer : object->m_layers) {
|
||||||
if (layer->print_z > skirt_height_z)
|
if (layer->print_z > skirt_height_z)
|
||||||
break;
|
break;
|
||||||
for (const ExPolygon &expoly : layer->slices.expolygons)
|
for (const ExPolygon &expoly : layer->slices.expolygons)
|
||||||
|
@ -904,7 +918,7 @@ void Print::_make_skirt()
|
||||||
append(object_points, expoly.contour.points);
|
append(object_points, expoly.contour.points);
|
||||||
}
|
}
|
||||||
// Get support layers up to skirt_height_z.
|
// Get support layers up to skirt_height_z.
|
||||||
for (const SupportLayer *layer : object->support_layers) {
|
for (const SupportLayer *layer : object->support_layers()) {
|
||||||
if (layer->print_z > skirt_height_z)
|
if (layer->print_z > skirt_height_z)
|
||||||
break;
|
break;
|
||||||
for (const ExtrusionEntity *extrusion_entity : layer->support_fills.entities)
|
for (const ExtrusionEntity *extrusion_entity : layer->support_fills.entities)
|
||||||
|
@ -942,18 +956,18 @@ void Print::_make_skirt()
|
||||||
extruders_e_per_mm.reserve(set_extruders.size());
|
extruders_e_per_mm.reserve(set_extruders.size());
|
||||||
for (auto &extruder_id : set_extruders) {
|
for (auto &extruder_id : set_extruders) {
|
||||||
extruders.push_back(extruder_id);
|
extruders.push_back(extruder_id);
|
||||||
extruders_e_per_mm.push_back(Extruder((unsigned int)extruder_id, &this->config).e_per_mm(mm3_per_mm));
|
extruders_e_per_mm.push_back(Extruder((unsigned int)extruder_id, &m_config).e_per_mm(mm3_per_mm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Number of skirt loops per skirt layer.
|
// Number of skirt loops per skirt layer.
|
||||||
int n_skirts = this->config.skirts.value;
|
int n_skirts = m_config.skirts.value;
|
||||||
if (this->has_infinite_skirt() && n_skirts == 0)
|
if (this->has_infinite_skirt() && n_skirts == 0)
|
||||||
n_skirts = 1;
|
n_skirts = 1;
|
||||||
|
|
||||||
// Initial offset of the brim inner edge from the object (possible with a support & raft).
|
// Initial offset of the brim inner edge from the object (possible with a support & raft).
|
||||||
// The skirt will touch the brim if the brim is extruded.
|
// The skirt will touch the brim if the brim is extruded.
|
||||||
coord_t distance = scale_(std::max(this->config.skirt_distance.value, this->config.brim_width.value));
|
coord_t distance = scale_(std::max(m_config.skirt_distance.value, m_config.brim_width.value));
|
||||||
// Draw outlines from outside to inside.
|
// Draw outlines from outside to inside.
|
||||||
// Loop while we have less skirts than required or any extruder hasn't reached the min length if any.
|
// Loop while we have less skirts than required or any extruder hasn't reached the min length if any.
|
||||||
std::vector<coordf_t> extruded_length(extruders.size(), 0.);
|
std::vector<coordf_t> extruded_length(extruders.size(), 0.);
|
||||||
|
@ -978,16 +992,16 @@ void Print::_make_skirt()
|
||||||
first_layer_height // this will be overridden at G-code export time
|
first_layer_height // this will be overridden at G-code export time
|
||||||
)));
|
)));
|
||||||
eloop.paths.back().polyline = loop.split_at_first_point();
|
eloop.paths.back().polyline = loop.split_at_first_point();
|
||||||
this->skirt.append(eloop);
|
m_skirt.append(eloop);
|
||||||
if (this->config.min_skirt_length.value > 0) {
|
if (m_config.min_skirt_length.value > 0) {
|
||||||
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
|
// The skirt length is limited. Sum the total amount of filament length extruded, in mm.
|
||||||
extruded_length[extruder_idx] += unscale(loop.length()) * extruders_e_per_mm[extruder_idx];
|
extruded_length[extruder_idx] += unscale(loop.length()) * extruders_e_per_mm[extruder_idx];
|
||||||
if (extruded_length[extruder_idx] < this->config.min_skirt_length.value) {
|
if (extruded_length[extruder_idx] < m_config.min_skirt_length.value) {
|
||||||
// Not extruded enough yet with the current extruder. Add another loop.
|
// Not extruded enough yet with the current extruder. Add another loop.
|
||||||
if (i == 1)
|
if (i == 1)
|
||||||
++ i;
|
++ i;
|
||||||
} else {
|
} else {
|
||||||
assert(extruded_length[extruder_idx] >= this->config.min_skirt_length.value);
|
assert(extruded_length[extruder_idx] >= m_config.min_skirt_length.value);
|
||||||
// Enough extruded with the current extruder. Extrude with the next one,
|
// Enough extruded with the current extruder. Extrude with the next one,
|
||||||
// until the prescribed number of skirt loops is extruded.
|
// until the prescribed number of skirt loops is extruded.
|
||||||
if (extruder_idx + 1 < extruders.size())
|
if (extruder_idx + 1 < extruders.size())
|
||||||
|
@ -998,7 +1012,7 @@ void Print::_make_skirt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Brims were generated inside out, reverse to print the outmost contour first.
|
// Brims were generated inside out, reverse to print the outmost contour first.
|
||||||
this->skirt.reverse();
|
m_skirt.reverse();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Print::_make_brim()
|
void Print::_make_brim()
|
||||||
|
@ -1006,13 +1020,13 @@ void Print::_make_brim()
|
||||||
// Brim is only printed on first layer and uses perimeter extruder.
|
// Brim is only printed on first layer and uses perimeter extruder.
|
||||||
Flow flow = this->brim_flow();
|
Flow flow = this->brim_flow();
|
||||||
Polygons islands;
|
Polygons islands;
|
||||||
for (PrintObject *object : this->objects) {
|
for (PrintObject *object : m_objects) {
|
||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
Polygons object_islands;
|
Polygons object_islands;
|
||||||
for (ExPolygon &expoly : object->layers.front()->slices.expolygons)
|
for (ExPolygon &expoly : object->m_layers.front()->slices.expolygons)
|
||||||
object_islands.push_back(expoly.contour);
|
object_islands.push_back(expoly.contour);
|
||||||
if (! object->support_layers.empty())
|
if (! object->support_layers().empty())
|
||||||
object->support_layers.front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON));
|
object->support_layers().front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON));
|
||||||
islands.reserve(islands.size() + object_islands.size() * object->_shifted_copies.size());
|
islands.reserve(islands.size() + object_islands.size() * object->_shifted_copies.size());
|
||||||
for (const Point &pt : object->_shifted_copies)
|
for (const Point &pt : object->_shifted_copies)
|
||||||
for (Polygon &poly : object_islands) {
|
for (Polygon &poly : object_islands) {
|
||||||
|
@ -1021,7 +1035,7 @@ void Print::_make_brim()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Polygons loops;
|
Polygons loops;
|
||||||
size_t num_loops = size_t(floor(this->config.brim_width.value / flow.width));
|
size_t num_loops = size_t(floor(m_config.brim_width.value / flow.width));
|
||||||
for (size_t i = 0; i < num_loops; ++ i) {
|
for (size_t i = 0; i < num_loops; ++ i) {
|
||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
islands = offset(islands, float(flow.scaled_spacing()), jtSquare);
|
islands = offset(islands, float(flow.scaled_spacing()), jtSquare);
|
||||||
|
@ -1037,32 +1051,24 @@ void Print::_make_brim()
|
||||||
|
|
||||||
loops = union_pt_chained(loops, false);
|
loops = union_pt_chained(loops, false);
|
||||||
std::reverse(loops.begin(), loops.end());
|
std::reverse(loops.begin(), loops.end());
|
||||||
extrusion_entities_append_loops(this->brim.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(this->skirt_first_layer_height()));
|
extrusion_entities_append_loops(m_brim.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(this->skirt_first_layer_height()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wipe tower support.
|
// Wipe tower support.
|
||||||
bool Print::has_wipe_tower() const
|
bool Print::has_wipe_tower() const
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
this->config.single_extruder_multi_material.value &&
|
m_config.single_extruder_multi_material.value &&
|
||||||
! this->config.spiral_vase.value &&
|
! m_config.spiral_vase.value &&
|
||||||
this->config.wipe_tower.value &&
|
m_config.wipe_tower.value &&
|
||||||
this->config.nozzle_diameter.values.size() > 1;
|
m_config.nozzle_diameter.values.size() > 1;
|
||||||
}
|
|
||||||
|
|
||||||
void Print::_clear_wipe_tower()
|
|
||||||
{
|
|
||||||
m_tool_ordering.clear();
|
|
||||||
m_wipe_tower_priming.reset(nullptr);
|
|
||||||
m_wipe_tower_tool_changes.clear();
|
|
||||||
m_wipe_tower_final_purge.reset(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Print::_make_wipe_tower()
|
void Print::_make_wipe_tower()
|
||||||
{
|
{
|
||||||
// Let the ToolOrdering class know there will be initial priming extrusions at the start of the print.
|
// Let the ToolOrdering class know there will be initial priming extrusions at the start of the print.
|
||||||
m_tool_ordering = ToolOrdering(*this, (unsigned int)-1, true);
|
m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, true);
|
||||||
if (! m_tool_ordering.has_wipe_tower())
|
if (! m_wipe_tower_data.tool_ordering.has_wipe_tower())
|
||||||
// Don't generate any wipe tower.
|
// Don't generate any wipe tower.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1072,33 +1078,31 @@ void Print::_make_wipe_tower()
|
||||||
// see https://github.com/prusa3d/Slic3r/issues/607
|
// see https://github.com/prusa3d/Slic3r/issues/607
|
||||||
{
|
{
|
||||||
size_t idx_begin = size_t(-1);
|
size_t idx_begin = size_t(-1);
|
||||||
size_t idx_end = m_tool_ordering.layer_tools().size();
|
size_t idx_end = m_wipe_tower_data.tool_ordering.layer_tools().size();
|
||||||
// Find the first wipe tower layer, which does not have a counterpart in an object or a support layer.
|
// Find the first wipe tower layer, which does not have a counterpart in an object or a support layer.
|
||||||
for (size_t i = 0; i < idx_end; ++ i) {
|
for (size_t i = 0; i < idx_end; ++ i) {
|
||||||
const ToolOrdering::LayerTools < = m_tool_ordering.layer_tools()[i];
|
const ToolOrdering::LayerTools < = m_wipe_tower_data.tool_ordering.layer_tools()[i];
|
||||||
if (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support) {
|
if (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support) {
|
||||||
idx_begin = i;
|
idx_begin = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (idx_begin != size_t(-1)) {
|
if (idx_begin != size_t(-1)) {
|
||||||
// Find the position in this->objects.first()->support_layers to insert these new support layers.
|
// Find the position in m_objects.first()->support_layers to insert these new support layers.
|
||||||
double wipe_tower_new_layer_print_z_first = m_tool_ordering.layer_tools()[idx_begin].print_z;
|
double wipe_tower_new_layer_print_z_first = m_wipe_tower_data.tool_ordering.layer_tools()[idx_begin].print_z;
|
||||||
SupportLayerPtrs::iterator it_layer = this->objects.front()->support_layers.begin();
|
SupportLayerPtrs::const_iterator it_layer = m_objects.front()->support_layers().begin();
|
||||||
SupportLayerPtrs::iterator it_end = this->objects.front()->support_layers.end();
|
SupportLayerPtrs::const_iterator it_end = m_objects.front()->support_layers().end();
|
||||||
for (; it_layer != it_end && (*it_layer)->print_z - EPSILON < wipe_tower_new_layer_print_z_first; ++ it_layer);
|
for (; it_layer != it_end && (*it_layer)->print_z - EPSILON < wipe_tower_new_layer_print_z_first; ++ it_layer);
|
||||||
// Find the stopper of the sequence of wipe tower layers, which do not have a counterpart in an object or a support layer.
|
// Find the stopper of the sequence of wipe tower layers, which do not have a counterpart in an object or a support layer.
|
||||||
for (size_t i = idx_begin; i < idx_end; ++ i) {
|
for (size_t i = idx_begin; i < idx_end; ++ i) {
|
||||||
ToolOrdering::LayerTools < = const_cast<ToolOrdering::LayerTools&>(m_tool_ordering.layer_tools()[i]);
|
ToolOrdering::LayerTools < = const_cast<ToolOrdering::LayerTools&>(m_wipe_tower_data.tool_ordering.layer_tools()[i]);
|
||||||
if (! (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support))
|
if (! (lt.has_wipe_tower && ! lt.has_object && ! lt.has_support))
|
||||||
break;
|
break;
|
||||||
lt.has_support = true;
|
lt.has_support = true;
|
||||||
// Insert the new support layer.
|
// Insert the new support layer.
|
||||||
double height = lt.print_z - m_tool_ordering.layer_tools()[i-1].print_z;
|
double height = lt.print_z - m_wipe_tower_data.tool_ordering.layer_tools()[i-1].print_z;
|
||||||
//FIXME the support layer ID is set to -1, as Vojtech hopes it is not being used anyway.
|
//FIXME the support layer ID is set to -1, as Vojtech hopes it is not being used anyway.
|
||||||
auto *new_layer = new SupportLayer(size_t(-1), this->objects.front(),
|
it_layer = m_objects.front()->insert_support_layer(it_layer, size_t(-1), height, lt.print_z, lt.print_z - 0.5 * height);
|
||||||
height, lt.print_z, lt.print_z - 0.5 * height);
|
|
||||||
it_layer = this->objects.front()->support_layers.insert(it_layer, new_layer);
|
|
||||||
++ it_layer;
|
++ it_layer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1107,9 +1111,9 @@ void Print::_make_wipe_tower()
|
||||||
|
|
||||||
// Initialize the wipe tower.
|
// Initialize the wipe tower.
|
||||||
WipeTowerPrusaMM wipe_tower(
|
WipeTowerPrusaMM wipe_tower(
|
||||||
float(this->config.wipe_tower_x.value), float(this->config.wipe_tower_y.value),
|
float(m_config.wipe_tower_x.value), float(m_config.wipe_tower_y.value),
|
||||||
float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value),
|
float(m_config.wipe_tower_width.value), float(m_config.wipe_tower_per_color_wipe.value),
|
||||||
m_tool_ordering.first_extruder());
|
m_wipe_tower_data.tool_ordering.first_extruder());
|
||||||
|
|
||||||
//wipe_tower.set_retract();
|
//wipe_tower.set_retract();
|
||||||
//wipe_tower.set_zhop();
|
//wipe_tower.set_zhop();
|
||||||
|
@ -1118,29 +1122,29 @@ void Print::_make_wipe_tower()
|
||||||
for (size_t i = 0; i < 4; ++ i)
|
for (size_t i = 0; i < 4; ++ i)
|
||||||
wipe_tower.set_extruder(
|
wipe_tower.set_extruder(
|
||||||
i,
|
i,
|
||||||
WipeTowerPrusaMM::parse_material(this->config.filament_type.get_at(i).c_str()),
|
WipeTowerPrusaMM::parse_material(m_config.filament_type.get_at(i).c_str()),
|
||||||
this->config.temperature.get_at(i),
|
m_config.temperature.get_at(i),
|
||||||
this->config.first_layer_temperature.get_at(i));
|
m_config.first_layer_temperature.get_at(i));
|
||||||
|
|
||||||
// When printing the first layer's wipe tower, the first extruder is expected to be active and primed.
|
// When printing the first layer's wipe tower, the first extruder is expected to be active and primed.
|
||||||
// Therefore the number of wipe sections at the wipe tower will be (m_tool_ordering.front().extruders-1) at the 1st layer.
|
// Therefore the number of wipe sections at the wipe tower will be (m_wipe_tower_data.tool_ordering.front().extruders-1) at the 1st layer.
|
||||||
// The following variable is true if the last priming section cannot be squeezed inside the wipe tower.
|
// The following variable is true if the last priming section cannot be squeezed inside the wipe tower.
|
||||||
bool last_priming_wipe_full = m_tool_ordering.front().extruders.size() > m_tool_ordering.front().wipe_tower_partitions;
|
bool last_priming_wipe_full = m_wipe_tower_data.tool_ordering.front().extruders.size() > m_wipe_tower_data.tool_ordering.front().wipe_tower_partitions;
|
||||||
|
|
||||||
m_wipe_tower_priming = Slic3r::make_unique<WipeTower::ToolChangeResult>(
|
m_wipe_tower_data.priming = Slic3r::make_unique<WipeTower::ToolChangeResult>(
|
||||||
wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full, WipeTower::PURPOSE_EXTRUDE));
|
wipe_tower.prime(this->skirt_first_layer_height(), m_wipe_tower_data.tool_ordering.all_extruders(), ! last_priming_wipe_full, WipeTower::PURPOSE_EXTRUDE));
|
||||||
|
|
||||||
// Generate the wipe tower layers.
|
// Generate the wipe tower layers.
|
||||||
m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size());
|
m_wipe_tower_data.tool_changes.reserve(m_wipe_tower_data.tool_ordering.layer_tools().size());
|
||||||
// Set current_extruder_id to the last extruder primed.
|
// Set current_extruder_id to the last extruder primed.
|
||||||
unsigned int current_extruder_id = m_tool_ordering.all_extruders().back();
|
unsigned int current_extruder_id = m_wipe_tower_data.tool_ordering.all_extruders().back();
|
||||||
for (const ToolOrdering::LayerTools &layer_tools : m_tool_ordering.layer_tools()) {
|
for (const ToolOrdering::LayerTools &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) {
|
||||||
this->throw_if_canceled();
|
this->throw_if_canceled();
|
||||||
if (! layer_tools.has_wipe_tower)
|
if (! layer_tools.has_wipe_tower)
|
||||||
// This is a support only layer, or the wipe tower does not reach to this height.
|
// This is a support only layer, or the wipe tower does not reach to this height.
|
||||||
continue;
|
continue;
|
||||||
bool first_layer = &layer_tools == &m_tool_ordering.front();
|
bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front();
|
||||||
bool last_layer = &layer_tools == &m_tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0;
|
bool last_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0;
|
||||||
wipe_tower.set_layer(
|
wipe_tower.set_layer(
|
||||||
float(layer_tools.print_z),
|
float(layer_tools.print_z),
|
||||||
float(layer_tools.wipe_tower_layer_height),
|
float(layer_tools.wipe_tower_layer_height),
|
||||||
|
@ -1151,7 +1155,7 @@ void Print::_make_wipe_tower()
|
||||||
for (unsigned int extruder_id : layer_tools.extruders)
|
for (unsigned int extruder_id : layer_tools.extruders)
|
||||||
// Call the wipe_tower.tool_change() at the first layer for the initial extruder
|
// Call the wipe_tower.tool_change() at the first layer for the initial extruder
|
||||||
// to extrude the wipe tower brim,
|
// to extrude the wipe tower brim,
|
||||||
if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) ||
|
if ((first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back()) ||
|
||||||
// or when an extruder shall be switched.
|
// or when an extruder shall be switched.
|
||||||
extruder_id != current_extruder_id) {
|
extruder_id != current_extruder_id) {
|
||||||
tool_changes.emplace_back(wipe_tower.tool_change(extruder_id, extruder_id == layer_tools.extruders.back(), WipeTower::PURPOSE_EXTRUDE));
|
tool_changes.emplace_back(wipe_tower.tool_change(extruder_id, extruder_id == layer_tools.extruders.back(), WipeTower::PURPOSE_EXTRUDE));
|
||||||
|
@ -1175,48 +1179,49 @@ void Print::_make_wipe_tower()
|
||||||
tool_changes.pop_back();
|
tool_changes.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_wipe_tower_tool_changes.emplace_back(std::move(tool_changes));
|
m_wipe_tower_data.tool_changes.emplace_back(std::move(tool_changes));
|
||||||
if (last_layer)
|
if (last_layer)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unload the current filament over the purge tower.
|
// Unload the current filament over the purge tower.
|
||||||
coordf_t layer_height = this->objects.front()->config.layer_height.value;
|
coordf_t layer_height = m_objects.front()->config().layer_height.value;
|
||||||
if (m_tool_ordering.back().wipe_tower_partitions > 0) {
|
if (m_wipe_tower_data.tool_ordering.back().wipe_tower_partitions > 0) {
|
||||||
// The wipe tower goes up to the last layer of the print.
|
// The wipe tower goes up to the last layer of the print.
|
||||||
if (wipe_tower.layer_finished()) {
|
if (wipe_tower.layer_finished()) {
|
||||||
// The wipe tower is printed to the top of the print and it has no space left for the final extruder purge.
|
// The wipe tower is printed to the top of the print and it has no space left for the final extruder purge.
|
||||||
// Lift Z to the next layer.
|
// Lift Z to the next layer.
|
||||||
wipe_tower.set_layer(float(m_tool_ordering.back().print_z + layer_height), float(layer_height), 0, false, true);
|
wipe_tower.set_layer(float(m_wipe_tower_data.tool_ordering.back().print_z + layer_height), float(layer_height), 0, false, true);
|
||||||
} else {
|
} else {
|
||||||
// There is yet enough space at this layer of the wipe tower for the final purge.
|
// There is yet enough space at this layer of the wipe tower for the final purge.
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The wipe tower does not reach the last print layer, perform the pruge at the last print layer.
|
// The wipe tower does not reach the last print layer, perform the pruge at the last print layer.
|
||||||
assert(m_tool_ordering.back().wipe_tower_partitions == 0);
|
assert(m_wipe_tower_data.tool_ordering.back().wipe_tower_partitions == 0);
|
||||||
wipe_tower.set_layer(float(m_tool_ordering.back().print_z), float(layer_height), 0, false, true);
|
wipe_tower.set_layer(float(m_wipe_tower_data.tool_ordering.back().print_z), float(layer_height), 0, false, true);
|
||||||
}
|
}
|
||||||
m_wipe_tower_final_purge = Slic3r::make_unique<WipeTower::ToolChangeResult>(
|
m_wipe_tower_data.final_purge = Slic3r::make_unique<WipeTower::ToolChangeResult>(
|
||||||
wipe_tower.tool_change((unsigned int)-1, false, WipeTower::PURPOSE_EXTRUDE));
|
wipe_tower.tool_change((unsigned int)-1, false, WipeTower::PURPOSE_EXTRUDE));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Print::output_filename()
|
std::string Print::output_filename() const
|
||||||
{
|
{
|
||||||
this->placeholder_parser.update_timestamp();
|
DynamicConfig cfg_timestamp;
|
||||||
|
PlaceholderParser::update_timestamp(cfg_timestamp);
|
||||||
try {
|
try {
|
||||||
return this->placeholder_parser.process(this->config.output_filename_format.value, 0);
|
return this->placeholder_parser().process(m_config.output_filename_format.value, 0, &cfg_timestamp);
|
||||||
} catch (std::runtime_error &err) {
|
} catch (std::runtime_error &err) {
|
||||||
throw std::runtime_error(std::string("Failed processing of the output_filename_format template.\n") + err.what());
|
throw std::runtime_error(std::string("Failed processing of the output_filename_format template.\n") + err.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Print::output_filepath(const std::string &path)
|
std::string Print::output_filepath(const std::string &path) const
|
||||||
{
|
{
|
||||||
// if we were supplied no path, generate an automatic one based on our first object's input file
|
// if we were supplied no path, generate an automatic one based on our first object's input file
|
||||||
if (path.empty()) {
|
if (path.empty()) {
|
||||||
// get the first input file name
|
// get the first input file name
|
||||||
std::string input_file;
|
std::string input_file;
|
||||||
for (const PrintObject *object : this->objects) {
|
for (const PrintObject *object : m_objects) {
|
||||||
input_file = object->model_object()->input_file;
|
input_file = object->model_object()->input_file;
|
||||||
if (! input_file.empty())
|
if (! input_file.empty())
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -51,7 +51,7 @@ template <class StepType, size_t COUNT>
|
||||||
class PrintState
|
class PrintState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PrintState() { for (size_t i = 0; i < COUNT; ++ i) m_state[i] = INVALID; }
|
PrintState() { for (size_t i = 0; i < COUNT; ++ i) m_state[i].store(INVALID, std::memory_order_relaxed); }
|
||||||
|
|
||||||
enum State {
|
enum State {
|
||||||
INVALID,
|
INVALID,
|
||||||
|
@ -59,24 +59,58 @@ public:
|
||||||
DONE,
|
DONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// With full memory barrier.
|
||||||
bool is_done(StepType step) const { return m_state[step] == DONE; }
|
bool is_done(StepType step) const { return m_state[step] == DONE; }
|
||||||
// set_started() will lock the provided mutex before setting the state.
|
|
||||||
|
// Set the step as started. Block on mutex while the Print / PrintObject / PrintRegion objects are being
|
||||||
|
// modified by the UI thread.
|
||||||
// This is necessary to block until the Print::apply_config() updates its state, which may
|
// This is necessary to block until the Print::apply_config() updates its state, which may
|
||||||
// influence the processing step being entered.
|
// influence the processing step being entered.
|
||||||
void set_started(StepType step, tbb::mutex &mtx) { mtx.lock(); m_state[step] = STARTED; mtx.unlock(); }
|
void set_started(StepType step, tbb::mutex &mtx) {
|
||||||
void set_done(StepType step) { m_state[step] = DONE; }
|
mtx.lock();
|
||||||
bool invalidate(StepType step) {
|
m_state[step].store(STARTED, std::memory_order_relaxed);
|
||||||
bool invalidated = m_state[step] != INVALID;
|
mtx.unlock();
|
||||||
m_state[step] = INVALID;
|
}
|
||||||
|
|
||||||
|
// Set the step as done. Block on mutex while the Print / PrintObject / PrintRegion objects are being
|
||||||
|
// modified by the UI thread.
|
||||||
|
void set_done(StepType step, tbb::mutex &mtx) {
|
||||||
|
mtx.lock();
|
||||||
|
m_state[step].store(DONE, std::memory_order_relaxed);
|
||||||
|
mtx.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the step invalid.
|
||||||
|
// The provided mutex should be locked at this point, guarding access to m_state.
|
||||||
|
// In case the step has already been entered or finished, cancel the background
|
||||||
|
// processing by calling the cancel callback.
|
||||||
|
template<typename CancelationCallback>
|
||||||
|
bool invalidate(StepType step, tbb::mutex &mtx, CancelationCallback &cancel) {
|
||||||
|
bool invalidated = m_state[step].load(std::memory_order_relaxed) != INVALID;
|
||||||
|
if (invalidated) {
|
||||||
|
mtx.unlock();
|
||||||
|
cancel();
|
||||||
|
mtx.lock();
|
||||||
|
}
|
||||||
return invalidated;
|
return invalidated;
|
||||||
}
|
}
|
||||||
bool invalidate_all() {
|
|
||||||
|
// Make all steps invalid.
|
||||||
|
// The provided mutex should be locked at this point, guarding access to m_state.
|
||||||
|
// In case any step has already been entered or finished, cancel the background
|
||||||
|
// processing by calling the cancel callback.
|
||||||
|
template<typename CancelationCallback>
|
||||||
|
bool invalidate_all(tbb::mutex &mtx, CancelationCallback &cancel) {
|
||||||
bool invalidated = false;
|
bool invalidated = false;
|
||||||
for (size_t i = 0; i < COUNT; ++ i)
|
for (size_t i = 0; i < COUNT; ++ i)
|
||||||
if (m_state[i] != INVALID) {
|
if (m_state[i].load(std::memory_order_relaxed) != INVALID) {
|
||||||
|
if (! invalidated) {
|
||||||
|
mtx.unlock();
|
||||||
|
cancel();
|
||||||
|
mtx.lock();
|
||||||
invalidated = true;
|
invalidated = true;
|
||||||
m_state[i] = INVALID;
|
}
|
||||||
break;
|
m_state[i].store(INVALID, std::memory_order_relaxed);
|
||||||
}
|
}
|
||||||
return invalidated;
|
return invalidated;
|
||||||
}
|
}
|
||||||
|
@ -91,17 +125,24 @@ class PrintRegion
|
||||||
{
|
{
|
||||||
friend class Print;
|
friend class Print;
|
||||||
|
|
||||||
|
// Methods NOT modifying the PrintRegion's state:
|
||||||
public:
|
public:
|
||||||
PrintRegionConfig config;
|
const Print* print() const { return m_print; }
|
||||||
|
const PrintRegionConfig& config() const { return m_config; }
|
||||||
Print* print() { return this->_print; }
|
|
||||||
Flow flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const;
|
Flow flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const;
|
||||||
coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const;
|
coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const;
|
||||||
|
|
||||||
private:
|
// Methods modifying the PrintRegion's state:
|
||||||
Print* _print;
|
public:
|
||||||
|
Print* print() { return m_print; }
|
||||||
|
void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) { this->m_config.apply_only(other, keys, ignore_nonexistent); }
|
||||||
|
|
||||||
PrintRegion(Print* print) : _print(print) {}
|
private:
|
||||||
|
Print *m_print;
|
||||||
|
PrintRegionConfig m_config;
|
||||||
|
|
||||||
|
PrintRegion(Print* print) : m_print(print) {}
|
||||||
|
PrintRegion(Print* print, const PrintRegionConfig &config) : m_print(print), m_config(config) {}
|
||||||
~PrintRegion() {}
|
~PrintRegion() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -117,7 +158,6 @@ class PrintObject
|
||||||
public:
|
public:
|
||||||
// vector of (vectors of volume ids), indexed by region_id
|
// vector of (vectors of volume ids), indexed by region_id
|
||||||
std::vector<std::vector<int>> region_volumes;
|
std::vector<std::vector<int>> region_volumes;
|
||||||
PrintObjectConfig config;
|
|
||||||
t_layer_height_ranges layer_height_ranges;
|
t_layer_height_ranges layer_height_ranges;
|
||||||
|
|
||||||
// Profile of increasing z to a layer height, to be linearly interpolated when calculating the layers.
|
// Profile of increasing z to a layer height, to be linearly interpolated when calculating the layers.
|
||||||
|
@ -144,15 +184,17 @@ public:
|
||||||
// Slic3r::Point objects in scaled G-code coordinates in our coordinates
|
// Slic3r::Point objects in scaled G-code coordinates in our coordinates
|
||||||
Points _shifted_copies;
|
Points _shifted_copies;
|
||||||
|
|
||||||
LayerPtrs layers;
|
Print* print() { return m_print; }
|
||||||
SupportLayerPtrs support_layers;
|
const Print* print() const { return m_print; }
|
||||||
|
ModelObject* model_object() { return m_model_object; }
|
||||||
|
const ModelObject* model_object() const { return m_model_object; }
|
||||||
|
const PrintObjectConfig& config() const { return m_config; }
|
||||||
|
void config_apply(const ConfigBase &other, bool ignore_nonexistent = false) { this->m_config.apply(other, ignore_nonexistent); }
|
||||||
|
void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) { this->m_config.apply_only(other, keys, ignore_nonexistent); }
|
||||||
|
const LayerPtrs& layers() const { return m_layers; }
|
||||||
|
const SupportLayerPtrs& support_layers() const { return m_support_layers; }
|
||||||
|
|
||||||
Print* print() { return this->_print; }
|
const Points& copies() const { return m_copies; }
|
||||||
const Print* print() const { return this->_print; }
|
|
||||||
ModelObject* model_object() { return this->_model_object; }
|
|
||||||
const ModelObject* model_object() const { return this->_model_object; }
|
|
||||||
|
|
||||||
const Points& copies() const { return this->_copies; }
|
|
||||||
bool add_copy(const Pointf &point);
|
bool add_copy(const Pointf &point);
|
||||||
bool delete_last_copy();
|
bool delete_last_copy();
|
||||||
bool delete_all_copies() { return this->set_copies(Points()); }
|
bool delete_all_copies() { return this->set_copies(Points()); }
|
||||||
|
@ -171,24 +213,25 @@ public:
|
||||||
// this value is not supposed to be compared with Layer::id
|
// this value is not supposed to be compared with Layer::id
|
||||||
// since they have different semantics.
|
// since they have different semantics.
|
||||||
size_t total_layer_count() const { return this->layer_count() + this->support_layer_count(); }
|
size_t total_layer_count() const { return this->layer_count() + this->support_layer_count(); }
|
||||||
size_t layer_count() const { return this->layers.size(); }
|
size_t layer_count() const { return m_layers.size(); }
|
||||||
void clear_layers();
|
void clear_layers();
|
||||||
Layer* get_layer(int idx) { return this->layers.at(idx); }
|
Layer* get_layer(int idx) { return m_layers[idx]; }
|
||||||
const Layer* get_layer(int idx) const { return this->layers.at(idx); }
|
const Layer* get_layer(int idx) const { return m_layers[idx]; }
|
||||||
|
|
||||||
// print_z: top of the layer; slice_z: center of the layer.
|
// print_z: top of the layer; slice_z: center of the layer.
|
||||||
Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
|
Layer* add_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
|
||||||
|
|
||||||
size_t support_layer_count() const { return this->support_layers.size(); }
|
size_t support_layer_count() const { return m_support_layers.size(); }
|
||||||
void clear_support_layers();
|
void clear_support_layers();
|
||||||
SupportLayer* get_support_layer(int idx) { return this->support_layers.at(idx); }
|
SupportLayer* get_support_layer(int idx) { return m_support_layers[idx]; }
|
||||||
SupportLayer* add_support_layer(int id, coordf_t height, coordf_t print_z);
|
SupportLayer* add_support_layer(int id, coordf_t height, coordf_t print_z);
|
||||||
|
SupportLayerPtrs::const_iterator insert_support_layer(SupportLayerPtrs::const_iterator pos, int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
|
||||||
void delete_support_layer(int idx);
|
void delete_support_layer(int idx);
|
||||||
|
|
||||||
// methods for handling state
|
// methods for handling state
|
||||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
||||||
bool invalidate_step(PrintObjectStep step);
|
bool invalidate_step(PrintObjectStep step);
|
||||||
bool invalidate_all_steps() { return m_state.invalidate_all(); }
|
bool invalidate_all_steps();
|
||||||
bool is_step_done(PrintObjectStep step) const { return m_state.is_done(step); }
|
bool is_step_done(PrintObjectStep step) const { return m_state.is_done(step); }
|
||||||
|
|
||||||
// To be used over the layer_height_profile of both the PrintObject and ModelObject
|
// To be used over the layer_height_profile of both the PrintObject and ModelObject
|
||||||
|
@ -229,9 +272,14 @@ private:
|
||||||
void combine_infill();
|
void combine_infill();
|
||||||
void _generate_support_material();
|
void _generate_support_material();
|
||||||
|
|
||||||
Print* _print;
|
Print *m_print;
|
||||||
ModelObject* _model_object;
|
ModelObject *m_model_object;
|
||||||
Points _copies; // Slic3r::Point objects in scaled G-code coordinates
|
PrintObjectConfig m_config;
|
||||||
|
// Slic3r::Point objects in scaled G-code coordinates
|
||||||
|
Points m_copies;
|
||||||
|
|
||||||
|
LayerPtrs m_layers;
|
||||||
|
SupportLayerPtrs m_support_layers;
|
||||||
|
|
||||||
PrintState<PrintObjectStep, posCount> m_state;
|
PrintState<PrintObjectStep, posCount> m_state;
|
||||||
// Mutex used for synchronization of the worker thread with the UI thread:
|
// Mutex used for synchronization of the worker thread with the UI thread:
|
||||||
|
@ -245,9 +293,49 @@ private:
|
||||||
~PrintObject() {}
|
~PrintObject() {}
|
||||||
|
|
||||||
void set_started(PrintObjectStep step) { m_state.set_started(step, m_mutex); }
|
void set_started(PrintObjectStep step) { m_state.set_started(step, m_mutex); }
|
||||||
|
void set_done(PrintObjectStep step) { m_state.set_done(step, m_mutex); }
|
||||||
std::vector<ExPolygons> _slice_region(size_t region_id, const std::vector<float> &z, bool modifier);
|
std::vector<ExPolygons> _slice_region(size_t region_id, const std::vector<float> &z, bool modifier);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WipeTowerData
|
||||||
|
{
|
||||||
|
// Following section will be consumed by the GCodeGenerator.
|
||||||
|
// Tool ordering of a non-sequential print has to be known to calculate the wipe tower.
|
||||||
|
// Cache it here, so it does not need to be recalculated during the G-code generation.
|
||||||
|
ToolOrdering tool_ordering;
|
||||||
|
// Cache of tool changes per print layer.
|
||||||
|
std::unique_ptr<WipeTower::ToolChangeResult> priming;
|
||||||
|
std::vector<std::vector<WipeTower::ToolChangeResult>> tool_changes;
|
||||||
|
std::unique_ptr<WipeTower::ToolChangeResult> final_purge;
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
tool_ordering.clear();
|
||||||
|
priming.reset(nullptr);
|
||||||
|
tool_changes.clear();
|
||||||
|
final_purge.reset(nullptr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PrintStatistics
|
||||||
|
{
|
||||||
|
PrintStatistics() { clear(); }
|
||||||
|
std::string estimated_print_time;
|
||||||
|
double total_used_filament;
|
||||||
|
double total_extruded_volume;
|
||||||
|
double total_cost;
|
||||||
|
double total_weight;
|
||||||
|
std::map<size_t, float> filament_stats;
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
estimated_print_time.clear();
|
||||||
|
total_used_filament = 0.;
|
||||||
|
total_extruded_volume = 0.;
|
||||||
|
total_weight = 0.;
|
||||||
|
total_cost = 0.;
|
||||||
|
filament_stats.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::vector<PrintObject*> PrintObjectPtrs;
|
typedef std::vector<PrintObject*> PrintObjectPtrs;
|
||||||
typedef std::vector<PrintRegion*> PrintRegionPtrs;
|
typedef std::vector<PrintRegion*> PrintRegionPtrs;
|
||||||
|
|
||||||
|
@ -255,44 +343,27 @@ typedef std::vector<PrintRegion*> PrintRegionPtrs;
|
||||||
class Print
|
class Print
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PrintConfig config;
|
Print() { restart(); }
|
||||||
PrintObjectConfig default_object_config;
|
|
||||||
PrintRegionConfig default_region_config;
|
|
||||||
PrintObjectPtrs objects;
|
|
||||||
PrintRegionPtrs regions;
|
|
||||||
PlaceholderParser placeholder_parser;
|
|
||||||
std::string estimated_print_time;
|
|
||||||
double total_used_filament, total_extruded_volume, total_cost, total_weight;
|
|
||||||
std::map<size_t, float> filament_stats;
|
|
||||||
|
|
||||||
// ordered collections of extrusion paths to build skirt loops and brim
|
|
||||||
ExtrusionEntityCollection skirt, brim;
|
|
||||||
|
|
||||||
Print() : total_used_filament(0), total_extruded_volume(0) { restart(); }
|
|
||||||
~Print() { clear_objects(); }
|
~Print() { clear_objects(); }
|
||||||
|
|
||||||
// methods for handling objects
|
// Methods, which change the state of Print / PrintObject / PrintRegion.
|
||||||
|
// The following methods are synchronized with process() and export_gcode(),
|
||||||
|
// so that process() and export_gcode() may be called from a background thread.
|
||||||
|
// In case the following methods need to modify data processed by process() or export_gcode(),
|
||||||
|
// a cancellation callback is executed to stop the background processing before the operation.
|
||||||
void clear_objects();
|
void clear_objects();
|
||||||
PrintObject* get_object(size_t idx) { return objects.at(idx); }
|
|
||||||
const PrintObject* get_object(size_t idx) const { return objects.at(idx); }
|
|
||||||
|
|
||||||
void delete_object(size_t idx);
|
void delete_object(size_t idx);
|
||||||
void reload_object(size_t idx);
|
void reload_object(size_t idx);
|
||||||
bool reload_model_instances();
|
bool reload_model_instances();
|
||||||
|
void add_model_object(ModelObject* model_object, int idx = -1);
|
||||||
// methods for handling regions
|
bool apply_config(DynamicPrintConfig config);
|
||||||
PrintRegion* get_region(size_t idx) { return regions.at(idx); }
|
void process();
|
||||||
const PrintRegion* get_region(size_t idx) const { return regions.at(idx); }
|
void export_gcode(const std::string &path_template, GCodePreviewData *preview_data);
|
||||||
PrintRegion* add_region();
|
|
||||||
|
|
||||||
// methods for handling state
|
// methods for handling state
|
||||||
bool invalidate_step(PrintStep step);
|
|
||||||
bool invalidate_all_steps() { return m_state.invalidate_all(); }
|
|
||||||
bool is_step_done(PrintStep step) const { return m_state.is_done(step); }
|
bool is_step_done(PrintStep step) const { return m_state.is_done(step); }
|
||||||
bool is_step_done(PrintObjectStep step) const;
|
bool is_step_done(PrintObjectStep step) const;
|
||||||
|
|
||||||
void add_model_object(ModelObject* model_object, int idx = -1);
|
|
||||||
bool apply_config(DynamicPrintConfig config);
|
|
||||||
bool has_infinite_skirt() const;
|
bool has_infinite_skirt() const;
|
||||||
bool has_skirt() const;
|
bool has_skirt() const;
|
||||||
// Returns an empty string if valid, otherwise returns an error message.
|
// Returns an empty string if valid, otherwise returns an error message.
|
||||||
|
@ -306,26 +377,29 @@ public:
|
||||||
std::vector<unsigned int> object_extruders() const;
|
std::vector<unsigned int> object_extruders() const;
|
||||||
std::vector<unsigned int> support_material_extruders() const;
|
std::vector<unsigned int> support_material_extruders() const;
|
||||||
std::vector<unsigned int> extruders() const;
|
std::vector<unsigned int> extruders() const;
|
||||||
void _simplify_slices(double distance);
|
|
||||||
double max_allowed_layer_height() const;
|
double max_allowed_layer_height() const;
|
||||||
bool has_support_material() const;
|
bool has_support_material() const;
|
||||||
|
// Make sure the background processing has no access to this model_object during this call!
|
||||||
void auto_assign_extruders(ModelObject* model_object) const;
|
void auto_assign_extruders(ModelObject* model_object) const;
|
||||||
|
|
||||||
void process();
|
const PrintConfig& config() const { return m_config; }
|
||||||
void export_gcode(const std::string &path_template, GCodePreviewData *preview_data);
|
const PrintObjectConfig& default_object_config() const { return m_default_object_config; }
|
||||||
|
const PrintRegionConfig& default_region_config() const { return m_default_region_config; }
|
||||||
|
const PrintObjectPtrs& objects() const { return m_objects; }
|
||||||
|
const PrintRegionPtrs& regions() const { return m_regions; }
|
||||||
|
const PlaceholderParser& placeholder_parser() const { return m_placeholder_parser; }
|
||||||
|
|
||||||
|
const ExtrusionEntityCollection& skirt() const { return m_skirt; }
|
||||||
|
const ExtrusionEntityCollection& brim() const { return m_brim; }
|
||||||
|
|
||||||
|
const PrintStatistics& print_statistics() const { return m_print_statistics; }
|
||||||
|
|
||||||
// Wipe tower support.
|
// Wipe tower support.
|
||||||
bool has_wipe_tower() const;
|
bool has_wipe_tower() const;
|
||||||
// Tool ordering of a non-sequential print has to be known to calculate the wipe tower.
|
const WipeTowerData& wipe_tower_data() const { return m_wipe_tower_data; }
|
||||||
// Cache it here, so it does not need to be recalculated during the G-code generation.
|
|
||||||
ToolOrdering m_tool_ordering;
|
|
||||||
// Cache of tool changes per print layer.
|
|
||||||
std::unique_ptr<WipeTower::ToolChangeResult> m_wipe_tower_priming;
|
|
||||||
std::vector<std::vector<WipeTower::ToolChangeResult>> m_wipe_tower_tool_changes;
|
|
||||||
std::unique_ptr<WipeTower::ToolChangeResult> m_wipe_tower_final_purge;
|
|
||||||
|
|
||||||
std::string output_filename();
|
std::string output_filename() const;
|
||||||
std::string output_filepath(const std::string &path);
|
std::string output_filepath(const std::string &path) const;
|
||||||
|
|
||||||
typedef std::function<void(int, const std::string&)> status_callback_type;
|
typedef std::function<void(int, const std::string&)> status_callback_type;
|
||||||
// Default status console print out in the form of percent => message.
|
// Default status console print out in the form of percent => message.
|
||||||
|
@ -339,26 +413,45 @@ public:
|
||||||
if (m_status_callback) m_status_callback(percent, message);
|
if (m_status_callback) m_status_callback(percent, message);
|
||||||
else printf("%d => %s\n", percent, message.c_str());
|
else printf("%d => %s\n", percent, message.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef std::function<void()> cancel_callback_type;
|
||||||
|
// Various methods will call this callback to stop the background processing (the Print::process() call)
|
||||||
|
// in case a successive change of the Print / PrintObject / PrintRegion instances changed
|
||||||
|
// the state of the finished or running calculations.
|
||||||
|
void set_cancel_callback(cancel_callback_type cancel_callback) { m_cancel_callback = cancel_callback; }
|
||||||
|
// Has the calculation been canceled?
|
||||||
|
bool canceled() const { return m_canceled; }
|
||||||
// Cancel the running computation. Stop execution of all the background threads.
|
// Cancel the running computation. Stop execution of all the background threads.
|
||||||
void cancel() { m_canceled = true; }
|
void cancel() { m_canceled = true; }
|
||||||
// Cancel the running computation. Stop execution of all the background threads.
|
// Cancel the running computation. Stop execution of all the background threads.
|
||||||
void restart() { m_canceled = false; }
|
void restart() { m_canceled = false; }
|
||||||
// Has the calculation been canceled?
|
|
||||||
bool canceled() { return m_canceled; }
|
// Accessed by SupportMaterial
|
||||||
void throw_if_canceled() { if (m_canceled) throw CanceledException(); }
|
const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void set_started(PrintStep step) { m_state.set_started(step, m_mutex); }
|
void set_started(PrintStep step) { m_state.set_started(step, m_mutex); }
|
||||||
void set_done(PrintStep step) { m_state.set_done(step); }
|
void set_done(PrintStep step) { m_state.set_done(step, m_mutex); }
|
||||||
|
bool invalidate_step(PrintStep step);
|
||||||
|
bool invalidate_all_steps() { return m_state.invalidate_all(m_mutex, m_cancel_callback); }
|
||||||
|
|
||||||
|
// methods for handling regions
|
||||||
|
PrintRegion* get_region(size_t idx) { return m_regions[idx]; }
|
||||||
|
PrintRegion* add_region();
|
||||||
|
PrintRegion* add_region(const PrintRegionConfig &config);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
||||||
PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume);
|
PrintRegionConfig _region_config_from_model_volume(const ModelVolume &volume);
|
||||||
|
|
||||||
|
// If the background processing stop was requested, throw CanceledException.
|
||||||
|
// To be called by the worker thread and its sub-threads (mostly launched on the TBB thread pool) regularly.
|
||||||
|
void throw_if_canceled() { if (m_canceled) throw CanceledException(); }
|
||||||
|
|
||||||
void _make_skirt();
|
void _make_skirt();
|
||||||
void _make_brim();
|
void _make_brim();
|
||||||
void _clear_wipe_tower();
|
|
||||||
void _make_wipe_tower();
|
void _make_wipe_tower();
|
||||||
|
void _simplify_slices(double distance);
|
||||||
|
|
||||||
PrintState<PrintStep, psCount> m_state;
|
PrintState<PrintStep, psCount> m_state;
|
||||||
// Mutex used for synchronization of the worker thread with the UI thread:
|
// Mutex used for synchronization of the worker thread with the UI thread:
|
||||||
|
@ -370,15 +463,36 @@ private:
|
||||||
// Callback to be evoked regularly to update state of the UI thread.
|
// Callback to be evoked regularly to update state of the UI thread.
|
||||||
status_callback_type m_status_callback;
|
status_callback_type m_status_callback;
|
||||||
|
|
||||||
|
// Callback to be evoked to stop the background processing before a state is updated.
|
||||||
|
cancel_callback_type m_cancel_callback = [](){};
|
||||||
|
|
||||||
|
PrintConfig m_config;
|
||||||
|
PrintObjectConfig m_default_object_config;
|
||||||
|
PrintRegionConfig m_default_region_config;
|
||||||
|
PrintObjectPtrs m_objects;
|
||||||
|
PrintRegionPtrs m_regions;
|
||||||
|
PlaceholderParser m_placeholder_parser;
|
||||||
|
|
||||||
|
// Ordered collections of extrusion paths to build skirt loops and brim.
|
||||||
|
ExtrusionEntityCollection m_skirt;
|
||||||
|
ExtrusionEntityCollection m_brim;
|
||||||
|
|
||||||
|
// Following section will be consumed by the GCodeGenerator.
|
||||||
|
WipeTowerData m_wipe_tower_data;
|
||||||
|
|
||||||
|
// Estimated print time, filament consumed.
|
||||||
|
PrintStatistics m_print_statistics;
|
||||||
|
|
||||||
// To allow GCode to set the Print's GCodeExport step status.
|
// To allow GCode to set the Print's GCodeExport step status.
|
||||||
friend class GCode;
|
friend class GCode;
|
||||||
|
// Allow PrintObject to access m_mutex and m_cancel_callback.
|
||||||
|
friend class PrintObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FOREACH_BASE(type, container, iterator) for (type::const_iterator iterator = (container).begin(); iterator != (container).end(); ++iterator)
|
#define FOREACH_BASE(type, container, iterator) for (type::const_iterator iterator = (container).begin(); iterator != (container).end(); ++iterator)
|
||||||
#define FOREACH_REGION(print, region) FOREACH_BASE(PrintRegionPtrs, (print)->regions, region)
|
#define FOREACH_OBJECT(print, object) FOREACH_BASE(PrintObjectPtrs, (print)->m_objects, object)
|
||||||
#define FOREACH_OBJECT(print, object) FOREACH_BASE(PrintObjectPtrs, (print)->objects, object)
|
#define FOREACH_LAYER(object, layer) FOREACH_BASE(LayerPtrs, (object)->m_layers, layer)
|
||||||
#define FOREACH_LAYER(object, layer) FOREACH_BASE(LayerPtrs, (object)->layers, layer)
|
#define FOREACH_LAYERREGION(layer, layerm) FOREACH_BASE(LayerRegionPtrs, (layer)->m_regions, layerm)
|
||||||
#define FOREACH_LAYERREGION(layer, layerm) FOREACH_BASE(LayerRegionPtrs, (layer)->regions, layerm)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -12,48 +12,48 @@ Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool fir
|
||||||
} else {
|
} else {
|
||||||
// otherwise, get extrusion width from configuration
|
// otherwise, get extrusion width from configuration
|
||||||
// (might be an absolute value, or a percent value, or zero for auto)
|
// (might be an absolute value, or a percent value, or zero for auto)
|
||||||
if (first_layer && this->_print->config.first_layer_extrusion_width.value > 0) {
|
if (first_layer && m_print->config().first_layer_extrusion_width.value > 0) {
|
||||||
config_width = this->_print->config.first_layer_extrusion_width;
|
config_width = m_print->config().first_layer_extrusion_width;
|
||||||
} else if (role == frExternalPerimeter) {
|
} else if (role == frExternalPerimeter) {
|
||||||
config_width = this->config.external_perimeter_extrusion_width;
|
config_width = m_config.external_perimeter_extrusion_width;
|
||||||
} else if (role == frPerimeter) {
|
} else if (role == frPerimeter) {
|
||||||
config_width = this->config.perimeter_extrusion_width;
|
config_width = m_config.perimeter_extrusion_width;
|
||||||
} else if (role == frInfill) {
|
} else if (role == frInfill) {
|
||||||
config_width = this->config.infill_extrusion_width;
|
config_width = m_config.infill_extrusion_width;
|
||||||
} else if (role == frSolidInfill) {
|
} else if (role == frSolidInfill) {
|
||||||
config_width = this->config.solid_infill_extrusion_width;
|
config_width = m_config.solid_infill_extrusion_width;
|
||||||
} else if (role == frTopSolidInfill) {
|
} else if (role == frTopSolidInfill) {
|
||||||
config_width = this->config.top_infill_extrusion_width;
|
config_width = m_config.top_infill_extrusion_width;
|
||||||
} else {
|
} else {
|
||||||
CONFESS("Unknown role");
|
CONFESS("Unknown role");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (config_width.value == 0) {
|
if (config_width.value == 0) {
|
||||||
config_width = object.config.extrusion_width;
|
config_width = object.config().extrusion_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the configured nozzle_diameter for the extruder associated
|
// get the configured nozzle_diameter for the extruder associated
|
||||||
// to the flow role requested
|
// to the flow role requested
|
||||||
size_t extruder = 0; // 1-based
|
size_t extruder = 0; // 1-based
|
||||||
if (role == frPerimeter || role == frExternalPerimeter) {
|
if (role == frPerimeter || role == frExternalPerimeter) {
|
||||||
extruder = this->config.perimeter_extruder;
|
extruder = m_config.perimeter_extruder;
|
||||||
} else if (role == frInfill) {
|
} else if (role == frInfill) {
|
||||||
extruder = this->config.infill_extruder;
|
extruder = m_config.infill_extruder;
|
||||||
} else if (role == frSolidInfill || role == frTopSolidInfill) {
|
} else if (role == frSolidInfill || role == frTopSolidInfill) {
|
||||||
extruder = this->config.solid_infill_extruder;
|
extruder = m_config.solid_infill_extruder;
|
||||||
} else {
|
} else {
|
||||||
CONFESS("Unknown role $role");
|
CONFESS("Unknown role $role");
|
||||||
}
|
}
|
||||||
double nozzle_diameter = this->_print->config.nozzle_diameter.get_at(extruder-1);
|
double nozzle_diameter = m_print->config().nozzle_diameter.get_at(extruder-1);
|
||||||
|
|
||||||
return Flow::new_from_config_width(role, config_width, nozzle_diameter, layer_height, bridge ? (float)this->config.bridge_flow_ratio : 0.0);
|
return Flow::new_from_config_width(role, config_width, nozzle_diameter, layer_height, bridge ? (float)m_config.bridge_flow_ratio : 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
coordf_t PrintRegion::nozzle_dmr_avg(const PrintConfig &print_config) const
|
coordf_t PrintRegion::nozzle_dmr_avg(const PrintConfig &print_config) const
|
||||||
{
|
{
|
||||||
return (print_config.nozzle_diameter.get_at(this->config.perimeter_extruder.value - 1) +
|
return (print_config.nozzle_diameter.get_at(m_config.perimeter_extruder.value - 1) +
|
||||||
print_config.nozzle_diameter.get_at(this->config.infill_extruder.value - 1) +
|
print_config.nozzle_diameter.get_at(m_config.infill_extruder.value - 1) +
|
||||||
print_config.nozzle_diameter.get_at(this->config.solid_infill_extruder.value - 1)) / 3.;
|
print_config.nozzle_diameter.get_at(m_config.solid_infill_extruder.value - 1)) / 3.;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,8 +142,8 @@ void export_print_z_polygons_and_extrusions_to_svg(
|
||||||
|
|
||||||
PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params) :
|
PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object, const SlicingParameters &slicing_params) :
|
||||||
m_object (object),
|
m_object (object),
|
||||||
m_print_config (&object->print()->config),
|
m_print_config (&object->print()->config()),
|
||||||
m_object_config (&object->config),
|
m_object_config (&object->config()),
|
||||||
m_slicing_params (slicing_params),
|
m_slicing_params (slicing_params),
|
||||||
m_first_layer_flow (support_material_1st_layer_flow(object, float(slicing_params.first_print_layer_height))),
|
m_first_layer_flow (support_material_1st_layer_flow(object, float(slicing_params.first_print_layer_height))),
|
||||||
m_support_material_flow (support_material_flow(object, float(slicing_params.layer_height))),
|
m_support_material_flow (support_material_flow(object, float(slicing_params.layer_height))),
|
||||||
|
@ -164,7 +164,7 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
|
||||||
coordf_t external_perimeter_width = 0.;
|
coordf_t external_perimeter_width = 0.;
|
||||||
for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) {
|
for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) {
|
||||||
if (! object->region_volumes[region_id].empty()) {
|
if (! object->region_volumes[region_id].empty()) {
|
||||||
const PrintRegionConfig &config = object->print()->get_region(region_id)->config;
|
const PrintRegionConfig &config = object->print()->get_region(region_id)->config();
|
||||||
coordf_t width = config.external_perimeter_extrusion_width.get_abs_value(slicing_params.layer_height);
|
coordf_t width = config.external_perimeter_extrusion_width.get_abs_value(slicing_params.layer_height);
|
||||||
if (width <= 0.)
|
if (width <= 0.)
|
||||||
width = m_print_config->nozzle_diameter.get_at(config.perimeter_extruder-1);
|
width = m_print_config->nozzle_diameter.get_at(config.perimeter_extruder-1);
|
||||||
|
@ -226,7 +226,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
|
||||||
|
|
||||||
coordf_t max_object_layer_height = 0.;
|
coordf_t max_object_layer_height = 0.;
|
||||||
for (size_t i = 0; i < object.layer_count(); ++ i)
|
for (size_t i = 0; i < object.layer_count(); ++ i)
|
||||||
max_object_layer_height = std::max(max_object_layer_height, object.layers[i]->height);
|
max_object_layer_height = std::max(max_object_layer_height, object.layers()[i]->height);
|
||||||
|
|
||||||
// Layer instances will be allocated by std::deque and they will be kept until the end of this function call.
|
// Layer instances will be allocated by std::deque and they will be kept until the end of this function call.
|
||||||
// The layers will be referenced by various LayersPtr (of type std::vector<Layer*>)
|
// The layers will be referenced by various LayersPtr (of type std::vector<Layer*>)
|
||||||
|
@ -266,9 +266,9 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
|
||||||
layer_support_areas);
|
layer_support_areas);
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG
|
#ifdef SLIC3R_DEBUG
|
||||||
for (size_t layer_id = 0; layer_id < object.layers.size(); ++ layer_id)
|
for (size_t layer_id = 0; layer_id < object.layers().size(); ++ layer_id)
|
||||||
Slic3r::SVG::export_expolygons(
|
Slic3r::SVG::export_expolygons(
|
||||||
debug_out_path("support-areas-%d-%lf.svg", iRun, object.layers[layer_id]->print_z),
|
debug_out_path("support-areas-%d-%lf.svg", iRun, object.layers()[layer_id]->print_z),
|
||||||
union_ex(layer_support_areas[layer_id], false));
|
union_ex(layer_support_areas[layer_id], false));
|
||||||
#endif /* SLIC3R_DEBUG */
|
#endif /* SLIC3R_DEBUG */
|
||||||
|
|
||||||
|
@ -354,7 +354,7 @@ void PrintObjectSupportMaterial::generate(PrintObject &object)
|
||||||
// Sort the layers lexicographically by a raising print_z and a decreasing height.
|
// Sort the layers lexicographically by a raising print_z and a decreasing height.
|
||||||
std::sort(layers_sorted.begin(), layers_sorted.end(), MyLayersPtrCompare());
|
std::sort(layers_sorted.begin(), layers_sorted.end(), MyLayersPtrCompare());
|
||||||
int layer_id = 0;
|
int layer_id = 0;
|
||||||
assert(object.support_layers.empty());
|
assert(object.support_layers().empty());
|
||||||
for (int i = 0; i < int(layers_sorted.size());) {
|
for (int i = 0; i < int(layers_sorted.size());) {
|
||||||
// Find the last layer with roughly the same print_z, find the minimum layer height of all.
|
// Find the last layer with roughly the same print_z, find the minimum layer height of all.
|
||||||
// Due to the floating point inaccuracies, the print_z may not be the same even if in theory they should.
|
// Due to the floating point inaccuracies, the print_z may not be the same even if in theory they should.
|
||||||
|
@ -420,8 +420,8 @@ Polygons collect_region_slices_by_type(const Layer &layer, SurfaceType surface_t
|
||||||
{
|
{
|
||||||
// 1) Count the new polygons first.
|
// 1) Count the new polygons first.
|
||||||
size_t n_polygons_new = 0;
|
size_t n_polygons_new = 0;
|
||||||
for (LayerRegionPtrs::const_iterator it_region = layer.regions.begin(); it_region != layer.regions.end(); ++ it_region) {
|
for (const LayerRegion* pregion : layer.regions()) {
|
||||||
const LayerRegion ®ion = *(*it_region);
|
const LayerRegion ®ion = *pregion;
|
||||||
const SurfaceCollection &slices = region.slices;
|
const SurfaceCollection &slices = region.slices;
|
||||||
for (Surfaces::const_iterator it = slices.surfaces.begin(); it != slices.surfaces.end(); ++ it) {
|
for (Surfaces::const_iterator it = slices.surfaces.begin(); it != slices.surfaces.end(); ++ it) {
|
||||||
const Surface &surface = *it;
|
const Surface &surface = *it;
|
||||||
|
@ -433,8 +433,8 @@ Polygons collect_region_slices_by_type(const Layer &layer, SurfaceType surface_t
|
||||||
// 2) Collect the new polygons.
|
// 2) Collect the new polygons.
|
||||||
Polygons out;
|
Polygons out;
|
||||||
out.reserve(n_polygons_new);
|
out.reserve(n_polygons_new);
|
||||||
for (LayerRegionPtrs::const_iterator it_region = layer.regions.begin(); it_region != layer.regions.end(); ++ it_region) {
|
for (const LayerRegion *pregion : layer.regions()) {
|
||||||
const LayerRegion ®ion = *(*it_region);
|
const LayerRegion ®ion = *pregion;
|
||||||
const SurfaceCollection &slices = region.slices;
|
const SurfaceCollection &slices = region.slices;
|
||||||
for (Surfaces::const_iterator it = slices.surfaces.begin(); it != slices.surfaces.end(); ++ it) {
|
for (Surfaces::const_iterator it = slices.surfaces.begin(); it != slices.surfaces.end(); ++ it) {
|
||||||
const Surface &surface = *it;
|
const Surface &surface = *it;
|
||||||
|
@ -658,9 +658,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
std::vector<Polygons> buildplate_covered;
|
std::vector<Polygons> buildplate_covered;
|
||||||
if (buildplate_only) {
|
if (buildplate_only) {
|
||||||
BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::top_contact_layers() - collecting regions covering the print bed.";
|
BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::top_contact_layers() - collecting regions covering the print bed.";
|
||||||
buildplate_covered.assign(object.layers.size(), Polygons());
|
buildplate_covered.assign(object.layers().size(), Polygons());
|
||||||
for (size_t layer_id = 1; layer_id < object.layers.size(); ++ layer_id) {
|
for (size_t layer_id = 1; layer_id < object.layers().size(); ++ layer_id) {
|
||||||
const Layer &lower_layer = *object.layers[layer_id-1];
|
const Layer &lower_layer = *object.layers()[layer_id-1];
|
||||||
// Merge the new slices with the preceding slices.
|
// Merge the new slices with the preceding slices.
|
||||||
// Apply the safety offset to the newly added polygons, so they will connect
|
// Apply the safety offset to the newly added polygons, so they will connect
|
||||||
// with the polygons collected before,
|
// with the polygons collected before,
|
||||||
|
@ -686,7 +686,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
[this, &object, &buildplate_covered, threshold_rad, &layer_storage, &layer_storage_mutex, &contact_out](const tbb::blocked_range<size_t>& range) {
|
[this, &object, &buildplate_covered, threshold_rad, &layer_storage, &layer_storage_mutex, &contact_out](const tbb::blocked_range<size_t>& range) {
|
||||||
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id)
|
for (size_t layer_id = range.begin(); layer_id < range.end(); ++ layer_id)
|
||||||
{
|
{
|
||||||
const Layer &layer = *object.layers[layer_id];
|
const Layer &layer = *object.layers()[layer_id];
|
||||||
|
|
||||||
// Detect overhangs and contact areas needed to support them.
|
// Detect overhangs and contact areas needed to support them.
|
||||||
// Collect overhangs and contacts of all regions of this layer supported by the layer immediately below.
|
// Collect overhangs and contacts of all regions of this layer supported by the layer immediately below.
|
||||||
|
@ -703,13 +703,13 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
contact_polygons = offset(overhang_polygons, scale_(SUPPORT_MATERIAL_MARGIN));
|
contact_polygons = offset(overhang_polygons, scale_(SUPPORT_MATERIAL_MARGIN));
|
||||||
} else {
|
} else {
|
||||||
// Generate overhang / contact_polygons for non-raft layers.
|
// Generate overhang / contact_polygons for non-raft layers.
|
||||||
const Layer &lower_layer = *object.layers[layer_id-1];
|
const Layer &lower_layer = *object.layers()[layer_id-1];
|
||||||
for (LayerRegion *layerm : layer.regions) {
|
for (LayerRegion *layerm : layer.regions()) {
|
||||||
// Extrusion width accounts for the roundings of the extrudates.
|
// Extrusion width accounts for the roundings of the extrudates.
|
||||||
// It is the maximum widh of the extrudate.
|
// It is the maximum widh of the extrudate.
|
||||||
float fw = float(layerm->flow(frExternalPerimeter).scaled_width());
|
float fw = float(layerm->flow(frExternalPerimeter).scaled_width());
|
||||||
float lower_layer_offset =
|
float lower_layer_offset =
|
||||||
(layer_id < this->m_object_config->support_material_enforce_layers.value) ?
|
(layer_id < m_object_config->support_material_enforce_layers.value) ?
|
||||||
// Enforce a full possible support, ignore the overhang angle.
|
// Enforce a full possible support, ignore the overhang angle.
|
||||||
0.f :
|
0.f :
|
||||||
(threshold_rad > 0. ?
|
(threshold_rad > 0. ?
|
||||||
|
@ -762,14 +762,14 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
}
|
}
|
||||||
#endif /* SLIC3R_DEBUG */
|
#endif /* SLIC3R_DEBUG */
|
||||||
|
|
||||||
if (this->m_object_config->dont_support_bridges) {
|
if (m_object_config->dont_support_bridges) {
|
||||||
// compute the area of bridging perimeters
|
// compute the area of bridging perimeters
|
||||||
// Note: this is duplicate code from GCode.pm, we need to refactor
|
// Note: this is duplicate code from GCode.pm, we need to refactor
|
||||||
if (true) {
|
if (true) {
|
||||||
Polygons bridged_perimeters;
|
Polygons bridged_perimeters;
|
||||||
{
|
{
|
||||||
Flow bridge_flow = layerm->flow(frPerimeter, true);
|
Flow bridge_flow = layerm->flow(frPerimeter, true);
|
||||||
coordf_t nozzle_diameter = m_print_config->nozzle_diameter.get_at(layerm->region()->config.perimeter_extruder-1);
|
coordf_t nozzle_diameter = m_print_config->nozzle_diameter.get_at(layerm->region()->config().perimeter_extruder-1);
|
||||||
Polygons lower_grown_slices = offset(lower_layer_polygons, 0.5f*float(scale_(nozzle_diameter)), SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
Polygons lower_grown_slices = offset(lower_layer_polygons, 0.5f*float(scale_(nozzle_diameter)), SUPPORT_SURFACES_OFFSET_PARAMETERS);
|
||||||
|
|
||||||
// Collect perimeters of this layer.
|
// Collect perimeters of this layer.
|
||||||
|
@ -894,8 +894,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
} else {
|
} else {
|
||||||
// Interface layer will be synchronized with the object.
|
// Interface layer will be synchronized with the object.
|
||||||
assert(layer_id > 0);
|
assert(layer_id > 0);
|
||||||
new_layer.height = object.layers[layer_id - 1]->height;
|
new_layer.height = object.layers()[layer_id - 1]->height;
|
||||||
new_layer.bottom_z = (layer_id == 1) ? m_slicing_params.object_print_z_min : object.layers[layer_id - 2]->print_z;
|
new_layer.bottom_z = (layer_id == 1) ? m_slicing_params.object_print_z_min : object.layers()[layer_id - 2]->print_z;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Contact layer will be printed with a normal flow, but
|
// Contact layer will be printed with a normal flow, but
|
||||||
|
@ -904,9 +904,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
||||||
// In the future we may switch to a normal extrusion flow for the supported bridges.
|
// In the future we may switch to a normal extrusion flow for the supported bridges.
|
||||||
// Get the average nozzle diameter used on this layer.
|
// Get the average nozzle diameter used on this layer.
|
||||||
coordf_t nozzle_dmr = 0.;
|
coordf_t nozzle_dmr = 0.;
|
||||||
for (const LayerRegion *region : layer.regions)
|
for (const LayerRegion *region : layer.regions())
|
||||||
nozzle_dmr += region->region()->nozzle_dmr_avg(*m_print_config);
|
nozzle_dmr += region->region()->nozzle_dmr_avg(*m_print_config);
|
||||||
nozzle_dmr /= coordf_t(layer.regions.size());
|
nozzle_dmr /= coordf_t(layer.regions().size());
|
||||||
new_layer.print_z = layer.print_z - nozzle_dmr - m_object_config->support_material_contact_distance;
|
new_layer.print_z = layer.print_z - nozzle_dmr - m_object_config->support_material_contact_distance;
|
||||||
new_layer.bottom_z = new_layer.print_z;
|
new_layer.bottom_z = new_layer.print_z;
|
||||||
new_layer.height = 0.;
|
new_layer.height = 0.;
|
||||||
|
@ -1048,10 +1048,10 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
||||||
// top shapes so this can be done here
|
// top shapes so this can be done here
|
||||||
layer_new.height = m_slicing_params.soluble_interface ?
|
layer_new.height = m_slicing_params.soluble_interface ?
|
||||||
// Align the interface layer with the object's layer height.
|
// Align the interface layer with the object's layer height.
|
||||||
object.layers[layer_id + 1]->height :
|
object.layers()[layer_id + 1]->height :
|
||||||
// Place a bridge flow interface layer over the top surface.
|
// Place a bridge flow interface layer over the top surface.
|
||||||
m_support_material_interface_flow.nozzle_diameter;
|
m_support_material_interface_flow.nozzle_diameter;
|
||||||
layer_new.print_z = m_slicing_params.soluble_interface ? object.layers[layer_id + 1]->print_z :
|
layer_new.print_z = m_slicing_params.soluble_interface ? object.layers()[layer_id + 1]->print_z :
|
||||||
layer.print_z + layer_new.height + m_object_config->support_material_contact_distance.value;
|
layer.print_z + layer_new.height + m_object_config->support_material_contact_distance.value;
|
||||||
layer_new.bottom_z = layer.print_z;
|
layer_new.bottom_z = layer.print_z;
|
||||||
layer_new.idx_object_layer_below = layer_id;
|
layer_new.idx_object_layer_below = layer_id;
|
||||||
|
@ -1062,16 +1062,16 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
||||||
// Walk the top surfaces, snap the top of the new bottom surface to the closest top of the top surface,
|
// Walk the top surfaces, snap the top of the new bottom surface to the closest top of the top surface,
|
||||||
// so there will be no support surfaces generated with thickness lower than m_support_layer_height_min.
|
// so there will be no support surfaces generated with thickness lower than m_support_layer_height_min.
|
||||||
for (size_t top_idx = size_t(std::max<int>(0, contact_idx));
|
for (size_t top_idx = size_t(std::max<int>(0, contact_idx));
|
||||||
top_idx < top_contacts.size() && top_contacts[top_idx]->print_z < layer_new.print_z + this->m_support_layer_height_min;
|
top_idx < top_contacts.size() && top_contacts[top_idx]->print_z < layer_new.print_z + m_support_layer_height_min;
|
||||||
++ top_idx) {
|
++ top_idx) {
|
||||||
if (top_contacts[top_idx]->print_z > layer_new.print_z - this->m_support_layer_height_min) {
|
if (top_contacts[top_idx]->print_z > layer_new.print_z - m_support_layer_height_min) {
|
||||||
// A top layer has been found, which is close to the new bottom layer.
|
// A top layer has been found, which is close to the new bottom layer.
|
||||||
coordf_t diff = layer_new.print_z - top_contacts[top_idx]->print_z;
|
coordf_t diff = layer_new.print_z - top_contacts[top_idx]->print_z;
|
||||||
assert(std::abs(diff) <= this->m_support_layer_height_min);
|
assert(std::abs(diff) <= m_support_layer_height_min);
|
||||||
if (diff > 0.) {
|
if (diff > 0.) {
|
||||||
// The top contact layer is below this layer. Make the bridging layer thinner to align with the existing top layer.
|
// The top contact layer is below this layer. Make the bridging layer thinner to align with the existing top layer.
|
||||||
assert(diff < layer_new.height + EPSILON);
|
assert(diff < layer_new.height + EPSILON);
|
||||||
assert(layer_new.height - diff >= this->m_support_layer_height_min - EPSILON);
|
assert(layer_new.height - diff >= m_support_layer_height_min - EPSILON);
|
||||||
layer_new.print_z = top_contacts[top_idx]->print_z;
|
layer_new.print_z = top_contacts[top_idx]->print_z;
|
||||||
layer_new.height -= diff;
|
layer_new.height -= diff;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1093,7 +1093,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
||||||
// Trim the already created base layers above the current layer intersecting with the new bottom contacts layer.
|
// Trim the already created base layers above the current layer intersecting with the new bottom contacts layer.
|
||||||
touching = offset(touching, float(SCALED_EPSILON));
|
touching = offset(touching, float(SCALED_EPSILON));
|
||||||
for (int layer_id_above = layer_id + 1; layer_id_above < int(object.total_layer_count()); ++ layer_id_above) {
|
for (int layer_id_above = layer_id + 1; layer_id_above < int(object.total_layer_count()); ++ layer_id_above) {
|
||||||
const Layer &layer_above = *object.layers[layer_id_above];
|
const Layer &layer_above = *object.layers()[layer_id_above];
|
||||||
if (layer_above.print_z > layer_new.print_z + EPSILON)
|
if (layer_above.print_z > layer_new.print_z + EPSILON)
|
||||||
break;
|
break;
|
||||||
if (! layer_support_areas[layer_id_above].empty()) {
|
if (! layer_support_areas[layer_id_above].empty()) {
|
||||||
|
@ -1320,7 +1320,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
||||||
// Verify that the extremes are separated by m_support_layer_height_min.
|
// Verify that the extremes are separated by m_support_layer_height_min.
|
||||||
for (size_t i = 1; i < extremes.size(); ++ i) {
|
for (size_t i = 1; i < extremes.size(); ++ i) {
|
||||||
assert(extremes[i]->extreme_z() - extremes[i-1]->extreme_z() == 0. ||
|
assert(extremes[i]->extreme_z() - extremes[i-1]->extreme_z() == 0. ||
|
||||||
extremes[i]->extreme_z() - extremes[i-1]->extreme_z() > this->m_support_layer_height_min - EPSILON);
|
extremes[i]->extreme_z() - extremes[i-1]->extreme_z() > m_support_layer_height_min - EPSILON);
|
||||||
assert(extremes[i]->extreme_z() - extremes[i-1]->extreme_z() > 0. ||
|
assert(extremes[i]->extreme_z() - extremes[i-1]->extreme_z() > 0. ||
|
||||||
extremes[i]->layer_type == extremes[i-1]->layer_type ||
|
extremes[i]->layer_type == extremes[i-1]->layer_type ||
|
||||||
(extremes[i]->layer_type == sltBottomContact && extremes[i - 1]->layer_type == sltTopContact));
|
(extremes[i]->layer_type == sltBottomContact && extremes[i - 1]->layer_type == sltTopContact));
|
||||||
|
@ -1344,7 +1344,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
||||||
// This is a bottom of a synchronized (or soluble) top contact layer, its height has been decided in this->top_contact_layers().
|
// This is a bottom of a synchronized (or soluble) top contact layer, its height has been decided in this->top_contact_layers().
|
||||||
assert(extr2->layer_type == sltTopContact);
|
assert(extr2->layer_type == sltTopContact);
|
||||||
assert(extr2->bottom_z == m_slicing_params.first_print_layer_height);
|
assert(extr2->bottom_z == m_slicing_params.first_print_layer_height);
|
||||||
assert(extr2->print_z >= m_slicing_params.first_print_layer_height + this->m_support_layer_height_min - EPSILON);
|
assert(extr2->print_z >= m_slicing_params.first_print_layer_height + m_support_layer_height_min - EPSILON);
|
||||||
if (intermediate_layers.empty() || intermediate_layers.back()->print_z < m_slicing_params.first_print_layer_height) {
|
if (intermediate_layers.empty() || intermediate_layers.back()->print_z < m_slicing_params.first_print_layer_height) {
|
||||||
MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate);
|
MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate);
|
||||||
layer_new.bottom_z = 0.;
|
layer_new.bottom_z = 0.;
|
||||||
|
@ -1384,7 +1384,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
||||||
if (synchronize) {
|
if (synchronize) {
|
||||||
// Emit support layers synchronized with the object layers.
|
// Emit support layers synchronized with the object layers.
|
||||||
// Find the first object layer, which has its print_z in this support Z range.
|
// Find the first object layer, which has its print_z in this support Z range.
|
||||||
while (idx_layer_object < object.layers.size() && object.layers[idx_layer_object]->print_z < extr1z + EPSILON)
|
while (idx_layer_object < object.layers().size() && object.layers()[idx_layer_object]->print_z < extr1z + EPSILON)
|
||||||
++ idx_layer_object;
|
++ idx_layer_object;
|
||||||
if (idx_layer_object == 0 && extr1z == m_slicing_params.raft_interface_top_z) {
|
if (idx_layer_object == 0 && extr1z == m_slicing_params.raft_interface_top_z) {
|
||||||
// Insert one base support layer below the object.
|
// Insert one base support layer below the object.
|
||||||
|
@ -1395,11 +1395,11 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
||||||
intermediate_layers.push_back(&layer_new);
|
intermediate_layers.push_back(&layer_new);
|
||||||
}
|
}
|
||||||
// Emit all intermediate support layers synchronized with object layers up to extr2z.
|
// Emit all intermediate support layers synchronized with object layers up to extr2z.
|
||||||
for (; idx_layer_object < object.layers.size() && object.layers[idx_layer_object]->print_z < extr2z + EPSILON; ++ idx_layer_object) {
|
for (; idx_layer_object < object.layers().size() && object.layers()[idx_layer_object]->print_z < extr2z + EPSILON; ++ idx_layer_object) {
|
||||||
MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate);
|
MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate);
|
||||||
layer_new.print_z = object.layers[idx_layer_object]->print_z;
|
layer_new.print_z = object.layers()[idx_layer_object]->print_z;
|
||||||
layer_new.height = object.layers[idx_layer_object]->height;
|
layer_new.height = object.layers()[idx_layer_object]->height;
|
||||||
layer_new.bottom_z = (idx_layer_object > 0) ? object.layers[idx_layer_object - 1]->print_z : (layer_new.print_z - layer_new.height);
|
layer_new.bottom_z = (idx_layer_object > 0) ? object.layers()[idx_layer_object - 1]->print_z : (layer_new.print_z - layer_new.height);
|
||||||
assert(intermediate_layers.empty() || intermediate_layers.back()->print_z < layer_new.print_z + EPSILON);
|
assert(intermediate_layers.empty() || intermediate_layers.back()->print_z < layer_new.print_z + EPSILON);
|
||||||
intermediate_layers.push_back(&layer_new);
|
intermediate_layers.push_back(&layer_new);
|
||||||
}
|
}
|
||||||
|
@ -1409,10 +1409,10 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
||||||
assert(n_layers_extra > 0);
|
assert(n_layers_extra > 0);
|
||||||
coordf_t step = dist / coordf_t(n_layers_extra);
|
coordf_t step = dist / coordf_t(n_layers_extra);
|
||||||
if (extr1 != nullptr && extr1->layer_type == sltTopContact &&
|
if (extr1 != nullptr && extr1->layer_type == sltTopContact &&
|
||||||
extr1->print_z + this->m_support_layer_height_min > extr1->bottom_z + step) {
|
extr1->print_z + m_support_layer_height_min > extr1->bottom_z + step) {
|
||||||
// The bottom extreme is a bottom of a top surface. Ensure that the gap
|
// The bottom extreme is a bottom of a top surface. Ensure that the gap
|
||||||
// between the 1st intermediate layer print_z and extr1->print_z is not too small.
|
// between the 1st intermediate layer print_z and extr1->print_z is not too small.
|
||||||
assert(extr1->bottom_z + this->m_support_layer_height_min < extr1->print_z + EPSILON);
|
assert(extr1->bottom_z + m_support_layer_height_min < extr1->print_z + EPSILON);
|
||||||
// Generate the first intermediate layer.
|
// Generate the first intermediate layer.
|
||||||
MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate);
|
MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate);
|
||||||
layer_new.bottom_z = extr1->bottom_z;
|
layer_new.bottom_z = extr1->bottom_z;
|
||||||
|
@ -1509,7 +1509,7 @@ void PrintObjectSupportMaterial::generate_base_layers(
|
||||||
Polygons polygons_new;
|
Polygons polygons_new;
|
||||||
|
|
||||||
// Use the precomputed layer_support_areas.
|
// Use the precomputed layer_support_areas.
|
||||||
idx_object_layer_above = std::max(0, idx_lower_or_equal(object.layers, idx_object_layer_above,
|
idx_object_layer_above = std::max(0, idx_lower_or_equal(object.layers(), idx_object_layer_above,
|
||||||
[&layer_intermediate](const Layer *layer){ return layer->print_z <= layer_intermediate.print_z + EPSILON; }));
|
[&layer_intermediate](const Layer *layer){ return layer->print_z <= layer_intermediate.print_z + EPSILON; }));
|
||||||
polygons_new = layer_support_areas[idx_object_layer_above];
|
polygons_new = layer_support_areas[idx_object_layer_above];
|
||||||
|
|
||||||
|
@ -1644,24 +1644,24 @@ void PrintObjectSupportMaterial::trim_support_layers_by_object(
|
||||||
// Find the overlapping object layers including the extra above / below gap.
|
// Find the overlapping object layers including the extra above / below gap.
|
||||||
coordf_t z_threshold = support_layer.print_z - support_layer.height - gap_extra_below + EPSILON;
|
coordf_t z_threshold = support_layer.print_z - support_layer.height - gap_extra_below + EPSILON;
|
||||||
idx_object_layer_overlapping = idx_higher_or_equal(
|
idx_object_layer_overlapping = idx_higher_or_equal(
|
||||||
object.layers, idx_object_layer_overlapping,
|
object.layers(), idx_object_layer_overlapping,
|
||||||
[z_threshold](const Layer *layer){ return layer->print_z >= z_threshold; });
|
[z_threshold](const Layer *layer){ return layer->print_z >= z_threshold; });
|
||||||
// Collect all the object layers intersecting with this layer.
|
// Collect all the object layers intersecting with this layer.
|
||||||
Polygons polygons_trimming;
|
Polygons polygons_trimming;
|
||||||
size_t i = idx_object_layer_overlapping;
|
size_t i = idx_object_layer_overlapping;
|
||||||
for (; i < object.layers.size(); ++ i) {
|
for (; i < object.layers().size(); ++ i) {
|
||||||
const Layer &object_layer = *object.layers[i];
|
const Layer &object_layer = *object.layers()[i];
|
||||||
if (object_layer.print_z - object_layer.height > support_layer.print_z + gap_extra_above - EPSILON)
|
if (object_layer.print_z - object_layer.height > support_layer.print_z + gap_extra_above - EPSILON)
|
||||||
break;
|
break;
|
||||||
polygons_append(polygons_trimming, (Polygons)object_layer.slices);
|
polygons_append(polygons_trimming, (Polygons)object_layer.slices);
|
||||||
}
|
}
|
||||||
if (! this->m_slicing_params.soluble_interface) {
|
if (! m_slicing_params.soluble_interface) {
|
||||||
// Collect all bottom surfaces, which will be extruded with a bridging flow.
|
// Collect all bottom surfaces, which will be extruded with a bridging flow.
|
||||||
for (; i < object.layers.size(); ++ i) {
|
for (; i < object.layers().size(); ++ i) {
|
||||||
const Layer &object_layer = *object.layers[i];
|
const Layer &object_layer = *object.layers()[i];
|
||||||
bool some_region_overlaps = false;
|
bool some_region_overlaps = false;
|
||||||
for (LayerRegion* region : object_layer.regions) {
|
for (LayerRegion* region : object_layer.regions()) {
|
||||||
coordf_t nozzle_dmr = region->region()->nozzle_dmr_avg(*this->m_print_config);
|
coordf_t nozzle_dmr = region->region()->nozzle_dmr_avg(*m_print_config);
|
||||||
if (object_layer.print_z - nozzle_dmr > support_layer.print_z + gap_extra_above - EPSILON)
|
if (object_layer.print_z - nozzle_dmr > support_layer.print_z + gap_extra_above - EPSILON)
|
||||||
break;
|
break;
|
||||||
some_region_overlaps = true;
|
some_region_overlaps = true;
|
||||||
|
@ -1764,7 +1764,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
|
||||||
// Expand the bases of the support columns in the 1st layer.
|
// Expand the bases of the support columns in the 1st layer.
|
||||||
columns_base->polygons = diff(
|
columns_base->polygons = diff(
|
||||||
offset(columns_base->polygons, inflate_factor_1st_layer),
|
offset(columns_base->polygons, inflate_factor_1st_layer),
|
||||||
offset(m_object->layers.front()->slices.expolygons, scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
offset(m_object->layers().front()->slices.expolygons, scale_(m_gap_xy), SUPPORT_SURFACES_OFFSET_PARAMETERS));
|
||||||
if (contacts != nullptr)
|
if (contacts != nullptr)
|
||||||
columns_base->polygons = diff(columns_base->polygons, interface_polygons);
|
columns_base->polygons = diff(columns_base->polygons, interface_polygons);
|
||||||
}
|
}
|
||||||
|
@ -1909,8 +1909,8 @@ struct MyLayerExtruded
|
||||||
else
|
else
|
||||||
*m_polygons_to_extrude = std::move(polygons);
|
*m_polygons_to_extrude = std::move(polygons);
|
||||||
}
|
}
|
||||||
Polygons& polygons_to_extrude() { return (this->m_polygons_to_extrude == nullptr) ? layer->polygons : *this->m_polygons_to_extrude; }
|
Polygons& polygons_to_extrude() { return (m_polygons_to_extrude == nullptr) ? layer->polygons : *m_polygons_to_extrude; }
|
||||||
const Polygons& polygons_to_extrude() const { return (this->m_polygons_to_extrude == nullptr) ? layer->polygons : *this->m_polygons_to_extrude; }
|
const Polygons& polygons_to_extrude() const { return (m_polygons_to_extrude == nullptr) ? layer->polygons : *m_polygons_to_extrude; }
|
||||||
|
|
||||||
bool could_merge(const MyLayerExtruded &other) const {
|
bool could_merge(const MyLayerExtruded &other) const {
|
||||||
return ! this->empty() && ! other.empty() &&
|
return ! this->empty() && ! other.empty() &&
|
||||||
|
@ -1923,21 +1923,21 @@ struct MyLayerExtruded
|
||||||
assert(this->could_merge(other));
|
assert(this->could_merge(other));
|
||||||
// 1) Merge the rest polygons to extrude, if there are any.
|
// 1) Merge the rest polygons to extrude, if there are any.
|
||||||
if (other.m_polygons_to_extrude != nullptr) {
|
if (other.m_polygons_to_extrude != nullptr) {
|
||||||
if (this->m_polygons_to_extrude == nullptr) {
|
if (m_polygons_to_extrude == nullptr) {
|
||||||
// This layer has no extrusions generated yet, if it has no m_polygons_to_extrude (its area to extrude was not reduced yet).
|
// This layer has no extrusions generated yet, if it has no m_polygons_to_extrude (its area to extrude was not reduced yet).
|
||||||
assert(this->extrusions.empty());
|
assert(this->extrusions.empty());
|
||||||
this->m_polygons_to_extrude = new Polygons(this->layer->polygons);
|
m_polygons_to_extrude = new Polygons(this->layer->polygons);
|
||||||
}
|
}
|
||||||
Slic3r::polygons_append(*this->m_polygons_to_extrude, std::move(*other.m_polygons_to_extrude));
|
Slic3r::polygons_append(*m_polygons_to_extrude, std::move(*other.m_polygons_to_extrude));
|
||||||
*this->m_polygons_to_extrude = union_(*this->m_polygons_to_extrude, true);
|
*m_polygons_to_extrude = union_(*m_polygons_to_extrude, true);
|
||||||
delete other.m_polygons_to_extrude;
|
delete other.m_polygons_to_extrude;
|
||||||
other.m_polygons_to_extrude = nullptr;
|
other.m_polygons_to_extrude = nullptr;
|
||||||
} else if (this->m_polygons_to_extrude != nullptr) {
|
} else if (m_polygons_to_extrude != nullptr) {
|
||||||
assert(other.m_polygons_to_extrude == nullptr);
|
assert(other.m_polygons_to_extrude == nullptr);
|
||||||
// The other layer has no extrusions generated yet, if it has no m_polygons_to_extrude (its area to extrude was not reduced yet).
|
// The other layer has no extrusions generated yet, if it has no m_polygons_to_extrude (its area to extrude was not reduced yet).
|
||||||
assert(other.extrusions.empty());
|
assert(other.extrusions.empty());
|
||||||
Slic3r::polygons_append(*this->m_polygons_to_extrude, other.layer->polygons);
|
Slic3r::polygons_append(*m_polygons_to_extrude, other.layer->polygons);
|
||||||
*this->m_polygons_to_extrude = union_(*this->m_polygons_to_extrude, true);
|
*m_polygons_to_extrude = union_(*m_polygons_to_extrude, true);
|
||||||
}
|
}
|
||||||
// 2) Merge the extrusions.
|
// 2) Merge the extrusions.
|
||||||
this->extrusions.insert(this->extrusions.end(), other.extrusions.begin(), other.extrusions.end());
|
this->extrusions.insert(this->extrusions.end(), other.extrusions.begin(), other.extrusions.end());
|
||||||
|
@ -2535,7 +2535,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
||||||
for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id)
|
for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id)
|
||||||
{
|
{
|
||||||
assert(support_layer_id < raft_layers.size());
|
assert(support_layer_id < raft_layers.size());
|
||||||
SupportLayer &support_layer = *object.support_layers[support_layer_id];
|
SupportLayer &support_layer = *object.support_layers()[support_layer_id];
|
||||||
assert(support_layer.support_fills.entities.empty());
|
assert(support_layer.support_fills.entities.empty());
|
||||||
MyLayer &raft_layer = *raft_layers[support_layer_id];
|
MyLayer &raft_layer = *raft_layers[support_layer_id];
|
||||||
|
|
||||||
|
@ -2631,9 +2631,9 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
||||||
MyLayerExtruded interface_layer;
|
MyLayerExtruded interface_layer;
|
||||||
std::vector<LayerCacheItem> overlaps;
|
std::vector<LayerCacheItem> overlaps;
|
||||||
};
|
};
|
||||||
std::vector<LayerCache> layer_caches(object.support_layers.size(), LayerCache());
|
std::vector<LayerCache> layer_caches(object.support_layers().size(), LayerCache());
|
||||||
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, object.support_layers.size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, object.support_layers().size()),
|
||||||
[this, &object, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &layer_caches, &loop_interface_processor,
|
[this, &object, &bottom_contacts, &top_contacts, &intermediate_layers, &interface_layers, &layer_caches, &loop_interface_processor,
|
||||||
infill_pattern, &bbox_object, support_density, interface_density, interface_angle, &angles, link_max_length_factor, with_sheath]
|
infill_pattern, &bbox_object, support_density, interface_density, interface_angle, &angles, link_max_length_factor, with_sheath]
|
||||||
(const tbb::blocked_range<size_t>& range) {
|
(const tbb::blocked_range<size_t>& range) {
|
||||||
|
@ -2648,7 +2648,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
||||||
filler_support->set_bounding_box(bbox_object);
|
filler_support->set_bounding_box(bbox_object);
|
||||||
for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id)
|
for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id)
|
||||||
{
|
{
|
||||||
SupportLayer &support_layer = *object.support_layers[support_layer_id];
|
SupportLayer &support_layer = *object.support_layers()[support_layer_id];
|
||||||
LayerCache &layer_cache = layer_caches[support_layer_id];
|
LayerCache &layer_cache = layer_caches[support_layer_id];
|
||||||
|
|
||||||
// Find polygons with the same print_z.
|
// Find polygons with the same print_z.
|
||||||
|
@ -2844,11 +2844,11 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now modulate the support layer height in parallel.
|
// Now modulate the support layer height in parallel.
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, object.support_layers.size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, object.support_layers().size()),
|
||||||
[this, &object, &layer_caches]
|
[this, &object, &layer_caches]
|
||||||
(const tbb::blocked_range<size_t>& range) {
|
(const tbb::blocked_range<size_t>& range) {
|
||||||
for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id) {
|
for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id) {
|
||||||
SupportLayer &support_layer = *object.support_layers[support_layer_id];
|
SupportLayer &support_layer = *object.support_layers()[support_layer_id];
|
||||||
LayerCache &layer_cache = layer_caches[support_layer_id];
|
LayerCache &layer_cache = layer_caches[support_layer_id];
|
||||||
for (LayerCacheItem &layer_cache_item : layer_cache.overlaps) {
|
for (LayerCacheItem &layer_cache_item : layer_cache.overlaps) {
|
||||||
modulate_extrusion_by_overlapping_layers(layer_cache_item.layer_extruded->extrusions, *layer_cache_item.layer_extruded->layer, layer_cache_item.overlapping);
|
modulate_extrusion_by_overlapping_layers(layer_cache_item.layer_extruded->extrusions, *layer_cache_item.layer_extruded->layer, layer_cache_item.overlapping);
|
||||||
|
|
|
@ -1670,30 +1670,30 @@ void _3DScene::_load_print_toolpaths(
|
||||||
// The skirt and brim steps should be marked as done, so their paths are valid.
|
// The skirt and brim steps should be marked as done, so their paths are valid.
|
||||||
assert(print->is_step_done(psSkirt) && print->is_step_done(psBrim));
|
assert(print->is_step_done(psSkirt) && print->is_step_done(psBrim));
|
||||||
|
|
||||||
if (!print->has_skirt() && print->config.brim_width.value == 0)
|
if (!print->has_skirt() && print->config().brim_width.value == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const float color[] = { 0.5f, 1.0f, 0.5f, 1.f }; // greenish
|
const float color[] = { 0.5f, 1.0f, 0.5f, 1.f }; // greenish
|
||||||
|
|
||||||
// number of skirt layers
|
// number of skirt layers
|
||||||
size_t total_layer_count = 0;
|
size_t total_layer_count = 0;
|
||||||
for (const PrintObject *print_object : print->objects)
|
for (const PrintObject *print_object : print->objects())
|
||||||
total_layer_count = std::max(total_layer_count, print_object->total_layer_count());
|
total_layer_count = std::max(total_layer_count, print_object->total_layer_count());
|
||||||
size_t skirt_height = print->has_infinite_skirt() ?
|
size_t skirt_height = print->has_infinite_skirt() ?
|
||||||
total_layer_count :
|
total_layer_count :
|
||||||
std::min<size_t>(print->config.skirt_height.value, total_layer_count);
|
std::min<size_t>(print->config().skirt_height.value, total_layer_count);
|
||||||
if (skirt_height == 0 && print->config.brim_width.value > 0)
|
if (skirt_height == 0 && print->config().brim_width.value > 0)
|
||||||
skirt_height = 1;
|
skirt_height = 1;
|
||||||
|
|
||||||
// get first skirt_height layers (maybe this should be moved to a PrintObject method?)
|
// get first skirt_height layers (maybe this should be moved to a PrintObject method?)
|
||||||
const PrintObject *object0 = print->objects.front();
|
const PrintObject *object0 = print->objects().front();
|
||||||
std::vector<float> print_zs;
|
std::vector<float> print_zs;
|
||||||
print_zs.reserve(skirt_height * 2);
|
print_zs.reserve(skirt_height * 2);
|
||||||
for (size_t i = 0; i < std::min(skirt_height, object0->layers.size()); ++ i)
|
for (size_t i = 0; i < std::min(skirt_height, object0->layers().size()); ++ i)
|
||||||
print_zs.push_back(float(object0->layers[i]->print_z));
|
print_zs.push_back(float(object0->layers()[i]->print_z));
|
||||||
//FIXME why there are support layers?
|
//FIXME why there are support layers?
|
||||||
for (size_t i = 0; i < std::min(skirt_height, object0->support_layers.size()); ++ i)
|
for (size_t i = 0; i < std::min(skirt_height, object0->support_layers().size()); ++ i)
|
||||||
print_zs.push_back(float(object0->support_layers[i]->print_z));
|
print_zs.push_back(float(object0->support_layers()[i]->print_z));
|
||||||
sort_remove_duplicates(print_zs);
|
sort_remove_duplicates(print_zs);
|
||||||
if (print_zs.size() > skirt_height)
|
if (print_zs.size() > skirt_height)
|
||||||
print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
|
print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
|
||||||
|
@ -1705,8 +1705,8 @@ void _3DScene::_load_print_toolpaths(
|
||||||
volume.offsets.push_back(volume.indexed_vertex_array.quad_indices.size());
|
volume.offsets.push_back(volume.indexed_vertex_array.quad_indices.size());
|
||||||
volume.offsets.push_back(volume.indexed_vertex_array.triangle_indices.size());
|
volume.offsets.push_back(volume.indexed_vertex_array.triangle_indices.size());
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
extrusionentity_to_verts(print->brim, print_zs[i], Point(0, 0), volume);
|
extrusionentity_to_verts(print->brim(), print_zs[i], Point(0, 0), volume);
|
||||||
extrusionentity_to_verts(print->skirt, print_zs[i], Point(0, 0), volume);
|
extrusionentity_to_verts(print->skirt(), print_zs[i], Point(0, 0), volume);
|
||||||
}
|
}
|
||||||
volume.bounding_box = volume.indexed_vertex_array.bounding_box();
|
volume.bounding_box = volume.indexed_vertex_array.bounding_box();
|
||||||
volume.indexed_vertex_array.finalize_geometry(use_VBOs);
|
volume.indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||||
|
@ -1753,10 +1753,10 @@ void _3DScene::_load_print_object_toolpaths(
|
||||||
ctxt.shifted_copies = &print_object->_shifted_copies;
|
ctxt.shifted_copies = &print_object->_shifted_copies;
|
||||||
|
|
||||||
// order layers by print_z
|
// order layers by print_z
|
||||||
ctxt.layers.reserve(print_object->layers.size() + print_object->support_layers.size());
|
ctxt.layers.reserve(print_object->layers().size() + print_object->support_layers().size());
|
||||||
for (const Layer *layer : print_object->layers)
|
for (const Layer *layer : print_object->layers())
|
||||||
ctxt.layers.push_back(layer);
|
ctxt.layers.push_back(layer);
|
||||||
for (const Layer *layer : print_object->support_layers)
|
for (const Layer *layer : print_object->support_layers())
|
||||||
ctxt.layers.push_back(layer);
|
ctxt.layers.push_back(layer);
|
||||||
std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
|
std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
|
||||||
|
|
||||||
|
@ -1803,10 +1803,10 @@ void _3DScene::_load_print_object_toolpaths(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const Point ©: *ctxt.shifted_copies) {
|
for (const Point ©: *ctxt.shifted_copies) {
|
||||||
for (const LayerRegion *layerm : layer->regions) {
|
for (const LayerRegion *layerm : layer->regions()) {
|
||||||
if (ctxt.has_perimeters)
|
if (ctxt.has_perimeters)
|
||||||
extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
|
extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
|
||||||
*vols[ctxt.volume_idx(layerm->region()->config.perimeter_extruder.value, 0)]);
|
*vols[ctxt.volume_idx(layerm->region()->config().perimeter_extruder.value, 0)]);
|
||||||
if (ctxt.has_infill) {
|
if (ctxt.has_infill) {
|
||||||
for (const ExtrusionEntity *ee : layerm->fills.entities) {
|
for (const ExtrusionEntity *ee : layerm->fills.entities) {
|
||||||
// fill represents infill extrusions of a single island.
|
// fill represents infill extrusions of a single island.
|
||||||
|
@ -1815,8 +1815,8 @@ void _3DScene::_load_print_object_toolpaths(
|
||||||
extrusionentity_to_verts(*fill, float(layer->print_z), copy,
|
extrusionentity_to_verts(*fill, float(layer->print_z), copy,
|
||||||
*vols[ctxt.volume_idx(
|
*vols[ctxt.volume_idx(
|
||||||
is_solid_infill(fill->entities.front()->role()) ?
|
is_solid_infill(fill->entities.front()->role()) ?
|
||||||
layerm->region()->config.solid_infill_extruder :
|
layerm->region()->config().solid_infill_extruder :
|
||||||
layerm->region()->config.infill_extruder,
|
layerm->region()->config().infill_extruder,
|
||||||
1)]);
|
1)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1828,8 +1828,8 @@ void _3DScene::_load_print_object_toolpaths(
|
||||||
extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
|
extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
|
||||||
*vols[ctxt.volume_idx(
|
*vols[ctxt.volume_idx(
|
||||||
(extrusion_entity->role() == erSupportMaterial) ?
|
(extrusion_entity->role() == erSupportMaterial) ?
|
||||||
support_layer->object()->config.support_material_extruder :
|
support_layer->object()->config().support_material_extruder :
|
||||||
support_layer->object()->config.support_material_interface_extruder,
|
support_layer->object()->config().support_material_interface_extruder,
|
||||||
2)]);
|
2)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1877,7 +1877,7 @@ void _3DScene::_load_wipe_tower_toolpaths(
|
||||||
const std::vector<std::string> &tool_colors_str,
|
const std::vector<std::string> &tool_colors_str,
|
||||||
bool use_VBOs)
|
bool use_VBOs)
|
||||||
{
|
{
|
||||||
if (print->m_wipe_tower_tool_changes.empty())
|
if (print->wipe_tower_data().tool_changes.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::vector<float> tool_colors = parse_colors(tool_colors_str);
|
std::vector<float> tool_colors = parse_colors(tool_colors_str);
|
||||||
|
@ -1902,8 +1902,8 @@ void _3DScene::_load_wipe_tower_toolpaths(
|
||||||
|
|
||||||
const std::vector<WipeTower::ToolChangeResult>& tool_change(size_t idx) {
|
const std::vector<WipeTower::ToolChangeResult>& tool_change(size_t idx) {
|
||||||
return priming.empty() ?
|
return priming.empty() ?
|
||||||
((idx == print->m_wipe_tower_tool_changes.size()) ? final : print->m_wipe_tower_tool_changes[idx]) :
|
((idx == print->wipe_tower_data().tool_changes.size()) ? final : print->wipe_tower_data().tool_changes[idx]) :
|
||||||
((idx == 0) ? priming : (idx == print->m_wipe_tower_tool_changes.size() + 1) ? final : print->m_wipe_tower_tool_changes[idx - 1]);
|
((idx == 0) ? priming : (idx == print->wipe_tower_data().tool_changes.size() + 1) ? final : print->wipe_tower_data().tool_changes[idx - 1]);
|
||||||
}
|
}
|
||||||
std::vector<WipeTower::ToolChangeResult> priming;
|
std::vector<WipeTower::ToolChangeResult> priming;
|
||||||
std::vector<WipeTower::ToolChangeResult> final;
|
std::vector<WipeTower::ToolChangeResult> final;
|
||||||
|
@ -1911,15 +1911,15 @@ void _3DScene::_load_wipe_tower_toolpaths(
|
||||||
|
|
||||||
ctxt.print = print;
|
ctxt.print = print;
|
||||||
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
||||||
if (print->m_wipe_tower_priming)
|
if (print->wipe_tower_data().priming != nullptr)
|
||||||
ctxt.priming.emplace_back(*print->m_wipe_tower_priming.get());
|
ctxt.priming.emplace_back(*print->wipe_tower_data().priming);
|
||||||
if (print->m_wipe_tower_final_purge)
|
if (print->wipe_tower_data().final_purge)
|
||||||
ctxt.final.emplace_back(*print->m_wipe_tower_final_purge.get());
|
ctxt.final.emplace_back(*print->wipe_tower_data().final_purge);
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
|
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
|
||||||
|
|
||||||
//FIXME Improve the heuristics for a grain size.
|
//FIXME Improve the heuristics for a grain size.
|
||||||
size_t n_items = print->m_wipe_tower_tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
size_t n_items = print->wipe_tower_data().tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
||||||
size_t grain_size = std::max(n_items / 128, size_t(1));
|
size_t grain_size = std::max(n_items / 128, size_t(1));
|
||||||
tbb::spin_mutex new_volume_mutex;
|
tbb::spin_mutex new_volume_mutex;
|
||||||
auto new_volume = [volumes, &new_volume_mutex](const float *color) -> GLVolume* {
|
auto new_volume = [volumes, &new_volume_mutex](const float *color) -> GLVolume* {
|
||||||
|
@ -2554,13 +2554,13 @@ void _3DScene::_load_shells(const Print& print, GLVolumeCollection& volumes, boo
|
||||||
size_t initial_volumes_count = volumes.volumes.size();
|
size_t initial_volumes_count = volumes.volumes.size();
|
||||||
s_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Shell, 0, (unsigned int)initial_volumes_count);
|
s_gcode_preview_volume_index.first_volumes.emplace_back(GCodePreviewVolumeIndex::Shell, 0, (unsigned int)initial_volumes_count);
|
||||||
|
|
||||||
if (print.objects.empty())
|
if (print.objects().empty())
|
||||||
// nothing to render, return
|
// nothing to render, return
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// adds objects' volumes
|
// adds objects' volumes
|
||||||
unsigned int object_id = 0;
|
unsigned int object_id = 0;
|
||||||
for (PrintObject* obj : print.objects)
|
for (PrintObject* obj : print.objects())
|
||||||
{
|
{
|
||||||
ModelObject* model_obj = obj->model_object();
|
ModelObject* model_obj = obj->model_object();
|
||||||
|
|
||||||
|
@ -2579,8 +2579,8 @@ void _3DScene::_load_shells(const Print& print, GLVolumeCollection& volumes, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
// adds wipe tower's volume
|
// adds wipe tower's volume
|
||||||
coordf_t max_z = print.objects[0]->model_object()->get_model()->bounding_box().max.z;
|
coordf_t max_z = print.objects().front()->model_object()->get_model()->bounding_box().max.z;
|
||||||
const PrintConfig& config = print.config;
|
const PrintConfig& config = print.config();
|
||||||
unsigned int extruders_count = config.nozzle_diameter.size();
|
unsigned int extruders_count = config.nozzle_diameter.size();
|
||||||
if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects)
|
if ((extruders_count > 1) && config.single_extruder_multi_material && config.wipe_tower && !config.complete_objects)
|
||||||
volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, config.wipe_tower_per_color_wipe * (extruders_count - 1), max_z, use_VBOs);
|
volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, config.wipe_tower_per_color_wipe * (extruders_count - 1), max_z, use_VBOs);
|
||||||
|
|
|
@ -31,7 +31,7 @@ _constant()
|
||||||
// owned by Print, no constructor/destructor
|
// owned by Print, no constructor/destructor
|
||||||
|
|
||||||
Ref<StaticPrintConfig> config()
|
Ref<StaticPrintConfig> config()
|
||||||
%code%{ RETVAL = &THIS->config; %};
|
%code%{ RETVAL = &THIS->config(); %};
|
||||||
Ref<Print> print();
|
Ref<Print> print();
|
||||||
|
|
||||||
Clone<Flow> flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, PrintObject* object)
|
Clone<Flow> flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, PrintObject* object)
|
||||||
|
@ -42,12 +42,12 @@ _constant()
|
||||||
// owned by Print, no constructor/destructor
|
// owned by Print, no constructor/destructor
|
||||||
|
|
||||||
int region_count()
|
int region_count()
|
||||||
%code%{ RETVAL = THIS->print()->regions.size(); %};
|
%code%{ RETVAL = THIS->print()->regions().size(); %};
|
||||||
|
|
||||||
Ref<Print> print();
|
Ref<Print> print();
|
||||||
Ref<ModelObject> model_object();
|
Ref<ModelObject> model_object();
|
||||||
Ref<StaticPrintConfig> config()
|
Ref<StaticPrintConfig> config()
|
||||||
%code%{ RETVAL = &THIS->config; %};
|
%code%{ RETVAL = &THIS->config(); %};
|
||||||
Points copies();
|
Points copies();
|
||||||
t_layer_height_ranges layer_height_ranges()
|
t_layer_height_ranges layer_height_ranges()
|
||||||
%code%{ RETVAL = THIS->layer_height_ranges; %};
|
%code%{ RETVAL = THIS->layer_height_ranges; %};
|
||||||
|
@ -95,32 +95,41 @@ _constant()
|
||||||
~Print();
|
~Print();
|
||||||
|
|
||||||
Ref<StaticPrintConfig> config()
|
Ref<StaticPrintConfig> config()
|
||||||
%code%{ RETVAL = &THIS->config; %};
|
%code%{ RETVAL = &THIS->config(); %};
|
||||||
Ref<PlaceholderParser> placeholder_parser()
|
Ref<PlaceholderParser> placeholder_parser()
|
||||||
%code%{ RETVAL = &THIS->placeholder_parser; %};
|
%code%{ RETVAL = &THIS->placeholder_parser(); %};
|
||||||
Ref<ExtrusionEntityCollection> skirt()
|
Ref<ExtrusionEntityCollection> skirt()
|
||||||
%code%{ RETVAL = &THIS->skirt; %};
|
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->skirt()); %};
|
||||||
Ref<ExtrusionEntityCollection> brim()
|
Ref<ExtrusionEntityCollection> brim()
|
||||||
%code%{ RETVAL = &THIS->brim; %};
|
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->brim()); %};
|
||||||
std::string estimated_print_time()
|
std::string estimated_print_time()
|
||||||
%code%{ RETVAL = THIS->estimated_print_time; %};
|
%code%{ RETVAL = THIS->print_statistics().estimated_print_time; %};
|
||||||
|
double total_used_filament()
|
||||||
|
%code%{ RETVAL = THIS->print_statistics().total_used_filament; %};
|
||||||
|
double total_extruded_volume()
|
||||||
|
%code%{ RETVAL = THIS->print_statistics().total_extruded_volume; %};
|
||||||
|
double total_weight()
|
||||||
|
%code%{ RETVAL = THIS->print_statistics().total_weight; %};
|
||||||
|
double total_cost()
|
||||||
|
%code%{ RETVAL = THIS->print_statistics().total_cost; %};
|
||||||
|
|
||||||
PrintObjectPtrs* objects()
|
PrintObjectPtrs* objects()
|
||||||
%code%{ RETVAL = &THIS->objects; %};
|
%code%{ RETVAL = const_cast<PrintObjectPtrs*>(&THIS->objects()); %};
|
||||||
void clear_objects();
|
void clear_objects();
|
||||||
Ref<PrintObject> get_object(int idx);
|
Ref<PrintObject> get_object(int idx)
|
||||||
|
%code%{ RETVAL = THIS->objects()[idx]; %};
|
||||||
void delete_object(int idx);
|
void delete_object(int idx);
|
||||||
void reload_object(int idx);
|
void reload_object(int idx);
|
||||||
bool reload_model_instances();
|
bool reload_model_instances();
|
||||||
size_t object_count()
|
size_t object_count()
|
||||||
%code%{ RETVAL = THIS->objects.size(); %};
|
%code%{ RETVAL = THIS->objects().size(); %};
|
||||||
|
|
||||||
PrintRegionPtrs* regions()
|
PrintRegionPtrs* regions()
|
||||||
%code%{ RETVAL = &THIS->regions; %};
|
%code%{ RETVAL = const_cast<PrintRegionPtrs*>(&THIS->regions()); %};
|
||||||
Ref<PrintRegion> get_region(int idx);
|
Ref<PrintRegion> get_region(int idx)
|
||||||
Ref<PrintRegion> add_region();
|
%code%{ RETVAL = THIS->regions()[idx]; %};
|
||||||
size_t region_count()
|
size_t region_count()
|
||||||
%code%{ RETVAL = THIS->regions.size(); %};
|
%code%{ RETVAL = THIS->regions().size(); %};
|
||||||
|
|
||||||
bool step_done(PrintStep step)
|
bool step_done(PrintStep step)
|
||||||
%code%{ RETVAL = THIS->is_step_done(step); %};
|
%code%{ RETVAL = THIS->is_step_done(step); %};
|
||||||
|
@ -130,7 +139,7 @@ _constant()
|
||||||
SV* filament_stats()
|
SV* filament_stats()
|
||||||
%code%{
|
%code%{
|
||||||
HV* hv = newHV();
|
HV* hv = newHV();
|
||||||
for (std::map<size_t,float>::const_iterator it = THIS->filament_stats.begin(); it != THIS->filament_stats.end(); ++it) {
|
for (std::map<size_t,float>::const_iterator it = THIS->print_statistics().filament_stats.begin(); it != THIS->print_statistics().filament_stats.end(); ++it) {
|
||||||
// stringify extruder_id
|
// stringify extruder_id
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
ss << it->first;
|
ss << it->first;
|
||||||
|
@ -194,47 +203,4 @@ _constant()
|
||||||
}
|
}
|
||||||
%};
|
%};
|
||||||
|
|
||||||
%{
|
|
||||||
|
|
||||||
double
|
|
||||||
Print::total_used_filament(...)
|
|
||||||
CODE:
|
|
||||||
if (items > 1) {
|
|
||||||
THIS->total_used_filament = (double)SvNV(ST(1));
|
|
||||||
}
|
|
||||||
RETVAL = THIS->total_used_filament;
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
|
|
||||||
double
|
|
||||||
Print::total_extruded_volume(...)
|
|
||||||
CODE:
|
|
||||||
if (items > 1) {
|
|
||||||
THIS->total_extruded_volume = (double)SvNV(ST(1));
|
|
||||||
}
|
|
||||||
RETVAL = THIS->total_extruded_volume;
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
|
|
||||||
|
|
||||||
double
|
|
||||||
Print::total_weight(...)
|
|
||||||
CODE:
|
|
||||||
if (items > 1) {
|
|
||||||
THIS->total_weight = (double)SvNV(ST(1));
|
|
||||||
}
|
|
||||||
RETVAL = THIS->total_weight;
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
|
|
||||||
double
|
|
||||||
Print::total_cost(...)
|
|
||||||
CODE:
|
|
||||||
if (items > 1) {
|
|
||||||
THIS->total_cost = (double)SvNV(ST(1));
|
|
||||||
}
|
|
||||||
RETVAL = THIS->total_cost;
|
|
||||||
OUTPUT:
|
|
||||||
RETVAL
|
|
||||||
%}
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue