When generating a g-code for a layer, collect layers of multiple objects

with not exactly the same print_z, but support a slight deviation.
This commit is contained in:
bubnikv 2017-05-23 17:09:43 +02:00
parent ca590cb559
commit 2713aa1772
2 changed files with 86 additions and 38 deletions

View File

@ -264,6 +264,81 @@ inline void writeln(FILE *file, const std::string &what)
fprintf(file, "\n"); fprintf(file, "\n");
} }
// Collect pairs of object_layer + support_layer sorted by print_z.
// object_layer & support_layer are considered to be on the same print_z, if they are not further than EPSILON.
std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObject &object)
{
std::vector<GCode::LayerToPrint> layers_to_print;
layers_to_print.reserve(object.layers.size() + object.support_layers.size());
// Pair the object layers with the support layers by z.
size_t idx_object_layer = 0;
size_t idx_support_layer = 0;
while (idx_object_layer < object.layers.size() || idx_support_layer < object.support_layers.size()) {
LayerToPrint layer_to_print;
layer_to_print.object_layer = (idx_object_layer < object.layers.size()) ? object.layers[idx_object_layer ++] : nullptr;
layer_to_print.support_layer = (idx_support_layer < object.support_layers.size()) ? object.support_layers[idx_support_layer ++] : nullptr;
if (layer_to_print.object_layer && layer_to_print.support_layer) {
if (layer_to_print.object_layer->print_z < layer_to_print.support_layer->print_z - EPSILON) {
layer_to_print.support_layer = nullptr;
-- idx_support_layer;
} else if (layer_to_print.support_layer->print_z < layer_to_print.object_layer->print_z - EPSILON) {
layer_to_print.object_layer = nullptr;
-- idx_object_layer;
}
}
layers_to_print.emplace_back(layer_to_print);
}
return layers_to_print;
}
std::vector<std::pair<coordf_t, std::vector<GCode::LayerToPrint>>> GCode::collect_layers_to_print(const Print &print)
{
struct OrderingItem {
coordf_t print_z;
size_t object_idx;
size_t layer_idx;
};
std::vector<std::vector<LayerToPrint>> per_object(print.objects.size(), std::vector<LayerToPrint>());
std::vector<OrderingItem> ordering;
for (size_t i = 0; i < print.objects.size(); ++ i) {
per_object[i] = collect_layers_to_print(*print.objects[i]);
const LayerToPrint &front = per_object[i].front();
OrderingItem ordering_item;
ordering_item.object_idx = i;
for (const LayerToPrint &ltp : per_object[i]) {
ordering_item.print_z = ltp.print_z();
ordering_item.layer_idx = &ltp - &front;
ordering.emplace_back(ordering_item);
}
}
std::sort(ordering.begin(), ordering.end(), [](const OrderingItem &oi1, const OrderingItem &oi2) { return oi1.print_z < oi2.print_z; });
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print;
// Merge numerically very close Z values.
for (size_t i = 0; i < ordering.size();) {
// Find the last layer with roughly the same print_z.
size_t j = i + 1;
coordf_t zmax = ordering[i].print_z + EPSILON;
for (; j < ordering.size() && ordering[j].print_z <= zmax; ++ j) ;
// Merge into layers_to_print.
std::pair<coordf_t, std::vector<LayerToPrint>> merged;
// Assign an average print_z to the set of layers with nearly equal print_z.
merged.first = 0.5 * (ordering[i].print_z + ordering[j-1].print_z);
merged.second.assign(print.objects.size(), LayerToPrint());
for (; i < j; ++ i) {
const OrderingItem &oi = ordering[i];
assert(merged.second[oi.object_idx].layer() == nullptr);
merged.second[oi.object_idx] = std::move(per_object[oi.object_idx][oi.layer_idx]);
}
layers_to_print.emplace_back(std::move(merged));
}
return layers_to_print;
}
bool GCode::do_export(FILE *file, Print &print) bool GCode::do_export(FILE *file, Print &print)
{ {
// How many times will be change_layer() called? // How many times will be change_layer() called?
@ -539,23 +614,11 @@ bool GCode::do_export(FILE *file, Print &print)
this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, false); this->_print_first_layer_extruder_temperatures(file, print, initial_extruder_id, false);
} }
// Pair the object layers with the support layers by z, extrude them. // Pair the object layers with the support layers by z, extrude them.
size_t idx_object_layer = 0; std::vector<LayerToPrint> layers_to_print = collect_layers_to_print(object);
size_t idx_support_layer = 0; for (const LayerToPrint &ltp : layers_to_print) {
std::vector<LayerToPrint> layers_to_print(1, LayerToPrint()); std::vector<LayerToPrint> lrs;
LayerToPrint &layer_to_print = layers_to_print.front(); lrs.emplace_back(std::move(ltp));
while (idx_object_layer < object.layers.size() || idx_support_layer < object.support_layers.size()) { this->process_layer(file, print, lrs, tool_ordering.tools_for_layer(ltp.print_z()), &copy - object._shifted_copies.data());
layer_to_print.object_layer = (idx_object_layer < object.layers.size()) ? object.layers[idx_object_layer ++] : nullptr;
layer_to_print.support_layer = (idx_support_layer < object.support_layers.size()) ? object.support_layers[idx_support_layer ++] : nullptr;
if (layer_to_print.object_layer && layer_to_print.support_layer) {
if (layer_to_print.object_layer->print_z < layer_to_print.support_layer->print_z) {
layer_to_print.support_layer = nullptr;
-- idx_support_layer;
} else if (layer_to_print.support_layer->print_z < layer_to_print.object_layer->print_z) {
layer_to_print.object_layer = nullptr;
-- idx_object_layer;
}
}
this->process_layer(file, print, layers_to_print, tool_ordering.tools_for_layer(layer_to_print.layer()->print_z), &copy - object._shifted_copies.data());
} }
write(file, this->filter(m_cooling_buffer->flush(), true)); write(file, this->filter(m_cooling_buffer->flush(), true));
++ finished_objects; ++ finished_objects;
@ -573,35 +636,18 @@ bool GCode::do_export(FILE *file, Print &print)
Slic3r::Geometry::chained_path(object_reference_points, object_indices); Slic3r::Geometry::chained_path(object_reference_points, object_indices);
// Sort layers by Z. // Sort layers by Z.
// All extrusion moves with the same top layer height are extruded uninterrupted. // All extrusion moves with the same top layer height are extruded uninterrupted.
std::map<coordf_t, std::vector<LayerToPrint>> layers; std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);
size_t object_order = 0;
for (size_t obj_idx : object_indices) {
PrintObject *print_object = print.objects[obj_idx];
for (Layer *layer : print_object->layers) {
std::vector<LayerToPrint> &object_layers_at_printz = layers[layer->print_z];
if (object_layers_at_printz.empty())
object_layers_at_printz.resize(print.objects.size(), LayerToPrint());
object_layers_at_printz[object_order].object_layer = layer;
}
for (SupportLayer *layer : print_object->support_layers) {
std::vector<LayerToPrint> &object_layers_at_printz = layers[layer->print_z];
if (object_layers_at_printz.empty())
object_layers_at_printz.resize(print.objects.size(), LayerToPrint());
object_layers_at_printz[object_order].support_layer = layer;
}
++ object_order;
}
// Prusa Multi-Material wipe tower. // Prusa Multi-Material wipe tower.
if (print.config.single_extruder_multi_material.value && print.config.wipe_tower.value && if (print.config.single_extruder_multi_material.value && print.config.wipe_tower.value &&
! tool_ordering.empty() && tool_ordering.front().wipe_tower_partitions > 0) ! tool_ordering.empty() && tool_ordering.front().wipe_tower_partitions > 0)
m_wipe_tower.reset(new WipeTowerIntegration(print.config)); m_wipe_tower.reset(new WipeTowerIntegration(print.config));
// Extrude the layers. // Extrude the layers.
for (auto &layer : layers) { for (auto &layer : layers_to_print) {
// layer.second is of type std::vector<LayerToPrint>, // layer.second is of type std::vector<LayerToPrint>,
// wher the objects are sorted by their sorted order given by object_indices. // wher the objects are sorted by their sorted order given by object_indices.
const ToolOrdering::LayerTools &layer_tools = tool_ordering.tools_for_layer(layer.first); const ToolOrdering::LayerTools &layer_tools = tool_ordering.tools_for_layer(layer.first);
if (layer_tools.has_wipe_tower && m_wipe_tower) { if (layer_tools.has_wipe_tower && m_wipe_tower) {
bool first_layer = layer.first == layers.begin()->first; bool first_layer = &layer == layers_to_print.data();
m_wipe_tower->set_layer( m_wipe_tower->set_layer(
layer.first, layer.first,
first_layer ? first_layer ?

View File

@ -140,8 +140,10 @@ protected:
const SupportLayer *support_layer; const SupportLayer *support_layer;
const Layer* layer() const { return (object_layer != nullptr) ? object_layer : support_layer; } const Layer* layer() const { return (object_layer != nullptr) ? object_layer : support_layer; }
const PrintObject* object() const { return (this->layer() != nullptr) ? this->layer()->object() : nullptr; } const PrintObject* object() const { return (this->layer() != nullptr) ? this->layer()->object() : nullptr; }
coordf_t print_z() const { return this->layer()->print_z; } coordf_t print_z() const { return (object_layer != nullptr && support_layer != nullptr) ? 0.5 * (object_layer->print_z + support_layer->print_z) : this->layer()->print_z; }
}; };
static std::vector<GCode::LayerToPrint> collect_layers_to_print(const PrintObject &object);
static std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> collect_layers_to_print(const Print &print);
void process_layer( void process_layer(
// Write into the output file. // Write into the output file.
FILE *file, FILE *file,