Skip to content

Commit

Permalink
Implement Small Area Infill Flow Compensation
Browse files Browse the repository at this point in the history
* Use graph option type
* Disable small area flow compensation on first layer
  Reasoning: We do not want to affect the first layer's extrusion in any way, especially by underextruding it. Doing so might cause user confusion and/or adhesion issues.

inspired by OrcaSlicer
Credits:
- Graph adaptation: @supermerill
- OrcaSlicer port: @mjonuschat
- Original implementation: @Alexander-T-Moss

#4329
  • Loading branch information
TheSlashEffect authored and supermerill committed Jun 26, 2024
1 parent 982409c commit eb53170
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 9 deletions.
4 changes: 4 additions & 0 deletions resources/ui_layout/default/print.ui
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ group:Advanced Infill options
setting:label_width$8:width$5:fill_smooth_distribution
setting:label_width$26:label$Spacing between ironing lines:width$5:sidetext_width$7:fill_smooth_width
end_line
line:Small Area Infill Flow Compensation (beta)
setting:label$_:sidetext_width$0:small_area_infill_flow_compensation
setting:label$_:small_area_infill_flow_compensation_model
end_line
group:title_width$19:Ironing post-process (This will go on top of infills and perimeters)
line:Enable ironing post-process
setting:label$_:sidetext_width$0:ironing
Expand Down
4 changes: 4 additions & 0 deletions resources/ui_layout/example/print.ui
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ group:Advanced Infill options
setting:label_width$8:width$5:fill_smooth_distribution
setting:label_width$26:label$Spacing between ironing lines:width$5:sidetext_width$7:fill_smooth_width
end_line
line:Small Area Infill Flow Compensation (beta)
setting:label$_:sidetext_width$0:small_area_infill_flow_compensation
setting:label_:small_area_infill_flow_compensation_model
end_line
group:title_width$19:Ironing post-process (This will go on top of infills and perimeters)
line:Enable ironing post-process
setting:label$_:sidetext_width$0:ironing
Expand Down
19 changes: 19 additions & 0 deletions src/libslic3r/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,25 @@ bool GraphData::deserialize(const std::string &str)
this->begin_idx = 0;
this->end_idx = this->graph_points.size();
this->type = GraphType::SPLINE;
} else if (size_t pos = str.find(','); pos != std::string::npos) {
//maybe a coStrings with 0,0 values inside, like a coPoints but worse (used by orca's small_area_infill_flow_compensation_model)
std::vector<std::string> args;
boost::split(args, str, boost::is_any_of(","));
if (args.size() % 2 == 0) {
for (size_t i = 0; i < args.size(); i += 2) {
this->graph_points.emplace_back();
Vec2d &data_point = this->graph_points.back();
args[i].erase(std::remove(args[i].begin(), args[i].end(), '\n'), args[i].end());
args[i].erase(std::remove(args[i].begin(), args[i].end(), '"'), args[i].end());
data_point.x() = std::stod(args[i]);
args[i+1].erase(std::remove(args[i+1].begin(), args[i+1].end(), '\n'), args[i+1].end());
args[i+1].erase(std::remove(args[i+1].begin(), args[i+1].end(), '"'), args[i+1].end());
data_point.y() = std::stod(args[i+1]);
}
}
this->begin_idx = 0;
this->end_idx = this->graph_points.size();
this->type = GraphType::SPLINE;
} else {
std::istringstream iss(str);
std::string item;
Expand Down
6 changes: 5 additions & 1 deletion src/libslic3r/Fill/Fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ struct SurfaceFillParams : FillParams
RETURN_COMPARE_NON_EQUAL(config->gap_fill_acceleration);
RETURN_COMPARE_NON_EQUAL(config->gap_fill_speed);
RETURN_COMPARE_NON_EQUAL(config->print_extrusion_multiplier);
RETURN_COMPARE_NON_EQUAL(config->region_gcode.value);
RETURN_COMPARE_NON_EQUAL(config->region_gcode.value)
RETURN_COMPARE_NON_EQUAL(config->small_area_infill_flow_compensation.value)
RETURN_COMPARE_NON_EQUAL(config->small_area_infill_flow_compensation_model.value);
}
if (config == nullptr || rhs.config == nullptr || max_sparse_infill_spacing == 0)
RETURN_COMPARE_NON_EQUAL(flow.width());
Expand Down Expand Up @@ -115,6 +117,8 @@ struct SurfaceFillParams : FillParams
|| config->gap_fill_speed != rhs.config->gap_fill_speed
|| config->print_extrusion_multiplier != rhs.config->print_extrusion_multiplier
|| config->region_gcode != rhs.config->region_gcode
|| config->small_area_infill_flow_compensation != rhs.config->small_area_infill_flow_compensation
|| config->small_area_infill_flow_compensation_model != rhs.config->small_area_infill_flow_compensation_model
))
return false;
// then check params
Expand Down
36 changes: 30 additions & 6 deletions src/libslic3r/GCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5595,16 +5595,40 @@ std::vector<double> cut_corner_cache = {
0.252510726678311,0.262777267777188,0.27352986689699,0.284799648665007,0.296620441746888,0.309029079319231,0.322065740515038,0.335774339512048,0.350202970204428,0.365404415947691,
0.381436735764648,0.398363940736199,0.416256777189962,0.435193636891737,0.455261618934834 };


