Wipe into infill - copies of one object are properly processed
This commit is contained in:
parent
8bdbe41505
commit
2d24bf5f73
7 changed files with 92 additions and 63 deletions
|
@ -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;
|
||||
|
|
|
@ -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); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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 © : 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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -21,7 +21,6 @@ TODO LIST
|
|||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <numeric>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Analyzer.hpp"
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <string>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
#include "WipeTower.hpp"
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue