diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index d46b7c736..7a96e15e5 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -235,6 +235,7 @@ group:Flow setting:fill_top_flow_ratio setting:first_layer_flow_ratio end_line + setting:external_perimeter_cut_corners page:Multiple extruders:funnel group:Extruders diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 314074af7..567b77210 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -3552,23 +3552,81 @@ void GCode::_write_format(FILE* file, const char* format, ...) std::string GCode::_extrude(const ExtrusionPath &path, const std::string &description, double speed) { std::string gcode = this->_before_extrude(path, description, speed); - + // calculate extrusion length per distance unit double e_per_mm = path.mm3_per_mm * m_writer.extruder()->e_per_mm3() * this->config().print_extrusion_multiplier.get_abs_value(1); if (this->m_layer_index <= 0) e_per_mm *= this->config().first_layer_flow_ratio.get_abs_value(1); if (m_writer.extrusion_axis().empty()) e_per_mm = 0; - double path_length = 0.; - { - std::string comment = m_config.gcode_comments ? description : ""; - for (const Line &line : path.polyline.lines()) { - const double line_length = line.length() * SCALING_FACTOR; - path_length += line_length; - gcode += m_writer.extrude_to_xy( - this->point_to_gcode(line.b), - e_per_mm * line_length, - comment); + if (path.polyline.lines().size() > 0) { + //get last direction //TODO: save it + { + std::string comment = m_config.gcode_comments ? description : ""; + if (path.role() != erExternalPerimeter || config().external_perimeter_cut_corners.value == 0) { + // normal & legacy pathcode + for (const Line& line : path.polyline.lines()) { + gcode += m_writer.extrude_to_xy( + this->point_to_gcode(line.b), + e_per_mm * unscaled(line.length()), + comment); + } + } else { + // external_perimeter_cut_corners pathcode + Point last_pos = path.polyline.lines()[0].a; + for (const Line& line : path.polyline.lines()) { + //check the angle + double angle = line.a == last_pos ? PI : line.a.ccw_angle(last_pos, line.b); + if (angle > 1) angle = 2 * PI - angle; + double coeff = std::cos(angle) + 1; + //Create extrusion mult + double mult = config().external_perimeter_cut_corners.get_abs_value(0.05375) * coeff; // 0.94625 = 3.78 / 4 = (4 - ((4 - pi) / 4)) / 4 // 4 = carre, 3.14 = disk + double length1 = scale_(path.width) / 4; + + //extrude in three steps: one short with big mult, one of nozzle size with the rest and then the normal one. + //it's a very rough approx of a cos. + length1 /= (2.1 - coeff); + if (line.length() > length1 && mult > 0.001) { + //Create a point + Point inter_point1 = line.point_at(length1); + //extrude very reduced + gcode += m_writer.extrude_to_xy( + this->point_to_gcode(inter_point1), + e_per_mm * unscaled(length1) * (1 - mult * 2.5), + comment); + + double length2 = scale_(path.width); + length2 /= (2.1 - coeff); + if (line.length() > length2) { + Point inter_point2 = line.point_at(length2); + //extrude reduced + gcode += m_writer.extrude_to_xy( + this->point_to_gcode(inter_point2), + e_per_mm * unscaled(length2 - length1) * (1 - mult / 2), + comment); + + //extrude normal + gcode += m_writer.extrude_to_xy( + this->point_to_gcode(line.b), + e_per_mm * unscaled(line.length() - length2), + comment); + } else { + gcode += m_writer.extrude_to_xy( + this->point_to_gcode(line.b), + e_per_mm * unscaled(line.length() - length1) * (1 - mult / 2), + comment); + } + } else { + gcode += m_writer.extrude_to_xy( + this->point_to_gcode(line.b), + e_per_mm * unscaled(line.length() - length1) * (1 - mult * path.width / unscaled(line.length())), + comment); + } + + //relance + last_pos = line.a; + } + } } } gcode += this->_after_extrude(path); diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 0c34f49c5..8e827fa57 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -86,6 +86,7 @@ bool Print::invalidate_state_by_config_options(const std::vectorfull_label = L("External perimeters width"); def->category = OptionCategory::width; def->tooltip = L("Set this to a non-zero value to set a manual extrusion width for external perimeters. " - "If left zero, default extrusion width will be used if set, otherwise 1.05 x nozzle diameter will be used. " - "If expressed as percentage (for example 112.5%), it will be computed over nozzle diameter."); + "If left zero, default extrusion width will be used if set, otherwise 1.05 x nozzle diameter will be used. " + "If expressed as percentage (for example 112.5%), it will be computed over nozzle diameter."); def->sidetext = L("mm or %"); def->min = 0; def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloatOrPercent(0, false)); + def = this->add("external_perimeter_cut_corners", coPercent); + def->label = L("Cutting corners"); + def->full_label = L("Ext. peri. cut corners"); + def->category = OptionCategory::width; + def->tooltip = L("Activate this option to modify the flow to acknoledge that the nozzle is round and the corners will have a round shape, and so change the flow to realized that and avoid over-extrusion." + " 100% is activated, 0% is deactivated and 50% is half-activated"); + def->sidetext = L("%"); + def->mode = comExpert; + def->set_default_value(new ConfigOptionPercent(0)); + def = this->add("external_perimeter_speed", coFloatOrPercent); def->label = L("External"); def->full_label = L("External perimeters speed"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 85ba6f145..6c33fa8f9 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -466,6 +466,7 @@ public: ConfigOptionBool clip_multipart_objects; ConfigOptionBool dont_support_bridges; ConfigOptionFloat elefant_foot_compensation; + ConfigOptionPercent external_perimeter_cut_corners; ConfigOptionBool exact_last_layer_height; ConfigOptionFloatOrPercent extrusion_width; ConfigOptionFloatOrPercent first_layer_height; @@ -525,6 +526,7 @@ protected: OPT_PTR(clip_multipart_objects); OPT_PTR(dont_support_bridges); OPT_PTR(elefant_foot_compensation); + OPT_PTR(external_perimeter_cut_corners); OPT_PTR(exact_last_layer_height); OPT_PTR(extrusion_width); OPT_PTR(first_layer_height); diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index 2e20a376d..8b173ea0c 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -520,7 +520,8 @@ const std::vector& Preset::print_options() , "curve_smoothing_cutoff_dist" , "curve_smoothing_angle_convex" , "curve_smoothing_angle_concave", - "print_extrusion_multiplier" + "print_extrusion_multiplier", + "external_perimeter_cut_corners" }; return s_opts; }