void GCode::_extrude_line(std::string& gcode_str, const Line& line, const double e_per_mm, const std::string& comment) {
void GCode::_extrude_line(std::string& gcode_str, const Line& line, const double e_per_mm, const std::string& comment,
ExtrusionRole role) {
if (line.a.coincides_with_epsilon(line.b)) {
assert(false); // todo: investigate if it happens (it happens in perimeters)
return;
}
std::string comment_copy = comment;
double unscaled_line_length = unscaled(line.length());
double extrusion_value = e_per_mm * unscaled_line_length;
// small_area_infill_flow_compensation
// this is only done in _extrude_line and not in _extrude_line_cut_corner because _extrude_line_cut_corner doesn't apply to solid infill, but only for external perimeters.
if (!this->on_first_layer() && (role == ExtrusionRole::erSolidInfill || role == ExtrusionRole::erTopSolidInfill) &&
m_config.small_area_infill_flow_compensation.value &&
m_config.small_area_infill_flow_compensation_model.value.data_size() > 1) {
GraphData graph = m_config.small_area_infill_flow_compensation_model.value;
assert(graph.begin_idx >= 0 && graph.begin_idx + 1 < graph.end_idx && graph.end_idx <= graph.graph_points.size());
// ensure it start at length = 0, and ensure it ends with a compensation of 1.
graph.graph_points[graph.begin_idx].x() = 0;
graph.graph_points[graph.end_idx - 1].y() = 1;
//interpolate and verify
double new_extrusion_value = extrusion_value * graph.interpolate(unscaled_line_length);
assert(new_extrusion_value > 0.0);
if (new_extrusion_value > 0.0 && new_extrusion_value != extrusion_value) {
extrusion_value = new_extrusion_value;
if (m_config.gcode_comments) {
comment_copy += Slic3r::format(_(L(" | Old Flow Value: %0.5f Length: %0.5f")), extrusion_value, unscaled_line_length);
}
}
}
// end small_area_infill_flow_compensation
gcode_str += m_writer.extrude_to_xy(
this->point_to_gcode(line.b),
e_per_mm * unscaled(line.length()),
comment);
extrusion_value,
comment_copy);
}

