Optimization of G-code export:
1) Don't allocate ExtruderOverrides if not necessary 2) Use boost::container::small_vector<int32, 3) for ExtruderOverrides (usually less than 4 instances are printed))
This commit is contained in:
parent
4aee673b13
commit
e0811e4aa5
5 changed files with 169 additions and 107 deletions
|
@ -2026,58 +2026,69 @@ void GCode::process_layer(
|
|||
layer.lslices[i].contour.contains(point);
|
||||
};
|
||||
|
||||
for (size_t region_id = 0; region_id < print.regions().size(); ++ region_id) {
|
||||
const LayerRegion *layerm = (region_id < layer.regions().size()) ? layer.regions()[region_id] : nullptr;
|
||||
for (size_t region_id = 0; region_id < layer.regions().size(); ++ region_id) {
|
||||
const LayerRegion *layerm = layer.regions()[region_id];
|
||||
if (layerm == nullptr)
|
||||
continue;
|
||||
const PrintRegion ®ion = *print.regions()[region_id];
|
||||
|
||||
|
||||
// Now we must process perimeters and infills and create islands of extrusions in by_region std::map.
|
||||
// It is also necessary to save which extrusions are part of MM wiping and which are not.
|
||||
// The process is almost the same for perimeters and infills - we will do it in a cycle that repeats twice:
|
||||
for (std::string entity_type("infills") ; entity_type != "done" ; entity_type = entity_type=="infills" ? "perimeters" : "done") {
|
||||
|
||||
const ExtrusionEntitiesPtr& source_entities = entity_type=="infills" ? layerm->fills.entities : layerm->perimeters.entities;
|
||||
|
||||
for (const ExtrusionEntity *ee : source_entities) {
|
||||
// fill represents infill extrusions of a single island.
|
||||
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
||||
if (fill->entities.empty()) // This shouldn't happen but first_point() would fail.
|
||||
std::vector<unsigned int> printing_extruders;
|
||||
for (const ObjectByExtruder::Island::Region::Type entity_type : { ObjectByExtruder::Island::Region::INFILL, ObjectByExtruder::Island::Region::PERIMETERS }) {
|
||||
for (const ExtrusionEntity *ee : (entity_type == ObjectByExtruder::Island::Region::INFILL) ? layerm->fills.entities : layerm->perimeters.entities) {
|
||||
// extrusions represents infill or perimeter extrusions of a single island.
|
||||
assert(dynamic_cast<const ExtrusionEntityCollection*>(ee) != nullptr);
|
||||
const auto *extrusions = static_cast<const ExtrusionEntityCollection*>(ee);
|
||||
if (extrusions->entities.empty()) // This shouldn't happen but first_point() would fail.
|
||||
continue;
|
||||
|
||||
// This extrusion is part of certain Region, which tells us which extruder should be used for it:
|
||||
int correct_extruder_id = Print::get_extruder(*fill, region);
|
||||
int correct_extruder_id = Print::get_extruder(*extrusions, region);
|
||||
|
||||
// Let's recover vector of extruder overrides:
|
||||
const ExtruderPerCopy* entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(fill, correct_extruder_id, layer_to_print.object()->copies().size());
|
||||
const WipingExtrusions::ExtruderPerCopy *entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(extrusions, correct_extruder_id, layer_to_print.object()->copies().size());
|
||||
printing_extruders.clear();
|
||||
if (entity_overrides == nullptr) {
|
||||
printing_extruders.emplace_back(correct_extruder_id);
|
||||
} else {
|
||||
printing_extruders.reserve(entity_overrides->size() + 1);
|
||||
for (int extruder : *entity_overrides)
|
||||
printing_extruders.emplace_back(extruder >= 0 ?
|
||||
// at least one copy is overridden to use this extruder
|
||||
extruder :
|
||||
// at least one copy would normally be printed with this extruder (see get_extruder_overrides function for explanation)
|
||||
static_cast<unsigned int>(- extruder - 1));
|
||||
}
|
||||
if (! layer_tools.has_extruder(correct_extruder_id)) {
|
||||
// this entity is not overridden, but its extruder is not in layer_tools - we'll print it
|
||||
// by last extruder on this layer (could happen e.g. when a wiping object is taller than others - dontcare extruders are eradicated from layer_tools)
|
||||
printing_extruders.emplace_back(layer_tools.extruders.back());
|
||||
}
|
||||
Slic3r::sort_remove_duplicates(printing_extruders);
|
||||
if (printing_extruders.size() == 1 && printing_extruders.front() == correct_extruder_id)
|
||||
entity_overrides = nullptr;
|
||||
|
||||
// Now we must add this extrusion into the by_extruder map, once for each extruder that will print it:
|
||||
for (unsigned int extruder : layer_tools.extruders)
|
||||
for (unsigned int extruder : printing_extruders)
|
||||
{
|
||||
// Init by_extruder item only if we actually use the extruder:
|
||||
if (std::find(entity_overrides->begin(), entity_overrides->end(), extruder) != entity_overrides->end() || // at least one copy is overridden to use this extruder
|
||||
std::find(entity_overrides->begin(), entity_overrides->end(), -extruder-1) != entity_overrides->end() || // at least one copy would normally be printed with this extruder (see get_extruder_overrides function for explanation)
|
||||
(std::find(layer_tools.extruders.begin(), layer_tools.extruders.end(), correct_extruder_id) == layer_tools.extruders.end() && extruder == layer_tools.extruders.back())) // this entity is not overridden, but its extruder is not in layer_tools - we'll print it
|
||||
//by last extruder on this layer (could happen e.g. when a wiping object is taller than others - dontcare extruders are eradicated from layer_tools)
|
||||
{
|
||||
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
|
||||
by_extruder,
|
||||
extruder,
|
||||
&layer_to_print - layers.data(),
|
||||
layers.size(), n_slices+1);
|
||||
for (size_t i = 0; i <= n_slices; ++ i) {
|
||||
bool last = i == n_slices;
|
||||
size_t island_idx = last ? n_slices : slices_test_order[i];
|
||||
if (// fill->first_point does not fit inside any slice
|
||||
last ||
|
||||
// fill->first_point fits inside ith slice
|
||||
point_inside_surface(island_idx, fill->first_point())) {
|
||||
if (islands[island_idx].by_region.empty())
|
||||
islands[island_idx].by_region.assign(print.regions().size(), ObjectByExtruder::Island::Region());
|
||||
islands[island_idx].by_region[region_id].append(entity_type, fill, entity_overrides, layer_to_print.object()->copies().size());
|
||||
break;
|
||||
}
|
||||
std::vector<ObjectByExtruder::Island> &islands = object_islands_by_extruder(
|
||||
by_extruder,
|
||||
extruder,
|
||||
&layer_to_print - layers.data(),
|
||||
layers.size(), n_slices+1);
|
||||
for (size_t i = 0; i <= n_slices; ++ i) {
|
||||
bool last = i == n_slices;
|
||||
size_t island_idx = last ? n_slices : slices_test_order[i];
|
||||
if (// extrusions->first_point does not fit inside any slice
|
||||
last ||
|
||||
// extrusions->first_point fits inside ith slice
|
||||
point_inside_surface(island_idx, extrusions->first_point())) {
|
||||
if (islands[island_idx].by_region.empty())
|
||||
islands[island_idx].by_region.assign(print.regions().size(), ObjectByExtruder::Island::Region());
|
||||
islands[island_idx].by_region[region_id].append(entity_type, extrusions, entity_overrides);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2147,6 +2158,7 @@ void GCode::process_layer(
|
|||
|
||||
// We are almost ready to print. However, we must go through all the objects twice to print the the overridden extrusions first (infill/perimeter wiping feature):
|
||||
bool is_anything_overridden = const_cast<LayerTools&>(layer_tools).wiping_extrusions().is_anything_overridden();
|
||||
std::vector<ObjectByExtruder::Island::Region> by_region_per_copy_cache;
|
||||
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";
|
||||
|
@ -2174,8 +2186,8 @@ void GCode::process_layer(
|
|||
m_layer = layers[instance_to_print.layer_id].layer();
|
||||
}
|
||||
for (ObjectByExtruder::Island &island : instance_to_print.object_by_extruder.islands) {
|
||||
const auto& by_region_specific = is_anything_overridden ? island.by_region_per_copy(instance_to_print.instance_id, extruder_id, print_wipe_extrusions) : island.by_region;
|
||||
|
||||
const auto& by_region_specific = is_anything_overridden ? island.by_region_per_copy(by_region_per_copy_cache, instance_to_print.instance_id, extruder_id, print_wipe_extrusions) : island.by_region;
|
||||
//FIXME the following code prints regions in the order they are defined, the path is not optimized in any way.
|
||||
if (print.config().infill_first) {
|
||||
gcode += this->extrude_infill(print, by_region_specific);
|
||||
gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]);
|
||||
|
@ -3260,59 +3272,97 @@ Point GCode::gcode_to_point(const Vec2d &point) const
|
|||
|
||||
// Goes through by_region std::vector and returns reference to a subvector of entities, that are to be printed
|
||||
// during infill/perimeter wiping, or normally (depends on wiping_entities parameter)
|
||||
// Returns a reference to member to avoid copying.
|
||||
const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtruder::Island::by_region_per_copy(unsigned int copy, int extruder, bool wiping_entities)
|
||||
// Fills in by_region_per_copy_cache and returns its reference.
|
||||
const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtruder::Island::by_region_per_copy(std::vector<Region> &by_region_per_copy_cache, unsigned int copy, int extruder, bool wiping_entities) const
|
||||
{
|
||||
bool has_overrides = false;
|
||||
for (const auto& reg : by_region)
|
||||
if (! reg.infills_overrides.empty() || ! reg.perimeters_overrides.empty()) {
|
||||
has_overrides = true;
|
||||
break;
|
||||
}
|
||||
if (! has_overrides)
|
||||
// Simple case. No need to copy the regions.
|
||||
return this->by_region;
|
||||
|
||||
// Complex case. Some of the extrusions of some object instances are to be printed first - those are the wiping extrusions.
|
||||
// Some of the extrusions of some object instances are printed later - those are the clean print extrusions.
|
||||
// Filter out the extrusions based on the infill_overrides / perimeter_overrides:
|
||||
|
||||
// Data is cleared, but the memory is not.
|
||||
by_region_per_copy_cache.clear();
|
||||
|
||||
for (const auto& reg : by_region) {
|
||||
by_region_per_copy_cache.push_back(ObjectByExtruder::Island::Region()); // creates a region in the newly created Island
|
||||
by_region_per_copy_cache.emplace_back(); // creates a region in the newly created Island
|
||||
|
||||
// Now we are going to iterate through perimeters and infills and pick ones that are supposed to be printed
|
||||
// References are used so that we don't have to repeat the same code
|
||||
for (int iter = 0; iter < 2; ++iter) {
|
||||
const ExtrusionEntitiesPtr& entities = (iter ? reg.infills.entities : reg.perimeters.entities);
|
||||
ExtrusionEntityCollection& target_eec = (iter ? by_region_per_copy_cache.back().infills : by_region_per_copy_cache.back().perimeters);
|
||||
const std::vector<const ExtruderPerCopy*>& overrides = (iter ? reg.infills_overrides : reg.perimeters_overrides);
|
||||
const ExtrusionEntitiesPtr& entities = (iter ? reg.infills.entities : reg.perimeters.entities);
|
||||
ExtrusionEntityCollection& target_eec = (iter ? by_region_per_copy_cache.back().infills : by_region_per_copy_cache.back().perimeters);
|
||||
const std::vector<const WipingExtrusions::ExtruderPerCopy*>& overrides = (iter ? reg.infills_overrides : reg.perimeters_overrides);
|
||||
|
||||
// Now the most important thing - which extrusion should we print.
|
||||
// See function ToolOrdering::get_extruder_overrides for details about the negative numbers hack.
|
||||
int this_extruder_mark = wiping_entities ? extruder : -extruder-1;
|
||||
|
||||
for (unsigned int i=0;i<entities.size();++i)
|
||||
if (overrides[i]->at(copy) == this_extruder_mark) // this copy should be printed with this extruder
|
||||
target_eec.append((*entities[i]));
|
||||
if (wiping_entities) {
|
||||
// Apply overrides for this region.
|
||||
for (unsigned int i = 0; i < overrides.size(); ++ i) {
|
||||
const WipingExtrusions::ExtruderPerCopy *this_override = overrides[i];
|
||||
// This copy (aka object instance) should be printed with this extruder, which overrides the default one.
|
||||
if (this_override != nullptr && (*this_override)[copy] == extruder)
|
||||
// Clone the ExtrusionEntity. This is quite expensive.
|
||||
target_eec.append((*entities[i]));
|
||||
}
|
||||
} else {
|
||||
// Apply normal extrusions (non-overrides) for this region.
|
||||
unsigned int i = 0;
|
||||
for (; i < overrides.size(); ++ i) {
|
||||
const WipingExtrusions::ExtruderPerCopy *this_override = overrides[i];
|
||||
// This copy (aka object instance) should be printed with this extruder, which shall be equal to the default one.
|
||||
if (this_override == nullptr || (*this_override)[copy] == -extruder-1)
|
||||
// Clone the ExtrusionEntity. This is quite expensive.
|
||||
target_eec.append((*entities[i]));
|
||||
}
|
||||
for (; i < overrides.size(); ++ i)
|
||||
// Clone the ExtrusionEntity. This is quite expensive.
|
||||
target_eec.append(*entities[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return by_region_per_copy_cache;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This function takes the eec and appends its entities to either perimeters or infills of this Region (depending on the first parameter)
|
||||
// It also saves pointer to ExtruderPerCopy struct (for each entity), that holds information about which extruders should be used for which copy.
|
||||
void GCode::ObjectByExtruder::Island::Region::append(const std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copies_extruder, size_t object_copies_num)
|
||||
void GCode::ObjectByExtruder::Island::Region::append(const Type type, const ExtrusionEntityCollection* eec, const WipingExtrusions::ExtruderPerCopy* copies_extruder)
|
||||
{
|
||||
// We are going to manipulate either perimeters or infills, exactly in the same way. Let's create pointers to the proper structure to not repeat ourselves:
|
||||
ExtrusionEntityCollection* perimeters_or_infills = &infills;
|
||||
std::vector<const ExtruderPerCopy*>* perimeters_or_infills_overrides = &infills_overrides;
|
||||
ExtrusionEntityCollection* perimeters_or_infills;
|
||||
std::vector<const WipingExtrusions::ExtruderPerCopy*>* perimeters_or_infills_overrides;
|
||||
|
||||
if (type == "perimeters") {
|
||||
perimeters_or_infills = &perimeters;
|
||||
perimeters_or_infills_overrides = &perimeters_overrides;
|
||||
switch (type) {
|
||||
case PERIMETERS:
|
||||
perimeters_or_infills = &perimeters;
|
||||
perimeters_or_infills_overrides = &perimeters_overrides;
|
||||
break;
|
||||
case INFILL:
|
||||
perimeters_or_infills = &infills;
|
||||
perimeters_or_infills_overrides = &infills_overrides;
|
||||
break;
|
||||
default:
|
||||
throw std::invalid_argument("Unknown parameter!");
|
||||
}
|
||||
else
|
||||
if (type != "infills") {
|
||||
throw std::invalid_argument("Unknown parameter!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// First we append the entities, there are eec->entities.size() of them:
|
||||
size_t old_size = perimeters_or_infills->entities.size();
|
||||
perimeters_or_infills->append(eec->entities);
|
||||
|
||||
for (unsigned int i=0;i<eec->entities.size();++i)
|
||||
perimeters_or_infills_overrides->push_back(copies_extruder);
|
||||
if (copies_extruder != nullptr) {
|
||||
perimeters_or_infills_overrides->reserve(old_size + eec->entities.size());
|
||||
perimeters_or_infills_overrides->resize(old_size, nullptr);
|
||||
for (unsigned int i = 0; i < eec->entities.size(); ++ i)
|
||||
perimeters_or_infills_overrides->emplace_back(copies_extruder);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -239,7 +239,6 @@ protected:
|
|||
std::string extrude_multi_path(ExtrusionMultiPath multipath, std::string description = "", double speed = -1.);
|
||||
std::string extrude_path(ExtrusionPath path, std::string description = "", double speed = -1.);
|
||||
|
||||
typedef std::vector<int> ExtruderPerCopy;
|
||||
// Extruding multiple objects with soluble / non-soluble / combined supports
|
||||
// on a multi-material printer, trying to minimize tool switches.
|
||||
// Following structures sort extrusions by the extruder ID, by an order of objects and object islands.
|
||||
|
@ -256,18 +255,23 @@ protected:
|
|||
ExtrusionEntityCollection perimeters;
|
||||
ExtrusionEntityCollection infills;
|
||||
|
||||
std::vector<const ExtruderPerCopy*> infills_overrides;
|
||||
std::vector<const ExtruderPerCopy*> perimeters_overrides;
|
||||
std::vector<const WipingExtrusions::ExtruderPerCopy*> infills_overrides;
|
||||
std::vector<const WipingExtrusions::ExtruderPerCopy*> perimeters_overrides;
|
||||
|
||||
enum Type {
|
||||
PERIMETERS,
|
||||
INFILL,
|
||||
};
|
||||
|
||||
// Appends perimeter/infill entities and writes don't indices of those that are not to be extruder as part of perimeter/infill wiping
|
||||
void append(const std::string& type, const ExtrusionEntityCollection* eec, const ExtruderPerCopy* copy_extruders, size_t object_copies_num);
|
||||
void append(const Type type, const ExtrusionEntityCollection* eec, const WipingExtrusions::ExtruderPerCopy* copy_extruders);
|
||||
};
|
||||
|
||||
std::vector<Region> by_region; // all extrusions for this island, grouped by regions
|
||||
const std::vector<Region>& by_region_per_copy(unsigned int copy, int extruder, bool wiping_entities = false); // returns reference to subvector of by_region
|
||||
|
||||
private:
|
||||
std::vector<Region> by_region_per_copy_cache; // caches vector generated by function above to avoid copying and recalculating
|
||||
std::vector<Region> by_region; // all extrusions for this island, grouped by regions
|
||||
|
||||
// Fills in by_region_per_copy_cache and returns its reference.
|
||||
const std::vector<Region>& by_region_per_copy(std::vector<Region> &by_region_per_copy_cache, unsigned int copy, int extruder, bool wiping_entities = false) const;
|
||||
};
|
||||
std::vector<Island> islands;
|
||||
};
|
||||
|
@ -277,7 +281,9 @@ protected:
|
|||
InstanceToPrint(ObjectByExtruder &object_by_extruder, size_t layer_id, const PrintObject &print_object, size_t instance_id) :
|
||||
object_by_extruder(object_by_extruder), layer_id(layer_id), print_object(print_object), instance_id(instance_id) {}
|
||||
|
||||
ObjectByExtruder &object_by_extruder;
|
||||
// Repository
|
||||
ObjectByExtruder &object_by_extruder;
|
||||
// Index into std::vector<LayerToPrint>, which contains Object and Support layers for the current print_z, collected for a single object, or for possibly multiple objects with multiple instances.
|
||||
const size_t layer_id;
|
||||
const PrintObject &print_object;
|
||||
// Instance idx of the copy of a print object.
|
||||
|
@ -285,7 +291,8 @@ protected:
|
|||
};
|
||||
|
||||
std::vector<InstanceToPrint> sort_print_object_instances(
|
||||
std::vector<ObjectByExtruder> &objects_by_extruder,
|
||||
std::vector<ObjectByExtruder> &objects_by_extruder,
|
||||
// Object and Support layers for the current print_z, collected for a single object, or for possibly multiple objects with multiple instances.
|
||||
const std::vector<LayerToPrint> &layers,
|
||||
// Ordering must be defined for normal (non-sequential print).
|
||||
const std::vector<std::pair<size_t, size_t>> *ordering,
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace Slic3r {
|
|||
// Returns true in case that extruder a comes before b (b does not have to be present). False otherwise.
|
||||
bool LayerTools::is_extruder_order(unsigned int a, unsigned int b) const
|
||||
{
|
||||
if (a==b)
|
||||
if (a == b)
|
||||
return false;
|
||||
|
||||
for (auto extruder : extruders) {
|
||||
|
@ -415,10 +415,9 @@ void WipingExtrusions::set_extruder_override(const ExtrusionEntity* entity, unsi
|
|||
{
|
||||
something_overridden = true;
|
||||
|
||||
auto entity_map_it = (entity_map.insert(std::make_pair(entity, std::vector<int>()))).first; // (add and) return iterator
|
||||
auto& copies_vector = entity_map_it->second;
|
||||
if (copies_vector.size() < num_of_copies)
|
||||
copies_vector.resize(num_of_copies, -1);
|
||||
auto entity_map_it = (entity_map.emplace(entity, ExtruderPerCopy())).first; // (add and) return iterator
|
||||
ExtruderPerCopy& copies_vector = entity_map_it->second;
|
||||
copies_vector.resize(num_of_copies, -1);
|
||||
|
||||
if (copies_vector[copy_id] != -1)
|
||||
std::cout << "ERROR: Entity extruder overriden multiple times!!!\n"; // A debugging message - this must never happen.
|
||||
|
@ -426,7 +425,6 @@ void WipingExtrusions::set_extruder_override(const ExtrusionEntity* entity, unsi
|
|||
copies_vector[copy_id] = extruder;
|
||||
}
|
||||
|
||||
|
||||
// Finds first non-soluble extruder on the layer
|
||||
int WipingExtrusions::first_nonsoluble_extruder_on_layer(const PrintConfig& print_config) const
|
||||
{
|
||||
|
@ -622,31 +620,23 @@ void WipingExtrusions::ensure_perimeters_infills_order(const Print& print)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Following function is called from process_layer and returns pointer to vector with information about which extruders should be used for given copy of this entity.
|
||||
// It first makes sure the pointer is valid (creates the vector if it does not exist) and contains a record for each copy
|
||||
// It also modifies the vector in place and changes all -1 to correct_extruder_id (at the time the overrides were created, correct extruders were not known,
|
||||
// so -1 was used as "print as usual".
|
||||
// The resulting vector has to keep track of which extrusions are the ones that were overridden and which were not. In the extruder is used as overridden,
|
||||
// its number is saved as it is (zero-based index). Usual extrusions are saved as -number-1 (unfortunately there is no negative zero).
|
||||
const std::vector<int>* WipingExtrusions::get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies)
|
||||
// Following function is called from GCode::process_layer and returns pointer to vector with information about which extruders should be used for given copy of this entity.
|
||||
// If this extrusion does not have any override, nullptr is returned.
|
||||
// Otherwise it modifies the vector in place and changes all -1 to correct_extruder_id (at the time the overrides were created, correct extruders were not known,
|
||||
// so -1 was used as "print as usual").
|
||||
// The resulting vector therefore keeps track of which extrusions are the ones that were overridden and which were not. If the extruder used is overridden,
|
||||
// its number is saved as is (zero-based index). Regular extrusions are saved as -number-1 (unfortunately there is no negative zero).
|
||||
const WipingExtrusions::ExtruderPerCopy* WipingExtrusions::get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies)
|
||||
{
|
||||
ExtruderPerCopy *overrides = nullptr;
|
||||
auto entity_map_it = entity_map.find(entity);
|
||||
if (entity_map_it == entity_map.end())
|
||||
entity_map_it = (entity_map.insert(std::make_pair(entity, std::vector<int>()))).first;
|
||||
|
||||
// Now the entity_map_it should be valid, let's make sure the vector is long enough:
|
||||
entity_map_it->second.resize(num_of_copies, -1);
|
||||
|
||||
// Each -1 now means "print as usual" - we will replace it with actual extruder id (shifted it so we don't lose that information):
|
||||
std::replace(entity_map_it->second.begin(), entity_map_it->second.end(), -1, -correct_extruder_id-1);
|
||||
|
||||
return &(entity_map_it->second);
|
||||
if (entity_map_it != entity_map.end()) {
|
||||
overrides = &entity_map_it->second;
|
||||
overrides->resize(num_of_copies, -1);
|
||||
// Each -1 now means "print as usual" - we will replace it with actual extruder id (shifted it so we don't lose that information):
|
||||
std::replace(overrides->begin(), overrides->end(), -1, -correct_extruder_id-1);
|
||||
}
|
||||
return overrides;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include <utility>
|
||||
|
||||
#include <boost/container/small_vector.hpp>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class Print;
|
||||
|
@ -25,8 +27,19 @@ public:
|
|||
return something_overridden;
|
||||
}
|
||||
|
||||
// When allocating extruder overrides of an object's ExtrusionEntity, overrides for maximum 3 copies are allocated in place.
|
||||
typedef boost::container::small_vector<int32_t, 3> ExtruderPerCopy;
|
||||
|
||||
class ExtruderOverrides
|
||||
{
|
||||
public:
|
||||
ExtruderOverrides(const ExtruderPerCopy *overrides, const int correct_extruder_id) : m_overrides(overrides) {}
|
||||
private:
|
||||
const ExtruderPerCopy *m_overrides;
|
||||
};
|
||||
|
||||
// This is called from GCode::process_layer - see implementation for further comments:
|
||||
const std::vector<int>* get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies);
|
||||
const ExtruderPerCopy* get_extruder_overrides(const ExtrusionEntity* entity, int correct_extruder_id, size_t num_of_copies);
|
||||
|
||||
// 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:
|
||||
|
@ -50,7 +63,7 @@ private:
|
|||
return (entity_map.find(entity) == entity_map.end() ? false : entity_map.at(entity).at(copy_id) != -1);
|
||||
}
|
||||
|
||||
std::map<const ExtrusionEntity*, std::vector<int>> entity_map; // to keep track of who prints what
|
||||
std::map<const ExtrusionEntity*, ExtruderPerCopy> entity_map; // to keep track of who prints what
|
||||
bool something_overridden = false;
|
||||
const LayerTools* m_layer_tools; // so we know which LayerTools object this belongs to
|
||||
};
|
||||
|
@ -74,6 +87,7 @@ public:
|
|||
bool operator==(const LayerTools &rhs) const { return print_z == rhs.print_z; }
|
||||
|
||||
bool is_extruder_order(unsigned int a, unsigned int b) const;
|
||||
bool has_extruder(unsigned int extruder) const { return std::find(this->extruders.begin(), this->extruders.end(), extruder) != this->extruders.end(); }
|
||||
|
||||
coordf_t print_z;
|
||||
bool has_object;
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
#include <boost/bind.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/warning_disable.hpp>
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include <boost/date_time/local_time/local_time.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
|
Loading…
Reference in a new issue