mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-14 09:15:57 +08:00
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).
This commit is contained in:
parent
72d828cf74
commit
a48e190137
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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 "
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user