diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index b1aa81c73a..fc66dd7f07 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1977,7 +1977,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato } else m_enable_extrusion_role_markers = false; - if (m_config.small_area_infill_flow_compensation.value && !print.config().small_area_infill_flow_compensation_model.empty()) + if (!print.config().small_area_infill_flow_compensation_model.empty()) m_small_area_infill_flow_compensator = make_unique(print.config()); file.write_format("; HEADER_BLOCK_START\n"); diff --git a/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp index 573347d5ec..dabf710a22 100644 --- a/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp +++ b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.cpp @@ -14,6 +14,7 @@ #include "../PrintConfig.hpp" #include "SmallAreaInfillFlowCompensator.hpp" +#include namespace Slic3r { @@ -24,61 +25,75 @@ bool nearly_equal(double a, double b) SmallAreaInfillFlowCompensator::SmallAreaInfillFlowCompensator(const Slic3r::GCodeConfig& config) { - for (auto& line : config.small_area_infill_flow_compensation_model.values) { - std::istringstream iss(line); - std::string value_str; - double eLength = 0.0; + try { + for (auto& line : config.small_area_infill_flow_compensation_model.values) { + std::istringstream iss(line); + std::string value_str; + double eLength = 0.0; - if (std::getline(iss, value_str, ',')) { - try { - eLength = std::stod(value_str); - if (std::getline(iss, value_str, ',')) { - eLengths.push_back(eLength); - flowComps.push_back(std::stod(value_str)); + if (std::getline(iss, value_str, ',')) { + try { + // Trim leading and trailing whitespace + value_str = std::regex_replace(value_str, std::regex("^\\s+|\\s+$"), ""); + if (value_str.empty()) { + continue; + } + eLength = std::stod(value_str); + if (std::getline(iss, value_str, ',')) { + eLengths.push_back(eLength); + flowComps.push_back(std::stod(value_str)); + } + } catch (...) { + std::stringstream ss; + ss << "Error parsing data point in small area infill compensation model:" << line << std::endl; + + throw Slic3r::InvalidArgument(ss.str()); } - } catch (...) { - std::stringstream ss; - ss << "Error parsing data point in small area infill compensation model:" << line << std::endl; - - throw Slic3r::InvalidArgument(ss.str()); } } - } - for (int i = 0; i < eLengths.size(); i++) { - if (i == 0) { - if (!nearly_equal(eLengths[i], 0.0)) { - throw Slic3r::InvalidArgument("First extrusion length for small area infill compensation model must be 0"); - } - } else { - if (nearly_equal(eLengths[i], 0.0)) { - throw Slic3r::InvalidArgument("Only the first extrusion length for small area infill compensation model can be 0"); - } - if (eLengths[i] <= eLengths[i - 1]) { - throw Slic3r::InvalidArgument("Extrusion lengths for subsequent points must be increasing"); + for (int i = 0; i < eLengths.size(); i++) { + if (i == 0) { + if (!nearly_equal(eLengths[i], 0.0)) { + throw Slic3r::InvalidArgument("First extrusion length for small area infill compensation model must be 0"); + } + } else { + if (nearly_equal(eLengths[i], 0.0)) { + throw Slic3r::InvalidArgument("Only the first extrusion length for small area infill compensation model can be 0"); + } + if (eLengths[i] <= eLengths[i - 1]) { + throw Slic3r::InvalidArgument("Extrusion lengths for subsequent points must be increasing"); + } } } - } - if (!flowComps.empty() && !nearly_equal(flowComps.back(), 1.0)) { - throw Slic3r::InvalidArgument("Final compensation factor for small area infill flow compensation model must be 1.0"); - } + if (!flowComps.empty() && !nearly_equal(flowComps.back(), 1.0)) { + throw Slic3r::InvalidArgument("Final compensation factor for small area infill flow compensation model must be 1.0"); + } - flowModel.set_points(eLengths, flowComps); + flowModel = std::make_unique(); + flowModel->set_points(eLengths, flowComps); + + } catch (std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "Error parsing small area infill compensation model: " << e.what(); + } } - double SmallAreaInfillFlowCompensator::flow_comp_model(const double line_length) { + if(flowModel == nullptr) + return 1.0; + if (line_length == 0 || line_length > max_modified_length()) { return 1.0; } - return flowModel(line_length); + return (*flowModel)(line_length); } double SmallAreaInfillFlowCompensator::modify_flow(const double line_length, const double dE, const ExtrusionRole role) { - if (role == ExtrusionRole::erSolidInfill || role == ExtrusionRole::erTopSolidInfill || role == ExtrusionRole::erBottomSurface) { + if (flowModel && + (role == ExtrusionRole::erSolidInfill || role == ExtrusionRole::erTopSolidInfill || role == ExtrusionRole::erBottomSurface)) { return dE * flow_comp_model(line_length); } diff --git a/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp index 7d804c9b47..34c14864d1 100644 --- a/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp +++ b/src/libslic3r/GCode/SmallAreaInfillFlowCompensator.hpp @@ -5,6 +5,7 @@ #include "../PrintConfig.hpp" #include "../ExtrusionEntity.hpp" #include "spline/spline.h" +#include namespace Slic3r { @@ -23,7 +24,7 @@ private: std::vector flowComps; // TODO: Cubic Spline - tk::spline flowModel; + std::unique_ptr flowModel; double flow_comp_model(const double line_length); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index d4ae44c967..c3d6d971e5 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -924,8 +924,7 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "wipe_speed") { steps.emplace_back(posPerimeters); } else if ( - opt_key == "small_area_infill_flow_compensation" - || opt_key == "small_area_infill_flow_compensation_model") { + opt_key == "small_area_infill_flow_compensation_model") { steps.emplace_back(posSlice); } else if (opt_key == "gap_infill_speed" || opt_key == "filter_out_gap_fill" ) { @@ -1080,7 +1079,8 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "infill_anchor" || opt_key == "infill_anchor_max" || opt_key == "top_surface_line_width" - || opt_key == "initial_layer_line_width") { + || opt_key == "initial_layer_line_width" + || opt_key == "small_area_infill_flow_compensation") { steps.emplace_back(posInfill); } else if (opt_key == "sparse_infill_pattern") { steps.emplace_back(posPrepareInfill);