mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 04:36:10 +08:00
#4 perimeter overlaps : total control over perimeter width vs spacing.
- add a spacing_ratio in flow, but it's only sed for two spacing in perimeter_generator, not sure about the usefulness of it. - external_perimeter_overlap now use the spacing_ratio to compute - add perimeter_overlap, using the spacing_ratio to compute - add perimeter_bonding, that shrink the external-internal spacing, without growing the infill polygons.
This commit is contained in:
parent
498c48580a
commit
bbbb4d9396
@ -54,16 +54,18 @@ group:Advanced
|
||||
setting:seam_position
|
||||
setting:seam_travel
|
||||
end_line
|
||||
line:External Perimeter
|
||||
setting:external_perimeters_first
|
||||
setting:external_perimeters_vase
|
||||
setting:external_perimeters_nothole
|
||||
setting:external_perimeters_hole
|
||||
end_line
|
||||
line:Looping perimeter
|
||||
setting:perimeter_loop
|
||||
setting:perimeter_loop_seam
|
||||
end_line
|
||||
group: External perimeter first
|
||||
setting:label$Activate:external_perimeters_first
|
||||
line:Apply on
|
||||
setting:external_perimeters_nothole
|
||||
setting:external_perimeters_hole
|
||||
end_line
|
||||
setting:external_perimeters_vase
|
||||
setting:perimeter_bonding
|
||||
|
||||
page:Slicing:layers
|
||||
group:Layer height
|
||||
@ -230,9 +232,12 @@ group:Extrusion width
|
||||
setting:top_infill_extrusion_width
|
||||
setting:support_material_extrusion_width
|
||||
group:Overlap
|
||||
line:Perimeter overlap
|
||||
setting:label$External:external_perimeter_overlap
|
||||
setting:label$Inner:perimeter_overlap
|
||||
end_line
|
||||
setting:infill_overlap
|
||||
setting:bridge_overlap
|
||||
setting:external_perimeter_overlap
|
||||
group:Flow
|
||||
line:Flow ratio
|
||||
setting:bridge_flow_ratio
|
||||
|
@ -172,7 +172,7 @@ float Flow::spacing() const
|
||||
float min_flow_spacing = this->width - this->height * (1. - 0.25 * PI);
|
||||
float res = this->width - PERIMETER_LINE_OVERLAP_FACTOR * (this->width - min_flow_spacing);
|
||||
#else
|
||||
float res = float(this->bridge ? (this->width + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter) : (this->width - this->height * (1. - 0.25 * PI)));
|
||||
float res = float(this->bridge ? (this->width + BRIDGE_EXTRA_SPACING_MULT * nozzle_diameter) : (this->width - this->height * (1. - 0.25 * PI) * spacing_ratio));
|
||||
#endif
|
||||
// assert(res > 0.f);
|
||||
if (res <= 0.f)
|
||||
|
@ -65,6 +65,8 @@ public:
|
||||
float nozzle_diameter;
|
||||
// Is it a bridge?
|
||||
bool bridge;
|
||||
// % of spacing taken into account 1=>all/default, 0=> width=spacing
|
||||
float spacing_ratio = 1;
|
||||
|
||||
Flow(float _w, float _h, float _nd, bool _bridge = false) :
|
||||
width(_w), height(_h), nozzle_diameter(_nd), bridge(_bridge) {}
|
||||
|
@ -37,6 +37,10 @@ namespace Slic3r {
|
||||
|
||||
void PerimeterGenerator::process()
|
||||
{
|
||||
//set spacing
|
||||
this->perimeter_flow.spacing_ratio = this->object_config->perimeter_overlap.get_abs_value(1);
|
||||
this->ext_perimeter_flow.spacing_ratio = this->object_config->external_perimeter_overlap.get_abs_value(1);
|
||||
|
||||
// other perimeters
|
||||
this->_mm3_per_mm = this->perimeter_flow.mm3_per_mm();
|
||||
coord_t perimeter_width = this->perimeter_flow.scaled_width();
|
||||
@ -50,22 +54,30 @@ void PerimeterGenerator::process()
|
||||
coord_t ext_perimeter_spacing = this->ext_perimeter_flow.scaled_spacing();
|
||||
//spacing between external perimeter and the second
|
||||
coord_t ext_perimeter_spacing2 = this->ext_perimeter_flow.scaled_spacing(this->perimeter_flow);
|
||||
//external_perimeter_overlap effect: change distance between the extrenal periemter and the other ones.
|
||||
if (this->config->external_perimeter_overlap.get_abs_value(1) != 1) {
|
||||
//choose between the normal spacing and "don't touch it".
|
||||
ext_perimeter_spacing2 =
|
||||
ext_perimeter_spacing2 * this->config->external_perimeter_overlap.get_abs_value(1)
|
||||
+ (ext_perimeter_width + perimeter_width) * 0.5f * (1 - this->config->external_perimeter_overlap.get_abs_value(1));
|
||||
}
|
||||
|
||||
|
||||
// overhang perimeters
|
||||
this->_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
|
||||
|
||||
this->_mm3_per_mm_overhang = this->overhang_flow.mm3_per_mm();
|
||||
|
||||
// solid infill
|
||||
coord_t solid_infill_spacing = this->solid_infill_flow.scaled_spacing();
|
||||
coord_t solid_infill_spacing = this->solid_infill_flow.scaled_spacing();
|
||||
|
||||
//infill / perimeter
|
||||
coord_t infill_peri_overlap = (coord_t)scale_(this->config->get_abs_value("infill_overlap", unscale<coordf_t>(perimeter_spacing + solid_infill_spacing) / 2));
|
||||
// infill gap to add vs periemter (useful if using perimeter bonding)
|
||||
coord_t infill_gap = 0;
|
||||
|
||||
|
||||
// nozzle diameter
|
||||
const double nozzle_diameter = this->print_config->nozzle_diameter.get_at(this->config->perimeter_extruder - 1);
|
||||
|
||||
// perimeter conding set.
|
||||
if (this->perimeter_flow.spacing_ratio == 1
|
||||
&& this->ext_perimeter_flow.spacing_ratio == 1
|
||||
&& this->config->external_perimeters_first
|
||||
&& this->object_config->perimeter_bonding.value > 0) {
|
||||
infill_gap = (1 - this->object_config->perimeter_bonding.get_abs_value(1)) * ext_perimeter_spacing;
|
||||
ext_perimeter_spacing2 -= infill_gap;
|
||||
}
|
||||
|
||||
// Calculate the minimum required spacing between two adjacent traces.
|
||||
// This should be equal to the nominal flow spacing but we experiment
|
||||
@ -88,7 +100,7 @@ void PerimeterGenerator::process()
|
||||
this->_lower_slices_p = offset(*this->lower_slices, double(scale_(config->overhangs_width.get_abs_value(nozzle_diameter))));
|
||||
}
|
||||
|
||||
// have to grown the periemters if mill post-process
|
||||
// have to grown the perimeters if mill post-process
|
||||
MillingPostProcess miller(this->slices, this->lower_slices, config, object_config, print_config);
|
||||
bool have_to_grow_for_miller = miller.can_be_milled(layer) && config->milling_extra_size.get_abs_value(1) > 0;
|
||||
ExPolygons unmillable;
|
||||
@ -218,7 +230,6 @@ void PerimeterGenerator::process()
|
||||
//it's not dangerous as it will be intersected by 'unsupported' later
|
||||
//FIXME: add overlap in this->fill_surfaces->append
|
||||
//FIXME: it overlap inside unsuppported not-bridgeable area!
|
||||
double overlap = scale_(this->config->get_abs_value("infill_overlap", unscale<double>(perimeter_spacing)));
|
||||
|
||||
//bridgeable_simplified = offset2_ex(bridgeable_simplified, (double)-perimeter_spacing, (double)perimeter_spacing * 2);
|
||||
//ExPolygons unbridgeable = offset_ex(diff_ex(unsupported, bridgeable_simplified), perimeter_spacing * 3 / 2);
|
||||
@ -391,7 +402,7 @@ void PerimeterGenerator::process()
|
||||
if ( this->config->extra_perimeters_overhangs && !last.empty() && !overhangs_unsupported.empty()) {
|
||||
overhangs_unsupported = intersection_ex(overhangs_unsupported, last, true);
|
||||
if (overhangs_unsupported.size() > 0) {
|
||||
//please don't stop adding periemter yet.
|
||||
//please don't stop adding perimeter yet.
|
||||
has_overhang = true;
|
||||
}
|
||||
}
|
||||
@ -456,9 +467,9 @@ void PerimeterGenerator::process()
|
||||
ExPolygons thin = offset_ex(half_thin, double(min_width / 2));
|
||||
assert(thin.size() <= 1);
|
||||
if (thin.empty()) continue;
|
||||
coord_t overlap = (coord_t)scale_(this->config->thin_walls_overlap.get_abs_value(this->ext_perimeter_flow.nozzle_diameter));
|
||||
coord_t thin_walls_overlap = (coord_t)scale_(this->config->thin_walls_overlap.get_abs_value(this->ext_perimeter_flow.nozzle_diameter));
|
||||
ExPolygons anchor = intersection_ex(offset_ex(half_thin, double(min_width / 2) +
|
||||
(float)(overlap), jtSquare), no_thin_zone, true);
|
||||
(float)(thin_walls_overlap), jtSquare), no_thin_zone, true);
|
||||
ExPolygons bounds = union_ex(thin, anchor, true);
|
||||
for (ExPolygon &bound : bounds) {
|
||||
if (!intersection_ex(thin[0], bound).empty()) {
|
||||
@ -472,7 +483,7 @@ void PerimeterGenerator::process()
|
||||
min_width, coord_t(this->layer->height) };
|
||||
ma.use_bounds(bound)
|
||||
.use_min_real_width((coord_t)scale_(this->ext_perimeter_flow.nozzle_diameter))
|
||||
.use_tapers(overlap)
|
||||
.use_tapers(thin_walls_overlap)
|
||||
.build(thin_walls);
|
||||
}
|
||||
break;
|
||||
@ -818,7 +829,7 @@ void PerimeterGenerator::process()
|
||||
last = diff_ex(to_polygons(last), gap_fill.polygons_covered_by_width(10.f));
|
||||
}
|
||||
}
|
||||
//TODO: if a gapfill extrusion is a loop and with width always >= periemter width then change the type to perimeter and put it at the right place in the loops vector.
|
||||
//TODO: if a gapfill extrusion is a loop and with width always >= perimeter width then change the type to perimeter and put it at the right place in the loops vector.
|
||||
|
||||
// create one more offset to be used as boundary for fill
|
||||
// we offset by half the perimeter spacing (to get to the actual infill boundary)
|
||||
@ -832,9 +843,8 @@ void PerimeterGenerator::process()
|
||||
// two or more loops?
|
||||
perimeter_spacing / 2;
|
||||
// only apply infill overlap if we actually have one perimeter
|
||||
coord_t overlap = 0;
|
||||
if (inset > 0) {
|
||||
overlap = (coord_t)scale_(this->config->get_abs_value("infill_overlap", unscale<coordf_t>(inset + solid_infill_spacing / 2)));
|
||||
if (inset == 0) {
|
||||
infill_peri_overlap = 0;
|
||||
}
|
||||
// simplify infill contours according to resolution
|
||||
Polygons not_filled_p;
|
||||
@ -846,14 +856,14 @@ void PerimeterGenerator::process()
|
||||
// append infill areas to fill_surfaces
|
||||
//auto it_surf = this->fill_surfaces->surfaces.end();
|
||||
ExPolygons infill_exp = offset2_ex(not_filled_exp,
|
||||
-inset - min_perimeter_infill_spacing / 2 + overlap,
|
||||
-inset - min_perimeter_infill_spacing / 2 + infill_peri_overlap - infill_gap,
|
||||
(float)min_perimeter_infill_spacing / 2);
|
||||
this->fill_surfaces->append(infill_exp, stPosInternal | stDensSparse);
|
||||
|
||||
if (overlap != 0) {
|
||||
if (infill_peri_overlap != 0) {
|
||||
ExPolygons polyWithoutOverlap = offset2_ex(
|
||||
not_filled_exp,
|
||||
-inset - min_perimeter_infill_spacing / 2,
|
||||
-inset - infill_gap - min_perimeter_infill_spacing / 2,
|
||||
(float) min_perimeter_infill_spacing / 2);
|
||||
this->fill_no_overlap.insert(this->fill_no_overlap.end(), polyWithoutOverlap.begin(), polyWithoutOverlap.end());
|
||||
}
|
||||
|
@ -729,12 +729,45 @@ void PrintConfigDef::init_fff_params()
|
||||
def->label = L("external perimeter overlap");
|
||||
def->full_label = L("Ext. peri. overlap");
|
||||
def->category = OptionCategory::width;
|
||||
def->tooltip = L("This perimeter allow you to reduce the overlap between the perimeters and the external one, to reduce the impact of the perimeters artifacts."
|
||||
def->tooltip = L("This setting allow you to reduce the overlap between the perimeters and the external one, to reduce the impact of the perimeters artifacts."
|
||||
" 100% means that no gaps is left, and 0% means that the external perimeter isn't contributing to the overlap with the 'inner' one."
|
||||
"\nIt's very experimental, please report about the usefulness. It may be removed if there is no use of it.");
|
||||
def->sidetext = L("%");
|
||||
def->min = 0;
|
||||
def->max = 100;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionPercent(100));
|
||||
|
||||
def = this->add("perimeter_overlap", coPercent);
|
||||
def->label = L("perimeter overlap");
|
||||
def->full_label = L("Perimeter overlap");
|
||||
def->category = OptionCategory::width;
|
||||
def->tooltip = L("This setting allow you to reduce the overlap between the perimeters, to reduce the impact of the perimeters artifacts."
|
||||
" 100% means that no gaps is left, and 0% means that perimeters are not touching each other anymore."
|
||||
"\nIt's very experimental, please report about the usefulness. It may be removed if there is no use for it.");
|
||||
def->sidetext = L("%");
|
||||
def->min = 0;
|
||||
def->max = 100;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionPercent(100));
|
||||
|
||||
def = this->add("perimeter_bonding", coPercent);
|
||||
def->label = L("Better bonding");
|
||||
def->full_label = L("Perimeter bonding");
|
||||
def->category = OptionCategory::perimeter;
|
||||
def->tooltip = L("This setting may degrad a bit the quality of your external perimeter, in exchange for a better bonding between perimeters."
|
||||
"Use it if you have great difficulties with perimeter bonding, for example with high temperature filaments."
|
||||
"\nThis percentage is the % of overlap between perimeters, a bit like perimeter_overlap and external_perimeter_overlap, but in reverse."
|
||||
" You have to set perimeter_overlap and external_perimeter_overlap to 100%, or this setting has no effect."
|
||||
" 0: no effect, 50%: half of the nozzle will be over an already extruded perimeter while extruding a new one"
|
||||
", unless it's an external ones)."
|
||||
"\nIt's very experimental, please report about the usefulness. It may be removed if there is no use for it.");
|
||||
def->sidetext = L("%");
|
||||
def->min = 0;
|
||||
def->max = 50;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionPercent(0));
|
||||
|
||||
def = this->add("external_perimeter_speed", coFloatOrPercent);
|
||||
def->label = L("External");
|
||||
def->full_label = L("External perimeters speed");
|
||||
@ -2022,7 +2055,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->label = L("minimum top width for infill");
|
||||
def->category = OptionCategory::speed;
|
||||
def->tooltip = L("If a top surface has to be printed and it's partially covered by an other layer, it won't be considered at a top layer where his width is below this value."
|
||||
" This can be useful to not let the 'one perimeter on top' trigger on surface that should be covered only by periemters."
|
||||
" This can be useful to not let the 'one perimeter on top' trigger on surface that should be covered only by perimeters."
|
||||
" This value can be a mm or a % of the perimeter extrusion width.");
|
||||
def->sidetext = L("mm or %");
|
||||
def->ratio_over = "perimeter_extrusion_width";
|
||||
|
@ -494,6 +494,7 @@ public:
|
||||
ConfigOptionBool dont_support_bridges;
|
||||
ConfigOptionPercent external_perimeter_cut_corners;
|
||||
ConfigOptionBool exact_last_layer_height;
|
||||
ConfigOptionPercent external_perimeter_overlap;
|
||||
ConfigOptionFloatOrPercent extrusion_width;
|
||||
ConfigOptionFloatOrPercent first_layer_height;
|
||||
ConfigOptionFloat first_layer_size_compensation;
|
||||
@ -503,6 +504,8 @@ public:
|
||||
ConfigOptionBool interface_shells;
|
||||
ConfigOptionFloat layer_height;
|
||||
ConfigOptionFloat model_precision;
|
||||
ConfigOptionPercent perimeter_bonding;
|
||||
ConfigOptionPercent perimeter_overlap;
|
||||
ConfigOptionInt raft_layers;
|
||||
ConfigOptionEnum<SeamPosition> seam_position;
|
||||
ConfigOptionBool seam_travel;
|
||||
@ -555,6 +558,7 @@ protected:
|
||||
OPT_PTR(dont_support_bridges);
|
||||
OPT_PTR(external_perimeter_cut_corners);
|
||||
OPT_PTR(exact_last_layer_height);
|
||||
OPT_PTR(external_perimeter_overlap);
|
||||
OPT_PTR(extrusion_width);
|
||||
OPT_PTR(hole_size_compensation);
|
||||
OPT_PTR(first_layer_height);
|
||||
@ -563,6 +567,8 @@ protected:
|
||||
OPT_PTR(interface_shells);
|
||||
OPT_PTR(layer_height);
|
||||
OPT_PTR(model_precision);
|
||||
OPT_PTR(perimeter_bonding);
|
||||
OPT_PTR(perimeter_overlap);
|
||||
OPT_PTR(raft_layers);
|
||||
OPT_PTR(seam_position);
|
||||
OPT_PTR(seam_travel);
|
||||
@ -621,7 +627,6 @@ public:
|
||||
ConfigOptionBool enforce_full_fill_volume;
|
||||
ConfigOptionFloatOrPercent external_infill_margin;
|
||||
ConfigOptionFloatOrPercent external_perimeter_extrusion_width;
|
||||
ConfigOptionPercent external_perimeter_overlap;
|
||||
ConfigOptionFloatOrPercent external_perimeter_speed;
|
||||
ConfigOptionBool external_perimeters_first;
|
||||
ConfigOptionBool external_perimeters_vase;
|
||||
@ -709,7 +714,6 @@ protected:
|
||||
OPT_PTR(enforce_full_fill_volume);
|
||||
OPT_PTR(external_infill_margin);
|
||||
OPT_PTR(external_perimeter_extrusion_width);
|
||||
OPT_PTR(external_perimeter_overlap);
|
||||
OPT_PTR(external_perimeter_speed);
|
||||
OPT_PTR(external_perimeters_first);
|
||||
OPT_PTR(external_perimeters_vase);
|
||||
|
@ -305,7 +305,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
|
||||
toggle_field("overhangs_reverse_threshold", config->opt_bool("overhangs_reverse"));
|
||||
toggle_field("min_width_top_surface", config->opt_bool("only_one_perimeter_top"));
|
||||
|
||||
for (auto el : { "external_perimeters_vase", "external_perimeters_nothole", "external_perimeters_hole"})
|
||||
for (auto el : { "external_perimeters_vase", "external_perimeters_nothole", "external_perimeters_hole", "perimeter_bonding"})
|
||||
toggle_field(el, config->opt_bool("external_perimeters_first"));
|
||||
|
||||
for (auto el : { "thin_walls_min_width", "thin_walls_overlap" })
|
||||
|
@ -536,6 +536,8 @@ const std::vector<std::string>& Preset::print_options()
|
||||
"print_extrusion_multiplier",
|
||||
"external_perimeter_cut_corners",
|
||||
"external_perimeter_overlap",
|
||||
"perimeter_bonding",
|
||||
"perimeter_overlap",
|
||||
"milling_after_z",
|
||||
"milling_post_process",
|
||||
"milling_extra_size",
|
||||
|
@ -319,6 +319,9 @@ std::string PresetHints::recommended_thin_wall_thickness(const PresetBundle &pre
|
||||
*print_config.opt<ConfigOptionFloatOrPercent>("perimeter_extrusion_width"),
|
||||
nozzle_diameter, layer_height, false);
|
||||
|
||||
//set spacing
|
||||
external_perimeter_flow.spacing_ratio = print_config.opt<ConfigOptionPercent>("external_perimeter_overlap")->get_abs_value(1);
|
||||
perimeter_flow.spacing_ratio = print_config.opt<ConfigOptionPercent>("perimeter_overlap")->get_abs_value(1);
|
||||
|
||||
if (num_perimeters > 0) {
|
||||
int num_lines = std::min(num_perimeters, 6);
|
||||
|
Loading…
x
Reference in New Issue
Block a user