Skip to content

Commit

Permalink
ensure the layer height & first layer height are low enough.
Browse files Browse the repository at this point in the history
TODO: same for actual real layer height (from variable layer heights)
  • Loading branch information
supermerill authored and supermerill committed Aug 21, 2021
1 parent a510c30 commit 26500cd
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 84 deletions.
4 changes: 2 additions & 2 deletions src/libslic3r/Fill/Fill.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
FlowRole extrusion_role = surface.has_pos_top() ? frTopSolidInfill : (surface.has_fill_solid() ? frSolidInfill : frInfill);
bool is_bridge = layer.id() > 0 && surface.has_mod_bridge();
bool is_denser = false;
params.extruder = layerm.region()->extruder(extrusion_role);
params.extruder = layerm.region()->extruder(extrusion_role, *layer.object());
params.pattern = region_config.fill_pattern.value;
params.density = float(region_config.fill_density) / 100.f;
params.dont_adjust = false;
Expand Down Expand Up @@ -324,7 +324,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
}
if (internal_solid_fill == nullptr) {
// Produce another solid fill.
params.extruder = layerm.region()->extruder(frSolidInfill);
params.extruder = layerm.region()->extruder(frSolidInfill, *layer.object());
params.pattern = layerm.region()->config().solid_fill_pattern.value;
params.density = 100.f;
params.role = erInternalInfill;
Expand Down
102 changes: 55 additions & 47 deletions src/libslic3r/Print.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1518,20 +1518,6 @@ std::pair<PrintBase::PrintValidationError, std::string> Print::validate() const
return L("One or more object were assigned an extruder that the printer does not have.");
#endif

auto validate_extrusion_width = [min_nozzle_diameter, max_nozzle_diameter](const ConfigBase &config, const char *opt_key, double layer_height, std::string &err_msg) -> bool {
double extrusion_width_min = config.get_abs_value(opt_key, min_nozzle_diameter);
double extrusion_width_max = config.get_abs_value(opt_key, max_nozzle_diameter);
if (extrusion_width_min == 0) {
// Default "auto-generated" extrusion width is always valid.
} else if (extrusion_width_min <= layer_height) {
err_msg = (boost::format(L("%1%=%2% mm is too low to be printable at a layer height %3% mm")) % opt_key % extrusion_width_min % layer_height).str();
return false;
} else if (extrusion_width_max >= max_nozzle_diameter * 4.) {
err_msg = (boost::format(L("Excessive %1%=%2% mm to be printable with a nozzle diameter %3% mm")) % opt_key % extrusion_width_max % max_nozzle_diameter).str();
return false;
}
return true;
};
for (PrintObject *object : m_objects) {
if (object->config().raft_layers > 0 || object->config().support_material.value) {
if ((object->config().support_material_extruder == 0 || object->config().support_material_interface_extruder == 0) && max_nozzle_diameter - min_nozzle_diameter > EPSILON) {
Expand All @@ -1555,40 +1541,62 @@ std::pair<PrintBase::PrintValidationError, std::string> Print::validate() const
}
}
}

// validate first_layer_height
double first_layer_height = object->config().get_abs_value("first_layer_height", this->m_config.nozzle_diameter.get_at(0));
double first_layer_min_nozzle_diameter;
if (object->config().raft_layers > 0) {
// if we have raft layers, only support material extruder is used on first layer
size_t first_layer_extruder = object->config().raft_layers == 1
? object->config().support_material_interface_extruder-1
: object->config().support_material_extruder-1;
first_layer_min_nozzle_diameter = (first_layer_extruder == size_t(-1)) ?
min_nozzle_diameter :
m_config.nozzle_diameter.get_at(first_layer_extruder);
} else {
// if we don't have raft layers, any nozzle diameter is potentially used in first layer
first_layer_min_nozzle_diameter = min_nozzle_diameter;

// validate layer_height for each region
for (size_t region_id = 0; region_id < object->region_volumes.size(); ++region_id) {
if (object->region_volumes[region_id].empty()) continue;
const PrintRegion* region = this->regions()[region_id];
std::vector<uint16_t> object_extruders;
PrintRegion::collect_object_printing_extruders(config(), object->config(), region->config(), object_extruders);
//object->region_volumes[region_id].front().first.second < object->layers()
double layer_height = object->config().layer_height.value;
for (uint16_t extruder_id : object_extruders) {
double min_layer_height = config().min_layer_height.values[extruder_id];
double max_layer_height = config().max_layer_height.values[extruder_id];
double nozzle_diameter = config().nozzle_diameter.values[extruder_id];
double first_layer_height = object->config().first_layer_height.get_abs_value(nozzle_diameter);
if (max_layer_height < EPSILON) max_layer_height = nozzle_diameter * 0.75;

//check first layer
if (object->region_volumes[region_id].front().first.first < first_layer_height) {
if (first_layer_height + EPSILON < min_layer_height)
return { PrintBase::PrintValidationError::pveWrongSettings, (boost::format(L("First layer height can't be greater than %s")) % "min layer height").str() };
for (auto tuple : std::vector<std::pair<double, const char*>>{
{nozzle_diameter, "nozzle diameter"},
{max_layer_height, "max layer height"},
{skirt_flow(extruder_id).width, "skirt extrusion width"},
{region->width(FlowRole::frSupportMaterial, true, *object), "support material extrusion width"},
{region->width(FlowRole::frPerimeter, true, *object), "perimeter extrusion width"},
{region->width(FlowRole::frExternalPerimeter, true, *object), "perimeter extrusion width"},
{region->width(FlowRole::frInfill, true, *object), "infill extrusion width"},
{region->width(FlowRole::frSolidInfill, true, *object), "solid infill extrusion width"},
{region->width(FlowRole::frTopSolidInfill, true, *object), "top solid infill extrusion width"},
})
if (first_layer_height > tuple.first + EPSILON)
return { PrintBase::PrintValidationError::pveWrongSettings, (boost::format(L("First layer height can't be greater than %s")) % tuple.second).str() };

}
//check not-first layer
if (object->region_volumes[region_id].front().first.second > layer_height) {
if (layer_height + EPSILON < min_layer_height)
return { PrintBase::PrintValidationError::pveWrongSettings, (boost::format(L("First layer height can't be greater than %s")) % "min layer height").str() };
for (auto tuple : std::vector<std::pair<double, const char*>>{
{nozzle_diameter, "nozzle diameter"},
{max_layer_height, "max layer height"},
{skirt_flow(extruder_id).width, "skirt extrusion width"},
{region->width(FlowRole::frSupportMaterial, false, *object), "support material extrusion width"},
{region->width(FlowRole::frPerimeter, false, *object), "perimeter extrusion width"},
{region->width(FlowRole::frExternalPerimeter, false, *object), "perimeter extrusion width"},
{region->width(FlowRole::frInfill, false, *object), "infill extrusion width"},
{region->width(FlowRole::frSolidInfill, false, *object), "solid infill extrusion width"},
{region->width(FlowRole::frTopSolidInfill, false, *object), "top solid infill extrusion width"},
})
if (layer_height > tuple.first + EPSILON)
return { PrintBase::PrintValidationError::pveWrongSettings, (boost::format(L("Layer height can't be greater than %s")) % tuple.second).str() };
}
}
}
if (first_layer_height > first_layer_min_nozzle_diameter)
return { PrintBase::PrintValidationError::pveWrongSettings,L("First layer height can't be greater than nozzle diameter") };

// validate layer_height
double layer_height = object->config().layer_height.value;
if (layer_height > min_nozzle_diameter)
return { PrintBase::PrintValidationError::pveWrongSettings,L("Layer height can't be greater than nozzle diameter") };

// Validate extrusion widths.
std::string err_msg;
if (! validate_extrusion_width(object->config(), "extrusion_width", layer_height, err_msg))
return { PrintBase::PrintValidationError::pveWrongSettings,err_msg };
if ((object->config().support_material || object->config().raft_layers > 0) && ! validate_extrusion_width(object->config(), "support_material_extrusion_width", layer_height, err_msg))
return { PrintBase::PrintValidationError::pveWrongSettings,err_msg };
for (const char *opt_key : { "perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width", "top_infill_extrusion_width" })
for (size_t i = 0; i < object->region_volumes.size(); ++ i)
if (! object->region_volumes[i].empty() && ! validate_extrusion_width(this->get_region(i)->config(), opt_key, layer_height, err_msg))
return { PrintBase::PrintValidationError::pveWrongSettings, err_msg };

}
}

