Wiping into infill/objects - invalidation of the wipe tower, bugfixes

This commit is contained in:
Lukas Matena 2018-06-07 16:19:57 +02:00
parent 73452fd79d
commit b6455b66bd
6 changed files with 60 additions and 24 deletions

View File

@ -1357,7 +1357,7 @@ void GCode::process_layer(
m_avoid_crossing_perimeters.disable_once = true; m_avoid_crossing_perimeters.disable_once = true;
} }
if (print.config.wipe_into_infill.value) { {
gcode += "; INFILL WIPING STARTS\n"; gcode += "; INFILL WIPING STARTS\n";
if (extruder_id != layer_tools.extruders.front()) { // if this is the first extruder on this layer, there was no toolchange if (extruder_id != layer_tools.extruders.front()) { // if this is the first extruder on this layer, there was no toolchange
for (const auto& layer_to_print : layers) { // iterate through all objects for (const auto& layer_to_print : layers) { // iterate through all objects
@ -1373,12 +1373,12 @@ void GCode::process_layer(
overridden.push_back(new_region); overridden.push_back(new_region);
for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->fills.entities) { for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->fills.entities) {
auto *fill = dynamic_cast<ExtrusionEntityCollection*>(ee); auto *fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
if (fill->get_extruder_override(copy_id) == (unsigned int)extruder_id) if (fill->get_extruder_override(copy_id) == (int)extruder_id)
overridden.back().infills.append(*fill); overridden.back().infills.append(*fill);
} }
for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->perimeters.entities) { for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->perimeters.entities) {
auto *fill = dynamic_cast<ExtrusionEntityCollection*>(ee); auto *fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
if (fill->get_extruder_override(copy_id) == (unsigned int)extruder_id) if (fill->get_extruder_override(copy_id) == (int)extruder_id)
overridden.back().perimeters.append((*fill).entities); overridden.back().perimeters.append((*fill).entities);
} }
} }
@ -2527,12 +2527,13 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
by_region_per_copy_cache.push_back(ObjectByExtruder::Island::Region()); by_region_per_copy_cache.push_back(ObjectByExtruder::Island::Region());
//out.back().perimeters.append(reg.perimeters); // we will print all perimeters there are //out.back().perimeters.append(reg.perimeters); // we will print all perimeters there are
if (!reg.infills_per_copy_ids.empty()) { if (!reg.infills_per_copy_ids.empty())
for (unsigned int i=0; i<reg.infills_per_copy_ids[copy].size(); ++i) for (unsigned int i=0; i<reg.infills_per_copy_ids[copy].size(); ++i)
by_region_per_copy_cache.back().infills.append(*(reg.infills.entities[reg.infills_per_copy_ids[copy][i]])); by_region_per_copy_cache.back().infills.append(*(reg.infills.entities[reg.infills_per_copy_ids[copy][i]]));
if (!reg.perimeters_per_copy_ids.empty())
for (unsigned int i=0; i<reg.perimeters_per_copy_ids[copy].size(); ++i) for (unsigned int i=0; i<reg.perimeters_per_copy_ids[copy].size(); ++i)
by_region_per_copy_cache.back().perimeters.append(*(reg.perimeters.entities[reg.perimeters_per_copy_ids[copy][i]])); by_region_per_copy_cache.back().perimeters.append(*(reg.perimeters.entities[reg.perimeters_per_copy_ids[copy][i]]));
}
} }
return by_region_per_copy_cache; return by_region_per_copy_cache;
} }

View File

