diff --git a/doc/print_settings/quality/quality_settings_ironing.md b/doc/print_settings/quality/quality_settings_ironing.md index c764a9124c..c9b46b3889 100644 --- a/doc/print_settings/quality/quality_settings_ironing.md +++ b/doc/print_settings/quality/quality_settings_ironing.md @@ -52,7 +52,17 @@ If this value is set to 0, the ironing toolpath will start directly at the perim ## Angle Offset -The angle of ironing lines offset relative to the top surface solid infill direction. Commonly used ironing angle offsets are 0°, 45°, and 90° each producing a [different surface finish](https://github.com/SoftFever/OrcaSlicer/issues/10834#issuecomment-3322628589) which will depend on your printer nozzle. +The angle of ironing lines offset relative to the top surface solid infill direction. + +Commonly used ironing angle offsets are 0°, 45°, and 90° each producing a [different surface finish](https://github.com/SoftFever/OrcaSlicer/issues/10834#issuecomment-3322628589) which will depend on your printer nozzle. + +## Fixed Angle + +Use a fixed absolute angle for ironing that is not offset from the top surface infill direction. This results in an ironing finish that does not have alternating line directions and may result in a more uniform surface finish and reduced tiger striping effect when reflecting light. + +Set the Ironing Angle Offset to an angle with optimal ironing angle offsets from all affected top surface solid infill directions. + +Suggested fixed ironing angles are 0° and 90° if you are using the default solid infill direction of 45°. ## Speed diff --git a/src/libslic3r/Fill/Fill.cpp b/src/libslic3r/Fill/Fill.cpp index 1be8e8997a..4e5904e88a 100644 --- a/src/libslic3r/Fill/Fill.cpp +++ b/src/libslic3r/Fill/Fill.cpp @@ -227,8 +227,8 @@ struct SurfaceFillParams coordf_t overlap = 0.; // Angle as provided by the region config, in radians. float angle = 0.f; - // Orca: is_using_template_angle - bool is_using_template_angle = false; + // Orca: fixed_angle + bool fixed_angle = false; // Is bridging used for this fill? Bridging parameters may be used even if this->flow.bridge() is not set. bool bridge; // Non-negative for a bridge. @@ -284,7 +284,7 @@ struct SurfaceFillParams RETURN_COMPARE_NON_EQUAL(spacing); RETURN_COMPARE_NON_EQUAL(overlap); RETURN_COMPARE_NON_EQUAL(angle); - RETURN_COMPARE_NON_EQUAL(is_using_template_angle); + RETURN_COMPARE_NON_EQUAL(fixed_angle); RETURN_COMPARE_NON_EQUAL(density); RETURN_COMPARE_NON_EQUAL(multiline); // RETURN_COMPARE_NON_EQUAL_TYPED(unsigned, dont_adjust); @@ -313,7 +313,7 @@ struct SurfaceFillParams this->spacing == rhs.spacing && this->overlap == rhs.overlap && this->angle == rhs.angle && - this->is_using_template_angle == rhs.is_using_template_angle && + this->fixed_angle == rhs.fixed_angle && this->bridge == rhs.bridge && this->bridge_angle == rhs.bridge_angle && this->density == rhs.density && @@ -902,11 +902,11 @@ std::vector group_fills(const Layer &layer, LockRegionParam &lock_p if (params.extrusion_role == erInternalInfill) { params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.infill_direction.value, region_config.sparse_infill_rotate_template.value); - params.is_using_template_angle = !region_config.sparse_infill_rotate_template.value.empty(); + params.fixed_angle = !region_config.sparse_infill_rotate_template.value.empty(); } else { params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.solid_infill_direction.value, region_config.solid_infill_rotate_template.value); - params.is_using_template_angle = !region_config.solid_infill_rotate_template.value.empty(); + params.fixed_angle = !region_config.solid_infill_rotate_template.value.empty(); } params.bridge_angle = float(surface.bridge_angle); @@ -1094,7 +1094,7 @@ std::vector group_fills(const Layer &layer, LockRegionParam &lock_p const PrintRegionConfig ®ion_config = layerm.region().config(); params.angle = calculate_infill_rotation_angle(layer.object(), layer.id(), region_config.solid_infill_direction.value, region_config.solid_infill_rotate_template.value); - params.is_using_template_angle = !region_config.solid_infill_rotate_template.value.empty(); + params.fixed_angle = !region_config.solid_infill_rotate_template.value.empty(); // calculate the actual flow we'll be using for this infill params.flow = layerm.flow(frSolidInfill); @@ -1199,7 +1199,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive: f->layer_id = this->id(); f->z = this->print_z; f->angle = surface_fill.params.angle; - f->is_using_template_angle = surface_fill.params.is_using_template_angle; + f->fixed_angle = surface_fill.params.fixed_angle; f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree; f->print_config = &this->object()->print()->config(); f->print_object_config = &this->object()->config(); @@ -1389,7 +1389,7 @@ Polylines Layer::generate_sparse_infill_polylines_for_anchoring(FillAdaptive::Oc f->layer_id = this->id() - this->object()->get_layer(0)->id(); // We need to subtract raft layers. f->z = this->print_z; f->angle = surface_fill.params.angle; - f->is_using_template_angle = surface_fill.params.is_using_template_angle; + f->fixed_angle = surface_fill.params.fixed_angle; f->adapt_fill_octree = (surface_fill.params.pattern == ipSupportCubic) ? support_fill_octree : adaptive_fill_octree; f->print_config = &this->object()->print()->config(); f->print_object_config = &this->object()->config(); @@ -1462,7 +1462,7 @@ void Layer::make_ironing() double height; double speed; double angle; - bool is_using_template_angle; + bool fixed_angle; double inset; bool operator<(const IroningParams &rhs) const { @@ -1472,7 +1472,7 @@ void Layer::make_ironing() RETURN_COMPARE_NON_EQUAL(height); RETURN_COMPARE_NON_EQUAL(speed); RETURN_COMPARE_NON_EQUAL(angle); - RETURN_COMPARE_NON_EQUAL(is_using_template_angle); + RETURN_COMPARE_NON_EQUAL(fixed_angle); RETURN_COMPARE_NON_EQUAL(inset); return false; } @@ -1484,7 +1484,7 @@ void Layer::make_ironing() this->height == rhs.height && this->speed == rhs.speed && this->angle == rhs.angle && - this->is_using_template_angle == rhs.is_using_template_angle && + this->fixed_angle == rhs.fixed_angle && this->pattern == rhs.pattern && this->inset == rhs.inset; } @@ -1533,8 +1533,8 @@ void Layer::make_ironing() ironing_params.inset = config.ironing_inset; ironing_params.height = default_layer_height * 0.01 * config.ironing_flow; ironing_params.speed = config.ironing_speed; - ironing_params.angle = calculate_infill_rotation_angle(this->object(), this->id(), config.solid_infill_direction.value, config.solid_infill_rotate_template.value) + config.ironing_angle * M_PI / 180.; - ironing_params.is_using_template_angle = !config.solid_infill_rotate_template.value.empty(); + ironing_params.angle = (config.ironing_angle_fixed ? 0 : calculate_infill_rotation_angle(this->object(), this->id(), config.solid_infill_direction.value, config.solid_infill_rotate_template.value)) + config.ironing_angle * M_PI / 180.; + ironing_params.fixed_angle = config.ironing_angle_fixed || !config.solid_infill_rotate_template.value.empty(); ironing_params.pattern = config.ironing_pattern; ironing_params.layerm = layerm; by_extruder.emplace_back(ironing_params); @@ -1630,7 +1630,7 @@ void Layer::make_ironing() // Create the filler object. f->spacing = ironing_params.line_spacing; f->angle = float(ironing_params.angle); - f->is_using_template_angle = ironing_params.is_using_template_angle; + f->fixed_angle = ironing_params.fixed_angle; f->link_max_length = (coord_t) scale_(3. * f->spacing); double extrusion_height = ironing_params.height * f->spacing / nozzle_dmr; float extrusion_width = Flow::rounded_rectangle_extrusion_width_from_spacing(float(nozzle_dmr), float(extrusion_height)); diff --git a/src/libslic3r/Fill/FillBase.cpp b/src/libslic3r/Fill/FillBase.cpp index 1549fd0e8d..3a9412119f 100644 --- a/src/libslic3r/Fill/FillBase.cpp +++ b/src/libslic3r/Fill/FillBase.cpp @@ -304,11 +304,10 @@ std::pair Fill::_infill_direction(const Surface *surface) const printf("Filling bridge with angle %f\n", surface->bridge_angle); #endif /* SLIC3R_DEBUG */ out_angle = float(surface->bridge_angle); - } else if (this->layer_id != size_t(-1)) { + } else if (this->layer_id != size_t(-1) && !fixed_angle) { // alternate fill direction - //Orca: if template angle is not empty, don't apply layer angle - if(!is_using_template_angle) - out_angle += this->_layer_angle(this->layer_id / surface->thickness_layers); + //Orca: Do not alternate direction if Fill.fixed_angle is true + out_angle += this->_layer_angle(this->layer_id / surface->thickness_layers); } else { // printf("Layer_ID undefined!\n"); } diff --git a/src/libslic3r/Fill/FillBase.hpp b/src/libslic3r/Fill/FillBase.hpp index 5e1b6d5445..010dff8a08 100644 --- a/src/libslic3r/Fill/FillBase.hpp +++ b/src/libslic3r/Fill/FillBase.hpp @@ -119,8 +119,9 @@ public: coordf_t overlap; // in radians, ccw, 0 = East float angle; - // Orca: is_using_template_angle - bool is_using_template_angle{false}; + + // Orca: Fill direction is fixed absolute angle if SurfaceFillParams.fixed_angle or config.ironing_angle_fixed + bool fixed_angle{false}; // In scaled coordinates. Maximum lenght of a perimeter segment connecting two infill lines. // Used by the FillRectilinear2, FillGrid2, FillTriangles, FillStars and FillCubic. // If left to zero, the links will not be limited. @@ -203,7 +204,7 @@ protected: ExPolygon expolygon, ThickPolylines& thick_polylines_out) {} - virtual float _layer_angle(size_t idx) const { return is_using_template_angle ? 0.f : (idx & 1) ? float(M_PI/2.) : 0.f; } + virtual float _layer_angle(size_t idx) const { return fixed_angle ? 0.f : (idx & 1) ? float(M_PI/2.) : 0.f; } virtual std::pair _infill_direction(const Surface *surface) const; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index d1025a3f5d..08dc5de794 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -888,7 +888,7 @@ static std::vector s_Preset_print_options { "infill_direction", "solid_infill_direction", "counterbore_hole_bridging","infill_shift_step", "sparse_infill_rotate_template", "solid_infill_rotate_template", "symmetric_infill_y_axis","skeleton_infill_density", "infill_lock_depth", "skin_infill_depth", "skin_infill_density", "align_infill_direction_to_model", "extra_solid_infills", "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", + "ironing_type", "ironing_pattern", "ironing_flow", "ironing_speed", "ironing_spacing", "ironing_angle", "ironing_angle_fixed", "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_mode", "fuzzy_skin_scale", "fuzzy_skin_octaves", "fuzzy_skin_persistence", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 3ef21ee41f..986c790775 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3887,6 +3887,13 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionFloat(0)); + def = this->add("ironing_angle_fixed", coBool); + def->label = L("Fixed ironing angle"); + def->category = L("Quality"); + def->tooltip = L("Use a fixed absolute angle for ironing."); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + def = this->add("layer_change_gcode", coString); def->label = L("Layer change G-code"); def->tooltip = L("This G-code is inserted at every layer change after the Z lift."); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 807ce56b36..a36cc21c51 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1084,6 +1084,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, ironing_direction)) ((ConfigOptionFloat, ironing_speed)) ((ConfigOptionFloat, ironing_angle)) + ((ConfigOptionBool, ironing_angle_fixed)) // Detect bridging perimeters ((ConfigOptionBool, detect_overhang_wall)) ((ConfigOptionInt, wall_filament)) diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 33d7ccba2f..a53051b6dd 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2339,6 +2339,7 @@ void TabPrint::build() optgroup->append_single_option_line("ironing_spacing", "quality_settings_ironing#line-spacing"); optgroup->append_single_option_line("ironing_inset", "quality_settings_ironing#inset"); optgroup->append_single_option_line("ironing_angle", "quality_settings_ironing#angle-offset"); + optgroup->append_single_option_line("ironing_angle_fixed", "quality_settings_ironing#fixed-angle"); optgroup = page->new_optgroup(L("Wall generator"), L"param_wall_generator"); optgroup->append_single_option_line("wall_generator", "quality_settings_wall_generator");