diff --git a/src/libslic3r/Arachne/WallToolPaths.cpp b/src/libslic3r/Arachne/WallToolPaths.cpp index d875b04486..0a59619560 100644 --- a/src/libslic3r/Arachne/WallToolPaths.cpp +++ b/src/libslic3r/Arachne/WallToolPaths.cpp @@ -54,6 +54,12 @@ WallToolPathsParams make_paths_params(const int layer_id, const PrintObjectConfi input_params.wall_distribution_count = print_object_config.wall_distribution_count.value; input_params.is_top_or_bottom_layer = false; // Set to default value + + if (const auto& wall_maximum_resolution_opt = print_object_config.wall_maximum_resolution) + input_params.wall_maximum_resolution = scaled(wall_maximum_resolution_opt.value); + + if (const auto& wall_maximum_deviation_opt = print_object_config.wall_maximum_deviation) + input_params.wall_maximum_deviation = scaled(wall_maximum_deviation_opt.value); } return input_params; @@ -125,7 +131,11 @@ void simplify(Polygon &thiss, const int64_t smallest_line_segment_squared, const accumulated_area_removed += removed_area_next; const int64_t length2 = (current - previous).cast().squaredNorm(); - if (length2 < scaled(25.)) { + + // Orca: + // Checking if the segment's length is smaller than 5 microns (0.005mm). + // The value of `length2` is scaled and squared, so we need to compare it with the squared value of 5 microns + if (length2 < Slic3r::sqr(scaled(0.005))) { // We're allowed to always delete segments of less than 5 micron. continue; } @@ -143,6 +153,7 @@ void simplify(Polygon &thiss, const int64_t smallest_line_segment_squared, const //h^2 = (L / b)^2 [square it] //h^2 = L^2 / b^2 [factor the divisor] const int64_t height_2 = double(area_removed_so_far) * double(area_removed_so_far) / double(base_length_2); + // Orca: The value of `height_2` is squared, so we need to compare it with the squared value if ((height_2 <= Slic3r::sqr(scaled(0.005)) //Almost exactly colinear (barring rounding errors). && Line::distance_to_infinite(current, previous, next) <= scaled(0.005))) // make sure that height_2 is not small because of cancellation of positive and negative areas continue; @@ -473,8 +484,8 @@ const std::vector &WallToolPaths::generate() if (this->inset_count < 1) return toolpaths; - const coord_t smallest_segment = Slic3r::Arachne::meshfix_maximum_resolution(); - const coord_t allowed_distance = Slic3r::Arachne::meshfix_maximum_deviation(); + const coord_t smallest_segment = m_params.wall_maximum_resolution; + const coord_t allowed_distance = m_params.wall_maximum_deviation; const coord_t epsilon_offset = (allowed_distance / 2) - 1; const double transitioning_angle = Geometry::deg2rad(m_params.wall_transition_angle); const coord_t discretization_step_size = scaled(0.8); @@ -547,7 +558,7 @@ const std::vector &WallToolPaths::generate() separateOutInnerContour(); - simplifyToolPaths(toolpaths); + simplifyToolPaths(toolpaths, m_params); removeEmptyToolPaths(toolpaths); assert(std::is_sorted(toolpaths.cbegin(), toolpaths.cend(), @@ -688,16 +699,21 @@ void WallToolPaths::removeSmallLines(std::vector &toolpaths) } } -void WallToolPaths::simplifyToolPaths(std::vector &toolpaths) +void WallToolPaths::simplifyToolPaths(std::vector& toolpaths, const WallToolPathsParams& params) { - for (size_t toolpaths_idx = 0; toolpaths_idx < toolpaths.size(); ++toolpaths_idx) + const int64_t maximum_resolution = params.wall_maximum_resolution; + const int64_t maximum_deviation = params.wall_maximum_deviation; + + const int64_t smallest_line_segment_squared = maximum_resolution * maximum_resolution; + const int64_t allowed_error_distance_squared = maximum_deviation * maximum_deviation; + + const int64_t maximum_extrusion_area_deviation = Slic3r::Arachne::meshfix_maximum_extrusion_area_deviation(); // unit: μm² + + for (VariableWidthLines& lines : toolpaths) { - const int64_t maximum_resolution = Slic3r::Arachne::meshfix_maximum_resolution(); - const int64_t maximum_deviation = Slic3r::Arachne::meshfix_maximum_deviation(); - const int64_t maximum_extrusion_area_deviation = Slic3r::Arachne::meshfix_maximum_extrusion_area_deviation(); // unit: μm² - for (auto& line : toolpaths[toolpaths_idx]) + for (ExtrusionLine& line : lines) { - line.simplify(maximum_resolution * maximum_resolution, maximum_deviation * maximum_deviation, maximum_extrusion_area_deviation); + line.simplify(smallest_line_segment_squared, allowed_error_distance_squared, maximum_extrusion_area_deviation); } } } diff --git a/src/libslic3r/Arachne/WallToolPaths.hpp b/src/libslic3r/Arachne/WallToolPaths.hpp index 457f7e7149..dde3dc785f 100644 --- a/src/libslic3r/Arachne/WallToolPaths.hpp +++ b/src/libslic3r/Arachne/WallToolPaths.hpp @@ -15,7 +15,7 @@ namespace Slic3r::Arachne { -constexpr bool fill_outline_gaps = true; +constexpr bool fill_outline_gaps = true; inline coord_t meshfix_maximum_resolution() { return scaled(0.5); } inline coord_t meshfix_maximum_deviation() { return scaled(0.025); } inline coord_t meshfix_maximum_extrusion_area_deviation() { return scaled(2.); } @@ -31,6 +31,9 @@ public: float wall_transition_filter_deviation; int wall_distribution_count; bool is_top_or_bottom_layer; + + coord_t wall_maximum_resolution = meshfix_maximum_resolution(); + coord_t wall_maximum_deviation = meshfix_maximum_deviation(); }; WallToolPathsParams make_paths_params(const int layer_id, const PrintObjectConfig &print_object_config, const PrintConfig &print_config); @@ -116,10 +119,11 @@ protected: /*! * Simplifies the variable-width toolpaths by calling the simplify on every line in the toolpath using the provided * settings. - * \param settings The settings as provided by the user + * \param toolpaths The toolpaths vector to simplify + * \param params The settings as provided by the user * \return */ - static void simplifyToolPaths(std::vector &toolpaths); + static void simplifyToolPaths(std::vector& toolpaths, const WallToolPathsParams& params); private: const Polygons& outline; //().squaredNorm(); - if (length2 < scaled(0.025)) + + // Orca: + // Checking if the segment's length is smaller than 5 microns (0.005mm). + // The value of `length2` is scaled and squared, so we need to compare it with the squared value of 5 microns + if (length2 < Slic3r::sqr(scaled(0.005))) { // We're allowed to always delete segments of less than 5 micron. The width in this case doesn't matter that much. continue; @@ -128,8 +132,9 @@ void ExtrusionLine::simplify(const int64_t smallest_line_segment_squared, const //h^2 = L^2 / b^2 [factor the divisor] const auto height_2 = int64_t(double(area_removed_so_far) * double(area_removed_so_far) / double(base_length_2)); const int64_t extrusion_area_error = calculateExtrusionAreaDeviationError(previous, current, next); - if ((height_2 <= scaled(0.001) //Almost exactly colinear (barring rounding errors). - && Line::distance_to_infinite(current.p, previous.p, next.p) <= scaled(0.001)) // Make sure that height_2 is not small because of cancellation of positive and negative areas + // Orca: The value of `height_2` is squared, so we need to compare it with the squared value + if ((height_2 <= Slic3r::sqr(scaled(0.005)) // Almost exactly colinear (barring rounding errors). + && Line::distance_to_infinite(current.p, previous.p, next.p) <= scaled(0.005)) // Make sure that height_2 is not small because of cancellation of positive and negative areas // We shouldn't remove middle junctions of colinear segments if the area changed for the C-P segment is exceeding the maximum allowed && extrusion_area_error <= maximum_extrusion_area_deviation) { diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 82fe8679a2..401480e96a 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -934,8 +934,9 @@ static std::vector s_Preset_print_options { "support_bottom_interface_spacing", "enable_overhang_speed", "slowdown_for_curled_perimeters", "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", "overhang_4_4_speed", "initial_layer_infill_speed", "only_one_wall_top", "timelapse_type", - "wall_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", - "wall_distribution_count", "min_feature_size", "min_bead_width", "post_process", "process_change_extrusion_role_gcode", "min_length_factor", + "wall_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", + "wall_distribution_count", "min_feature_size", "min_bead_width", "post_process", "process_change_extrusion_role_gcode", + "min_length_factor", "wall_maximum_resolution", "wall_maximum_deviation", "small_perimeter_speed", "small_perimeter_threshold","bridge_angle","internal_bridge_angle", "filter_out_gap_fill", "travel_acceleration","inner_wall_acceleration", "min_width_top_surface", "default_jerk", "outer_wall_jerk", "inner_wall_jerk", "infill_jerk", "top_surface_jerk", "initial_layer_jerk","travel_jerk","default_junction_deviation", "top_solid_infill_flow_ratio","bottom_solid_infill_flow_ratio","only_one_wall_first_layer", "print_flow_ratio", "seam_gap", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index ab080795b0..508e7c805f 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2595,7 +2595,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Number of cooling moves"); def->tooltip = L("Filament is cooled by being moved back and forth in the " "cooling tubes. Specify desired number of these moves."); - def->max = 0; + def->min = 0; def->max = 20; def->mode = comAdvanced; def->set_default_value(new ConfigOptionInts { 4 }); @@ -6797,6 +6797,29 @@ void PrintConfigDef::init_fff_params() def->max = 25.0; def->set_default_value(new ConfigOptionFloat(0.5)); + def = this->add("wall_maximum_resolution", coFloat); + def->label = L("Maximum wall resolution"); + def->category = L("Quality"); + def->tooltip = L("This value determines the smallest wall line segment length in mm. " + "The smaller you set this value, the more accurate and precise the walls will be."); + def->sidetext = L("mm"); // millimeters, CIS languages need translation + def->mode = comExpert; + def->min = 0.005; + def->max = 0.5f; + def->set_default_value(new ConfigOptionFloat(0.5f)); + + def = this->add("wall_maximum_deviation", coFloat); + def->label = L("Maximum wall deviation"); + def->category = L("Quality"); + def->tooltip = L("The maximum deviation allowed when reducing the resolution for the 'Maximum wall resolution' setting. If you increase this, " + "the print will be less accurate, but the G-Code will be smaller. 'Maximum wall deviation' limits 'Maximum wall resolution', " + "so if the two conflict, 'Maximum wall deviation' takes precedence."); + def->sidetext = L("mm"); // millimeters, CIS languages need translation + def->mode = comExpert; + def->min = 0.005f; + def->max = 0.05f; + def->set_default_value(new ConfigOptionFloat(0.025f)); + def = this->add("initial_layer_min_bead_width", coPercent); def->label = L("First layer minimum wall width"); def->category = L("Quality"); diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 6eebb5f5b7..af483f1c9e 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -997,6 +997,8 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionPercent, min_bead_width)) // Orca + ((ConfigOptionFloat, wall_maximum_resolution)) + ((ConfigOptionFloat, wall_maximum_deviation)) ((ConfigOptionFloat, make_overhang_printable_angle)) ((ConfigOptionFloat, make_overhang_printable_hole_size)) ((ConfigOptionFloat, tree_support_branch_distance_organic)) diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index 76d9312245..a08a7d74b0 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -1290,6 +1290,8 @@ bool PrintObject::invalidate_state_by_config_options( || opt_key == "wall_transition_filter_deviation" || opt_key == "wall_transition_angle" || opt_key == "wall_distribution_count" + || opt_key == "wall_maximum_resolution" + || opt_key == "wall_maximum_deviation" || opt_key == "min_feature_size" || opt_key == "min_length_factor" || opt_key == "min_bead_width") { diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index ef4c01440f..0a67c841ec 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -882,8 +882,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co toggle_line("fuzzy_skin_persistence", (fuzzy_skin_noise_type == NoiseType::Perlin || fuzzy_skin_noise_type == NoiseType::Billow) && has_fuzzy_skin); bool have_arachne = config->opt_enum("wall_generator") == PerimeterGeneratorType::Arachne; - for (auto el : {"wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", - "min_feature_size", "min_length_factor", "min_bead_width", "wall_distribution_count", "initial_layer_min_bead_width"}) + for (auto el : {"wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle", "min_feature_size", "min_length_factor", + "min_bead_width", "wall_distribution_count", "initial_layer_min_bead_width", "wall_maximum_resolution", "wall_maximum_deviation"}) toggle_line(el, have_arachne); toggle_field("detect_thin_wall", !have_arachne); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index c62bbcdf95..8296c668c7 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -2315,6 +2315,8 @@ void TabPrint::build() optgroup->append_single_option_line("min_bead_width", "quality_settings_wall_generator#arachne"); optgroup->append_single_option_line("min_feature_size", "quality_settings_wall_generator#arachne"); optgroup->append_single_option_line("min_length_factor", "quality_settings_wall_generator#arachne"); + optgroup->append_single_option_line("wall_maximum_resolution", "quality_settings_wall_generator#arachne"); + optgroup->append_single_option_line("wall_maximum_deviation", "quality_settings_wall_generator#arachne"); optgroup = page->new_optgroup(L("Walls and surfaces"), L"param_wall_surface"); optgroup->append_single_option_line("wall_sequence", "quality_settings_wall_and_surfaces#walls-printing-order");