mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-01 04:32:01 +08:00
Separate extrusions ordering and extrusions exporting into two for loops
This commit is contained in:
parent
fe1b8134d6
commit
17dc776109
@ -2462,39 +2462,44 @@ LayerResult GCodeGenerator::process_layer(
|
||||
}
|
||||
}
|
||||
|
||||
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
|
||||
for (unsigned int extruder_id : layer_tools.extruders)
|
||||
{
|
||||
gcode += (layer_tools.has_wipe_tower && m_wipe_tower) ?
|
||||
m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back()) :
|
||||
this->set_extruder(extruder_id, print_z);
|
||||
|
||||
// let analyzer tag generator aware of a role type change
|
||||
if (layer_tools.has_wipe_tower && m_wipe_tower)
|
||||
m_last_processor_extrusion_role = GCodeExtrusionRole::WipeTower;
|
||||
|
||||
if (has_custom_gcode_to_emit && extruder_id_for_custom_gcode == int(extruder_id)) {
|
||||
assert(m_writer.extruder()->id() == extruder_id_for_custom_gcode);
|
||||
assert(m_pending_pre_extrusion_gcode.empty());
|
||||
// Now we have picked the right extruder, so we can emit the custom g-code.
|
||||
gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, *layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config());
|
||||
}
|
||||
using GCode::ExtrusionOrder::NormalExtrusions;
|
||||
struct ExtruderExtrusions {
|
||||
unsigned extruder_id;
|
||||
std::vector<std::pair<std::size_t, const ExtrusionEntity *>> skirt;
|
||||
ExtrusionEntitiesPtr brim;
|
||||
std::vector<std::vector<SliceExtrusions>> overriden_extrusions;
|
||||
std::vector<NormalExtrusions> normal_extrusions;
|
||||
};
|
||||
|
||||
unsigned current_extruder_id{this->m_writer.extruder()->id()};
|
||||
unsigned toolchange_number{0};
|
||||
std::optional<Point> previous_position{this->last_position};
|
||||
|
||||
std::vector<std::pair<std::size_t, const ExtrusionEntity *>> skirt;
|
||||
std::vector<ExtruderExtrusions> extrusions;
|
||||
for (const unsigned int extruder_id : layer_tools.extruders)
|
||||
{
|
||||
if (layer_tools.has_wipe_tower && m_wipe_tower) {
|
||||
if (is_toolchange_required(first_layer, layer_tools.extruders.back(), extruder_id, current_extruder_id)) {
|
||||
const WipeTower::ToolChangeResult tool_change{m_wipe_tower->get_toolchange(toolchange_number++)};
|
||||
previous_position = this->gcode_to_point(m_wipe_tower->transform_wt_pt(tool_change.end_pos).cast<double>());
|
||||
current_extruder_id = tool_change.new_tool;
|
||||
}
|
||||
}
|
||||
|
||||
ExtruderExtrusions extruder_extrusions{extruder_id};
|
||||
|
||||
if (auto loops_it = skirt_loops_per_extruder.find(extruder_id); loops_it != skirt_loops_per_extruder.end()) {
|
||||
const std::pair<size_t, size_t> loops = loops_it->second;
|
||||
for (std::size_t i = loops.first; i < loops.second; ++i) {
|
||||
skirt.emplace_back(i, print.skirt().entities[i]);
|
||||
extruder_extrusions.skirt.emplace_back(i, print.skirt().entities[i]);
|
||||
}
|
||||
}
|
||||
|
||||
using GCode::ExtrusionOrder::get_last_position;
|
||||
ExtrusionEntitiesPtr brim;
|
||||
if (!m_brim_done) {
|
||||
brim = print.brim().entities;
|
||||
previous_position = get_last_position(brim);
|
||||
extruder_extrusions.brim = print.brim().entities;
|
||||
previous_position = get_last_position(extruder_extrusions.brim);
|
||||
m_brim_done = true;
|
||||
}
|
||||
|
||||
|
||||
@ -2519,22 +2524,40 @@ LayerResult GCodeGenerator::process_layer(
|
||||
|
||||
using GCode::ExtrusionOrder::get_overriden_extrusions;
|
||||
bool is_anything_overridden = layer_tools.wiping_extrusions().is_anything_overridden();
|
||||
std::vector<std::vector<SliceExtrusions>> overriden_extrusions;
|
||||
if (is_anything_overridden) {
|
||||
overriden_extrusions = get_overriden_extrusions(
|
||||
extruder_extrusions.overriden_extrusions = get_overriden_extrusions(
|
||||
print, layers, layer_tools, instances_to_print, extruder_id, place_seam,
|
||||
previous_position
|
||||
);
|
||||
}
|
||||
|
||||
using GCode::ExtrusionOrder::get_normal_extrusions;
|
||||
using GCode::ExtrusionOrder::NormalExtrusions;
|
||||
const std::vector<NormalExtrusions> normal_extrusions{get_normal_extrusions(
|
||||
extruder_extrusions.normal_extrusions = get_normal_extrusions(
|
||||
print, layers, layer_tools, instances_to_print, extruder_id, place_seam,
|
||||
previous_position
|
||||
)};
|
||||
);
|
||||
extrusions.push_back(std::move(extruder_extrusions));
|
||||
}
|
||||
|
||||
if (!skirt.empty()) {
|
||||
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
|
||||
for (const ExtruderExtrusions &extruder_extrusions : extrusions)
|
||||
{
|
||||
gcode += (layer_tools.has_wipe_tower && m_wipe_tower) ?
|
||||
m_wipe_tower->tool_change(*this, extruder_extrusions.extruder_id, extruder_extrusions.extruder_id == layer_tools.extruders.back()) :
|
||||
this->set_extruder(extruder_extrusions.extruder_id, print_z);
|
||||
|
||||
// let analyzer tag generator aware of a role type change
|
||||
if (layer_tools.has_wipe_tower && m_wipe_tower)
|
||||
m_last_processor_extrusion_role = GCodeExtrusionRole::WipeTower;
|
||||
|
||||
if (has_custom_gcode_to_emit && extruder_id_for_custom_gcode == int(extruder_extrusions.extruder_id)) {
|
||||
assert(m_writer.extruder()->id() == extruder_id_for_custom_gcode);
|
||||
assert(m_pending_pre_extrusion_gcode.empty());
|
||||
// Now we have picked the right extruder, so we can emit the custom g-code.
|
||||
gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, *layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config());
|
||||
}
|
||||
|
||||
if (!extruder_extrusions.skirt.empty()) {
|
||||
if (!this->m_config.complete_objects.value) {
|
||||
gcode += this->m_label_objects.maybe_stop_instance();
|
||||
}
|
||||
@ -2544,7 +2567,7 @@ LayerResult GCodeGenerator::process_layer(
|
||||
m_avoid_crossing_perimeters.use_external_mp();
|
||||
Flow layer_skirt_flow = print.skirt_flow().with_height(float(m_skirt_done.back() - (m_skirt_done.size() == 1 ? 0. : m_skirt_done[m_skirt_done.size() - 2])));
|
||||
double mm3_per_mm = layer_skirt_flow.mm3_per_mm();
|
||||
for (const auto&[_, loop_entity] : skirt) {
|
||||
for (const auto&[_, loop_entity] : extruder_extrusions.skirt) {
|
||||
// Adjust flow according to this layer's layer height.
|
||||
//FIXME using the support_material_speed of the 1st object printed.
|
||||
gcode += this->extrude_skirt(dynamic_cast<const ExtrusionLoop&>(*loop_entity),
|
||||
@ -2554,13 +2577,13 @@ LayerResult GCodeGenerator::process_layer(
|
||||
}
|
||||
m_avoid_crossing_perimeters.use_external_mp(false);
|
||||
// Allow a straight travel move to the first object point if this is the first layer (but don't in next layers).
|
||||
if (first_layer && skirt.front().first == 0)
|
||||
if (first_layer && extruder_extrusions.skirt.front().first == 0)
|
||||
m_avoid_crossing_perimeters.disable_once();
|
||||
}
|
||||
|
||||
|
||||
// Extrude brim with the extruder of the 1st region.
|
||||
if (!brim.empty()) {
|
||||
if (!extruder_extrusions.brim.empty()) {
|
||||
|
||||
if (!this->m_config.complete_objects.value) {
|
||||
gcode += this->m_label_objects.maybe_stop_instance();
|
||||
@ -2569,17 +2592,16 @@ LayerResult GCodeGenerator::process_layer(
|
||||
|
||||
this->set_origin(0., 0.);
|
||||
m_avoid_crossing_perimeters.use_external_mp();
|
||||
for (const ExtrusionEntity *ee : brim) {
|
||||
for (const ExtrusionEntity *ee : extruder_extrusions.brim) {
|
||||
gcode += this->extrude_entity({ *ee, false }, smooth_path_caches.global(), "brim"sv, m_config.support_material_speed.value);
|
||||
}
|
||||
m_brim_done = true;
|
||||
m_avoid_crossing_perimeters.use_external_mp(false);
|
||||
// Allow a straight travel move to the first object point.
|
||||
m_avoid_crossing_perimeters.disable_once();
|
||||
}
|
||||
this->m_label_objects.update(first_instance);
|
||||
|
||||
if (!overriden_extrusions.empty()) {
|
||||
if (!extruder_extrusions.overriden_extrusions.empty()) {
|
||||
// Extrude wipes.
|
||||
size_t gcode_size_old = gcode.size();
|
||||
for (std::size_t i{0}; i < instances_to_print.size(); ++i) {
|
||||
@ -2587,7 +2609,7 @@ LayerResult GCodeGenerator::process_layer(
|
||||
|
||||
this->process_layer_single_object(
|
||||
gcode, instance, layers[instance.object_layer_to_print_id],
|
||||
smooth_path_caches.layer_local(), {}, overriden_extrusions[i]
|
||||
smooth_path_caches.layer_local(), {}, extruder_extrusions.overriden_extrusions[i]
|
||||
);
|
||||
}
|
||||
if (gcode_size_old < gcode.size()) {
|
||||
@ -2601,8 +2623,8 @@ LayerResult GCodeGenerator::process_layer(
|
||||
|
||||
this->process_layer_single_object(
|
||||
gcode, instance, layers[instance.object_layer_to_print_id],
|
||||
smooth_path_caches.layer_local(), normal_extrusions[i].support_extrusions,
|
||||
normal_extrusions[i].slices_extrusions
|
||||
smooth_path_caches.layer_local(), extruder_extrusions.normal_extrusions[i].support_extrusions,
|
||||
extruder_extrusions.normal_extrusions[i].slices_extrusions
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -34,15 +34,6 @@ std::string WipeTowerIntegration::append_tcr(GCodeGenerator &gcodegen, const Wip
|
||||
|
||||
std::string gcode;
|
||||
|
||||
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin (except for priming lines)
|
||||
// We want to rotate and shift all extrusions (gcode postprocessing) and starting and ending position
|
||||
float alpha = m_wipe_tower_rotation / 180.f * float(M_PI);
|
||||
|
||||
auto transform_wt_pt = [&alpha, this](const Vec2f& pt) -> Vec2f {
|
||||
Vec2f out = Eigen::Rotation2Df(alpha) * pt;
|
||||
out += m_wipe_tower_pos;
|
||||
return out;
|
||||
};
|
||||
|
||||
Vec2f start_pos = tcr.start_pos;
|
||||
Vec2f end_pos = tcr.end_pos;
|
||||
@ -52,7 +43,7 @@ std::string WipeTowerIntegration::append_tcr(GCodeGenerator &gcodegen, const Wip
|
||||
}
|
||||
|
||||
Vec2f wipe_tower_offset = tcr.priming ? Vec2f::Zero() : m_wipe_tower_pos;
|
||||
float wipe_tower_rotation = tcr.priming ? 0.f : alpha;
|
||||
float wipe_tower_rotation = tcr.priming ? 0.f : this->get_alpha();
|
||||
|
||||
std::string tcr_rotated_gcode = post_process_wipe_tower_moves(tcr, wipe_tower_offset, wipe_tower_rotation);
|
||||
|
||||
@ -145,7 +136,7 @@ std::string WipeTowerIntegration::append_tcr(GCodeGenerator &gcodegen, const Wip
|
||||
Geometry::ArcWelder::Path path;
|
||||
path.reserve(tcr.wipe_path.size());
|
||||
std::transform(tcr.wipe_path.begin(), tcr.wipe_path.end(), std::back_inserter(path),
|
||||
[&gcodegen, &transform_wt_pt](const Vec2f &wipe_pt) {
|
||||
[&gcodegen, this](const Vec2f &wipe_pt) {
|
||||
return Geometry::ArcWelder::Segment{ wipe_tower_point_to_object_point(gcodegen, transform_wt_pt(wipe_pt)) };
|
||||
});
|
||||
// Pass to the wipe cache.
|
||||
|
@ -39,8 +39,23 @@ public:
|
||||
std::string tool_change(GCodeGenerator &gcodegen, int extruder_id, bool finish_layer);
|
||||
std::string finalize(GCodeGenerator &gcodegen);
|
||||
std::vector<float> used_filament_length() const;
|
||||
WipeTower::ToolChangeResult get_toolchange(std::size_t index) {
|
||||
return m_tool_changes.at(m_layer_idx).at(index);
|
||||
}
|
||||
|
||||
Vec2f transform_wt_pt(const Vec2f& pt) const {
|
||||
Vec2f out = Eigen::Rotation2Df(this->get_alpha()) * pt;
|
||||
out += m_wipe_tower_pos;
|
||||
return out;
|
||||
};
|
||||
|
||||
private:
|
||||
// Toolchangeresult.gcode assumes the wipe tower corner is at the origin (except for priming lines)
|
||||
// We want to rotate and shift all extrusions (gcode postprocessing) and starting and ending position
|
||||
float get_alpha() const {
|
||||
return m_wipe_tower_rotation / 180.f * float(M_PI);
|
||||
}
|
||||
|
||||
WipeTowerIntegration& operator=(const WipeTowerIntegration&);
|
||||
std::string append_tcr(GCodeGenerator &gcodegen, const WipeTower::ToolChangeResult &tcr, int new_extruder_id, double z = -1.) const;
|
||||
|
||||
|
@ -1484,6 +1484,21 @@ const WipeTowerData& Print::wipe_tower_data(size_t extruders_cnt) const
|
||||
return m_wipe_tower_data;
|
||||
}
|
||||
|
||||
bool is_toolchange_required(
|
||||
const bool first_layer,
|
||||
const unsigned last_extruder_id,
|
||||
const unsigned extruder_id,
|
||||
const unsigned current_extruder_id
|
||||
) {
|
||||
if (first_layer && extruder_id == last_extruder_id) {
|
||||
return true;
|
||||
}
|
||||
if (extruder_id != current_extruder_id) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Print::_make_wipe_tower()
|
||||
{
|
||||
m_wipe_tower_data.clear();
|
||||
@ -1552,10 +1567,11 @@ void Print::_make_wipe_tower()
|
||||
unsigned int current_extruder_id = m_wipe_tower_data.tool_ordering.all_extruders().back();
|
||||
for (auto &layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers
|
||||
if (!layer_tools.has_wipe_tower) continue;
|
||||
bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front();
|
||||
wipe_tower.plan_toolchange((float)layer_tools.print_z, (float)layer_tools.wipe_tower_layer_height, current_extruder_id, current_extruder_id, false);
|
||||
for (const auto extruder_id : layer_tools.extruders) {
|
||||
if ((first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) {
|
||||
const bool first_layer{&layer_tools == &m_wipe_tower_data.tool_ordering.front()};
|
||||
const unsigned last_extruder_id{m_wipe_tower_data.tool_ordering.all_extruders().back()};
|
||||
if (is_toolchange_required(first_layer, last_extruder_id, extruder_id, current_extruder_id)) {
|
||||
float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id]; // total volume to wipe after this toolchange
|
||||
// Not all of that can be used for infill purging:
|
||||
volume_to_wipe -= (float)m_config.filament_minimal_purge_on_wipe_tower.get_at(extruder_id);
|
||||
|
@ -493,6 +493,13 @@ private:
|
||||
WipeTowerData &operator=(const WipeTowerData & /* rhs */) = delete;
|
||||
};
|
||||
|
||||
bool is_toolchange_required(
|
||||
const bool first_layer,
|
||||
const unsigned last_extruder_id,
|
||||
const unsigned extruder_id,
|
||||
const unsigned current_extruder_id
|
||||
);
|
||||
|
||||
struct PrintStatistics
|
||||
{
|
||||
PrintStatistics() { clear(); }
|
||||
|
Loading…
x
Reference in New Issue
Block a user