Expand Down
5 changes: 3 additions & 2 deletions src/libslic3r/Print.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ class PrintRegion
const Print* print() const { return m_print; }
const PrintRegionConfig& config() const { return m_config; }
// 1-based extruder identifier for this region and role.
uint16_t extruder(FlowRole role) const;
Flow flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject &object) const;
uint16_t extruder(FlowRole role, const PrintObject& object) const;
Flow flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, const PrintObject& object) const;
float width(FlowRole role, bool first_layer, const PrintObject& object) const;
// Average diameter of nozzles participating on extruding this region.
coordf_t nozzle_dmr_avg(const PrintConfig &print_config) const;
// Average diameter of nozzles participating on extruding this region.
Expand Down
15 changes: 14 additions & 1 deletion src/libslic3r/PrintConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5945,7 +5945,13 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const
double max_nozzle_diameter = 0;
for (double dmr : nozzle_diameter_option->values)
max_nozzle_diameter = std::max(max_nozzle_diameter, dmr);
Flow flow = Flow::new_from_spacing(spacing_option->get_abs_value(max_nozzle_diameter), max_nozzle_diameter, layer_height_option->value, false);
double spacing_value = spacing_option->get_abs_value(max_nozzle_diameter);
Flow flow = Flow::new_from_spacing(spacing_value, max_nozzle_diameter,layer_height_option->value, false);
//test for valid height. If too high, revert to round shape
if (flow.height > spacing_value / (1 - (1. - 0.25 * PI) * flow.spacing_ratio)) {
flow.width = spacing_value / (1 - (1. - 0.25 * PI) * flow.spacing_ratio);
flow.height = flow.width;
}
if (opt_key == "extrusion_spacing") {
ConfigOptionFloatOrPercent* width_option = this->option<ConfigOptionFloatOrPercent>("extrusion_width");
if (width_option) {
Expand Down Expand Up @@ -6055,6 +6061,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const
width_option->set_phony(false);
spacing_option->set_phony(true);
Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
if (flow.width < flow.height) flow.height = flow.width;
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
Expand All @@ -6066,6 +6073,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const
width_option->set_phony(false);
spacing_option->set_phony(true);
Flow flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
if (flow.width < flow.height) flow.height = flow.width;
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
Expand All @@ -6078,6 +6086,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const
width_option->set_phony(false);
spacing_option->set_phony(true);
Flow flow = Flow::new_from_config_width(FlowRole::frExternalPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
if (flow.width < flow.height) flow.height = flow.width;
flow.spacing_ratio = perimeter_overlap_option->get_abs_value(1);
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
Expand All @@ -6091,6 +6100,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const
width_option->set_phony(false);
spacing_option->set_phony(true);
Flow ext_perimeter_flow = Flow::new_from_config_width(FlowRole::frPerimeter, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
if (ext_perimeter_flow.width < ext_perimeter_flow.height) ext_perimeter_flow.height = ext_perimeter_flow.width;
ext_perimeter_flow.spacing_ratio = external_perimeter_overlap_option->get_abs_value(0.5);
spacing_option->value = (width_option->percent) ? std::round(100 * ext_perimeter_flow.spacing() / max_nozzle_diameter) : (std::round(ext_perimeter_flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
Expand All @@ -6103,6 +6113,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const
width_option->set_phony(false);
spacing_option->set_phony(true);
Flow flow = Flow::new_from_config_width(FlowRole::frInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
if (flow.width < flow.height) flow.height = flow.width;
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
Expand All @@ -6114,6 +6125,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const
width_option->set_phony(false);
spacing_option->set_phony(true);
Flow flow = Flow::new_from_config_width(FlowRole::frSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
if (flow.width < flow.height) flow.height = flow.width;
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
Expand All @@ -6125,6 +6137,7 @@ bool DynamicPrintConfig::value_changed(const t_config_option_key& opt_key, const
width_option->set_phony(false);
spacing_option->set_phony(true);
Flow flow = Flow::new_from_config_width(FlowRole::frTopSolidInfill, *width_option, max_nozzle_diameter, layer_height_option->value, 0);
if (flow.width < flow.height) flow.height = flow.width;
spacing_option->value = (width_option->percent) ? std::round(100 * flow.spacing() / max_nozzle_diameter) : (std::round(flow.spacing() * 10000) / 10000);
spacing_option->percent = width_option->percent;
something_changed = true;
Expand Down
6 changes: 3 additions & 3 deletions src/libslic3r/PrintObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2171,7 +2171,7 @@ namespace Slic3r {

static void apply_to_print_region_config(PrintRegionConfig& out, const DynamicPrintConfig& in)
{
// 1) Copy the "extruder key to infill_extruder and perimeter_extruder.
// 1) Copy the "extruder" key to infill_extruder and perimeter_extruder.
std::string sextruder = "extruder";
auto* opt_extruder = in.opt<ConfigOptionInt>(sextruder);
if (opt_extruder) {
Expand Down Expand Up @@ -2381,7 +2381,7 @@ namespace Slic3r {
}
std::vector<ExPolygons> expolygons_by_layer = this->slice_region(region_id, slice_zs, slicing_mode, slicing_mode_normal_below_layer, SlicingMode::Regular);
//scale for shrinkage
const size_t extruder_id = this->print()->regions()[region_id]->extruder(FlowRole::frPerimeter) - 1;
const size_t extruder_id = this->print()->regions()[region_id]->extruder(FlowRole::frPerimeter, *this) - 1;
double scale = print()->config().filament_shrink.get_abs_value(extruder_id, 1);
if (scale != 1) {
scale = 1 / scale;
Expand Down Expand Up @@ -2434,7 +2434,7 @@ namespace Slic3r {
}
//scale for shrinkage
for (SlicedVolume& sv : sliced_volumes) {
double scale = print()->config().filament_shrink.get_abs_value(this->print()->regions()[sv.region_id]->extruder(FlowRole::frPerimeter) - 1, 1);
double scale = print()->config().filament_shrink.get_abs_value(this->print()->regions()[sv.region_id]->extruder(FlowRole::frPerimeter, *this) - 1, 1);
if (scale != 1) {
scale = 1 / scale;
for (ExPolygons& polys : sv.expolygons_by_layer)
Expand Down
Loading

0 comments on commit 26500cd

Please sign in to comment.