diff options
author | supermerill <merill@fr.fr> | 2019-01-03 19:42:10 +0300 |
---|---|---|
committer | supermerill <merill@fr.fr> | 2019-01-03 21:57:00 +0300 |
commit | a48e190137b3345a552bd1588c6bb145af55212a (patch) | |
tree | 3d52ee1b6145cb792d80d2f63b40cafd4db194c6 | |
parent | 72d828cf7442fe242891e52bfed1cd47a38a06c9 (diff) |
medial axis: now grows the extrusion to nozzle diameter if it's lower than that. Add a parameter to define the min width (default to 33% of nozzle diameter).
-rw-r--r-- | src/libslic3r/Layer.cpp | 1 | ||||
-rw-r--r-- | src/libslic3r/MedialAxis.cpp | 30 | ||||
-rw-r--r-- | src/libslic3r/MedialAxis.hpp | 11 | ||||
-rw-r--r-- | src/libslic3r/PerimeterGenerator.cpp | 7 | ||||
-rw-r--r-- | src/libslic3r/PrintConfig.cpp | 11 | ||||
-rw-r--r-- | src/libslic3r/PrintConfig.hpp | 2 | ||||
-rw-r--r-- | src/libslic3r/PrintObject.cpp | 1 | ||||
-rw-r--r-- | src/slic3r/GUI/Preset.cpp | 1 | ||||
-rw-r--r-- | src/slic3r/GUI/Tab.cpp | 8 |
9 files changed, 57 insertions, 15 deletions
diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp index c587e81cf..40f3d9988 100644 --- a/src/libslic3r/Layer.cpp +++ b/src/libslic3r/Layer.cpp @@ -110,6 +110,7 @@ void Layer::make_perimeters() && config.overhangs == other_config.overhangs && config.serialize("perimeter_extrusion_width").compare(other_config.serialize("perimeter_extrusion_width")) == 0 && config.thin_walls == other_config.thin_walls + && config.thin_walls_min_width == other_config.thin_walls_min_width && config.external_perimeters_first == other_config.external_perimeters_first && config.perimeter_loop == other_config.perimeter_loop) { layerms.push_back(other_layerm); diff --git a/src/libslic3r/MedialAxis.cpp b/src/libslic3r/MedialAxis.cpp index baad42836..c869ef36a 100644 --- a/src/libslic3r/MedialAxis.cpp +++ b/src/libslic3r/MedialAxis.cpp @@ -578,7 +578,7 @@ MedialAxis::fusion_corners(ThickPolylines &pp) //FIXME: also pull (a bit less) points that are near to this one. // if true, pull it a bit, depends on my size, the dot?, and the coeff at my 0-end (~14% for a square, almost 0 for a gentle curve) coord_t length_pull = polyline.length(); - length_pull *= 0.144 * get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, min(min_width, polyline.length() / 2)); + length_pull *= 0.144 * get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, min(min_width, (coord_t)(polyline.length() / 2))); //compute dir Vec2d pull_direction(polyline.points[1].x() - polyline.points[0].x(), polyline.points[1].y() - polyline.points[0].y()); @@ -801,11 +801,11 @@ MedialAxis::main_fusion(ThickPolylines& pp) //test if we don't merge with something too different and without any relevance. double coeffSizePolyI = 1; if (polyline.width.back() == 0) { - coeffSizePolyI = 0.1 + 0.9*get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, min(min_width, polyline.length() / 2)); + coeffSizePolyI = 0.1 + 0.9*get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, min(min_width, (coord_t)(polyline.length() / 2))); } double coeffSizeOtherJ = 1; if (other.width.back() == 0) { - coeffSizeOtherJ = 0.1 + 0.9*get_coeff_from_angle_countour(other.points.back(), this->expolygon, min(min_width, polyline.length() / 2)); + coeffSizeOtherJ = 0.1 + 0.9*get_coeff_from_angle_countour(other.points.back(), this->expolygon, min(min_width, (coord_t)(polyline.length() / 2))); } //std::cout << " try2 : " << i << ":" << j << " : " // << (abs(polyline.length()*coeffSizePolyI - other.length()*coeffSizeOtherJ) > max_width / 2) @@ -904,10 +904,10 @@ MedialAxis::main_fusion(ThickPolylines& pp) //TODO: try if we can achieve a better result if we use a different algo if the angle is <90° const double coeff_angle_poly = (coeff_angle_cache.find(polyline.points.back()) != coeff_angle_cache.end()) ? coeff_angle_cache[polyline.points.back()] - : (get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, min(min_width, polyline.length() / 2))); + : (get_coeff_from_angle_countour(polyline.points.back(), this->expolygon, min(min_width, (coord_t)(polyline.length() / 2)))); const double coeff_angle_candi = (coeff_angle_cache.find(best_candidate->points.back()) != coeff_angle_cache.end()) ? coeff_angle_cache[best_candidate->points.back()] - : (get_coeff_from_angle_countour(best_candidate->points.back(), this->expolygon, min(min_width, best_candidate->length() / 2))); + : (get_coeff_from_angle_countour(best_candidate->points.back(), this->expolygon, min(min_width, (coord_t)(best_candidate->length() / 2)))); //this will encourage to follow the curve, a little, because it's shorter near the center //without that, it tends to go to the outter rim. @@ -1488,11 +1488,31 @@ MedialAxis::build(ThickPolylines* polylines_out) // svg.draw(pp); // svg.Close(); //} + if (nozzle_diameter != min_width) + grow_to_nozzle_diameter(pp, diff_ex(this->bounds, this->expolygon)); polylines_out->insert(polylines_out->end(), pp.begin(), pp.end()); } + +void +MedialAxis::grow_to_nozzle_diameter(ThickPolylines& pp, const ExPolygons& anchors) { + //ensure the width is not lower than 0.4. + for (ThickPolyline& polyline : pp) { + for (int i = 0; i < polyline.points.size(); ++i) { + bool is_anchored = false; + for (const ExPolygon &poly : anchors) { + if (poly.contains(polyline.points[i])) { + is_anchored = true; + break; + } + } + if (!is_anchored && polyline.width[i]<nozzle_diameter) polyline.width[i] = nozzle_diameter; + } + } +} + ExtrusionEntityCollection thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow) { // this value determines granularity of adaptive width, as G-code does not allow // variable extrusion within a single move; this value shall only affect the amount diff --git a/src/libslic3r/MedialAxis.hpp b/src/libslic3r/MedialAxis.hpp index 21fbe3895..85607b718 100644 --- a/src/libslic3r/MedialAxis.hpp +++ b/src/libslic3r/MedialAxis.hpp @@ -21,12 +21,14 @@ namespace Slic3r { ExPolygon expolygon; const ExPolygon& bounds; const ExPolygon& surface; - const double max_width; - const double min_width; - const double height; + const coord_t max_width; + const coord_t min_width; + const coord_t height; + coord_t nozzle_diameter; bool stop_at_min_width = true; - MedialAxis(const ExPolygon &_expolygon, const ExPolygon &_bounds, const double _max_width, const double _min_width, const double _height) + MedialAxis(const ExPolygon &_expolygon, const ExPolygon &_bounds, const coord_t _max_width, const coord_t _min_width, const coord_t _height) : surface(_expolygon), bounds(_bounds), max_width(_max_width), min_width(_min_width), height(_height) { + nozzle_diameter = _min_width; }; void build(ThickPolylines* polylines_out); void build(Polylines* polylines); @@ -60,6 +62,7 @@ namespace Slic3r { void remove_too_thin_points(ThickPolylines& pp); void remove_too_short_polylines(ThickPolylines& pp, const coord_t min_size); void ensure_not_overextrude(ThickPolylines& pp); + void grow_to_nozzle_diameter(ThickPolylines& pp, const ExPolygons& anchors); }; ExtrusionEntityCollection thin_variable_width(const ThickPolylines &polylines, ExtrusionRole role, Flow flow); diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp index 637d0eec6..13652f86a 100644 --- a/src/libslic3r/PerimeterGenerator.cpp +++ b/src/libslic3r/PerimeterGenerator.cpp @@ -265,7 +265,7 @@ void PerimeterGenerator::process() // the following offset2 ensures almost nothing in @thin_walls is narrower than $min_width // (actually, something larger than that still may exist due to mitering or other causes) - coord_t min_width = (coord_t)scale_(this->ext_perimeter_flow.nozzle_diameter / 3); + coord_t min_width = (coord_t)scale_(this->config->thin_walls_min_width.get_abs_value(this->ext_perimeter_flow.nozzle_diameter)); ExPolygons no_thin_zone = offset_ex(next_onion, (float)(ext_perimeter_width / 2), jtSquare); // medial axis requires non-overlapping geometry @@ -297,8 +297,9 @@ void PerimeterGenerator::process() if (thin[0].area() > min_width*(ext_perimeter_width + ext_perimeter_spacing2)) { bound.remove_point_too_near(SCALED_RESOLUTION); // the maximum thickness of our thin wall area is equal to the minimum thickness of a single loop - thin[0].medial_axis(bound, ext_perimeter_width + ext_perimeter_spacing2, min_width, - &thin_walls, this->layer_height); + Slic3r::MedialAxis ma(thin[0], bound, ext_perimeter_width + ext_perimeter_spacing2, min_width, this->layer_height); + ma.nozzle_diameter = (coord_t)scale_(this->ext_perimeter_flow.nozzle_diameter); + ma.build(&thin_walls); thin_zones_extruded.emplace_back(thin[0]); } break; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index fddfef0f1..637de22f3 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2346,7 +2346,7 @@ void PrintConfigDef::init_fff_params() def->default_value = new ConfigOptionInts { 200 }; def = this->add("thin_walls", coBool); - def->label = L("Detect thin walls"); + def->label = L(""); def->category = L("Layers and Perimeters"); def->tooltip = L("Detect single-width walls (parts where two extrusions don't fit and we need " "to collapse them into a single trace)."); @@ -2354,6 +2354,15 @@ void PrintConfigDef::init_fff_params() def->mode = comAdvanced; def->default_value = new ConfigOptionBool(true); + def = this->add("thin_walls_min_width", coFloatOrPercent); + def->label = L("min width"); + def->category = L("Layers and Perimeters"); + def->tooltip = L("Minimum width for the extrusion to be extruded (widths lower than the nozzle diameter will be over-extruded at the nozzle diameter). Can be percent of the nozzle size."); + def->cli = "thin-walls-min-width=s"; + def->mode = comExpert; + def->min = 0; + def->default_value = new ConfigOptionFloatOrPercent(33,true); + def = this->add("threads", coInt); def->label = L("Threads"); def->tooltip = L("Threads are used to parallelize long-running tasks. Optimal threads number " diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 32629a64b..0cab33423 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -519,6 +519,7 @@ public: ConfigOptionFloatOrPercent solid_infill_speed; // Detect thin walls. ConfigOptionBool thin_walls; + ConfigOptionFloatOrPercent thin_walls_min_width; ConfigOptionFloatOrPercent top_infill_extrusion_width; ConfigOptionInt top_solid_layers; ConfigOptionFloatOrPercent top_solid_infill_speed; @@ -574,6 +575,7 @@ protected: OPT_PTR(solid_infill_every_layers); OPT_PTR(solid_infill_speed); OPT_PTR(thin_walls); + OPT_PTR(thin_walls_min_width); OPT_PTR(top_infill_extrusion_width); OPT_PTR(top_solid_infill_speed); OPT_PTR(top_solid_layers); diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp index a159d2020..aeee8750c 100644 --- a/src/libslic3r/PrintObject.cpp +++ b/src/libslic3r/PrintObject.cpp @@ -462,6 +462,7 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_ || opt_key == "perimeter_extrusion_width" || opt_key == "infill_overlap" || opt_key == "thin_walls" + || opt_key == "thin_walls_min_width" || opt_key == "external_perimeters_first" || opt_key == "perimeter_loop" || opt_key == "perimeter_loop_seam" diff --git a/src/slic3r/GUI/Preset.cpp b/src/slic3r/GUI/Preset.cpp index e2abde519..23d632b0c 100644 --- a/src/slic3r/GUI/Preset.cpp +++ b/src/slic3r/GUI/Preset.cpp @@ -353,6 +353,7 @@ const std::vector<std::string>& Preset::print_options() , "infill_not_connected" , "first_layer_infill_speed" , "label_printed_objects" + , "thin_walls_min_width" }; return s_opts; } diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 0f779984d..7c66b8cf1 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -923,7 +923,10 @@ void TabPrint::build() optgroup->append_single_option_line("only_one_perimeter_top"); optgroup->append_single_option_line("ensure_vertical_shell_thickness"); optgroup->append_single_option_line("avoid_crossing_perimeters"); - optgroup->append_single_option_line("thin_walls"); + line = { _(L("Thin walls")), "" }; + line.append_option(optgroup->get_option("thin_walls")); + line.append_option(optgroup->get_option("thin_walls_min_width")); + optgroup->append_line(line); optgroup->append_single_option_line("overhangs"); line = { _(L("Avoid unsupported perimeters")), "" }; line.append_option(optgroup->get_option("no_perimeter_unsupported")); @@ -1322,10 +1325,11 @@ void TabPrint::update() bool have_perimeters = m_config->opt_int("perimeters") > 0; for (auto el : { "extra_perimeters", "only_one_perimeter_top", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", - "seam_position", "external_perimeters_first", "external_perimeter_extrusion_width", + "seam_position", "external_perimeters_first", "external_perimeter_extrusion_width", "thin_walls_min_width", "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "perimeter_loop", "perimeter_loop_seam" }) get_field(el)->toggle(have_perimeters); + get_field("thin_walls_min_width")->toggle(m_config->opt_bool("thin_walls")); get_field("perimeter_loop_seam")->toggle(m_config->opt_bool("perimeter_loop")); bool have_no_perimeter_unsupported = have_perimeters && m_config->opt_bool("no_perimeter_unsupported"); |