Wipe into infill - copies of one object are properly processed

This commit is contained in:
Lukas Matena 2018-05-31 16:21:10 +02:00
parent 8bdbe41505
commit 2d24bf5f73
7 changed files with 92 additions and 63 deletions

View file

@ -93,6 +93,19 @@ public:
virtual Polyline as_polyline() const = 0;
virtual double length() const = 0;
virtual double total_volume() const = 0;
void set_entity_extruder_override(unsigned int copy, int extruder) {
if (copy+1 > extruder_override.size())
extruder_override.resize(copy+1, -1); // copy is zero-based index
extruder_override[copy] = extruder;
}
virtual int get_extruder_override(unsigned int copy) const { try { return extruder_override.at(copy); } catch (...) { return -1; } }
virtual bool is_extruder_overridden(unsigned int copy) const { try { return extruder_override.at(copy) != -1; } catch (...) { return false; } }
private:
// Set this variable to explicitly state you want to use specific extruder for thie EE (used for MM infill wiping)
// Each member of the vector corresponds to the respective copy of the object
std::vector<int> extruder_override;
};
typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;

View file

@ -91,20 +91,12 @@ public:
return 0.;
}
void set_extruder_override(int extruder) {
extruder_override = extruder;
for (auto& member : entities) {
if (member->is_collection())
dynamic_cast<ExtrusionEntityCollection*>(member)->set_extruder_override(extruder);
}
void set_extruder_override(unsigned int copy, int extruder) {
for (ExtrusionEntity* member : entities)
member->set_entity_extruder_override(copy, extruder);
}
int get_extruder_override() const { return extruder_override; }
bool is_extruder_overridden() const { return extruder_override != -1; }
private:
// Set this variable to explicitly state you want to use specific extruder for thie EEC (used for MM infill wiping)
int extruder_override = -1;
virtual int get_extruder_override(unsigned int copy) const { return entities.front()->get_extruder_override(copy); }
virtual bool is_extruder_overridden(unsigned int copy) const { return entities.front()->is_extruder_overridden(copy); }
};
}

View file

@ -1262,8 +1262,8 @@ void GCode::process_layer(
// This shouldn't happen but first_point() would fail.
continue;
if (fill->is_extruder_overridden())
continue;
/*if (fill->is_extruder_overridden())
continue;*/
// init by_extruder item only if we actually use the extruder
int extruder_id = std::max<int>(0, (is_solid_infill(fill->entities.front()->role()) ? region.config.solid_infill_extruder : region.config.infill_extruder) - 1);
@ -1342,28 +1342,27 @@ void GCode::process_layer(
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
for (const auto& layer_to_print : layers) { // iterate through all objects
gcode+="objekt\n";
if (layer_to_print.object_layer == nullptr)
continue;
std::vector<ObjectByExtruder::Island::Region> overridden;
for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) {
gcode+="region\n";
ObjectByExtruder::Island::Region new_region;
overridden.push_back(new_region);
for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->fills.entities) {
gcode+="entity\n";
auto *fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
if (fill->get_extruder_override() == extruder_id) {
gcode+="*\n";
overridden.back().infills.append(*fill);
fill->set_extruder_override(-1);
}
}
}
m_config.apply((layer_to_print.object_layer)->object()->config, true);
Point copy = (layer_to_print.object_layer)->object()->_shifted_copies.front();
this->set_origin(unscale(copy.x), unscale(copy.y));
gcode += this->extrude_infill(print, overridden);
for (unsigned copy_id = 0; copy_id < layer_to_print.object()->copies().size(); ++copy_id) {
std::vector<ObjectByExtruder::Island::Region> overridden;
for (size_t region_id = 0; region_id < print.regions.size(); ++ region_id) {
ObjectByExtruder::Island::Region new_region;
overridden.push_back(new_region);
for (ExtrusionEntity *ee : (*layer_to_print.object_layer).regions[region_id]->fills.entities) {
auto *fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
if (fill->get_extruder_override(copy_id) == extruder_id)
overridden.back().infills.append(*fill);
}
}
Point copy = (layer_to_print.object_layer)->object()->_shifted_copies[copy_id];
this->set_origin(unscale(copy.x), unscale(copy.y));
gcode += this->extrude_infill(print, overridden);
}
}
}
gcode += "; WIPING FINISHED\n";
@ -1393,6 +1392,7 @@ void GCode::process_layer(
// Sort the copies by the closest point starting with the current print position.
unsigned int copy_id = 0;
for (const Point &copy : copies) {
// When starting a new object, use the external motion planner for the first travel move.
std::pair<const PrintObject*, Point> this_object_copy(print_object, copy);
@ -1409,13 +1409,14 @@ void GCode::process_layer(
}
for (const ObjectByExtruder::Island &island : object_by_extruder.islands) {
if (print.config.infill_first) {
gcode += this->extrude_infill(print, island.by_region);
gcode += this->extrude_infill(print, island.by_region_special(copy_id));
gcode += this->extrude_perimeters(print, island.by_region, lower_layer_edge_grids[layer_id]);
} else {
gcode += this->extrude_perimeters(print, island.by_region, lower_layer_edge_grids[layer_id]);
gcode += this->extrude_infill(print, island.by_region);
gcode += this->extrude_infill(print, island.by_region_special(copy_id));
}
}
++copy_id;
}
}
}
@ -2042,7 +2043,6 @@ std::string GCode::extrude_perimeters(const Print &print, const std::vector<Obje
}
// Chain the paths hierarchically by a greedy algorithm to minimize a travel distance.
// if extruder_id is set, only entities marked with given extruder_id are extruded
std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region)
{
std::string gcode;
@ -2477,4 +2477,19 @@ Point GCode::gcode_to_point(const Pointf &point) const
scale_(point.y - m_origin.y + extruder_offset.y));
}
std::vector<GCode::ObjectByExtruder::Island::Region> GCode::ObjectByExtruder::Island::by_region_special(unsigned int copy) const
{
std::vector<ObjectByExtruder::Island::Region> out;
for (const auto& reg : by_region) {
out.push_back(ObjectByExtruder::Island::Region());
out.back().perimeters.append(reg.perimeters);
for (const auto& ee : reg.infills.entities)
if (ee->get_extruder_override(copy) == -1)
out.back().infills.append(*ee);
}
return out;
}
} // namespace Slic3r

