Fixed merge conflicts (whitespace only)
This commit is contained in:
parent
46eb96e84f
commit
60cf002e94
2 changed files with 297 additions and 294 deletions
|
@ -820,7 +820,7 @@ void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_
|
||||||
"Is " + path_tmp + " locked?" + '\n');
|
"Is " + path_tmp + " locked?" + '\n');
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Exporting G-code finished" << log_memory_info();
|
BOOST_LOG_TRIVIAL(info) << "Exporting G-code finished" << log_memory_info();
|
||||||
print->set_done(psGCodeExport);
|
print->set_done(psGCodeExport);
|
||||||
|
|
||||||
// Write the profiler measurements to file
|
// Write the profiler measurements to file
|
||||||
PROFILE_UPDATE();
|
PROFILE_UPDATE();
|
||||||
|
@ -983,7 +983,8 @@ namespace DoExport {
|
||||||
return volumetric_speed;
|
return volumetric_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_ooze_prevention(const Print &print, OozePrevention &ooze_prevention)
|
|
||||||
|
static void init_ooze_prevention(const Print &print, OozePrevention &ooze_prevention)
|
||||||
{
|
{
|
||||||
// Calculate wiping points if needed
|
// Calculate wiping points if needed
|
||||||
if (print.config().ooze_prevention.value && ! print.config().single_extruder_multi_material) {
|
if (print.config().ooze_prevention.value && ! print.config().single_extruder_multi_material) {
|
||||||
|
@ -1123,26 +1124,26 @@ namespace DoExport {
|
||||||
}
|
}
|
||||||
filament_stats_string_out += out_filament_used_mm.first;
|
filament_stats_string_out += out_filament_used_mm.first;
|
||||||
filament_stats_string_out += "\n" + out_filament_used_cm3.first;
|
filament_stats_string_out += "\n" + out_filament_used_cm3.first;
|
||||||
if (out_filament_used_g.second)
|
if (out_filament_used_g.second)
|
||||||
filament_stats_string_out += "\n" + out_filament_used_g.first;
|
filament_stats_string_out += "\n" + out_filament_used_g.first;
|
||||||
if (out_filament_cost.second)
|
if (out_filament_cost.second)
|
||||||
filament_stats_string_out += "\n" + out_filament_cost.first;
|
filament_stats_string_out += "\n" + out_filament_cost.first;
|
||||||
}
|
}
|
||||||
return filament_stats_string_out;
|
return filament_stats_string_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the PrintObjects by their increasing Z, likely useful for avoiding colisions on Deltas during sequential prints.
|
// Sort the PrintObjects by their increasing Z, likely useful for avoiding colisions on Deltas during sequential prints.
|
||||||
static inline std::vector<const PrintInstance*> sort_object_instances_by_max_z(const Print &print)
|
static inline std::vector<const PrintInstance*> sort_object_instances_by_max_z(const Print &print)
|
||||||
{
|
{
|
||||||
std::vector<const PrintObject*> objects(print.objects().begin(), print.objects().end());
|
std::vector<const PrintObject*> objects(print.objects().begin(), print.objects().end());
|
||||||
std::sort(objects.begin(), objects.end(), [](const PrintObject *po1, const PrintObject *po2) { return po1->height() < po2->height(); });
|
std::sort(objects.begin(), objects.end(), [](const PrintObject *po1, const PrintObject *po2) { return po1->height() < po2->height(); });
|
||||||
std::vector<const PrintInstance*> instances;
|
std::vector<const PrintInstance*> instances;
|
||||||
instances.reserve(objects.size());
|
instances.reserve(objects.size());
|
||||||
for (const PrintObject *object : objects)
|
for (const PrintObject *object : objects)
|
||||||
for (size_t i = 0; i < object->instances().size(); ++ i)
|
for (size_t i = 0; i < object->instances().size(); ++ i)
|
||||||
instances.emplace_back(&object->instances()[i]);
|
instances.emplace_back(&object->instances()[i]);
|
||||||
return instances;
|
return instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Produce a vector of PrintObjects in the order of their respective ModelObjects in print.model().
|
// Produce a vector of PrintObjects in the order of their respective ModelObjects in print.model().
|
||||||
|
@ -1321,12 +1322,12 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||||
}
|
}
|
||||||
// We don't allow switching of extruders per layer by Model::custom_gcode_per_print_z in sequential mode.
|
// We don't allow switching of extruders per layer by Model::custom_gcode_per_print_z in sequential mode.
|
||||||
// Use the extruder IDs collected from Regions.
|
// Use the extruder IDs collected from Regions.
|
||||||
this->set_extruders(print.extruders());
|
this->set_extruders(print.extruders());
|
||||||
} else {
|
} else {
|
||||||
// Find tool ordering for all the objects at once, and the initial extruder ID.
|
// Find tool ordering for all the objects at once, and the initial extruder ID.
|
||||||
// If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it.
|
// If the tool ordering has been pre-calculated by Print class for wipe tower already, reuse it.
|
||||||
tool_ordering = print.tool_ordering();
|
tool_ordering = print.tool_ordering();
|
||||||
tool_ordering.assign_custom_gcodes(print);
|
tool_ordering.assign_custom_gcodes(print);
|
||||||
has_wipe_tower = print.has_wipe_tower() && tool_ordering.has_wipe_tower();
|
has_wipe_tower = print.has_wipe_tower() && tool_ordering.has_wipe_tower();
|
||||||
initial_extruder_id = (has_wipe_tower && ! print.config().single_extruder_multi_material_priming) ?
|
initial_extruder_id = (has_wipe_tower && ! print.config().single_extruder_multi_material_priming) ?
|
||||||
// The priming towers will be skipped.
|
// The priming towers will be skipped.
|
||||||
|
@ -1335,7 +1336,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||||
tool_ordering.first_extruder();
|
tool_ordering.first_extruder();
|
||||||
// In non-sequential print, the printing extruders may have been modified by the extruder switches stored in Model::custom_gcode_per_print_z.
|
// In non-sequential print, the printing extruders may have been modified by the extruder switches stored in Model::custom_gcode_per_print_z.
|
||||||
// Therefore initialize the printing extruders from there.
|
// Therefore initialize the printing extruders from there.
|
||||||
this->set_extruders(tool_ordering.all_extruders());
|
this->set_extruders(tool_ordering.all_extruders());
|
||||||
// Order object instances using a nearest neighbor search.
|
// Order object instances using a nearest neighbor search.
|
||||||
print_object_instances_ordering = chain_print_object_instances(print);
|
print_object_instances_ordering = chain_print_object_instances(print);
|
||||||
}
|
}
|
||||||
|
@ -1510,7 +1511,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||||
m_wipe_tower.reset(new WipeTowerIntegration(print.config(), *print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()));
|
m_wipe_tower.reset(new WipeTowerIntegration(print.config(), *print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()));
|
||||||
_write(file, m_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height"));
|
_write(file, m_writer.travel_to_z(first_layer_height + m_config.z_offset.value, "Move to the first layer height"));
|
||||||
if (print.config().single_extruder_multi_material_priming) {
|
if (print.config().single_extruder_multi_material_priming) {
|
||||||
_write(file, m_wipe_tower->prime(*this));
|
_write(file, m_wipe_tower->prime(*this));
|
||||||
// Verify, whether the print overaps the priming extrusions.
|
// Verify, whether the print overaps the priming extrusions.
|
||||||
BoundingBoxf bbox_print(get_print_extrusions_extents(print));
|
BoundingBoxf bbox_print(get_print_extrusions_extents(print));
|
||||||
coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON;
|
coordf_t twolayers_printz = ((layers_to_print.size() == 1) ? layers_to_print.front() : layers_to_print[1]).first + EPSILON;
|
||||||
|
@ -1577,7 +1578,7 @@ void GCode::_do_export(Print& print, FILE* file, ThumbnailsGeneratorCallback thu
|
||||||
_writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(extruder_id), extruder_id, &config));
|
_writeln(file, this->placeholder_parser_process("end_filament_gcode", print.config().end_filament_gcode.get_at(extruder_id), extruder_id, &config));
|
||||||
} else {
|
} else {
|
||||||
for (const std::string &end_gcode : print.config().end_filament_gcode.values) {
|
for (const std::string &end_gcode : print.config().end_filament_gcode.values) {
|
||||||
int extruder_id = (unsigned int)(&end_gcode - &print.config().end_filament_gcode.values.front());
|
int extruder_id = (unsigned int)(&end_gcode - &print.config().end_filament_gcode.values.front());
|
||||||
config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id));
|
config.set_key_value("filament_extruder_id", new ConfigOptionInt(extruder_id));
|
||||||
_writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, extruder_id, &config));
|
_writeln(file, this->placeholder_parser_process("end_filament_gcode", end_gcode, extruder_id, &config));
|
||||||
}
|
}
|
||||||
|
@ -1678,12 +1679,12 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc
|
||||||
int mcode = int(strtol(ptr, &endptr, 10));
|
int mcode = int(strtol(ptr, &endptr, 10));
|
||||||
if (endptr != nullptr && endptr != ptr && (mcode == mcode_set_temp_dont_wait || mcode == mcode_set_temp_and_wait)) {
|
if (endptr != nullptr && endptr != ptr && (mcode == mcode_set_temp_dont_wait || mcode == mcode_set_temp_and_wait)) {
|
||||||
// M104/M109 or M140/M190 found.
|
// M104/M109 or M140/M190 found.
|
||||||
ptr = endptr;
|
ptr = endptr;
|
||||||
// Let the caller know that the custom G-code sets the temperature.
|
// Let the caller know that the custom G-code sets the temperature.
|
||||||
temp_set_by_gcode = true;
|
temp_set_by_gcode = true;
|
||||||
// Now try to parse the temperature value.
|
// Now try to parse the temperature value.
|
||||||
// While not at the end of the line:
|
// While not at the end of the line:
|
||||||
while (strchr(";\r\n\0", *ptr) == nullptr) {
|
while (strchr(";\r\n\0", *ptr) == nullptr) {
|
||||||
// Skip whitespaces.
|
// Skip whitespaces.
|
||||||
for (; *ptr == ' ' || *ptr == '\t'; ++ ptr);
|
for (; *ptr == ' ' || *ptr == '\t'; ++ ptr);
|
||||||
if (*ptr == 'S') {
|
if (*ptr == 'S') {
|
||||||
|
@ -1692,22 +1693,22 @@ static bool custom_gcode_sets_temperature(const std::string &gcode, const int mc
|
||||||
// Parse an int.
|
// Parse an int.
|
||||||
endptr = nullptr;
|
endptr = nullptr;
|
||||||
long temp_parsed = strtol(ptr, &endptr, 10);
|
long temp_parsed = strtol(ptr, &endptr, 10);
|
||||||
if (endptr > ptr) {
|
if (endptr > ptr) {
|
||||||
ptr = endptr;
|
ptr = endptr;
|
||||||
temp_out = temp_parsed;
|
temp_out = temp_parsed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Skip this word.
|
// Skip this word.
|
||||||
for (; strchr(" \t;\r\n\0", *ptr) == nullptr; ++ ptr);
|
for (; strchr(" \t;\r\n\0", *ptr) == nullptr; ++ ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Skip the rest of the line.
|
// Skip the rest of the line.
|
||||||
for (; *ptr != 0 && *ptr != '\r' && *ptr != '\n'; ++ ptr);
|
for (; *ptr != 0 && *ptr != '\r' && *ptr != '\n'; ++ ptr);
|
||||||
// Skip the end of line indicators.
|
// Skip the end of line indicators.
|
||||||
for (; *ptr == '\r' || *ptr == '\n'; ++ ptr);
|
for (; *ptr == '\r' || *ptr == '\n'; ++ ptr);
|
||||||
}
|
}
|
||||||
return temp_set_by_gcode;
|
return temp_set_by_gcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1821,82 +1822,82 @@ inline std::vector<GCode::ObjectByExtruder::Island>& object_islands_by_extruder(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<GCode::InstanceToPrint> GCode::sort_print_object_instances(
|
std::vector<GCode::InstanceToPrint> GCode::sort_print_object_instances(
|
||||||
std::vector<GCode::ObjectByExtruder> &objects_by_extruder,
|
std::vector<GCode::ObjectByExtruder> &objects_by_extruder,
|
||||||
const std::vector<LayerToPrint> &layers,
|
const std::vector<LayerToPrint> &layers,
|
||||||
// Ordering must be defined for normal (non-sequential print).
|
// Ordering must be defined for normal (non-sequential print).
|
||||||
const std::vector<const PrintInstance*> *ordering,
|
const std::vector<const PrintInstance*> *ordering,
|
||||||
// For sequential print, the instance of the object to be printing has to be defined.
|
// For sequential print, the instance of the object to be printing has to be defined.
|
||||||
const size_t single_object_instance_idx)
|
const size_t single_object_instance_idx)
|
||||||
{
|
{
|
||||||
std::vector<InstanceToPrint> out;
|
std::vector<InstanceToPrint> out;
|
||||||
|
|
||||||
if (ordering == nullptr) {
|
if (ordering == nullptr) {
|
||||||
// Sequential print, single object is being printed.
|
// Sequential print, single object is being printed.
|
||||||
for (ObjectByExtruder &object_by_extruder : objects_by_extruder) {
|
for (ObjectByExtruder &object_by_extruder : objects_by_extruder) {
|
||||||
const size_t layer_id = &object_by_extruder - objects_by_extruder.data();
|
const size_t layer_id = &object_by_extruder - objects_by_extruder.data();
|
||||||
const PrintObject *print_object = layers[layer_id].object();
|
const PrintObject *print_object = layers[layer_id].object();
|
||||||
if (print_object)
|
if (print_object)
|
||||||
out.emplace_back(object_by_extruder, layer_id, *print_object, single_object_instance_idx);
|
out.emplace_back(object_by_extruder, layer_id, *print_object, single_object_instance_idx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Create mapping from PrintObject* to ObjectByExtruder*.
|
// Create mapping from PrintObject* to ObjectByExtruder*.
|
||||||
std::vector<std::pair<const PrintObject*, ObjectByExtruder*>> sorted;
|
std::vector<std::pair<const PrintObject*, ObjectByExtruder*>> sorted;
|
||||||
sorted.reserve(objects_by_extruder.size());
|
sorted.reserve(objects_by_extruder.size());
|
||||||
for (ObjectByExtruder &object_by_extruder : objects_by_extruder) {
|
for (ObjectByExtruder &object_by_extruder : objects_by_extruder) {
|
||||||
const size_t layer_id = &object_by_extruder - objects_by_extruder.data();
|
const size_t layer_id = &object_by_extruder - objects_by_extruder.data();
|
||||||
const PrintObject *print_object = layers[layer_id].object();
|
const PrintObject *print_object = layers[layer_id].object();
|
||||||
if (print_object)
|
if (print_object)
|
||||||
sorted.emplace_back(print_object, &object_by_extruder);
|
sorted.emplace_back(print_object, &object_by_extruder);
|
||||||
}
|
}
|
||||||
std::sort(sorted.begin(), sorted.end());
|
std::sort(sorted.begin(), sorted.end());
|
||||||
|
|
||||||
if (! sorted.empty()) {
|
if (! sorted.empty()) {
|
||||||
out.reserve(sorted.size());
|
out.reserve(sorted.size());
|
||||||
for (const PrintInstance *instance : *ordering) {
|
for (const PrintInstance *instance : *ordering) {
|
||||||
const PrintObject &print_object = *instance->print_object;
|
const PrintObject &print_object = *instance->print_object;
|
||||||
std::pair<const PrintObject*, ObjectByExtruder*> key(&print_object, nullptr);
|
std::pair<const PrintObject*, ObjectByExtruder*> key(&print_object, nullptr);
|
||||||
auto it = std::lower_bound(sorted.begin(), sorted.end(), key);
|
auto it = std::lower_bound(sorted.begin(), sorted.end(), key);
|
||||||
if (it != sorted.end() && it->first == &print_object)
|
if (it != sorted.end() && it->first == &print_object)
|
||||||
// ObjectByExtruder for this PrintObject was found.
|
// ObjectByExtruder for this PrintObject was found.
|
||||||
out.emplace_back(*it->second, it->second - objects_by_extruder.data(), print_object, instance - print_object.instances().data());
|
out.emplace_back(*it->second, it->second - objects_by_extruder.data(), print_object, instance - print_object.instances().data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ProcessLayer
|
namespace ProcessLayer
|
||||||
{
|
{
|
||||||
|
|
||||||
static std::string emit_custom_gcode_per_print_z(
|
static std::string emit_custom_gcode_per_print_z(
|
||||||
const CustomGCode::Item *custom_gcode,
|
const CustomGCode::Item *custom_gcode,
|
||||||
// ID of the first extruder printing this layer.
|
// ID of the first extruder printing this layer.
|
||||||
unsigned int first_extruder_id,
|
unsigned int first_extruder_id,
|
||||||
const PrintConfig &config)
|
const PrintConfig &config)
|
||||||
{
|
{
|
||||||
std::string gcode;
|
std::string gcode;
|
||||||
bool single_extruder_printer = config.nozzle_diameter.size() == 1;
|
bool single_extruder_printer = config.nozzle_diameter.size() == 1;
|
||||||
|
|
||||||
if (custom_gcode != nullptr) {
|
if (custom_gcode != nullptr) {
|
||||||
// Extruder switches are processed by LayerTools, they should be filtered out.
|
// Extruder switches are processed by LayerTools, they should be filtered out.
|
||||||
assert(custom_gcode->type != CustomGCode::ToolChange);
|
assert(custom_gcode->type != CustomGCode::ToolChange);
|
||||||
|
|
||||||
CustomGCode::Type gcode_type = custom_gcode->type;
|
CustomGCode::Type gcode_type = custom_gcode->type;
|
||||||
bool color_change = gcode_type == CustomGCode::ColorChange;
|
bool color_change = gcode_type == CustomGCode::ColorChange;
|
||||||
bool tool_change = gcode_type == CustomGCode::ToolChange;
|
bool tool_change = gcode_type == CustomGCode::ToolChange;
|
||||||
// Tool Change is applied as Color Change for a single extruder printer only.
|
// Tool Change is applied as Color Change for a single extruder printer only.
|
||||||
assert(! tool_change || single_extruder_printer);
|
assert(! tool_change || single_extruder_printer);
|
||||||
|
|
||||||
std::string pause_print_msg;
|
std::string pause_print_msg;
|
||||||
int m600_extruder_before_layer = -1;
|
int m600_extruder_before_layer = -1;
|
||||||
if (color_change && custom_gcode->extruder > 0)
|
if (color_change && custom_gcode->extruder > 0)
|
||||||
m600_extruder_before_layer = custom_gcode->extruder - 1;
|
m600_extruder_before_layer = custom_gcode->extruder - 1;
|
||||||
else if (gcode_type == CustomGCode::PausePrint)
|
else if (gcode_type == CustomGCode::PausePrint)
|
||||||
pause_print_msg = custom_gcode->extra;
|
pause_print_msg = custom_gcode->extra;
|
||||||
|
|
||||||
// we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count
|
// we should add or not colorprint_change in respect to nozzle_diameter count instead of really used extruders count
|
||||||
if (color_change || tool_change)
|
if (color_change || tool_change)
|
||||||
{
|
{
|
||||||
assert(m600_extruder_before_layer >= 0);
|
assert(m600_extruder_before_layer >= 0);
|
||||||
// Color Change or Tool Change as Color Change.
|
// Color Change or Tool Change as Color Change.
|
||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
|
@ -1910,13 +1911,13 @@ namespace ProcessLayer
|
||||||
#endif // ENABLE_GCODE_VIEWER
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
|
|
||||||
if (!single_extruder_printer && m600_extruder_before_layer >= 0 && first_extruder_id != (unsigned)m600_extruder_before_layer
|
if (!single_extruder_printer && m600_extruder_before_layer >= 0 && first_extruder_id != (unsigned)m600_extruder_before_layer
|
||||||
// && !MMU1
|
// && !MMU1
|
||||||
) {
|
) {
|
||||||
//! FIXME_in_fw show message during print pause
|
//! FIXME_in_fw show message during print pause
|
||||||
gcode += config.pause_print_gcode;// pause print
|
gcode += config.pause_print_gcode;// pause print
|
||||||
gcode += "\n";
|
gcode += "\n";
|
||||||
gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n";
|
gcode += "M117 Change filament for Extruder " + std::to_string(m600_extruder_before_layer) + "\n";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
gcode += config.color_change_gcode;//ColorChangeCode;
|
gcode += config.color_change_gcode;//ColorChangeCode;
|
||||||
gcode += "\n";
|
gcode += "\n";
|
||||||
|
@ -1956,32 +1957,32 @@ namespace ProcessLayer
|
||||||
if (gcode_type == CustomGCode::Template) // Template Cistom Gcode
|
if (gcode_type == CustomGCode::Template) // Template Cistom Gcode
|
||||||
gcode += config.template_custom_gcode;
|
gcode += config.template_custom_gcode;
|
||||||
else // custom Gcode
|
else // custom Gcode
|
||||||
gcode += custom_gcode->extra;
|
gcode += custom_gcode->extra;
|
||||||
|
|
||||||
}
|
}
|
||||||
gcode += "\n";
|
gcode += "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return gcode;
|
return gcode;
|
||||||
}
|
}
|
||||||
} // namespace ProcessLayer
|
} // namespace ProcessLayer
|
||||||
|
|
||||||
namespace Skirt {
|
namespace Skirt {
|
||||||
static void skirt_loops_per_extruder_all_printing(const Print &print, const LayerTools &layer_tools, std::map<unsigned int, std::pair<size_t, size_t>> &skirt_loops_per_extruder_out)
|
static void skirt_loops_per_extruder_all_printing(const Print &print, const LayerTools &layer_tools, std::map<unsigned int, std::pair<size_t, size_t>> &skirt_loops_per_extruder_out)
|
||||||
{
|
{
|
||||||
// Prime all extruders printing over the 1st layer over the skirt lines.
|
// Prime all extruders printing over the 1st layer over the skirt lines.
|
||||||
size_t n_loops = print.skirt().entities.size();
|
size_t n_loops = print.skirt().entities.size();
|
||||||
size_t n_tools = layer_tools.extruders.size();
|
size_t n_tools = layer_tools.extruders.size();
|
||||||
size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
|
size_t lines_per_extruder = (n_loops + n_tools - 1) / n_tools;
|
||||||
for (size_t i = 0; i < n_loops; i += lines_per_extruder)
|
for (size_t i = 0; i < n_loops; i += lines_per_extruder)
|
||||||
skirt_loops_per_extruder_out[layer_tools.extruders[i / lines_per_extruder]] = std::pair<size_t, size_t>(i, std::min(i + lines_per_extruder, n_loops));
|
skirt_loops_per_extruder_out[layer_tools.extruders[i / lines_per_extruder]] = std::pair<size_t, size_t>(i, std::min(i + lines_per_extruder, n_loops));
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::map<unsigned int, std::pair<size_t, size_t>> make_skirt_loops_per_extruder_1st_layer(
|
static std::map<unsigned int, std::pair<size_t, size_t>> make_skirt_loops_per_extruder_1st_layer(
|
||||||
const Print &print,
|
const Print &print,
|
||||||
const std::vector<GCode::LayerToPrint> & /*layers */,
|
const std::vector<GCode::LayerToPrint> & /*layers */,
|
||||||
const LayerTools &layer_tools,
|
const LayerTools &layer_tools,
|
||||||
// Heights (print_z) at which the skirt has already been extruded.
|
// Heights (print_z) at which the skirt has already been extruded.
|
||||||
std::vector<coordf_t> &skirt_done)
|
std::vector<coordf_t> &skirt_done)
|
||||||
{
|
{
|
||||||
|
@ -1989,7 +1990,7 @@ namespace Skirt {
|
||||||
// not at the print_z of the interlaced support material layers.
|
// not at the print_z of the interlaced support material layers.
|
||||||
std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
|
std::map<unsigned int, std::pair<size_t, size_t>> skirt_loops_per_extruder_out;
|
||||||
if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty()) {
|
if (skirt_done.empty() && print.has_skirt() && ! print.skirt().entities.empty()) {
|
||||||
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
|
skirt_loops_per_extruder_all_printing(print, layer_tools, skirt_loops_per_extruder_out);
|
||||||
skirt_done.emplace_back(layer_tools.print_z);
|
skirt_done.emplace_back(layer_tools.print_z);
|
||||||
}
|
}
|
||||||
return skirt_loops_per_extruder_out;
|
return skirt_loops_per_extruder_out;
|
||||||
|
@ -1997,11 +1998,11 @@ namespace Skirt {
|
||||||
|
|
||||||
static std::map<unsigned int, std::pair<size_t, size_t>> make_skirt_loops_per_extruder_other_layers(
|
static std::map<unsigned int, std::pair<size_t, size_t>> make_skirt_loops_per_extruder_other_layers(
|
||||||
const Print &print,
|
const Print &print,
|
||||||
const std::vector<GCode::LayerToPrint> &layers,
|
const std::vector<GCode::LayerToPrint> &layers,
|
||||||
const LayerTools &layer_tools,
|
const LayerTools &layer_tools,
|
||||||
// First non-empty support layer.
|
// First non-empty support layer.
|
||||||
const SupportLayer *support_layer,
|
const SupportLayer *support_layer,
|
||||||
// Heights (print_z) at which the skirt has already been extruded.
|
// Heights (print_z) at which the skirt has already been extruded.
|
||||||
std::vector<coordf_t> &skirt_done)
|
std::vector<coordf_t> &skirt_done)
|
||||||
{
|
{
|
||||||
// Extrude skirt at the print_z of the raft layers and normal object layers
|
// Extrude skirt at the print_z of the raft layers and normal object layers
|
||||||
|
@ -2043,8 +2044,8 @@ void GCode::process_layer(
|
||||||
// Set of object & print layers of the same PrintObject and with the same print_z.
|
// Set of object & print layers of the same PrintObject and with the same print_z.
|
||||||
const std::vector<LayerToPrint> &layers,
|
const std::vector<LayerToPrint> &layers,
|
||||||
const LayerTools &layer_tools,
|
const LayerTools &layer_tools,
|
||||||
// Pairs of PrintObject index and its instance index.
|
// Pairs of PrintObject index and its instance index.
|
||||||
const std::vector<const PrintInstance*> *ordering,
|
const std::vector<const PrintInstance*> *ordering,
|
||||||
// If set to size_t(-1), then print all copies of all objects.
|
// If set to size_t(-1), then print all copies of all objects.
|
||||||
// Otherwise print a single copy of a single object.
|
// Otherwise print a single copy of a single object.
|
||||||
const size_t single_object_instance_idx)
|
const size_t single_object_instance_idx)
|
||||||
|
@ -2120,7 +2121,7 @@ void GCode::process_layer(
|
||||||
+ "\n";
|
+ "\n";
|
||||||
}
|
}
|
||||||
gcode += this->change_layer(print_z); // this will increase m_layer_index
|
gcode += this->change_layer(print_z); // this will increase m_layer_index
|
||||||
m_layer = &layer;
|
m_layer = &layer;
|
||||||
if (! print.config().layer_gcode.value.empty()) {
|
if (! print.config().layer_gcode.value.empty()) {
|
||||||
DynamicConfig config;
|
DynamicConfig config;
|
||||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||||
|
@ -2228,11 +2229,11 @@ void GCode::process_layer(
|
||||||
std::vector<size_t> slices_test_order;
|
std::vector<size_t> slices_test_order;
|
||||||
slices_test_order.reserve(n_slices);
|
slices_test_order.reserve(n_slices);
|
||||||
for (size_t i = 0; i < n_slices; ++ i)
|
for (size_t i = 0; i < n_slices; ++ i)
|
||||||
slices_test_order.emplace_back(i);
|
slices_test_order.emplace_back(i);
|
||||||
std::sort(slices_test_order.begin(), slices_test_order.end(), [&layer_surface_bboxes](size_t i, size_t j) {
|
std::sort(slices_test_order.begin(), slices_test_order.end(), [&layer_surface_bboxes](size_t i, size_t j) {
|
||||||
const Vec2d s1 = layer_surface_bboxes[i].size().cast<double>();
|
const Vec2d s1 = layer_surface_bboxes[i].size().cast<double>();
|
||||||
const Vec2d s2 = layer_surface_bboxes[j].size().cast<double>();
|
const Vec2d s2 = layer_surface_bboxes[j].size().cast<double>();
|
||||||
return s1.x() * s1.y() < s2.x() * s2.y();
|
return s1.x() * s1.y() < s2.x() * s2.y();
|
||||||
});
|
});
|
||||||
auto point_inside_surface = [&layer, &layer_surface_bboxes](const size_t i, const Point &point) {
|
auto point_inside_surface = [&layer, &layer_surface_bboxes](const size_t i, const Point &point) {
|
||||||
const BoundingBox &bbox = layer_surface_bboxes[i];
|
const BoundingBox &bbox = layer_surface_bboxes[i];
|
||||||
|
@ -2265,27 +2266,27 @@ void GCode::process_layer(
|
||||||
// Let's recover vector of extruder overrides:
|
// Let's recover vector of extruder overrides:
|
||||||
const WipingExtrusions::ExtruderPerCopy *entity_overrides = nullptr;
|
const WipingExtrusions::ExtruderPerCopy *entity_overrides = nullptr;
|
||||||
if (! layer_tools.has_extruder(correct_extruder_id)) {
|
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
|
// 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)
|
// 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)
|
||||||
correct_extruder_id = layer_tools.extruders.back();
|
correct_extruder_id = layer_tools.extruders.back();
|
||||||
}
|
}
|
||||||
printing_extruders.clear();
|
printing_extruders.clear();
|
||||||
if (is_anything_overridden) {
|
if (is_anything_overridden) {
|
||||||
entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(extrusions, correct_extruder_id, layer_to_print.object()->instances().size());
|
entity_overrides = const_cast<LayerTools&>(layer_tools).wiping_extrusions().get_extruder_overrides(extrusions, correct_extruder_id, layer_to_print.object()->instances().size());
|
||||||
if (entity_overrides == nullptr) {
|
if (entity_overrides == nullptr) {
|
||||||
printing_extruders.emplace_back(correct_extruder_id);
|
printing_extruders.emplace_back(correct_extruder_id);
|
||||||
} else {
|
} else {
|
||||||
printing_extruders.reserve(entity_overrides->size());
|
printing_extruders.reserve(entity_overrides->size());
|
||||||
for (int extruder : *entity_overrides)
|
for (int extruder : *entity_overrides)
|
||||||
printing_extruders.emplace_back(extruder >= 0 ?
|
printing_extruders.emplace_back(extruder >= 0 ?
|
||||||
// at least one copy is overridden to use this extruder
|
// at least one copy is overridden to use this extruder
|
||||||
extruder :
|
extruder :
|
||||||
// at least one copy would normally be printed with this extruder (see get_extruder_overrides function for explanation)
|
// at least one copy would normally be printed with this extruder (see get_extruder_overrides function for explanation)
|
||||||
static_cast<unsigned int>(- extruder - 1));
|
static_cast<unsigned int>(- extruder - 1));
|
||||||
Slic3r::sort_remove_duplicates(printing_extruders);
|
Slic3r::sort_remove_duplicates(printing_extruders);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
printing_extruders.emplace_back(correct_extruder_id);
|
printing_extruders.emplace_back(correct_extruder_id);
|
||||||
|
|
||||||
// Now we must add this extrusion into the by_extruder map, once for each extruder that will print it:
|
// Now we must add this extrusion into the by_extruder map, once for each extruder that will print it:
|
||||||
for (unsigned int extruder : printing_extruders)
|
for (unsigned int extruder : printing_extruders)
|
||||||
|
@ -2296,10 +2297,10 @@ void GCode::process_layer(
|
||||||
&layer_to_print - layers.data(),
|
&layer_to_print - layers.data(),
|
||||||
layers.size(), n_slices+1);
|
layers.size(), n_slices+1);
|
||||||
for (size_t i = 0; i <= n_slices; ++ i) {
|
for (size_t i = 0; i <= n_slices; ++ i) {
|
||||||
bool last = i == n_slices;
|
bool last = i == n_slices;
|
||||||
size_t island_idx = last ? n_slices : slices_test_order[i];
|
size_t island_idx = last ? n_slices : slices_test_order[i];
|
||||||
if (// extrusions->first_point does not fit inside any slice
|
if (// extrusions->first_point does not fit inside any slice
|
||||||
last ||
|
last ||
|
||||||
// extrusions->first_point fits inside ith slice
|
// extrusions->first_point fits inside ith slice
|
||||||
point_inside_surface(island_idx, extrusions->first_point())) {
|
point_inside_surface(island_idx, extrusions->first_point())) {
|
||||||
if (islands[island_idx].by_region.empty())
|
if (islands[island_idx].by_region.empty())
|
||||||
|
@ -2374,10 +2375,10 @@ void GCode::process_layer(
|
||||||
if (objects_by_extruder_it == by_extruder.end())
|
if (objects_by_extruder_it == by_extruder.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
std::vector<InstanceToPrint> instances_to_print = sort_print_object_instances(objects_by_extruder_it->second, layers, ordering, single_object_instance_idx);
|
std::vector<InstanceToPrint> instances_to_print = sort_print_object_instances(objects_by_extruder_it->second, layers, ordering, single_object_instance_idx);
|
||||||
|
|
||||||
// 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):
|
// 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):
|
||||||
std::vector<ObjectByExtruder::Island::Region> by_region_per_copy_cache;
|
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) {
|
for (int print_wipe_extrusions = is_anything_overridden; print_wipe_extrusions>=0; --print_wipe_extrusions) {
|
||||||
if (is_anything_overridden && print_wipe_extrusions == 0)
|
if (is_anything_overridden && print_wipe_extrusions == 0)
|
||||||
gcode+="; PURGING FINISHED\n";
|
gcode+="; PURGING FINISHED\n";
|
||||||
|
@ -2406,7 +2407,7 @@ void GCode::process_layer(
|
||||||
}
|
}
|
||||||
for (ObjectByExtruder::Island &island : instance_to_print.object_by_extruder.islands) {
|
for (ObjectByExtruder::Island &island : instance_to_print.object_by_extruder.islands) {
|
||||||
const auto& by_region_specific = is_anything_overridden ? island.by_region_per_copy(by_region_per_copy_cache, static_cast<unsigned int>(instance_to_print.instance_id), extruder_id, print_wipe_extrusions != 0) : island.by_region;
|
const auto& by_region_specific = is_anything_overridden ? island.by_region_per_copy(by_region_per_copy_cache, static_cast<unsigned int>(instance_to_print.instance_id), extruder_id, print_wipe_extrusions != 0) : island.by_region;
|
||||||
//FIXME the following code prints regions in the order they are defined, the path is not optimized in any way.
|
//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) {
|
if (print.config().infill_first) {
|
||||||
gcode += this->extrude_infill(print, by_region_specific, false);
|
gcode += this->extrude_infill(print, by_region_specific, false);
|
||||||
gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]);
|
gcode += this->extrude_perimeters(print, by_region_specific, lower_layer_edge_grids[instance_to_print.layer_id]);
|
||||||
|
@ -2418,7 +2419,7 @@ void GCode::process_layer(
|
||||||
gcode += this->extrude_infill(print,by_region_specific, true);
|
gcode += this->extrude_infill(print,by_region_specific, true);
|
||||||
}
|
}
|
||||||
if (this->config().gcode_label_objects)
|
if (this->config().gcode_label_objects)
|
||||||
gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.layer_id) + " copy " + std::to_string(instance_to_print.instance_id) + "\n";
|
gcode += std::string("; stop printing object ") + instance_to_print.print_object.model_object()->name + " id:" + std::to_string(instance_to_print.layer_id) + " copy " + std::to_string(instance_to_print.instance_id) + "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2470,19 +2471,19 @@ void GCode::apply_print_config(const PrintConfig &print_config)
|
||||||
|
|
||||||
void GCode::append_full_config(const Print &print, std::string &str)
|
void GCode::append_full_config(const Print &print, std::string &str)
|
||||||
{
|
{
|
||||||
const DynamicPrintConfig &cfg = print.full_print_config();
|
const DynamicPrintConfig &cfg = print.full_print_config();
|
||||||
// Sorted list of config keys, which shall not be stored into the G-code. Initializer list.
|
// Sorted list of config keys, which shall not be stored into the G-code. Initializer list.
|
||||||
static constexpr auto banned_keys = {
|
static constexpr auto banned_keys = {
|
||||||
"compatible_printers"sv,
|
"compatible_printers"sv,
|
||||||
"compatible_prints"sv,
|
"compatible_prints"sv,
|
||||||
"print_host"sv,
|
"print_host"sv,
|
||||||
"printhost_apikey"sv,
|
"printhost_apikey"sv,
|
||||||
"printhost_cafile"sv
|
"printhost_cafile"sv
|
||||||
};
|
};
|
||||||
assert(std::is_sorted(banned_keys.begin(), banned_keys.end()));
|
assert(std::is_sorted(banned_keys.begin(), banned_keys.end()));
|
||||||
auto is_banned = [](const std::string &key) {
|
auto is_banned = [](const std::string &key) {
|
||||||
return std::binary_search(banned_keys.begin(), banned_keys.end(), key);
|
return std::binary_search(banned_keys.begin(), banned_keys.end(), key);
|
||||||
};
|
};
|
||||||
for (const std::string &key : cfg.keys())
|
for (const std::string &key : cfg.keys())
|
||||||
if (! is_banned(key) && ! cfg.option(key)->is_nil())
|
if (! is_banned(key) && ! cfg.option(key)->is_nil())
|
||||||
str += "; " + key + " = " + cfg.opt_serialize(key) + "\n";
|
str += "; " + key + " = " + cfg.opt_serialize(key) + "\n";
|
||||||
|
@ -2554,16 +2555,16 @@ std::string GCode::change_layer(coordf_t print_z)
|
||||||
static inline float bspline_kernel(float x)
|
static inline float bspline_kernel(float x)
|
||||||
{
|
{
|
||||||
x = std::abs(x);
|
x = std::abs(x);
|
||||||
if (x < 1.f) {
|
if (x < 1.f) {
|
||||||
return 1.f - (3.f / 2.f) * x * x + (3.f / 4.f) * x * x * x;
|
return 1.f - (3.f / 2.f) * x * x + (3.f / 4.f) * x * x * x;
|
||||||
}
|
}
|
||||||
else if (x < 2.f) {
|
else if (x < 2.f) {
|
||||||
x -= 1.f;
|
x -= 1.f;
|
||||||
float x2 = x * x;
|
float x2 = x * x;
|
||||||
float x3 = x2 * x;
|
float x3 = x2 * x;
|
||||||
return (1.f / 4.f) - (3.f / 4.f) * x + (3.f / 4.f) * x2 - (1.f / 4.f) * x3;
|
return (1.f / 4.f) - (3.f / 4.f) * x + (3.f / 4.f) * x2 - (1.f / 4.f) * x3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2636,13 +2637,13 @@ static Points::const_iterator project_point_to_polygon_and_insert(Polygon &polyg
|
||||||
pt_min = p1;
|
pt_min = p1;
|
||||||
double linv = double(d_seg) / double(l2_seg);
|
double linv = double(d_seg) / double(l2_seg);
|
||||||
pt_min(0) = pt(0) - coord_t(floor(double(v_seg(1)) * linv + 0.5));
|
pt_min(0) = pt(0) - coord_t(floor(double(v_seg(1)) * linv + 0.5));
|
||||||
pt_min(1) = pt(1) + coord_t(floor(double(v_seg(0)) * linv + 0.5));
|
pt_min(1) = pt(1) + coord_t(floor(double(v_seg(0)) * linv + 0.5));
|
||||||
assert(Line(p1, p2).distance_to(pt_min) < scale_(1e-5));
|
assert(Line(p1, p2).distance_to(pt_min) < scale_(1e-5));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(i_min != size_t(-1));
|
assert(i_min != size_t(-1));
|
||||||
if ((pt_min - polygon.points[i_min]).cast<double>().norm() > eps) {
|
if ((pt_min - polygon.points[i_min]).cast<double>().norm() > eps) {
|
||||||
// Insert a new point on the segment i_min, i_min+1.
|
// Insert a new point on the segment i_min, i_min+1.
|
||||||
return polygon.points.insert(polygon.points.begin() + (i_min + 1), pt_min);
|
return polygon.points.insert(polygon.points.begin() + (i_min + 1), pt_min);
|
||||||
|
@ -2706,9 +2707,9 @@ std::vector<float> polygon_angles_at_vertices(const Polygon &polygon, const std:
|
||||||
const Point &p2 = polygon.points[idx_next];
|
const Point &p2 = polygon.points[idx_next];
|
||||||
const Point v1 = p1 - p0;
|
const Point v1 = p1 - p0;
|
||||||
const Point v2 = p2 - p1;
|
const Point v2 = p2 - p1;
|
||||||
int64_t dot = int64_t(v1(0))*int64_t(v2(0)) + int64_t(v1(1))*int64_t(v2(1));
|
int64_t dot = int64_t(v1(0))*int64_t(v2(0)) + int64_t(v1(1))*int64_t(v2(1));
|
||||||
int64_t cross = int64_t(v1(0))*int64_t(v2(1)) - int64_t(v1(1))*int64_t(v2(0));
|
int64_t cross = int64_t(v1(0))*int64_t(v2(1)) - int64_t(v1(1))*int64_t(v2(0));
|
||||||
float angle = float(atan2(double(cross), double(dot)));
|
float angle = float(atan2(double(cross), double(dot)));
|
||||||
angles[idx_curr] = angle;
|
angles[idx_curr] = angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2861,6 +2862,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||||
m_seam_position[m_layer->object()] = polygon.points[idx_min];
|
m_seam_position[m_layer->object()] = polygon.points[idx_min];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Export the contour into a SVG file.
|
// Export the contour into a SVG file.
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
|
@ -2937,11 +2939,11 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||||
m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path
|
m_wipe.path = paths.front().polyline; // TODO: don't limit wipe to last path
|
||||||
|
|
||||||
// make a little move inwards before leaving loop
|
// make a little move inwards before leaving loop
|
||||||
if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 1 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 3) {
|
if (paths.back().role() == erExternalPerimeter && m_layer != NULL && m_config.perimeters.value > 1 && paths.front().size() >= 2 && paths.back().polyline.points.size() >= 3) {
|
||||||
// detect angle between last and first segment
|
// detect angle between last and first segment
|
||||||
// the side depends on the original winding order of the polygon (left for contours, right for holes)
|
// the side depends on the original winding order of the polygon (left for contours, right for holes)
|
||||||
//FIXME improve the algorithm in case the loop is tiny.
|
//FIXME improve the algorithm in case the loop is tiny.
|
||||||
//FIXME improve the algorithm in case the loop is split into segments with a low number of points (see the Point b query).
|
//FIXME improve the algorithm in case the loop is split into segments with a low number of points (see the Point b query).
|
||||||
Point a = paths.front().polyline.points[1]; // second point
|
Point a = paths.front().polyline.points[1]; // second point
|
||||||
Point b = *(paths.back().polyline.points.end()-3); // second to last point
|
Point b = *(paths.back().polyline.points.end()-3); // second to last point
|
||||||
if (was_clockwise) {
|
if (was_clockwise) {
|
||||||
|
@ -3040,23 +3042,23 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
|
||||||
const char* extrusion_name = ironing ? "ironing" : "infill";
|
const char* extrusion_name = ironing ? "ironing" : "infill";
|
||||||
for (const ObjectByExtruder::Island::Region ®ion : by_region)
|
for (const ObjectByExtruder::Island::Region ®ion : by_region)
|
||||||
if (! region.infills.empty()) {
|
if (! region.infills.empty()) {
|
||||||
extrusions.clear();
|
extrusions.clear();
|
||||||
extrusions.reserve(region.infills.size());
|
extrusions.reserve(region.infills.size());
|
||||||
for (ExtrusionEntity *ee : region.infills)
|
for (ExtrusionEntity *ee : region.infills)
|
||||||
if ((ee->role() == erIroning) == ironing)
|
if ((ee->role() == erIroning) == ironing)
|
||||||
extrusions.emplace_back(ee);
|
extrusions.emplace_back(ee);
|
||||||
if (! extrusions.empty()) {
|
if (! extrusions.empty()) {
|
||||||
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
m_config.apply(print.regions()[®ion - &by_region.front()]->config());
|
||||||
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
|
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
|
||||||
for (const ExtrusionEntity *fill : extrusions) {
|
for (const ExtrusionEntity *fill : extrusions) {
|
||||||
auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(fill);
|
auto *eec = dynamic_cast<const ExtrusionEntityCollection*>(fill);
|
||||||
if (eec) {
|
if (eec) {
|
||||||
for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities)
|
for (ExtrusionEntity *ee : eec->chained_path_from(m_last_pos).entities)
|
||||||
gcode += this->extrude_entity(*ee, extrusion_name);
|
gcode += this->extrude_entity(*ee, extrusion_name);
|
||||||
} else
|
} else
|
||||||
gcode += this->extrude_entity(*fill, extrusion_name);
|
gcode += this->extrude_entity(*fill, extrusion_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return gcode;
|
return gcode;
|
||||||
}
|
}
|
||||||
|
@ -3382,7 +3384,7 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
|
||||||
Lines lines = travel.lines();
|
Lines lines = travel.lines();
|
||||||
if (! lines.empty()) {
|
if (! lines.empty()) {
|
||||||
for (const Line &line : lines)
|
for (const Line &line : lines)
|
||||||
gcode += m_writer.travel_to_xy(this->point_to_gcode(line.b), comment);
|
gcode += m_writer.travel_to_xy(this->point_to_gcode(line.b), comment);
|
||||||
this->set_last_pos(lines.back().b);
|
this->set_last_pos(lines.back().b);
|
||||||
}
|
}
|
||||||
return gcode;
|
return gcode;
|
||||||
|
@ -3556,17 +3558,17 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
|
||||||
{
|
{
|
||||||
bool has_overrides = false;
|
bool has_overrides = false;
|
||||||
for (const auto& reg : by_region)
|
for (const auto& reg : by_region)
|
||||||
if (! reg.infills_overrides.empty() || ! reg.perimeters_overrides.empty()) {
|
if (! reg.infills_overrides.empty() || ! reg.perimeters_overrides.empty()) {
|
||||||
has_overrides = true;
|
has_overrides = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data is cleared, but the memory is not.
|
// Data is cleared, but the memory is not.
|
||||||
by_region_per_copy_cache.clear();
|
by_region_per_copy_cache.clear();
|
||||||
|
|
||||||
if (! has_overrides)
|
if (! has_overrides)
|
||||||
// Simple case. No need to copy the regions.
|
// Simple case. No need to copy the regions.
|
||||||
return wiping_entities ? by_region_per_copy_cache : this->by_region;
|
return wiping_entities ? by_region_per_copy_cache : this->by_region;
|
||||||
|
|
||||||
// Complex case. Some of the extrusions of some object instances are to be printed first - those are the wiping extrusions.
|
// 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.
|
// Some of the extrusions of some object instances are printed later - those are the clean print extrusions.
|
||||||
|
@ -3585,25 +3587,25 @@ const std::vector<GCode::ObjectByExtruder::Island::Region>& GCode::ObjectByExtru
|
||||||
// Now the most important thing - which extrusion should we print.
|
// Now the most important thing - which extrusion should we print.
|
||||||
// See function ToolOrdering::get_extruder_overrides for details about the negative numbers hack.
|
// See function ToolOrdering::get_extruder_overrides for details about the negative numbers hack.
|
||||||
if (wiping_entities) {
|
if (wiping_entities) {
|
||||||
// Apply overrides for this region.
|
// Apply overrides for this region.
|
||||||
for (unsigned int i = 0; i < overrides.size(); ++ i) {
|
for (unsigned int i = 0; i < overrides.size(); ++ i) {
|
||||||
const WipingExtrusions::ExtruderPerCopy *this_override = overrides[i];
|
const WipingExtrusions::ExtruderPerCopy *this_override = overrides[i];
|
||||||
// This copy (aka object instance) should be printed with this extruder, which overrides the default one.
|
// This copy (aka object instance) should be printed with this extruder, which overrides the default one.
|
||||||
if (this_override != nullptr && (*this_override)[copy] == int(extruder))
|
if (this_override != nullptr && (*this_override)[copy] == int(extruder))
|
||||||
target_eec.emplace_back(entities[i]);
|
target_eec.emplace_back(entities[i]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Apply normal extrusions (non-overrides) for this region.
|
// Apply normal extrusions (non-overrides) for this region.
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
for (; i < overrides.size(); ++ i) {
|
for (; i < overrides.size(); ++ i) {
|
||||||
const WipingExtrusions::ExtruderPerCopy *this_override = overrides[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.
|
// 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] == -int(extruder)-1)
|
if (this_override == nullptr || (*this_override)[copy] == -int(extruder)-1)
|
||||||
target_eec.emplace_back(entities[i]);
|
target_eec.emplace_back(entities[i]);
|
||||||
}
|
}
|
||||||
for (; i < entities.size(); ++ i)
|
for (; i < entities.size(); ++ i)
|
||||||
target_eec.emplace_back(entities[i]);
|
target_eec.emplace_back(entities[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return by_region_per_copy_cache;
|
return by_region_per_copy_cache;
|
||||||
|
@ -3623,11 +3625,11 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr
|
||||||
perimeters_or_infills_overrides = &perimeters_overrides;
|
perimeters_or_infills_overrides = &perimeters_overrides;
|
||||||
break;
|
break;
|
||||||
case INFILL:
|
case INFILL:
|
||||||
perimeters_or_infills = &infills;
|
perimeters_or_infills = &infills;
|
||||||
perimeters_or_infills_overrides = &infills_overrides;
|
perimeters_or_infills_overrides = &infills_overrides;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::invalid_argument("Unknown parameter!");
|
throw std::invalid_argument("Unknown parameter!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// First we append the entities, there are eec->entities.size() of them:
|
// First we append the entities, there are eec->entities.size() of them:
|
||||||
|
@ -3635,18 +3637,18 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr
|
||||||
size_t new_size = old_size + (eec->can_reverse() ? eec->entities.size() : 1);
|
size_t new_size = old_size + (eec->can_reverse() ? eec->entities.size() : 1);
|
||||||
perimeters_or_infills->reserve(new_size);
|
perimeters_or_infills->reserve(new_size);
|
||||||
if (eec->can_reverse()) {
|
if (eec->can_reverse()) {
|
||||||
for (auto* ee : eec->entities)
|
for (auto* ee : eec->entities)
|
||||||
perimeters_or_infills->emplace_back(ee);
|
perimeters_or_infills->emplace_back(ee);
|
||||||
} else
|
} else
|
||||||
perimeters_or_infills->emplace_back(const_cast<ExtrusionEntityCollection*>(eec));
|
perimeters_or_infills->emplace_back(const_cast<ExtrusionEntityCollection*>(eec));
|
||||||
|
|
||||||
if (copies_extruder != nullptr) {
|
if (copies_extruder != nullptr) {
|
||||||
// Don't reallocate overrides if not needed.
|
// Don't reallocate overrides if not needed.
|
||||||
// Missing overrides are implicitely considered non-overridden.
|
// Missing overrides are implicitely considered non-overridden.
|
||||||
perimeters_or_infills_overrides->reserve(new_size);
|
perimeters_or_infills_overrides->reserve(new_size);
|
||||||
perimeters_or_infills_overrides->resize(old_size, nullptr);
|
perimeters_or_infills_overrides->resize(old_size, nullptr);
|
||||||
perimeters_or_infills_overrides->resize(new_size, copies_extruder);
|
perimeters_or_infills_overrides->resize(new_size, copies_extruder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -69,6 +69,7 @@ private:
|
||||||
std::unique_ptr<MotionPlanner> m_layer_mp;
|
std::unique_ptr<MotionPlanner> m_layer_mp;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class OozePrevention {
|
class OozePrevention {
|
||||||
public:
|
public:
|
||||||
bool enable;
|
bool enable;
|
||||||
|
|
Loading…
Reference in a new issue