mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-16 16:25:57 +08:00
Implemented more of process_layer through skirt generation
This commit is contained in:
parent
f1f05c35de
commit
f1616ee295
@ -186,7 +186,7 @@ PrintGCode::output()
|
|||||||
p.emplace_back(obj->_shifted_copies.at(0));
|
p.emplace_back(obj->_shifted_copies.at(0));
|
||||||
|
|
||||||
std::vector<size_t> z(100); // preallocate with 100 layers
|
std::vector<size_t> z(100); // preallocate with 100 layers
|
||||||
std::map<size_t, LayerPtrs> layers {};
|
std::map<coordf_t, LayerPtrs> layers {};
|
||||||
for (size_t idx = 0U; idx < print.objects.size(); ++idx) {
|
for (size_t idx = 0U; idx < print.objects.size(); ++idx) {
|
||||||
const auto& object {*(objects.at(idx))};
|
const auto& object {*(objects.at(idx))};
|
||||||
// sort layers by Z into buckets
|
// sort layers by Z into buckets
|
||||||
@ -288,12 +288,154 @@ PrintGCode::process_layer(size_t idx, const Layer* layer, const Points& copies)
|
|||||||
{
|
{
|
||||||
std::string gcode {""};
|
std::string gcode {""};
|
||||||
auto& gcodegen {this->_gcodegen};
|
auto& gcodegen {this->_gcodegen};
|
||||||
|
const auto& print {this->_print};
|
||||||
|
const auto& config {this->config};
|
||||||
|
|
||||||
const auto& obj {*(layer->object())};
|
const auto& obj {*(layer->object())};
|
||||||
gcodegen.config.apply(obj.config, true);
|
gcodegen.config.apply(obj.config, true);
|
||||||
|
|
||||||
|
// check for usage of spiralvase logic.
|
||||||
|
|
||||||
|
|
||||||
|
// if using spiralvase, disable loop clipping.
|
||||||
|
|
||||||
|
// initialize autospeed.
|
||||||
|
{
|
||||||
|
// 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)};
|
||||||
|
|
||||||
|
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.emplace_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 &&
|
||||||
|
region->config.get_abs_value("gap_fill_speed") > 0)) // TODO: make this configurable?
|
||||||
|
{
|
||||||
|
mm3_per_mm.emplace_back(layerm->fills.min_mm3_per_mm());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (typeid(layer) == typeid(SupportLayer*)) {
|
||||||
|
const SupportLayer* slayer = dynamic_cast<const SupportLayer*>(layer);
|
||||||
|
if (!(obj.config.get_abs_value("support_material_speed") > 0 &&
|
||||||
|
obj.config.get_abs_value("support_material_interface_speed") > 0))
|
||||||
|
{
|
||||||
|
mm3_per_mm.emplace_back(slayer->support_fills.min_mm3_per_mm());
|
||||||
|
mm3_per_mm.emplace_back(slayer->support_interface_fills.min_mm3_per_mm());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore too-thin segments.
|
||||||
|
// 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()))};
|
||||||
|
// 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
|
||||||
|
// 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};
|
||||||
|
if (config.max_volumetric_speed > 0) {
|
||||||
|
volumetric_speed = std::min(volumetric_speed, config.max_volumetric_speed.getFloat());
|
||||||
|
}
|
||||||
|
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) };
|
||||||
|
|
||||||
|
if (temp > 0 && temp != config.first_layer_temperature.get_at(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);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
pp.set("layer_z", layer->print_z);
|
||||||
|
pp.set("current_retraction", gcodegen.writer.extruder()->retracted);
|
||||||
|
|
||||||
|
gcode += apply_math(pp.process(print.config.layer_gcode.getString()));
|
||||||
|
gcode += "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// extrude skirt along raft layers and normal obj layers
|
||||||
|
// (not along interlaced support material layers)
|
||||||
|
if ((print.has_infinite_skirt() || (_skirt_done.rbegin())->first < print.config.skirt_height)
|
||||||
|
&& typeid(layer) != typeid(SupportLayer*)
|
||||||
|
&& _skirt_done.count(layer->print_z) > 0
|
||||||
|
&& layer->id() < static_cast<size_t>(obj.config.raft_layers)) {
|
||||||
|
|
||||||
|
gcodegen.set_origin(Pointf(0,0));
|
||||||
|
gcodegen.avoid_crossing_perimeters.use_external_mp = true;
|
||||||
|
|
||||||
|
/// data load
|
||||||
|
std::vector<size_t> extruder_ids {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));
|
||||||
|
|
||||||
|
// 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()};
|
||||||
|
|
||||||
|
// distribute skirt loops across all extruders in layer 0
|
||||||
|
auto skirt_loops {print.skirt.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)
|
||||||
|
gcode += gcodegen.set_extruder(extruder_id);
|
||||||
|
|
||||||
|
// adjust flow according to layer height
|
||||||
|
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()};
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this->_skirt_done[layer->print_z] = true;
|
||||||
|
gcodegen.avoid_crossing_perimeters.use_external_mp = false;
|
||||||
|
|
||||||
|
if (layer->id() == 0) gcodegen.avoid_crossing_perimeters.disable_once = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extrude brim
|
||||||
|
|
||||||
|
// write the resulting gcode
|
||||||
fh << this->filter(gcode);
|
fh << this->filter(gcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,8 @@ private:
|
|||||||
// Slic3r::ArcFitting _arc_fitting;
|
// Slic3r::ArcFitting _arc_fitting;
|
||||||
// Slic3r::PressureRegulator _pressure_regulator;
|
// Slic3r::PressureRegulator _pressure_regulator;
|
||||||
|
|
||||||
size_t _skirt_done {0};
|
/// presence in the array indicates that the
|
||||||
|
std::map<double, bool> _skirt_done {};
|
||||||
bool _brim_done {false};
|
bool _brim_done {false};
|
||||||
bool _second_layer_things_done {false};
|
bool _second_layer_things_done {false};
|
||||||
std::string _last_obj_copy {""};
|
std::string _last_obj_copy {""};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user