View file

@ -217,9 +217,12 @@ protected:
ExtrusionEntityCollection infills;
};
std::vector<Region> by_region;
std::vector<Region> by_region_special(unsigned int copy) const;
};
std::vector<Island> islands;
};
std::string extrude_perimeters(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region, std::unique_ptr<EdgeGrid::Grid> &lower_layer_edge_grid);
std::string extrude_infill(const Print &print, const std::vector<ObjectByExtruder::Island::Region> &by_region);
std::string extrude_support(const ExtrusionEntityCollection &support_fills);

View file

@ -21,7 +21,6 @@ TODO LIST
#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include "Analyzer.hpp"

View file

@ -5,6 +5,7 @@
#include <string>
#include <sstream>
#include <utility>
#include <algorithm>
#include "WipeTower.hpp"

View file

@ -1183,34 +1183,40 @@ float Print::mark_wiping_infill(const ToolOrdering::LayerTools& layer_tools, uns
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...
Layer* this_layer = nullptr;
for (unsigned int a = 0; a < objects[i]->layers.size(); this_layer = objects[i]->layers[++a]) // Finds this layer
if (std::abs(layer_tools.print_z - objects[i]->layers[a]->print_z) < EPSILON)
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) {
this_layer = objects[i]->layers[a];
break;
for (size_t region_id = 0; region_id < objects[i]->print()->regions.size(); ++ region_id) {
unsigned int region_extruder = objects[i]->print()->regions[region_id]->config.infill_extruder - 1; // config value is 1-based
if (config.filament_soluble.get_at(region_extruder)) // if this infill is meant to be soluble, keep it that way
continue;
if (!config.infill_first) { // in this case we must verify that region_extruder was already used at this layer (and perimeters of the infill are therefore extruded)
bool unused_yet = false;
for (unsigned i = 0; i < layer_tools.extruders.size(); ++i) {
if (layer_tools.extruders[i] == new_extruder)
unused_yet = true;
if (layer_tools.extruders[i] == region_extruder)
break;
}
if (unused_yet)
continue;
}
if (this_layer == nullptr)
continue;
ExtrusionEntityCollection& eec = this_layer->regions[region_id]->fills;
for (ExtrusionEntity* ee : eec.entities) { // iterate through all infill Collections
auto* fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
if (fill->role() == erTopSolidInfill) continue; // color of TopSolidInfill cannot be changed - it is visible
if (volume_to_wipe > 0.f && !fill->is_extruder_overridden() && fill->total_volume() > min_infill_volume) { // this infill will be used to wipe this extruder
fill->set_extruder_override(new_extruder);
volume_to_wipe -= fill->total_volume();
for (unsigned int copy = 0; copy < objects[i]->copies().size(); ++copy) { // iterate through copies first, so that we mark neighbouring infills
for (size_t region_id = 0; region_id < objects[i]->print()->regions.size(); ++ region_id) {
unsigned int region_extruder = objects[i]->print()->regions[region_id]->config.infill_extruder - 1; // config value is 1-based
if (config.filament_soluble.get_at(region_extruder)) // if this infill is meant to be soluble, keep it that way
continue;
if (!config.infill_first) { // in this case we must verify that region_extruder was already used at this layer (and perimeters of the infill are therefore extruded)
bool unused_yet = false;
for (unsigned i = 0; i < layer_tools.extruders.size(); ++i) {
if (layer_tools.extruders[i] == new_extruder)
unused_yet = true;
if (layer_tools.extruders[i] == region_extruder)
break;
}
if (unused_yet)
continue;
}
ExtrusionEntityCollection& eec = this_layer->regions[region_id]->fills;
for (ExtrusionEntity* ee : eec.entities) { // iterate through all infill Collections
auto* fill = dynamic_cast<ExtrusionEntityCollection*>(ee);
if (fill->role() == erTopSolidInfill || fill->role() == erGapFill) continue; // these cannot be changed - it is / may be visible
if (volume_to_wipe > 0.f && !fill->is_extruder_overridden(copy) && fill->total_volume() > min_infill_volume) { // this infill will be used to wipe this extruder
fill->set_extruder_override(copy, new_extruder);
volume_to_wipe -= fill->total_volume();
}
}
}
}