void GCode::_extrude_line_cut_corner(std::string& gcode_str, const Line& line, const double e_per_mm, const std::string& comment, Point& last_pos, const double path_width) {
Expand Down Expand Up @@ -5745,7 +5769,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string &descri
for (const Line& line : path.polyline.lines()) {
if (path.role() != erExternalPerimeter || config().external_perimeter_cut_corners.value == 0) {
// normal & legacy pathcode
_extrude_line(gcode, line, e_per_mm, comment);
_extrude_line(gcode, line, e_per_mm, comment, path.role());
} else {
_extrude_line_cut_corner(gcode, line, e_per_mm, comment, last_pos, path.width);
}
Expand All @@ -5763,7 +5787,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string &descri
const Line line = Line(path.polyline.get_points()[point_index - 1], path.polyline.get_points()[point_index]);
if (path.role() != erExternalPerimeter || config().external_perimeter_cut_corners.value == 0) {
// normal & legacy pathcode
_extrude_line(gcode, line, e_per_mm, comment);
_extrude_line(gcode, line, e_per_mm, comment, path.role());
} else {
_extrude_line_cut_corner(gcode, line, e_per_mm, comment, last_pos, path.width);
}
Expand Down
2 changes: 1 addition & 1 deletion src/libslic3r/GCode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ class GCode : ExtrusionVisitorConst {

double compute_e_per_mm(double path_mm3_per_mm);
std::string _extrude(const ExtrusionPath &path, const std::string &description, double speed = -1);
void _extrude_line(std::string& gcode_str, const Line& line, const double e_per_mm, const std::string& comment);
void _extrude_line(std::string& gcode_str, const Line& line, const double e_per_mm, const std::string& comment, ExtrusionRole role);
void _extrude_line_cut_corner(std::string& gcode_str, const Line& line, const double e_per_mm, const std::string& comment, Point& last_pos, const double path_width);
std::string _before_extrude(const ExtrusionPath &path, const std::string &description, double speed = -1);
double_t _compute_speed_mm_per_sec(const ExtrusionPath &path, double speed, std::string *comment);
Expand Down
3 changes: 2 additions & 1 deletion src/libslic3r/Preset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ static std::vector<std::string> s_Preset_print_options {
"bridge_overlap_min",
"first_layer_flow_ratio",
"clip_multipart_objects", "enforce_full_fill_volume", "external_infill_margin", "bridged_infill_margin",
"small_area_infill_flow_compensation", "small_area_infill_flow_compensation_model",
// compensation
"first_layer_size_compensation",
"first_layer_size_compensation_layers",
Expand Down Expand Up @@ -737,7 +738,7 @@ static std::vector<std::string> s_Preset_print_options {
"milling_speed",
//Arachne
"perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
"wall_distribution_count", "min_feature_size", "min_bead_width"
"wall_distribution_count", "min_feature_size", "min_bead_width",
};

static std::vector<std::string> s_Preset_filament_options {
Expand Down
38 changes: 38 additions & 0 deletions src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2510,6 +2510,42 @@ void PrintConfigDef::init_fff_params()
def->sidetext = L("%");
def->set_default_value(new ConfigOptionPercent(10));

def = this->add("small_area_infill_flow_compensation", coBool);
def->label = L("Enable small area flow compensation");
def->category = OptionCategory::infill;
def->tooltip = L("Enable flow compensation for small infill areas."
"\nFirst layer is always disabled, to not compromise adhesion.");
def->mode = comExpert | comSuSi;
def->set_default_value(new ConfigOptionBool(false));

def = this->add("small_area_infill_flow_compensation_model", coGraph);
def->label = L("Flow Compensation Model");
def->category = OptionCategory::infill;
def->tooltip = L("Flow Compensation Model, used to adjust the flow for small solid infill "
"lines. The model is a graph of flow correction factors (between 0 and 1) per extrusion length (in mm)."
"\nThe first point length has to be 0mm. the last point need to have a flow correction of 1.");
def->mode = comExpert | comSuSi;
def->set_default_value(new ConfigOptionGraph(GraphData(0,10, GraphData::GraphType::SPLINE,
{{0,0},{0.2,0.44},{0.4,0.61},{0.6,0.7},{0.8,0.76},{1.5,0.86},{2,0.89},{3,0.92},{5,0.95},{10,1}}
)));
def->graph_settings = std::make_shared<GraphSettings>();
def->graph_settings->title = L("Flow Compensation Model");
def->graph_settings->description = def->tooltip;
def->graph_settings->x_label = L("Length of an extrusion (mm)");
def->graph_settings->y_label = L("Flow correction (ratio between 0 and 1)");
def->graph_settings->null_label = L("No values");
def->graph_settings->label_min_x = "";
def->graph_settings->label_max_x = L("Maximum length");
def->graph_settings->label_min_y = L("Minimum ratio");
def->graph_settings->label_max_y = L("Maximum ratio");
def->graph_settings->min_x = 0;
def->graph_settings->max_x = 100;
def->graph_settings->step_x = 0.1;
def->graph_settings->min_y = 0;
def->graph_settings->max_y = 1;
def->graph_settings->step_y = 0.01;
def->graph_settings->allowed_types = {GraphData::GraphType::LINEAR, GraphData::GraphType::SPLINE, GraphData::GraphType::SQUARE};

def = this->add("first_layer_acceleration", coFloatOrPercent);
def->label = L("Max");
def->full_label = L("First layer acceleration");
Expand Down Expand Up @@ -8467,6 +8503,8 @@ std::unordered_set<std::string> prusa_export_to_remove_keys = {
"skirt_brim",
"skirt_distance_from_brim",
"skirt_extrusion_width",
"small_area_infill_flow_compensation",
"small_area_infill_flow_compensation_model",
"small_perimeter_max_length",
"small_perimeter_min_length",
"solid_fill_pattern",
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/PrintConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,8 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionFloat, print_retract_length))
((ConfigOptionFloat, print_retract_lift))
((ConfigOptionString, region_gcode))
((ConfigOptionBool, small_area_infill_flow_compensation))
((ConfigOptionGraph, small_area_infill_flow_compensation_model))
((ConfigOptionFloatOrPercent, small_perimeter_speed))
((ConfigOptionFloatOrPercent, small_perimeter_min_length))
((ConfigOptionFloatOrPercent, small_perimeter_max_length))
Expand Down
2 changes: 2 additions & 0 deletions src/libslic3r/PrintObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,8 @@ FillLightning::GeneratorPtr PrintObject::prepare_lightning_infill_data()
|| opt_key == "seam_notch_outer"
|| opt_key == "seam_travel_cost"
|| opt_key == "seam_visibility"
|| opt_key == "small_area_infill_flow_compensation"
|| opt_key == "small_area_infill_flow_compensation_model"
|| opt_key == "small_perimeter_speed"
|| opt_key == "small_perimeter_min_length"
|| opt_key == "small_perimeter_max_length"
Expand Down
5 changes: 5 additions & 0 deletions src/slic3r/GUI/ConfigManipulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,11 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)

toggle_field("fill_angle", (have_infill || has_solid_infill) && ((ConfigOptionVectorBase*)config->option("fill_angle_template"))->size() == 0);


toggle_field("small_area_infill_flow_compensation", has_solid_infill);
bool have_small_area_infill_flow_compensation = has_solid_infill && config->opt_bool("small_area_infill_flow_compensation");
toggle_field("small_area_infill_flow_compensation_model", have_small_area_infill_flow_compensation);

toggle_field("top_solid_min_thickness", ! has_spiral_vase && has_top_solid_infill);
toggle_field("bottom_solid_min_thickness", ! has_spiral_vase && has_bottom_solid_infill);

Expand Down

0 comments on commit eb53170

Please sign in to comment.