mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-06-26 09:25:26 -06:00
Ironing support interfaces (#9548)
* Generate support interface iron extrusion * Always ironing last * Add options * Move ironing speed to speed tab * Don't iron places that are covered by upper support layers * Disable support interface spacing settings when support ironing is enabled * Update text
This commit is contained in:
parent
961b73c6be
commit
b9cce6c179
10 changed files with 171 additions and 16 deletions
|
@ -4325,10 +4325,16 @@ LayerResult GCode::process_layer(
|
|||
|
||||
ExtrusionRole support_extrusion_role = instance_to_print.object_by_extruder.support_extrusion_role;
|
||||
bool is_overridden = support_extrusion_role == erSupportMaterialInterface ? support_intf_overridden : support_overridden;
|
||||
if (is_overridden == (print_wipe_extrusions != 0))
|
||||
if (is_overridden == (print_wipe_extrusions != 0)) {
|
||||
gcode += this->extrude_support(
|
||||
// support_extrusion_role is erSupportMaterial, erSupportTransition, erSupportMaterialInterface or erMixed for all extrusion paths.
|
||||
instance_to_print.object_by_extruder.support->chained_path_from(m_last_pos, support_extrusion_role));
|
||||
*instance_to_print.object_by_extruder.support, support_extrusion_role);
|
||||
|
||||
// Make sure ironing is the last
|
||||
if (support_extrusion_role == erMixed || support_extrusion_role == erSupportMaterialInterface) {
|
||||
gcode += this->extrude_support(*instance_to_print.object_by_extruder.support, erIroning);
|
||||
}
|
||||
}
|
||||
|
||||
m_layer = layer_to_print.layer();
|
||||
m_object_layer_over_raft = object_layer_over_raft;
|
||||
|
@ -5036,21 +5042,37 @@ std::string GCode::extrude_infill(const Print &print, const std::vector<ObjectBy
|
|||
return gcode;
|
||||
}
|
||||
|
||||
std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fills)
|
||||
std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fills, const ExtrusionRole support_extrusion_role)
|
||||
{
|
||||
static constexpr const char *support_label = "support material";
|
||||
static constexpr const char *support_interface_label = "support material interface";
|
||||
const char* support_transition_label = "support transition";
|
||||
static constexpr const char* support_transition_label = "support transition";
|
||||
static constexpr const char* support_ironing_label = "support ironing";
|
||||
|
||||
std::string gcode;
|
||||
if (! support_fills.entities.empty()) {
|
||||
|
||||
ExtrusionEntitiesPtr extrusions;
|
||||
extrusions.reserve(support_fills.entities.size());
|
||||
for (ExtrusionEntity* ee : support_fills.entities) {
|
||||
const auto role = ee->role();
|
||||
if ((role == support_extrusion_role) || (support_extrusion_role == erMixed && role != erIroning)) {
|
||||
extrusions.emplace_back(ee);
|
||||
}
|
||||
}
|
||||
if (extrusions.empty())
|
||||
return gcode;
|
||||
|
||||
chain_and_reorder_extrusion_entities(extrusions, &m_last_pos);
|
||||
|
||||
const double support_speed = m_config.support_speed.value;
|
||||
const double support_interface_speed = m_config.get_abs_value("support_interface_speed");
|
||||
for (const ExtrusionEntity *ee : support_fills.entities) {
|
||||
for (const ExtrusionEntity *ee : extrusions) {
|
||||
ExtrusionRole role = ee->role();
|
||||
assert(role == erSupportMaterial || role == erSupportMaterialInterface || role == erSupportTransition);
|
||||
assert(role == erSupportMaterial || role == erSupportMaterialInterface || role == erSupportTransition || role == erIroning);
|
||||
const char* label = (role == erSupportMaterial) ? support_label :
|
||||
((role == erSupportMaterialInterface) ? support_interface_label : support_transition_label);
|
||||
((role == erSupportMaterialInterface) ? support_interface_label :
|
||||
((role == erIroning) ? support_ironing_label : support_transition_label));
|
||||
// BBS
|
||||
//const double speed = (role == erSupportMaterial) ? support_speed : support_interface_speed;
|
||||
const double speed = -1.0;
|
||||
|
@ -5067,7 +5089,7 @@ std::string GCode::extrude_support(const ExtrusionEntityCollection &support_fill
|
|||
gcode += this->extrude_loop(*loop, label, speed);
|
||||
}
|
||||
else if (collection) {
|
||||
gcode += extrude_support(*collection);
|
||||
gcode += extrude_support(*collection, support_extrusion_role);
|
||||
}
|
||||
else {
|
||||
throw Slic3r::InvalidArgument("Unknown extrusion type");
|
||||
|
|
|
@ -449,7 +449,7 @@ private:
|
|||
|
||||
std::string extrude_perimeters(const Print& print, const std::vector<ObjectByExtruder::Island::Region>& by_region, bool is_first_layer, bool is_infill_first);
|
||||
std::string extrude_infill(const Print& print, const std::vector<ObjectByExtruder::Island::Region>& by_region, bool ironing);
|
||||
std::string extrude_support(const ExtrusionEntityCollection& support_fills);
|
||||
std::string extrude_support(const ExtrusionEntityCollection& support_fills, const ExtrusionRole support_extrusion_role);
|
||||
|
||||
// BBS
|
||||
LiftType to_lift_type(ZHopType z_hop_types);
|
||||
|
|
|
@ -789,6 +789,7 @@ static std::vector<std::string> s_Preset_print_options {
|
|||
"infill_direction", "solid_infill_direction", "rotate_solid_infill_direction", "counterbore_hole_bridging",
|
||||
"minimum_sparse_infill_area", "reduce_infill_retraction","internal_solid_infill_pattern","gap_fill_target",
|
||||
"ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_inset",
|
||||
"support_ironing", "support_ironing_pattern", "support_ironing_flow", "support_ironing_spacing",
|
||||
"max_travel_detour_distance",
|
||||
"fuzzy_skin", "fuzzy_skin_thickness", "fuzzy_skin_point_distance", "fuzzy_skin_first_layer", "fuzzy_skin_noise_type", "fuzzy_skin_scale", "fuzzy_skin_octaves", "fuzzy_skin_persistence",
|
||||
"max_volumetric_extrusion_rate_slope", "max_volumetric_extrusion_rate_slope_segment_length","extrusion_rate_smoothing_external_perimeter_only",
|
||||
|
|
|
@ -4897,7 +4897,8 @@ void PrintConfigDef::init_fff_params()
|
|||
def = this->add("support_interface_spacing", coFloat);
|
||||
def->label = L("Top interface spacing");
|
||||
def->category = L("Support");
|
||||
def->tooltip = L("Spacing of interface lines. Zero means solid interface.");
|
||||
def->tooltip = L("Spacing of interface lines. Zero means solid interface.\n"
|
||||
"Force using solid interface when support ironing is enabled.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
|
@ -5192,6 +5193,48 @@ void PrintConfigDef::init_fff_params()
|
|||
def->tooltip = L("This setting specifies whether to add infill inside large hollows of tree support.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("support_ironing", coBool);
|
||||
def->label = L("Ironing Support Interface");
|
||||
def->category = L("Support");
|
||||
def->tooltip = L("Ironing is using small flow to print on same height of support interface again to make it more smooth. "
|
||||
"This setting controls whether support interface being ironed. When enabled, support interface will be extruded as solid too.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("support_ironing_pattern", coEnum);
|
||||
def->label = L("Support Ironing Pattern");
|
||||
def->tooltip = L("The pattern that will be used when ironing.");
|
||||
def->category = L("Support");
|
||||
def->enum_keys_map = &ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||
def->enum_values.push_back("concentric");
|
||||
def->enum_values.push_back("zig-zag");
|
||||
def->enum_labels.push_back(L("Concentric"));
|
||||
def->enum_labels.push_back(L("Rectilinear"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipRectilinear));
|
||||
|
||||
def = this->add("support_ironing_flow", coPercent);
|
||||
def->label = L("Support Ironing flow");
|
||||
def->category = L("Support");
|
||||
def->tooltip = L("The amount of material to extrude during ironing. Relative to flow of normal support interface layer height. "
|
||||
"Too high value results in overextrusion on the surface.");
|
||||
def->sidetext = "%";
|
||||
def->ratio_over = "layer_height";
|
||||
def->min = 0;
|
||||
def->max = 100;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPercent(10));
|
||||
|
||||
def = this->add("support_ironing_spacing", coFloat);
|
||||
def->label = L("Support Ironing line spacing");
|
||||
def->category = L("Support");
|
||||
def->tooltip = L("The distance between the lines of ironing.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->max = 1;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.1));
|
||||
|
||||
def = this->add("activate_chamber_temp_control",coBools);
|
||||
def->label = L("Activate temperature control");
|
||||
|
|
|
@ -849,6 +849,10 @@ PRINT_CONFIG_CLASS_DEFINE(
|
|||
((ConfigOptionFloatOrPercent, support_threshold_overlap))
|
||||
((ConfigOptionFloat, support_object_xy_distance))
|
||||
((ConfigOptionFloat, support_object_first_layer_gap))
|
||||
((ConfigOptionBool, support_ironing))
|
||||
((ConfigOptionEnum<InfillPattern>, support_ironing_pattern))
|
||||
((ConfigOptionPercent, support_ironing_flow))
|
||||
((ConfigOptionFloat, support_ironing_spacing))
|
||||
((ConfigOptionFloat, xy_hole_compensation))
|
||||
((ConfigOptionFloat, xy_contour_compensation))
|
||||
((ConfigOptionBool, flush_into_objects))
|
||||
|
|
|
@ -1016,6 +1016,10 @@ bool PrintObject::invalidate_state_by_config_options(
|
|||
//|| opt_key == "independent_support_layer_height" // BBS
|
||||
|| opt_key == "support_threshold_angle"
|
||||
|| opt_key == "support_threshold_overlap"
|
||||
|| opt_key == "support_ironing"
|
||||
|| opt_key == "support_ironing_pattern"
|
||||
|| opt_key == "support_ironing_flow"
|
||||
|| opt_key == "support_ironing_spacing"
|
||||
|| opt_key == "raft_expansion"
|
||||
|| opt_key == "raft_first_layer_density"
|
||||
|| opt_key == "raft_first_layer_expansion"
|
||||
|
|
|
@ -1605,6 +1605,9 @@ void generate_support_toolpaths(
|
|||
SupportGeneratorLayerExtruded base_interface_layer;
|
||||
boost::container::static_vector<LayerCacheItem, 5> nonempty;
|
||||
|
||||
float ironing_angle;
|
||||
Polygons polys_to_iron;
|
||||
|
||||
void add_nonempty_and_sort() {
|
||||
for (SupportGeneratorLayerExtruded *item : { &bottom_contact_layer, &top_contact_layer, &interface_layer, &base_interface_layer, &base_layer })
|
||||
if (! item->empty())
|
||||
|
@ -1694,6 +1697,12 @@ void generate_support_toolpaths(
|
|||
base_layer = std::move(top_contact_layer);
|
||||
}
|
||||
} else {
|
||||
if (support_params.ironing && !top_contact_layer.empty()) {
|
||||
// Orca: save the top surface to be ironed later
|
||||
layer_cache.ironing_angle = support_interface_angle; // TODO: should we rotate 90 degrees?
|
||||
layer_cache.polys_to_iron = top_contact_layer.polygons_to_extrude();
|
||||
}
|
||||
|
||||
loop_interface_processor.generate(top_contact_layer, support_params.support_material_interface_flow);
|
||||
// If no loops are allowed, we treat the contact layer exactly as a generic interface layer.
|
||||
// Merge interface_layer into top_contact_layer, as the top_contact_layer is not synchronized and therefore it will be used
|
||||
|
@ -1886,7 +1895,7 @@ void generate_support_toolpaths(
|
|||
|
||||
// Now modulate the support layer height in parallel.
|
||||
tbb::parallel_for(tbb::blocked_range<size_t>(n_raft_layers, support_layers.size()),
|
||||
[&support_layers, &layer_caches]
|
||||
[&support_layers, &layer_caches, &support_params, &bbox_object]
|
||||
(const tbb::blocked_range<size_t>& range) {
|
||||
for (size_t support_layer_id = range.begin(); support_layer_id < range.end(); ++ support_layer_id) {
|
||||
SupportLayer &support_layer = *support_layers[support_layer_id];
|
||||
|
@ -1897,6 +1906,39 @@ void generate_support_toolpaths(
|
|||
modulate_extrusion_by_overlapping_layers(layer_cache_item.layer_extruded->extrusions, *layer_cache_item.layer_extruded->layer, layer_cache_item.overlapping);
|
||||
support_layer.support_fills.append(std::move(layer_cache_item.layer_extruded->extrusions));
|
||||
}
|
||||
|
||||
// Orca: Generate iron toolpath for contact layer
|
||||
if (!layer_cache.polys_to_iron.empty()) {
|
||||
auto f = std::unique_ptr<Fill>(Fill::new_from_type(support_params.ironing_pattern));
|
||||
f->set_bounding_box(bbox_object);
|
||||
f->layer_id = support_layer.id();
|
||||
f->z = support_layer.print_z;
|
||||
f->overlap = 0;
|
||||
f->angle = layer_cache.ironing_angle;
|
||||
f->spacing = support_params.ironing_spacing;
|
||||
f->link_max_length = (coord_t) scale_(3. * f->spacing);
|
||||
|
||||
ExPolygons polys_to_iron = union_safety_offset_ex(layer_cache.polys_to_iron);
|
||||
layer_cache.polys_to_iron.clear();
|
||||
|
||||
// Find the layer above that directly overlaps current layer, clip the overlapped part
|
||||
if (support_layer_id < support_layers.size() - 1) {
|
||||
const auto& upper_layer = support_layers[support_layer_id + 1];
|
||||
if (!upper_layer->support_islands.empty() && upper_layer->bottom_z() <= support_layer.print_z + EPSILON) {
|
||||
polys_to_iron = diff_ex(polys_to_iron, upper_layer->support_islands);
|
||||
}
|
||||
}
|
||||
|
||||
fill_expolygons_generate_paths(
|
||||
// Destination
|
||||
support_layer.support_fills.entities,
|
||||
// Regions to fill
|
||||
std::move(polys_to_iron),
|
||||
// Filler and its parameters
|
||||
f.get(), 1.f,
|
||||
// Extrusion parameters
|
||||
ExtrusionRole::erIroning, support_params.ironing_flow);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -48,6 +48,11 @@ struct SupportParameters {
|
|||
this->support_material_interface_flow = Slic3r::support_material_interface_flow(&object, float(slicing_params.layer_height));
|
||||
this->raft_interface_flow = support_material_interface_flow;
|
||||
|
||||
this->ironing = object_config.support_ironing;
|
||||
this->ironing_flow = support_material_interface_flow.with_height(support_material_interface_flow.height() * 0.01 * object_config.support_ironing_flow.value);
|
||||
this->ironing_spacing = object_config.support_ironing_spacing;
|
||||
this->ironing_pattern = object_config.support_ironing_pattern;
|
||||
|
||||
// Calculate a minimum support layer height as a minimum over all extruders, but not smaller than 10um.
|
||||
this->support_layer_height_min = scaled<coord_t>(0.01);
|
||||
for (auto lh : print_config.min_layer_height.values)
|
||||
|
@ -90,9 +95,11 @@ struct SupportParameters {
|
|||
|
||||
this->base_angle = Geometry::deg2rad(float(object_config.support_angle.value));
|
||||
this->interface_angle = Geometry::deg2rad(float(object_config.support_angle.value + 90.));
|
||||
this->interface_spacing = object_config.support_interface_spacing.value + this->support_material_interface_flow.spacing();
|
||||
// Orca: Force solid support interface when using support ironing
|
||||
this->interface_spacing = (this->ironing ? 0 : object_config.support_interface_spacing.value) + this->support_material_interface_flow.spacing();
|
||||
this->interface_density = std::min(1., this->support_material_interface_flow.spacing() / this->interface_spacing);
|
||||
double raft_interface_spacing = object_config.support_interface_spacing.value + this->raft_interface_flow.spacing();
|
||||
// Orca: Force solid support interface when using support ironing
|
||||
double raft_interface_spacing = (this->ironing ? 0 : object_config.support_interface_spacing.value) + this->raft_interface_flow.spacing();
|
||||
this->raft_interface_density = std::min(1., this->raft_interface_flow.spacing() / raft_interface_spacing);
|
||||
this->support_spacing = object_config.support_base_pattern_spacing.value + this->support_material_flow.spacing();
|
||||
this->support_density = std::min(1., this->support_material_flow.spacing() / this->support_spacing);
|
||||
|
@ -260,6 +267,11 @@ struct SupportParameters {
|
|||
|
||||
bool independent_layer_height = false;
|
||||
const double thresh_big_overhang = Slic3r::sqr(scale_(10));
|
||||
|
||||
bool ironing;
|
||||
Flow ironing_flow; // Flow at the interface ironing.
|
||||
InfillPattern ironing_pattern;
|
||||
float ironing_spacing;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -224,6 +224,17 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
|||
apply(config, &new_conf);
|
||||
is_msg_dlg_already_exist = false;
|
||||
}
|
||||
if (config->opt_float("support_ironing_spacing") < 0.05)
|
||||
{
|
||||
const wxString msg_text = _(L("Too small ironing spacing.\nReset to 0.1"));
|
||||
MessageDialog dialog(nullptr, msg_text, "", wxICON_WARNING | wxOK);
|
||||
DynamicPrintConfig new_conf = *config;
|
||||
is_msg_dlg_already_exist = true;
|
||||
dialog.ShowModal();
|
||||
new_conf.set_key_value("support_ironing_spacing", new ConfigOptionFloat(0.1));
|
||||
apply(config, &new_conf);
|
||||
is_msg_dlg_already_exist = false;
|
||||
}
|
||||
|
||||
if (config->option<ConfigOptionFloat>("initial_layer_print_height")->value < EPSILON)
|
||||
{
|
||||
|
@ -634,10 +645,18 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
toggle_line("bridge_no_support", !support_is_normal_tree);
|
||||
toggle_line("support_critical_regions_only", is_auto(support_type) && support_is_tree);
|
||||
|
||||
for (auto el : { "support_interface_spacing", "support_interface_filament",
|
||||
for (auto el : { "support_interface_filament",
|
||||
"support_interface_loop_pattern", "support_bottom_interface_spacing" })
|
||||
toggle_field(el, have_support_material && have_support_interface);
|
||||
|
||||
bool can_ironing_support = have_raft || (have_support_material && config->opt_int("support_interface_top_layers") > 0);
|
||||
toggle_field("support_ironing", can_ironing_support);
|
||||
bool has_support_ironing = can_ironing_support && config->opt_bool("support_ironing");
|
||||
for (auto el : {"support_ironing_pattern", "support_ironing_flow", "support_ironing_spacing" })
|
||||
toggle_line(el, has_support_ironing);
|
||||
// Orca: Force solid support interface when using support ironing
|
||||
toggle_field("support_interface_spacing", have_support_material && have_support_interface && !has_support_ironing);
|
||||
|
||||
bool have_skirt_height = have_skirt &&
|
||||
(config->opt_int("skirt_height") > 1 || config->opt_enum<DraftShield>("draft_shield") != dsEnabled);
|
||||
toggle_line("support_speed", have_support_material || have_skirt_height);
|
||||
|
@ -656,8 +675,10 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
|||
toggle_field(el, have_support_material && !(support_is_normal_tree && !have_raft));
|
||||
|
||||
bool has_ironing = (config->opt_enum<IroningType>("ironing_type") != IroningType::NoIroning);
|
||||
for (auto el : { "ironing_pattern", "ironing_flow", "ironing_spacing", "ironing_speed", "ironing_angle", "ironing_inset"})
|
||||
for (auto el : { "ironing_pattern", "ironing_flow", "ironing_spacing", "ironing_angle", "ironing_inset"})
|
||||
toggle_line(el, has_ironing);
|
||||
|
||||
toggle_line("ironing_speed", has_ironing || has_support_ironing);
|
||||
|
||||
bool have_sequential_printing = (config->opt_enum<PrintSequence>("print_sequence") == PrintSequence::ByObject);
|
||||
// for (auto el : { "extruder_clearance_radius", "extruder_clearance_height_to_rod", "extruder_clearance_height_to_lid" })
|
||||
|
|
|
@ -2090,7 +2090,6 @@ void TabPrint::build()
|
|||
optgroup = page->new_optgroup(L("Ironing"), L"param_ironing");
|
||||
optgroup->append_single_option_line("ironing_type", "parameter/ironing");
|
||||
optgroup->append_single_option_line("ironing_pattern");
|
||||
optgroup->append_single_option_line("ironing_speed");
|
||||
optgroup->append_single_option_line("ironing_flow");
|
||||
optgroup->append_single_option_line("ironing_spacing");
|
||||
optgroup->append_single_option_line("ironing_inset");
|
||||
|
@ -2203,6 +2202,7 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("internal_solid_infill_speed");
|
||||
optgroup->append_single_option_line("top_surface_speed");
|
||||
optgroup->append_single_option_line("gap_infill_speed");
|
||||
optgroup->append_single_option_line("ironing_speed");
|
||||
optgroup->append_single_option_line("support_speed");
|
||||
optgroup->append_single_option_line("support_interface_speed");
|
||||
optgroup = page->new_optgroup(L("Overhang speed"), L"param_overhang_speed", 15);
|
||||
|
@ -2278,6 +2278,12 @@ void TabPrint::build()
|
|||
optgroup->append_single_option_line("support_interface_filament", "support#support-filament");
|
||||
optgroup->append_single_option_line("support_interface_not_for_body", "support#support-filament");
|
||||
|
||||
optgroup = page->new_optgroup(L("Support ironing"), L"param_ironing");
|
||||
optgroup->append_single_option_line("support_ironing");
|
||||
optgroup->append_single_option_line("support_ironing_pattern");
|
||||
optgroup->append_single_option_line("support_ironing_flow");
|
||||
optgroup->append_single_option_line("support_ironing_spacing");
|
||||
|
||||
//optgroup = page->new_optgroup(L("Options for support material and raft"));
|
||||
|
||||
// Support
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue