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;
|
||||
|
||||
double fill_density = layerm.region()->config.fill_density;
|
||||
double fill_density = layerm.region()->config().fill_density;
|
||||
Flow infill_flow = layerm.flow(frInfill);
|
||||
Flow solid_infill_flow = layerm.flow(frSolidInfill);
|
||||
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)) {
|
||||
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].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.
|
||||
|
@ -152,7 +152,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||
for (const Surface &surface : surfaces) {
|
||||
if (surface.surface_type == stInternalVoid)
|
||||
continue;
|
||||
InfillPattern fill_pattern = layerm.region()->config.fill_pattern.value;
|
||||
InfillPattern fill_pattern = layerm.region()->config().fill_pattern.value;
|
||||
double density = fill_density;
|
||||
FlowRole role = (surface.surface_type == stTop) ? frTopSolidInfill :
|
||||
(surface.is_solid() ? frSolidInfill : frInfill);
|
||||
|
@ -161,7 +161,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||
if (surface.is_solid()) {
|
||||
density = 100.;
|
||||
fill_pattern = (surface.is_external() && ! is_bridge) ?
|
||||
layerm.region()->config.external_fill_pattern.value :
|
||||
layerm.region()->config().external_fill_pattern.value :
|
||||
ipRectilinear;
|
||||
} else if (density <= 0)
|
||||
continue;
|
||||
|
@ -190,7 +190,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||
// layer height
|
||||
Flow internal_flow = layerm.region()->flow(
|
||||
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 first layer
|
||||
-1, // auto width
|
||||
|
@ -205,7 +205,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||
double link_max_length = 0.;
|
||||
if (! is_bridge) {
|
||||
#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);
|
||||
#else
|
||||
if (density > 80.) // 80%
|
||||
|
@ -215,7 +215,7 @@ void make_fill(LayerRegion &layerm, ExtrusionEntityCollection &out)
|
|||
|
||||
f->layer_id = layerm.layer()->id();
|
||||
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.
|
||||
f->link_max_length = scale_(link_max_length);
|
||||
// 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(
|
||||
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.
|
||||
(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.
|
||||
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),
|
||||
(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.
|
||||
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),
|
||||
false);
|
||||
}
|
||||
|
||||
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(
|
||||
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.
|
||||
(width.value > 0) ? width : object->config.extrusion_width,
|
||||
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)),
|
||||
(width.value > 0) ? width : object->config().extrusion_width,
|
||||
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)),
|
||||
false);
|
||||
}
|
||||
|
||||
|
@ -135,10 +135,10 @@ Flow support_material_interface_flow(const PrintObject *object, float layer_heig
|
|||
return Flow::new_from_config_width(
|
||||
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.
|
||||
(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.
|
||||
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),
|
||||
(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.
|
||||
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),
|
||||
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> 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.
|
||||
size_t idx_object_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;
|
||||
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.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;
|
||||
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) {
|
||||
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 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;
|
||||
for (size_t i = 0; i < print.objects.size(); ++ i) {
|
||||
per_object[i] = collect_layers_to_print(*print.objects[i]);
|
||||
for (size_t i = 0; i < print.objects().size(); ++ i) {
|
||||
per_object[i] = collect_layers_to_print(*print.objects()[i]);
|
||||
OrderingItem ordering_item;
|
||||
ordering_item.object_idx = i;
|
||||
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;
|
||||
// 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.second.assign(print.objects.size(), LayerToPrint());
|
||||
merged.second.assign(print.objects().size(), LayerToPrint());
|
||||
for (; i < j; ++ i) {
|
||||
const OrderingItem &oi = ordering[i];
|
||||
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");
|
||||
|
||||
try {
|
||||
this->m_placeholder_parser_failed_templates.clear();
|
||||
m_placeholder_parser_failed_templates.clear();
|
||||
this->_do_export(*print, file, preview_data);
|
||||
fflush(file);
|
||||
if (ferror(file)) {
|
||||
|
@ -382,10 +382,10 @@ void GCode::do_export(Print *print, const char *path, GCodePreviewData *preview_
|
|||
throw;
|
||||
}
|
||||
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.
|
||||
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 += "\nPlease inspect the file ";
|
||||
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
|
||||
m_time_estimator.reset();
|
||||
m_time_estimator.set_dialect(print.config.gcode_flavor);
|
||||
m_time_estimator.set_dialect(print.config().gcode_flavor);
|
||||
|
||||
// resets analyzer
|
||||
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?
|
||||
// change_layer() in turn increments the progress bar status.
|
||||
m_layer_count = 0;
|
||||
if (print.config.complete_objects.value) {
|
||||
if (print.config().complete_objects.value) {
|
||||
// Add each of the object's layers separately.
|
||||
for (auto object : print.objects) {
|
||||
for (auto object : print.objects()) {
|
||||
std::vector<coordf_t> zs;
|
||||
zs.reserve(object->layers.size() + object->support_layers.size());
|
||||
for (auto layer : object->layers)
|
||||
zs.reserve(object->layers().size() + object->support_layers().size());
|
||||
for (auto layer : object->layers())
|
||||
zs.push_back(layer->print_z);
|
||||
for (auto layer : object->support_layers)
|
||||
for (auto layer : object->support_layers())
|
||||
zs.push_back(layer->print_z);
|
||||
std::sort(zs.begin(), zs.end());
|
||||
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 {
|
||||
// Print all objects with the same print_z together.
|
||||
std::vector<coordf_t> zs;
|
||||
for (auto object : print.objects) {
|
||||
zs.reserve(zs.size() + object->layers.size() + object->support_layers.size());
|
||||
for (auto layer : object->layers)
|
||||
for (auto object : print.objects()) {
|
||||
zs.reserve(zs.size() + object->layers().size() + object->support_layers().size());
|
||||
for (auto layer : object->layers())
|
||||
zs.push_back(layer->print_z);
|
||||
for (auto layer : object->support_layers)
|
||||
for (auto layer : object->support_layers())
|
||||
zs.push_back(layer->print_z);
|
||||
}
|
||||
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();
|
||||
|
||||
m_enable_cooling_markers = true;
|
||||
this->apply_print_config(print.config);
|
||||
this->apply_print_config(print.config());
|
||||
this->set_extruders(print.extruders());
|
||||
|
||||
// Initialize autospeed.
|
||||
{
|
||||
// get the minimum cross-section used in the print
|
||||
std::vector<double> mm3_per_mm;
|
||||
for (auto object : print.objects) {
|
||||
for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) {
|
||||
auto region = print.regions[region_id];
|
||||
for (auto layer : object->layers) {
|
||||
auto layerm = layer->regions[region_id];
|
||||
if (region->config.get_abs_value("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("bridge_speed" ) == 0)
|
||||
for (auto object : print.objects()) {
|
||||
for (size_t region_id = 0; region_id < print.regions().size(); ++ region_id) {
|
||||
auto region = print.regions()[region_id];
|
||||
for (auto layer : object->layers()) {
|
||||
auto layerm = layer->regions()[region_id];
|
||||
if (region->config().get_abs_value("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("bridge_speed" ) == 0)
|
||||
mm3_per_mm.push_back(layerm->perimeters.min_mm3_per_mm());
|
||||
if (region->config.get_abs_value("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("bridge_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("top_solid_infill_speed" ) == 0 ||
|
||||
region->config().get_abs_value("bridge_speed" ) == 0)
|
||||
mm3_per_mm.push_back(layerm->fills.min_mm3_per_mm());
|
||||
}
|
||||
}
|
||||
if (object->config.get_abs_value("support_material_speed" ) == 0 ||
|
||||
object->config.get_abs_value("support_material_interface_speed" ) == 0)
|
||||
for (auto layer : object->support_layers)
|
||||
if (object->config().get_abs_value("support_material_speed" ) == 0 ||
|
||||
object->config().get_abs_value("support_material_interface_speed" ) == 0)
|
||||
for (auto layer : object->support_layers())
|
||||
mm3_per_mm.push_back(layer->support_fills.min_mm3_per_mm());
|
||||
}
|
||||
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
|
||||
// smallest cross-section at the maximum speed: any larger cross-section
|
||||
// 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
|
||||
if (print.config.max_volumetric_speed.value > 0)
|
||||
m_volumetric_speed = std::min(m_volumetric_speed, print.config.max_volumetric_speed.value);
|
||||
if (print.config().max_volumetric_speed.value > 0)
|
||||
m_volumetric_speed = std::min(m_volumetric_speed, print.config().max_volumetric_speed.value);
|
||||
}
|
||||
}
|
||||
print.throw_if_canceled();
|
||||
|
||||
m_cooling_buffer = make_unique<CoolingBuffer>(*this);
|
||||
if (print.config.spiral_vase.value)
|
||||
m_spiral_vase = make_unique<SpiralVase>(print.config);
|
||||
if (print.config.max_volumetric_extrusion_rate_slope_positive.value > 0 ||
|
||||
print.config.max_volumetric_extrusion_rate_slope_negative.value > 0)
|
||||
m_pressure_equalizer = make_unique<PressureEqualizer>(&print.config);
|
||||
if (print.config().spiral_vase.value)
|
||||
m_spiral_vase = make_unique<SpiralVase>(print.config());
|
||||
if (print.config().max_volumetric_extrusion_rate_slope_positive.value > 0 ||
|
||||
print.config().max_volumetric_extrusion_rate_slope_negative.value > 0)
|
||||
m_pressure_equalizer = make_unique<PressureEqualizer>(&print.config());
|
||||
m_enable_extrusion_role_markers = (bool)m_pressure_equalizer;
|
||||
|
||||
// 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)
|
||||
{
|
||||
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) {
|
||||
// Remove the trailing '\r' from the '\r\n' sequence.
|
||||
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();
|
||||
|
||||
// Write some terse information on the slicing parameters.
|
||||
const PrintObject *first_object = print.objects.front();
|
||||
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);
|
||||
for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) {
|
||||
auto region = print.regions[region_id];
|
||||
const PrintObject *first_object = print.objects().front();
|
||||
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);
|
||||
for (size_t region_id = 0; region_id < print.regions().size(); ++ 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, "; 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);
|
||||
|
@ -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);
|
||||
if (print.has_support_material())
|
||||
_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, "\n");
|
||||
}
|
||||
print.throw_if_canceled();
|
||||
|
||||
// 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();
|
||||
|
||||
// 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;
|
||||
size_t initial_print_object_id = 0;
|
||||
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.
|
||||
for (; initial_print_object_id < print.objects.size(); ++initial_print_object_id) {
|
||||
tool_ordering = ToolOrdering(*print.objects[initial_print_object_id], initial_extruder_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);
|
||||
if ((initial_extruder_id = tool_ordering.first_extruder()) != (unsigned int)-1)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// 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.
|
||||
tool_ordering = print.m_tool_ordering.empty() ?
|
||||
tool_ordering = print.wipe_tower_data().tool_ordering.empty() ?
|
||||
ToolOrdering(print, initial_extruder_id) :
|
||||
print.m_tool_ordering;
|
||||
print.wipe_tower_data().tool_ordering;
|
||||
initial_extruder_id = tool_ordering.first_extruder();
|
||||
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);
|
||||
|
||||
// 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));
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
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.
|
||||
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
|
||||
_writeln(file, start_gcode);
|
||||
// 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) {
|
||||
// Wipe tower will control the extruder switching, it will call the start_filament_gcode.
|
||||
} else {
|
||||
// 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 {
|
||||
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())));
|
||||
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())));
|
||||
}
|
||||
this->_print_first_layer_extruder_temperatures(file, print, start_gcode, initial_extruder_id, true);
|
||||
print.throw_if_canceled();
|
||||
|
@ -634,12 +634,12 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
|||
_write(file, this->preamble());
|
||||
|
||||
// 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.
|
||||
// Discard objects only containing thin walls (offset would fail on an empty polygon).
|
||||
Polygons islands;
|
||||
for (const PrintObject *object : print.objects)
|
||||
for (const Layer *layer : object->layers)
|
||||
for (const PrintObject *object : print.objects())
|
||||
for (const Layer *layer : object->layers())
|
||||
for (const ExPolygon &expoly : layer->slices.expolygons)
|
||||
for (const Point © : object->_shifted_copies) {
|
||||
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
|
||||
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;
|
||||
for (const ExtrusionEntity *ee : print.skirt.entities)
|
||||
for (const ExtrusionEntity *ee : print.skirt().entities)
|
||||
for (const ExtrusionPath &path : dynamic_cast<const ExtrusionLoop*>(ee)->paths)
|
||||
append(skirt_points, path.polyline.points);
|
||||
if (! skirt_points.empty()) {
|
||||
Polygon outer_skirt = Slic3r::Geometry::convex_hull(skirt_points);
|
||||
Polygons skirts;
|
||||
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);
|
||||
s.translate(-scale_(extruder_offset.x), -scale_(extruder_offset.y));
|
||||
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));
|
||||
|
||||
// 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
|
||||
// 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; });
|
||||
size_t finished_objects = 0;
|
||||
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
|
||||
// is triggered, so machine has more time to reach such temperatures.
|
||||
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.
|
||||
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);
|
||||
|
@ -751,7 +751,7 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
|||
// Order objects using a nearest neighbor search.
|
||||
std::vector<size_t> object_indices;
|
||||
Points object_reference_points;
|
||||
for (PrintObject *object : print.objects)
|
||||
for (PrintObject *object : print.objects())
|
||||
object_reference_points.push_back(object->_shifted_copies.front());
|
||||
Slic3r::Geometry::chained_path(object_reference_points, object_indices);
|
||||
// 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);
|
||||
// Prusa Multi-Material wipe tower.
|
||||
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_wipe_tower->prime(*this));
|
||||
// Verify, whether the print overaps the priming extrusions.
|
||||
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;
|
||||
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_wipe_tower_extrusions_extents(print, twolayers_printz));
|
||||
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.
|
||||
if (print.config.single_extruder_multi_material) {
|
||||
if (print.config().single_extruder_multi_material) {
|
||||
// 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 {
|
||||
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())));
|
||||
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_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.postamble());
|
||||
print.throw_if_canceled();
|
||||
|
@ -829,31 +829,27 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data)
|
|||
m_time_estimator.calculate_time();
|
||||
|
||||
// Get filament stats.
|
||||
print.filament_stats.clear();
|
||||
print.total_used_filament = 0.;
|
||||
print.total_extruded_volume = 0.;
|
||||
print.total_weight = 0.;
|
||||
print.total_cost = 0.;
|
||||
print.estimated_print_time = m_time_estimator.get_time_hms();
|
||||
print.m_print_statistics.clear();
|
||||
print.m_print_statistics.estimated_print_time = m_time_estimator.get_time_hms();
|
||||
for (const Extruder &extruder : m_writer.extruders()) {
|
||||
double used_filament = extruder.used_filament();
|
||||
double extruded_volume = extruder.extruded_volume();
|
||||
double filament_weight = extruded_volume * extruder.filament_density() * 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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
print.total_used_filament = print.total_used_filament + used_filament;
|
||||
print.total_extruded_volume = print.total_extruded_volume + extruded_volume;
|
||||
print.m_print_statistics.total_used_filament = print.m_print_statistics.total_used_filament + used_filament;
|
||||
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());
|
||||
|
||||
// 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);
|
||||
} catch (std::runtime_error &err) {
|
||||
// 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.
|
||||
return
|
||||
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)
|
||||
{
|
||||
// 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?
|
||||
int temp_by_gcode = -1;
|
||||
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;
|
||||
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.
|
||||
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)
|
||||
temp = temp_by_gcode;
|
||||
m_writer.set_temperature(temp_by_gcode, wait, first_printing_extruder_id);
|
||||
} else {
|
||||
// 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.
|
||||
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)
|
||||
_write(file, m_writer.set_temperature(temp, wait, first_printing_extruder_id));
|
||||
} else {
|
||||
// Set temperatures of all the printing extruders.
|
||||
for (unsigned int tool_id : print.extruders()) {
|
||||
int temp = print.config.first_layer_temperature.get_at(tool_id);
|
||||
if (print.config.ooze_prevention.value)
|
||||
temp += print.config.standby_temperature_delta.value;
|
||||
int temp = print.config().first_layer_temperature.get_at(tool_id);
|
||||
if (print.config().ooze_prevention.value)
|
||||
temp += print.config().standby_temperature_delta.value;
|
||||
if (temp > 0)
|
||||
_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();
|
||||
|
||||
// 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.
|
||||
// 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) {
|
||||
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) {
|
||||
for (const LayerRegion *layer_region : layer.regions)
|
||||
if (layer_region->region()->config.bottom_solid_layers.value > layer.id() ||
|
||||
for (const LayerRegion *layer_region : layer.regions())
|
||||
if (layer_region->region()->config().bottom_solid_layers.value > layer.id() ||
|
||||
layer_region->perimeters.items_count() > 1 ||
|
||||
layer_region->fills.items_count() > 0) {
|
||||
enable = false;
|
||||
|
@ -1084,22 +1080,22 @@ void GCode::process_layer(
|
|||
std::string gcode;
|
||||
|
||||
// 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;
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index + 1));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
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";
|
||||
}
|
||||
gcode += this->change_layer(print_z); // this will increase m_layer_index
|
||||
m_layer = &layer;
|
||||
if (! print.config.layer_gcode.value.empty()) {
|
||||
if (! print.config().layer_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
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";
|
||||
}
|
||||
|
||||
|
@ -1107,14 +1103,14 @@ void GCode::process_layer(
|
|||
// Transition from 1st to 2nd layer. Adjust nozzle temperatures as prescribed by the nozzle dependent
|
||||
// first_layer_temperature vs. temperature settings.
|
||||
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.
|
||||
continue;
|
||||
int temperature = print.config.temperature.get_at(extruder.id());
|
||||
if (temperature > 0 && temperature != print.config.first_layer_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()))
|
||||
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.
|
||||
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
|
||||
// not at the print_z of the interlaced support material layers.
|
||||
bool extrude_skirt =
|
||||
! print.skirt.entities.empty() &&
|
||||
! print.skirt().entities.empty() &&
|
||||
// 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
|
||||
(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.
|
||||
|
@ -1146,7 +1142,7 @@ void GCode::process_layer(
|
|||
extruder_ids.front() = first_extruder_id;
|
||||
break;
|
||||
}
|
||||
size_t n_loops = print.skirt.entities.size();
|
||||
size_t n_loops = print.skirt().entities.size();
|
||||
if (n_loops <= extruder_ids.size()) {
|
||||
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);
|
||||
|
@ -1165,7 +1161,7 @@ void GCode::process_layer(
|
|||
}
|
||||
} else
|
||||
// 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.
|
||||
|
@ -1180,22 +1176,22 @@ void GCode::process_layer(
|
|||
bool has_support = role == erMixed || role == erSupportMaterial;
|
||||
bool has_interface = role == erMixed || role == erSupportMaterialInterface;
|
||||
// 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?
|
||||
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".
|
||||
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?
|
||||
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) {
|
||||
// Some support will be printed with "don't care" material, preferably non-soluble.
|
||||
// Is the current extruder assigned a soluble filament?
|
||||
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.
|
||||
// Try to find a non-soluble extruder on the same layer.
|
||||
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;
|
||||
break;
|
||||
}
|
||||
|
@ -1242,11 +1238,11 @@ void GCode::process_layer(
|
|||
layer.slices.expolygons[i].contour.contains(point);
|
||||
};
|
||||
|
||||
for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) {
|
||||
const LayerRegion *layerm = layer.regions[region_id];
|
||||
for (size_t region_id = 0; region_id < print.regions().size(); ++ region_id) {
|
||||
const LayerRegion *layerm = layer.regions()[region_id];
|
||||
if (layerm == nullptr)
|
||||
continue;
|
||||
const PrintRegion ®ion = *print.regions[region_id];
|
||||
const PrintRegion ®ion = *print.regions()[region_id];
|
||||
|
||||
// process perimeters
|
||||
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.
|
||||
std::vector<ObjectByExtruder::Island> &islands = object_islands_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(),
|
||||
layers.size(), n_slices+1);
|
||||
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
|
||||
point_inside_surface(i, perimeter_coll->first_point())) {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -1285,7 +1281,7 @@ void GCode::process_layer(
|
|||
// This shouldn't happen but first_point() would fail.
|
||||
continue;
|
||||
// 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.
|
||||
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
|
||||
by_extruder,
|
||||
|
@ -1298,7 +1294,7 @@ void GCode::process_layer(
|
|||
// fill->first_point fits inside ith slice
|
||||
point_inside_surface(i, fill->first_point())) {
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
@ -1324,7 +1320,7 @@ void GCode::process_layer(
|
|||
Flow skirt_flow = print.skirt_flow();
|
||||
for (size_t i = loops.first; i < loops.second; ++ i) {
|
||||
// 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);
|
||||
layer_skirt_flow.height = (float)skirt_height;
|
||||
double mm3_per_mm = layer_skirt_flow.mm3_per_mm();
|
||||
|
@ -1345,7 +1341,7 @@ void GCode::process_layer(
|
|||
if (! m_brim_done) {
|
||||
this->set_origin(0., 0.);
|
||||
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);
|
||||
m_brim_done = true;
|
||||
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.
|
||||
continue;
|
||||
|
||||
m_config.apply(print_object->config, true);
|
||||
m_config.apply(print_object->config(), true);
|
||||
m_layer = layers[layer_id].layer();
|
||||
if (m_config.avoid_crossing_perimeters)
|
||||
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();
|
||||
}
|
||||
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_perimeters(print, island.by_region, lower_layer_edge_grids[layer_id]);
|
||||
} 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)
|
||||
{
|
||||
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) {
|
||||
const StaticPrintConfig *cfg = configs[i];
|
||||
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;
|
||||
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)
|
||||
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;
|
||||
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);
|
||||
for (ExtrusionEntity *fill : chained.entities) {
|
||||
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 bbox(extrusionentity_extents(print.brim));
|
||||
bbox.merge(extrusionentity_extents(print.skirt));
|
||||
BoundingBoxf bbox(extrusionentity_extents(print.brim()));
|
||||
bbox.merge(extrusionentity_extents(print.skirt()));
|
||||
return bbox;
|
||||
}
|
||||
|
||||
BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coordf_t max_print_z)
|
||||
{
|
||||
BoundingBoxf bbox;
|
||||
for (const Layer *layer : print_object.layers) {
|
||||
for (const Layer *layer : print_object.layers()) {
|
||||
if (layer->print_z > max_print_z)
|
||||
break;
|
||||
BoundingBoxf bbox_this;
|
||||
for (const LayerRegion *layerm : layer->regions) {
|
||||
for (const LayerRegion *layerm : layer->regions()) {
|
||||
bbox_this.merge(extrusionentity_extents(layerm->perimeters));
|
||||
for (const ExtrusionEntity *ee : layerm->fills.entities)
|
||||
// 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 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)
|
||||
break;
|
||||
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 bbox;
|
||||
if (print.m_wipe_tower_priming) {
|
||||
const WipeTower::ToolChangeResult &tcr = *print.m_wipe_tower_priming.get();
|
||||
if (print.wipe_tower_data().priming != nullptr) {
|
||||
const WipeTower::ToolChangeResult &tcr = *print.wipe_tower_data().priming;
|
||||
for (size_t i = 1; i < tcr.extrusions.size(); ++ i) {
|
||||
const WipeTower::Extrusion &e = tcr.extrusions[i];
|
||||
if (e.width > 0) {
|
||||
|
|
|
@ -16,19 +16,19 @@
|
|||
namespace Slic3r {
|
||||
|
||||
// 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)
|
||||
{
|
||||
if (object.layers.empty())
|
||||
if (object.layers().empty())
|
||||
return;
|
||||
|
||||
// Initialize the print layers for just a single object.
|
||||
{
|
||||
std::vector<coordf_t> zs;
|
||||
zs.reserve(zs.size() + object.layers.size() + object.support_layers.size());
|
||||
for (auto layer : object.layers)
|
||||
zs.reserve(zs.size() + object.layers().size() + object.support_layers().size());
|
||||
for (auto layer : object.layers())
|
||||
zs.emplace_back(layer->print_z);
|
||||
for (auto layer : object.support_layers)
|
||||
for (auto layer : object.support_layers())
|
||||
zs.emplace_back(layer->print_z);
|
||||
this->initialize_layers(zs);
|
||||
}
|
||||
|
@ -39,39 +39,39 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
|
|||
// Reorder the extruders to minimize tool switches.
|
||||
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);
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// Initialize the print layers for all objects and all layers.
|
||||
coordf_t object_bottom_z = 0.;
|
||||
{
|
||||
std::vector<coordf_t> zs;
|
||||
for (auto object : print.objects) {
|
||||
zs.reserve(zs.size() + object->layers.size() + object->support_layers.size());
|
||||
for (auto layer : object->layers)
|
||||
for (auto object : print.objects()) {
|
||||
zs.reserve(zs.size() + object->layers().size() + object->support_layers().size());
|
||||
for (auto layer : object->layers())
|
||||
zs.emplace_back(layer->print_z);
|
||||
for (auto layer : object->support_layers)
|
||||
for (auto layer : object->support_layers())
|
||||
zs.emplace_back(layer->print_z);
|
||||
if (! object->layers.empty())
|
||||
object_bottom_z = object->layers.front()->print_z - object->layers.front()->height;
|
||||
if (! object->layers().empty())
|
||||
object_bottom_z = object->layers().front()->print_z - object->layers().front()->height;
|
||||
}
|
||||
this->initialize_layers(zs);
|
||||
}
|
||||
|
||||
// Collect extruders reuqired to print the layers.
|
||||
for (auto object : print.objects)
|
||||
for (auto object : print.objects())
|
||||
this->collect_extruders(*object);
|
||||
|
||||
// Reorder the extruders to minimize tool switches.
|
||||
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);
|
||||
}
|
||||
|
@ -111,13 +111,13 @@ void ToolOrdering::initialize_layers(std::vector<coordf_t> &zs)
|
|||
void ToolOrdering::collect_extruders(const PrintObject &object)
|
||||
{
|
||||
// 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);
|
||||
ExtrusionRole role = support_layer->support_fills.role();
|
||||
bool has_support = role == erMixed || role == erSupportMaterial;
|
||||
bool has_interface = role == erMixed || role == erSupportMaterialInterface;
|
||||
unsigned int extruder_support = object.config.support_material_extruder.value;
|
||||
unsigned int extruder_interface = object.config.support_material_interface_extruder.value;
|
||||
unsigned int extruder_support = object.config().support_material_extruder.value;
|
||||
unsigned int extruder_interface = object.config().support_material_interface_extruder.value;
|
||||
if (has_support)
|
||||
layer_tools.extruders.push_back(extruder_support);
|
||||
if (has_interface)
|
||||
|
@ -126,16 +126,16 @@ void ToolOrdering::collect_extruders(const PrintObject &object)
|
|||
layer_tools.has_support = true;
|
||||
}
|
||||
// Collect the object extruders.
|
||||
for (auto layer : object.layers) {
|
||||
for (auto layer : object.layers()) {
|
||||
LayerTools &layer_tools = this->tools_for_layer(layer->print_z);
|
||||
// What extruders are required to print this object layer?
|
||||
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;
|
||||
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;
|
||||
if (layerm == nullptr)
|
||||
continue;
|
||||
const PrintRegion ®ion = *object.print()->regions[region_id];
|
||||
const PrintRegion ®ion = *object.print()->regions()[region_id];
|
||||
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;
|
||||
}
|
||||
bool has_infill = false;
|
||||
|
@ -150,9 +150,9 @@ void ToolOrdering::collect_extruders(const PrintObject &object)
|
|||
has_infill = true;
|
||||
}
|
||||
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)
|
||||
layer_tools.extruders.push_back(region.config.infill_extruder);
|
||||
layer_tools.extruders.push_back(region.config().infill_extruder);
|
||||
if (has_solid_infill || has_infill)
|
||||
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->m_num_layer_changes = 0;
|
||||
this->m_current_tool = tools.front();
|
||||
m_num_layer_changes = 0;
|
||||
m_current_tool = tools.front();
|
||||
|
||||
// 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,
|
||||
|
@ -439,9 +439,9 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
|
|||
if (last_wipe_inside_wipe_tower) {
|
||||
// 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.
|
||||
this->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.ru.y -= this->m_initial_extra_wipe;
|
||||
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 -= m_initial_extra_wipe;
|
||||
cleaning_box.ru.y -= m_initial_extra_wipe;
|
||||
}
|
||||
toolchange_Wipe(writer, cleaning_box, false);
|
||||
} else {
|
||||
|
@ -471,8 +471,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(
|
|||
m_idx_tool_change_in_layer = (unsigned int)(-1);
|
||||
|
||||
ToolChangeResult result;
|
||||
result.print_z = this->m_z_pos;
|
||||
result.layer_height = this->m_layer_height;
|
||||
result.print_z = m_z_pos;
|
||||
result.layer_height = m_layer_height;
|
||||
result.gcode = writer.gcode();
|
||||
result.elapsed_time = writer.elapsed_time();
|
||||
result.extrusions = writer.extrusions();
|
||||
|
@ -612,8 +612,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
|
|||
}
|
||||
|
||||
ToolChangeResult result;
|
||||
result.print_z = this->m_z_pos;
|
||||
result.layer_height = this->m_layer_height;
|
||||
result.print_z = m_z_pos;
|
||||
result.layer_height = m_layer_height;
|
||||
result.gcode = writer.gcode();
|
||||
result.elapsed_time = writer.elapsed_time();
|
||||
result.extrusions = writer.extrusions();
|
||||
|
@ -718,8 +718,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b
|
|||
}
|
||||
|
||||
ToolChangeResult result;
|
||||
result.print_z = this->m_z_pos;
|
||||
result.layer_height = this->m_layer_height;
|
||||
result.print_z = m_z_pos;
|
||||
result.layer_height = m_layer_height;
|
||||
result.gcode = writer.gcode();
|
||||
result.elapsed_time = writer.elapsed_time();
|
||||
result.extrusions = writer.extrusions();
|
||||
|
@ -1040,8 +1040,8 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::finish_layer(Purpose purpose)
|
|||
}
|
||||
|
||||
ToolChangeResult result;
|
||||
result.print_z = this->m_z_pos;
|
||||
result.layer_height = this->m_layer_height;
|
||||
result.print_z = m_z_pos;
|
||||
result.layer_height = m_layer_height;
|
||||
result.gcode = writer.gcode();
|
||||
result.elapsed_time = writer.elapsed_time();
|
||||
result.extrusions = writer.extrusions();
|
||||
|
|
|
@ -12,24 +12,24 @@ namespace Slic3r {
|
|||
Layer::~Layer()
|
||||
{
|
||||
this->lower_layer = this->upper_layer = nullptr;
|
||||
for (LayerRegion *region : this->regions)
|
||||
for (LayerRegion *region : m_regions)
|
||||
delete region;
|
||||
this->regions.clear();
|
||||
m_regions.clear();
|
||||
}
|
||||
|
||||
LayerRegion* Layer::add_region(PrintRegion* print_region)
|
||||
{
|
||||
this->regions.emplace_back(new LayerRegion(this, print_region));
|
||||
return this->regions.back();
|
||||
m_regions.emplace_back(new LayerRegion(this, print_region));
|
||||
return m_regions.back();
|
||||
}
|
||||
|
||||
// merge all regions' slices to get islands
|
||||
void Layer::make_slices()
|
||||
{
|
||||
ExPolygons slices;
|
||||
if (this->regions.size() == 1) {
|
||||
if (m_regions.size() == 1) {
|
||||
// optimization: if we only have one region, take its slices
|
||||
slices = this->regions.front()->slices;
|
||||
slices = m_regions.front()->slices;
|
||||
} else {
|
||||
Polygons slices_p;
|
||||
FOREACH_LAYERREGION(this, layerm) {
|
||||
|
@ -58,10 +58,10 @@ void Layer::make_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,
|
||||
// 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 {
|
||||
FOREACH_LAYERREGION(this, layerm) {
|
||||
// without safety offset, artifacts are generated (GH #2494)
|
||||
|
@ -81,18 +81,18 @@ void Layer::make_perimeters()
|
|||
std::set<size_t> done;
|
||||
|
||||
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;
|
||||
BOOST_LOG_TRIVIAL(trace) << "Generating perimeters for layer " << this->id() << ", region " << region_id;
|
||||
done.insert(region_id);
|
||||
const PrintRegionConfig &config = (*layerm)->region()->config;
|
||||
const PrintRegionConfig &config = (*layerm)->region()->config();
|
||||
|
||||
// find compatible regions
|
||||
LayerRegionPtrs layerms;
|
||||
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;
|
||||
const PrintRegionConfig &other_config = other_layerm->region()->config;
|
||||
const PrintRegionConfig &other_config = other_layerm->region()->config();
|
||||
|
||||
if (config.perimeter_extruder == other_config.perimeter_extruder
|
||||
&& config.perimeters == other_config.perimeters
|
||||
|
@ -104,7 +104,7 @@ void Layer::make_perimeters()
|
|||
&& config.thin_walls == other_config.thin_walls
|
||||
&& config.external_perimeters_first == other_config.external_perimeters_first) {
|
||||
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
|
||||
printf("Making fills for layer " PRINTF_ZU "\n", this->id());
|
||||
#endif
|
||||
for (LayerRegion *layerm : regions) {
|
||||
for (LayerRegion *layerm : m_regions) {
|
||||
layerm->fills.clear();
|
||||
make_fill(*layerm, layerm->fills);
|
||||
#ifndef NDEBUG
|
||||
|
@ -163,18 +163,18 @@ void Layer::make_fills()
|
|||
void Layer::export_region_slices_to_svg(const char *path) const
|
||||
{
|
||||
BoundingBox bbox;
|
||||
for (LayerRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region)
|
||||
for (Surfaces::const_iterator surface = (*region)->slices.surfaces.begin(); surface != (*region)->slices.surfaces.end(); ++surface)
|
||||
bbox.merge(get_extents(surface->expolygon));
|
||||
for (const auto *region : m_regions)
|
||||
for (const auto &surface : region->slices.surfaces)
|
||||
bbox.merge(get_extents(surface.expolygon));
|
||||
Point legend_size = export_surface_type_legend_to_svg_box_size();
|
||||
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));
|
||||
|
||||
SVG svg(path, bbox);
|
||||
const float transparency = 0.5f;
|
||||
for (LayerRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region)
|
||||
for (Surfaces::const_iterator surface = (*region)->slices.surfaces.begin(); surface != (*region)->slices.surfaces.end(); ++surface)
|
||||
svg.draw(surface->expolygon, surface_type_to_color_name(surface->surface_type), transparency);
|
||||
for (const auto *region : m_regions)
|
||||
for (const auto &surface : region->slices.surfaces)
|
||||
svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency);
|
||||
export_surface_type_legend_to_svg(svg, legend_pos);
|
||||
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
|
||||
{
|
||||
BoundingBox bbox;
|
||||
for (LayerRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region)
|
||||
for (Surfaces::const_iterator surface = (*region)->fill_surfaces.surfaces.begin(); surface != (*region)->fill_surfaces.surfaces.end(); ++surface)
|
||||
bbox.merge(get_extents(surface->expolygon));
|
||||
for (const auto *region : m_regions)
|
||||
for (const auto &surface : region->slices.surfaces)
|
||||
bbox.merge(get_extents(surface.expolygon));
|
||||
Point legend_size = export_surface_type_legend_to_svg_box_size();
|
||||
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));
|
||||
|
||||
SVG svg(path, bbox);
|
||||
const float transparency = 0.5f;
|
||||
for (LayerRegionPtrs::const_iterator region = this->regions.begin(); region != this->regions.end(); ++region)
|
||||
for (Surfaces::const_iterator surface = (*region)->fill_surfaces.surfaces.begin(); surface != (*region)->fill_surfaces.surfaces.end(); ++surface)
|
||||
svg.draw(surface->expolygon, surface_type_to_color_name(surface->surface_type), transparency);
|
||||
for (const auto *region : m_regions)
|
||||
for (const auto &surface : region->slices.surfaces)
|
||||
svg.draw(surface.expolygon, surface_type_to_color_name(surface.surface_type), transparency);
|
||||
export_surface_type_legend_to_svg(svg, legend_pos);
|
||||
svg.Close();
|
||||
}
|
||||
|
|
|
@ -15,16 +15,13 @@ class Layer;
|
|||
class PrintRegion;
|
||||
class PrintObject;
|
||||
|
||||
// TODO: make stuff private
|
||||
class LayerRegion
|
||||
{
|
||||
friend class Layer;
|
||||
|
||||
public:
|
||||
Layer* layer() { return this->_layer; }
|
||||
const Layer* layer() const { return this->_layer; }
|
||||
PrintRegion* region() { return this->_region; }
|
||||
const PrintRegion* region() const { return this->_region; }
|
||||
Layer* layer() { return m_layer; }
|
||||
const Layer* layer() const { return m_layer; }
|
||||
PrintRegion* region() { return m_region; }
|
||||
const PrintRegion* region() const { return m_region; }
|
||||
|
||||
// collection of surfaces generated by slicing the original geometry
|
||||
// divided by type top/bottom/internal
|
||||
|
@ -77,29 +74,30 @@ public:
|
|||
// Is there any valid extrusion assigned to this LayerRegion?
|
||||
bool has_extrusions() const { return ! this->perimeters.entities.empty() || ! this->fills.entities.empty(); }
|
||||
|
||||
private:
|
||||
Layer *_layer;
|
||||
PrintRegion *_region;
|
||||
protected:
|
||||
friend class Layer;
|
||||
|
||||
LayerRegion(Layer *layer, PrintRegion *region) : _layer(layer), _region(region) {}
|
||||
LayerRegion(Layer *layer, PrintRegion *region) : m_layer(layer), m_region(region) {}
|
||||
~LayerRegion() {}
|
||||
|
||||
private:
|
||||
Layer *m_layer;
|
||||
PrintRegion *m_region;
|
||||
};
|
||||
|
||||
|
||||
typedef std::vector<LayerRegion*> LayerRegionPtrs;
|
||||
|
||||
class Layer {
|
||||
friend class PrintObject;
|
||||
|
||||
class Layer
|
||||
{
|
||||
public:
|
||||
size_t id() const { return this->_id; }
|
||||
void set_id(size_t id) { this->_id = id; }
|
||||
PrintObject* object() { return this->_object; }
|
||||
const PrintObject* object() const { return this->_object; }
|
||||
size_t id() const { return m_id; }
|
||||
void set_id(size_t id) { m_id = id; }
|
||||
PrintObject* object() { return m_object; }
|
||||
const PrintObject* object() const { return m_object; }
|
||||
|
||||
Layer *upper_layer;
|
||||
Layer *lower_layer;
|
||||
LayerRegionPtrs regions;
|
||||
bool slicing_errors;
|
||||
coordf_t slice_z; // Z used for slicing 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.
|
||||
ExPolygonCollection slices;
|
||||
|
||||
size_t region_count() const { return this->regions.size(); }
|
||||
const LayerRegion* get_region(int idx) const { return this->regions.at(idx); }
|
||||
LayerRegion* get_region(int idx) { return this->regions.at(idx); }
|
||||
size_t region_count() const { return m_regions.size(); }
|
||||
const LayerRegion* get_region(int idx) const { return m_regions.at(idx); }
|
||||
LayerRegion* get_region(int idx) { return m_regions[idx]; }
|
||||
LayerRegion* add_region(PrintRegion* print_region);
|
||||
const LayerRegionPtrs& regions() const { return m_regions; }
|
||||
|
||||
void make_slices();
|
||||
void merge_slices();
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
void make_perimeters();
|
||||
|
@ -136,22 +135,26 @@ public:
|
|||
void export_region_fill_surfaces_to_svg_debug(const char *name) const;
|
||||
|
||||
// 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:
|
||||
size_t _id; // sequential number of layer, 0-based
|
||||
PrintObject *_object;
|
||||
friend class PrintObject;
|
||||
|
||||
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),
|
||||
slice_z(slice_z), print_z(print_z), height(height),
|
||||
_id(id), _object(object) {}
|
||||
m_id(id), m_object(object) {}
|
||||
virtual ~Layer();
|
||||
|
||||
private:
|
||||
// sequential number of layer, 0-based
|
||||
size_t m_id;
|
||||
PrintObject *m_object;
|
||||
LayerRegionPtrs m_regions;
|
||||
};
|
||||
|
||||
class SupportLayer : public Layer {
|
||||
friend class PrintObject;
|
||||
|
||||
class SupportLayer : public Layer
|
||||
{
|
||||
public:
|
||||
// Polygons covered by the supports: base, interface and contact areas.
|
||||
ExPolygonCollection support_islands;
|
||||
|
@ -161,7 +164,9 @@ public:
|
|||
// Is there any valid extrusion assigned to this LayerRegion?
|
||||
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
|
||||
// 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) :
|
||||
|
|
|
@ -18,13 +18,13 @@ namespace Slic3r {
|
|||
Flow
|
||||
LayerRegion::flow(FlowRole role, bool bridge, double width) const
|
||||
{
|
||||
return this->_region->flow(
|
||||
return m_region->flow(
|
||||
role,
|
||||
this->_layer->height,
|
||||
m_layer->height,
|
||||
bridge,
|
||||
this->_layer->id() == 0,
|
||||
m_layer->id() == 0,
|
||||
width,
|
||||
*this->_layer->object()
|
||||
*m_layer->object()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -61,9 +61,9 @@ void LayerRegion::make_perimeters(const SurfaceCollection &slices, SurfaceCollec
|
|||
&slices,
|
||||
this->layer()->height,
|
||||
this->flow(frPerimeter),
|
||||
&this->region()->config,
|
||||
&this->layer()->object()->config,
|
||||
&this->layer()->object()->print()->config,
|
||||
&this->region()->config(),
|
||||
&this->layer()->object()->config(),
|
||||
&this->layer()->object()->print()->config(),
|
||||
|
||||
// output:
|
||||
&this->perimeters,
|
||||
|
@ -116,7 +116,7 @@ void LayerRegion::process_external_surfaces(const Layer* lower_layer)
|
|||
{
|
||||
// bottom_polygons are used to trim inflated top 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) {
|
||||
if (surface.surface_type == stTop) {
|
||||
// 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
|
||||
printf("Processing bridge at layer " PRINTF_ZU ":\n", this->layer()->id());
|
||||
#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;
|
||||
if (this->layer()->object()->config.support_material) {
|
||||
if (this->layer()->object()->config().support_material) {
|
||||
polygons_append(this->bridged, bd.coverage());
|
||||
this->unsupported_bridge_edges.append(bd.unsupported_edges());
|
||||
}
|
||||
|
@ -351,13 +351,13 @@ void LayerRegion::prepare_fill_surfaces()
|
|||
the only meaningful information returned by psPerimeters. */
|
||||
|
||||
// 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)
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge)
|
||||
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
|
||||
if (this->region()->config.fill_density.value > 0) {
|
||||
if (this->region()->config().fill_density.value > 0) {
|
||||
// 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) {
|
||||
if (surface->surface_type == stInternal && surface->area() <= min_area)
|
||||
surface->surface_type = stInternalSolid;
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
void
|
||||
PerimeterGenerator::process()
|
||||
void PerimeterGenerator::process()
|
||||
{
|
||||
// other perimeters
|
||||
this->_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
|
||||
|
|
|
@ -38,30 +38,30 @@ typedef std::vector<PerimeterGeneratorLoop> PerimeterGeneratorLoops;
|
|||
class PerimeterGenerator {
|
||||
public:
|
||||
// Inputs:
|
||||
const SurfaceCollection* slices;
|
||||
const ExPolygonCollection* lower_slices;
|
||||
const SurfaceCollection *slices;
|
||||
const ExPolygonCollection *lower_slices;
|
||||
double layer_height;
|
||||
int layer_id;
|
||||
Flow perimeter_flow;
|
||||
Flow ext_perimeter_flow;
|
||||
Flow overhang_flow;
|
||||
Flow solid_infill_flow;
|
||||
PrintRegionConfig* config;
|
||||
PrintObjectConfig* object_config;
|
||||
PrintConfig* print_config;
|
||||
const PrintRegionConfig *config;
|
||||
const PrintObjectConfig *object_config;
|
||||
const PrintConfig *print_config;
|
||||
// Outputs:
|
||||
ExtrusionEntityCollection* loops;
|
||||
ExtrusionEntityCollection* gap_fill;
|
||||
SurfaceCollection* fill_surfaces;
|
||||
ExtrusionEntityCollection *loops;
|
||||
ExtrusionEntityCollection *gap_fill;
|
||||
SurfaceCollection *fill_surfaces;
|
||||
|
||||
PerimeterGenerator(
|
||||
// Input:
|
||||
const SurfaceCollection* slices,
|
||||
double layer_height,
|
||||
Flow flow,
|
||||
PrintRegionConfig* config,
|
||||
PrintObjectConfig* object_config,
|
||||
PrintConfig* print_config,
|
||||
const PrintRegionConfig* config,
|
||||
const PrintObjectConfig* object_config,
|
||||
const PrintConfig* print_config,
|
||||
// Output:
|
||||
// Loops with the external thin walls
|
||||
ExtrusionEntityCollection* loops,
|
||||
|
@ -84,10 +84,8 @@ private:
|
|||
double _mm3_per_mm_overhang;
|
||||
Polygons _lower_slices_p;
|
||||
|
||||
ExtrusionEntityCollection _traverse_loops(const PerimeterGeneratorLoops &loops,
|
||||
ThickPolylines &thin_walls) const;
|
||||
ExtrusionEntityCollection _variable_width
|
||||
(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const;
|
||||
ExtrusionEntityCollection _traverse_loops(const PerimeterGeneratorLoops &loops, ThickPolylines &thin_walls) const;
|
||||
ExtrusionEntityCollection _variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ PlaceholderParser::PlaceholderParser()
|
|||
this->update_timestamp();
|
||||
}
|
||||
|
||||
void PlaceholderParser::update_timestamp()
|
||||
void PlaceholderParser::update_timestamp(DynamicConfig &config)
|
||||
{
|
||||
time_t 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_min;
|
||||
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);
|
||||
this->set("month", 1 + timeinfo->tm_mon);
|
||||
this->set("day", timeinfo->tm_mday);
|
||||
this->set("hour", timeinfo->tm_hour);
|
||||
this->set("minute", timeinfo->tm_min);
|
||||
this->set("second", timeinfo->tm_sec);
|
||||
config.set_key_value("year", new ConfigOptionInt(1900 + timeinfo->tm_year));
|
||||
config.set_key_value("month", new ConfigOptionInt(1 + timeinfo->tm_mon));
|
||||
config.set_key_value("day", new ConfigOptionInt(timeinfo->tm_mday));
|
||||
config.set_key_value("hour", new ConfigOptionInt(timeinfo->tm_hour));
|
||||
config.set_key_value("minute", new ConfigOptionInt(timeinfo->tm_min));
|
||||
config.set_key_value("second", new ConfigOptionInt(timeinfo->tm_sec));
|
||||
}
|
||||
|
||||
// Scalar configuration values are stored into m_single,
|
||||
|
|
|
@ -14,7 +14,6 @@ class PlaceholderParser
|
|||
public:
|
||||
PlaceholderParser();
|
||||
|
||||
void update_timestamp();
|
||||
void apply_config(const DynamicPrintConfig &config);
|
||||
void apply_env_variables();
|
||||
|
||||
|
@ -37,6 +36,11 @@ public:
|
|||
// 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);
|
||||
|
||||
// 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:
|
||||
DynamicConfig m_config;
|
||||
};
|
||||
|
|
|
@ -20,24 +20,27 @@ template class PrintState<PrintObjectStep, posCount>;
|
|||
|
||||
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);
|
||||
for (PrintRegion *region : this->regions)
|
||||
for (PrintRegion *region : m_regions)
|
||||
delete region;
|
||||
this->regions.clear();
|
||||
m_regions.clear();
|
||||
}
|
||||
|
||||
void Print::delete_object(size_t idx)
|
||||
{
|
||||
tbb::mutex::scoped_lock lock(m_mutex);
|
||||
// destroy object and remove it from our container
|
||||
delete this->objects[idx];
|
||||
this->objects.erase(this->objects.begin() + idx);
|
||||
delete m_objects[idx];
|
||||
m_objects.erase(m_objects.begin() + idx);
|
||||
this->invalidate_all_steps();
|
||||
// TODO: purge unused regions
|
||||
}
|
||||
|
||||
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
|
||||
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()
|
||||
|
@ -46,8 +49,8 @@ void Print::reload_object(size_t /* idx */)
|
|||
|
||||
// collect all current model objects
|
||||
ModelObjectPtrs model_objects;
|
||||
model_objects.reserve(this->objects.size());
|
||||
for (PrintObject *object : this->objects)
|
||||
model_objects.reserve(m_objects.size());
|
||||
for (PrintObject *object : m_objects)
|
||||
model_objects.push_back(object->model_object());
|
||||
// remove our print objects
|
||||
this->clear_objects();
|
||||
|
@ -63,15 +66,21 @@ void Print::reload_object(size_t /* idx */)
|
|||
bool Print::reload_model_instances()
|
||||
{
|
||||
bool invalidated = false;
|
||||
for (PrintObject *object : this->objects)
|
||||
for (PrintObject *object : m_objects)
|
||||
invalidated |= object->reload_model_instances();
|
||||
return invalidated;
|
||||
}
|
||||
|
||||
PrintRegion* Print::add_region()
|
||||
{
|
||||
regions.push_back(new PrintRegion(this));
|
||||
return regions.back();
|
||||
m_regions.emplace_back(new PrintRegion(this));
|
||||
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().
|
||||
|
@ -224,18 +233,18 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
|||
invalidated |= this->invalidate_step(step);
|
||||
sort_remove_duplicates(osteps);
|
||||
for (PrintObjectStep ostep : osteps)
|
||||
for (PrintObject *object : this->objects)
|
||||
for (PrintObject *object : m_objects)
|
||||
invalidated |= object->invalidate_step(ostep);
|
||||
return invalidated;
|
||||
}
|
||||
|
||||
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.
|
||||
//FIXME Why should skirt invalidate brim? Shouldn't it be vice versa?
|
||||
if (step == psSkirt)
|
||||
invalidated |= m_state.invalidate(psBrim);
|
||||
invalidated |= m_state.invalidate(psBrim, m_mutex, m_cancel_callback);
|
||||
return invalidated;
|
||||
}
|
||||
|
||||
|
@ -243,9 +252,9 @@ bool Print::invalidate_step(PrintStep step)
|
|||
// and there's at least one object
|
||||
bool Print::is_step_done(PrintObjectStep step) const
|
||||
{
|
||||
if (this->objects.empty())
|
||||
if (m_objects.empty())
|
||||
return false;
|
||||
for (const PrintObject *object : this->objects)
|
||||
for (const PrintObject *object : m_objects)
|
||||
if (!object->m_state.is_done(step))
|
||||
return false;
|
||||
return true;
|
||||
|
@ -256,15 +265,15 @@ std::vector<unsigned int> Print::object_extruders() const
|
|||
{
|
||||
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
|
||||
// extruder selection fields
|
||||
if (region->config.perimeters.value > 0 || this->config.brim_width.value > 0)
|
||||
extruders.push_back(region->config.perimeter_extruder - 1);
|
||||
if (region->config.fill_density.value > 0)
|
||||
extruders.push_back(region->config.infill_extruder - 1);
|
||||
if (region->config.top_solid_layers.value > 0 || region->config.bottom_solid_layers.value > 0)
|
||||
extruders.push_back(region->config.solid_infill_extruder - 1);
|
||||
if (region->config().perimeters.value > 0 || m_config.brim_width.value > 0)
|
||||
extruders.push_back(region->config().perimeter_extruder - 1);
|
||||
if (region->config().fill_density.value > 0)
|
||||
extruders.push_back(region->config().infill_extruder - 1);
|
||||
if (region->config().top_solid_layers.value > 0 || region->config().bottom_solid_layers.value > 0)
|
||||
extruders.push_back(region->config().solid_infill_extruder - 1);
|
||||
}
|
||||
|
||||
sort_remove_duplicates(extruders);
|
||||
|
@ -277,16 +286,16 @@ std::vector<unsigned int> Print::support_material_extruders() const
|
|||
std::vector<unsigned int> extruders;
|
||||
bool support_uses_current_extruder = false;
|
||||
|
||||
for (PrintObject *object : this->objects) {
|
||||
for (PrintObject *object : m_objects) {
|
||||
if (object->has_support_material()) {
|
||||
if (object->config.support_material_extruder == 0)
|
||||
if (object->config().support_material_extruder == 0)
|
||||
support_uses_current_extruder = true;
|
||||
else
|
||||
extruders.push_back(object->config.support_material_extruder - 1);
|
||||
if (object->config.support_material_interface_extruder == 0)
|
||||
extruders.push_back(object->config().support_material_extruder - 1);
|
||||
if (object->config().support_material_interface_extruder == 0)
|
||||
support_uses_current_extruder = true;
|
||||
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)
|
||||
{
|
||||
for (PrintObject *object : this->objects) {
|
||||
for (Layer *layer : object->layers) {
|
||||
for (PrintObject *object : m_objects) {
|
||||
for (Layer *layer : object->m_layers) {
|
||||
layer->slices.simplify(distance);
|
||||
for (LayerRegion *layerm : layer->regions)
|
||||
for (LayerRegion *layerm : layer->regions())
|
||||
layerm->slices.simplify(distance);
|
||||
}
|
||||
}
|
||||
|
@ -322,7 +331,7 @@ double Print::max_allowed_layer_height() const
|
|||
{
|
||||
double nozzle_diameter_max = 0.;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
PrintObject *object = new PrintObject(this, model_object, model_object->raw_bounding_box());
|
||||
if (idx != -1) {
|
||||
delete this->objects[idx];
|
||||
this->objects[idx] = object;
|
||||
delete m_objects[idx];
|
||||
m_objects[idx] = object;
|
||||
} else
|
||||
this->objects.emplace_back(object);
|
||||
m_objects.emplace_back(object);
|
||||
// Invalidate all print 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]);
|
||||
// Find an existing print region with the same config.
|
||||
size_t region_id = size_t(-1);
|
||||
for (size_t i = 0; i < this->regions.size(); ++ i)
|
||||
if (config.equals(this->regions[i]->config)) {
|
||||
for (size_t i = 0; i < m_regions.size(); ++ i)
|
||||
if (config.equals(m_regions[i]->config())) {
|
||||
region_id = i;
|
||||
break;
|
||||
}
|
||||
// If no region exists with the same config, create a new one.
|
||||
if (region_id == size_t(-1)) {
|
||||
region_id = this->regions.size();
|
||||
this->add_region()->config.apply(config);
|
||||
region_id = this->regions().size();
|
||||
this->add_region(config);
|
||||
}
|
||||
// Assign volume to a region.
|
||||
object->add_region_volume(region_id, volume_id);
|
||||
}
|
||||
|
||||
// Apply config to print object.
|
||||
object->config.apply(this->default_object_config);
|
||||
normalize_and_apply_config(object->config, model_object->config);
|
||||
object->config_apply(this->default_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
|
||||
{
|
||||
// get the first input file name
|
||||
std::string input_file;
|
||||
std::vector<std::string> v_scale;
|
||||
for (const PrintObject *object : this->objects) {
|
||||
for (const PrintObject *object : m_objects) {
|
||||
const ModelObject &mobj = *object->model_object();
|
||||
v_scale.push_back(boost::lexical_cast<std::string>(mobj.instances[0]->scaling_factor*100) + "%");
|
||||
if (input_file.empty())
|
||||
input_file = mobj.input_file;
|
||||
}
|
||||
|
||||
PlaceholderParser &pp = this->placeholder_parser;
|
||||
PlaceholderParser &pp = m_placeholder_parser;
|
||||
pp.set("scale", v_scale);
|
||||
if (! input_file.empty()) {
|
||||
// get basename with and without suffix
|
||||
|
@ -393,19 +407,19 @@ bool Print::apply_config(DynamicPrintConfig config)
|
|||
config.normalize();
|
||||
|
||||
// apply variables to placeholder parser
|
||||
this->placeholder_parser.apply_config(config);
|
||||
m_placeholder_parser.apply_config(config);
|
||||
|
||||
// handle changes to print config
|
||||
t_config_option_keys print_diff = this->config.diff(config);
|
||||
this->config.apply_only(config, print_diff, true);
|
||||
t_config_option_keys print_diff = m_config.diff(config);
|
||||
m_config.apply_only(config, print_diff, true);
|
||||
bool invalidated = this->invalidate_state_by_config_options(print_diff);
|
||||
|
||||
// handle changes to object config defaults
|
||||
this->default_object_config.apply(config, true);
|
||||
for (PrintObject *object : this->objects) {
|
||||
m_default_object_config.apply(config, true);
|
||||
for (PrintObject *object : m_objects) {
|
||||
// we don't assume that config contains a full ObjectConfig,
|
||||
// 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
|
||||
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.
|
||||
|
@ -417,13 +431,13 @@ bool Print::apply_config(DynamicPrintConfig config)
|
|||
invalidated = true;
|
||||
}
|
||||
// check whether the new config is different from the current one
|
||||
t_config_option_keys diff = object->config.diff(new_config);
|
||||
object->config.apply_only(new_config, diff, true);
|
||||
t_config_option_keys diff = object->config().diff(new_config);
|
||||
object->config_apply_only(new_config, diff, true);
|
||||
invalidated |= object->invalidate_state_by_config_options(diff);
|
||||
}
|
||||
|
||||
// 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.
|
||||
// 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,
|
||||
// so one may check for duplicates.
|
||||
std::vector<PrintRegionConfig> other_region_configs;
|
||||
for (size_t region_id = 0; region_id < this->regions.size(); ++ region_id) {
|
||||
PrintRegion ®ion = *this->regions[region_id];
|
||||
for (size_t region_id = 0; region_id < m_regions.size(); ++ region_id) {
|
||||
PrintRegion ®ion = *m_regions[region_id];
|
||||
PrintRegionConfig this_region_config;
|
||||
bool this_region_config_set = false;
|
||||
for (PrintObject *object : this->objects) {
|
||||
for (PrintObject *object : m_objects) {
|
||||
if (region_id < object->region_volumes.size()) {
|
||||
for (int volume_id : object->region_volumes[region_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) {
|
||||
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()) {
|
||||
region.config.apply_only(this_region_config, diff);
|
||||
for (PrintObject *object : this->objects)
|
||||
region.config_apply_only(this_region_config, diff, false);
|
||||
for (PrintObject *object : m_objects)
|
||||
if (region_id < object->region_volumes.size() && ! object->region_volumes[region_id].empty())
|
||||
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.
|
||||
// We need to remove all objects and re-add them.
|
||||
ModelObjectPtrs model_objects;
|
||||
model_objects.reserve(this->objects.size());
|
||||
for (PrintObject *object : this->objects)
|
||||
model_objects.reserve(m_objects.size());
|
||||
for (PrintObject *object : m_objects)
|
||||
model_objects.push_back(object->model_object());
|
||||
this->clear_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.
|
||||
for (PrintObject *object : this->objects)
|
||||
for (PrintObject *object : m_objects)
|
||||
if (! object->layer_height_profile_valid)
|
||||
object->update_layer_height_profile();
|
||||
|
||||
|
@ -503,32 +517,32 @@ exit_for_rearrange_regions:
|
|||
|
||||
bool Print::has_infinite_skirt() const
|
||||
{
|
||||
return (this->config.skirt_height == -1 && this->config.skirts > 0)
|
||||
|| (this->config.ooze_prevention && this->extruders().size() > 1);
|
||||
return (m_config.skirt_height == -1 && m_config.skirts > 0)
|
||||
|| (m_config.ooze_prevention && this->extruders().size() > 1);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
std::string Print::validate() const
|
||||
{
|
||||
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(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));
|
||||
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), 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.
|
||||
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)))
|
||||
return "Some objects are outside of the print volume.";
|
||||
}
|
||||
|
||||
if (this->config.complete_objects) {
|
||||
if (m_config.complete_objects) {
|
||||
// Check horizontal clearance.
|
||||
{
|
||||
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.
|
||||
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.
|
||||
object->model_object()->instances.front()->transform_polygon(&convex_hull);
|
||||
// Grow convex hull with the clearance margin.
|
||||
convex_hull = offset(convex_hull, scale_(this->config.extruder_clearance_radius.value)/2, 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.
|
||||
for (const Point © : object->_shifted_copies) {
|
||||
Polygon p = convex_hull;
|
||||
|
@ -556,47 +570,47 @@ std::string Print::validate() const
|
|||
// Check vertical clearance.
|
||||
{
|
||||
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);
|
||||
std::sort(object_height.begin(), object_height.end());
|
||||
// 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.
|
||||
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.";
|
||||
}
|
||||
} // 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;
|
||||
for (const PrintObject *object : this->objects)
|
||||
for (const PrintObject *object : m_objects)
|
||||
total_copies_count += object->copies().size();
|
||||
// #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.";
|
||||
if (this->regions.size() > 1)
|
||||
if (m_regions.size() > 1)
|
||||
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
|
||||
for (auto dmr : this->config.nozzle_diameter.values)
|
||||
for (auto dmr : m_config.nozzle_diameter.values)
|
||||
if (std::abs(dmr - 0.4) > EPSILON)
|
||||
return "The Wipe Tower is currently only supported for the 0.4mm nozzle diameter.";
|
||||
#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.";
|
||||
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).";
|
||||
SlicingParameters slicing_params0 = this->objects.front()->slicing_parameters();
|
||||
for (PrintObject *object : this->objects) {
|
||||
SlicingParameters slicing_params0 = m_objects.front()->slicing_parameters();
|
||||
for (PrintObject *object : m_objects) {
|
||||
SlicingParameters slicing_params = object->slicing_parameters();
|
||||
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)
|
||||
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())
|
||||
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";
|
||||
if (! equal_layering(slicing_params, slicing_params0))
|
||||
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;
|
||||
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 &&
|
||||
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.";
|
||||
}
|
||||
}
|
||||
|
@ -618,12 +632,12 @@ std::string Print::validate() const
|
|||
|
||||
std::vector<double> nozzle_diameters;
|
||||
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());
|
||||
|
||||
for (PrintObject *object : this->objects) {
|
||||
if ((object->config.support_material_extruder == -1 || object->config.support_material_interface_extruder == -1) &&
|
||||
(object->config.raft_layers > 0 || object->config.support_material.value)) {
|
||||
for (PrintObject *object : m_objects) {
|
||||
if ((object->config().support_material_extruder == -1 || object->config().support_material_interface_extruder == -1) &&
|
||||
(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
|
||||
// will be printed with the current tool without a forced tool change. Play safe, assert that all object nozzles
|
||||
// are of the same diameter.
|
||||
|
@ -634,16 +648,16 @@ std::string Print::validate() const
|
|||
}
|
||||
|
||||
// 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;
|
||||
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
|
||||
size_t first_layer_extruder = object->config.raft_layers == 1
|
||||
? object->config.support_material_interface_extruder-1
|
||||
: object->config.support_material_extruder-1;
|
||||
size_t first_layer_extruder = object->config().raft_layers == 1
|
||||
? object->config().support_material_interface_extruder-1
|
||||
: object->config().support_material_extruder-1;
|
||||
first_layer_min_nozzle_diameter = (first_layer_extruder == size_t(-1)) ?
|
||||
min_nozzle_diameter :
|
||||
this->config.nozzle_diameter.get_at(first_layer_extruder);
|
||||
m_config.nozzle_diameter.get_at(first_layer_extruder);
|
||||
} else {
|
||||
// if we don't have raft layers, any nozzle diameter is potentially used in first layer
|
||||
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";
|
||||
|
||||
// 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";
|
||||
}
|
||||
}
|
||||
|
@ -665,7 +679,7 @@ std::string Print::validate() const
|
|||
BoundingBox Print::bounding_box() const
|
||||
{
|
||||
BoundingBox bb;
|
||||
for (const PrintObject *object : this->objects)
|
||||
for (const PrintObject *object : m_objects)
|
||||
for (Point copy : object->_shifted_copies) {
|
||||
bb.merge(copy);
|
||||
copy.translate(object->size);
|
||||
|
@ -683,7 +697,7 @@ BoundingBox Print::total_bounding_box() const
|
|||
BoundingBox bb = this->bounding_box();
|
||||
|
||||
// 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;
|
||||
|
||||
// consider support material
|
||||
|
@ -692,18 +706,18 @@ BoundingBox Print::total_bounding_box() const
|
|||
}
|
||||
|
||||
// consider brim and skirt
|
||||
if (this->config.brim_width.value > 0) {
|
||||
if (m_config.brim_width.value > 0) {
|
||||
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()) {
|
||||
int skirts = this->config.skirts.value;
|
||||
int skirts = m_config.skirts.value;
|
||||
if (skirts == 0 && this->has_infinite_skirt()) skirts = 1;
|
||||
Flow skirt_flow = this->skirt_flow();
|
||||
extra = std::max(
|
||||
extra,
|
||||
this->config.brim_width.value
|
||||
+ this->config.skirt_distance.value
|
||||
m_config.brim_width.value
|
||||
+ m_config.skirt_distance.value
|
||||
+ skirts * skirt_flow.spacing()
|
||||
+ skirt_flow.width/2
|
||||
);
|
||||
|
@ -717,17 +731,17 @@ BoundingBox Print::total_bounding_box() const
|
|||
|
||||
double Print::skirt_first_layer_height() const
|
||||
{
|
||||
if (this->objects.empty()) CONFESS("skirt_first_layer_height() can't be called without PrintObjects");
|
||||
return this->objects.front()->config.get_abs_value("first_layer_height");
|
||||
if (m_objects.empty()) CONFESS("skirt_first_layer_height() can't be called without PrintObjects");
|
||||
return m_objects.front()->config().get_abs_value("first_layer_height");
|
||||
}
|
||||
|
||||
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)
|
||||
width = this->regions.front()->config.perimeter_extrusion_width;
|
||||
width = m_regions.front()->config().perimeter_extrusion_width;
|
||||
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.
|
||||
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(
|
||||
frPerimeter,
|
||||
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(),
|
||||
0
|
||||
);
|
||||
|
@ -745,11 +759,11 @@ Flow Print::brim_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)
|
||||
width = this->regions.front()->config.perimeter_extrusion_width;
|
||||
width = m_regions.front()->config().perimeter_extrusion_width;
|
||||
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.
|
||||
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(
|
||||
frPerimeter,
|
||||
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(),
|
||||
0
|
||||
);
|
||||
|
@ -767,7 +781,7 @@ Flow Print::skirt_flow() const
|
|||
|
||||
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.config);
|
||||
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
|
||||
{
|
||||
for (const PrintObject *object : this->objects)
|
||||
for (const PrintObject *object : m_objects)
|
||||
if (object->has_support_material())
|
||||
return true;
|
||||
return false;
|
||||
|
@ -791,7 +805,7 @@ void Print::auto_assign_extruders(ModelObject* model_object) const
|
|||
if (model_object->volumes.size() < 2)
|
||||
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) {
|
||||
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.
|
||||
|
@ -804,44 +818,44 @@ void Print::auto_assign_extruders(ModelObject* model_object) const
|
|||
void Print::process()
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(info) << "Staring the slicing process.";
|
||||
for (PrintObject *obj : this->objects)
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->make_perimeters();
|
||||
this->throw_if_canceled();
|
||||
this->set_status(70, "Infilling layers");
|
||||
for (PrintObject *obj : this->objects)
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->infill();
|
||||
this->throw_if_canceled();
|
||||
for (PrintObject *obj : this->objects)
|
||||
for (PrintObject *obj : m_objects)
|
||||
obj->generate_support_material();
|
||||
this->throw_if_canceled();
|
||||
if (! m_state.is_done(psSkirt)) {
|
||||
this->set_started(psSkirt);
|
||||
this->skirt.clear();
|
||||
m_skirt.clear();
|
||||
if (this->has_skirt()) {
|
||||
this->set_status(88, "Generating skirt");
|
||||
this->_make_skirt();
|
||||
}
|
||||
m_state.set_done(psSkirt);
|
||||
this->set_done(psSkirt);
|
||||
}
|
||||
this->throw_if_canceled();
|
||||
if (! m_state.is_done(psBrim)) {
|
||||
this->set_started(psBrim);
|
||||
this->brim.clear();
|
||||
if (this->config.brim_width > 0) {
|
||||
m_brim.clear();
|
||||
if (m_config.brim_width > 0) {
|
||||
this->set_status(88, "Generating brim");
|
||||
this->_make_brim();
|
||||
}
|
||||
m_state.set_done(psBrim);
|
||||
this->set_done(psBrim);
|
||||
}
|
||||
this->throw_if_canceled();
|
||||
if (! m_state.is_done(psWipeTower)) {
|
||||
this->set_started(psWipeTower);
|
||||
this->_clear_wipe_tower();
|
||||
m_wipe_tower_data.clear();
|
||||
if (this->has_wipe_tower()) {
|
||||
//this->set_status(95, "Generating wipe tower");
|
||||
this->_make_wipe_tower();
|
||||
}
|
||||
m_state.set_done(psWipeTower);
|
||||
this->set_done(psWipeTower);
|
||||
}
|
||||
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).
|
||||
// $skirt_height_z in this case is the highest possible skirt height for safety.
|
||||
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() ?
|
||||
object->layer_count() :
|
||||
std::min(size_t(this->config.skirt_height.value), object->layer_count());
|
||||
skirt_height_z = std::max(skirt_height_z, object->layers[skirt_layers-1]->print_z);
|
||||
std::min(size_t(m_config.skirt_height.value), object->layer_count());
|
||||
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.
|
||||
Points points;
|
||||
for (const PrintObject *object : this->objects) {
|
||||
for (const PrintObject *object : m_objects) {
|
||||
this->throw_if_canceled();
|
||||
Points object_points;
|
||||
// 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)
|
||||
break;
|
||||
for (const ExPolygon &expoly : layer->slices.expolygons)
|
||||
|
@ -904,7 +918,7 @@ void Print::_make_skirt()
|
|||
append(object_points, expoly.contour.points);
|
||||
}
|
||||
// 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)
|
||||
break;
|
||||
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());
|
||||
for (auto &extruder_id : set_extruders) {
|
||||
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.
|
||||
int n_skirts = this->config.skirts.value;
|
||||
int n_skirts = m_config.skirts.value;
|
||||
if (this->has_infinite_skirt() && n_skirts == 0)
|
||||
n_skirts = 1;
|
||||
|
||||
// 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.
|
||||
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.
|
||||
// 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.);
|
||||
|
@ -978,16 +992,16 @@ void Print::_make_skirt()
|
|||
first_layer_height // this will be overridden at G-code export time
|
||||
)));
|
||||
eloop.paths.back().polyline = loop.split_at_first_point();
|
||||
this->skirt.append(eloop);
|
||||
if (this->config.min_skirt_length.value > 0) {
|
||||
m_skirt.append(eloop);
|
||||
if (m_config.min_skirt_length.value > 0) {
|
||||
// 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];
|
||||
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.
|
||||
if (i == 1)
|
||||
++ i;
|
||||
} 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,
|
||||
// until the prescribed number of skirt loops is extruded.
|
||||
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.
|
||||
this->skirt.reverse();
|
||||
m_skirt.reverse();
|
||||
}
|
||||
|
||||
void Print::_make_brim()
|
||||
|
@ -1006,13 +1020,13 @@ void Print::_make_brim()
|
|||
// Brim is only printed on first layer and uses perimeter extruder.
|
||||
Flow flow = this->brim_flow();
|
||||
Polygons islands;
|
||||
for (PrintObject *object : this->objects) {
|
||||
for (PrintObject *object : m_objects) {
|
||||
this->throw_if_canceled();
|
||||
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);
|
||||
if (! object->support_layers.empty())
|
||||
object->support_layers.front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON));
|
||||
if (! object->support_layers().empty())
|
||||
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());
|
||||
for (const Point &pt : object->_shifted_copies)
|
||||
for (Polygon &poly : object_islands) {
|
||||
|
@ -1021,7 +1035,7 @@ void Print::_make_brim()
|
|||
}
|
||||
}
|
||||
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) {
|
||||
this->throw_if_canceled();
|
||||
islands = offset(islands, float(flow.scaled_spacing()), jtSquare);
|
||||
|
@ -1037,32 +1051,24 @@ void Print::_make_brim()
|
|||
|
||||
loops = union_pt_chained(loops, false);
|
||||
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.
|
||||
bool Print::has_wipe_tower() const
|
||||
{
|
||||
return
|
||||
this->config.single_extruder_multi_material.value &&
|
||||
! this->config.spiral_vase.value &&
|
||||
this->config.wipe_tower.value &&
|
||||
this->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);
|
||||
m_config.single_extruder_multi_material.value &&
|
||||
! m_config.spiral_vase.value &&
|
||||
m_config.wipe_tower.value &&
|
||||
m_config.nozzle_diameter.values.size() > 1;
|
||||
}
|
||||
|
||||
void Print::_make_wipe_tower()
|
||||
{
|
||||
// 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);
|
||||
if (! m_tool_ordering.has_wipe_tower())
|
||||
m_wipe_tower_data.tool_ordering = ToolOrdering(*this, (unsigned int)-1, true);
|
||||
if (! m_wipe_tower_data.tool_ordering.has_wipe_tower())
|
||||
// Don't generate any wipe tower.
|
||||
return;
|
||||
|
||||
|
@ -1072,33 +1078,31 @@ void Print::_make_wipe_tower()
|
|||
// see https://github.com/prusa3d/Slic3r/issues/607
|
||||
{
|
||||
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.
|
||||
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) {
|
||||
idx_begin = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx_begin != size_t(-1)) {
|
||||
// Find the position in this->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;
|
||||
SupportLayerPtrs::iterator it_layer = this->objects.front()->support_layers.begin();
|
||||
SupportLayerPtrs::iterator it_end = this->objects.front()->support_layers.end();
|
||||
// Find the position in m_objects.first()->support_layers to insert these new support layers.
|
||||
double wipe_tower_new_layer_print_z_first = m_wipe_tower_data.tool_ordering.layer_tools()[idx_begin].print_z;
|
||||
SupportLayerPtrs::const_iterator it_layer = m_objects.front()->support_layers().begin();
|
||||
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);
|
||||
// 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) {
|
||||
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))
|
||||
break;
|
||||
lt.has_support = true;
|
||||
// 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.
|
||||
auto *new_layer = new SupportLayer(size_t(-1), this->objects.front(),
|
||||
height, lt.print_z, lt.print_z - 0.5 * height);
|
||||
it_layer = this->objects.front()->support_layers.insert(it_layer, new_layer);
|
||||
it_layer = m_objects.front()->insert_support_layer(it_layer, size_t(-1), height, lt.print_z, lt.print_z - 0.5 * height);
|
||||
++ it_layer;
|
||||
}
|
||||
}
|
||||
|
@ -1107,9 +1111,9 @@ void Print::_make_wipe_tower()
|
|||
|
||||
// Initialize the wipe tower.
|
||||
WipeTowerPrusaMM wipe_tower(
|
||||
float(this->config.wipe_tower_x.value), float(this->config.wipe_tower_y.value),
|
||||
float(this->config.wipe_tower_width.value), float(this->config.wipe_tower_per_color_wipe.value),
|
||||
m_tool_ordering.first_extruder());
|
||||
float(m_config.wipe_tower_x.value), float(m_config.wipe_tower_y.value),
|
||||
float(m_config.wipe_tower_width.value), float(m_config.wipe_tower_per_color_wipe.value),
|
||||
m_wipe_tower_data.tool_ordering.first_extruder());
|
||||
|
||||
//wipe_tower.set_retract();
|
||||
//wipe_tower.set_zhop();
|
||||
|
@ -1118,29 +1122,29 @@ void Print::_make_wipe_tower()
|
|||
for (size_t i = 0; i < 4; ++ i)
|
||||
wipe_tower.set_extruder(
|
||||
i,
|
||||
WipeTowerPrusaMM::parse_material(this->config.filament_type.get_at(i).c_str()),
|
||||
this->config.temperature.get_at(i),
|
||||
this->config.first_layer_temperature.get_at(i));
|
||||
WipeTowerPrusaMM::parse_material(m_config.filament_type.get_at(i).c_str()),
|
||||
m_config.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.
|
||||
// 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.
|
||||
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>(
|
||||
wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full, WipeTower::PURPOSE_EXTRUDE));
|
||||
m_wipe_tower_data.priming = Slic3r::make_unique<WipeTower::ToolChangeResult>(
|
||||
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.
|
||||
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.
|
||||
unsigned int current_extruder_id = m_tool_ordering.all_extruders().back();
|
||||
for (const ToolOrdering::LayerTools &layer_tools : m_tool_ordering.layer_tools()) {
|
||||
unsigned int current_extruder_id = m_wipe_tower_data.tool_ordering.all_extruders().back();
|
||||
for (const ToolOrdering::LayerTools &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) {
|
||||
this->throw_if_canceled();
|
||||
if (! layer_tools.has_wipe_tower)
|
||||
// This is a support only layer, or the wipe tower does not reach to this height.
|
||||
continue;
|
||||
bool first_layer = &layer_tools == &m_tool_ordering.front();
|
||||
bool last_layer = &layer_tools == &m_tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0;
|
||||
bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front();
|
||||
bool last_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.back() || (&layer_tools + 1)->wipe_tower_partitions == 0;
|
||||
wipe_tower.set_layer(
|
||||
float(layer_tools.print_z),
|
||||
float(layer_tools.wipe_tower_layer_height),
|
||||
|
@ -1151,7 +1155,7 @@ void Print::_make_wipe_tower()
|
|||
for (unsigned int extruder_id : layer_tools.extruders)
|
||||
// Call the wipe_tower.tool_change() at the first layer for the initial extruder
|
||||
// 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.
|
||||
extruder_id != current_extruder_id) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
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)
|
||||
break;
|
||||
}
|
||||
|
||||
// Unload the current filament over the purge tower.
|
||||
coordf_t layer_height = this->objects.front()->config.layer_height.value;
|
||||
if (m_tool_ordering.back().wipe_tower_partitions > 0) {
|
||||
coordf_t layer_height = m_objects.front()->config().layer_height.value;
|
||||
if (m_wipe_tower_data.tool_ordering.back().wipe_tower_partitions > 0) {
|
||||
// The wipe tower goes up to the last layer of the print.
|
||||
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.
|
||||
// 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 {
|
||||
// There is yet enough space at this layer of the wipe tower for the final purge.
|
||||
}
|
||||
} else {
|
||||
// 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);
|
||||
wipe_tower.set_layer(float(m_tool_ordering.back().print_z), float(layer_height), 0, false, true);
|
||||
assert(m_wipe_tower_data.tool_ordering.back().wipe_tower_partitions == 0);
|
||||
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));
|
||||
}
|
||||
|
||||
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 {
|
||||
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) {
|
||||
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 (path.empty()) {
|
||||
// get the first input file name
|
||||
std::string input_file;
|
||||
for (const PrintObject *object : this->objects) {
|
||||
for (const PrintObject *object : m_objects) {
|
||||
input_file = object->model_object()->input_file;
|
||||
if (! input_file.empty())
|
||||
break;
|
||||
|
|
|
@ -51,7 +51,7 @@ template <class StepType, size_t COUNT>
|
|||
class PrintState
|
||||
{
|
||||
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 {
|
||||
INVALID,
|
||||
|
@ -59,24 +59,58 @@ public:
|
|||
DONE,
|
||||
};
|
||||
|
||||
// With full memory barrier.
|
||||
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
|
||||
// influence the processing step being entered.
|
||||
void set_started(StepType step, tbb::mutex &mtx) { mtx.lock(); m_state[step] = STARTED; mtx.unlock(); }
|
||||
void set_done(StepType step) { m_state[step] = DONE; }
|
||||
bool invalidate(StepType step) {
|
||||
bool invalidated = m_state[step] != INVALID;
|
||||
m_state[step] = INVALID;
|
||||
void set_started(StepType step, tbb::mutex &mtx) {
|
||||
mtx.lock();
|
||||
m_state[step].store(STARTED, std::memory_order_relaxed);
|
||||
mtx.unlock();
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
m_state[i] = INVALID;
|
||||
break;
|
||||
}
|
||||
m_state[i].store(INVALID, std::memory_order_relaxed);
|
||||
}
|
||||
return invalidated;
|
||||
}
|
||||
|
@ -91,17 +125,24 @@ class PrintRegion
|
|||
{
|
||||
friend class Print;
|
||||
|
||||
// Methods NOT modifying the PrintRegion's state:
|
||||
public:
|
||||
PrintRegionConfig config;
|
||||
|
||||
Print* print() { return this->_print; }
|
||||
const Print* print() const { return m_print; }
|
||||
const PrintRegionConfig& config() const { return m_config; }
|
||||
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;
|
||||
|
||||
private:
|
||||
Print* _print;
|
||||
// Methods modifying the PrintRegion's state:
|
||||
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() {}
|
||||
};
|
||||
|
||||
|
@ -117,7 +158,6 @@ class PrintObject
|
|||
public:
|
||||
// vector of (vectors of volume ids), indexed by region_id
|
||||
std::vector<std::vector<int>> region_volumes;
|
||||
PrintObjectConfig config;
|
||||
t_layer_height_ranges layer_height_ranges;
|
||||
|
||||
// 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
|
||||
Points _shifted_copies;
|
||||
|
||||
LayerPtrs layers;
|
||||
SupportLayerPtrs support_layers;
|
||||
Print* print() { return m_print; }
|
||||
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 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; }
|
||||
const Points& copies() const { return m_copies; }
|
||||
bool add_copy(const Pointf &point);
|
||||
bool delete_last_copy();
|
||||
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
|
||||
// since they have different semantics.
|
||||
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();
|
||||
Layer* get_layer(int idx) { return this->layers.at(idx); }
|
||||
const Layer* get_layer(int idx) const { return this->layers.at(idx); }
|
||||
Layer* get_layer(int idx) { return m_layers[idx]; }
|
||||
const Layer* get_layer(int idx) const { return m_layers[idx]; }
|
||||
|
||||
// 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);
|
||||
|
||||
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();
|
||||
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);
|
||||
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);
|
||||
|
||||
// methods for handling state
|
||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
||||
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); }
|
||||
|
||||
// To be used over the layer_height_profile of both the PrintObject and ModelObject
|
||||
|
@ -229,9 +272,14 @@ private:
|
|||
void combine_infill();
|
||||
void _generate_support_material();
|
||||
|
||||
Print* _print;
|
||||
ModelObject* _model_object;
|
||||
Points _copies; // Slic3r::Point objects in scaled G-code coordinates
|
||||
Print *m_print;
|
||||
ModelObject *m_model_object;
|
||||
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;
|
||||
// Mutex used for synchronization of the worker thread with the UI thread:
|
||||
|
@ -245,9 +293,49 @@ private:
|
|||
~PrintObject() {}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
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<PrintRegion*> PrintRegionPtrs;
|
||||
|
||||
|
@ -255,44 +343,27 @@ typedef std::vector<PrintRegion*> PrintRegionPtrs;
|
|||
class Print
|
||||
{
|
||||
public:
|
||||
PrintConfig config;
|
||||
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() { restart(); }
|
||||
~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();
|
||||
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 reload_object(size_t idx);
|
||||
bool reload_model_instances();
|
||||
|
||||
// methods for handling regions
|
||||
PrintRegion* get_region(size_t idx) { return regions.at(idx); }
|
||||
const PrintRegion* get_region(size_t idx) const { return regions.at(idx); }
|
||||
PrintRegion* add_region();
|
||||
void add_model_object(ModelObject* model_object, int idx = -1);
|
||||
bool apply_config(DynamicPrintConfig config);
|
||||
void process();
|
||||
void export_gcode(const std::string &path_template, GCodePreviewData *preview_data);
|
||||
|
||||
// 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(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_skirt() const;
|
||||
// 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> support_material_extruders() const;
|
||||
std::vector<unsigned int> extruders() const;
|
||||
void _simplify_slices(double distance);
|
||||
double max_allowed_layer_height() 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 process();
|
||||
void export_gcode(const std::string &path_template, GCodePreviewData *preview_data);
|
||||
const PrintConfig& config() const { return m_config; }
|
||||
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.
|
||||
bool has_wipe_tower() const;
|
||||
// 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 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;
|
||||
const WipeTowerData& wipe_tower_data() const { return m_wipe_tower_data; }
|
||||
|
||||
std::string output_filename();
|
||||
std::string output_filepath(const std::string &path);
|
||||
std::string output_filename() const;
|
||||
std::string output_filepath(const std::string &path) const;
|
||||
|
||||
typedef std::function<void(int, const std::string&)> status_callback_type;
|
||||
// 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);
|
||||
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.
|
||||
void cancel() { m_canceled = true; }
|
||||
// Cancel the running computation. Stop execution of all the background threads.
|
||||
void restart() { m_canceled = false; }
|
||||
// Has the calculation been canceled?
|
||||
bool canceled() { return m_canceled; }
|
||||
void throw_if_canceled() { if (m_canceled) throw CanceledException(); }
|
||||
|
||||
// Accessed by SupportMaterial
|
||||
const PrintRegion* get_region(size_t idx) const { return m_regions[idx]; }
|
||||
|
||||
protected:
|
||||
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:
|
||||
bool invalidate_state_by_config_options(const std::vector<t_config_option_key> &opt_keys);
|
||||
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_brim();
|
||||
void _clear_wipe_tower();
|
||||
void _make_wipe_tower();
|
||||
void _simplify_slices(double distance);
|
||||
|
||||
PrintState<PrintStep, psCount> m_state;
|
||||
// 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.
|
||||
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.
|
||||
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_REGION(print, region) FOREACH_BASE(PrintRegionPtrs, (print)->regions, region)
|
||||
#define FOREACH_OBJECT(print, object) FOREACH_BASE(PrintObjectPtrs, (print)->objects, object)
|
||||
#define FOREACH_LAYER(object, layer) FOREACH_BASE(LayerPtrs, (object)->layers, layer)
|
||||
#define FOREACH_LAYERREGION(layer, layerm) FOREACH_BASE(LayerRegionPtrs, (layer)->regions, layerm)
|
||||
#define FOREACH_OBJECT(print, object) FOREACH_BASE(PrintObjectPtrs, (print)->m_objects, object)
|
||||
#define FOREACH_LAYER(object, layer) FOREACH_BASE(LayerPtrs, (object)->m_layers, layer)
|
||||
#define FOREACH_LAYERREGION(layer, layerm) FOREACH_BASE(LayerRegionPtrs, (layer)->m_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 {
|
||||
// otherwise, get extrusion width from configuration
|
||||
// (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) {
|
||||
config_width = this->_print->config.first_layer_extrusion_width;
|
||||
if (first_layer && m_print->config().first_layer_extrusion_width.value > 0) {
|
||||
config_width = m_print->config().first_layer_extrusion_width;
|
||||
} else if (role == frExternalPerimeter) {
|
||||
config_width = this->config.external_perimeter_extrusion_width;
|
||||
config_width = m_config.external_perimeter_extrusion_width;
|
||||
} else if (role == frPerimeter) {
|
||||
config_width = this->config.perimeter_extrusion_width;
|
||||
config_width = m_config.perimeter_extrusion_width;
|
||||
} else if (role == frInfill) {
|
||||
config_width = this->config.infill_extrusion_width;
|
||||
config_width = m_config.infill_extrusion_width;
|
||||
} else if (role == frSolidInfill) {
|
||||
config_width = this->config.solid_infill_extrusion_width;
|
||||
config_width = m_config.solid_infill_extrusion_width;
|
||||
} else if (role == frTopSolidInfill) {
|
||||
config_width = this->config.top_infill_extrusion_width;
|
||||
config_width = m_config.top_infill_extrusion_width;
|
||||
} else {
|
||||
CONFESS("Unknown role");
|
||||
}
|
||||
}
|
||||
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
|
||||
// to the flow role requested
|
||||
size_t extruder = 0; // 1-based
|
||||
if (role == frPerimeter || role == frExternalPerimeter) {
|
||||
extruder = this->config.perimeter_extruder;
|
||||
extruder = m_config.perimeter_extruder;
|
||||
} else if (role == frInfill) {
|
||||
extruder = this->config.infill_extruder;
|
||||
extruder = m_config.infill_extruder;
|
||||
} else if (role == frSolidInfill || role == frTopSolidInfill) {
|
||||
extruder = this->config.solid_infill_extruder;
|
||||
extruder = m_config.solid_infill_extruder;
|
||||
} else {
|
||||
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
|
||||
{
|
||||
return (print_config.nozzle_diameter.get_at(this->config.perimeter_extruder.value - 1) +
|
||||
print_config.nozzle_diameter.get_at(this->config.infill_extruder.value - 1) +
|
||||
print_config.nozzle_diameter.get_at(this->config.solid_infill_extruder.value - 1)) / 3.;
|
||||
return (print_config.nozzle_diameter.get_at(m_config.perimeter_extruder.value - 1) +
|
||||
print_config.nozzle_diameter.get_at(m_config.infill_extruder.value - 1) +
|
||||
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) :
|
||||
m_object (object),
|
||||
m_print_config (&object->print()->config),
|
||||
m_object_config (&object->config),
|
||||
m_print_config (&object->print()->config()),
|
||||
m_object_config (&object->config()),
|
||||
m_slicing_params (slicing_params),
|
||||
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))),
|
||||
|
@ -164,7 +164,7 @@ PrintObjectSupportMaterial::PrintObjectSupportMaterial(const PrintObject *object
|
|||
coordf_t external_perimeter_width = 0.;
|
||||
for (size_t region_id = 0; region_id < object->region_volumes.size(); ++ region_id) {
|
||||
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);
|
||||
if (width <= 0.)
|
||||
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.;
|
||||
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.
|
||||
// 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);
|
||||
|
||||
#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(
|
||||
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));
|
||||
#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.
|
||||
std::sort(layers_sorted.begin(), layers_sorted.end(), MyLayersPtrCompare());
|
||||
int layer_id = 0;
|
||||
assert(object.support_layers.empty());
|
||||
assert(object.support_layers().empty());
|
||||
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.
|
||||
// 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.
|
||||
size_t n_polygons_new = 0;
|
||||
for (LayerRegionPtrs::const_iterator it_region = layer.regions.begin(); it_region != layer.regions.end(); ++ it_region) {
|
||||
const LayerRegion ®ion = *(*it_region);
|
||||
for (const LayerRegion* pregion : layer.regions()) {
|
||||
const LayerRegion ®ion = *pregion;
|
||||
const SurfaceCollection &slices = region.slices;
|
||||
for (Surfaces::const_iterator it = slices.surfaces.begin(); it != slices.surfaces.end(); ++ 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.
|
||||
Polygons out;
|
||||
out.reserve(n_polygons_new);
|
||||
for (LayerRegionPtrs::const_iterator it_region = layer.regions.begin(); it_region != layer.regions.end(); ++ it_region) {
|
||||
const LayerRegion ®ion = *(*it_region);
|
||||
for (const LayerRegion *pregion : layer.regions()) {
|
||||
const LayerRegion ®ion = *pregion;
|
||||
const SurfaceCollection &slices = region.slices;
|
||||
for (Surfaces::const_iterator it = slices.surfaces.begin(); it != slices.surfaces.end(); ++ it) {
|
||||
const Surface &surface = *it;
|
||||
|
@ -658,9 +658,9 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
std::vector<Polygons> buildplate_covered;
|
||||
if (buildplate_only) {
|
||||
BOOST_LOG_TRIVIAL(debug) << "PrintObjectSupportMaterial::top_contact_layers() - collecting regions covering the print bed.";
|
||||
buildplate_covered.assign(object.layers.size(), Polygons());
|
||||
for (size_t layer_id = 1; layer_id < object.layers.size(); ++ layer_id) {
|
||||
const Layer &lower_layer = *object.layers[layer_id-1];
|
||||
buildplate_covered.assign(object.layers().size(), Polygons());
|
||||
for (size_t layer_id = 1; layer_id < object.layers().size(); ++ layer_id) {
|
||||
const Layer &lower_layer = *object.layers()[layer_id-1];
|
||||
// Merge the new slices with the preceding slices.
|
||||
// Apply the safety offset to the newly added polygons, so they will connect
|
||||
// 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) {
|
||||
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.
|
||||
// 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));
|
||||
} else {
|
||||
// Generate overhang / contact_polygons for non-raft layers.
|
||||
const Layer &lower_layer = *object.layers[layer_id-1];
|
||||
for (LayerRegion *layerm : layer.regions) {
|
||||
const Layer &lower_layer = *object.layers()[layer_id-1];
|
||||
for (LayerRegion *layerm : layer.regions()) {
|
||||
// Extrusion width accounts for the roundings of the extrudates.
|
||||
// It is the maximum widh of the extrudate.
|
||||
float fw = float(layerm->flow(frExternalPerimeter).scaled_width());
|
||||
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.
|
||||
0.f :
|
||||
(threshold_rad > 0. ?
|
||||
|
@ -762,14 +762,14 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
}
|
||||
#endif /* SLIC3R_DEBUG */
|
||||
|
||||
if (this->m_object_config->dont_support_bridges) {
|
||||
if (m_object_config->dont_support_bridges) {
|
||||
// compute the area of bridging perimeters
|
||||
// Note: this is duplicate code from GCode.pm, we need to refactor
|
||||
if (true) {
|
||||
Polygons bridged_perimeters;
|
||||
{
|
||||
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);
|
||||
|
||||
// Collect perimeters of this layer.
|
||||
|
@ -894,8 +894,8 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::top_contact_
|
|||
} else {
|
||||
// Interface layer will be synchronized with the object.
|
||||
assert(layer_id > 0);
|
||||
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.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;
|
||||
}
|
||||
} else {
|
||||
// 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.
|
||||
// Get the average nozzle diameter used on this layer.
|
||||
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 /= 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.bottom_z = new_layer.print_z;
|
||||
new_layer.height = 0.;
|
||||
|
@ -1048,10 +1048,10 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::bottom_conta
|
|||
// top shapes so this can be done here
|
||||
layer_new.height = m_slicing_params.soluble_interface ?
|
||||
// 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.
|
||||
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_new.bottom_z = layer.print_z;
|
||||
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,
|
||||
// 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));
|
||||
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) {
|
||||
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.
|
||||
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.) {
|
||||
// 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(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.height -= diff;
|
||||
} 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.
|
||||
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) {
|
||||
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)
|
||||
break;
|
||||
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.
|
||||
for (size_t i = 1; i < extremes.size(); ++ i) {
|
||||
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. ||
|
||||
extremes[i]->layer_type == extremes[i-1]->layer_type ||
|
||||
(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().
|
||||
assert(extr2->layer_type == sltTopContact);
|
||||
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) {
|
||||
MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate);
|
||||
layer_new.bottom_z = 0.;
|
||||
|
@ -1384,7 +1384,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
|||
if (synchronize) {
|
||||
// Emit support layers synchronized with the object layers.
|
||||
// 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;
|
||||
if (idx_layer_object == 0 && extr1z == m_slicing_params.raft_interface_top_z) {
|
||||
// Insert one base support layer below the object.
|
||||
|
@ -1395,11 +1395,11 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
|||
intermediate_layers.push_back(&layer_new);
|
||||
}
|
||||
// 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);
|
||||
layer_new.print_z = object.layers[idx_layer_object]->print_z;
|
||||
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.print_z = object.layers()[idx_layer_object]->print_z;
|
||||
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);
|
||||
assert(intermediate_layers.empty() || intermediate_layers.back()->print_z < layer_new.print_z + EPSILON);
|
||||
intermediate_layers.push_back(&layer_new);
|
||||
}
|
||||
|
@ -1409,10 +1409,10 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::raft_and_int
|
|||
assert(n_layers_extra > 0);
|
||||
coordf_t step = dist / coordf_t(n_layers_extra);
|
||||
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
|
||||
// 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.
|
||||
MyLayer &layer_new = layer_allocate(layer_storage, sltIntermediate);
|
||||
layer_new.bottom_z = extr1->bottom_z;
|
||||
|
@ -1509,7 +1509,7 @@ void PrintObjectSupportMaterial::generate_base_layers(
|
|||
Polygons polygons_new;
|
||||
|
||||
// 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; }));
|
||||
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.
|
||||
coordf_t z_threshold = support_layer.print_z - support_layer.height - gap_extra_below + EPSILON;
|
||||
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; });
|
||||
// Collect all the object layers intersecting with this layer.
|
||||
Polygons polygons_trimming;
|
||||
size_t i = idx_object_layer_overlapping;
|
||||
for (; i < object.layers.size(); ++ i) {
|
||||
const Layer &object_layer = *object.layers[i];
|
||||
for (; i < object.layers().size(); ++ i) {
|
||||
const Layer &object_layer = *object.layers()[i];
|
||||
if (object_layer.print_z - object_layer.height > support_layer.print_z + gap_extra_above - EPSILON)
|
||||
break;
|
||||
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.
|
||||
for (; i < object.layers.size(); ++ i) {
|
||||
const Layer &object_layer = *object.layers[i];
|
||||
for (; i < object.layers().size(); ++ i) {
|
||||
const Layer &object_layer = *object.layers()[i];
|
||||
bool some_region_overlaps = false;
|
||||
for (LayerRegion* region : object_layer.regions) {
|
||||
coordf_t nozzle_dmr = region->region()->nozzle_dmr_avg(*this->m_print_config);
|
||||
for (LayerRegion* region : object_layer.regions()) {
|
||||
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)
|
||||
break;
|
||||
some_region_overlaps = true;
|
||||
|
@ -1764,7 +1764,7 @@ PrintObjectSupportMaterial::MyLayersPtr PrintObjectSupportMaterial::generate_raf
|
|||
// Expand the bases of the support columns in the 1st layer.
|
||||
columns_base->polygons = diff(
|
||||
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)
|
||||
columns_base->polygons = diff(columns_base->polygons, interface_polygons);
|
||||
}
|
||||
|
@ -1909,8 +1909,8 @@ struct MyLayerExtruded
|
|||
else
|
||||
*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; }
|
||||
const Polygons& polygons_to_extrude() const { 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 (m_polygons_to_extrude == nullptr) ? layer->polygons : *m_polygons_to_extrude; }
|
||||
|
||||
bool could_merge(const MyLayerExtruded &other) const {
|
||||
return ! this->empty() && ! other.empty() &&
|
||||
|
@ -1923,21 +1923,21 @@ struct MyLayerExtruded
|
|||
assert(this->could_merge(other));
|
||||
// 1) Merge the rest polygons to extrude, if there are any.
|
||||
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).
|
||||
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));
|
||||
*this->m_polygons_to_extrude = union_(*this->m_polygons_to_extrude, true);
|
||||
Slic3r::polygons_append(*m_polygons_to_extrude, std::move(*other.m_polygons_to_extrude));
|
||||
*m_polygons_to_extrude = union_(*m_polygons_to_extrude, true);
|
||||
delete other.m_polygons_to_extrude;
|
||||
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);
|
||||
// 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());
|
||||
Slic3r::polygons_append(*this->m_polygons_to_extrude, other.layer->polygons);
|
||||
*this->m_polygons_to_extrude = union_(*this->m_polygons_to_extrude, true);
|
||||
Slic3r::polygons_append(*m_polygons_to_extrude, other.layer->polygons);
|
||||
*m_polygons_to_extrude = union_(*m_polygons_to_extrude, true);
|
||||
}
|
||||
// 2) Merge the extrusions.
|
||||
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)
|
||||
{
|
||||
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());
|
||||
MyLayer &raft_layer = *raft_layers[support_layer_id];
|
||||
|
||||
|
@ -2631,9 +2631,9 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
MyLayerExtruded interface_layer;
|
||||
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,
|
||||
infill_pattern, &bbox_object, support_density, interface_density, interface_angle, &angles, link_max_length_factor, with_sheath]
|
||||
(const tbb::blocked_range<size_t>& range) {
|
||||
|
@ -2648,7 +2648,7 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
filler_support->set_bounding_box(bbox_object);
|
||||
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];
|
||||
|
||||
// Find polygons with the same print_z.
|
||||
|
@ -2844,11 +2844,11 @@ void PrintObjectSupportMaterial::generate_toolpaths(
|
|||
});
|
||||
|
||||
// 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]
|
||||
(const tbb::blocked_range<size_t>& range) {
|
||||
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];
|
||||
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);
|
||||
|
|
|
@ -1670,30 +1670,30 @@ void _3DScene::_load_print_toolpaths(
|
|||
// 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));
|
||||
|
||||
if (!print->has_skirt() && print->config.brim_width.value == 0)
|
||||
if (!print->has_skirt() && print->config().brim_width.value == 0)
|
||||
return;
|
||||
|
||||
const float color[] = { 0.5f, 1.0f, 0.5f, 1.f }; // greenish
|
||||
|
||||
// number of skirt layers
|
||||
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());
|
||||
size_t skirt_height = print->has_infinite_skirt() ?
|
||||
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)
|
||||
std::min<size_t>(print->config().skirt_height.value, total_layer_count);
|
||||
if (skirt_height == 0 && print->config().brim_width.value > 0)
|
||||
skirt_height = 1;
|
||||
|
||||
// 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;
|
||||
print_zs.reserve(skirt_height * 2);
|
||||
for (size_t i = 0; i < std::min(skirt_height, object0->layers.size()); ++ i)
|
||||
print_zs.push_back(float(object0->layers[i]->print_z));
|
||||
for (size_t i = 0; i < std::min(skirt_height, object0->layers().size()); ++ i)
|
||||
print_zs.push_back(float(object0->layers()[i]->print_z));
|
||||
//FIXME why there are support layers?
|
||||
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));
|
||||
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));
|
||||
sort_remove_duplicates(print_zs);
|
||||
if (print_zs.size() > skirt_height)
|
||||
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.triangle_indices.size());
|
||||
if (i == 0)
|
||||
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->brim(), 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.indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||
|
@ -1753,10 +1753,10 @@ void _3DScene::_load_print_object_toolpaths(
|
|||
ctxt.shifted_copies = &print_object->_shifted_copies;
|
||||
|
||||
// order layers by print_z
|
||||
ctxt.layers.reserve(print_object->layers.size() + print_object->support_layers.size());
|
||||
for (const Layer *layer : print_object->layers)
|
||||
ctxt.layers.reserve(print_object->layers().size() + print_object->support_layers().size());
|
||||
for (const Layer *layer : print_object->layers())
|
||||
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);
|
||||
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 LayerRegion *layerm : layer->regions) {
|
||||
for (const LayerRegion *layerm : layer->regions()) {
|
||||
if (ctxt.has_perimeters)
|
||||
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) {
|
||||
for (const ExtrusionEntity *ee : layerm->fills.entities) {
|
||||
// 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,
|
||||
*vols[ctxt.volume_idx(
|
||||
is_solid_infill(fill->entities.front()->role()) ?
|
||||
layerm->region()->config.solid_infill_extruder :
|
||||
layerm->region()->config.infill_extruder,
|
||||
layerm->region()->config().solid_infill_extruder :
|
||||
layerm->region()->config().infill_extruder,
|
||||
1)]);
|
||||
}
|
||||
}
|
||||
|
@ -1828,8 +1828,8 @@ void _3DScene::_load_print_object_toolpaths(
|
|||
extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
|
||||
*vols[ctxt.volume_idx(
|
||||
(extrusion_entity->role() == erSupportMaterial) ?
|
||||
support_layer->object()->config.support_material_extruder :
|
||||
support_layer->object()->config.support_material_interface_extruder,
|
||||
support_layer->object()->config().support_material_extruder :
|
||||
support_layer->object()->config().support_material_interface_extruder,
|
||||
2)]);
|
||||
}
|
||||
}
|
||||
|
@ -1877,7 +1877,7 @@ void _3DScene::_load_wipe_tower_toolpaths(
|
|||
const std::vector<std::string> &tool_colors_str,
|
||||
bool use_VBOs)
|
||||
{
|
||||
if (print->m_wipe_tower_tool_changes.empty())
|
||||
if (print->wipe_tower_data().tool_changes.empty())
|
||||
return;
|
||||
|
||||
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) {
|
||||
return priming.empty() ?
|
||||
((idx == print->m_wipe_tower_tool_changes.size()) ? final : print->m_wipe_tower_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 == print->wipe_tower_data().tool_changes.size()) ? final : print->wipe_tower_data().tool_changes[idx]) :
|
||||
((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> final;
|
||||
|
@ -1911,15 +1911,15 @@ void _3DScene::_load_wipe_tower_toolpaths(
|
|||
|
||||
ctxt.print = print;
|
||||
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
||||
if (print->m_wipe_tower_priming)
|
||||
ctxt.priming.emplace_back(*print->m_wipe_tower_priming.get());
|
||||
if (print->m_wipe_tower_final_purge)
|
||||
ctxt.final.emplace_back(*print->m_wipe_tower_final_purge.get());
|
||||
if (print->wipe_tower_data().priming != nullptr)
|
||||
ctxt.priming.emplace_back(*print->wipe_tower_data().priming);
|
||||
if (print->wipe_tower_data().final_purge)
|
||||
ctxt.final.emplace_back(*print->wipe_tower_data().final_purge);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
|
||||
|
||||
//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));
|
||||
tbb::spin_mutex new_volume_mutex;
|
||||
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();
|
||||
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
|
||||
return;
|
||||
|
||||
// adds objects' volumes
|
||||
unsigned int object_id = 0;
|
||||
for (PrintObject* obj : print.objects)
|
||||
for (PrintObject* obj : print.objects())
|
||||
{
|
||||
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
|
||||
coordf_t max_z = print.objects[0]->model_object()->get_model()->bounding_box().max.z;
|
||||
const PrintConfig& config = print.config;
|
||||
coordf_t max_z = print.objects().front()->model_object()->get_model()->bounding_box().max.z;
|
||||
const PrintConfig& config = print.config();
|
||||
unsigned int extruders_count = config.nozzle_diameter.size();
|
||||
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);
|
||||
|
|
|
@ -31,7 +31,7 @@ _constant()
|
|||
// owned by Print, no constructor/destructor
|
||||
|
||||
Ref<StaticPrintConfig> config()
|
||||
%code%{ RETVAL = &THIS->config; %};
|
||||
%code%{ RETVAL = &THIS->config(); %};
|
||||
Ref<Print> print();
|
||||
|
||||
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
|
||||
|
||||
int region_count()
|
||||
%code%{ RETVAL = THIS->print()->regions.size(); %};
|
||||
%code%{ RETVAL = THIS->print()->regions().size(); %};
|
||||
|
||||
Ref<Print> print();
|
||||
Ref<ModelObject> model_object();
|
||||
Ref<StaticPrintConfig> config()
|
||||
%code%{ RETVAL = &THIS->config; %};
|
||||
%code%{ RETVAL = &THIS->config(); %};
|
||||
Points copies();
|
||||
t_layer_height_ranges layer_height_ranges()
|
||||
%code%{ RETVAL = THIS->layer_height_ranges; %};
|
||||
|
@ -95,32 +95,41 @@ _constant()
|
|||
~Print();
|
||||
|
||||
Ref<StaticPrintConfig> config()
|
||||
%code%{ RETVAL = &THIS->config; %};
|
||||
%code%{ RETVAL = &THIS->config(); %};
|
||||
Ref<PlaceholderParser> placeholder_parser()
|
||||
%code%{ RETVAL = &THIS->placeholder_parser; %};
|
||||
%code%{ RETVAL = &THIS->placeholder_parser(); %};
|
||||
Ref<ExtrusionEntityCollection> skirt()
|
||||
%code%{ RETVAL = &THIS->skirt; %};
|
||||
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->skirt()); %};
|
||||
Ref<ExtrusionEntityCollection> brim()
|
||||
%code%{ RETVAL = &THIS->brim; %};
|
||||
%code%{ RETVAL = const_cast<ExtrusionEntityCollection*>(&THIS->brim()); %};
|
||||
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()
|
||||
%code%{ RETVAL = &THIS->objects; %};
|
||||
%code%{ RETVAL = const_cast<PrintObjectPtrs*>(&THIS->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 reload_object(int idx);
|
||||
bool reload_model_instances();
|
||||
size_t object_count()
|
||||
%code%{ RETVAL = THIS->objects.size(); %};
|
||||
%code%{ RETVAL = THIS->objects().size(); %};
|
||||
|
||||
PrintRegionPtrs* regions()
|
||||
%code%{ RETVAL = &THIS->regions; %};
|
||||
Ref<PrintRegion> get_region(int idx);
|
||||
Ref<PrintRegion> add_region();
|
||||
%code%{ RETVAL = const_cast<PrintRegionPtrs*>(&THIS->regions()); %};
|
||||
Ref<PrintRegion> get_region(int idx)
|
||||
%code%{ RETVAL = THIS->regions()[idx]; %};
|
||||
size_t region_count()
|
||||
%code%{ RETVAL = THIS->regions.size(); %};
|
||||
%code%{ RETVAL = THIS->regions().size(); %};
|
||||
|
||||
bool step_done(PrintStep step)
|
||||
%code%{ RETVAL = THIS->is_step_done(step); %};
|
||||
|
@ -130,7 +139,7 @@ _constant()
|
|||
SV* filament_stats()
|
||||
%code%{
|
||||
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
|
||||
std::ostringstream ss;
|
||||
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