mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 00:15:55 +08:00
#206 reverse direction on overhang overhaul:
- now has a setting & a threshold - when reverse_direction trigger on the external loop, it also trigger for all other loops on this side (so, no more U-turn) - do not depends on extra_perimeter anymore - now extra_perimeters split into extra_perimeters (the old useless one) and extra_perimeters_overhangs - reordering settings in the tab.
This commit is contained in:
parent
1da021b352
commit
3d5ddd60b4
@ -15,12 +15,12 @@ group:Horizontal shells
|
||||
end_line
|
||||
top_bottom_shell_thickness_explanation
|
||||
setting:enforce_full_fill_volume
|
||||
group:Quality (slower slicing)
|
||||
group:Quality
|
||||
setting:only_one_perimeter_top
|
||||
line:Extra perimeters
|
||||
setting:extra_perimeters
|
||||
setting:extra_perimeters_overhangs
|
||||
setting:extra_perimeters_odd_layers
|
||||
end_line
|
||||
setting:only_one_perimeter_top
|
||||
setting:ensure_vertical_shell_thickness
|
||||
line:Avoid crossing perimeters
|
||||
setting:label$:avoid_crossing_perimeters
|
||||
@ -32,12 +32,17 @@ group:Quality (slower slicing)
|
||||
setting:width$5:thin_walls_min_width
|
||||
setting:width$5:thin_walls_overlap
|
||||
end_line
|
||||
line:Overhangs
|
||||
setting:overhangs
|
||||
group:Overhangs
|
||||
line:On perimeters
|
||||
setting:sidetext_width$1:overhangs
|
||||
setting:width$5:overhangs_width
|
||||
end_line
|
||||
setting:no_perimeter_unsupported_algo
|
||||
line:Extrusion direction
|
||||
setting:sidetext_width$1:overhangs_reverse
|
||||
setting:width$5:overhangs_reverse_threshold
|
||||
end_line
|
||||
group:Advanced
|
||||
setting:no_perimeter_unsupported_algo
|
||||
line:Gap Fill
|
||||
setting:gap_fill
|
||||
setting:width$5:gap_fill_min_area
|
||||
|
@ -144,6 +144,7 @@ void Layer::make_perimeters()
|
||||
&& config.external_perimeters_nothole == other_config.external_perimeters_nothole
|
||||
&& config.external_perimeter_speed == other_config.external_perimeter_speed
|
||||
&& config.extra_perimeters_odd_layers == other_config.extra_perimeters_odd_layers
|
||||
&& config.extra_perimeters_overhangs == other_config.extra_perimeters_overhangs
|
||||
&& config.gap_fill == other_config.gap_fill
|
||||
&& config.gap_fill_min_area == other_config.gap_fill_min_area
|
||||
&& config.gap_fill_speed == other_config.gap_fill_speed
|
||||
@ -153,6 +154,8 @@ void Layer::make_perimeters()
|
||||
&& config.only_one_perimeter_top == other_config.only_one_perimeter_top
|
||||
&& config.overhangs == other_config.overhangs
|
||||
&& config.overhangs_width == other_config.overhangs_width
|
||||
&& config.overhangs_reverse == other_config.overhangs_reverse
|
||||
&& config.overhangs_reverse_threshold == other_config.overhangs_reverse_threshold
|
||||
&& config.perimeter_extrusion_width == other_config.perimeter_extrusion_width
|
||||
&& config.perimeter_loop == other_config.perimeter_loop
|
||||
&& config.perimeter_loop_seam == other_config.perimeter_loop_seam
|
||||
|
@ -295,8 +295,8 @@ void PerimeterGenerator::process()
|
||||
|
||||
// Add perimeters on overhangs : initialization
|
||||
ExPolygons overhangs_unsupported;
|
||||
if (this->config->extra_perimeters && !last.empty()
|
||||
&& this->lower_slices != NULL && !this->lower_slices->empty()) {
|
||||
if ( (this->config->extra_perimeters_overhangs || (this->config->overhangs_reverse && this->layer_id % 2 == 1))
|
||||
&& !last.empty() && this->lower_slices != NULL && !this->lower_slices->empty()) {
|
||||
//remove holes from lower layer, we only ant that for overhangs, not bridges!
|
||||
ExPolygons lower_without_holes;
|
||||
for (const ExPolygon &exp : *this->lower_slices)
|
||||
@ -330,6 +330,18 @@ void PerimeterGenerator::process()
|
||||
}
|
||||
}
|
||||
}
|
||||
bool has_steep_overhang = false;
|
||||
if (this->layer_id % 2 == 1 && this->config->overhangs_reverse //check if my option is set and good layer
|
||||
&& !last.empty() && !overhangs_unsupported.empty() //has something to work with
|
||||
) {
|
||||
coord_t offset = scale_(config->overhangs_reverse_threshold.get_abs_value(this->perimeter_flow.width));
|
||||
//version with °: scale_(std::tan(PI * (0.5f / 90) * config->overhangs_reverse_threshold.value ) * this->layer_height)
|
||||
|
||||
if (offset_ex(overhangs_unsupported, -offset / 2).size() > 0) {
|
||||
//allow this loop to be printed in reverse
|
||||
has_steep_overhang = true;
|
||||
}
|
||||
}
|
||||
|
||||
// In case no perimeters are to be generated, loop_number will equal to -1.
|
||||
std::vector<PerimeterGeneratorLoops> contours(loop_number+1); // depth => loops
|
||||
@ -341,10 +353,10 @@ void PerimeterGenerator::process()
|
||||
// We can add more perimeters if there are uncovered overhangs
|
||||
// improvement for future: find a way to add perimeters only where it's needed.
|
||||
bool has_overhang = false;
|
||||
if (this->config->extra_perimeters && !last.empty() && !overhangs_unsupported.empty()) {
|
||||
if ( this->config->extra_perimeters_overhangs && !last.empty() && !overhangs_unsupported.empty()) {
|
||||
overhangs_unsupported = intersection_ex(overhangs_unsupported, last, true);
|
||||
if (overhangs_unsupported.size() > 0) {
|
||||
//add fake perimeters here
|
||||
//please don't stop adding periemter yet.
|
||||
has_overhang = true;
|
||||
}
|
||||
}
|
||||
@ -512,11 +524,11 @@ void PerimeterGenerator::process()
|
||||
|
||||
for (const ExPolygon &expolygon : next_onion) {
|
||||
//TODO: add width here to allow variable width (if we want to extrude a sightly bigger perimeter, see thin wall)
|
||||
contours[i].emplace_back(PerimeterGeneratorLoop(expolygon.contour, i, true, has_overhang));
|
||||
contours[i].emplace_back(expolygon.contour, i, true, has_steep_overhang);
|
||||
if (! expolygon.holes.empty()) {
|
||||
holes[i].reserve(holes[i].size() + expolygon.holes.size());
|
||||
for (const Polygon &hole : expolygon.holes)
|
||||
holes[i].emplace_back(PerimeterGeneratorLoop(hole, i, false, has_overhang));
|
||||
holes[i].emplace_back(hole, i, false, has_steep_overhang);
|
||||
}
|
||||
}
|
||||
last = std::move(next_onion);
|
||||
@ -889,7 +901,8 @@ ExtrusionEntityCollection PerimeterGenerator::_traverse_loops(
|
||||
ExtrusionLoop *eloop = static_cast<ExtrusionLoop*>(coll.entities[idx.first]);
|
||||
coll.entities[idx.first] = nullptr;
|
||||
if (loop.is_contour) {
|
||||
if (loop.is_overhang && this->layer_id % 2 == 1)
|
||||
//note: this->layer_id % 2 == 1 already taken into account in the is_steep_overhang compute (to save time).
|
||||
if (loop.is_steep_overhang && this->layer_id % 2 == 1)
|
||||
eloop->make_clockwise();
|
||||
else
|
||||
eloop->make_counter_clockwise();
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
// Contours are CCW oriented, holes are CW oriented.
|
||||
bool is_contour;
|
||||
//overhang may need to be reversed
|
||||
bool is_overhang;
|
||||
bool is_steep_overhang;
|
||||
// Depth in the hierarchy. External perimeter has depth = 0. An external perimeter could be both a contour and a hole.
|
||||
unsigned short depth;
|
||||
// Children contour, may be both CCW and CW oriented (outer contours or holes).
|
||||
@ -37,9 +37,9 @@ public:
|
||||
|
||||
|
||||
PerimeterGeneratorLoop(Polygon polygon, unsigned short depth, bool is_contour) :
|
||||
polygon(polygon), is_contour(is_contour), depth(depth), is_overhang(false) {}
|
||||
PerimeterGeneratorLoop(Polygon polygon, unsigned short depth, bool is_contour, bool is_overhang) :
|
||||
polygon(polygon), is_contour(is_contour), depth(depth), is_overhang(is_overhang) {}
|
||||
polygon(polygon), is_contour(is_contour), depth(depth), is_steep_overhang(false) {}
|
||||
PerimeterGeneratorLoop(Polygon polygon, unsigned short depth, bool is_contour, bool is_steep_overhang) :
|
||||
polygon(polygon), is_contour(is_contour), depth(depth), is_steep_overhang(is_steep_overhang) {}
|
||||
// External perimeter. It may be CCW or CW oriented (outer contour or hole contour).
|
||||
bool is_external() const { return this->depth == 0; }
|
||||
// An island, which may have holes, but it does not have another internal island.
|
||||
|
@ -761,12 +761,24 @@ void PrintConfigDef::init_fff_params()
|
||||
|
||||
def = this->add("extra_perimeters", coBool);
|
||||
def->label = L("filling horizontal gaps on slopes");
|
||||
def->full_label = L("Extra perimeters if needed");
|
||||
def->full_label = L("Extra perimeters (do nothing)");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("Add more perimeters when needed for avoiding gaps in sloping walls. "
|
||||
"Slic3r keeps adding perimeters, until more than 70% of the loop immediately above "
|
||||
"is supported, and keep adding periemter until all overhangs are filled."
|
||||
"\n!! this is a very slow algorithm !!");
|
||||
"is supported."
|
||||
"\nIf you succeed to trigger the algorihtm behind this setting, please send me a message."
|
||||
" Personally, i think it's useless.");
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("extra_perimeters_overhangs", coBool);
|
||||
def->label = L("on overhangs");
|
||||
def->full_label = L("Extra perimeters in overhangs");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("Add more perimeters when needed for avoiding gaps in sloping walls. "
|
||||
"Slic3r keeps adding periemter until all overhangs are filled."
|
||||
"\n!! this is a very slow algorithm !!"
|
||||
"\nIf you use this setting, consider strongly using also overhangs_reverse.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
@ -2030,13 +2042,31 @@ void PrintConfigDef::init_fff_params()
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
|
||||
def = this->add("overhangs_width", coFloatOrPercent);
|
||||
def->label = L("Threshold");
|
||||
def->full_label = L("Overhang Threshold");
|
||||
def->label = L("As bridge threshold");
|
||||
def->full_label = L("Overhang bridge threshold");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("Minimum unsupported width for an extrusion to be considered an overhang. Can be in mm or in a % of the nozzle diameter.");
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(50, true));
|
||||
|
||||
def = this->add("overhangs_reverse", coBool);
|
||||
def->label = L("Reverse on odd");
|
||||
def->full_label = L("Overhang reversal");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("Extrude perimeters that have a part over an overhang in the reverse direction in odd layers. That alternating pattern can drastically improve steep overhang."
|
||||
"\n!! this is a very slow algorithm (it uses the same results as extra_perimeters_overhangs) !!");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("overhangs_reverse_threshold", coFloatOrPercent);
|
||||
def->label = L("Reverse threshold");
|
||||
def->full_label = L("Overhang reversal threshold");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("Number of mm the overhang need to be for the reversal to be considered useful. Can be a % of the periemter width.");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(250, true));
|
||||
|
||||
def = this->add("no_perimeter_unsupported_algo", coEnum);
|
||||
def->label = L("No perimeters on bridge areas");
|
||||
def->category = OptionCategory::perimeter;
|
||||
|
@ -597,6 +597,7 @@ public:
|
||||
ConfigOptionBool external_perimeters_hole;
|
||||
ConfigOptionBool extra_perimeters;
|
||||
ConfigOptionBool extra_perimeters_odd_layers;
|
||||
ConfigOptionBool extra_perimeters_overhangs;
|
||||
ConfigOptionBool only_one_perimeter_top;
|
||||
ConfigOptionFloat fill_angle;
|
||||
ConfigOptionPercent fill_density;
|
||||
@ -620,6 +621,8 @@ public:
|
||||
// Detect bridging perimeters
|
||||
ConfigOptionBool overhangs;
|
||||
ConfigOptionFloatOrPercent overhangs_width;
|
||||
ConfigOptionBool overhangs_reverse;
|
||||
ConfigOptionFloatOrPercent overhangs_reverse_threshold;
|
||||
ConfigOptionEnum<NoPerimeterUnsupportedAlgo> no_perimeter_unsupported_algo;
|
||||
ConfigOptionInt perimeter_extruder;
|
||||
ConfigOptionFloatOrPercent perimeter_extrusion_width;
|
||||
@ -675,6 +678,7 @@ protected:
|
||||
OPT_PTR(external_perimeters_hole);
|
||||
OPT_PTR(extra_perimeters);
|
||||
OPT_PTR(extra_perimeters_odd_layers);
|
||||
OPT_PTR(extra_perimeters_overhangs);
|
||||
OPT_PTR(only_one_perimeter_top);
|
||||
OPT_PTR(fill_angle);
|
||||
OPT_PTR(fill_density);
|
||||
@ -697,6 +701,8 @@ protected:
|
||||
OPT_PTR(infill_first);
|
||||
OPT_PTR(overhangs);
|
||||
OPT_PTR(overhangs_width);
|
||||
OPT_PTR(overhangs_reverse);
|
||||
OPT_PTR(overhangs_reverse_threshold);
|
||||
OPT_PTR(no_perimeter_unsupported_algo);
|
||||
OPT_PTR(perimeter_extruder);
|
||||
OPT_PTR(perimeter_extrusion_width);
|
||||
|
@ -598,6 +598,9 @@ bool PrintObject::invalidate_state_by_config_options(const std::vector<t_config_
|
||||
|| opt_key == "gap_fill"
|
||||
|| opt_key == "gap_fill_speed"
|
||||
|| opt_key == "overhangs"
|
||||
|| opt_key == "overhangs_width"
|
||||
|| opt_key == "overhangs_reverse"
|
||||
|| opt_key == "overhangs_reverse_threshold"
|
||||
|| opt_key == "first_layer_extrusion_width"
|
||||
|| opt_key == "perimeter_extrusion_width"
|
||||
|| opt_key == "infill_overlap"
|
||||
|
@ -294,11 +294,16 @@ void ConfigManipulation::update_print_fff_config(DynamicPrintConfig* config, con
|
||||
void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
||||
{
|
||||
bool have_perimeters = config->opt_int("perimeters") > 0;
|
||||
for (auto el : { "extra_perimeters", "extra_perimeters_odd_layers", "only_one_perimeter_top", "ensure_vertical_shell_thickness", "thin_walls", "overhangs",
|
||||
for (auto el : { "extra_perimeters", "extra_perimeters_overhangs", "extra_perimeters_odd_layers",
|
||||
"only_one_perimeter_top", "ensure_vertical_shell_thickness", "thin_walls",
|
||||
"overhangs", "overhangs_reverse",
|
||||
"seam_position", "external_perimeters_first", "external_perimeters_vase", "external_perimeter_extrusion_width",
|
||||
"perimeter_speed", "small_perimeter_speed", "external_perimeter_speed", "perimeter_loop", "perimeter_loop_seam" })
|
||||
toggle_field(el, have_perimeters);
|
||||
|
||||
toggle_field("overhangs_width", config->opt_bool("overhangs"));
|
||||
toggle_field("overhangs_reverse_threshold", config->opt_bool("overhangs_reverse"));
|
||||
|
||||
for (auto el : { "external_perimeters_vase", "external_perimeters_nothole", "external_perimeters_hole"})
|
||||
toggle_field(el, config->opt_bool("external_perimeters_first"));
|
||||
|
||||
|
@ -426,6 +426,7 @@ const std::vector<std::string>& Preset::print_options()
|
||||
"bottom_solid_min_thickness",
|
||||
"extra_perimeters",
|
||||
"extra_perimeters_odd_layers",
|
||||
"extra_perimeters_overhangs",
|
||||
"only_one_perimeter_top", "ensure_vertical_shell_thickness",
|
||||
"allow_empty_layers",
|
||||
"avoid_crossing_perimeters",
|
||||
@ -433,6 +434,8 @@ const std::vector<std::string>& Preset::print_options()
|
||||
"thin_perimeters",
|
||||
"thin_walls", "overhangs",
|
||||
"overhangs_width",
|
||||
"overhangs_reverse",
|
||||
"overhangs_reverse_threshold",
|
||||
"seam_position",
|
||||
"external_perimeters_first",
|
||||
"external_perimeters_vase",
|
||||
|
Loading…
x
Reference in New Issue
Block a user