From 43d0d22532f1067722282e6368a9a56be0098e88 Mon Sep 17 00:00:00 2001 From: remi durand Date: Sun, 2 May 2021 15:52:11 +0200 Subject: [PATCH] add hole_to_polyhole_threshold to allow user-defined margin supermerill/SuperSlicer#924 --- resources/ui_layout/print.ui | 5 +++- src/libslic3r/Preset.cpp | 1 + src/libslic3r/PrintConfig.cpp | 13 ++++++++++ src/libslic3r/PrintConfig.hpp | 2 ++ src/libslic3r/PrintObject.cpp | 37 ++++++++++++--------------- src/libslic3r/PrintRegion.cpp | 6 ++--- src/slic3r/GUI/ConfigManipulation.cpp | 2 ++ 7 files changed, 41 insertions(+), 25 deletions(-) diff --git a/resources/ui_layout/print.ui b/resources/ui_layout/print.ui index 784d2d6d0..cd1fab071 100644 --- a/resources/ui_layout/print.ui +++ b/resources/ui_layout/print.ui @@ -94,10 +94,13 @@ group:Modifying slices setting:width$6:first_layer_size_compensation end_line line:Vertical Hole shrinking compensation - setting:hole_to_polyhole setting:width$6:hole_size_compensation setting:width$6:hole_size_threshold end_line + line:Convert round vertical holes to polyholes + setting:label$:hole_to_polyhole + setting:hole_to_polyhole_threshold + end_line group:Other setting:clip_multipart_objects setting:allow_empty_layers diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index e3a4fbca8..aa392ad80 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -565,6 +565,7 @@ const std::vector& Preset::print_options() "hole_size_compensation", "hole_size_threshold", "hole_to_polyhole", + "hole_to_polyhole_threshold", "threads", "resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_bridging", "wipe_tower_brim", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index aa95da2ad..b999f4876 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -4270,6 +4270,18 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(false)); + def = this->add("hole_to_polyhole_threshold", coFloatOrPercent); + def->label = L("Roundness margin"); + def->full_label = L("Polyhole detection margin"); + def->category = OptionCategory::slicing; + def->tooltip = L("Maximum defection of a point to the estimated radius of the circle." + "\nAs cylinder are often exported as triangles of varying size, point may not be on the circle circumference." + " This setting allow you some leway to browden the detection." + "\nIn mm or in % of the radius."); + def->sidetext = L("mm²"); + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloatOrPercent(0.01, false)); + def = this->add("z_offset", coFloat); def->label = L("Z offset"); def->category = OptionCategory::general; @@ -5406,6 +5418,7 @@ void PrintConfigDef::to_prusa(t_config_option_key& opt_key, std::string& value, "hole_size_compensation", "hole_size_threshold", "hole_to_polyhole", +"hole_to_polyhole_threshold", "z_step", "milling_cutter", "milling_diameter", diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 2c8c0b298..4d268002f 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -776,6 +776,7 @@ public: ConfigOptionFloatOrPercent infill_anchor; ConfigOptionFloatOrPercent infill_anchor_max; ConfigOptionBool hole_to_polyhole; + ConfigOptionFloatOrPercent hole_to_polyhole_threshold; ConfigOptionInt infill_extruder; ConfigOptionFloatOrPercent infill_extrusion_width; ConfigOptionInt infill_every_layers; @@ -888,6 +889,7 @@ protected: OPT_PTR(infill_anchor); OPT_PTR(infill_anchor_max); OPT_PTR(hole_to_polyhole); + OPT_PTR(hole_to_polyhole_threshold); OPT_PTR(infill_extruder); OPT_PTR(infill_extrusion_width); OPT_PTR(infill_every_layers); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index a852fc77f..69c80eac8 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -169,7 +169,7 @@ namespace Slic3r { { // get all circular holes for each layer // the id is center-diameter-extruderid - std::vector, Polygon*>>> layerid2center; + std::vector, Polygon*>>> layerid2center; for (size_t i = 0; i < this->m_layers.size(); i++) layerid2center.emplace_back(); tbb::parallel_for( tbb::blocked_range(0, m_layers.size()), @@ -185,27 +185,20 @@ namespace Slic3r { //test if convex (as it's clockwise bc it's a hole, we have to do the opposite) if (hole.convex_points().empty() && hole.points.size() > 8) { // Computing circle center - double center_x = 0, center_y = 0; - double lines_length = 0; - for (Line l : hole.lines()) { - center_x += l.a.x() * l.length(); - center_x += l.b.x() * l.length(); - center_y += l.a.y() * l.length(); - center_y += l.b.y() * l.length(); - lines_length += l.length() + l.length(); - } - Point center{ center_x / lines_length, center_y / lines_length }; - // check for roundeness + Point center = hole.centroid(); double diameter_min = std::numeric_limits::max(), diameter_max = 0; + double diameter_sum = 0; for (int i = 0; i < hole.points.size(); ++i) { double dist = hole.points[i].distance_to(center); diameter_min = std::min(diameter_min, dist); diameter_max = std::max(diameter_max, dist); + diameter_sum += dist; } - // SCALED_EPSILON was a bit too harsh. - if (diameter_max - diameter_min < 1000) { + // SCALED_EPSILON was a bit too harsh. Now using a config, as some may want some harsh setting and some don't. + coord_t max_variation = std::max(SCALED_EPSILON, scale_(this->m_layers[layer_idx]->m_regions[region_idx]->region()->config().hole_to_polyhole_threshold.get_abs_value(unscaled(diameter_sum / hole.points.size())))); + if (diameter_max - diameter_min < max_variation * 2) { layerid2center[layer_idx].emplace_back( - std::tuple{center, diameter_max, layer->m_regions[region_idx]->region()->config().perimeter_extruder.value}, & hole); + std::tuple{center, diameter_max, layer->m_regions[region_idx]->region()->config().perimeter_extruder.value, max_variation}, & hole); } } } @@ -216,7 +209,7 @@ namespace Slic3r { } }); //sort holes per center-diameter - std::map, std::vector>> id2layerz2hole; + std::map, std::vector>> id2layerz2hole; //search & find hole that span at least X layers const size_t min_nb_layers = 2; @@ -224,7 +217,7 @@ namespace Slic3r { for (size_t layer_idx = 0; layer_idx < this->m_layers.size(); ++layer_idx) { for (size_t hole_idx = 0; hole_idx < layerid2center[layer_idx].size(); ++hole_idx) { //get all other same polygons - std::tuple& id = layerid2center[layer_idx][hole_idx].first; + std::tuple& id = layerid2center[layer_idx][hole_idx].first; float max_z = layers()[layer_idx]->print_z; std::vector> holes; holes.emplace_back(layerid2center[layer_idx][hole_idx].second, layer_idx); @@ -232,10 +225,11 @@ namespace Slic3r { if (layers()[search_layer_idx]->print_z - layers()[search_layer_idx]->height - max_z > EPSILON) break; //search an other polygon with same id for (size_t search_hole_idx = 0; search_hole_idx < layerid2center[search_layer_idx].size(); ++search_hole_idx) { - std::tuple& search_id = layerid2center[search_layer_idx][search_hole_idx].first; - if (std::get<0>(id).distance_to(std::get<0>(search_id)) < SCALED_EPSILON - && std::abs(std::get<1>(id) - std::get<1>(search_id)) < SCALED_EPSILON - && std::get<2>(id) == std::get<2>(search_id)) { + std::tuple& search_id = layerid2center[search_layer_idx][search_hole_idx].first; + if (std::get<2>(id) == std::get<2>(search_id) + && std::get<0>(id).distance_to(std::get<0>(search_id)) < std::get<3>(id) + && std::abs(std::get<1>(id) - std::get<1>(search_id)) < std::get<3>(id) + ) { max_z = layers()[search_layer_idx]->print_z; holes.emplace_back(layerid2center[search_layer_idx][search_hole_idx].second, search_layer_idx); layerid2center[search_layer_idx].erase(layerid2center[search_layer_idx].begin() + search_hole_idx); @@ -721,6 +715,7 @@ namespace Slic3r { || opt_key == "hole_size_compensation" || opt_key == "hole_size_threshold" || opt_key == "hole_to_polyhole" + || opt_key == "hole_to_polyhole_threshold" || opt_key == "z_step") { steps.emplace_back(posSlice); } else if (opt_key == "support_material") { diff --git a/src/libslic3r/PrintRegion.cpp b/src/libslic3r/PrintRegion.cpp index e50de2cad..a6010a3aa 100644 --- a/src/libslic3r/PrintRegion.cpp +++ b/src/libslic3r/PrintRegion.cpp @@ -88,9 +88,9 @@ void PrintRegion::collect_object_printing_extruders(std::vector &objec // If not, then there must be something wrong with the Print::apply() function. #ifndef NDEBUG auto num_extruders = (int)print()->config().nozzle_diameter.size(); - assert(this->config().perimeter_extruder <= num_extruders); - assert(this->config().infill_extruder <= num_extruders); - assert(this->config().solid_infill_extruder <= num_extruders); + assert(this->config().perimeter_extruder.value <= num_extruders); + assert(this->config().infill_extruder.value <= num_extruders); + assert(this->config().solid_infill_extruder.value <= num_extruders); #endif for(const PrintObject * obj : this->m_print->objects()) collect_object_printing_extruders(print()->config(), obj->config(), this->config(), object_extruders); diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index a4b2a1480..51f59cc47 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -429,6 +429,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) for (auto el : { "solid_fill_pattern", "infill_connection_solid" }) toggle_field(el, has_solid_infill); // should be top_solid_layers") > 1 || bottom_solid_layers") > 1 + toggle_field("hole_to_polyhole_threshold", config->opt_bool("hole_to_polyhole")); + bool have_default_acceleration = config->option("default_acceleration")->value > 0; for (auto el : { "perimeter_acceleration", "infill_acceleration", "bridge_acceleration", "first_layer_acceleration" })