@ -160,6 +160,11 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
std::vector<PrintStep> steps; std::vector<PrintStep> steps;
std::vector<PrintObjectStep> osteps; std::vector<PrintObjectStep> osteps;
bool invalidated = false; bool invalidated = false;
// Always invalidate the wipe tower. This is probably necessary because of the wipe_into_infill / wipe_into_objects
// features - nearly anything can influence what should (and could) be wiped into.
steps.emplace_back(psWipeTower);
for (const t_config_option_key &opt_key : opt_keys) { for (const t_config_option_key &opt_key : opt_keys) {
if (steps_ignore.find(opt_key) != steps_ignore.end()) { if (steps_ignore.find(opt_key) != steps_ignore.end()) {
// These options only affect G-code export or they are just notes without influence on the generated G-code, // These options only affect G-code export or they are just notes without influence on the generated G-code,
@ -201,7 +206,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|| opt_key == "wipe_tower_rotation_angle" || opt_key == "wipe_tower_rotation_angle"
|| opt_key == "wipe_tower_bridging" || opt_key == "wipe_tower_bridging"
|| opt_key == "wiping_volumes_matrix" || opt_key == "wiping_volumes_matrix"
|| opt_key == "parking_pos_retraction" || opt_key == u8"parking_pos_retraction"
|| opt_key == "cooling_tube_retraction" || opt_key == "cooling_tube_retraction"
|| opt_key == "cooling_tube_length" || opt_key == "cooling_tube_length"
|| opt_key == "extra_loading_move" || opt_key == "extra_loading_move"
@ -216,7 +221,6 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
osteps.emplace_back(posSupportMaterial); osteps.emplace_back(posSupportMaterial);
steps.emplace_back(psSkirt); steps.emplace_back(psSkirt);
steps.emplace_back(psBrim); steps.emplace_back(psBrim);
steps.emplace_back(psWipeTower);
} else { } else {
// for legacy, if we can't handle this option let's invalidate all steps // for legacy, if we can't handle this option let's invalidate all steps
//FIXME invalidate all steps of all objects as well? //FIXME invalidate all steps of all objects as well?
@ -1125,6 +1129,7 @@ void Print::_make_wipe_tower()
m_wipe_tower_priming = Slic3r::make_unique<WipeTower::ToolChangeResult>( 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)); wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full));
reset_wiping_extrusions(); // if this is not the first time the wipe tower is generated, some extrusions might remember their last wiping status
// Lets go through the wipe tower layers and determine pairs of extruder changes for each // Lets go through the wipe tower layers and determine pairs of extruder changes for each
// to pass to wipe_tower (so that it can use it for planning the layout of the tower) // to pass to wipe_tower (so that it can use it for planning the layout of the tower)
@ -1138,8 +1143,8 @@ void Print::_make_wipe_tower()
if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) { if ((first_layer && extruder_id == m_tool_ordering.all_extruders().back()) || extruder_id != current_extruder_id) {
float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id]; // total volume to wipe after this toolchange float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id]; // total volume to wipe after this toolchange
if (config.wipe_into_infill && !first_layer) if (!first_layer) // unless we're on the first layer, try to assign some infills/objects for the wiping:
volume_to_wipe = mark_wiping_infill(layer_tools, extruder_id, wipe_volumes[current_extruder_id][extruder_id]); volume_to_wipe = mark_wiping_extrusions(layer_tools, extruder_id, wipe_volumes[current_extruder_id][extruder_id]);
wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id, first_layer && extruder_id == m_tool_ordering.all_extruders().back(), volume_to_wipe); wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id, first_layer && extruder_id == m_tool_ordering.all_extruders().back(), volume_to_wipe);
current_extruder_id = extruder_id; current_extruder_id = extruder_id;
@ -1176,12 +1181,31 @@ void Print::_make_wipe_tower()
float Print::mark_wiping_infill(const ToolOrdering::LayerTools& layer_tools, unsigned int new_extruder, float volume_to_wipe) void Print::reset_wiping_extrusions() {
for (size_t i = 0; i < objects.size(); ++ i) {
for (auto& this_layer : objects[i]->layers) {
for (size_t region_id = 0; region_id < objects[i]->print()->regions.size(); ++ region_id) {
for (unsigned int copy = 0; copy < objects[i]->_shifted_copies.size(); ++copy) {
this_layer->regions[region_id]->fills.set_extruder_override(copy, -1);
this_layer->regions[region_id]->perimeters.set_extruder_override(copy, -1);
}
}
}
}
}
float Print::mark_wiping_extrusions(const ToolOrdering::LayerTools& layer_tools, unsigned int new_extruder, float volume_to_wipe)
{ {
const float min_infill_volume = 0.f; // ignore infill with smaller volume than this const float min_infill_volume = 0.f; // ignore infill with smaller volume than this
if (!config.filament_soluble.get_at(new_extruder)) { // Soluble filament cannot be wiped in a random infill if (!config.filament_soluble.get_at(new_extruder)) { // Soluble filament cannot be wiped in a random infill
for (size_t i = 0; i < objects.size(); ++ i) { // Let's iterate through all objects... for (size_t i = 0; i < objects.size(); ++ i) { // Let's iterate through all objects...
if (!objects[i]->config.wipe_into_infill && !objects[i]->config.wipe_into_objects)
continue;
Layer* this_layer = nullptr; Layer* this_layer = nullptr;
for (unsigned int a = 0; a < objects[i]->layers.size(); ++a) // Finds this layer for (unsigned int a = 0; a < objects[i]->layers.size(); ++a) // Finds this layer
if (std::abs(layer_tools.print_z - objects[i]->layers[a]->print_z) < EPSILON) { if (std::abs(layer_tools.print_z - objects[i]->layers[a]->print_z) < EPSILON) {
@ -1210,16 +1234,18 @@ float Print::mark_wiping_infill(const ToolOrdering::LayerTools& layer_tools, uns
continue; continue;
} }
ExtrusionEntityCollection& eec = this_layer->regions[region_id]->fills; if (objects[i]->config.wipe_into_infill) {
for (ExtrusionEntity* ee : eec.entities) { // iterate through all infill Collections ExtrusionEntityCollection& eec = this_layer->regions[region_id]->fills;
auto* fill = dynamic_cast<ExtrusionEntityCollection*>(ee); for (ExtrusionEntity* ee : eec.entities) { // iterate through all infill Collections
if (fill->role() == erTopSolidInfill || fill->role() == erGapFill) continue; // these cannot be changed - it is / may be visible auto* fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
if (volume_to_wipe <= 0.f) if (fill->role() == erTopSolidInfill || fill->role() == erGapFill) continue; // these cannot be changed - it is / may be visible
break; if (volume_to_wipe <= 0.f)
if (!fill->is_extruder_overridden(copy) && fill->total_volume() > min_infill_volume) { // this infill will be used to wipe this extruder break;
fill->set_extruder_override(copy, new_extruder); if (!fill->is_extruder_overridden(copy) && fill->total_volume() > min_infill_volume) { // this infill will be used to wipe this extruder
volume_to_wipe -= fill->total_volume(); fill->set_extruder_override(copy, new_extruder);
} volume_to_wipe -= fill->total_volume();
}
}
} }
if (objects[i]->config.wipe_into_objects) if (objects[i]->config.wipe_into_objects)

View File

@ -317,7 +317,10 @@ private:
// This function goes through all infill entities, decides which ones will be used for wiping and // This function goes through all infill entities, decides which ones will be used for wiping and
// marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower: // marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower:
float mark_wiping_infill(const ToolOrdering::LayerTools& layer_tools, unsigned int new_extruder, float volume_to_wipe); float mark_wiping_extrusions(const ToolOrdering::LayerTools& layer_tools, unsigned int new_extruder, float volume_to_wipe);
// A function to go through all entities and unsets their extruder_override flag
void reset_wiping_extrusions();
// Has the calculation been canceled? // Has the calculation been canceled?
tbb::atomic<bool> m_canceled; tbb::atomic<bool> m_canceled;

View File

@ -1886,6 +1886,7 @@ PrintConfigDef::PrintConfigDef()
def->default_value = new ConfigOptionFloat(0.); def->default_value = new ConfigOptionFloat(0.);
def = this->add("wipe_into_infill", coBool); def = this->add("wipe_into_infill", coBool);
def->category = L("Extruders");
def->label = L("Wiping into infill"); def->label = L("Wiping into infill");
def->tooltip = L("Wiping after toolchange will be preferentially done inside infills. " def->tooltip = L("Wiping after toolchange will be preferentially done inside infills. "
"This lowers the amount of waste but may result in longer print time " "This lowers the amount of waste but may result in longer print time "

View File

@ -337,6 +337,7 @@ public:
ConfigOptionFloatOrPercent support_material_xy_spacing; ConfigOptionFloatOrPercent support_material_xy_spacing;
ConfigOptionFloat xy_size_compensation; ConfigOptionFloat xy_size_compensation;
ConfigOptionBool wipe_into_objects; ConfigOptionBool wipe_into_objects;
ConfigOptionBool wipe_into_infill;
protected: protected:
void initialize(StaticCacheBase &cache, const char *base_ptr) void initialize(StaticCacheBase &cache, const char *base_ptr)
@ -374,6 +375,7 @@ protected:
OPT_PTR(support_material_with_sheath); OPT_PTR(support_material_with_sheath);
OPT_PTR(xy_size_compensation); OPT_PTR(xy_size_compensation);
OPT_PTR(wipe_into_objects); OPT_PTR(wipe_into_objects);
OPT_PTR(wipe_into_infill);
} }
}; };
@ -644,7 +646,6 @@ public:
ConfigOptionFloat wipe_tower_per_color_wipe; ConfigOptionFloat wipe_tower_per_color_wipe;
ConfigOptionFloat wipe_tower_rotation_angle; ConfigOptionFloat wipe_tower_rotation_angle;
ConfigOptionFloat wipe_tower_bridging; ConfigOptionFloat wipe_tower_bridging;
ConfigOptionBool wipe_into_infill;
ConfigOptionFloats wiping_volumes_matrix; ConfigOptionFloats wiping_volumes_matrix;
ConfigOptionFloats wiping_volumes_extruders; ConfigOptionFloats wiping_volumes_extruders;
ConfigOptionFloat z_offset; ConfigOptionFloat z_offset;
@ -713,7 +714,6 @@ protected:
OPT_PTR(wipe_tower_width); OPT_PTR(wipe_tower_width);
OPT_PTR(wipe_tower_per_color_wipe); OPT_PTR(wipe_tower_per_color_wipe);
OPT_PTR(wipe_tower_rotation_angle); OPT_PTR(wipe_tower_rotation_angle);
OPT_PTR(wipe_into_infill);
OPT_PTR(wipe_tower_bridging); OPT_PTR(wipe_tower_bridging);
OPT_PTR(wiping_volumes_matrix); OPT_PTR(wiping_volumes_matrix);
OPT_PTR(wiping_volumes_extruders); OPT_PTR(wiping_volumes_extruders);

View File

@ -231,7 +231,10 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|| opt_key == "perimeter_speed" || opt_key == "perimeter_speed"
|| opt_key == "small_perimeter_speed" || opt_key == "small_perimeter_speed"
|| opt_key == "solid_infill_speed" || opt_key == "solid_infill_speed"
|| opt_key == "top_solid_infill_speed") { || opt_key == "top_solid_infill_speed"
|| opt_key == "wipe_into_infill" // when these these two are changed, we only need to invalidate the wipe tower,
|| opt_key == "wipe_into_objects" // which we already did at the very beginning - nothing more to be done
) {
// these options only affect G-code export, so nothing to invalidate // these options only affect G-code export, so nothing to invalidate
} else { } else {
// for legacy, if we can't handle this option let's invalidate all steps // for legacy, if we can't handle this option let's invalidate all steps
@ -271,6 +274,8 @@ bool PrintObject::invalidate_step(PrintObjectStep step)
} }
// Wipe tower depends on the ordering of extruders, which in turn depends on everything. // Wipe tower depends on the ordering of extruders, which in turn depends on everything.
// It also decides about what the wipe_into_infill / wipe_into_object features will do,
// and that too depends on many of the settings.
invalidated |= this->_print->invalidate_step(psWipeTower); invalidated |= this->_print->invalidate_step(psWipeTower);
return invalidated; return invalidated;
} }