|
@@ -1,4 +1,3 @@
|
|
|
-#ifndef SLIC3RXS
|
|
|
#include "PrintGCode.hpp"
|
|
|
#include "PrintConfig.hpp"
|
|
|
|
|
@@ -9,12 +8,6 @@ namespace Slic3r {
|
|
|
void
|
|
|
PrintGCode::output()
|
|
|
{
|
|
|
- auto& gcodegen {this->_gcodegen};
|
|
|
- auto& fh {this->fh};
|
|
|
- auto& print {this->_print};
|
|
|
- const auto& config {this->config};
|
|
|
- const auto extruders {print.extruders()};
|
|
|
-
|
|
|
// Write information about the generator.
|
|
|
time_t rawtime; tm * timeinfo;
|
|
|
time(&rawtime);
|
|
@@ -25,16 +18,16 @@ PrintGCode::output()
|
|
|
fh << "; Git Commit: " << BUILD_COMMIT << "\n\n";
|
|
|
|
|
|
// Writes notes (content of all Settings tabs -> Notes)
|
|
|
- fh << gcodegen.notes();
|
|
|
+ fh << _gcodegen.notes();
|
|
|
|
|
|
// Write some terse information on the slicing parameters.
|
|
|
- auto& first_object {*(this->objects.at(0))};
|
|
|
- auto layer_height {first_object.config.layer_height.getFloat()};
|
|
|
+ PrintObject& first_object { *this->objects.at(0) };
|
|
|
+ const auto layer_height = first_object.config.layer_height.getFloat();
|
|
|
|
|
|
- for (auto* region : print.regions) {
|
|
|
+ for (auto* region : _print.regions) {
|
|
|
{
|
|
|
- auto flow {region->flow(frExternalPerimeter, layer_height, false, false, -1, first_object)};
|
|
|
- auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("external_perimeter_speed")};
|
|
|
+ const Flow flow { region->flow(frExternalPerimeter, layer_height, false, false, -1, first_object) };
|
|
|
+ auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("external_perimeter_speed");
|
|
|
if (config.max_volumetric_speed.getInt() > 0)
|
|
|
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
|
|
fh << "; external perimeters extrusion width = ";
|
|
@@ -42,8 +35,8 @@ PrintGCode::output()
|
|
|
fh << "(" << vol_speed << "mm^3/s)\n";
|
|
|
}
|
|
|
{
|
|
|
- auto flow {region->flow(frPerimeter, layer_height, false, false, -1, first_object)};
|
|
|
- auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("perimeter_speed")};
|
|
|
+ const Flow flow { region->flow(frPerimeter, layer_height, false, false, -1, first_object) };
|
|
|
+ auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("perimeter_speed");
|
|
|
if (config.max_volumetric_speed.getInt() > 0)
|
|
|
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
|
|
fh << "; perimeters extrusion width = ";
|
|
@@ -51,8 +44,8 @@ PrintGCode::output()
|
|
|
fh << "(" << vol_speed << "mm^3/s)\n";
|
|
|
}
|
|
|
{
|
|
|
- auto flow {region->flow(frInfill, layer_height, false, false, -1, first_object)};
|
|
|
- auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("infill_speed")};
|
|
|
+ const Flow flow { region->flow(frInfill, layer_height, false, false, -1, first_object) };
|
|
|
+ auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("infill_speed");
|
|
|
if (config.max_volumetric_speed.getInt() > 0)
|
|
|
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
|
|
fh << "; infill extrusion width = ";
|
|
@@ -60,8 +53,8 @@ PrintGCode::output()
|
|
|
fh << "(" << vol_speed << "mm^3/s)\n";
|
|
|
}
|
|
|
{
|
|
|
- auto flow {region->flow(frSolidInfill, layer_height, false, false, -1, first_object)};
|
|
|
- auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("solid_infill_speed")};
|
|
|
+ const Flow flow { region->flow(frSolidInfill, layer_height, false, false, -1, first_object) };
|
|
|
+ auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("solid_infill_speed");
|
|
|
if (config.max_volumetric_speed.getInt() > 0)
|
|
|
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
|
|
fh << "; solid infill extrusion width = ";
|
|
@@ -69,26 +62,26 @@ PrintGCode::output()
|
|
|
fh << "(" << vol_speed << "mm^3/s)\n";
|
|
|
}
|
|
|
{
|
|
|
- auto flow {region->flow(frTopSolidInfill, layer_height, false, false, -1, first_object)};
|
|
|
- auto vol_speed {flow.mm3_per_mm() * region->config.get_abs_value("top_solid_infill_speed")};
|
|
|
+ const Flow flow { region->flow(frTopSolidInfill, layer_height, false, false, -1, first_object) };
|
|
|
+ auto vol_speed = flow.mm3_per_mm() * region->config.get_abs_value("top_solid_infill_speed");
|
|
|
if (config.max_volumetric_speed.getInt() > 0)
|
|
|
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
|
|
fh << "; top solid infill extrusion width = ";
|
|
|
fh << std::fixed << std::setprecision(2) << flow.width << "mm ";
|
|
|
fh << "(" << vol_speed << "mm^3/s)\n";
|
|
|
}
|
|
|
- if (print.has_support_material()) {
|
|
|
- auto flow {first_object._support_material_flow()};
|
|
|
- auto vol_speed {flow.mm3_per_mm() * first_object.config.get_abs_value("support_material_speed")};
|
|
|
+ if (_print.has_support_material()) {
|
|
|
+ const Flow flow { first_object._support_material_flow() };
|
|
|
+ auto vol_speed = flow.mm3_per_mm() * first_object.config.get_abs_value("support_material_speed");
|
|
|
if (config.max_volumetric_speed.getInt() > 0)
|
|
|
vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
|
|
fh << "; support material extrusion width = ";
|
|
|
fh << std::fixed << std::setprecision(2) << flow.width << "mm ";
|
|
|
fh << "(" << vol_speed << "mm^3/s)\n";
|
|
|
}
|
|
|
- if (print.config.first_layer_extrusion_width.getFloat() > 0) {
|
|
|
- auto flow {region->flow(frPerimeter, layer_height, false, false, -1, first_object)};
|
|
|
-// auto vol_speed {flow.mm3_per_mm() * print.config.get_abs_value("first_layer_speed")};
|
|
|
+ if (_print.config.first_layer_extrusion_width.getFloat() > 0) {
|
|
|
+ const Flow flow { region->flow(frPerimeter, layer_height, false, false, -1, first_object) };
|
|
|
+// auto vol_speed = flow.mm3_per_mm() * _print.config.get_abs_value("first_layer_speed");
|
|
|
// if (config.max_volumetric_speed.getInt() > 0)
|
|
|
// vol_speed = std::min(vol_speed, config.max_volumetric_speed.getFloat());
|
|
|
fh << "; first layer extrusion width = ";
|
|
@@ -99,29 +92,29 @@ PrintGCode::output()
|
|
|
fh << std::endl;
|
|
|
}
|
|
|
// Prepare the helper object for replacing placeholders in custom G-Code and output filename
|
|
|
- print.placeholder_parser.update_timestamp();
|
|
|
+ _print.placeholder_parser.update_timestamp();
|
|
|
|
|
|
// GCode sets this automatically when change_layer() is called, but needed for skirt/brim as well
|
|
|
- gcodegen.first_layer = true;
|
|
|
+ _gcodegen.first_layer = true;
|
|
|
|
|
|
// disable fan
|
|
|
if (config.cooling.getBool() && config.disable_fan_first_layers.getInt() > 0) {
|
|
|
- fh << gcodegen.writer.set_fan(0,1) << "\n";
|
|
|
+ fh << _gcodegen.writer.set_fan(0,1) << "\n";
|
|
|
}
|
|
|
|
|
|
// set bed temperature
|
|
|
- auto temp{config.first_layer_bed_temperature.getFloat()};
|
|
|
+ const auto temp = config.first_layer_bed_temperature.getFloat();
|
|
|
if (config.has_heatbed && temp > 0 && std::regex_search(config.start_gcode.getString(), bed_temp_regex)) {
|
|
|
- fh << gcodegen.writer.set_bed_temperature(temp, 1);
|
|
|
+ fh << _gcodegen.writer.set_bed_temperature(temp, 1);
|
|
|
}
|
|
|
|
|
|
// Set extruder(s) temperature before and after start gcode.
|
|
|
- auto include_start_extruder_temp {!std::regex_search(config.start_gcode.getString(), ex_temp_regex)};
|
|
|
+ auto include_start_extruder_temp = !std::regex_search(config.start_gcode.getString(), ex_temp_regex);
|
|
|
for(const auto& start_gcode : config.start_filament_gcode.values) {
|
|
|
include_start_extruder_temp = include_start_extruder_temp && !std::regex_search(start_gcode, ex_temp_regex);
|
|
|
}
|
|
|
|
|
|
- auto include_end_extruder_temp {!std::regex_search(config.end_gcode.getString(), ex_temp_regex)};
|
|
|
+ auto include_end_extruder_temp = !std::regex_search(config.end_gcode.getString(), ex_temp_regex);
|
|
|
for(const auto& end_gcode : config.end_filament_gcode.values) {
|
|
|
include_end_extruder_temp = include_end_extruder_temp && !std::regex_search(end_gcode, ex_temp_regex);
|
|
|
}
|
|
@@ -129,12 +122,12 @@ PrintGCode::output()
|
|
|
if (include_start_extruder_temp) this->_print_first_layer_temperature(0);
|
|
|
|
|
|
// Apply gcode math to start gcode
|
|
|
- fh << apply_math(gcodegen.placeholder_parser->process(config.start_gcode.value));
|
|
|
+ fh << apply_math(_gcodegen.placeholder_parser->process(config.start_gcode.value));
|
|
|
{
|
|
|
- auto filament_extruder {0U};
|
|
|
+ auto filament_extruder = 0U;
|
|
|
for(const auto& start_gcode : config.start_filament_gcode.values) {
|
|
|
- gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++);
|
|
|
- fh << apply_math(gcodegen.placeholder_parser->process(start_gcode));
|
|
|
+ _gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++);
|
|
|
+ fh << apply_math(_gcodegen.placeholder_parser->process(start_gcode));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -142,7 +135,7 @@ PrintGCode::output()
|
|
|
|
|
|
|
|
|
// Set other general things (preamble)
|
|
|
- fh << gcodegen.preamble();
|
|
|
+ fh << _gcodegen.preamble();
|
|
|
|
|
|
// initialize motion planner for object-to-object travel moves
|
|
|
if (config.avoid_crossing_perimeters.getBool()) {
|
|
@@ -153,7 +146,7 @@ PrintGCode::output()
|
|
|
Polygons polygons {};
|
|
|
// Add polygons that aren't just thin walls.
|
|
|
for (auto layer : object->layers) {
|
|
|
- const auto& slice {ExPolygons(layer->slices)};
|
|
|
+ const ExPolygons& slice { layer->slices };
|
|
|
std::for_each(slice.cbegin(), slice.cend(), [&polygons] (const ExPolygon& a) { polygons.emplace_back(a.contour); });
|
|
|
}
|
|
|
|
|
@@ -166,39 +159,70 @@ PrintGCode::output()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- gcodegen.avoid_crossing_perimeters.init_external_mp(union_ex(islands_p));
|
|
|
+ _gcodegen.avoid_crossing_perimeters.init_external_mp(union_ex(islands_p));
|
|
|
}
|
|
|
+
|
|
|
+ const auto extruders = _print.extruders();
|
|
|
|
|
|
// Calculate wiping points if needed.
|
|
|
if (config.ooze_prevention && extruders.size() > 1) {
|
|
|
+ /*
|
|
|
+ TODO: PORT THIS!
|
|
|
+ my @skirt_points = map @$_, map @$_, @{$self->print->skirt};
|
|
|
+ if (@skirt_points) {
|
|
|
+ my $outer_skirt = convex_hull(\@skirt_points);
|
|
|
+ my @skirts = ();
|
|
|
+ foreach my $extruder_id (@extruders) {
|
|
|
+ my $extruder_offset = $self->config->get_at('extruder_offset', $extruder_id);
|
|
|
+ push @skirts, my $s = $outer_skirt->clone;
|
|
|
+ $s->translate(-scale($extruder_offset->x), -scale($extruder_offset->y)); #)
|
|
|
+ }
|
|
|
+ my $convex_hull = convex_hull([ map @$_, @skirts ]);
|
|
|
+
|
|
|
+ $gcodegen->ooze_prevention->set_enable(1);
|
|
|
+ $gcodegen->ooze_prevention->set_standby_points(
|
|
|
+ [ map @{$_->equally_spaced_points(scale 10)}, @{offset([$convex_hull], scale 3)} ]
|
|
|
+ );
|
|
|
+
|
|
|
+ if (0) {
|
|
|
+ require "Slic3r/SVG.pm";
|
|
|
+ Slic3r::SVG::output(
|
|
|
+ "ooze_prevention.svg",
|
|
|
+ red_polygons => \@skirts,
|
|
|
+ polygons => [$outer_skirt],
|
|
|
+ points => $gcodegen->ooze_prevention->standby_points,
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ */
|
|
|
}
|
|
|
|
|
|
// Set initial extruder only after custom start gcode
|
|
|
- fh << gcodegen.set_extruder(*(extruders.begin()));
|
|
|
+ fh << _gcodegen.set_extruder( *(extruders.begin()) );
|
|
|
|
|
|
// Do all objects for each layer.
|
|
|
|
|
|
if (config.complete_objects) {
|
|
|
// print objects from the smallest to the tallest to avoid collisions
|
|
|
// when moving onto next object starting point
|
|
|
- std::sort(print.objects.begin(), print.objects.end(), [] (const PrintObject* a, const PrintObject* b) {
|
|
|
+ std::sort(_print.objects.begin(), _print.objects.end(), [] (const PrintObject* a, const PrintObject* b) {
|
|
|
return (a->config.sequential_print_priority < a->config.sequential_print_priority) || (a->size.z < b->size.z);
|
|
|
});
|
|
|
size_t finished_objects {0};
|
|
|
|
|
|
- for (size_t obj_idx {0}; obj_idx < print.objects.size(); ++obj_idx) {
|
|
|
+ for (size_t obj_idx {0}; obj_idx < _print.objects.size(); ++obj_idx) {
|
|
|
PrintObject& object {*(this->objects.at(obj_idx))};
|
|
|
for (const Point& copy : object._shifted_copies) {
|
|
|
if (finished_objects > 0) {
|
|
|
- gcodegen.set_origin(Pointf::new_unscale(copy));
|
|
|
- gcodegen.enable_cooling_markers = false;
|
|
|
- gcodegen.avoid_crossing_perimeters.use_external_mp_once = true;
|
|
|
- fh << gcodegen.retract();
|
|
|
- fh << gcodegen.travel_to(Point(0,0), erNone, "move to origin position for next object");
|
|
|
+ _gcodegen.set_origin(Pointf::new_unscale(copy));
|
|
|
+ _gcodegen.enable_cooling_markers = false;
|
|
|
+ _gcodegen.avoid_crossing_perimeters.use_external_mp_once = true;
|
|
|
+ fh << _gcodegen.retract();
|
|
|
+ fh << _gcodegen.travel_to(Point(0,0), erNone, "move to origin position for next object");
|
|
|
|
|
|
- gcodegen.enable_cooling_markers = true;
|
|
|
+ _gcodegen.enable_cooling_markers = true;
|
|
|
// disable motion planner when traveling to first object point
|
|
|
- gcodegen.avoid_crossing_perimeters.disable_once = true;
|
|
|
+ _gcodegen.avoid_crossing_perimeters.disable_once = true;
|
|
|
}
|
|
|
std::vector<Layer*> layers;
|
|
|
layers.reserve(object.layers.size() + object.support_layers.size());
|
|
@@ -218,7 +242,7 @@ PrintGCode::output()
|
|
|
config.has_heatbed &&
|
|
|
std::regex_search(config.between_objects_gcode.getString(), bed_temp_regex))
|
|
|
{
|
|
|
- fh << gcodegen.writer.set_bed_temperature(config.first_layer_bed_temperature);
|
|
|
+ fh << _gcodegen.writer.set_bed_temperature(config.first_layer_bed_temperature);
|
|
|
}
|
|
|
if (std::regex_search(config.between_objects_gcode.getString(), ex_temp_regex)) {
|
|
|
_print_first_layer_temperature(false);
|
|
@@ -242,8 +266,8 @@ PrintGCode::output()
|
|
|
std::vector<size_t> z;
|
|
|
z.reserve(100); // preallocate with 100 layers
|
|
|
std::map<coord_t, std::map<size_t, LayerPtrs > > layers {};
|
|
|
- for (size_t idx = 0U; idx < print.objects.size(); ++idx) {
|
|
|
- const auto& object {*(objects.at(idx))};
|
|
|
+ for (size_t idx = 0U; idx < _print.objects.size(); ++idx) {
|
|
|
+ const PrintObject& object { *objects.at(idx) };
|
|
|
// sort layers by Z into buckets
|
|
|
for (Layer* layer : object.layers) {
|
|
|
if (layers.count(scale_(layer->print_z)) == 0) { // initialize bucket if empty
|
|
@@ -272,47 +296,47 @@ PrintGCode::output()
|
|
|
this->process_layer(idx, layer, layer->object()->_shifted_copies);
|
|
|
}
|
|
|
}
|
|
|
- gcodegen.placeholder_parser->set("layer_z", unscale(print_z));
|
|
|
- gcodegen.placeholder_parser->set("layer_num", gcodegen.layer_index);
|
|
|
+ _gcodegen.placeholder_parser->set("layer_z", unscale(print_z));
|
|
|
+ _gcodegen.placeholder_parser->set("layer_num", _gcodegen.layer_index);
|
|
|
}
|
|
|
|
|
|
this->flush_filters();
|
|
|
}
|
|
|
|
|
|
// Write end commands to file.
|
|
|
- fh << gcodegen.retract(); // TODO: process this retract through PressureRegulator in order to discharge fully
|
|
|
+ fh << _gcodegen.retract(); // TODO: process this retract through PressureRegulator in order to discharge fully
|
|
|
|
|
|
{
|
|
|
- auto filament_extruder {0U};
|
|
|
+ auto filament_extruder = 0U;
|
|
|
for(const auto& end_gcode : config.end_filament_gcode.values) {
|
|
|
- gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++);
|
|
|
- fh << apply_math(gcodegen.placeholder_parser->process(end_gcode));
|
|
|
+ _gcodegen.placeholder_parser->set("filament_extruder_id", filament_extruder++);
|
|
|
+ fh << apply_math(_gcodegen.placeholder_parser->process(end_gcode));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- fh << apply_math(gcodegen.placeholder_parser->process(config.end_gcode));
|
|
|
+ fh << apply_math(_gcodegen.placeholder_parser->process(config.end_gcode));
|
|
|
|
|
|
// set bed temperature
|
|
|
if (config.has_heatbed && temp > 0 && std::regex_search(config.end_gcode.getString(), bed_temp_regex)) {
|
|
|
- fh << gcodegen.writer.set_bed_temperature(0, 0);
|
|
|
+ fh << _gcodegen.writer.set_bed_temperature(0, 0);
|
|
|
}
|
|
|
|
|
|
// Get filament stats
|
|
|
- print.filament_stats.clear();
|
|
|
- print.total_used_filament = 0.0;
|
|
|
- print.total_extruded_volume = 0.0;
|
|
|
- print.total_weight = 0.0;
|
|
|
- print.total_cost = 0.0;
|
|
|
+ _print.filament_stats.clear();
|
|
|
+ _print.total_used_filament = 0.0;
|
|
|
+ _print.total_extruded_volume = 0.0;
|
|
|
+ _print.total_weight = 0.0;
|
|
|
+ _print.total_cost = 0.0;
|
|
|
|
|
|
|
|
|
- for (auto extruder_pair : gcodegen.writer.extruders) {
|
|
|
- const auto& extruder {extruder_pair.second};
|
|
|
- auto used_material {extruder.used_filament()};
|
|
|
- auto extruded_volume {extruder.extruded_volume()};
|
|
|
- auto material_weight {extruded_volume * extruder.filament_density() / 1000.0};
|
|
|
- auto material_cost { material_weight * (extruder.filament_cost() / 1000.0)};
|
|
|
+ for (auto extruder_pair : _gcodegen.writer.extruders) {
|
|
|
+ const Extruder& extruder { extruder_pair.second };
|
|
|
+ const auto used_material = extruder.used_filament();
|
|
|
+ const auto extruded_volume = extruder.extruded_volume();
|
|
|
+ const auto material_weight = extruded_volume * extruder.filament_density() / 1000.0;
|
|
|
+ const auto material_cost = material_weight * (extruder.filament_cost() / 1000.0);
|
|
|
|
|
|
- print.filament_stats[extruder.id] = used_material;
|
|
|
+ _print.filament_stats[extruder.id] = used_material;
|
|
|
|
|
|
fh << "; material used = ";
|
|
|
fh << std::fixed << std::setprecision(2) << used_material << "mm ";
|
|
@@ -321,28 +345,28 @@ PrintGCode::output()
|
|
|
<< used_material << "cm3)\n";
|
|
|
|
|
|
if (material_weight > 0) {
|
|
|
- print.total_weight += material_weight;
|
|
|
+ _print.total_weight += material_weight;
|
|
|
fh << "; material used = "
|
|
|
<< std::fixed << std::setprecision(2) << material_weight << "g\n";
|
|
|
if (material_cost > 0) {
|
|
|
- print.total_cost += material_cost;
|
|
|
+ _print.total_cost += material_cost;
|
|
|
fh << "; material cost = "
|
|
|
<< std::fixed << std::setprecision(2) << material_weight << "g\n";
|
|
|
}
|
|
|
}
|
|
|
- print.total_used_filament += used_material;
|
|
|
- print.total_extruded_volume += extruded_volume;
|
|
|
+ _print.total_used_filament += used_material;
|
|
|
+ _print.total_extruded_volume += extruded_volume;
|
|
|
}
|
|
|
fh << "; total filament cost = "
|
|
|
- << std::fixed << std::setprecision(2) << print.total_cost << "\n";
|
|
|
+ << std::fixed << std::setprecision(2) << _print.total_cost << "\n";
|
|
|
|
|
|
// Append full config
|
|
|
fh << std::endl;
|
|
|
|
|
|
// print config
|
|
|
- _print_config(print.config);
|
|
|
- _print_config(print.default_object_config);
|
|
|
- _print_config(print.default_region_config);
|
|
|
+ _print_config(_print.config);
|
|
|
+ _print_config(_print.default_object_config);
|
|
|
+ _print_config(_print.default_region_config);
|
|
|
}
|
|
|
|
|
|
std::string
|
|
@@ -355,17 +379,14 @@ void
|
|
|
PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
|
|
{
|
|
|
std::string gcode {""};
|
|
|
- auto& gcodegen {this->_gcodegen};
|
|
|
- const auto& print {this->_print};
|
|
|
- const auto& config {this->config};
|
|
|
|
|
|
- const auto& obj {*(layer->object())};
|
|
|
- gcodegen.config.apply(obj.config, true);
|
|
|
+ const PrintObject& obj { *layer->object() };
|
|
|
+ _gcodegen.config.apply(obj.config, true);
|
|
|
|
|
|
// check for usage of spiralvase logic.
|
|
|
this->_spiral_vase.enable = (
|
|
|
layer->id() > 0
|
|
|
- && (print.config.skirts == 0 || (layer->id() >= print.config.skirt_height && !print.has_infinite_skirt()))
|
|
|
+ && (_print.config.skirts == 0 || (layer->id() >= _print.config.skirt_height && !_print.has_infinite_skirt()))
|
|
|
&& std::find_if(layer->regions.cbegin(), layer->regions.cend(), [layer] (const LayerRegion* l)
|
|
|
{ return l->region()->config.bottom_solid_layers > layer->id()
|
|
|
|| l->perimeters.items_count() > 1
|
|
@@ -382,9 +403,9 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
|
|
{
|
|
|
// get the minimum cross-section used in the layer.
|
|
|
std::vector<double> mm3_per_mm;
|
|
|
- for (auto region_id = 0U; region_id < print.regions.size(); ++region_id) {
|
|
|
- const auto& region {print.regions.at(region_id)};
|
|
|
- const auto& layerm {layer->get_region(region_id)};
|
|
|
+ for (auto region_id = 0U; region_id < _print.regions.size(); ++region_id) {
|
|
|
+ const PrintRegion* region = _print.get_region(region_id);
|
|
|
+ const LayerRegion* layerm = layer->get_region(region_id);
|
|
|
|
|
|
if (!(region->config.get_abs_value("perimeter_speed") > 0 &&
|
|
|
region->config.get_abs_value("small_perimeter_speed") > 0 &&
|
|
@@ -417,53 +438,53 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
|
|
// TODO make the definition of "too thin" based on a config somewhere
|
|
|
mm3_per_mm.erase(std::remove_if(mm3_per_mm.begin(), mm3_per_mm.end(), [] (const double& vol) { return vol <= 0.01;} ), mm3_per_mm.end());
|
|
|
if (mm3_per_mm.size() > 0) {
|
|
|
- const auto min_mm3_per_mm {*(std::min_element(mm3_per_mm.begin(), mm3_per_mm.end()))};
|
|
|
+ const double min_mm3_per_mm { *(std::min_element(mm3_per_mm.begin(), mm3_per_mm.end())) };
|
|
|
// In order to honor max_print_speed we need to find a target volumetric
|
|
|
- // speed that we can use throughout the print. So we define this target
|
|
|
+ // speed that we can use throughout the _print. So we define this target
|
|
|
// volumetric speed as the volumetric speed produced by printing the
|
|
|
// smallest cross-section at the maximum speed: any larger cross-section
|
|
|
// will need slower feedrates.
|
|
|
- auto volumetric_speed {min_mm3_per_mm * config.max_print_speed};
|
|
|
+ double volumetric_speed { min_mm3_per_mm * config.max_print_speed };
|
|
|
if (config.max_volumetric_speed > 0) {
|
|
|
volumetric_speed = std::min(volumetric_speed, config.max_volumetric_speed.getFloat());
|
|
|
}
|
|
|
- gcodegen.volumetric_speed = volumetric_speed;
|
|
|
+ _gcodegen.volumetric_speed = volumetric_speed;
|
|
|
}
|
|
|
}
|
|
|
// set the second layer + temp
|
|
|
if (!this->_second_layer_things_done && layer->id() == 1) {
|
|
|
- for (const auto& extruder_ref : gcodegen.writer.extruders) {
|
|
|
- const auto& extruder { extruder_ref.second };
|
|
|
- auto temp { config.temperature.get_at(extruder.id) };
|
|
|
+ for (const auto& extruder_ref : _gcodegen.writer.extruders) {
|
|
|
+ const Extruder& extruder { extruder_ref.second };
|
|
|
+ auto temp = config.temperature.get_at(extruder.id);
|
|
|
|
|
|
if (temp > 0 && temp != config.first_layer_temperature.get_at(extruder.id) )
|
|
|
- gcode += gcodegen.writer.set_temperature(temp, 0, extruder.id);
|
|
|
+ gcode += _gcodegen.writer.set_temperature(temp, 0, extruder.id);
|
|
|
|
|
|
}
|
|
|
- if (config.has_heatbed && print.config.first_layer_bed_temperature > 0 && print.config.bed_temperature != print.config.first_layer_bed_temperature) {
|
|
|
- gcode += gcodegen.writer.set_bed_temperature(print.config.bed_temperature);
|
|
|
+ if (config.has_heatbed && _print.config.first_layer_bed_temperature > 0 && _print.config.bed_temperature != _print.config.first_layer_bed_temperature) {
|
|
|
+ gcode += _gcodegen.writer.set_bed_temperature(_print.config.bed_temperature);
|
|
|
}
|
|
|
this->_second_layer_things_done = true;
|
|
|
}
|
|
|
|
|
|
// set new layer - this will change Z and force a retraction if retract_layer_change is enabled
|
|
|
- if (print.config.before_layer_gcode.getString().size() > 0) {
|
|
|
- auto pp {*(gcodegen.placeholder_parser)};
|
|
|
- pp.set("layer_num", gcodegen.layer_index);
|
|
|
+ if (_print.config.before_layer_gcode.getString().size() > 0) {
|
|
|
+ PlaceholderParser pp { *_gcodegen.placeholder_parser };
|
|
|
+ pp.set("layer_num", _gcodegen.layer_index);
|
|
|
pp.set("layer_z", layer->print_z);
|
|
|
- pp.set("current_retraction", gcodegen.writer.extruder()->retracted);
|
|
|
+ pp.set("current_retraction", _gcodegen.writer.extruder()->retracted);
|
|
|
|
|
|
- gcode += apply_math(pp.process(print.config.before_layer_gcode.getString()));
|
|
|
+ gcode += apply_math(pp.process(_print.config.before_layer_gcode.getString()));
|
|
|
gcode += "\n";
|
|
|
}
|
|
|
- gcode += gcodegen.change_layer(*layer);
|
|
|
- if (print.config.layer_gcode.getString().size() > 0) {
|
|
|
- auto pp {*(gcodegen.placeholder_parser)};
|
|
|
- pp.set("layer_num", gcodegen.layer_index);
|
|
|
+ gcode += _gcodegen.change_layer(*layer);
|
|
|
+ if (_print.config.layer_gcode.getString().size() > 0) {
|
|
|
+ PlaceholderParser pp { *_gcodegen.placeholder_parser };
|
|
|
+ pp.set("layer_num", _gcodegen.layer_index);
|
|
|
pp.set("layer_z", layer->print_z);
|
|
|
- pp.set("current_retraction", gcodegen.writer.extruder()->retracted);
|
|
|
+ pp.set("current_retraction", _gcodegen.writer.extruder()->retracted);
|
|
|
|
|
|
- gcode += apply_math(pp.process(print.config.layer_gcode.getString()));
|
|
|
+ gcode += apply_math(pp.process(_print.config.layer_gcode.getString()));
|
|
|
gcode += "\n";
|
|
|
}
|
|
|
|
|
@@ -471,73 +492,73 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
|
|
// extrude skirt along raft layers and normal obj layers
|
|
|
// (not along interlaced support material layers)
|
|
|
if (layer->id() < static_cast<size_t>(obj.config.raft_layers)
|
|
|
- || ((print.has_infinite_skirt() || _skirt_done.size() == 0 || (_skirt_done.rbegin())->first < print.config.skirt_height)
|
|
|
+ || ((_print.has_infinite_skirt() || _skirt_done.size() == 0 || (_skirt_done.rbegin())->first < _print.config.skirt_height)
|
|
|
&& _skirt_done.count(scale_(layer->print_z)) == 0
|
|
|
&& typeid(layer) != typeid(SupportLayer*)) ) {
|
|
|
|
|
|
|
|
|
- gcodegen.set_origin(Pointf(0,0));
|
|
|
- gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
|
|
+ _gcodegen.set_origin(Pointf(0,0));
|
|
|
+ _gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
|
|
|
|
|
/// data load
|
|
|
std::vector<size_t> extruder_ids;
|
|
|
- extruder_ids.reserve(gcodegen.writer.extruders.size());
|
|
|
- std::transform(gcodegen.writer.extruders.cbegin(), gcodegen.writer.extruders.cend(), std::back_inserter(extruder_ids),
|
|
|
+ extruder_ids.reserve(_gcodegen.writer.extruders.size());
|
|
|
+ std::transform(_gcodegen.writer.extruders.cbegin(), _gcodegen.writer.extruders.cend(), std::back_inserter(extruder_ids),
|
|
|
[] (const std::pair<unsigned int, Extruder>& z) -> std::size_t { return z.second.id; } );
|
|
|
- gcode += gcodegen.set_extruder(extruder_ids.at(0));
|
|
|
+ gcode += _gcodegen.set_extruder(extruder_ids.at(0));
|
|
|
|
|
|
// skip skirt if a large brim
|
|
|
- if (print.has_infinite_skirt() || layer->id() < static_cast<size_t>(print.config.skirt_height)) {
|
|
|
- const auto& skirt_flow {print.skirt_flow()};
|
|
|
+ if (_print.has_infinite_skirt() || layer->id() < static_cast<size_t>(_print.config.skirt_height)) {
|
|
|
+ const Flow skirt_flow { _print.skirt_flow() };
|
|
|
|
|
|
// distribute skirt loops across all extruders in layer 0
|
|
|
- auto skirt_loops {print.skirt.flatten().entities};
|
|
|
+ const auto skirt_loops = _print.skirt.flatten().entities;
|
|
|
for (size_t i = 0; i < skirt_loops.size(); ++i) {
|
|
|
|
|
|
// when printing layers > 0 ignore 'min_skirt_length' and
|
|
|
// just use the 'skirts' setting; also just use the current extruder
|
|
|
- if (layer->id() > 0 && i >= static_cast<size_t>(print.config.skirts)) break;
|
|
|
- const auto extruder_id { extruder_ids.at((i / extruder_ids.size()) % extruder_ids.size()) };
|
|
|
+ if (layer->id() > 0 && i >= static_cast<size_t>(_print.config.skirts)) break;
|
|
|
+ const size_t extruder_id { extruder_ids.at((i / extruder_ids.size()) % extruder_ids.size()) };
|
|
|
if (layer->id() == 0)
|
|
|
- gcode += gcodegen.set_extruder(extruder_id);
|
|
|
+ gcode += _gcodegen.set_extruder(extruder_id);
|
|
|
|
|
|
// adjust flow according to layer height
|
|
|
- auto& loop {*(dynamic_cast<ExtrusionLoop*>(skirt_loops.at(i)))};
|
|
|
+ auto& loop = *dynamic_cast<ExtrusionLoop*>(skirt_loops.at(i));
|
|
|
{
|
|
|
Flow layer_skirt_flow(skirt_flow);
|
|
|
layer_skirt_flow.height = layer->height;
|
|
|
|
|
|
- auto mm3_per_mm {layer_skirt_flow.mm3_per_mm()};
|
|
|
+ const auto mm3_per_mm = layer_skirt_flow.mm3_per_mm();
|
|
|
|
|
|
for (auto& path : loop.paths) {
|
|
|
path.height = layer->height;
|
|
|
path.mm3_per_mm = mm3_per_mm;
|
|
|
}
|
|
|
}
|
|
|
- gcode += gcodegen.extrude(loop, "skirt", obj.config.support_material_speed);
|
|
|
+ gcode += _gcodegen.extrude(loop, "skirt", obj.config.support_material_speed);
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
this->_skirt_done[scale_(layer->print_z)] = true;
|
|
|
- gcodegen.avoid_crossing_perimeters.use_external_mp = false;
|
|
|
+ _gcodegen.avoid_crossing_perimeters.use_external_mp = false;
|
|
|
|
|
|
- if (layer->id() == 0) gcodegen.avoid_crossing_perimeters.disable_once = true;
|
|
|
+ if (layer->id() == 0) _gcodegen.avoid_crossing_perimeters.disable_once = true;
|
|
|
}
|
|
|
|
|
|
// extrude brim
|
|
|
if (this->_brim_done) {
|
|
|
- gcode += gcodegen.set_extruder(print.brim_extruder() - 1);
|
|
|
- gcodegen.set_origin(Pointf(0,0));
|
|
|
- gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
|
|
- for (const auto& b : print.brim.entities) {
|
|
|
- gcode += gcodegen.extrude(*b, "brim", obj.config.get_abs_value("support_material_speed"));
|
|
|
+ gcode += _gcodegen.set_extruder(_print.brim_extruder() - 1);
|
|
|
+ _gcodegen.set_origin(Pointf(0,0));
|
|
|
+ _gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
|
|
+ for (const auto& b : _print.brim.entities) {
|
|
|
+ gcode += _gcodegen.extrude(*b, "brim", obj.config.get_abs_value("support_material_speed"));
|
|
|
}
|
|
|
this->_brim_done = true;
|
|
|
- gcodegen.avoid_crossing_perimeters.use_external_mp = false;
|
|
|
+ _gcodegen.avoid_crossing_perimeters.use_external_mp = false;
|
|
|
|
|
|
// allow a straight travel move to the first object point
|
|
|
- gcodegen.avoid_crossing_perimeters.disable_once = true;
|
|
|
+ _gcodegen.avoid_crossing_perimeters.disable_once = true;
|
|
|
}
|
|
|
|
|
|
auto copy_idx = 0U;
|
|
@@ -548,10 +569,10 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
|
|
|
|
|
// when starting a new object, use the external motion planner for the first travel move
|
|
|
if (this->_last_obj_copy.first != copy && this->_last_obj_copy.second )
|
|
|
- gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
|
|
+ _gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
|
|
this->_last_obj_copy.first = copy;
|
|
|
this->_last_obj_copy.second = true;
|
|
|
- gcodegen.set_origin(Pointf::new_unscale(copy));
|
|
|
+ _gcodegen.set_origin(Pointf::new_unscale(copy));
|
|
|
|
|
|
// extrude support material before other things because it might use a lower Z
|
|
|
// and also because we avoid travelling on other things when printing it
|
|
@@ -559,17 +580,17 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
|
|
const SupportLayer* slayer = dynamic_cast<const SupportLayer*>(layer);
|
|
|
ExtrusionEntityCollection paths;
|
|
|
if (slayer->support_interface_fills.size() > 0) {
|
|
|
- gcode += gcodegen.set_extruder(obj.config.support_material_interface_extruder - 1);
|
|
|
- slayer->support_interface_fills.chained_path_from(gcodegen.last_pos(), &paths, false);
|
|
|
+ gcode += _gcodegen.set_extruder(obj.config.support_material_interface_extruder - 1);
|
|
|
+ slayer->support_interface_fills.chained_path_from(_gcodegen.last_pos(), &paths, false);
|
|
|
for (const auto& path : paths) {
|
|
|
- gcode += gcodegen.extrude(*path, "support material interface", obj.config.get_abs_value("support_material_interface_speed"));
|
|
|
+ gcode += _gcodegen.extrude(*path, "support material interface", obj.config.get_abs_value("support_material_interface_speed"));
|
|
|
}
|
|
|
}
|
|
|
if (slayer->support_fills.size() > 0) {
|
|
|
- gcode += gcodegen.set_extruder(obj.config.support_material_extruder - 1);
|
|
|
- slayer->support_fills.chained_path_from(gcodegen.last_pos(), &paths, false);
|
|
|
+ gcode += _gcodegen.set_extruder(obj.config.support_material_extruder - 1);
|
|
|
+ slayer->support_fills.chained_path_from(_gcodegen.last_pos(), &paths, false);
|
|
|
for (const auto& path : paths) {
|
|
|
- gcode += gcodegen.extrude(*path, "support material", obj.config.get_abs_value("support_material_speed"));
|
|
|
+ gcode += _gcodegen.extrude(*path, "support material", obj.config.get_abs_value("support_material_speed"));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -594,25 +615,25 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
|
|
// cache bounding boxes of layer slices
|
|
|
std::vector<BoundingBox> layer_slices_bb;
|
|
|
std::transform(layer->slices.cbegin(), layer->slices.cend(), std::back_inserter(layer_slices_bb), [] (const ExPolygon& s)-> BoundingBox { return s.bounding_box(); });
|
|
|
- auto point_inside_surface { [&layer_slices_bb, &layer] (size_t i, Point point) -> bool {
|
|
|
- const auto& bbox {layer_slices_bb.at(i)};
|
|
|
+ auto point_inside_surface = [&layer_slices_bb, &layer] (size_t i, Point point) -> bool {
|
|
|
+ const BoundingBox& bbox { layer_slices_bb.at(i) };
|
|
|
return bbox.contains(point) && layer->slices.at(i).contour.contains(point);
|
|
|
- }};
|
|
|
- const auto n_slices {layer->slices.size()};
|
|
|
+ };
|
|
|
+ const size_t n_slices { layer->slices.size() };
|
|
|
|
|
|
- for (auto region_id = 0U; region_id < print.regions.size(); ++region_id) {
|
|
|
+ for (auto region_id = 0U; region_id < _print.regions.size(); ++region_id) {
|
|
|
const LayerRegion* layerm;
|
|
|
try {
|
|
|
layerm = layer->get_region(region_id); // we promise to be good and not give this to anyone who will modify it
|
|
|
} catch (std::out_of_range &e) {
|
|
|
continue; // if no regions, bail;
|
|
|
}
|
|
|
- auto* region {print.get_region(region_id)};
|
|
|
+ const PrintRegion* region { _print.get_region(region_id) };
|
|
|
// process perimeters
|
|
|
{
|
|
|
auto extruder_id = region->config.perimeter_extruder-1;
|
|
|
// Casting away const just to avoid double dereferences
|
|
|
- for(auto* perimeter_coll : layerm->perimeters.flatten().entities) {
|
|
|
+ for(const auto* perimeter_coll : layerm->perimeters.flatten().entities) {
|
|
|
|
|
|
if(perimeter_coll->length() == 0) continue; // this shouldn't happen but first_point() would fail
|
|
|
|
|
@@ -654,10 +675,10 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
|
|
|
|
|
// tweak extruder ordering to save toolchanges
|
|
|
|
|
|
- auto last_extruder = gcodegen.writer.extruder()->id;
|
|
|
+ auto last_extruder = _gcodegen.writer.extruder()->id;
|
|
|
if (by_extruder.count(last_extruder)) {
|
|
|
for(auto &island : by_extruder[last_extruder]) {
|
|
|
- if (print.config.infill_first()) {
|
|
|
+ if (_print.config.infill_first()) {
|
|
|
gcode += this->_extrude_infill(std::get<1>(island.second));
|
|
|
gcode += this->_extrude_perimeters(std::get<0>(island.second));
|
|
|
} else {
|
|
@@ -668,9 +689,9 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
|
|
}
|
|
|
for(auto &pair : by_extruder) {
|
|
|
if(pair.first == last_extruder)continue;
|
|
|
- gcode += gcodegen.set_extruder(pair.first);
|
|
|
+ gcode += _gcodegen.set_extruder(pair.first);
|
|
|
for(auto &island : pair.second) {
|
|
|
- if (print.config.infill_first()) {
|
|
|
+ if (_print.config.infill_first()) {
|
|
|
gcode += this->_extrude_infill(std::get<1>(island.second));
|
|
|
gcode += this->_extrude_perimeters(std::get<0>(island.second));
|
|
|
} else {
|
|
@@ -733,16 +754,10 @@ PrintGCode::_extrude_infill(std::map<size_t,ExtrusionEntityCollection> &by_regio
|
|
|
void
|
|
|
PrintGCode::_print_first_layer_temperature(bool wait)
|
|
|
{
|
|
|
- auto& gcodegen {this->_gcodegen};
|
|
|
- auto& fh {this->fh};
|
|
|
- const auto& print {this->_print};
|
|
|
- const auto& config {this->config};
|
|
|
- const auto extruders {print.extruders()};
|
|
|
-
|
|
|
- for (auto& t : extruders) {
|
|
|
- auto temp { config.first_layer_temperature.get_at(t) };
|
|
|
+ for (auto& t : _print.extruders()) {
|
|
|
+ auto temp = config.first_layer_temperature.get_at(t);
|
|
|
if (config.ooze_prevention.value) temp += config.standby_temperature_delta.value;
|
|
|
- if (temp > 0) fh << gcodegen.writer.set_temperature(temp, wait, t);
|
|
|
+ if (temp > 0) fh << _gcodegen.writer.set_temperature(temp, wait, t);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -758,9 +773,9 @@ PrintGCode::_print_config(const ConfigBase& config)
|
|
|
|
|
|
PrintGCode::PrintGCode(Slic3r::Print& print, std::ostream& _fh) :
|
|
|
_print(print),
|
|
|
- config(print.config),
|
|
|
+ config(_print.config),
|
|
|
_gcodegen(Slic3r::GCode()),
|
|
|
- objects(print.objects),
|
|
|
+ objects(_print.objects),
|
|
|
fh(_fh),
|
|
|
_cooling_buffer(Slic3r::CoolingBuffer(this->_gcodegen)),
|
|
|
_spiral_vase(Slic3r::SpiralVase(this->config))
|
|
@@ -771,16 +786,16 @@ PrintGCode::PrintGCode(Slic3r::Print& print, std::ostream& _fh) :
|
|
|
} else {
|
|
|
layer_count = std::accumulate(objects.cbegin(), objects.cend(), layer_count, [](const size_t& ret, const PrintObject* obj){ return ret + obj->total_layer_count(); });
|
|
|
}
|
|
|
- _gcodegen.placeholder_parser = &(print.placeholder_parser); // initialize
|
|
|
+ _gcodegen.placeholder_parser = &(_print.placeholder_parser); // initialize
|
|
|
_gcodegen.layer_count = layer_count;
|
|
|
_gcodegen.enable_cooling_markers = true;
|
|
|
_gcodegen.apply_print_config(config);
|
|
|
|
|
|
if (config.spiral_vase) _spiral_vase.enable = true;
|
|
|
|
|
|
- auto extruders {print.extruders()};
|
|
|
+ const auto extruders = _print.extruders();
|
|
|
_gcodegen.set_extruders(extruders.cbegin(), extruders.cend());
|
|
|
}
|
|
|
|
|
|
} // namespace Slic3r
|
|
|
-#endif //SLIC3RXS
|
|
|
+
|