Object skirt

This commit is contained in:
vovodroid 2024-08-22 17:12:42 +03:00
parent 0b6a1d3636
commit 2a8b39acd4
14 changed files with 266 additions and 138 deletions

View file

@ -3356,10 +3356,10 @@ namespace ProcessLayer
} // namespace ProcessLayer
namespace Skirt {
static void skirt_loops_per_extruder_all_printing(const Print &print, const LayerTools &layer_tools, std::map<unsigned int, std::pair<size_t, size_t>> &skirt_loops_per_extruder_out)
static void skirt_loops_per_extruder_all_printing(const Print &print, const ExtrusionEntityCollection &skirt, const LayerTools &layer_tools, std::map<unsigned int, std::pair<size_t, size_t>> &skirt_loops_per_extruder_out)
{
// Prime all extruders printing over the 1st layer over the skirt lines.
size_t n_loops = print.skirt().entities.size();
size_t n_loops = skirt.entities.size();
size_t n_tools = layer_tools.extruders.size();
size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
@ -3377,6 +3377,7 @@ namespace Skirt {
static std::map<unsigned int, std::pair<size_t, size_t>> make_skirt_loops_per_extruder_1st_layer(
const Print &print,
const ExtrusionEntityCollection &skirt,
const LayerTools &layer_tools,
// Heights (print_z) at which the skirt has already been extruded.
std::vector<coordf_t> &skirt_done)
@ -3386,8 +3387,8 @@ namespace Skirt {
std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
//For sequential print, the following test may fail when extruding the 2nd and other objects.
// assert(skirt_done.empty());
if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt) {
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
if (skirt_done.empty() && print.has_skirt() && ! skirt.entities.empty() && layer_tools.has_skirt) {
skirt_loops_per_extruder_all_printing(print, skirt, layer_tools, skirt_loops_per_extruder_out);
skirt_done.emplace_back(layer_tools.print_z);
}
return skirt_loops_per_extruder_out;
@ -3395,6 +3396,7 @@ namespace Skirt {
static std::map<unsigned int, std::pair<size_t, size_t>> make_skirt_loops_per_extruder_other_layers(
const Print &print,
const ExtrusionEntityCollection &skirt,
const LayerTools &layer_tools,
// Heights (print_z) at which the skirt has already been extruded.
std::vector<coordf_t> &skirt_done)
@ -3402,7 +3404,7 @@ namespace Skirt {
// 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.
std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
if (print.has_skirt() && ! print.skirt().entities.empty() && layer_tools.has_skirt &&
if (print.has_skirt() && ! skirt.entities.empty() && layer_tools.has_skirt &&
// Not enough skirt layers printed yet.
//FIXME infinite or high skirt does not make sense for sequential print!
(skirt_done.size() < (size_t)print.config().skirt_height.value || print.has_infinite_skirt())) {
@ -3416,7 +3418,7 @@ namespace Skirt {
skirt_loops_per_extruder_out[layer_tools.extruders.front()] = std::pair<size_t, size_t>(0, print.config().skirt_loops.value);
#else
// Prime all extruders planned for this layer, see
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
skirt_loops_per_extruder_all_printing(print, skirt, layer_tools, skirt_loops_per_extruder_out);
#endif
assert(!skirt_done.empty());
skirt_done.emplace_back(layer_tools.print_z);
@ -3479,6 +3481,57 @@ inline std::string get_instance_name(const PrintObject *object, const PrintInsta
return get_instance_name(object, inst.id);
}
std::string GCode::generate_skirt(const Print &print,
const ExtrusionEntityCollection &skirt,
const Point& offset,
const LayerTools &layer_tools,
const Layer& layer,
unsigned int extruder_id)
{
bool first_layer = (layer.id() == 0 && abs(layer.bottom_z()) < EPSILON);
std::string gcode;
// 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.
// Map from extruder ID to <begin, end> index of skirt loops to be extruded with that extruder.
std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder;
skirt_loops_per_extruder = first_layer ?
Skirt::make_skirt_loops_per_extruder_1st_layer(print, skirt, layer_tools, m_skirt_done) :
Skirt::make_skirt_loops_per_extruder_other_layers(print, skirt, layer_tools, m_skirt_done);
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;
set_origin(unscaled(offset));
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 (size_t i = first_layer ? loops.first : loops.second - 1; i < loops.second; ++i) {
// Adjust flow according to this layer's layer height.
ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(skirt.entities[i]);
for (ExtrusionPath &path : loop.paths) {
path.height = layer_skirt_flow.height();
path.mm3_per_mm = mm3_per_mm;
}
//set skirt start point location
if (first_layer && i==loops.first)
this->set_last_pos(Skirt::find_start_point(loop, layer.object()->config().skirt_start_angle));
//FIXME using the support_speed of the 1st object printed.
gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value);
if (!first_layer)
break;
}
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 && loops.first == 0)
m_avoid_crossing_perimeters.disable_once();
}
return gcode;
}
// In sequential mode, process_layer is called once per each object and its copy,
// therefore layers will contain a single entry and single_object_instance_idx will point to the copy of the object.
// In non-sequential mode, process_layer is called per each print_z height with all object and support layers accumulated.
@ -3730,18 +3783,10 @@ LayerResult GCode::process_layer(
m_second_layer_things_done = true;
}
// Map from extruder ID to <begin, end> index of skirt loops to be extruded with that extruder.
std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder;
if (single_object_instance_idx == size_t(-1)) {
// Normal (non-sequential) print.
gcode += ProcessLayer::emit_custom_gcode_per_print_z(*this, layer_tools.custom_gcode, m_writer.extruder()->id(), first_extruder_id, print.config());
}
// 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.
skirt_loops_per_extruder = first_layer ?
Skirt::make_skirt_loops_per_extruder_1st_layer(print, layer_tools, m_skirt_done) :
Skirt::make_skirt_loops_per_extruder_other_layers(print, layer_tools, m_skirt_done);
// BBS: get next extruder according to flush and soluble
auto get_next_extruder = [&](int current_extruder,const std::vector<unsigned int>&extruders) {
@ -4008,33 +4053,9 @@ LayerResult GCode::process_layer(
// let analyzer tag generator aware of a role type change
if (layer_tools.has_wipe_tower && m_wipe_tower)
m_last_processor_extrusion_role = erWipeTower;
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;
this->set_origin(0., 0.);
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 (size_t i = (layer.id() == 0) ? loops.first : loops.second - 1; i < loops.second; ++i) {
// Adjust flow according to this layer's layer height.
ExtrusionLoop loop = *dynamic_cast<const ExtrusionLoop*>(print.skirt().entities[i]);
for (ExtrusionPath &path : loop.paths) {
path.height = layer_skirt_flow.height();
path.mm3_per_mm = mm3_per_mm;
}
//set skirt start point location
if (first_layer && i==loops.first)
this->set_last_pos(Skirt::find_start_point(loop, layer.object()->config().skirt_start_angle));
//FIXME using the support_speed of the 1st object printed.
gcode += this->extrude_loop(loop, "skirt", m_config.support_speed.value);
}
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 && loops.first == 0)
m_avoid_crossing_perimeters.disable_once();
}
if (print.config().skirt_type == stCommon && !print.skirt().empty())
gcode += generate_skirt(print, print.skirt(), Point(0,0), layer_tools, layer, extruder_id);
auto objects_by_extruder_it = by_extruder.find(extruder_id);
if (objects_by_extruder_it == by_extruder.end())
@ -4069,8 +4090,17 @@ LayerResult GCode::process_layer(
}
// BBS
if (print.has_skirt() && print.config().print_sequence == PrintSequence::ByObject && prime_extruder && first_layer && extruder_id == first_extruder_id) {
if (print.config().skirt_type == stObject &&
print.config().print_sequence == PrintSequence::ByObject &&
!layer.object()->object_skirt().empty() &&
((layer.id() < print.config().skirt_height || print.config().draft_shield == DraftShield::dsEnabled))
)
{
for (InstanceToPrint& instance_to_print : instances_to_print) {
if (instance_to_print.print_object.object_skirt().empty())
continue;
if (this->m_objSupportsWithBrim.find(instance_to_print.print_object.id()) != this->m_objSupportsWithBrim.end() &&
print.m_supportBrimMap.at(instance_to_print.print_object.id()).entities.size() > 0)
continue;
@ -4078,12 +4108,14 @@ LayerResult GCode::process_layer(
if (this->m_objsWithBrim.find(instance_to_print.print_object.id()) != this->m_objsWithBrim.end() &&
print.m_brimMap.at(instance_to_print.print_object.id()).entities.size() > 0)
continue;
if (first_layer)
m_skirt_done.clear();
if (layer.id() == 1 && m_skirt_done.size() > 1)
m_skirt_done.erase(m_skirt_done.begin()+1,m_skirt_done.end());
const Point& offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift;
set_origin(unscaled(offset));
for (ExtrusionEntity* ee : layer.object()->object_skirt().entities)
//FIXME using the support_speed of the 1st object printed.
gcode += this->extrude_entity(*ee, "skirt", m_config.support_speed.value);
gcode += generate_skirt(print, instance_to_print.print_object.object_skirt(), offset, layer_tools, layer, extruder_id);
}
}
@ -4092,7 +4124,22 @@ LayerResult GCode::process_layer(
for (int print_wipe_extrusions = is_anything_overridden; print_wipe_extrusions>=0; --print_wipe_extrusions) {
if (is_anything_overridden && print_wipe_extrusions == 0)
gcode+="; PURGING FINISHED\n";
for (InstanceToPrint &instance_to_print : instances_to_print) {
if (print.config().skirt_type == stObject &&
!instance_to_print.print_object.object_skirt().empty() &&
print.config().print_sequence == PrintSequence::ByLayer
&&
(layer.id() < print.config().skirt_height || print.config().draft_shield == DraftShield::dsEnabled))
{
if (first_layer)
m_skirt_done.clear();
const Point& offset = instance_to_print.print_object.instances()[instance_to_print.instance_id].shift;
gcode += generate_skirt(print, instance_to_print.print_object.object_skirt(), offset, layer_tools, layer, extruder_id);
if (instances_to_print.size() > 1 && &instance_to_print != &*(instances_to_print.end() - 1))
m_skirt_done.pop_back();
}
const auto& inst = instance_to_print.print_object.instances()[instance_to_print.instance_id];
const LayerToPrint &layer_to_print = layers[instance_to_print.layer_id];
// To control print speed of the 1st object layer printed over raft interface.