mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-23 16:51:21 -06:00
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_gcode_window
This commit is contained in:
commit
da7d7ae11b
61 changed files with 6895 additions and 646 deletions
|
|
@ -18,6 +18,7 @@ public:
|
|||
// Routing around the objects vs. inside a single object.
|
||||
void use_external_mp(bool use = true) { m_use_external_mp = use; };
|
||||
void use_external_mp_once() { m_use_external_mp_once = true; }
|
||||
bool used_external_mp_once() { return m_use_external_mp_once; }
|
||||
void disable_once() { m_disabled_once = true; }
|
||||
bool disabled_once() const { return m_disabled_once; }
|
||||
void reset_once_modifiers() { m_use_external_mp_once = false; m_disabled_once = false; }
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@
|
|||
#include "GCodeProcessor.hpp"
|
||||
|
||||
#include <boost/log/trivial.hpp>
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#endif // ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
#include <boost/nowide/fstream.hpp>
|
||||
#include <boost/nowide/cstdio.hpp>
|
||||
#if ENABLE_GCODE_WINDOW
|
||||
|
|
@ -597,12 +600,6 @@ const std::vector<std::pair<GCodeProcessor::EProducer, std::string>> GCodeProces
|
|||
unsigned int GCodeProcessor::s_result_id = 0;
|
||||
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
static inline bool starts_with(const std::string_view comment, const std::string_view tag)
|
||||
{
|
||||
size_t tag_len = tag.size();
|
||||
return comment.size() >= tag_len && comment.substr(0, tag_len) == tag;
|
||||
}
|
||||
|
||||
bool GCodeProcessor::contains_reserved_tag(const std::string& gcode, std::string& found_tag)
|
||||
{
|
||||
bool ret = false;
|
||||
|
|
@ -613,7 +610,7 @@ bool GCodeProcessor::contains_reserved_tag(const std::string& gcode, std::string
|
|||
if (comment.length() > 2 && comment.front() == ';') {
|
||||
comment = comment.substr(1);
|
||||
for (const std::string& s : Reserved_Tags) {
|
||||
if (starts_with(comment, s)) {
|
||||
if (boost::starts_with(comment, s)) {
|
||||
ret = true;
|
||||
found_tag = comment;
|
||||
parser.quit_parsing();
|
||||
|
|
@ -638,7 +635,7 @@ bool GCodeProcessor::contains_reserved_tags(const std::string& gcode, unsigned i
|
|||
if (comment.length() > 2 && comment.front() == ';') {
|
||||
comment = comment.substr(1);
|
||||
for (const std::string& s : Reserved_Tags) {
|
||||
if (starts_with(comment, s)) {
|
||||
if (boost::starts_with(comment, s)) {
|
||||
ret = true;
|
||||
found_tag.push_back(comment);
|
||||
if (found_tag.size() == max_count) {
|
||||
|
|
@ -681,6 +678,8 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
m_extruder_colors[i] = static_cast<unsigned char>(i);
|
||||
}
|
||||
|
||||
m_extruder_temps.resize(extruders_count);
|
||||
|
||||
m_filament_diameters.resize(config.filament_diameter.values.size());
|
||||
for (size_t i = 0; i < config.filament_diameter.values.size(); ++i) {
|
||||
m_filament_diameters[i] = static_cast<float>(config.filament_diameter.values[i]);
|
||||
|
|
@ -708,10 +707,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
|||
}
|
||||
|
||||
m_time_processor.export_remaining_time_enabled = config.remaining_times.value;
|
||||
|
||||
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
m_use_volumetric_e = config.use_volumetric_e;
|
||||
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
}
|
||||
|
||||
void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
||||
|
|
@ -782,6 +778,8 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
|||
m_extruder_colors[i] = static_cast<unsigned char>(i);
|
||||
}
|
||||
|
||||
m_extruder_temps.resize(m_result.extruders_count);
|
||||
|
||||
const ConfigOptionFloats* filament_load_time = config.option<ConfigOptionFloats>("filament_load_time");
|
||||
if (filament_load_time != nullptr) {
|
||||
m_time_processor.filament_load_times.resize(filament_load_time->values.size());
|
||||
|
|
@ -873,11 +871,9 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
|||
if (m_time_processor.machine_limits.machine_max_acceleration_x.values.size() > 1)
|
||||
enable_stealth_time_estimator(true);
|
||||
|
||||
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
const ConfigOptionBool* use_volumetric_e = config.option<ConfigOptionBool>("use_volumetric_e");
|
||||
if (use_volumetric_e != nullptr)
|
||||
m_use_volumetric_e = use_volumetric_e->value;
|
||||
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
}
|
||||
|
||||
void GCodeProcessor::enable_stealth_time_estimator(bool enabled)
|
||||
|
|
@ -918,6 +914,10 @@ void GCodeProcessor::reset()
|
|||
for (size_t i = 0; i < Min_Extruder_Count; ++i) {
|
||||
m_extruder_colors[i] = static_cast<unsigned char>(i);
|
||||
}
|
||||
m_extruder_temps.resize(Min_Extruder_Count);
|
||||
for (size_t i = 0; i < Min_Extruder_Count; ++i) {
|
||||
m_extruder_temps[i] = 0.0f;
|
||||
}
|
||||
|
||||
m_filament_diameters = std::vector<float>(Min_Extruder_Count, 1.75f);
|
||||
m_extruded_last_z = 0.0f;
|
||||
|
|
@ -933,9 +933,7 @@ void GCodeProcessor::reset()
|
|||
m_result.reset();
|
||||
m_result.id = ++s_result_id;
|
||||
|
||||
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
m_use_volumetric_e = false;
|
||||
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
m_mm3_per_mm_compare.reset();
|
||||
|
|
@ -1136,9 +1134,11 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
|
|||
case 1: { process_M1(line); break; } // Sleep or Conditional stop
|
||||
case 82: { process_M82(line); break; } // Set extruder to absolute mode
|
||||
case 83: { process_M83(line); break; } // Set extruder to relative mode
|
||||
case 104: { process_M104(line); break; } // Set extruder temperature
|
||||
case 106: { process_M106(line); break; } // Set fan speed
|
||||
case 107: { process_M107(line); break; } // Disable fan
|
||||
case 108: { process_M108(line); break; } // Set tool (Sailfish)
|
||||
case 109: { process_M109(line); break; } // Set extruder temperature and wait
|
||||
case 132: { process_M132(line); break; } // Recall stored home offsets
|
||||
case 135: { process_M135(line); break; } // Set tool (MakerWare)
|
||||
case 201: { process_M201(line); break; } // Set max printing acceleration
|
||||
|
|
@ -1171,14 +1171,6 @@ void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
|
|||
}
|
||||
}
|
||||
|
||||
#if !ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
static inline bool starts_with(const std::string_view comment, const std::string_view tag)
|
||||
{
|
||||
size_t tag_len = tag.size();
|
||||
return comment.size() >= tag_len && comment.substr(0, tag_len) == tag;
|
||||
}
|
||||
#endif // !ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
|
||||
#if __has_include(<charconv>)
|
||||
template <typename T, typename = void>
|
||||
struct is_from_chars_convertible : std::false_type {};
|
||||
|
|
@ -1232,37 +1224,37 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
|||
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
// extrusion role tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Role))) {
|
||||
if (boost::starts_with(comment, reserved_tag(ETags::Role))) {
|
||||
m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(reserved_tag(ETags::Role).length()));
|
||||
return;
|
||||
}
|
||||
|
||||
// wipe start tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Wipe_Start))) {
|
||||
if (boost::starts_with(comment, reserved_tag(ETags::Wipe_Start))) {
|
||||
m_wiping = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// wipe end tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Wipe_End))) {
|
||||
if (boost::starts_with(comment, reserved_tag(ETags::Wipe_End))) {
|
||||
m_wiping = false;
|
||||
return;
|
||||
}
|
||||
#else
|
||||
// extrusion role tag
|
||||
if (starts_with(comment, Extrusion_Role_Tag)) {
|
||||
if (boost::starts_with(comment, Extrusion_Role_Tag)) {
|
||||
m_extrusion_role = ExtrusionEntity::string_to_role(comment.substr(Extrusion_Role_Tag.length()));
|
||||
return;
|
||||
}
|
||||
|
||||
// wipe start tag
|
||||
if (starts_with(comment, Wipe_Start_Tag)) {
|
||||
if (boost::starts_with(comment, Wipe_Start_Tag)) {
|
||||
m_wiping = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// wipe end tag
|
||||
if (starts_with(comment, Wipe_End_Tag)) {
|
||||
if (boost::starts_with(comment, Wipe_End_Tag)) {
|
||||
m_wiping = false;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1271,26 +1263,26 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
|||
if (!m_producers_enabled || m_producer == EProducer::PrusaSlicer) {
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
// height tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Height))) {
|
||||
if (boost::starts_with(comment, reserved_tag(ETags::Height))) {
|
||||
if (!parse_number(comment.substr(reserved_tag(ETags::Height).size()), m_forced_height))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
|
||||
return;
|
||||
}
|
||||
// width tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Width))) {
|
||||
if (boost::starts_with(comment, reserved_tag(ETags::Width))) {
|
||||
if (!parse_number(comment.substr(reserved_tag(ETags::Width).size()), m_forced_width))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
|
||||
return;
|
||||
}
|
||||
#else
|
||||
// height tag
|
||||
if (starts_with(comment, Height_Tag)) {
|
||||
if (boost::starts_with(comment, Height_Tag)) {
|
||||
if (!parse_number(comment.substr(Height_Tag.size()), m_forced_height))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Height (" << comment << ").";
|
||||
return;
|
||||
}
|
||||
// width tag
|
||||
if (starts_with(comment, Width_Tag)) {
|
||||
if (boost::starts_with(comment, Width_Tag)) {
|
||||
if (!parse_number(comment.substr(Width_Tag.size()), m_forced_width))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Width (" << comment << ").";
|
||||
return;
|
||||
|
|
@ -1300,9 +1292,9 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
|||
|
||||
#if ENABLE_VALIDATE_CUSTOM_GCODE
|
||||
// color change tag
|
||||
if (starts_with(comment, reserved_tag(ETags::Color_Change))) {
|
||||
if (boost::starts_with(comment, reserved_tag(ETags::Color_Change))) {
|
||||
unsigned char extruder_id = 0;
|
||||
if (starts_with(comment.substr(reserved_tag(ETags::Color_Change).size()), ",T")) {
|
||||
if (boost::starts_with(comment.substr(reserved_tag(ETags::Color_Change).size()), ",T")) {
|
||||
int eid;
|
||||
if (!parse_number(comment.substr(reserved_tag(ETags::Color_Change).size() + 2), eid) || eid < 0 || eid > 255) {
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ").";
|
||||
|
|
@ -1346,9 +1338,9 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
|||
}
|
||||
#else
|
||||
// color change tag
|
||||
if (starts_with(comment, Color_Change_Tag)) {
|
||||
if (boost::starts_with(comment, Color_Change_Tag)) {
|
||||
unsigned char extruder_id = 0;
|
||||
if (starts_with(comment.substr(Color_Change_Tag.size()), ",T")) {
|
||||
if (boost::starts_with(comment.substr(Color_Change_Tag.size()), ",T")) {
|
||||
int eid;
|
||||
if (! parse_number(comment.substr(Color_Change_Tag.size() + 2), eid) || eid < 0 || eid > 255) {
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Color_Change (" << comment << ").";
|
||||
|
|
@ -1394,7 +1386,7 @@ void GCodeProcessor::process_tags(const std::string_view comment)
|
|||
|
||||
#if ENABLE_GCODE_VIEWER_DATA_CHECKING
|
||||
// mm3_per_mm print tag
|
||||
if (starts_with(comment, Mm3_Per_Mm_Tag)) {
|
||||
if (boost::starts_with(comment, Mm3_Per_Mm_Tag)) {
|
||||
if (! parse_number(comment.substr(Mm3_Per_Mm_Tag.size()), m_mm3_per_mm_compare.last_tag_value))
|
||||
BOOST_LOG_TRIVIAL(error) << "GCodeProcessor encountered an invalid value for Mm3_Per_Mm (" << comment << ").";
|
||||
return;
|
||||
|
|
@ -1846,14 +1838,10 @@ void GCodeProcessor::process_G0(const GCodeReader::GCodeLine& line)
|
|||
|
||||
void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_filament_diameters.size()) ? m_filament_diameters[m_extruder_id] : m_filament_diameters.back();
|
||||
float filament_radius = 0.5f * filament_diameter;
|
||||
float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
|
||||
auto absolute_position = [this, area_filament_cross_section](Axis axis, const GCodeReader::GCodeLine& lineG1) {
|
||||
#else
|
||||
auto absolute_position = [this](Axis axis, const GCodeReader::GCodeLine& lineG1) {
|
||||
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
bool is_relative = (m_global_positioning_type == EPositioningType::Relative);
|
||||
if (axis == E)
|
||||
is_relative |= (m_e_local_positioning_type == EPositioningType::Relative);
|
||||
|
|
@ -1861,10 +1849,8 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||
if (lineG1.has(Slic3r::Axis(axis))) {
|
||||
float lengthsScaleFactor = (m_units == EUnits::Inches) ? INCHES_TO_MM : 1.0f;
|
||||
float ret = lineG1.value(Slic3r::Axis(axis)) * lengthsScaleFactor;
|
||||
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
if (axis == E && m_use_volumetric_e)
|
||||
ret /= area_filament_cross_section;
|
||||
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
return is_relative ? m_start_position[axis] + ret : m_origin[axis] + ret;
|
||||
}
|
||||
else
|
||||
|
|
@ -1922,11 +1908,6 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line)
|
|||
|
||||
if (type == EMoveType::Extrude) {
|
||||
float delta_xyz = std::sqrt(sqr(delta_pos[X]) + sqr(delta_pos[Y]) + sqr(delta_pos[Z]));
|
||||
#if !ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
float filament_diameter = (static_cast<size_t>(m_extruder_id) < m_filament_diameters.size()) ? m_filament_diameters[m_extruder_id] : m_filament_diameters.back();
|
||||
float filament_radius = 0.5f * filament_diameter;
|
||||
float area_filament_cross_section = static_cast<float>(M_PI) * sqr(filament_radius);
|
||||
#endif // !ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
float volume_extruded_filament = area_filament_cross_section * delta_pos[E];
|
||||
float area_toolpath_cross_section = volume_extruded_filament / delta_xyz;
|
||||
|
||||
|
|
@ -2235,6 +2216,13 @@ void GCodeProcessor::process_M83(const GCodeReader::GCodeLine& line)
|
|||
m_e_local_positioning_type = EPositioningType::Relative;
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_M104(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
float new_temp;
|
||||
if (line.has_value('S', new_temp))
|
||||
m_extruder_temps[m_extruder_id] = new_temp;
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_M106(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
if (!line.has('P')) {
|
||||
|
|
@ -2267,6 +2255,21 @@ void GCodeProcessor::process_M108(const GCodeReader::GCodeLine& line)
|
|||
process_T(cmd.substr(pos));
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_M109(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
float new_temp;
|
||||
if (line.has_value('R', new_temp)) {
|
||||
float val;
|
||||
if (line.has_value('T', val)) {
|
||||
size_t eid = static_cast<size_t>(val);
|
||||
if (eid < m_extruder_temps.size())
|
||||
m_extruder_temps[eid] = new_temp;
|
||||
}
|
||||
else
|
||||
m_extruder_temps[m_extruder_id] = new_temp;
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_M132(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
// This command is used by Makerbot to load the current home position from EEPROM
|
||||
|
|
@ -2555,6 +2558,7 @@ void GCodeProcessor::store_move_vertex(EMoveType type)
|
|||
m_height,
|
||||
m_mm3_per_mm,
|
||||
m_fan_speed,
|
||||
m_extruder_temps[m_extruder_id],
|
||||
static_cast<float>(m_result.moves.size())
|
||||
};
|
||||
m_result.moves.emplace_back(vertex);
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ namespace Slic3r {
|
|||
private:
|
||||
using AxisCoords = std::array<float, 4>;
|
||||
using ExtruderColors = std::vector<unsigned char>;
|
||||
using ExtruderTemps = std::vector<float>;
|
||||
|
||||
enum class EUnits : unsigned char
|
||||
{
|
||||
|
|
@ -211,6 +212,7 @@ namespace Slic3r {
|
|||
float height{ 0.0f }; // mm
|
||||
float mm3_per_mm{ 0.0f };
|
||||
float fan_speed{ 0.0f }; // percentage
|
||||
float temperature{ 0.0f }; // Celsius degrees
|
||||
float time{ 0.0f }; // s
|
||||
|
||||
float volumetric_rate() const { return feedrate * mm3_per_mm; }
|
||||
|
|
@ -320,6 +322,7 @@ namespace Slic3r {
|
|||
float height{ 0.0f }; // mm
|
||||
float mm3_per_mm{ 0.0f };
|
||||
float fan_speed{ 0.0f }; // percentage
|
||||
float temperature{ 0.0f }; // Celsius degrees
|
||||
float time{ 0.0f }; // s
|
||||
|
||||
float volumetric_rate() const { return feedrate * mm3_per_mm; }
|
||||
|
|
@ -470,14 +473,13 @@ namespace Slic3r {
|
|||
ExtrusionRole m_extrusion_role;
|
||||
unsigned char m_extruder_id;
|
||||
ExtruderColors m_extruder_colors;
|
||||
ExtruderTemps m_extruder_temps;
|
||||
std::vector<float> m_filament_diameters;
|
||||
float m_extruded_last_z;
|
||||
unsigned int m_g1_line_id;
|
||||
unsigned int m_layer_id;
|
||||
CpColor m_cp_color;
|
||||
#if ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
bool m_use_volumetric_e;
|
||||
#endif // ENABLE_VOLUMETRIC_EXTRUSION_PROCESSING
|
||||
|
||||
enum class EProducer
|
||||
{
|
||||
|
|
@ -590,6 +592,9 @@ namespace Slic3r {
|
|||
// Set extruder to relative mode
|
||||
void process_M83(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Set extruder temperature
|
||||
void process_M104(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Set fan speed
|
||||
void process_M106(const GCodeReader::GCodeLine& line);
|
||||
|
||||
|
|
@ -599,6 +604,9 @@ namespace Slic3r {
|
|||
// Set tool (Sailfish)
|
||||
void process_M108(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Set extruder temperature and wait
|
||||
void process_M109(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Recall stored home offsets
|
||||
void process_M132(const GCodeReader::GCodeLine& line);
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,20 @@ unsigned int LayerTools::extruder(const ExtrusionEntityCollection &extrusions, c
|
|||
return (extruder == 0) ? 0 : extruder - 1;
|
||||
}
|
||||
|
||||
static double calc_max_layer_height(const PrintConfig &config, double max_object_layer_height)
|
||||
{
|
||||
double max_layer_height = std::numeric_limits<double>::max();
|
||||
for (size_t i = 0; i < config.nozzle_diameter.values.size(); ++ i) {
|
||||
double mlh = config.max_layer_height.values[i];
|
||||
if (mlh == 0.)
|
||||
mlh = 0.75 * config.nozzle_diameter.values[i];
|
||||
max_layer_height = std::min(max_layer_height, mlh);
|
||||
}
|
||||
// The Prusa3D Fast (0.35mm layer height) print profile sets a higher layer height than what is normally allowed
|
||||
// by the nozzle. This is a hack and it works by increasing extrusion width. See GH #3919.
|
||||
return std::max(max_layer_height, max_object_layer_height);
|
||||
}
|
||||
|
||||
// For the use case when each object is printed separately
|
||||
// (print.config().complete_objects is true).
|
||||
ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extruder, bool prime_multi_material)
|
||||
|
|
@ -87,6 +101,7 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
|
|||
zs.emplace_back(layer->print_z);
|
||||
this->initialize_layers(zs);
|
||||
}
|
||||
double max_layer_height = calc_max_layer_height(object.print()->config(), object.config().layer_height);
|
||||
|
||||
// Collect extruders reuqired to print the layers.
|
||||
this->collect_extruders(object, std::vector<std::pair<double, unsigned int>>());
|
||||
|
|
@ -94,9 +109,11 @@ ToolOrdering::ToolOrdering(const PrintObject &object, unsigned int first_extrude
|
|||
// Reorder the extruders to minimize tool switches.
|
||||
this->reorder_extruders(first_extruder);
|
||||
|
||||
this->fill_wipe_tower_partitions(object.print()->config(), object.layers().front()->print_z - object.layers().front()->height, object.config().layer_height);
|
||||
this->fill_wipe_tower_partitions(object.print()->config(), object.layers().front()->print_z - object.layers().front()->height, max_layer_height);
|
||||
|
||||
this->collect_extruder_statistics(prime_multi_material);
|
||||
|
||||
this->mark_skirt_layers(object.print()->config(), max_layer_height);
|
||||
}
|
||||
|
||||
// For the use case when all objects are printed at once.
|
||||
|
|
@ -128,6 +145,7 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
|
|||
}
|
||||
this->initialize_layers(zs);
|
||||
}
|
||||
max_layer_height = calc_max_layer_height(print.config(), max_layer_height);
|
||||
|
||||
// Use the extruder switches from Model::custom_gcode_per_print_z to override the extruder to print the object.
|
||||
// Do it only if all the objects were configured to be printed with a single extruder.
|
||||
|
|
@ -150,6 +168,8 @@ ToolOrdering::ToolOrdering(const Print &print, unsigned int first_extruder, bool
|
|||
this->fill_wipe_tower_partitions(print.config(), object_bottom_z, max_layer_height);
|
||||
|
||||
this->collect_extruder_statistics(prime_multi_material);
|
||||
|
||||
this->mark_skirt_layers(print.config(), max_layer_height);
|
||||
}
|
||||
|
||||
void ToolOrdering::initialize_layers(std::vector<coordf_t> &zs)
|
||||
|
|
@ -321,7 +341,7 @@ void ToolOrdering::reorder_extruders(unsigned int last_extruder_id)
|
|||
}
|
||||
}
|
||||
|
||||
void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_object_layer_height)
|
||||
void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height)
|
||||
{
|
||||
if (m_layer_tools.empty())
|
||||
return;
|
||||
|
|
@ -347,17 +367,6 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
|
|||
lt.has_wipe_tower = (lt.has_object && lt.wipe_tower_partitions > 0) || lt.print_z < object_bottom_z + EPSILON;
|
||||
|
||||
// Test for a raft, insert additional wipe tower layer to fill in the raft separation gap.
|
||||
double max_layer_height = std::numeric_limits<double>::max();
|
||||
for (size_t i = 0; i < config.nozzle_diameter.values.size(); ++ i) {
|
||||
double mlh = config.max_layer_height.values[i];
|
||||
if (mlh == 0.)
|
||||
mlh = 0.75 * config.nozzle_diameter.values[i];
|
||||
max_layer_height = std::min(max_layer_height, mlh);
|
||||
}
|
||||
// The Prusa3D Fast (0.35mm layer height) print profile sets a higher layer height than what is normally allowed
|
||||
// by the nozzle. This is a hack and it works by increasing extrusion width. See GH #3919.
|
||||
max_layer_height = std::max(max_layer_height, max_object_layer_height);
|
||||
|
||||
for (size_t i = 0; i + 1 < m_layer_tools.size(); ++ i) {
|
||||
const LayerTools < = m_layer_tools[i];
|
||||
const LayerTools <_next = m_layer_tools[i + 1];
|
||||
|
|
@ -460,6 +469,48 @@ void ToolOrdering::collect_extruder_statistics(bool prime_multi_material)
|
|||
}
|
||||
}
|
||||
|
||||
// Layers are marked for infinite skirt aka draft shield. Not all the layers have to be printed.
|
||||
void ToolOrdering::mark_skirt_layers(const PrintConfig &config, coordf_t max_layer_height)
|
||||
{
|
||||
if (m_layer_tools.empty())
|
||||
return;
|
||||
|
||||
if (m_layer_tools.front().extruders.empty()) {
|
||||
// Empty first layer, no skirt will be printed.
|
||||
//FIXME throw an exception?
|
||||
return;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (;;) {
|
||||
m_layer_tools[i].has_skirt = true;
|
||||
size_t j = i + 1;
|
||||
for (; j < m_layer_tools.size() && ! m_layer_tools[j].has_object; ++ j);
|
||||
// i and j are two successive layers printing an object.
|
||||
if (j == m_layer_tools.size())
|
||||
// Don't print skirt above the last object layer.
|
||||
break;
|
||||
// Mark some printing intermediate layers as having skirt.
|
||||
double last_z = m_layer_tools[i].print_z;
|
||||
for (size_t k = i + 1; k < j; ++ k) {
|
||||
if (m_layer_tools[k + 1].print_z - last_z > max_layer_height + EPSILON) {
|
||||
// Layer k is the last one not violating the maximum layer height.
|
||||
// Don't extrude skirt on empty layers.
|
||||
while (m_layer_tools[k].extruders.empty())
|
||||
-- k;
|
||||
if (m_layer_tools[k].has_skirt) {
|
||||
// Skirt cannot be generated due to empty layers, there would be a missing layer in the skirt.
|
||||
//FIXME throw an exception?
|
||||
break;
|
||||
}
|
||||
m_layer_tools[k].has_skirt = true;
|
||||
last_z = m_layer_tools[k].print_z;
|
||||
}
|
||||
}
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
|
||||
// Assign a pointer to a custom G-code to the respective ToolOrdering::LayerTools.
|
||||
// Ignore color changes, which are performed on a layer and for such an extruder, that the extruder will not be printing above that layer.
|
||||
// If multiple events are planned over a span of a single layer, use the last one.
|
||||
|
|
|
|||
|
|
@ -17,8 +17,6 @@ class LayerTools;
|
|||
namespace CustomGCode { struct Item; }
|
||||
class PrintRegion;
|
||||
|
||||
|
||||
|
||||
// Object of this class holds information about whether an extrusion is printed immediately
|
||||
// after a toolchange (as part of infill/perimeter wiping) or not. One extrusion can be a part
|
||||
// of several copies - this has to be taken into account.
|
||||
|
|
@ -69,8 +67,6 @@ private:
|
|||
const LayerTools* m_layer_tools = nullptr; // so we know which LayerTools object this belongs to
|
||||
};
|
||||
|
||||
|
||||
|
||||
class LayerTools
|
||||
{
|
||||
public:
|
||||
|
|
@ -99,6 +95,9 @@ public:
|
|||
// If per layer extruder switches are inserted by the G-code preview slider, this value contains the new (1 based) extruder, with which the whole object layer is being printed with.
|
||||
// If not overriden, it is set to 0.
|
||||
unsigned int extruder_override = 0;
|
||||
// Should a skirt be printed at this layer?
|
||||
// Layers are marked for infinite skirt aka draft shield. Not all the layers have to be printed.
|
||||
bool has_skirt = false;
|
||||
// Will there be anything extruded on this layer for the wipe tower?
|
||||
// Due to the support layers possibly interleaving the object layers,
|
||||
// wipe tower will be disabled for some support only layers.
|
||||
|
|
@ -120,12 +119,10 @@ private:
|
|||
WipingExtrusions m_wiping_extrusions;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ToolOrdering
|
||||
{
|
||||
public:
|
||||
ToolOrdering() {}
|
||||
ToolOrdering() = default;
|
||||
|
||||
// For the use case when each object is printed separately
|
||||
// (print.config.complete_objects is true).
|
||||
|
|
@ -169,6 +166,7 @@ private:
|
|||
void collect_extruders(const PrintObject &object, const std::vector<std::pair<double, unsigned int>> &per_layer_extruder_switches);
|
||||
void reorder_extruders(unsigned int last_extruder_id);
|
||||
void fill_wipe_tower_partitions(const PrintConfig &config, coordf_t object_bottom_z, coordf_t max_layer_height);
|
||||
void mark_skirt_layers(const PrintConfig &config, coordf_t max_layer_height);
|
||||
void collect_extruder_statistics(bool prime_multi_material);
|
||||
|
||||
std::vector<LayerTools> m_layer_tools;
|
||||
|
|
@ -182,8 +180,6 @@ private:
|
|||
const PrintConfig* m_print_config_ptr = nullptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // namespace SLic3r
|
||||
|
||||
#endif /* slic3r_ToolOrdering_hpp_ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue