Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsupermerill <merill@free.fr>2022-07-22 02:24:40 +0300
committersupermerill <merill@free.fr>2022-07-24 02:45:21 +0300
commitd16b7d155b8d76db73c1b1e912d91d53f4241fb9 (patch)
tree04db985c9525d03047accecd9cb943dec8088f23
parent3ce5d1a4e1ea3fce0a8f869cad581370a49e7dcd (diff)
gapfill min_width and max_width
-rw-r--r--resources/ui_layout/default/print.ui6
-rw-r--r--src/libslic3r/Geometry/MedialAxis.cpp124
-rw-r--r--src/libslic3r/Geometry/MedialAxis.hpp8
-rw-r--r--src/libslic3r/Layer.cpp2
-rw-r--r--src/libslic3r/PerimeterGenerator.cpp19
-rw-r--r--src/libslic3r/Preset.cpp2
-rw-r--r--src/libslic3r/PrintConfig.cpp31
-rw-r--r--src/libslic3r/PrintConfig.hpp2
-rw-r--r--src/libslic3r/PrintObject.cpp2
-rw-r--r--src/slic3r/GUI/ConfigManipulation.cpp2
10 files changed, 186 insertions, 12 deletions
diff --git a/resources/ui_layout/default/print.ui b/resources/ui_layout/default/print.ui
index b61c33748..52668964d 100644
--- a/resources/ui_layout/default/print.ui
+++ b/resources/ui_layout/default/print.ui
@@ -66,9 +66,13 @@ group:Advanced
setting:width$25:no_perimeter_unsupported_algo
line:Gap Fill
setting:label$_:gap_fill_enabled
- setting:width$5:gap_fill_min_area
setting:width$5:gap_fill_last
end_line
+ line:Gap Fill threshold
+ setting:width$5:gap_fill_min_width
+ setting:width$5:gap_fill_max_width
+ setting:width$5:gap_fill_min_area
+ end_line
line:Seam
setting:tags$Simple$Advanced$Expert$Prusa$SuSi:script:enum$corners$Corners$nearest$Nearest$random$Random$aligned$Aligned$rear$Rear$custom$Custom:depends$seam_position$seam_angle_cost$seam_travel_cost:label$Seam position:label_width$12:sidetext_width$0:tooltip$Position of perimeters' starting points.\nCustom can be defined in Advanced or Expert mode. Cost-based settings let you choose the angle and travel cost. A high angle cost will place the seam where it can be hidden by a corner, the travel cost place the seam near the last position (often at the end of the previous infill).:s_seam_position
# setting:tags$Expert:label_width$12:sidetext_width$0:seam_position
diff --git a/src/libslic3r/Geometry/MedialAxis.cpp b/src/libslic3r/Geometry/MedialAxis.cpp
index 670c8fb45..e5cc5d6dd 100644
--- a/src/libslic3r/Geometry/MedialAxis.cpp
+++ b/src/libslic3r/Geometry/MedialAxis.cpp
@@ -1979,7 +1979,72 @@ MedialAxis::remove_too_thin_extrusion(ThickPolylines& pp)
changes = true;
}
//remove points and bits that comes from a "main line"
- if (polyline.points.size() < 2 || (polyline_changes && polyline.points.size() == 2 && polyline.length() < std::max(this->min_length, std::max(polyline.width.front(), polyline.width.back()))) ) {
+ if (polyline.points.size() < 2 || (polyline_changes && polyline.points.size() == 2 && polyline.length() < std::max(this->min_length, std::max(polyline.width.front(), polyline.width.back())))) {
+ //remove self if too small
+ pp.erase(pp.begin() + i);
+ --i;
+ }
+ }
+ if (changes) concatThickPolylines(pp);
+}
+
+void
+MedialAxis::remove_too_thick_extrusion(ThickPolylines& pp)
+{
+ // remove too thin extrusion at start & end of polylines
+ bool changes = false;
+ for (size_t i = 0; i < pp.size(); ++i) {
+ ThickPolyline& polyline = pp[i];
+ bool polyline_changes = false;
+ // remove bits with too small extrusion
+ while (polyline.points.size() > 1 && polyline.width.front() > this->biggest_width && polyline.endpoints.first) {
+ //try to split if possible
+ if (polyline.width[1] < this->biggest_width) {
+ double percent_can_keep = (this->biggest_width - polyline.width[0]) / (polyline.width[1] - polyline.width[0]);
+ if (polyline.points.front().distance_to(polyline.points[1]) * (1 - percent_can_keep) > coordf_t(this->resolution)) {
+ //Can split => move the first point and assign a new weight.
+ //the update of endpoints wil be performed in concatThickPolylines
+ polyline.points.front() = polyline.points.front().interpolate(percent_can_keep, polyline.points[1]);
+ polyline.width.front() = this->biggest_width;
+ } else {
+ /// almost 0-length, Remove
+ polyline.points.erase(polyline.points.begin());
+ polyline.width.erase(polyline.width.begin());
+ }
+ changes = true;
+ polyline_changes = true;
+ break;
+ }
+ polyline.points.erase(polyline.points.begin());
+ polyline.width.erase(polyline.width.begin());
+ changes = true;
+ polyline_changes = true;
+ }
+ while (polyline.points.size() > 1 && polyline.width.back() > this->biggest_width && polyline.endpoints.second) {
+ //try to split if possible
+ if (polyline.width[polyline.points.size() - 2] < this->biggest_width) {
+ double percent_can_keep = (this->biggest_width - polyline.width.back()) / (polyline.width[polyline.points.size() - 2] - polyline.width.back());
+ if (polyline.points.back().distance_to(polyline.points[polyline.points.size() - 2]) * (1 - percent_can_keep) > coordf_t(this->resolution)) {
+ //Can split => move the first point and assign a new weight.
+ //the update of endpoints wil be performed in concatThickPolylines
+ polyline.points.back() = polyline.points.back().interpolate(percent_can_keep, polyline.points[polyline.points.size() - 2]);
+ polyline.width.back() = this->biggest_width;
+ } else {
+ /// almost 0-length, Remove
+ polyline.points.erase(polyline.points.end() - 1);
+ polyline.width.erase(polyline.width.end() - 1);
+ }
+ polyline_changes = true;
+ changes = true;
+ break;
+ }
+ polyline.points.erase(polyline.points.end() - 1);
+ polyline.width.erase(polyline.width.end() - 1);
+ polyline_changes = true;
+ changes = true;
+ }
+ //remove points and bits that comes from a "main line"
+ if (polyline.points.size() < 2 || (polyline_changes && polyline.points.size() == 2 && polyline.length() < std::max(this->min_length, std::max(polyline.width.front(), polyline.width.back())))) {
//remove self if too small
pp.erase(pp.begin() + i);
--i;
@@ -2229,6 +2294,62 @@ MedialAxis::remove_too_thin_points(ThickPolylines& pp)
}
void
+MedialAxis::remove_too_thick_points(ThickPolylines& pp)
+{
+ if (biggest_width <= 0) return;
+ //remove too thin polylines points (inside a polyline : split it)
+ for (size_t i = 0; i < pp.size(); ++i) {
+ ThickPolyline* polyline = &pp[i];
+
+ // remove bits with too small extrusion
+ size_t idx_point = 0;
+ while (idx_point < polyline->points.size()) {
+ if (polyline->width[idx_point] > biggest_width) {
+ if (idx_point == 0) {
+ //too thin at start
+ polyline->points.erase(polyline->points.begin());
+ polyline->width.erase(polyline->width.begin());
+ idx_point = 0;
+ } else if (idx_point == 1) {
+ //too thin at start
+ polyline->points.erase(polyline->points.begin());
+ polyline->width.erase(polyline->width.begin());
+ polyline->points.erase(polyline->points.begin());
+ polyline->width.erase(polyline->width.begin());
+ idx_point = 0;
+ } else if (idx_point == polyline->points.size() - 2) {
+ //too thin at (near) end
+ polyline->points.erase(polyline->points.end() - 1);
+ polyline->width.erase(polyline->width.end() - 1);
+ polyline->points.erase(polyline->points.end() - 1);
+ polyline->width.erase(polyline->width.end() - 1);
+ } else if (idx_point == polyline->points.size() - 1) {
+ //too thin at end
+ polyline->points.erase(polyline->points.end() - 1);
+ polyline->width.erase(polyline->width.end() - 1);
+ } else {
+ //too thin in middle : split
+ pp.emplace_back();
+ polyline = &pp[i]; // have to refresh the pointer, as the emplace_back() may have moved the array
+ ThickPolyline& newone = pp.back();
+ newone.points.insert(newone.points.begin(), polyline->points.begin() + idx_point + 1, polyline->points.end());
+ newone.width.insert(newone.width.begin(), polyline->width.begin() + idx_point + 1, polyline->width.end());
+ polyline->points.erase(polyline->points.begin() + idx_point, polyline->points.end());
+ polyline->width.erase(polyline->width.begin() + idx_point, polyline->width.end());
+ }
+ } else idx_point++;
+
+ if (polyline->points.size() < 2) {
+ //remove self if too small
+ pp.erase(pp.begin() + i);
+ --i;
+ break;
+ }
+ }
+ }
+}
+
+void
MedialAxis::remove_too_short_polylines(ThickPolylines& pp)
{
// reduce the flow at the intersection ( + ) points
@@ -2800,6 +2921,7 @@ MedialAxis::build(ThickPolylines& polylines_out)
//}
remove_too_thin_points(pp);
+ remove_too_thick_extrusion(pp);
//{
// std::stringstream stri;
// stri << "medial_axis_5.0_thuinner_" << id << ".svg";
diff --git a/src/libslic3r/Geometry/MedialAxis.hpp b/src/libslic3r/Geometry/MedialAxis.hpp
index e9a0f5737..21e2ddad8 100644
--- a/src/libslic3r/Geometry/MedialAxis.hpp
+++ b/src/libslic3r/Geometry/MedialAxis.hpp
@@ -72,6 +72,7 @@ public:
/// optional parameter: if true, the extension inside the bounds can be cut if the width is too small. Default : true
MedialAxis& set_stop_at_min_width(const bool stop_at_min_width) { this->stop_at_min_width = stop_at_min_width; return *this; }
MedialAxis& set_min_length(const coord_t min_length) { this->min_length = min_length; return *this; }
+ MedialAxis& set_biggest_width(const coord_t biggest_width) { this->biggest_width = biggest_width; return *this; }
private:
@@ -80,10 +81,12 @@ private:
/// the copied expolygon from surface, it's modified in build() to simplify it. It's then used to create the voronoi diagram.
ExPolygon expolygon;
const ExPolygon* bounds;
- /// maximum width of the extrusion. _expolygon shouldn't have a spot where a circle diameter is higher than that (or almost).
+ /// maximum width for the algorithm. _expolygon shouldn't have a spot where a circle diameter is higher than that (or almost).
const coord_t max_width;
/// minimum width of the extrusion, every spot where a circle diameter is lower than that will be ignored (unless it's the tip of the extrusion)
const coord_t min_width;
+ /// maximum width of the extrusion. if a point has a width higher than that, it will be removed
+ coord_t biggest_width = 0;
/// minimum length of continuous segments (may cross a crossing)
coord_t min_length;
/// resolution for simplifuing and stuff like that
@@ -123,16 +126,19 @@ private:
void fusion_corners(ThickPolylines& pp);
/// extends the polylines inside bounds, use extends_line on both end
void extends_line_both_side(ThickPolylines& pp);
+ void extends_line_extra(ThickPolylines& pp);
/// extends the polylines inside bounds (anchors)
void extends_line(ThickPolyline& polyline, const ExPolygons& anchors, const coord_t join_width);
/// remove too thin bits at start & end of polylines
void remove_too_thin_extrusion(ThickPolylines& pp);
+ void remove_too_thick_extrusion(ThickPolylines& pp);
/// when we have a too small polyline, try to see if we can't concatenate it at a crossing to keep it.
void concatenate_small_polylines(ThickPolylines& pp);
/// instead of keeping polyline split at each corssing, we try to create long strait polylines that can cross each other.
void concatenate_polylines_with_crossing(ThickPolylines& pp);
/// remove bits around points that are too thin (can be inside the polyline)
void remove_too_thin_points(ThickPolylines& pp);
+ void remove_too_thick_points(ThickPolylines& pp);
/// delete polylines that are too short (below the this->min_length)
void remove_too_short_polylines(ThickPolylines& pp);
/// be sure we didn't try to push more plastic than the volume defined by surface * height can receive. If overextruded, reduce all widths by the correct %.
diff --git a/src/libslic3r/Layer.cpp b/src/libslic3r/Layer.cpp
index 5046bd285..5c1966560 100644
--- a/src/libslic3r/Layer.cpp
+++ b/src/libslic3r/Layer.cpp
@@ -183,7 +183,9 @@ void Layer::make_perimeters()
&& ((config.gap_fill_speed == other_config.gap_fill_speed) || !config.gap_fill_enabled)
&& config.gap_fill_last == other_config.gap_fill_last
&& config.gap_fill_flow_match_perimeter == other_config.gap_fill_flow_match_perimeter
+ && config.gap_fill_max_width == other_config.gap_fill_max_width
&& config.gap_fill_min_area == other_config.gap_fill_min_area
+ && config.gap_fill_min_width == other_config.gap_fill_min_width
&& config.gap_fill_overlap == other_config.gap_fill_overlap
&& config.infill_dense == other_config.infill_dense
&& config.infill_dense_algo == other_config.infill_dense_algo
diff --git a/src/libslic3r/PerimeterGenerator.cpp b/src/libslic3r/PerimeterGenerator.cpp
index 9e23d3847..83cd8da6f 100644
--- a/src/libslic3r/PerimeterGenerator.cpp
+++ b/src/libslic3r/PerimeterGenerator.cpp
@@ -1127,14 +1127,23 @@ void PerimeterGenerator::process()
ExPolygons gap_srf;
if (!gaps.empty()) {
// collapse
- double min = 0.2 * perimeter_width * (1 - INSET_OVERLAP_TOLERANCE);
+ coordf_t min = 0.2 * perimeter_width * (1 - INSET_OVERLAP_TOLERANCE);
//be sure we don't gapfill where the perimeters are already touching each other (negative spacing).
min = std::max(min, double(Flow::new_from_spacing((float)EPSILON, (float)this->perimeter_flow.nozzle_diameter(), (float)this->layer->height, (float)this->perimeter_flow.spacing_ratio(), false).scaled_width()));
- double max = 2.2 * perimeter_spacing;
+ coordf_t real_max = 2.5 * perimeter_spacing;
+ const coordf_t minwidth = scale_d(this->config->gap_fill_min_width.get_abs_value(unscaled((double)perimeter_width)));
+ const coordf_t maxwidth = scale_d(this->config->gap_fill_max_width.get_abs_value(unscaled((double)perimeter_width)));
+ if (minwidth > 0) {
+ min = std::max(min, minwidth);
+ }
+ coordf_t max = real_max;
+ if (maxwidth > 0) {
+ max = std::min(max, maxwidth);
+ }
//remove areas that are too big (shouldn't occur...)
ExPolygons too_big = offset2_ex(gaps, double(-max / 2), double(+max / 2));
ExPolygons gaps_ex_to_test = too_big.empty() ? gaps : diff_ex(gaps, too_big, ApplySafetyOffset::Yes);
- const double minarea = scale_(scale_(this->config->gap_fill_min_area.get_abs_value(unscaled((double)perimeter_width) * unscaled((double)perimeter_width))));
+ const double minarea = scale_d(scale_d(this->config->gap_fill_min_area.get_abs_value(unscaled((double)perimeter_width) * unscaled((double)perimeter_width))));
// check each gapfill area to see if it's printable.
for (const ExPolygon& expoly : gaps_ex_to_test) {
//remove too small gaps that are too hard to fill.
@@ -1189,7 +1198,9 @@ void PerimeterGenerator::process()
// create lines from the area
ThickPolylines polylines;
for (const ExPolygon& ex : gaps_ex) {
- Geometry::MedialAxis{ ex, coord_t(max * 1.1), coord_t(min), coord_t(this->layer->height) }.build(polylines);
+ Geometry::MedialAxis{ ex, coord_t(real_max), coord_t(min), coord_t(this->layer->height) }
+ .set_biggest_width(max)
+ .build(polylines);
}
// create extrusion from lines
if (!polylines.empty()) {
diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp
index aa33fb602..c0346f3f5 100644
--- a/src/libslic3r/Preset.cpp
+++ b/src/libslic3r/Preset.cpp
@@ -534,7 +534,9 @@ static std::vector<std::string> s_Preset_print_options {
"gap_fill_enabled",
"gap_fill_flow_match_perimeter",
"gap_fill_last",
+ "gap_fill_max_width",
"gap_fill_min_area",
+ "gap_fill_min_width",
"gap_fill_overlap",
"gap_fill_speed",
// fuzzy
diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp
index acf5c08de..77792980a 100644
--- a/src/libslic3r/PrintConfig.cpp
+++ b/src/libslic3r/PrintConfig.cpp
@@ -2587,7 +2587,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("gap_fill_flow_match_perimeter", coPercent);
def->label = L("Cap with perimeter flow");
- def->full_label = L("Cap gapfill speed with perimeter flow");
+ def->full_label = L("Gapfill: cap speed with perimeter flow");
def->category = OptionCategory::output;
def->tooltip = L("A percentage of the perimeter flow (mm3/s) is used as a limit for the gap fill flow, and so the gapfill may reduce its speed when the gap fill extrusions became too thick."
" This allow you to use a high gapfill speed, to print the thin gapfill quickly and reduce the difference in flow rate for the gapfill."
@@ -2599,21 +2599,44 @@ void PrintConfigDef::init_fff_params()
def = this->add("gap_fill_last", coBool);
def->label = L("after last perimeter");
- def->full_label = L("Gapfill after last perimeter");
+ def->full_label = L("Gapfill: after last perimeter");
def->category = OptionCategory::perimeter;
def->tooltip = L("All gaps, between the last perimeter and the infill, which are thinner than a perimeter will be filled by gapfill.");
def->mode = comExpert | comSuSi;
def->set_default_value(new ConfigOptionBool(false));
+ def = this->add("gap_fill_max_width", coFloatOrPercent);
+ def->label = L("Max width");
+ def->full_label = L("Gapfill: Max width");
+ def->category = OptionCategory::perimeter;
+ def->tooltip = L("This setting represents the maximum width of a gapfill. Points wider than this threshold won't be created.\nCan be a % of the perimeter width\n0 to auto");
+ def->ratio_over = "perimeter_width";
+ def->sidetext = L("mm or %");
+ def->min = 0;
+ def->mode = comExpert | comSuSi;
+ def->set_default_value(new ConfigOptionFloatOrPercent{ 0, false });
+
def = this->add("gap_fill_min_area", coFloatOrPercent);
def->label = L("Min surface");
- def->full_label = L("Min surface for gap filling");
+ def->full_label = L("Gapfill: Min surface");
def->category = OptionCategory::perimeter;
def->tooltip = L("This setting represents the minimum mm² for a gapfill extrusion to be created.\nCan be a % of (perimeter width)²");
def->ratio_over = "perimeter_width_square";
+ def->sidetext = L("mm² or %");
+ def->min = 0;
+ def->mode = comExpert | comSuSi;
+ def->set_default_value(new ConfigOptionFloatOrPercent{ 100, true });
+
+ def = this->add("gap_fill_min_width", coFloatOrPercent);
+ def->label = L("Min width");
+ def->full_label = L("Gapfill: Min width");
+ def->category = OptionCategory::perimeter;
+ def->tooltip = L("This setting represents the minimum width of a gapfill. Points thinner than this threshold won't be created.\nCan be a % of the perimeter width\n0 to auto");
+ def->ratio_over = "perimeter_width";
+ def->sidetext = L("mm or %");
def->min = 0;
def->mode = comExpert | comSuSi;
- def->set_default_value(new ConfigOptionFloatOrPercent{100, true });
+ def->set_default_value(new ConfigOptionFloatOrPercent{ 0, false });
def = this->add("gap_fill_overlap", coPercent);
def->label = L("Gap fill overlap");
diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp
index 568c00181..37402d12c 100644
--- a/src/libslic3r/PrintConfig.hpp
+++ b/src/libslic3r/PrintConfig.hpp
@@ -812,7 +812,9 @@ PRINT_CONFIG_CLASS_DEFINE(
((ConfigOptionBool, gap_fill_enabled))
((ConfigOptionPercent, gap_fill_flow_match_perimeter))
((ConfigOptionBool, gap_fill_last))
+ ((ConfigOptionFloatOrPercent, gap_fill_max_width))
((ConfigOptionFloatOrPercent, gap_fill_min_area))
+ ((ConfigOptionFloatOrPercent, gap_fill_min_width))
((ConfigOptionPercent, gap_fill_overlap))
((ConfigOptionFloatOrPercent, gap_fill_speed))
((ConfigOptionFloatOrPercent, infill_anchor))
diff --git a/src/libslic3r/PrintObject.cpp b/src/libslic3r/PrintObject.cpp
index 82b5397ee..a6209ac69 100644
--- a/src/libslic3r/PrintObject.cpp
+++ b/src/libslic3r/PrintObject.cpp
@@ -714,7 +714,9 @@ bool PrintObject::invalidate_state_by_config_options(
if (
opt_key == "gap_fill_enabled"
|| opt_key == "gap_fill_last"
+ || opt_key == "gap_fill_max_width"
|| opt_key == "gap_fill_min_area"
+ || opt_key == "gap_fill_min_width"
|| opt_key == "only_one_perimeter_first_layer"
|| opt_key == "only_one_perimeter_top"
|| opt_key == "only_one_perimeter_top_other_algo"
diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp
index db0097f79..ab9ce37ce 100644
--- a/src/slic3r/GUI/ConfigManipulation.cpp
+++ b/src/slic3r/GUI/ConfigManipulation.cpp
@@ -345,7 +345,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
toggle_field("perimeter_loop_seam", config->opt_bool("perimeter_loop"));
- for (auto el : { "gap_fill_last", "gap_fill_min_area" })
+ for (auto el : { "gap_fill_last", "gap_fill_max_width", "gap_fill_min_area", "gap_fill_min_width" })
toggle_field(el, config->opt_bool("gap_fill_enabled"));
for (auto el : { "fuzzy_skin_thickness", "fuzzy_skin_point_dist" })